diff options
113 files changed, 9731 insertions, 2456 deletions
diff --git a/common_features.mk b/common_features.mk index 8338ce4080..6463efb8ba 100644 --- a/common_features.mk +++ b/common_features.mk @@ -42,12 +42,31 @@ ifeq ($(strip $(COMMAND_ENABLE)), yes) OPT_DEFS += -DCOMMAND_ENABLE endif +AUDIO_ENABLE ?= no ifeq ($(strip $(AUDIO_ENABLE)), yes) + ifeq ($(PLATFORM),CHIBIOS) + AUDIO_DRIVER ?= dac_basic + ifeq ($(strip $(AUDIO_DRIVER)), dac_basic) + OPT_DEFS += -DAUDIO_DRIVER_DAC + else ifeq ($(strip $(AUDIO_DRIVER)), dac_additive) + OPT_DEFS += -DAUDIO_DRIVER_DAC + ## stm32f2 and above have a usable DAC unit, f1 do not, and need to use pwm instead + else ifeq ($(strip $(AUDIO_DRIVER)), pwm_software) + OPT_DEFS += -DAUDIO_DRIVER_PWM + else ifeq ($(strip $(AUDIO_DRIVER)), pwm_hardware) + OPT_DEFS += -DAUDIO_DRIVER_PWM + endif + else + # fallback for all other platforms is pwm + AUDIO_DRIVER ?= pwm_hardware + OPT_DEFS += -DAUDIO_DRIVER_PWM + endif OPT_DEFS += -DAUDIO_ENABLE MUSIC_ENABLE = yes SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c - SRC += $(QUANTUM_DIR)/audio/audio_$(PLATFORM_KEY).c + SRC += $(QUANTUM_DIR)/audio/audio.c ## common audio code, hardware agnostic + SRC += $(QUANTUM_DIR)/audio/driver_$(PLATFORM_KEY)_$(strip $(AUDIO_DRIVER)).c SRC += $(QUANTUM_DIR)/audio/voices.c SRC += $(QUANTUM_DIR)/audio/luts.c endif diff --git a/docs/_summary.md b/docs/_summary.md index 526caf926f..acbfcfaeda 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -133,6 +133,7 @@ * [Compatible Microcontrollers](compatible_microcontrollers.md) * [Drivers](hardware_drivers.md) * [ADC Driver](adc_driver.md) + * [Audio Driver](audio_driver.md) * [I2C Driver](i2c_driver.md) * [SPI Driver](spi_driver.md) * [WS2812 Driver](ws2812_driver.md) diff --git a/docs/audio_driver.md b/docs/audio_driver.md new file mode 100644 index 0000000000..7cd5a98d9f --- /dev/null +++ b/docs/audio_driver.md @@ -0,0 +1,221 @@ +# Audio Driver :id=audio-driver + +The [Audio feature](feature_audio.md) breaks the hardware specifics out into separate, exchangeable driver units, with a common interface to the audio-"core" - which itself handles playing songs and notes while tracking their progress in an internal state, initializing/starting/stopping the driver as needed. + +Not all MCUs support every available driver, either the platform-support is not there (yet?) or the MCU simply does not have the required hardware peripheral. + + +## AVR :id=avr + +Boards built around an Atmega32U4 can use two sets of PWM capable pins, each driving a separate speaker. +The possible configurations are: + +| | Timer3 | Timer1 | +|--------------|-------------|--------------| +| one speaker | C4,C5 or C6 | | +| one speaker | | B4, B5 or B7 | +| two speakers | C4,C5 or C6 | B4, B5 or B7 | + +Currently there is only one/default driver for AVR based boards, which is automatically configured to: + +```make +AUDIO_DRIVER = pwm_hardware +``` + + +## ARM :id=arm + +For Arm based boards, QMK depends on ChibiOS - hence any MCU supported by the later is likely usable, as long as certain hardware peripherals are available. + +Supported wiring configurations, with their ChibiOS/MCU peripheral requirement are listed below; +piezo speakers are marked with :one: for the first/primary and :two: for the secondary. + + | driver | GPTD6<br>Tim6 | GPTD7<br>Tim7 | GPTD8<br>Tim8 | PWMD1<sup>1</sup><br>Tim1_Ch1 | + |--------------|------------------------------------------|------------------------|---------------|-------------------------------| + | dac_basic | A4+DACD1 = :one: | A5+DACD2 = :one: | state | | + | | A4+DACD1 = :one: + Gnd | A5+DACD2 = :two: + Gnd | state | | + | | A4+DACD1 = :two: + Gnd | A5+DACD2 = :one: + Gnd | state | | + | | A4+DACD1 = :one: + Gnd | | state | | + | | | A5+DACD2 = :one: + Gnd | state | | + | dac_additive | A4+DACD1 = :one: + Gnd | | | | + | | A5+DACD2 = :one: + Gnd | | | | + | | A4+DACD1 + A5+DACD2 = :one: <sup>2</sup> | | | | + | pwm_software | state-update | | | any = :one: | + | pwm hardware | state-update | | | A8 = :one: <sup>3</sup> | + + +<sup>1</sup>: the routing and alternate functions for PWM differ sometimes between STM32 MCUs, if in doubt consult the data-sheet +<sup>2</sup>: one piezo connected to A4 and A5, with AUDIO_PIN_ALT_AS_NEGATIVE set +<sup>3</sup>: TIM1_CH1 = A8 on STM32F103C8, other combinations are possible, see Data-sheet. configured with: AUDIO_PWM_DRIVER and AUDIO_PWM_CHANNEL + + + +### DAC basic :id=dac-basic + +The default driver for ARM boards, in absence of an overriding configuration. +This driver needs one Timer per enabled/used DAC channel, to trigger conversion; and a third timer to trigger state updates with the audio-core. + +Additionally, in the board config, you'll want to make changes to enable the DACs, GPT for Timers 6, 7 and 8: + +``` c +//halconf.h: +#define HAL_USE_DAC TRUE +#define HAL_USE_GPT TRUE +#include_next <halconf.h> +``` + +``` c +// mcuconf.h: +#include_next <mcuconf.h> +#undef STM32_DAC_USE_DAC1_CH1 +#define STM32_DAC_USE_DAC1_CH1 TRUE +#undef STM32_DAC_USE_DAC1_CH2 +#define STM32_DAC_USE_DAC1_CH2 TRUE +#undef STM32_GPT_USE_TIM6 +#define STM32_GPT_USE_TIM6 TRUE +#undef STM32_GPT_USE_TIM7 +#define STM32_GPT_USE_TIM7 TRUE +#undef STM32_GPT_USE_TIM8 +#define STM32_GPT_USE_TIM8 TRUE +``` + +?> Note: DAC1 (A4) uses TIM6, DAC2 (A5) uses TIM7, and the audio state timer uses TIM8 (configurable). + +You can also change the timer used for the overall audio state by defining the driver. For instance: + +```c +#define AUDIO_STATE_TIMER GPTD9 +``` + +### DAC additive :id=dac-additive + +only needs one timer (GPTD6, Tim6) to trigger the DAC unit to do a conversion; the audio state updates are in turn trigge |