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 | 176 +++++++----------- platforms/chibios/vendors/RP/_pin_defs.h | 5 - 22 files changed, 94 insertions(+), 145 deletions(-) diff --git a/docs/audio_driver.md b/docs/audio_driver.md index ffd9c8d5ad..a0bbb22e19 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 65055ef07a..3a6f1a1683 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 f3e8f83b2a..ad549a5e22 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 39644726c3..bc07c10527 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 05b5776ac3..fd71b54b77 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 7e47953d63..e29ff644da 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 3d9f187317..8aad829e5c 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 5712bb4574..4f04811e54 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 31cb5fa11b..03fd00d182 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 06585c9d5e..02e11e8144 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 5b190d7ec2..e62fb3341e 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 82c5592dc9..d3e7b5c076 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 86f821640f..5c2587395d 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 f7e9cfb7d6..e93e70f569 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 39644726c3..bc07c10527 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 05b5776ac3..fd71b54b77 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 285f3209aa..4279f955a9 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 d28ae12fde..04fa5f6994 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 f4dc31bff2..c2763caabc 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 38d3a40f6b..4c8333f07b 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 710f397609..54dac46605 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 . - */ +// 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. - - */ +// 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); -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); -#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); -} - -void audio_driver_start(void) { - channel_1_stop(); - channel_1_start(); - - if (playing_note || playing_melody) { - gptStartContinuous(&AUDIO_STATE_TIMER, 64); - } -} - -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) { +// 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, 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 + + chVTObjectInit(&audio_vt); +} + +void audio_driver_start(void) { + channel_1_stop(); + channel_1_start(); + + 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(); + chVTReset(&audio_vt); } diff --git a/platforms/chibios/vendors/RP/_pin_defs.h b/platforms/chibios/vendors/RP/_pin_defs.h index b56ab31406..4241845369 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