From c1c8e079ca78937096238f11f5ed6ee87cc743ef Mon Sep 17 00:00:00 2001 From: flabbergast Date: Wed, 14 Oct 2015 10:13:49 +0100 Subject: [PATCH] Chibios: use WFI in idle. WIP suspend stuff. --- keyboard/stm32_onekey/chconf.h | 4 ++ keyboard/stm32_onekey/keymap_plain.c | 2 +- keyboard/teensy_lc_onekey/chconf.h | 4 ++ keyboard/teensy_lc_onekey/instructions.md | 2 + keyboard/teensy_lc_onekey/keymap_plain.c | 4 +- tmk_core/common/chibios/sleep_led.c | 4 ++ tmk_core/common/chibios/suspend.c | 65 +++++++++++++++++++++-- tmk_core/protocol/chibios/main.c | 21 +++++++- tmk_core/protocol/chibios/usb_main.c | 8 +-- 9 files changed, 102 insertions(+), 12 deletions(-) diff --git a/keyboard/stm32_onekey/chconf.h b/keyboard/stm32_onekey/chconf.h index da4160b6..be362a95 100644 --- a/keyboard/stm32_onekey/chconf.h +++ b/keyboard/stm32_onekey/chconf.h @@ -103,6 +103,10 @@ */ #define CH_CFG_NO_IDLE_THREAD FALSE +/* Use __WFI in the idle thread for waiting. Does lower the power + * consumption. */ +#define CORTEX_ENABLE_WFI_IDLE TRUE + /** @} */ /*===========================================================================*/ diff --git a/keyboard/stm32_onekey/keymap_plain.c b/keyboard/stm32_onekey/keymap_plain.c index ea173935..8de1c027 100644 --- a/keyboard/stm32_onekey/keymap_plain.c +++ b/keyboard/stm32_onekey/keymap_plain.c @@ -25,7 +25,7 @@ along with this program. If not, see . #include "keymap.h" static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - {{KC_A}}, + {{KC_CAPS}}, // test with KC_CAPS, KC_A, KC_BTLD }; static const uint16_t fn_actions[] = { diff --git a/keyboard/teensy_lc_onekey/chconf.h b/keyboard/teensy_lc_onekey/chconf.h index 50cb1be4..ee527d47 100644 --- a/keyboard/teensy_lc_onekey/chconf.h +++ b/keyboard/teensy_lc_onekey/chconf.h @@ -103,6 +103,10 @@ */ #define CH_CFG_NO_IDLE_THREAD FALSE +/* Use __WFI in the idle thread for waiting. Does lower the power + * consumption. */ +#define CORTEX_ENABLE_WFI_IDLE TRUE + /** @} */ /*===========================================================================*/ diff --git a/keyboard/teensy_lc_onekey/instructions.md b/keyboard/teensy_lc_onekey/instructions.md index b19b8984..9a7aeece 100644 --- a/keyboard/teensy_lc_onekey/instructions.md +++ b/keyboard/teensy_lc_onekey/instructions.md @@ -16,6 +16,8 @@ It's set up for Teensy LC. To use 3.x, you'll need to edit the `Makefile` (and c ## Credits +TMK itself is written by hasu, original sources [here](https://github.com/tmk/tmk_keyboard). + The USB support for Kinetis MCUs is due to RedoX. His ChibiOS fork is also [on github](https://github.com/RedoXyde/ChibiOS); but it doesn't include Teensy LC definitions. ## Features that are not implemented yet diff --git a/keyboard/teensy_lc_onekey/keymap_plain.c b/keyboard/teensy_lc_onekey/keymap_plain.c index a8357489..922fa537 100644 --- a/keyboard/teensy_lc_onekey/keymap_plain.c +++ b/keyboard/teensy_lc_onekey/keymap_plain.c @@ -25,8 +25,8 @@ along with this program. If not, see . #include "keymap.h" static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - {{KC_BTLD}}, -}; // to test: KC_CAPS, KT_BTLD + {{KC_A}}, +}; // to test: KC_CAPS, KT_BTLD, KC_A static const uint16_t fn_actions[] = { }; diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c index b08c9c2a..fad7ac04 100644 --- a/tmk_core/common/chibios/sleep_led.c +++ b/tmk_core/common/chibios/sleep_led.c @@ -4,6 +4,10 @@ #include "sleep_led.h" void sleep_led_init(void) { + // we could go the 'software way' -- just enable *some* timer + // and go with callbacks + // or we could go the 'hardware way' -- and use timer output to + // pins directly } void sleep_led_enable(void) { diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c index 49ecad43..6ca16034 100644 --- a/tmk_core/common/chibios/suspend.c +++ b/tmk_core/common/chibios/suspend.c @@ -1,8 +1,65 @@ /* TODO */ -#include +#include "ch.h" +#include "hal.h" +#include "matrix.h" +#include "action.h" +#include "action_util.h" +#include "mousekey.h" +#include "host.h" +#include "backlight.h" +#include "suspend.h" -void suspend_power_down(void) {} -bool suspend_wakeup_condition(void) { return true; } -void suspend_wakeup_init(void) {} +void suspend_idle(uint8_t time) { + // TODO: this is not used anywhere - what units is 'time' in? + chThdSleepMilliseconds(time); +} + +void suspend_power_down(void) { + // TODO: figure out what to power down and how + // shouldn't power down TPM/FTM if we want a breathing LED + // also shouldn't power down USB + + // on AVR, this enables the watchdog for 15ms (max), and goes to + // SLEEP_MODE_PWR_DOWN + + chThdSleepMilliseconds(17); +} + +__attribute__ ((weak)) void matrix_power_up(void) {} +__attribute__ ((weak)) void matrix_power_down(void) {} +bool suspend_wakeup_condition(void) +{ + matrix_power_up(); + matrix_scan(); + matrix_power_down(); + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + if (matrix_get_row(r)) return true; + } + return false; +} + +// run immediately after wakeup +void suspend_wakeup_init(void) +{ + // clear keyboard state + // need to do it manually, because we're running from ISR + // and clear_keyboard() calls print + // so only clear the variables in memory + // the reports will be sent from main.c afterwards + // or if the PC asks for GET_REPORT + clear_mods(); + clear_weak_mods(); + clear_keys(); +#ifdef MOUSEKEY_ENABLE + mousekey_clear(); +#endif /* MOUSEKEY_ENABLE */ +#ifdef EXTRAKEY_ENABLE + host_system_send(0); + host_consumer_send(0); +#endif /* EXTRAKEY_ENABLE */ +#ifdef BACKLIGHT_ENABLE + backlight_init(); +#endif /* BACKLIGHT_ENABLE */ +} diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index b2526d14..c4666ebd 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -26,6 +26,8 @@ #include "host_driver.h" #include "keyboard.h" #include "action.h" +#include "action_util.h" +#include "mousekey.h" #include "led.h" #include "sendchar.h" #include "debug.h" @@ -113,7 +115,24 @@ int main(void) { /* Main loop */ while(true) { - /* TODO: check for suspended event */ + + if(USB_DRIVER.state == USB_SUSPENDED) { + print("[s]"); + while(USB_DRIVER.state == USB_SUSPENDED) { + /* Do this in the suspended state */ + suspend_power_down(); // on AVR this deep sleeps for 15ms + // TODO: remote wakeup + // if(USB_Device_RemoteWakeupEnabled (USB_DRIVER.status & 2) && suspend_wakeup_condition()) { + // USB_Device_SendRemoteWakeup(); + // } + } + /* Woken up */ + // variables has been already cleared by the wakeup hook + send_keyboard_report(); +#ifdef MOUSEKEY_ENABLE + mousekey_send(); +#endif /* MOUSEKEY_ENABLE */ + } keyboard_task(); chThdSleepMilliseconds(5); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 2625c425..872d1c65 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -22,6 +22,7 @@ #include "host.h" #include "debug.h" +#include "suspend.h" #ifdef SLEEP_LED_ENABLE #include "sleep_led.h" #include "led.h" @@ -356,8 +357,8 @@ static const uint8_t hid_configuration_descriptor_data[] = { NUM_INTERFACES, // bNumInterfaces 1, // bConfigurationValue 0, // iConfiguration - 0xA0, // bmAttributes - 50), // bMaxPower (100mA) + 0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP) + 50), // bMaxPower (50mA) /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */ USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber @@ -793,7 +794,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { case USB_EVENT_SUSPEND: //TODO: from ISR! print("[S]"); - //TODO: signal suspend? #ifdef SLEEP_LED_ENABLE sleep_led_enable(); #endif /* SLEEP_LED_ENABLE */ @@ -801,7 +801,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { case USB_EVENT_WAKEUP: //TODO: from ISR! print("[W]"); - //TODO: suspend_wakeup_init(); + suspend_wakeup_init(); #ifdef SLEEP_LED_ENABLE sleep_led_disable(); // NOTE: converters may not accept this