Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio system overhaul #11820

Merged
merged 153 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from 152 commits
Commits
Show all changes
153 commits
Select commit Hold shift + click to select a range
c14c47d
Redo Arm DAC implementation for additive, wavetable synthesis, sample…
Sep 15, 2019
a483d40
Redo Arm DAC implementation for additive, wavetable synthesis, sample…
Sep 16, 2019
3f093e0
refactoring: rename audio_ to reflect their supported hardware-platfo…
Jun 16, 2019
4d6e7f9
refactoring: deducplicate ISR code to update the pwm duty-cycle and p…
Jun 17, 2019
a1651dc
refactoring: move common code of arm and avr implementation into a se…
Jun 17, 2019
dc81755
refactoring: audio_avr_pwm, renaming defines to decouple them from ac…
Sep 16, 2019
5ba2d15
refactoring: audio_avr_pwm - replacing function defines with plain re…
Jun 22, 2019
369e949
add audio-arm-pwm
Jun 19, 2019
6401062
clang-format changes on quantum/audio/* only
Sep 16, 2019
dc2b408
audio_arm_dac: stopping the notes caused screeching when using the DA…
Feb 23, 2020
ed423f2
audio_arm_pwm: use pushpull on the pin; so that a piezzo can be hooke…
Feb 23, 2020
a8b25fe
refactoring: remove unused file from/for atmel-avr chips
Mar 1, 2020
2ed2cc6
refactoring: remove unused (avr) wavetable file
Mar 19, 2020
e6a5010
audio_arm_dac: adapt dac_end callback to changed chibios DAC api
Mar 1, 2020
57ee6a2
audio-arm-dac: show a compile-warning on undefined audio-pins
JohSchneider Mar 5, 2020
47f697e
audio_arm_dac: switch from exemplary wavetable generation to sine only
Mar 11, 2020
000cde6
audio_arm_dac: enable output buffers in the STM32
Mar 12, 2020
c4a5373
audio: prevent out-of-bounds array access
Mar 16, 2020
966757f
audio_arm_dac: add output-frequency correcting factor
Mar 16, 2020
4e00b51
audio_arm_pwm: get both the alternate-function and pm-callback varian…
Mar 17, 2020
0f913f2
audio_arm_pwm: increase pwm frequency for "higher fidelity"
Mar 17, 2020
f61efd1
audio refactoring: remove unused variables
Mar 18, 2020
26ed373
audio_arm_dac: calibrate note tempo: with a tempo of 60beats-per-seco…
Mar 18, 2020
1045acf
audio: allow feature selection in rules.mk
Mar 19, 2020
5f76573
audio-refactoring: move codeblocks in audio.[ch] into more coherent g…
Mar 21, 2020
c88052b
audio-refactoring: cleanup and streamline common code between audio_a…
Mar 21, 2020
2c38c18
audio_avr_pwm: getting it back into working condition, and cleanup+re…
Mar 21, 2020
1290f0a
audio-refactoring: documentation and typo fixes
JohSchneider Mar 22, 2020
363bacb
audio-refactoring: cleanup defines, inludes and remove debug-prints
Mar 22, 2020
5548bf4
audio_chibios_dac: define&use a minimal sampling rate, based on the a…
Mar 25, 2020
6f3fed5
audio-refactoring: one common AUDIO_MAX_VOICES define for all audio-d…
Mar 25, 2020
981ad17
audio-chibios-pwm: pwm-pin-allternate: make the the timer, timer-chan…
Mar 25, 2020
2c80f4e
audio_chibios_dac: math.h has fmod for this
Mar 25, 2020
e7c84d6
Redo Arm DAC implementation for additive, wavetable synthesis, sample…
Mar 25, 2020
1008d5a
audio-refactoring: use a common AUDIO_PIN configuration switch instea…
Mar 26, 2020
768f540
audio-refactoring: switch backlight_avr.c to the new AUDIO_PIN defines
Mar 26, 2020
f1c8c64
audio-common: have advance_note return a boolean if the note changed,…
Mar 26, 2020
5c41d51
audio-chibios-pwm: fix issue with ~130ms silence between note/frequen…
Mar 26, 2020
da47af6
audio-refactoring: get 'play_note' working again
Mar 26, 2020
d0f6f50
audio: set the fallback driver to DAC for chibios and PWM for all oth…
Mar 26, 2020
e33bb3e
audio-refactoring: moore documentation
Mar 27, 2020
f37394f
audio-avr-pwm: no fallback on unset AUDIO_PIN
Mar 27, 2020
f6cbbbf
audio-refactoring: untangling terminology: voice->tone
Mar 27, 2020
7ec6cb2
audio-pwm: allow freq=0 aka a pause/rest in a SONG
Mar 27, 2020
d33db7c
audio-refactoring: audio_advance_note -> audio_advance_state
Mar 28, 2020
34d3b22
audio-refactoring: untangling terminology: polyphony
Mar 28, 2020
ada0775
audio-chibios-dac: add zero-crossing feature
Mar 28, 2020
d69cfca
audio-refactoring: feature: time-multiplexing of tones on a single ou…
Mar 31, 2020
e5837cf
audio-avr-pwm: get music-mode working (again) on AVRs
Mar 31, 2020
7f1695a
audio-refactoring: split define MAX_SIMULTANEOUS_TONES -> TONE_STACKSIZE
Apr 1, 2020
4cab662
audio-arm-dac: per define selectable sample-luts
Apr 1, 2020
88f2830
audio-refactoring: heh, avr has a MIN...
Apr 2, 2020
1330844
audio-refactoring: add basic dac audio-driver based on the current/ma…
Apr 2, 2020
1286d48
audio-refactoring: rename audio-drivers to driver_$PLATFORM_$DRIVER
Apr 2, 2020
66f5d08
audio-arm-pwm: split the software/hardware implementations into separ…
Apr 2, 2020
a42d605
audio-refactoring: update documentation
Apr 2, 2020
e098b7f
audio-arm-dac: apply AUDIO_PIN defines to driver_chibios_dac_basic
Apr 2, 2020
65ed46b
audio-arm-dac: dac_additive: stop the hardware when the last sample c…
Apr 2, 2020
4eb7d77
audio-refactoring: make function-namespace consistent
Apr 3, 2020
b3d481b
audio-refactoring: consistent define namespace: DAC_ -> AUDIO_DAC_
Apr 3, 2020
404b5e3
audio-arm-dac: update (inline) documentation regarding MAX for sample…
Apr 3, 2020
94efb30
audio-chibios-dac: remove zero-crossing feature
Apr 3, 2020
15b76b0
audio-arm-dac: dac_basic: respect the configured sample-rate
Apr 4, 2020
7e1c670
audio-arm-pwm: have 'note_timbre' influence the pwm-duty cycle
Apr 8, 2020
0c14fc8
audio-refactoring: get VIBRATO working (again)
Apr 8, 2020
4690dc1
audio-arm-dac: zero-crossing feature (Mk II)
Apr 8, 2020
8f43ec4
audio-refactoring: re-add note-resting -> introduce short_rest inbetween
Apr 8, 2020
27a9500
audio-refactoring: cleanup refactoring remnants
Apr 8, 2020
ca5acf2
audio-refactoring: reserve negative numbers as unitialized frequencies
Apr 8, 2020
61e6711
audio-refactoring: FIX: first note of melody was missing
Apr 8, 2020
1a1d986
audio-arm-dac: fix hardware init-click
Apr 8, 2020
38de9db
audio-refactoring: new conveniance function: audio_play_click
Apr 8, 2020
35d71a7
audio-refactoring: clang-format on quantum/audio/*
Apr 8, 2020
f235ef6
audio-avr-pwm: consecutive notes of the same frequency get a pause in…
Apr 8, 2020
6bb4e40
audio-refactoring: use milliseconds instead of seconds for 'click' pa…
Apr 10, 2020
2d4f907
audio-refactoring: use timer ticks instead of counters
Apr 10, 2020
264734a
audio-refactoring: voices.c: drop 'envelope_index' counter in favour …
Apr 10, 2020
136f6a0
audio-refactoring: move vibrato and timbre related parts from audio.c…
Apr 10, 2020
5047505
audio.c: use system-ticks instead of counters the drivers have to tak…
Apr 11, 2020
bd37142
audio.c: stop notes after new ones have been started
Apr 11, 2020
03a3534
audio.c: bugfix: actually play a pause
Apr 11, 2020
29151ce
audio-arm-pwm: pwm-software: add inverted output
Apr 11, 2020
2c22d4a
audio-arm-dac: basic: handle piezo configured&wired to both audio pins
Apr 11, 2020
77d3338
audio-refactoring: docs: update for AUDIO_PIN_ALT_AS_NEGATIVE and pie…
Apr 11, 2020
f644912
audio.c: bugfix: use timer_elapsed32 instad of keeping timestamps
Apr 13, 2020
e095641
audio-refactoring: add 'pragma once' and remove deprecated NOTE_REST
Apr 13, 2020
db230e9
audio_arm_dac: basic: add missing bracket
Apr 13, 2020
0fe6183
audio.c: fix delta calculation
Apr 14, 2020
b47d785
audio-refactoring: buildfix: wrong legacy macro for set_timbre
Apr 14, 2020
20d2af7
audio.c: 16bit timerstamps suffice
Apr 14, 2020
6eecf29
audio-refactoring: separate includes for AVR and chibios
Apr 18, 2020
775805d
audio-refactoring: timbre: use uint8 instead of float
Apr 18, 2020
7105f1a
audio-refactoring: duration: use uint16 for internal per-tone/note state
Apr 21, 2020
15ee70d
audio-refactoring: tonemultiplexing: use uint16 instead of float
Apr 21, 2020
759fccc
audio-arm-dac: additive: set second pin output-low
Apr 22, 2020
5805704
audio-refactoring: move AUDIO_PIN selection from rules.mk to config.h
Apr 22, 2020
ee7401f
audio-refactoring: buildfix: wrong legacy macro for set_tempo
Apr 24, 2020
8d91bf9
audio-arm-dac: additive: set second pin output-low -- FIXUP
Apr 25, 2020
6ad86b8
audio.c: do duration<>ms conversion in uint instead of float
Apr 25, 2020
9c0bbb2
audio-refactoring: cleanup eeprom defines/usage
JohSchneider Apr 26, 2020
7e170f8
audio.h: throw an error if OFF is larger than MAX
Apr 26, 2020
90e517d
audio-arm-dac: basic: actually stop the dac-conversion on a audio_dri…
Apr 26, 2020
9672e45
audio-arm-dac: additive: move zero-crossing code out of dac_value_gen…
Apr 30, 2020
fedd7ff
audio-arm-dac: dac-additive: zero-crossing: ramping up or down
Apr 30, 2020
c8b6434
audio-arm-dac: dac-additive: BUGFIX: return OFF_VALUE when a pause is…
Apr 30, 2020
25a7b82
audio-arm-dac: set a sensible default for AUDIO_DAC_VALUE_OFF
Apr 30, 2020
1daacef
audio-arm-dac: update synth_sample/_wavetable for new pin-defines
Apr 30, 2020
6ed0a90
audio-arm-dac: default for AUDIO_DAC_VALUE_OFF
Apr 30, 2020
6d8a113
audio-arm-dac: additive: use DAC for negative pin
May 1, 2020
3e613af
audio-arm-dac: more compile-time configuration checks
May 1, 2020
f1d9be1
audio-refactoring: typo fixed
May 1, 2020
64d5833
audio-refactoring: clang-format on quantum/audio/*
May 1, 2020
3475518
audio-avr-pwm: add defines for B-pin as primary/only speaker
May 1, 2020
31f27fd
audio-refactoring: update documentation with proton-c config.h example
May 1, 2020
2876ebd
audio-refactoring: move glissando (TODO) to voices.c
May 1, 2020
0155095
audio-refactoring: cleanup: one round of aspell -c
May 2, 2020
90184f6
audio-avr-pwm: back to AUDIO_PIN
May 2, 2020
a23ce28
audio-refactoring: add technical documentation audio_driver.md
May 3, 2020
54d17f4
audio-arm-dac: move AUDIO_PIN checks into c-code
May 4, 2020
5a39a34
audio-arm-dac: compile-fix: set AUDIO_PIN if unset
May 4, 2020
85d04f2
audio-refactoring: document tone-multiplexing feature
May 7, 2020
d75a3c4
audio-refactoring: Apply suggestions from documentation review
JohSchneider May 8, 2020
39161f2
audio-refactoring: Update docs/audio_driver.md
JohSchneider May 8, 2020
cbdc711
audio-refactoring: docs: fix markdown newlines
JohSchneider May 9, 2020
6f7d185
audio-arm-dac: additive: fix AUDIO_PIN_ALT handling
May 19, 2020
e870e4d
audio-arm-pwm: align define naming with other drivers
JohSchneider May 21, 2020
44a45b3
audio-refactoring: set detault tempo to 120
Jun 4, 2020
d4d651b
audio-refactoring: update backlight define checks to new AUDIO_PIN names
JohSchneider Jun 4, 2020
a1442e0
audio-refactoring: reworking PWM related defines
JohSchneider Jun 4, 2020
e9eb7b5
audio-arm: have the state-update-timer user configurable
Jun 4, 2020
61df59d
audio-refactoring: PLAY_NOTE_ARRAY was already removed in master
JohSchneider Jun 4, 2020
4294fa4
Add prototype for startup
drashna Feb 4, 2021
8da02d2
Update chibiOS dac basic to disable pins on stop
drashna Feb 4, 2021
60ed191
Add defaults for Proton C
drashna Feb 4, 2021
0cf5829
avoid hanging audio if note is completely missed
spidey3 Feb 7, 2021
bb05c3c
Don't redefine pins if they're already defined
drashna Feb 7, 2021
52f68c4
Define A4 and A5 for CTPC support
drashna Feb 7, 2021
62942f5
Add license headers to keymap files
drashna Feb 7, 2021
e173b36
Remove figlet? comments
drashna Feb 7, 2021
abeb77c
Add DAC config to audio driver docs
drashna Feb 8, 2021
30006b7
Apply suggestions from code review
drashna Feb 8, 2021
356d9f4
Add license header to py files
drashna Feb 8, 2021
630e1e2
correct license header
drashna Feb 8, 2021
5ec4004
Add JohSchneider's name to modified files
drashna Feb 8, 2021
c6ea759
Set executable permission and change interpeter
drashna Feb 8, 2021
c71264a
Add 'wave' to pip requirements
drashna Feb 8, 2021
4970cc2
Improve documentation
drashna Feb 8, 2021
28c4b3c
Add some settings I missed
drashna Feb 8, 2021
fa31cad
Strip AUDIO_DRIVER to parse the name correctly
drashna Feb 8, 2021
cea6cfb
fix depreciated
drashna Feb 9, 2021
76bf2b6
Update util/audio_generate_dac_lut.py
drashna Feb 9, 2021
c0f8605
Fix type in clueboard config
drashna Feb 12, 2021
5cd859c
Apply suggestions from tzarc
drashna Feb 14, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
205 changes: 205 additions & 0 deletions docs/audio_driver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# 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
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

``` c
// mcuconf.h:
#define STM32_DAC_USE_DAC1_CH1 TRUE
#define STM32_DAC_USE_DAC1_CH2 TRUE
#define STM32_GPT_USE_TIM6 TRUE
#define STM32_GPT_USE_TIM7 TRUE
#define STM32_GPT_USE_TIM8 TRUE
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

?> 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 triggered during the DAC callback.

Additionally, in the board config, you'll want to make changes to enable the DACs, GPT for Timer 6:

``` c
//halconf.h:
#define HAL_USE_DAC TRUE
#define HAL_USE_GPT TRUE
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

``` c
// mcuconf.h:
#define STM32_DAC_USE_DAC1_CH1 TRUE
#define STM32_DAC_USE_DAC1_CH2 TRUE
#define STM32_GPT_USE_TIM6 TRUE
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

### DAC Config

| Define | Defaults | Description --------------------------------------------------------------------------------------------- |
| `AUDIO_DAC_SAMPLE_MAX` | `4095U` | Highest value allowed. Lower value means lower volume. And 4095U is the upper limit, since this is limited to a 12 bit value. Only effects non-pregenerated samples. |
| `AUDIO_DAC_OFF_VALUE` | `AUDIO_DAC_SAMPLE_MAX / 2` | The value of the DAC when notplaying anything. Some setups may require a high (`AUDIO_DAC_SAMPLE_MAX`) or low (`0`) value here. |
| `AUDIO_MAX_SIMULTANEOUS_TONES` | __see next table__ | The number of tones that can be played simultaneously. A value that is too high may freeze the controller or glitch out when too many tones are being played. |
| `AUDIO_DAC_SAMPLE_RATE` | __see next table__ | Effective bit rate of the DAC (in hertz), higher limits simultaneous tones, and lower sacrifices quality. |

There are a number of predefined quality settings that you can use, with "sane minimum" being the default. You can use custom values by simply defining the sample rate and number of simultaneous tones, instead of using one of the listed presets.

| Define | Sample Rate | Simultaneous tones |
| `AUDIO_DAC_QUALITY_VERY_LOW` | `11025U` | `8` |
| `AUDIO_DAC_QUALITY_LOW` | `22040U` | `4` |
| `AUDIO_DAC_QUALITY_HIGH` | `44100U` | `2` |
| `AUDIO_DAC_QUALITY_VERY_HIGH` | `88200U` | `1` |
| `AUDIO_DAC_QUALITY_SANE_MINIMUM` | `16384U` | `8` |


```c
/* zero crossing (or approach, whereas zero == DAC_OFF_VALUE, which can be configured to anything from 0 to DAC_SAMPLE_MAX)
* ============================*=*========================== AUDIO_DAC_SAMPLE_MAX
* * *
* * *
* ---------------------------------------------------------
* * * } AUDIO_DAC_SAMPLE_MAX/100
* --------------------------------------------------------- AUDIO_DAC_OFF_VALUE
* * * } AUDIO_DAC_SAMPLE_MAX/100
* ---------------------------------------------------------
* *
* * *
* * *
* =====*=*================================================= 0x0
*/
```


### PWM hardware :id=pwm-hardware

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 MCU's data-sheet for which pin can be driven by what timer - looking for TIMx_CHy and the corresponding alternate function.

A configuration example for the STM32F103C8 would be:
``` c
//halconf.h:
#define HAL_USE_PWM TRUE
#define HAL_USE_PAL TRUE
#define HAL_USE_GPT TRUE
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

