From 83e6ddbbb4c8e715bfe419c4d7fc0ae305ea5bd5 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Wed, 6 Mar 2024 03:02:37 -0800 Subject: [PATCH] [Audio] Add support for audio shutdown pin (#22731) Co-authored-by: Ryan --- data/mappings/info_config.hjson | 2 + data/schemas/keyboard.jsonschema | 8 ++++ docs/feature_audio.md | 48 ++++++++++--------- docs/reference_info_json.md | 7 +++ keyboards/adafruit/macropad/config.h | 2 - keyboards/adafruit/macropad/info.json | 5 ++ keyboards/adafruit/macropad/macropad.c | 42 ---------------- platforms/avr/drivers/audio_pwm_hardware.c | 6 +-- .../chibios/drivers/audio_dac_additive.c | 6 +-- platforms/chibios/drivers/audio_dac_basic.c | 6 +-- .../chibios/drivers/audio_pwm_hardware.c | 6 +-- .../chibios/drivers/audio_pwm_software.c | 6 +-- platforms/test/drivers/audio_pwm_hardware.c | 6 +-- quantum/audio/audio.c | 27 +++++++++++ quantum/audio/audio.h | 6 +-- 15 files changed, 95 insertions(+), 88 deletions(-) delete mode 100644 keyboards/adafruit/macropad/macropad.c diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson index e2e9569372e..c0417b88396 100644 --- a/data/mappings/info_config.hjson +++ b/data/mappings/info_config.hjson @@ -19,6 +19,8 @@ // Audio "AUDIO_DEFAULT_ON": {"info_key": "audio.default.on", "value_type": "bool"}, "AUDIO_DEFAULT_CLICKY_ON": {"info_key": "audio.default.clicky", "value_type": "bool"}, + "AUDIO_POWER_CONTROL_PIN": {"info_key": "audio.power_control.pin"}, + "AUDIO_POWER_CONTROL_PIN_ON_STATE": {"info_key": "audio.power_control.on_state", "value_type": "int" }, "AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "flag"}, "SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "flag"}, diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema index 340eb64ba1a..5c6788913b0 100644 --- a/data/schemas/keyboard.jsonschema +++ b/data/schemas/keyboard.jsonschema @@ -135,6 +135,14 @@ }, "macro_beep": {"type": "boolean"}, "pins": {"$ref": "qmk.definitions.v1#/mcu_pin_array"}, + "power_control": { + "type": "object", + "additionalProperties": false, + "properties": { + "on_state": {"$ref": "qmk.definitions.v1#/bit"}, + "pin": {"$ref": "qmk.definitions.v1#/mcu_pin"} + } + }, "voices": {"type": "boolean"} } }, diff --git a/docs/feature_audio.md b/docs/feature_audio.md index 5227d063c3a..05f32e98401 100644 --- a/docs/feature_audio.md +++ b/docs/feature_audio.md @@ -171,29 +171,31 @@ The available keycodes for audio are: ## Audio Config -| Settings | Default | Description | -|---------------------------------|----------------------|-------------------------------------------------------------------------------| -|`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. | -|`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker.| -|`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. | -|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. | -|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. | -|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) | -|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) | -|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) | -|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) | -|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) | -|`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) | -|`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) | -|`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) | -|`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) | -|`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) | -|`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) | -|`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) | -|`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) | -|`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) | -|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c) | -|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) | +| Settings | Default | Description | +|----------------------------------|----------------------|---------------------------------------------------------------------------------------------| +|`AUDIO_PIN` | *Not defined* |Configures the pin that the speaker is connected to. | +|`AUDIO_PIN_ALT` | *Not defined* |Configures the pin for a second speaker or second pin connected to one speaker. | +|`AUDIO_PIN_ALT_AS_NEGATIVE` | *Not defined* |Enables support for one speaker connected to two pins. | +|`AUDIO_INIT_DELAY` | *Not defined* |Enables delay during startup song to accomidate for USB startup issues. | +|`AUDIO_ENABLE_TONE_MULTIPLEXING` | *Not defined* |Enables time splicing/multiplexing to create multiple tones simutaneously. | +|`AUDIO_POWER_CONTROL_PIN` | *Not defined* |Enables power control code to enable or cut off power to speaker (such as with PAM8302 amp). | +|`AUDIO_POWER_CONTROL_PIN_ON_STATE`| `1` |The state of the audio power control pin when audio is "on" - `1` for high, `0` for low. | +|`STARTUP_SONG` | `STARTUP_SOUND` |Plays when the keyboard starts up (audio.c) | +|`GOODBYE_SONG` | `GOODBYE_SOUND` |Plays when you press the QK_BOOT key (quantum.c) | +|`AG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press AG_NORM (process_magic.c) | +|`AG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press AG_SWAP (process_magic.c) | +|`CG_NORM_SONG` | `AG_NORM_SOUND` |Plays when you press CG_NORM (process_magic.c) | +|`CG_SWAP_SONG` | `AG_SWAP_SOUND` |Plays when you press CG_SWAP (process_magic.c) | +|`MUSIC_ON_SONG` | `MUSIC_ON_SOUND` |Plays when music mode is activated (process_music.c) | +|`MUSIC_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when music mode is deactivated (process_music.c) | +|`MIDI_ON_SONG` | `MUSIC_ON_SOUND` |Plays when midi mode is activated (process_music.c) | +|`MIDI_OFF_SONG` | `MUSIC_OFF_SOUND` |Plays when midi mode is deactivated (process_music.c) | +|`CHROMATIC_SONG` | `CHROMATIC_SOUND` |Plays when the chromatic music mode is selected (process_music.c) | +|`GUITAR_SONG` | `GUITAR_SOUND` |Plays when the guitar music mode is selected (process_music.c) | +|`VIOLIN_SONG` | `VIOLIN_SOUND` |Plays when the violin music mode is selected (process_music.c) | +|`MAJOR_SONG` | `MAJOR_SOUND` |Plays when the major music mode is selected (process_music.c) | +|`DEFAULT_LAYER_SONGS` | *Not defined* |Plays song when switched default layers with [`set_single_persistent_default_layer(layer)`](ref_functions.md#setting-the-persistent-default-layer)(quantum.c). | +|`SENDSTRING_BELL` | *Not defined* |Plays chime when the "enter" ("\a") character is sent (send_string.c) | ## Tempo the 'speed' at which SONGs are played is dictated by the set Tempo, which is measured in beats-per-minute. Note lengths are defined relative to that. diff --git a/docs/reference_info_json.md b/docs/reference_info_json.md index 796db1f2446..b715c14041c 100644 --- a/docs/reference_info_json.md +++ b/docs/reference_info_json.md @@ -123,10 +123,17 @@ Configures the [Audio](feature_audio.md) feature. * Default: `false` * `pins` (Required) * The GPIO pin(s) connected to the speaker(s). + * `power_control` + * `on_state` + * The logical GPIO state required to turn the speaker on. + * Default: `1` (on = high) + * `pin` + * The GPIO pin connected to speaker power circuit. * `voices` * Use multiple audio voices. * Default: `false` + ## Backlight :id=backlight Configures the [Backlight](feature_backlight.md) feature. diff --git a/keyboards/adafruit/macropad/config.h b/keyboards/adafruit/macropad/config.h index 7f2e9ab6f96..725530a512b 100644 --- a/keyboards/adafruit/macropad/config.h +++ b/keyboards/adafruit/macropad/config.h @@ -48,5 +48,3 @@ #define AUDIO_PWM_CHANNEL RP2040_PWM_CHANNEL_A #define AUDIO_INIT_DELAY #define AUDIO_CLICKY - -#define SPEAKER_SHUTDOWN GP14 diff --git a/keyboards/adafruit/macropad/info.json b/keyboards/adafruit/macropad/info.json index 0facf7e0f66..295af783398 100644 --- a/keyboards/adafruit/macropad/info.json +++ b/keyboards/adafruit/macropad/info.json @@ -8,6 +8,11 @@ "pid": "0x0108", "device_version": "0.0.1" }, + "audio": { + "power_control": { + "pin": "GP14" + } + }, "encoder": { "rotary": [ {"pin_a": "GP18", "pin_b": "GP17"} diff --git a/keyboards/adafruit/macropad/macropad.c b/keyboards/adafruit/macropad/macropad.c deleted file mode 100644 index 5c1d2ba5930..00000000000 --- a/keyboards/adafruit/macropad/macropad.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright 2022 Jose Pablo Ramirez - * - * 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 . - */ - -#include "quantum.h" - -#ifdef AUDIO_ENABLE -void keyboard_pre_init_kb(void) { - // ensure pin is set and enabled pre-audio init - setPinOutput(SPEAKER_SHUTDOWN); - writePinHigh(SPEAKER_SHUTDOWN); - keyboard_pre_init_user(); -} - -void keyboard_post_init_kb(void) { - // set pin based on active status - writePin(SPEAKER_SHUTDOWN, audio_is_on()); - keyboard_post_init_user(); -} - -void audio_on_user(void) { - writePinHigh(SPEAKER_SHUTDOWN); -} - -void audio_off_user(void) { - // needs a delay or it runs right after play note. - wait_ms(200); - writePinLow(SPEAKER_SHUTDOWN); -} -#endif diff --git a/platforms/avr/drivers/audio_pwm_hardware.c b/platforms/avr/drivers/audio_pwm_hardware.c index d484fba00fb..16264cf0a22 100644 --- a/platforms/avr/drivers/audio_pwm_hardware.c +++ b/platforms/avr/drivers/audio_pwm_hardware.c @@ -213,7 +213,7 @@ void channel_2_stop(void) { } #endif -void audio_driver_initialize(void) { +void audio_driver_initialize_impl(void) { #ifdef AUDIO1_PIN_SET channel_1_stop(); gpio_set_pin_output(AUDIO1_PIN); @@ -254,7 +254,7 @@ void audio_driver_initialize(void) { #endif } -void audio_driver_stop(void) { +void audio_driver_stop_impl(void) { #ifdef AUDIO1_PIN_SET channel_1_stop(); #endif @@ -264,7 +264,7 @@ void audio_driver_stop(void) { #endif } -void audio_driver_start(void) { +void audio_driver_start_impl(void) { #ifdef AUDIO1_PIN_SET channel_1_start(); if (playing_note) { diff --git a/platforms/chibios/drivers/audio_dac_additive.c b/platforms/chibios/drivers/audio_dac_additive.c index d6fde42b68f..8e29053301f 100644 --- a/platforms/chibios/drivers/audio_dac_additive.c +++ b/platforms/chibios/drivers/audio_dac_additive.c @@ -303,7 +303,7 @@ static const DACConfig dac_conf = {.init = AUDIO_DAC_OFF_VALUE, .datamode = DAC_ */ static const DACConversionGroup dac_conv_cfg = {.num_channels = 1U, .end_cb = dac_end, .error_cb = dac_error, .trigger = DAC_TRG(0b000)}; -void audio_driver_initialize(void) { +void audio_driver_initialize_impl(void) { if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { palSetLineMode(A4, PAL_MODE_INPUT_ANALOG); dacStart(&DACD1, &dac_conf); @@ -350,11 +350,11 @@ void audio_driver_initialize(void) { gptStart(&GPTD6, &gpt6cfg1); } -void audio_driver_stop(void) { +void audio_driver_stop_impl(void) { state = OUTPUT_SHOULD_STOP; } -void audio_driver_start(void) { +void audio_driver_start_impl(void) { gptStartContinuous(&GPTD6, 2U); for (uint8_t i = 0; i < AUDIO_MAX_SIMULTANEOUS_TONES; i++) { diff --git a/platforms/chibios/drivers/audio_dac_basic.c b/platforms/chibios/drivers/audio_dac_basic.c index 9a3f3fea1f3..99b938e610a 100644 --- a/platforms/chibios/drivers/audio_dac_basic.c +++ b/platforms/chibios/drivers/audio_dac_basic.c @@ -190,7 +190,7 @@ static void gpt_audio_state_cb(GPTDriver *gptp) { } } -void audio_driver_initialize(void) { +void audio_driver_initialize_impl(void) { if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); dacStart(&DACD1, &dac_conf_ch1); @@ -223,7 +223,7 @@ void audio_driver_initialize(void) { gptStart(&AUDIO_STATE_TIMER, &gptStateUpdateCfg); } -void audio_driver_stop(void) { +void audio_driver_stop_impl(void) { if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { gptStopTimer(&GPTD6); @@ -241,7 +241,7 @@ void audio_driver_stop(void) { gptStopTimer(&AUDIO_STATE_TIMER); } -void audio_driver_start(void) { +void audio_driver_start_impl(void) { if ((AUDIO_PIN == A4) || (AUDIO_PIN_ALT == A4)) { dacStartConversion(&DACD1, &dac_conv_grp_ch1, (dacsample_t *)dac_buffer_1, AUDIO_DAC_BUFFER_SIZE); } diff --git a/platforms/chibios/drivers/audio_pwm_hardware.c b/platforms/chibios/drivers/audio_pwm_hardware.c index 21b5c6892cd..1ba7ec13bcf 100644 --- a/platforms/chibios/drivers/audio_pwm_hardware.c +++ b/platforms/chibios/drivers/audio_pwm_hardware.c @@ -87,7 +87,7 @@ static void audio_callback(virtual_timer_t *vtp, void *p) { chSysUnlockFromISR(); } -void audio_driver_initialize(void) { +void audio_driver_initialize_impl(void) { pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); // connect the AUDIO_PIN to the PWM hardware @@ -100,7 +100,7 @@ void audio_driver_initialize(void) { chVTObjectInit(&audio_vt); } -void audio_driver_start(void) { +void audio_driver_start_impl(void) { channel_1_stop(); channel_1_start(); @@ -115,7 +115,7 @@ void audio_driver_start(void) { } } -void audio_driver_stop(void) { +void audio_driver_stop_impl(void) { channel_1_stop(); chVTReset(&audio_vt); } diff --git a/platforms/chibios/drivers/audio_pwm_software.c b/platforms/chibios/drivers/audio_pwm_software.c index 663a9eca165..f48323900b4 100644 --- a/platforms/chibios/drivers/audio_pwm_software.c +++ b/platforms/chibios/drivers/audio_pwm_software.c @@ -121,7 +121,7 @@ GPTConfig gptCFG = { .callback = gpt_callback, }; -void audio_driver_initialize(void) { +void audio_driver_initialize_impl(void) { pwmStart(&AUDIO_PWM_DRIVER, &pwmCFG); palSetLineMode(AUDIO_PIN, PAL_MODE_OUTPUT_PUSHPULL); @@ -138,7 +138,7 @@ void audio_driver_initialize(void) { gptStart(&AUDIO_STATE_TIMER, &gptCFG); } -void audio_driver_start(void) { +void audio_driver_start_impl(void) { channel_1_stop(); channel_1_start(); @@ -147,7 +147,7 @@ void audio_driver_start(void) { } } -void audio_driver_stop(void) { +void audio_driver_stop_impl(void) { channel_1_stop(); gptStopTimer(&AUDIO_STATE_TIMER); } diff --git a/platforms/test/drivers/audio_pwm_hardware.c b/platforms/test/drivers/audio_pwm_hardware.c index 336e4f58449..3a0384117a4 100644 --- a/platforms/test/drivers/audio_pwm_hardware.c +++ b/platforms/test/drivers/audio_pwm_hardware.c @@ -15,6 +15,6 @@ #include "audio.h" -void audio_driver_initialize(void) {} -void audio_driver_start() {} -void audio_driver_stop() {} +void audio_driver_initialize_impl(void) {} +void audio_driver_start_impl() {} +void audio_driver_stop_impl() {} diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index c1a15004930..b2611c5f099 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -20,6 +20,7 @@ #include "debug.h" #include "wait.h" #include "util.h" +#include "gpio.h" /* audio system: * @@ -121,6 +122,32 @@ static bool audio_initialized = false; static bool audio_driver_stopped = true; audio_config_t audio_config; +#ifndef AUDIO_POWER_CONTROL_PIN_ON_STATE +# define AUDIO_POWER_CONTROL_PIN_ON_STATE 1 +#endif + +void audio_driver_initialize(void) { +#ifdef AUDIO_POWER_CONTROL_PIN + gpio_set_pin_output_push_pull(AUDIO_POWER_CONTROL_PIN); + gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE); +#endif + audio_driver_initialize_impl(); +} + +void audio_driver_stop(void) { + audio_driver_stop_impl(); +#ifdef AUDIO_POWER_CONTROL_PIN + gpio_write_pin(AUDIO_POWER_CONTROL_PIN, !AUDIO_POWER_CONTROL_PIN_ON_STATE); +#endif +} + +void audio_driver_start(void) { +#ifdef AUDIO_POWER_CONTROL_PIN + gpio_write_pin(AUDIO_POWER_CONTROL_PIN, AUDIO_POWER_CONTROL_PIN_ON_STATE); +#endif + audio_driver_start_impl(); +} + void eeconfig_update_audio_current(void) { eeconfig_update_audio(audio_config.raw); } diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index eb0bedc6f9f..054331d6f33 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -215,9 +215,9 @@ void audio_startup(void); // hardware interface // implementation in the driver_avr/arm_* respective parts -void audio_driver_initialize(void); -void audio_driver_start(void); -void audio_driver_stop(void); +void audio_driver_initialize_impl(void); +void audio_driver_start_impl(void); +void audio_driver_stop_impl(void); /** * @brief get the number of currently active tones