From cc5c6b449a4a36fc56fa5896b2b8f120e4bb0b31 Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Thu, 14 Feb 2019 20:18:54 -0800 Subject: [PATCH] Add kb and user level keyboard initialization functions (#3113) * Add suspend functions * Disable RGB code if it's disabled * Add keyboard_init functions * Change where references so it will compile * Wrong command chained in wake up kb function * Fix non-feature file changes * Add documentation * Re-add matrix init docs * add rgblight code to example * Remove suspend code * Clean up docs * Fix docs * Fix suspend code * more doc fixes * change function to startup_* rather than keyboard_init_ * fix spelling error * fix up docs to finish removing keyboard_init * Use Pre and Post init functions * Update Documenation * Remove changes to my keymap and userspace code * Cleanup * Revert changes to extra files * Forgot a semicolon * Make sure all protocols call keyboard_setup * Cleanup functions * Unset startup_user * Remove changes from division keyboard * Readd startup_user function * Remove all to startup_user * Update docs/custom_quantum_functions.md Co-Authored-By: drashna * Update docs/custom_quantum_functions.md Co-Authored-By: drashna * Add suggestion line * Rebase fixes * Update documentation to be more useful/accurate * Cleanup of documentation * Fix spacing inconsistency * Revert unexpected change to keymap --- docs/custom_quantum_functions.md | 68 ++++++++++++++++++++++++++---- tmk_core/common/avr/suspend.c | 26 ++++++------ tmk_core/common/keyboard.c | 36 ++++++++++++++++ tmk_core/common/keyboard.h | 5 +++ tmk_core/protocol/bluefruit/main.c | 15 ++++--- tmk_core/protocol/chibios/main.c | 2 + tmk_core/protocol/vusb/main.c | 1 + 7 files changed, 125 insertions(+), 28 deletions(-) diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md index d44786e2d5..cc84e141f9 100644 --- a/docs/custom_quantum_functions.md +++ b/docs/custom_quantum_functions.md @@ -165,18 +165,35 @@ In addition, it is possible to specify the brightness level of all LEDs with `er Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default). -# Matrix Initialization Code +# Keyboard Initialization Code -Before a keyboard can be used the hardware must be initialized. QMK handles initialization of the keyboard matrix itself, but if you have other hardware like LEDs or i²c controllers you will need to set up that hardware before it can be used. +There are several steps in the keyboard initialization process. Depending on what you want to do, it will influence which function you should use. +These are the three main initialization functions, listed in the order that they're called. -### Example `matrix_init_user()` Implementation +* `keyboard_pre_init_*` - Happens before most anything is started. Good for hardware setup that you want running very early. +* `matrix_init_*` - Happens midway through the firmware's startup process. Hardware is initialized, but features may not be yet. +* `keyboard_post_init_*` - Happens at the end of the firmware's startup process. This is where you'd want to put "customization" code, for the most part. + +!> For most people, the `keyboard_post_init_user` function is what you want to call. For instance, this is where you want to set up things for RGB Underglow. + +## Keyboard Pre Initialization code + +This runs very early during startup, even before the USB has been started. + +Shortly after this, the matrix is initialized. + +For most users, this shouldn't be used, as it's primarily for hardware oriented initialization. + +However, if you have hardware stuff that you need initialized, this is the best place for it (such as initializing LED pins). + +### Example `keyboard_pre_init_user()` Implementation This example, at the keyboard level, sets up B1, B2, and B3 as LED pins. ```c -void matrix_init_user(void) { - // Call the keymap level matrix init. +void keyboard_pre_init_user(void) { + // Call the keyboard pre init code. // Set our LED pins as output DDRB |= (1<<1); @@ -185,11 +202,47 @@ void matrix_init_user(void) { } ``` +### `keyboard_pre_init_*` Function Documentation + +* Keyboard/Revision: `void keyboard_pre_init_kb(void)` +* Keymap: `void keyboard_pre_init_user(void)` + +## Matrix Initialization Code + +This is called when the matrix is initialized, and after some of the hardware has been set up, but before many of the features have been initialized. + +This is useful for setting up stuff that you may need elsewhere, but isn't hardware related nor is dependant on where it's started. + + ### `matrix_init_*` Function Documentation * Keyboard/Revision: `void matrix_init_kb(void)` * Keymap: `void matrix_init_user(void)` + +## Keyboard Post Initialization code + +This is ran as the very last task in the keyboard initialization process. This is useful if you want to make changes to certain features, as they should be initialized by this point. + + +### Example `keyboard_post_init_user()` Implementation + +This example, running after everything else has initialized, sets up the rgb underglow configuration. + +```c +void keyboard_post_init_user(void) { + // Call the post init code. + rgblight_enable_noeeprom(); // enables Rgb, without saving settings + rgblight_sethsv_noeeprom(180, 255, 255): // sets the color to teal/cyan without saving + rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // sets mode to Fast breathing without saving +} +``` + +### `keyboard_post_init_*` Function Documentation + +* Keyboard/Revision: `void keyboard_post_init_kb(void)` +* Keymap: `void keyboard_post_init_user(void)` + # Matrix Scanning Code Whenever possible you should customize your keyboard by using `process_record_*()` and hooking into events that way, to ensure that your code does not have a negative performance impact on your keyboard. However, in rare cases it is necessary to hook into the matrix scanning. Be extremely careful with the performance of code in these functions, as it will be called at least 10 times per second. @@ -229,10 +282,9 @@ void suspend_wakeup_init_user(void) { rgb_matrix_set_suspend_state(false); } - ``` -### `keyboard_init_*` Function Documentation +### Keyboard suspend/wake Function Documentation * Keyboard/Revision: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)` * Keymap: `void suspend_power_down_kb(void)` and `void suspend_wakeup_init_user(void)` @@ -285,7 +337,7 @@ Keep in mind that EEPROM has a limited number of writes. While this is very high * If you don't understand the example, then you may want to avoid using this feature, as it is rather complicated. -### Example Implementation +### Example Implementation This is an example of how to add settings, and read and write it. We're using the user keymap for the example here. This is a complex function, and has a lot going on. In fact, it uses a lot of the above functions to work! diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 1194a040ee..b29447ac4e 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -142,20 +142,20 @@ static void power_down(uint8_t wdto) { #endif suspend_power_down_kb(); - // TODO: more power saving - // See PicoPower application note - // - I/O port input with pullup - // - prescale clock - // - BOD disable - // - Power Reduction Register PRR - set_sleep_mode(SLEEP_MODE_PWR_DOWN); - sleep_enable(); - sei(); - sleep_cpu(); - sleep_disable(); + // TODO: more power saving + // See PicoPower application note + // - I/O port input with pullup + // - prescale clock + // - BOD disable + // - Power Reduction Register PRR + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_enable(); + sei(); + sleep_cpu(); + sleep_disable(); - // Disable watchdog after sleep - wdt_disable(); + // Disable watchdog after sleep + wdt_disable(); } #endif diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 6f659b2440..15652276b8 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -139,6 +139,40 @@ __attribute__ ((weak)) void matrix_setup(void) { } +/** \brief keyboard_pre_init_user + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void keyboard_pre_init_user(void) { } + +/** \brief keyboard_pre_init_kb + * + * FIXME: needs doc + */ +__attribute__ ((weak)) +void keyboard_pre_init_kb(void) { + keyboard_pre_init_user(); +} + +/** \brief keyboard_post_init_user + * + * FIXME: needs doc + */ + +__attribute__ ((weak)) +void keyboard_post_init_user() {} + +/** \brief keyboard_post_init_kb + * + * FIXME: needs doc + */ + +__attribute__ ((weak)) +void keyboard_post_init_kb(void) { + keyboard_post_init_user(); +} + /** \brief keyboard_setup * * FIXME: needs doc @@ -146,6 +180,7 @@ void matrix_setup(void) { void keyboard_setup(void) { disable_jtag(); matrix_setup(); + keyboard_pre_init_kb(); } /** \brief is_keyboard_master @@ -199,6 +234,7 @@ void keyboard_init(void) { #if defined(NKRO_ENABLE) && defined(FORCE_NKRO) keymap_config.nkro = 1; #endif + keyboard_post_init_kb(); /* Always keep this last */ } /** \brief Keyboard task: Do keyboard routine jobs diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index ea2f336e9d..bf8b71fb78 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -70,6 +70,11 @@ void keyboard_set_leds(uint8_t leds); /* it runs whenever code has to behave differently on a slave */ bool is_keyboard_master(void); +void keyboard_pre_init_kb(void); +void keyboard_pre_init_user(void); +void keyboard_post_init_kb(void); +void keyboard_post_init_user(void); + #ifdef __cplusplus } #endif diff --git a/tmk_core/protocol/bluefruit/main.c b/tmk_core/protocol/bluefruit/main.c index 0dbb637e2c..8a6386b4eb 100644 --- a/tmk_core/protocol/bluefruit/main.c +++ b/tmk_core/protocol/bluefruit/main.c @@ -42,13 +42,13 @@ along with this program. If not, see . int main(void) -{ +{ CPU_PRESCALE(0); // DDRD = _BV(PD5); // DDRB = _BV(PB0); - + // PORTD = _BV(PD5); // PORTB = _BV(PB0); @@ -59,22 +59,23 @@ int main(void) // while (!usb_configured()) /* wait */ + keyboard_setup(); dprintf("Initializing keyboard...\n"); keyboard_init(); - + // This implementation is pretty simplistic... if the USB connection // is not configured, choose the Bluefruit, otherwise use USB // Definitely would prefer to have this driven by an input pin and make // it switch dynamically - BCG // if (!usb_configured()) { - + // // Send power to Bluefruit... Adafruit says it takes 27 mA, I think - // // the pins should provide 40 mA, but just in case I switch the + // // the pins should provide 40 mA, but just in case I switch the // // Bluefruit using a transistor - BCG // DDRB = _BV(PB6); // PORTB |= _BV(PB6); - + dprintf("Setting host driver to bluefruit...\n"); host_set_driver(bluefruit_driver()); @@ -131,7 +132,7 @@ int main(void) // usb_remote_wakeup(); // } // } -// keyboard_task(); +// keyboard_task(); // } // } diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 5436d49090..8de55bfe3f 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -119,6 +119,8 @@ int main(void) { // TESTING // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); + keyboard_setup(); + /* Init USB */ init_usb_driver(&USB_DRIVER); diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c index f6a0c7e9a4..86c2188c87 100644 --- a/tmk_core/protocol/vusb/main.c +++ b/tmk_core/protocol/vusb/main.c @@ -56,6 +56,7 @@ int main(void) #ifndef NO_UART uart_init(UART_BAUD_RATE); #endif + keyboard_setup(); keyboard_init(); host_set_driver(vusb_driver());