[Core] Adjust PWM hardware audio driver for RP2040 (#17723)
parent
efe520645e
commit
19145704e4
|
@ -159,7 +159,6 @@ A configuration example for the STM32F103C8 would be:
|
||||||
//halconf.h:
|
//halconf.h:
|
||||||
#define HAL_USE_PWM TRUE
|
#define HAL_USE_PWM TRUE
|
||||||
#define HAL_USE_PAL TRUE
|
#define HAL_USE_PAL TRUE
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
#include_next <halconf.h>
|
#include_next <halconf.h>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -168,8 +167,6 @@ A configuration example for the STM32F103C8 would be:
|
||||||
#include_next <mcuconf.h>
|
#include_next <mcuconf.h>
|
||||||
#undef STM32_PWM_USE_TIM1
|
#undef STM32_PWM_USE_TIM1
|
||||||
#define STM32_PWM_USE_TIM1 TRUE
|
#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
|
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_PIN A8
|
||||||
#define AUDIO_PWM_DRIVER PWMD1
|
#define AUDIO_PWM_DRIVER PWMD1
|
||||||
#define AUDIO_PWM_CHANNEL 1
|
#define AUDIO_PWM_CHANNEL 1
|
||||||
#define AUDIO_STATE_TIMER GPTD4
|
|
||||||
```
|
```
|
||||||
|
|
||||||
ChibiOS uses GPIOv1 for the F103, which only knows of one alternate function.
|
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:
|
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: |
|
| Atmega32U4 | :o: | :o: | :heavy_check_mark: | :o: |
|
||||||
|
| RP2040 | :x: | :x: | :heavy_check_mark: | ? |
|
||||||
| STM32F103C8 (bluepill) | :x: | :x: | :heavy_check_mark: | :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: |
|
| 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: |
|
| STM32F405VG | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| L0xx | :x: (no Tim8) | ? | ? | ? |
|
| L0xx | :x: (no Tim8) | ? | ? | ? |
|
||||||
|
|
||||||
|
|
||||||
:heavy_check_mark: : works and was tested
|
:heavy_check_mark: : works and was tested
|
||||||
:o: : does not apply
|
:o: : does not apply
|
||||||
:x: : not supported by MCU
|
:x: : not supported by MCU
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
The following table shows the current driver status for peripherals on RP2040 MCUs:
|
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) |
|
| [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: |
|
| [Backlight](feature_backlight.md) | :heavy_check_mark: |
|
||||||
| [I2C driver](i2c_driver.md) | :heavy_check_mark: |
|
| [I2C driver](i2c_driver.md) | :heavy_check_mark: |
|
||||||
| [SPI driver](spi_driver.md) | :heavy_check_mark: |
|
| [SPI driver](spi_driver.md) | :heavy_check_mark: |
|
||||||
|
|
|
@ -60,7 +60,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#define AUDIO_PWM_DRIVER PWMD3
|
#define AUDIO_PWM_DRIVER PWMD3
|
||||||
#define AUDIO_PWM_CHANNEL 4
|
#define AUDIO_PWM_CHANNEL 4
|
||||||
#define AUDIO_PWM_PAL_MODE 2
|
#define AUDIO_PWM_PAL_MODE 2
|
||||||
#define AUDIO_STATE_TIMER GPTD4
|
|
||||||
|
|
||||||
/* serial.c configuration for split keyboard */
|
/* serial.c configuration for split keyboard */
|
||||||
#undef SOFT_SERIAL_PIN
|
#undef SOFT_SERIAL_PIN
|
||||||
|
|
|
@ -21,6 +21,5 @@
|
||||||
#define HAL_USE_SPI TRUE
|
#define HAL_USE_SPI TRUE
|
||||||
#define SPI_USE_WAIT TRUE
|
#define SPI_USE_WAIT TRUE
|
||||||
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
|
|
||||||
#include_next <halconf.h>
|
#include_next <halconf.h>
|
||||||
|
|
|
@ -38,8 +38,5 @@
|
||||||
#undef STM32_SERIAL_USE_USART2
|
#undef STM32_SERIAL_USE_USART2
|
||||||
#define STM32_SERIAL_USE_USART2 TRUE
|
#define STM32_SERIAL_USE_USART2 TRUE
|
||||||
|
|
||||||
#undef STM32_GPT_USE_TIM4
|
|
||||||
#define STM32_GPT_USE_TIM4 TRUE
|
|
||||||
|
|
||||||
#undef STM32_ST_USE_TIMER
|
#undef STM32_ST_USE_TIMER
|
||||||
#define STM32_ST_USE_TIMER 5
|
#define STM32_ST_USE_TIMER 5
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
#define AUDIO_PWM_DRIVER PWMD4
|
#define AUDIO_PWM_DRIVER PWMD4
|
||||||
#define AUDIO_PWM_CHANNEL 2
|
#define AUDIO_PWM_CHANNEL 2
|
||||||
#define AUDIO_PWM_PAL_MODE 2
|
#define AUDIO_PWM_PAL_MODE 2
|
||||||
#define AUDIO_STATE_TIMER GPTD3
|
|
||||||
#define AUDIO_INIT_DELAY
|
#define AUDIO_INIT_DELAY
|
||||||
#define AUDIO_ENABLE_TONE_MULTIPLEXING
|
#define AUDIO_ENABLE_TONE_MULTIPLEXING
|
||||||
#define AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT 10
|
#define AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT 10
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#define HAL_USE_PWM TRUE
|
#define HAL_USE_PWM TRUE
|
||||||
#define HAL_USE_PAL TRUE
|
#define HAL_USE_PAL TRUE
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
#define HAL_USE_SERIAL TRUE
|
#define HAL_USE_SERIAL TRUE
|
||||||
// #define HAL_USE_I2C TRUE
|
// #define HAL_USE_I2C TRUE
|
||||||
#define HAL_USE_SPI TRUE
|
#define HAL_USE_SPI TRUE
|
||||||
|
|
|
@ -36,8 +36,5 @@
|
||||||
#undef STM32_SERIAL_USE_USART1
|
#undef STM32_SERIAL_USE_USART1
|
||||||
#define STM32_SERIAL_USE_USART1 TRUE
|
#define STM32_SERIAL_USE_USART1 TRUE
|
||||||
|
|
||||||
#undef STM32_GPT_USE_TIM3
|
|
||||||
#define STM32_GPT_USE_TIM3 TRUE
|
|
||||||
|
|
||||||
#undef STM32_ST_USE_TIMER
|
#undef STM32_ST_USE_TIMER
|
||||||
#define STM32_ST_USE_TIMER 5
|
#define STM32_ST_USE_TIMER 5
|
||||||
|
|
|
@ -27,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#define AUDIO_PWM_DRIVER PWMD2
|
#define AUDIO_PWM_DRIVER PWMD2
|
||||||
#define AUDIO_PWM_CHANNEL 3
|
#define AUDIO_PWM_CHANNEL 3
|
||||||
#define AUDIO_PWM_PAL_MODE 1
|
#define AUDIO_PWM_PAL_MODE 1
|
||||||
#define AUDIO_STATE_TIMER GPTD1
|
|
||||||
|
|
||||||
#define AUDIO_CLICKY
|
#define AUDIO_CLICKY
|
||||||
#define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f
|
#define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f
|
||||||
|
|
|
@ -23,6 +23,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define HAL_USE_PWM TRUE
|
#define HAL_USE_PWM TRUE
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
|
|
||||||
#include_next <halconf.h>
|
#include_next <halconf.h>
|
||||||
|
|
|
@ -23,8 +23,5 @@
|
||||||
#undef STM32_PWM_USE_TIM4
|
#undef STM32_PWM_USE_TIM4
|
||||||
#define STM32_PWM_USE_TIM4 TRUE
|
#define STM32_PWM_USE_TIM4 TRUE
|
||||||
|
|
||||||
#undef STM32_GPT_USE_TIM1
|
|
||||||
#define STM32_GPT_USE_TIM1 TRUE
|
|
||||||
|
|
||||||
#undef STM32_ST_USE_TIMER
|
#undef STM32_ST_USE_TIMER
|
||||||
#define STM32_ST_USE_TIMER 5
|
#define STM32_ST_USE_TIMER 5
|
||||||
|
|
|
@ -16,3 +16,7 @@
|
||||||
|
|
||||||
#define BACKLIGHT_PWM_DRIVER PWMD4
|
#define BACKLIGHT_PWM_DRIVER PWMD4
|
||||||
#define BACKLIGHT_PWM_CHANNEL RP2040_PWM_CHANNEL_B
|
#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
|
||||||
|
|
|
@ -5,5 +5,8 @@
|
||||||
|
|
||||||
#include_next "mcuconf.h"
|
#include_next "mcuconf.h"
|
||||||
|
|
||||||
|
#undef RP_PWM_USE_PWM0
|
||||||
|
#define RP_PWM_USE_PWM0 TRUE
|
||||||
|
|
||||||
#undef RP_PWM_USE_PWM4
|
#undef RP_PWM_USE_PWM4
|
||||||
#define RP_PWM_USE_PWM4 TRUE
|
#define RP_PWM_USE_PWM4 TRUE
|
||||||
|
|
|
@ -53,7 +53,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#define AUDIO_PWM_DRIVER PWMD3
|
#define AUDIO_PWM_DRIVER PWMD3
|
||||||
#define AUDIO_PWM_CHANNEL 4
|
#define AUDIO_PWM_CHANNEL 4
|
||||||
#define AUDIO_PWM_PAL_MODE 2
|
#define AUDIO_PWM_PAL_MODE 2
|
||||||
#define AUDIO_STATE_TIMER GPTD4
|
|
||||||
|
|
||||||
/* serial.c configuration for split keyboard */
|
/* serial.c configuration for split keyboard */
|
||||||
#define SERIAL_USART_FULL_DUPLEX // Enable full duplex operation mode.
|
#define SERIAL_USART_FULL_DUPLEX // Enable full duplex operation mode.
|
||||||
|
|
|
@ -21,6 +21,5 @@
|
||||||
#define HAL_USE_SPI TRUE
|
#define HAL_USE_SPI TRUE
|
||||||
#define SPI_USE_WAIT TRUE
|
#define SPI_USE_WAIT TRUE
|
||||||
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
|
|
||||||
#include_next <halconf.h>
|
#include_next <halconf.h>
|
||||||
|
|
|
@ -38,8 +38,5 @@
|
||||||
#undef STM32_SERIAL_USE_USART2
|
#undef STM32_SERIAL_USE_USART2
|
||||||
#define STM32_SERIAL_USE_USART2 TRUE
|
#define STM32_SERIAL_USE_USART2 TRUE
|
||||||
|
|
||||||
#undef STM32_GPT_USE_TIM4
|
|
||||||
#define STM32_GPT_USE_TIM4 TRUE
|
|
||||||
|
|
||||||
#undef STM32_ST_USE_TIMER
|
#undef STM32_ST_USE_TIMER
|
||||||
#define STM32_ST_USE_TIMER 5
|
#define STM32_ST_USE_TIMER 5
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#define AUDIO_PWM_PAL_MODE 1
|
#define AUDIO_PWM_PAL_MODE 1
|
||||||
#define AUDIO_PWM_DRIVER PWMD1
|
#define AUDIO_PWM_DRIVER PWMD1
|
||||||
#define AUDIO_PWM_CHANNEL 1
|
#define AUDIO_PWM_CHANNEL 1
|
||||||
#define AUDIO_STATE_TIMER GPTD4
|
|
||||||
|
|
||||||
/* RGB LED */
|
/* RGB LED */
|
||||||
#define RGB_DI_PIN B1
|
#define RGB_DI_PIN B1
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
|
|
||||||
/* PWM for AUDIO and RGB LED */
|
/* PWM for AUDIO and RGB LED */
|
||||||
#define HAL_USE_PWM TRUE
|
#define HAL_USE_PWM TRUE
|
||||||
/* GPT and PAL for Audio */
|
|
||||||
#define HAL_USE_GPT TRUE
|
|
||||||
#define HAL_USE_PAL TRUE
|
|
||||||
/* I2C for OLED display */
|
/* I2C for OLED display */
|
||||||
#define HAL_USE_I2C TRUE
|
#define HAL_USE_I2C TRUE
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,6 @@
|
||||||
/* TIM1 PWM used for audio driver */
|
/* TIM1 PWM used for audio driver */
|
||||||
#undef STM32_PWM_USE_TIM1
|
#undef STM32_PWM_USE_TIM1
|
||||||
#define STM32_PWM_USE_TIM1 TRUE
|
#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 */
|
/* TIM3 used for WS2812 driver */
|
||||||
#undef STM32_PWM_USE_TIM3
|
#undef STM32_PWM_USE_TIM3
|
||||||
|
|
|
@ -28,10 +28,18 @@
|
||||||
# define USE_GPIOV1
|
# define USE_GPIOV1
|
||||||
# define PAL_OUTPUT_TYPE_OPENDRAIN _Static_assert(0, "RP2040 has no Open Drain GPIO configuration, setting this is not possible");
|
# 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_PAL_MODE (PAL_MODE_ALTERNATE_PWM | PAL_RP_PAD_DRIVE12 | PAL_RP_GPIO_OE)
|
||||||
# define BACKLIGHT_PWM_COUNTER_FREQUENCY 1000000
|
# define BACKLIGHT_PWM_COUNTER_FREQUENCY 1000000
|
||||||
# define BACKLIGHT_PWM_PERIOD BACKLIGHT_PWM_COUNTER_FREQUENCY / 2048
|
# 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 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)
|
# 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 USE_GPIOV1
|
||||||
# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN
|
# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_STM32_ALTERNATE_OPENDRAIN
|
||||||
# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL
|
# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_STM32_ALTERNATE_PUSHPULL
|
||||||
|
# define AUDIO_PWM_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL
|
||||||
# else
|
# else
|
||||||
# define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN
|
# define PAL_OUTPUT_TYPE_OPENDRAIN PAL_STM32_OTYPE_OPENDRAIN
|
||||||
# define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL
|
# define PAL_OUTPUT_TYPE_PUSHPULL PAL_STM32_OTYPE_PUSHPULL
|
||||||
|
@ -76,6 +85,7 @@
|
||||||
# define USE_I2CV1
|
# define USE_I2CV1
|
||||||
# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN
|
# define PAL_MODE_ALTERNATE_OPENDRAIN PAL_MODE_GD32_ALTERNATE_OPENDRAIN
|
||||||
# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL
|
# define PAL_MODE_ALTERNATE_PUSHPULL PAL_MODE_GD32_ALTERNATE_PUSHPULL
|
||||||
|
# define AUDIO_PWM_PAL_MODE PAL_MODE_GD32_ALTERNATE_PUSHPULL
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,15 @@
|
||||||
/* Copyright 2020 Jack Humbert
|
// Copyright 2022 Stefan Kerkmann
|
||||||
* Copyright 2020 JohSchneider
|
// Copyright 2020 Jack Humbert
|
||||||
*
|
// Copyright 2020 JohSchneider
|
||||||
* This program is free software: you can redistribute it and/or modify
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
// Audio Driver: PWM the duty-cycle is always kept at 50%, and the pwm-period is
|
||||||
Audio Driver: PWM
|
// 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
|
||||||
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.
|
// 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
|
||||||
this driver uses the chibios-PWM system to produce a square-wave on specific output pins that are connected to the PWM hardware.
|
// by what timer - looking for TIMx_CHy and the corresponding alternate
|
||||||
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.
|
// function.
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "ch.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"
|
# error "Audio feature enabled, but no pin selected - see docs/feature_audio under the ARM PWM settings"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(AUDIO_PWM_COUNTER_FREQUENCY)
|
||||||
|
# define AUDIO_PWM_COUNTER_FREQUENCY 100000
|
||||||
|
#endif
|
||||||
|
|
||||||
extern bool playing_note;
|
extern bool playing_note;
|
||||||
extern bool playing_melody;
|
extern bool playing_melody;
|
||||||
extern uint8_t note_timbre;
|
extern uint8_t note_timbre;
|
||||||
|
|
||||||
static PWMConfig pwmCFG = {
|
static PWMConfig pwmCFG = {.frequency = AUDIO_PWM_COUNTER_FREQUENCY, /* PWM clock frequency */
|
||||||
.frequency = 100000, /* PWM clock frequency */
|
.period = 2,
|
||||||
// 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
|
.callback = NULL,
|
||||||
.period = 2, /* initial PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
|
.channels = {[(AUDIO_PWM_CHANNEL - 1)] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}}};
|
||||||
.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 float channel_1_frequency = 0.0f;
|
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;
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pwmcnt_t period = (pwmCFG.frequency / freq);
|
pwmcnt_t period = (pwmCFG.frequency / freq);
|
||||||
pwmChangePeriod(&AUDIO_PWM_DRIVER, period);
|
chSysLockFromISR();
|
||||||
pwmEnableChannel(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1,
|
pwmChangePeriodI(&AUDIO_PWM_DRIVER, period);
|
||||||
// adjust the duty-cycle so that the output is for 'note_timbre' duration HIGH
|
pwmEnableChannelI(&AUDIO_PWM_DRIVER, AUDIO_PWM_CHANNEL - 1,
|
||||||
PWM_PERCENTAGE_TO_WIDTH(&AUDIO_PWM_DRIVER, (100 - note_timbre) * 100));
|
// 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) {
|
float channel_1_get_frequency(void) {
|
||||||
|
@ -95,54 +64,53 @@ void channel_1_stop(void) {
|
||||||
pwmStop(&AUDIO_PWM_DRIVER);
|
pwmStop(&AUDIO_PWM_DRIVER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gpt_callback(GPTDriver *gptp);
|
static virtual_timer_t audio_vt;
|
||||||
GPTConfig gptCFG = {
|
static void audio_callback(virtual_timer_t *vtp, void *p);
|
||||||
/* 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
void audio_driver_initialize(void) {
|
// a regular timer task, that checks the note to be currently played and updates
|
||||||
pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG);
|
// the pwm to output that frequency.
|
||||||
|
static void audio_callback(virtual_timer_t *vtp, void *p) {
|
||||||
// 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) {
|
|
||||||
float freq; // TODO: freq_alt
|
float freq; // TODO: freq_alt
|
||||||
|
|
||||||
if (audio_update_state()) {
|
if (audio_update_state()) {
|
||||||
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
freq = audio_get_processed_frequency(0); // freq_alt would be index=1
|
||||||
channel_1_set_frequency(freq);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,3 @@
|
||||||
#define GP28 28U
|
#define GP28 28U
|
||||||
#define GP29 29U
|
#define GP29 29U
|
||||||
#define GP30 30U
|
#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
|
|
||||||
|
|
Loading…
Reference in New Issue