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

Add kb and user level keyboard initialization functions #3113

Merged
merged 37 commits into from Feb 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e92b2b5
Add suspend functions
drashna Jun 1, 2018
cfe9c6c
Disable RGB code if it's disabled
drashna Jun 1, 2018
f2ec9cb
Add keyboard_init functions
drashna Jun 2, 2018
2adde43
Change where references so it will compile
drashna Jun 2, 2018
9bbce97
Wrong command chained in wake up kb function
drashna Jun 2, 2018
c733ca8
Fix non-feature file changes
drashna Jun 2, 2018
20491f0
Add documentation
drashna Jun 2, 2018
8efd254
Re-add matrix init docs
drashna Jun 2, 2018
205b419
add rgblight code to example
drashna Jun 2, 2018
7ded7da
Remove suspend code
drashna Jun 2, 2018
1b25ffb
Clean up docs
drashna Jun 2, 2018
1d78ec8
Fix docs
drashna Jun 11, 2018
8b519fe
Fix suspend code
drashna Jun 11, 2018
4ceb0b7
more doc fixes
drashna Jun 11, 2018
570067c
change function to startup_* rather than keyboard_init_
drashna Jun 12, 2018
65ffa3e
fix up docs to finish removing keyboard_init
drashna Jun 12, 2018
fb85430
fix spelling error
ylixir Jun 11, 2018
5c4a3e6
Use Pre and Post init functions
drashna Nov 6, 2018
1ad1cf2
Update Documenation
drashna Nov 6, 2018
8c8d53a
Remove changes to my keymap and userspace code
drashna Nov 6, 2018
dad3525
Cleanup
drashna Nov 6, 2018
6e5d2aa
Revert changes to extra files
drashna Nov 6, 2018
dea7413
Forgot a semicolon
drashna Nov 6, 2018
b563e5e
Make sure all protocols call keyboard_setup
drashna Nov 6, 2018
ae36d65
Cleanup functions
drashna Nov 6, 2018
22e49c6
Unset startup_user
drashna Nov 6, 2018
f91f579
Remove changes from division keyboard
drashna Nov 6, 2018
1470579
Readd startup_user function
drashna Nov 6, 2018
90407a3
Remove all to startup_user
drashna Nov 6, 2018
5018143
Update docs/custom_quantum_functions.md
mechmerlin Nov 6, 2018
5c74fdd
Update docs/custom_quantum_functions.md
mechmerlin Nov 6, 2018
98068cd
Add suggestion line
drashna Nov 6, 2018
fedcd10
Rebase fixes
drashna Dec 6, 2018
23d4068
Update documentation to be more useful/accurate
drashna Dec 6, 2018
af02782
Cleanup of documentation
drashna Dec 28, 2018
58f6b2e
Fix spacing inconsistency
drashna Dec 28, 2018
77565b0
Revert unexpected change to keymap
drashna Jan 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 60 additions & 8 deletions docs/custom_quantum_functions.md
Expand Up @@ -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);
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like the word "Post" here. That implies that initialization should be complete by this point. I don't have any immediate suggestions for better names, but to me the naming of this means that I have no idea what the purpose of this function is. It's post initialization, so nothing should be initialized here, but it's also not called in a loop or anything?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps user_code_init?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The biggest issue with the name is that there are 3 inits. Which ... is far from ideal.

Though, the post init is the last function run as part of the keyboard setup, and should always be the last thing called.

The problem with user_code_init is... the functionality levels. user_code_init_kb, and user_code_init_user?

init_cleanup? init_finished?

I'm not great with naming, and this was close in name to existing stuff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, one question: does there need to be a _kb and _user version of this function? What would the keyboard need to do that it doesn't already have a callback for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, for one, it would be a better place to start the setup for SSD1306 screens. Or additional keyboard specific hardware, when matrix_init wouldn't necessarily be appropriate.


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.
drashna marked this conversation as resolved.
Show resolved Hide resolved

```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.
Expand Down Expand Up @@ -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)`
Expand Down Expand Up @@ -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!

Expand Down
28 changes: 14 additions & 14 deletions tmk_core/common/avr/suspend.c
Expand Up @@ -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();

// Disable watchdog after sleep
wdt_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();
}
#endif

Expand Down
36 changes: 36 additions & 0 deletions tmk_core/common/keyboard.c
Expand Up @@ -139,13 +139,48 @@ __attribute__ ((weak))
void matrix_setup(void) {
}

/** \brief keyboard_pre_init_user
*
* FIXME: needs doc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you'll fix these before merging?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? Nothing else is actually documented. And I'm not sure of the formatting for this still.

*/
__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
*/
void keyboard_setup(void) {
disable_jtag();
matrix_setup();
keyboard_pre_init_kb();
}

/** \brief is_keyboard_master
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tmk_core/common/keyboard.h
Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions tmk_core/protocol/bluefruit/main.c
Expand Up @@ -42,13 +42,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.


int main(void)
{
{

CPU_PRESCALE(0);

// DDRD = _BV(PD5);
// DDRB = _BV(PB0);

// PORTD = _BV(PD5);
// PORTB = _BV(PB0);

Expand All @@ -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());

Expand Down Expand Up @@ -131,7 +132,7 @@ int main(void)
// usb_remote_wakeup();
// }
// }
// keyboard_task();
// keyboard_task();
// }
// }

Expand Down
2 changes: 2 additions & 0 deletions tmk_core/protocol/chibios/main.c
Expand Up @@ -119,6 +119,8 @@ int main(void) {
// TESTING
// chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

keyboard_setup();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matrix_setup and disable_jtag already getting called. Doesn't this mean you've added a second call for these functions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment for the other main.c

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean here.

But keyboard_pre_init_* relies on `keyboard_setup. Which doesn't exist. And it should be the first thing called (or one of the first things).


/* Init USB */
init_usb_driver(&USB_DRIVER);

Expand Down
1 change: 1 addition & 0 deletions tmk_core/protocol/vusb/main.c
Expand Up @@ -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());
Expand Down