*/ | */ | ||||
#define CH_CFG_NO_IDLE_THREAD FALSE | #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 | |||||
/** @} */ | /** @} */ | ||||
/*===========================================================================*/ | /*===========================================================================*/ |
#include "keymap.h" | #include "keymap.h" | ||||
static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | 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[] = { | static const uint16_t fn_actions[] = { |
*/ | */ | ||||
#define CH_CFG_NO_IDLE_THREAD FALSE | #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 | |||||
/** @} */ | /** @} */ | ||||
/*===========================================================================*/ | /*===========================================================================*/ |
## Credits | ## 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. | 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 | ## Features that are not implemented yet |
#include "keymap.h" | #include "keymap.h" | ||||
static const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | 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[] = { | static const uint16_t fn_actions[] = { | ||||
}; | }; |
#include "sleep_led.h" | #include "sleep_led.h" | ||||
void sleep_led_init(void) { | 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) { | void sleep_led_enable(void) { |
/* TODO */ | /* TODO */ | ||||
#include <stdbool.h> | |||||
#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 */ | |||||
} |
#include "host_driver.h" | #include "host_driver.h" | ||||
#include "keyboard.h" | #include "keyboard.h" | ||||
#include "action.h" | #include "action.h" | ||||
#include "action_util.h" | |||||
#include "mousekey.h" | |||||
#include "led.h" | #include "led.h" | ||||
#include "sendchar.h" | #include "sendchar.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
/* Main loop */ | /* Main loop */ | ||||
while(true) { | 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(); | keyboard_task(); | ||||
chThdSleepMilliseconds(5); | chThdSleepMilliseconds(5); |
#include "host.h" | #include "host.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "suspend.h" | |||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
#include "sleep_led.h" | #include "sleep_led.h" | ||||
#include "led.h" | #include "led.h" | ||||
NUM_INTERFACES, // bNumInterfaces | NUM_INTERFACES, // bNumInterfaces | ||||
1, // bConfigurationValue | 1, // bConfigurationValue | ||||
0, // iConfiguration | 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 */ | /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */ | ||||
USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber | USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber | ||||
case USB_EVENT_SUSPEND: | case USB_EVENT_SUSPEND: | ||||
//TODO: from ISR! print("[S]"); | //TODO: from ISR! print("[S]"); | ||||
//TODO: signal suspend? | |||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_enable(); | sleep_led_enable(); | ||||
#endif /* SLEEP_LED_ENABLE */ | #endif /* SLEEP_LED_ENABLE */ | ||||
case USB_EVENT_WAKEUP: | case USB_EVENT_WAKEUP: | ||||
//TODO: from ISR! print("[W]"); | //TODO: from ISR! print("[W]"); | ||||
//TODO: suspend_wakeup_init(); | |||||
suspend_wakeup_init(); | |||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_disable(); | sleep_led_disable(); | ||||
// NOTE: converters may not accept this | // NOTE: converters may not accept this |