``` c
// mcuconf.h:
#define STM32_PWM_USE_TIM1 TRUE
#define STM32_GPT_USE_TIM4 TRUE
drashna marked this conversation as resolved.
Show resolved Hide resolved
```

If we now target pin A8, looking through the data-sheet of the STM32F103C8, for the timers and alternate functions
- TIM1_CH1 = PA8 <- alternate0
- TIM1_CH2 = PA9
- TIM1_CH3 = PA10
- TIM1_CH4 = PA11

with all this information, the configuration would contain these lines:
``` c
//config.h:
#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.
On 'larger' STM32s, GPIOv2 or GPIOv3 are used; with them it is also necessary to configure `AUDIO_PWM_PAL_MODE` to the correct alternate function for the selected pin, timer and timer-channel.


### PWM software :id=pwm-software

This driver uses the PWM callbacks from PWMD1 with TIM1_CH1 to toggle the selected AUDIO_PIN in software.
During the same callback, with AUDIO_PIN_ALT_AS_NEGATIVE set, the AUDIO_PIN_ALT is toggled inversely to AUDIO_PIN. This is useful for setups that drive a piezo from two pins (instead of one and Gnd).

You can also change the timer used for software PWM by defining the driver. For instance:

```c
#define AUDIO_STATE_TIMER GPTD8
```


### Testing Notes :id=testing-notes

While not an exhaustive list, the following table provides the scenarios that have been partially validated:

| | DAC basic | DAC additive | PWM hardware | PWM software |
|--------------------------|--------------------|--------------------|--------------------|--------------------|
| Atmega32U4 | :o: | :o: | :heavy_check_mark: | :o: |
| 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

*Other supported ChibiOS boards and/or pins may function, it will be highly chip and configuration dependent.*
12 changes: 9 additions & 3 deletions docs/config_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,22 @@ This is a C header file that is one of the first things included, and will persi
* turns on the alternate audio voices (to cycle through)
* `#define C4_AUDIO`
* enables audio on pin C4
* Deprecated. Use `#define AUDIO_PIN C4`
* `#define C5_AUDIO`
* enables audio on pin C5
* Deprecated. Use `#define AUDIO_PIN C5`
* `#define C6_AUDIO`
* enables audio on pin C6
* Deprecated. Use `#define AUDIO_PIN C6`
* `#define B5_AUDIO`
* enables audio on pin B5 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
* enables audio on pin B5 (duophony is enabled if one of B pins is enabled along with one of C pins)
* Deprecated. Use `#define AUDIO_PIN B5`, or use `#define AUDIO_PIN_ALT B5` if a `C` pin is enabled with `AUDIO_PIN`
* `#define B6_AUDIO`
* enables audio on pin B6 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
* enables audio on pin B5 (duophony is enabled if one of B pins is enabled along with one of C pins)
* Deprecated. Use `#define AUDIO_PIN B6`, or use `#define AUDIO_PIN_ALT B6` if a `C` pin is enabled with `AUDIO_PIN`
* `#define B7_AUDIO`
* enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
* enables audio on pin B5 (duophony is enabled if one of B pins is enabled along with one of C pins)
* Deprecated. Use `#define AUDIO_PIN B7`, or use `#define AUDIO_PIN_ALT B7` if a `C` pin is enabled with `AUDIO_PIN`
* `#define BACKLIGHT_PIN B7`
* pin of the backlight
* `#define BACKLIGHT_LEVELS 3`
Expand Down
Loading