Browse Source

[Audio] Add support for audio shutdown pin (#22731)

Co-authored-by: Ryan <fauxpark@gmail.com>
Drashna Jaelre 2 years ago
parent
commit
83e6ddbbb4

+ 2 - 0
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"},
 

+ 8 - 0
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"}
             }
         },

+ 25 - 23
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.

+ 7 - 0
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.

+ 0 - 2
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

+ 5 - 0
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"}

+ 0 - 42
keyboards/adafruit/macropad/macropad.c

@@ -1,42 +0,0 @@
-/* Copyright 2022 Jose Pablo Ramirez <jp.ramangulo@gmail.com>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#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

+ 3 - 3
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) {

+ 3 - 3
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++) {

+ 3 - 3
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);
     }

+ 3 - 3
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);
 }

+ 3 - 3
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);
 }

+ 3 - 3
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() {}

+ 27 - 0
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);
 }

+ 3 - 3
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