From 19145704e4a7a8a7609d697585a6423b67dc5371 Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Thu, 27 Oct 2022 19:26:16 +0200 Subject: [PATCH] [Core] Adjust PWM hardware audio driver for RP2040 (#17723) --- docs/audio_driver.md | 10 +- docs/platformdev_rp2040.md | 4 +- .../charybdis/3x5/keymaps/drashna/config.h | 1 - .../charybdis/3x5/keymaps/drashna/halconf.h | 1 - .../charybdis/3x5/keymaps/drashna/mcuconf.h | 3 - .../charybdis/4x6/keymaps/drashna/config.h | 1 - .../charybdis/4x6/keymaps/drashna/halconf.h | 1 - .../charybdis/4x6/keymaps/drashna/mcuconf.h | 3 - keyboards/handwired/macroboard/f411/config.h | 1 - keyboards/handwired/macroboard/halconf.h | 1 - keyboards/handwired/macroboard/mcuconf.h | 3 - keyboards/handwired/onekey/rp2040/config.h | 4 + keyboards/handwired/onekey/rp2040/mcuconf.h | 3 + .../tractyl_manuform/5x6_right/f411/config.h | 1 - .../tractyl_manuform/5x6_right/f411/halconf.h | 1 - .../tractyl_manuform/5x6_right/f411/mcuconf.h | 3 - keyboards/yanghu/unicorne/config.h | 1 - keyboards/yanghu/unicorne/f411/halconf.h | 3 - keyboards/yanghu/unicorne/f411/mcuconf.h | 3 - platforms/chibios/chibios_config.h | 10 ++ .../chibios/drivers/audio_pwm_hardware.c | 152 +++++++----------- platforms/chibios/vendors/RP/_pin_defs.h | 5 - 22 files changed, 82 insertions(+), 133 deletions(-) diff --git a/docs/audio_driver.md b/docs/audio_driver.md index ffd9c8d5ad9a8ac3c310c6e29968cd4b81abff68..a0bbb22e196255f84d4864f7f71e5fb354644b3a 100644 --- a/docs/audio_driver.md +++ b/docs/audio_driver.md @@ -159,7 +159,6 @@ A configuration example for the STM32F103C8 would be: //halconf.h: #define HAL_USE_PWM TRUE #define HAL_USE_PAL TRUE -#define HAL_USE_GPT TRUE #include_next ``` @@ -168,8 +167,6 @@ A configuration example for the STM32F103C8 would be: #include_next #undef STM32_PWM_USE_TIM1 #define STM32_PWM_USE_TIM1 TRUE -#undef STM32_GPT_USE_TIM4 -#define STM32_GPT_USE_TIM4 TRUE ``` If we now target pin A8, looking through the data-sheet of the STM32F103C8, for the timers and alternate functions @@ -184,7 +181,6 @@ with all this information, the configuration would contain these lines: #define AUDIO_PIN A8 #define AUDIO_PWM_DRIVER PWMD1 #define AUDIO_PWM_CHANNEL 1 -#define AUDIO_STATE_TIMER GPTD4 ``` ChibiOS uses GPIOv1 for the F103, which only knows of one alternate function. @@ -207,15 +203,15 @@ You can also change the timer used for software PWM by defining the driver. For While not an exhaustive list, the following table provides the scenarios that have been partially validated: -| | DAC basic | DAC additive | PWM hardware | PWM software | -|--------------------------|--------------------|--------------------|--------------------|--------------------| +| | DAC basic | DAC additive | PWM hardware | PWM software | +| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ | | Atmega32U4 | :o: | :o: | :heavy_check_mark: | :o: | +| RP2040 | :x: | :x: | :heavy_check_mark: | ? | | STM32F103C8 (bluepill) | :x: | :x: | :heavy_check_mark: | :heavy_check_mark: | | STM32F303CCT6 (proton-c) | :heavy_check_mark: | :heavy_check_mark: | ? | :heavy_check_mark: | | STM32F405VG | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | | L0xx | :x: (no Tim8) | ? | ? | ? | - :heavy_check_mark: : works and was tested :o: : does not apply :x: : not supported by MCU diff --git a/docs/platformdev_rp2040.md b/docs/platformdev_rp2040.md index 65055ef07ae571f3c4b46d8672a1732a0b186053..3a6f1a16834dc4b7546f981cd0a359e12194949c 100644 --- a/docs/platformdev_rp2040.md +++ b/docs/platformdev_rp2040.md @@ -2,10 +2,10 @@ The following table shows the current driver status for peripherals on RP2040 MCUs: -| System | Support | +| System | Support | | ---------------------------------------------------------------- | ---------------------------------------------- | | [ADC driver](adc_driver.md) | Support planned (no ETA) | -| [Audio](audio_driver.md) | Support planned (no ETA) | +| [Audio](audio_driver.md#pwm-hardware) | :heavy_check_mark: | | [Backlight](feature_backlight.md) | :heavy_check_mark: | | [I2C driver](i2c_driver.md) | :heavy_check_mark: | | [SPI driver](spi_driver.md) | :heavy_check_mark: | diff --git a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/config.h b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/config.h index f3e8f83b2a51ba0cfe3cf0b9ff83e8fee88e13dc..ad549a5e226a71289c14e3d91048e24870cfc25a 100644 --- a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/config.h +++ b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/config.h @@ -60,7 +60,6 @@ along with this program. If not, see . #define AUDIO_PWM_DRIVER PWMD3 #define AUDIO_PWM_CHANNEL 4 #define AUDIO_PWM_PAL_MODE 2 -#define AUDIO_STATE_TIMER GPTD4 /* serial.c configuration for split keyboard */ #undef SOFT_SERIAL_PIN diff --git a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/halconf.h b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/halconf.h index 39644726c3c3bba2f82e19f3311f872bc2260f82..bc07c10527634ca5fcc4b32798e8e29e6aba00da 100644 --- a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/halconf.h +++ b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/halconf.h @@ -21,6 +21,5 @@ #define HAL_USE_SPI TRUE #define SPI_USE_WAIT TRUE #define SPI_SELECT_MODE SPI_SELECT_MODE_PAD -#define HAL_USE_GPT TRUE #include_next diff --git a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/mcuconf.h b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/mcuconf.h index 05b5776ac3bf7999eda5782aee4cba9d745f97d1..fd71b54b77da68b402755e736129edd7d6d48e9d 100644 --- a/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/mcuconf.h +++ b/keyboards/bastardkb/charybdis/3x5/keymaps/drashna/mcuconf.h @@ -38,8 +38,5 @@ #undef STM32_SERIAL_USE_USART2 #define STM32_SERIAL_USE_USART2 TRUE -#undef STM32_GPT_USE_TIM4 -#define STM32_GPT_USE_TIM4 TRUE - #undef STM32_ST_USE_TIMER #define STM32_ST_USE_TIMER 5 diff --git a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/config.h b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/config.h index 7e47953d630bbc48a6a3a34ed299f5e93a8ccd82..e29ff644da8d7ffb3060a727e1c5977426dcaeb8 100644 --- a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/config.h +++ b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/config.h @@ -56,7 +56,6 @@ #define AUDIO_PWM_DRIVER PWMD4 #define AUDIO_PWM_CHANNEL 2 #define AUDIO_PWM_PAL_MODE 2 -#define AUDIO_STATE_TIMER GPTD3 #define AUDIO_INIT_DELAY #define AUDIO_ENABLE_TONE_MULTIPLEXING #define AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT 10 diff --git a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/halconf.h b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/halconf.h index 3d9f18731741932d7fb36ef44fc8a337feaf1cff..8aad829e5c5e7bac3fabaa37c131a24687096d06 100644 --- a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/halconf.h +++ b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/halconf.h @@ -17,7 +17,6 @@ #define HAL_USE_PWM TRUE #define HAL_USE_PAL TRUE -#define HAL_USE_GPT TRUE #define HAL_USE_SERIAL TRUE // #define HAL_USE_I2C TRUE #define HAL_USE_SPI TRUE diff --git a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/mcuconf.h b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/mcuconf.h index 5712bb45743f11449c1728b6d6920ee970ed660e..4f04811e549a9586bba03483ef1741da75c3b5ba 100644 --- a/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/mcuconf.h +++ b/keyboards/bastardkb/charybdis/4x6/keymaps/drashna/mcuconf.h @@ -36,8 +36,5 @@ #undef STM32_SERIAL_USE_USART1 #define STM32_SERIAL_USE_USART1 TRUE -#undef STM32_GPT_USE_TIM3 -#define STM32_GPT_USE_TIM3 TRUE - #undef STM32_ST_USE_TIMER #define STM32_ST_USE_TIMER 5 diff --git a/keyboards/handwired/macroboard/f411/config.h b/keyboards/handwired/macroboard/f411/config.h index 31cb5fa11b5399416b684dd541b67d23bc4755d2..03fd00d182d807464b8b82912e3949fa2575f261 100644 --- a/keyboards/handwired/macroboard/f411/config.h +++ b/keyboards/handwired/macroboard/f411/config.h @@ -27,7 +27,6 @@ along with this program. If not, see . #define AUDIO_PWM_DRIVER PWMD2 #define AUDIO_PWM_CHANNEL 3 #define AUDIO_PWM_PAL_MODE 1 -#define AUDIO_STATE_TIMER GPTD1 #define AUDIO_CLICKY #define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f diff --git a/keyboards/handwired/macroboard/halconf.h b/keyboards/handwired/macroboard/halconf.h index 06585c9d5ea58ecab75ed172d9cf108cb5caad7f..02e11e814418f1c4e88322923183d8635d8746f9 100644 --- a/keyboards/handwired/macroboard/halconf.h +++ b/keyboards/handwired/macroboard/halconf.h @@ -23,6 +23,5 @@ #pragma once #define HAL_USE_PWM TRUE -#define HAL_USE_GPT TRUE #include_next diff --git a/keyboards/handwired/macroboard/mcuconf.h b/keyboards/handwired/macroboard/mcuconf.h index 5b190d7ec25b07c5d916d97900114496f927241a..e62fb3341eaaf20df0993efc6a7ed5674a684c64 100644 --- a/keyboards/handwired/macroboard/mcuconf.h +++ b/keyboards/handwired/macroboard/mcuconf.h @@ -23,8 +23,5 @@ #undef STM32_PWM_USE_TIM4 #define STM32_PWM_USE_TIM4 TRUE -#undef STM32_GPT_USE_TIM1 -#define STM32_GPT_USE_TIM1 TRUE - #undef STM32_ST_USE_TIMER #define STM32_ST_USE_TIMER 5 diff --git a/keyboards/handwired/onekey/rp2040/config.h b/keyboards/handwired/onekey/rp2040/config.h index 82c5592dc98f4957d81f194e5b06e4d3457a1821..d3e7b5c0763ee334ccc556954bff3085ad2e6e2a 100644 --- a/keyboards/handwired/onekey/rp2040/config.h +++ b/keyboards/handwired/onekey/rp2040/config.h @@ -16,3 +16,7 @@ #define BACKLIGHT_PWM_DRIVER PWMD4 #define BACKLIGHT_PWM_CHANNEL RP2040_PWM_CHANNEL_B + +#define AUDIO_PIN GP16 +#define AUDIO_PWM_DRIVER PWMD0 +#define AUDIO_PWM_CHANNEL RP2040_PWM_CHANNEL_A diff --git a/keyboards/handwired/onekey/rp2040/mcuconf.h b/keyboards/handwired/onekey/rp2040/mcuconf.h index 86f821640f17f05fbe0a3c7be355b87bef872121..5c2587395d7792148d601c7249081fbc42910bfa 100644 --- a/keyboards/handwired/onekey/rp2040/mcuconf.h +++ b/keyboards/handwired/onekey/rp2040/mcuconf.h @@ -5,5 +5,8 @@ #include_next "mcuconf.h" +#undef RP_PWM_USE_PWM0 +#define RP_PWM_USE_PWM0 TRUE + #undef RP_PWM_USE_PWM4 #define RP_PWM_USE_PWM4 TRUE diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h index f7e9cfb7d6e676cf1c0edda525ef04dfaf8276fc..e93e70f569bca036ffaef00ecbb67426b168853c 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/config.h @@ -53,7 +53,6 @@ along with this program. If not, see . #define AUDIO_PWM_DRIVER PWMD3 #define AUDIO_PWM_CHANNEL 4 #define AUDIO_PWM_PAL_MODE 2 -#define AUDIO_STATE_TIMER GPTD4 /* serial.c configuration for split keyboard */ #define SERIAL_USART_FULL_DUPLEX // Enable full duplex operation mode. diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/halconf.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/halconf.h index 39644726c3c3bba2f82e19f3311f872bc2260f82..bc07c10527634ca5fcc4b32798e8e29e6aba00da 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/f411/halconf.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/halconf.h @@ -21,6 +21,5 @@ #define HAL_USE_SPI TRUE #define SPI_USE_WAIT TRUE #define SPI_SELECT_MODE SPI_SELECT_MODE_PAD -#define HAL_USE_GPT TRUE #include_next diff --git a/keyboards/handwired/tractyl_manuform/5x6_right/f411/mcuconf.h b/keyboards/handwired/tractyl_manuform/5x6_right/f411/mcuconf.h index 05b5776ac3bf7999eda5782aee4cba9d745f97d1..fd71b54b77da68b402755e736129edd7d6d48e9d 100644 --- a/keyboards/handwired/tractyl_manuform/5x6_right/f411/mcuconf.h +++ b/keyboards/handwired/tractyl_manuform/5x6_right/f411/mcuconf.h @@ -38,8 +38,5 @@ #undef STM32_SERIAL_USE_USART2 #define STM32_SERIAL_USE_USART2 TRUE -#undef STM32_GPT_USE_TIM4 -#define STM32_GPT_USE_TIM4 TRUE - #undef STM32_ST_USE_TIMER #define STM32_ST_USE_TIMER 5 diff --git a/keyboards/yanghu/unicorne/config.h b/keyboards/yanghu/unicorne/config.h index 285f3209aa92630b04dc0ef60aa0e2b61198ce53..4279f955a924ae296f22b18fd70041cfe10b79c4 100644 --- a/keyboards/yanghu/unicorne/config.h +++ b/keyboards/yanghu/unicorne/config.h @@ -46,7 +46,6 @@ #define AUDIO_PWM_PAL_MODE 1 #define AUDIO_PWM_DRIVER PWMD1 #define AUDIO_PWM_CHANNEL 1 -#define AUDIO_STATE_TIMER GPTD4 /* RGB LED */ #define RGB_DI_PIN B1 diff --git a/keyboards/yanghu/unicorne/f411/halconf.h b/keyboards/yanghu/unicorne/f411/halconf.h index d28ae12fde5eaed987adac5ce45293a32aa2cbf7..04fa5f699427abbdbe5b35a2324293b6f3f8fffe 100644 --- a/keyboards/yanghu/unicorne/f411/halconf.h +++ b/keyboards/yanghu/unicorne/f411/halconf.h @@ -18,9 +18,6 @@ /* PWM for AUDIO and RGB LED */ #define HAL_USE_PWM TRUE -/* GPT and PAL for Audio */ -#define HAL_USE_GPT TRUE -#define HAL_USE_PAL TRUE /* I2C for OLED display */ #define HAL_USE_I2C TRUE diff --git a/keyboards/yanghu/unicorne/f411/mcuconf.h b/keyboards/yanghu/unicorne/f411/mcuconf.h index f4dc31bff28af3825c7e56957e62759abeef69e9..c2763caabc57ac36c667847d6acedded4e3c9fc5 100644 --- a/keyboards/yanghu/unicorne/f411/mcuconf.h +++ b/keyboards/yanghu/unicorne/f411/mcuconf.h @@ -21,9 +21,6 @@ /* TIM1 PWM used for audio driver */ #undef STM32_PWM_USE_TIM1 #define STM32_PWM_USE_TIM1 TRUE -/* TIM5 GPT used for audio driver */ -#undef STM32_GPT_USE_TIM4 -#define STM32_GPT_USE_TIM4 TRUE /* TIM3 used for WS2812 driver */ #undef STM32_PWM_USE_TIM3 diff --git a/platforms/chibios/chibios_config.h b/platforms/chibios/chibios_config.h index 38d3a40f6b2fc72ab0f3c243ea38439a869ed08b..4c8333f07bb3fc39a3a162ecc09d527716c89edf 100644 --- a/platforms/chibios/chibios_config.h +++ b/platforms/chibios/chibios_config.h @@ -28,10 +28,18 @@ # define USE_GPIOV1 # define PAL_OUTPUT_TYPE_OPENDRAIN _Static_assert(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible"); +/* Aliases for GPIO PWM channels - every pin has at least one PWM channel + * assigned */ +# define RP2040_PWM_CHANNEL_A 1U +# define RP2040_PWM_CHANNEL_B 2U + # define BACKLIGHT_PAL_MODE (PAL_MODE_ALTERNATE_PWM | PAL_RP_PAD_DRIVE12 | PAL_RP_GPIO_OE) # define BACKLIGHT_PWM_COUNTER_FREQUENCY 1000000 # define BACKLIGHT_PWM_PERIOD BACKLIGHT_PWM_COUNTER_FREQUENCY / 2048 +# define AUDIO_PWM_PAL_MODE (PAL_MODE_ALTERNATE_PWM | PAL_RP_PAD_DRIVE12 | PAL_RP_GPIO_OE) +# define AUDIO_PWM_COUNTER_FREQUENCY 500000 + # define usb_lld_endpoint_fields # define I2C1_SCL_PAL_MODE (PAL_MODE_ALTERNATE_I2C | PAL_RP_PAD_SLEWFAST | PAL_RP_PAD_PUE | PAL_RP_PAD_DRIVE4) @@ -55,6 +63,7 @@ # define USE_GPIOV1 # define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN # define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL +# define AUDIO_PWM_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL # else # define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN # define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL @@ -76,6 +85,7 @@ # define USE_I2CV1 # define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN # define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL +# define AUDIO_PWM_PAL_MODE PAL_MODE_GD32_ALTERNATE_PUSHPULL # endif #endif diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c index 710f3976090c26a23f087a125ab288c72f3c9068..54dac4660582be02ad48f2f80e3f5ddc167a5995 100644 --- a/platforms/chibios/drivers/audio_pwm_hardware.c +++ b/platforms/chibios/drivers/audio_pwm_hardware.c @@ -1,29 +1,15 @@ -/* Copyright 2020 Jack Humbert - * Copyright 2020 JohSchneider - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* -Audio Driver: PWM - -the duty-cycle is always kept at 50%, and the pwm-period is adjusted to match the frequency of a note to be played back. - -this driver uses the chibios-PWM system to produce a square-wave on specific output pins that are connected to the PWM hardware. -The hardware directly toggles the pin via its alternate function. see your MCUs data-sheet for which pin can be driven by what timer - looking for TIMx_CHy and the corresponding alternate function. - - */ +// Copyright 2022 Stefan Kerkmann +// Copyright 2020 Jack Humbert +// Copyright 2020 JohSchneider +// SPDX-License-Identifier: GPL-2.0-or-later + +// Audio Driver: PWM the duty-cycle is always kept at 50%, and the pwm-period is +// adjusted to match the frequency of a note to be played back. This driver uses +// the chibios-PWM system to produce a square-wave on specific output pins that +// are connected to the PWM hardware. The hardware directly toggles the pin via +// its alternate function. see your MCUs data-sheet for which pin can be driven +// by what timer - looking for TIMx_CHy and the corresponding alternate +// function. #include "audio.h" #include "ch.h" @@ -33,53 +19,36 @@ The hardware directly toggles the pin via its alternate function. see your MCUs # error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings" #endif +#if !defined(AUDIO_PWM_COUNTER_FREQUENCY) +# define AUDIO_PWM_COUNTER_FREQUENCY 100000 +#endif + extern bool playing_note; extern bool playing_melody; extern uint8_t note_timbre; -static PWMConfig pwmCFG = { - .frequency = 100000, /* PWM clock frequency */ - // CHIBIOS-BUG? can't set the initial period to <2, or the pwm (hard or software) takes ~130ms with .frequency=500000 for a pwmChangePeriod to take effect; with no output=silence in the meantime - .period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */ - .callback = NULL, /* no callback, the hardware directly toggles the pin */ - .channels = - { -#if AUDIO_PWM_CHANNEL == 4 - {PWM_OUTPUT_DISABLED, NULL}, /* channel 0 -> TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 1 -> TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, /* channel 2 -> TIMx_CH3 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL} /* channel 3 -> TIMx_CH4 */ -#elif AUDIO_PWM_CHANNEL == 3 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH3 */ - {PWM_OUTPUT_DISABLED, NULL} -#elif AUDIO_PWM_CHANNEL == 2 - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH2 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#else /*fallback to CH1 */ - {PWM_OUTPUT_ACTIVE_HIGH, NULL}, /* TIMx_CH1 */ - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL}, - {PWM_OUTPUT_DISABLED, NULL} -#endif - }, -}; +static PWMConfig pwmCFG = {.frequency = AUDIO_PWM_COUNTER_FREQUENCY, /* PWM clock frequency */ + .period = 2, + .callback = NULL, + .channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}}}; static float channel_1_frequency = 0.0f; -void channel_1_set_frequency(float freq) { + +void channel_1_set_frequency(float freq) { channel_1_frequency = freq; - if (freq <= 0.0) // a pause/rest has freq=0 + if (freq <= 0.0) { + // a pause/rest has freq=0 return; + } pwmcnt_t period = (pwmCFG.frequency / freq); - pwmChangePeriod(&AUDIO_PWM_DRIVER, period); - pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, - // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH - PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); + chSysLockFromISR(); + pwmChangePeriodI(&AUDIO_PWM_DRIVER, period); + pwmEnableChannelI(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1, + // adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH + PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100)); + chSysUnlockFromISR(); } float channel_1_get_frequency(void) { @@ -95,54 +64,53 @@ void channel_1_stop(void) { pwmStop(&AUDIO_PWM_DRIVER); } -static void gpt_callback(GPTDriver *gptp); -GPTConfig gptCFG = { - /* a whole note is one beat, which is - per definition in musical_notes.h - set to 64 - the longest note is BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 - the tempo (which might vary!) is in bpm (beats per minute) - therefore: if the timer ticks away at .frequency = (60*64)Hz, - and the .interval counts from 64 downwards - audio_update_state is - called just often enough to not miss any notes - */ - .frequency = 60 * 64, - .callback = gpt_callback, -}; +static virtual_timer_t audio_vt; +static void audio_callback(virtual_timer_t *vtp, void *p); + +// a regular timer task, that checks the note to be currently played and updates +// the pwm to output that frequency. +static void audio_callback(virtual_timer_t *vtp, void *p) { + float freq; // TODO: freq_alt + + if (audio_update_state()) { + freq = audio_get_processed_frequency(0); // freq_alt would be index=1 + channel_1_set_frequency(freq); + } + + chSysLockFromISR(); + chVTSetI(&audio_vt, TIME_MS2I(16), audio_callback, NULL); + chSysUnlockFromISR(); +} void audio_driver_initialize(void) { pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); // connect the AUDIO_PIN to the PWM hardware -#if defined(USE_GPIOV1) // STM32F103C8 - palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE_PUSHPULL); +#if defined(USE_GPIOV1) // STM32F103C8, RP2040 + palSetLineMode(AUDIO_PIN, AUDIO_PWM_PAL_MODE); #else // GPIOv2 (or GPIOv3 for f4xx, which is the same/compatible at this command) palSetLineMode(AUDIO_PIN, PAL_MODE_ALTERNATE(AUDIO_PWM_PAL_MODE)); #endif - gptStart(&AUDIO_STATE_TIMER, &gptCFG); + chVTObjectInit(&audio_vt); } void audio_driver_start(void) { channel_1_stop(); channel_1_start(); - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); + if ((playing_note || playing_melody) && !chVTIsArmed(&audio_vt)) { + // a whole note is one beat, which is - per definition in + // musical_notes.h - set to 64 the longest note is + // BREAVE_DOT=128+64=192, the shortest SIXTEENTH=4 the tempo (which + // might vary!) is in bpm (beats per minute) therefore: if the timer + // ticks away at 64Hz (~16.6ms) audio_update_state is called just often + // enough to not miss any notes + chVTSet(&audio_vt, TIME_MS2I(16), audio_callback, NULL); } } void audio_driver_stop(void) { channel_1_stop(); - gptStopTimer(&AUDIO_STATE_TIMER); -} - -/* a regular timer task, that checks the note to be currently played - * and updates the pwm to output that frequency - */ -static void gpt_callback(GPTDriver *gptp) { - float freq; // TODO: freq_alt - - if (audio_update_state()) { - freq = audio_get_processed_frequency(0); // freq_alt would be index=1 - channel_1_set_frequency(freq); - } + chVTReset(&audio_vt); } diff --git a/platforms/chibios/vendors/RP/_pin_defs.h b/platforms/chibios/vendors/RP/_pin_defs.h index b56ab314068c288f8fdf51420308287136f75008..424184536982b178d996c3d3f33996396aa2dfb9 100644 --- a/platforms/chibios/vendors/RP/_pin_defs.h +++ b/platforms/chibios/vendors/RP/_pin_defs.h @@ -35,8 +35,3 @@ #define GP28 28U #define GP29 29U #define GP30 30U - -/* Aliases for GPIO PWM channels - every pin has at least one PWM channel - * assigned */ -#define RP2040_PWM_CHANNEL_A 1U -#define RP2040_PWM_CHANNEL_B 2U