$(COMMON_DIR)/print.c \ | $(COMMON_DIR)/print.c \ | ||||
$(COMMON_DIR)/debug.c \ | $(COMMON_DIR)/debug.c \ | ||||
$(COMMON_DIR)/bootloader.c \ | $(COMMON_DIR)/bootloader.c \ | ||||
$(COMMON_DIR)/suspend.c \ | |||||
$(COMMON_DIR)/util.c | $(COMMON_DIR)/util.c | ||||
ifdef SLEEP_LED_ENABLE | ifdef SLEEP_LED_ENABLE | ||||
SRC += $(COMMON_DIR)/sleep_led.c | SRC += $(COMMON_DIR)/sleep_led.c | ||||
OPT_DEFS += -DSLEEP_LED_ENABLE | OPT_DEFS += -DSLEEP_LED_ENABLE | ||||
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN | |||||
endif | endif | ||||
#include "bootloader.h" | #include "bootloader.h" | ||||
#include "layer_switch.h" | #include "layer_switch.h" | ||||
#include "eeconfig.h" | #include "eeconfig.h" | ||||
#include "sleep_led.h" | |||||
#include "led.h" | |||||
#include "command.h" | #include "command.h" | ||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE | ||||
{ | { | ||||
static host_driver_t *host_driver = 0; | static host_driver_t *host_driver = 0; | ||||
switch (code) { | switch (code) { | ||||
case KC_Z: | |||||
// test breathing sleep LED | |||||
print("Sleep LED test\n"); | |||||
sleep_led_toggle(); | |||||
led_set(host_keyboard_leds()); | |||||
break; | |||||
#ifdef BOOTMAGIC_ENABLE | #ifdef BOOTMAGIC_ENABLE | ||||
case KC_E: | case KC_E: | ||||
print("eeprom config\n"); | print("eeprom config\n"); |
#ifndef SLEEP_LED_H | #ifndef SLEEP_LED_H | ||||
#define SLEEP_LED_H | #define SLEEP_LED_H | ||||
#define NO_SUSPEND_POWER_DOWN | |||||
#ifdef SLEEP_LED_ENABLE | |||||
void sleep_led_init(void); | void sleep_led_init(void); | ||||
void sleep_led_enable(void); | void sleep_led_enable(void); | ||||
void sleep_led_disable(void); | void sleep_led_disable(void); | ||||
void sleep_led_toggle(void); | |||||
#else | |||||
#define sleep_led_init() | |||||
#define sleep_led_enable() | |||||
#define sleep_led_disable() | |||||
#define sleep_led_toggle() | |||||
#endif | |||||
#endif | #endif |
#include "suspend.h" | |||||
#include "matrix.h" | |||||
#include "action.h" | |||||
void suspend_power_down(void) | |||||
{ | |||||
#ifndef NO_SUSPEND_POWER_DOWN | |||||
// Enable watchdog to wake from MCU sleep | |||||
cli(); | |||||
wdt_reset(); | |||||
// Watchdog Interrupt and System Reset Mode | |||||
//wdt_enable(WDTO_1S); | |||||
//WDTCSR |= _BV(WDIE); | |||||
// Watchdog Interrupt Mode | |||||
wdt_intr_enable(WDTO_120MS); | |||||
// TODO: more power saving | |||||
// See PicoPower application note | |||||
// - I/O port input with pullup | |||||
// - prescale clock | |||||
// - BOD disable | |||||
// - Power Reduction Register PRR | |||||
// sleep in power down mode | |||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |||||
sleep_enable(); | |||||
sei(); | |||||
sleep_cpu(); | |||||
sleep_disable(); | |||||
// Disable watchdog after sleep | |||||
wdt_disable(); | |||||
#endif | |||||
} | |||||
bool suspend_wakeup_condition(void) | |||||
{ | |||||
matrix_scan(); | |||||
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 matrix and keyboard state | |||||
matrix_init(); | |||||
clear_keyboard(); | |||||
} | |||||
#ifndef NO_SUSPEND_POWER_DOWN | |||||
/* watchdog timeout */ | |||||
ISR(WDT_vect) | |||||
{ | |||||
/* wakeup from MCU sleep mode */ | |||||
/* | |||||
// blink LED | |||||
static uint8_t led_state = 0; | |||||
static uint8_t led_count = 0; | |||||
led_count++; | |||||
if ((led_count & 0x07) == 0) { | |||||
led_set((led_state ^= (1<<USB_LED_CAPS_LOCK))); | |||||
} | |||||
*/ | |||||
} | |||||
#endif |
#ifndef SUSPEND_H | |||||
#define SUSPEND_H | |||||
#include <stdint.h> | |||||
#include <stdbool.h> | |||||
#include <avr/sleep.h> | |||||
#include <avr/wdt.h> | |||||
#include <avr/interrupt.h> | |||||
#define wdt_intr_enable(value) \ | |||||
__asm__ __volatile__ ( \ | |||||
"in __tmp_reg__,__SREG__" "\n\t" \ | |||||
"cli" "\n\t" \ | |||||
"wdr" "\n\t" \ | |||||
"sts %0,%1" "\n\t" \ | |||||
"out __SREG__,__tmp_reg__" "\n\t" \ | |||||
"sts %0,%2" "\n\t" \ | |||||
: /* no outputs */ \ | |||||
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ | |||||
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ | |||||
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \ | |||||
_BV(WDIE) | (value & 0x07)) ) \ | |||||
: "r0" \ | |||||
) | |||||
void suspend_power_down(void); | |||||
bool suspend_wakeup_condition(void); | |||||
void suspend_wakeup_init(void); | |||||
#endif |
TARGET_DIR = . | TARGET_DIR = . | ||||
# project specific files | # project specific files | ||||
SRC += keymap.c \ | |||||
SRC = keymap.c \ | |||||
matrix.c \ | matrix.c \ | ||||
led.c | led.c | ||||
#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | #OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT | ||||
# Boot Section Size in bytes | |||||
# Teensy halfKay 512 | |||||
# Atmel DFU loader 4096 | |||||
# LUFA bootloader 4096 | |||||
OPT_DEFS += -DBOOT_SIZE=4096 | |||||
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # |
# examples use this variable to calculate timings. Do not add a "UL" here. | # examples use this variable to calculate timings. Do not add a "UL" here. | ||||
F_CPU = 16000000 | F_CPU = 16000000 | ||||
# Boot Section Size in bytes | # Boot Section Size in bytes | ||||
# Teensy halfKay 512 | # Teensy halfKay 512 | ||||
# Atmel DFU loader 4096 | # Atmel DFU loader 4096 | ||||
# LUFA bootloader 4096 | # LUFA bootloader 4096 | ||||
OPT_DEFS += -DBOOT_SIZE=4096 | OPT_DEFS += -DBOOT_SIZE=4096 | ||||
# Build Options | # Build Options | ||||
# comment out to disable the options. | # comment out to disable the options. | ||||
# | # | ||||
EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | EXTRAKEY_ENABLE = yes # Audio control and System control(+600) | ||||
CONSOLE_ENABLE = yes # Console for debug | CONSOLE_ENABLE = yes # Console for debug | ||||
COMMAND_ENABLE = yes # Commands for debug and configuration | COMMAND_ENABLE = yes # Commands for debug and configuration | ||||
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | |||||
NKRO_ENABLE = yes # USB Nkey Rollover(+500) | NKRO_ENABLE = yes # USB Nkey Rollover(+500) | ||||
#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | ||||
this software. | this software. | ||||
*/ | */ | ||||
#include <avr/sleep.h> | |||||
#include <avr/wdt.h> | |||||
#include "report.h" | #include "report.h" | ||||
#include "host.h" | #include "host.h" | ||||
#include "host_driver.h" | #include "host_driver.h" | ||||
#include "keyboard.h" | #include "keyboard.h" | ||||
#include "action.h" | #include "action.h" | ||||
#include "matrix.h" | |||||
#include "led.h" | #include "led.h" | ||||
#include "sendchar.h" | #include "sendchar.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
#include "sleep_led.h" | #include "sleep_led.h" | ||||
#endif | #endif | ||||
#include "suspend.h" | |||||
#include "descriptor.h" | #include "descriptor.h" | ||||
#include "lufa.h" | #include "lufa.h" | ||||
void EVENT_USB_Device_WakeUp() | void EVENT_USB_Device_WakeUp() | ||||
{ | { | ||||
// initialize | |||||
matrix_init(); | |||||
clear_keyboard(); | |||||
suspend_wakeup_init(); | |||||
#ifdef SLEEP_LED_ENABLE | #ifdef SLEEP_LED_ENABLE | ||||
sleep_led_disable(); | sleep_led_disable(); | ||||
USB_Device_EnableSOFEvents(); | USB_Device_EnableSOFEvents(); | ||||
} | } | ||||
static bool wakeup_condition(void) | |||||
{ | |||||
matrix_scan(); | |||||
for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | |||||
if (matrix_get_row(r)) return true; | |||||
} | |||||
return false; | |||||
} | |||||
#define wdt_intr_enable(value) \ | |||||
__asm__ __volatile__ ( \ | |||||
"in __tmp_reg__,__SREG__" "\n\t" \ | |||||
"cli" "\n\t" \ | |||||
"wdr" "\n\t" \ | |||||
"sts %0,%1" "\n\t" \ | |||||
"out __SREG__,__tmp_reg__" "\n\t" \ | |||||
"sts %0,%2" "\n\t" \ | |||||
: /* no outputs */ \ | |||||
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ | |||||
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ | |||||
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \ | |||||
_BV(WDIE) | (value & 0x07)) ) \ | |||||
: "r0" \ | |||||
) | |||||
int main(void) __attribute__ ((weak)); | int main(void) __attribute__ ((weak)); | ||||
int main(void) | int main(void) | ||||
{ | { | ||||
sei(); | sei(); | ||||
while (1) { | while (1) { | ||||
// while suspend | |||||
while (USB_DeviceState == DEVICE_STATE_Suspended) { | while (USB_DeviceState == DEVICE_STATE_Suspended) { | ||||
#ifndef NO_SUSPEND_POWER_DOWN | |||||
// Enable watchdog to wake from MCU sleep | |||||
cli(); | |||||
wdt_reset(); | |||||
// Watchdog Interrupt and System Reset Mode | |||||
//wdt_enable(WDTO_1S); | |||||
//WDTCSR |= _BV(WDIE); | |||||
// Watchdog Interrupt Mode | |||||
wdt_intr_enable(WDTO_120MS); | |||||
// TODO: more power saving | |||||
// See PicoPower application note | |||||
// - I/O port input with pullup | |||||
// - prescale clock | |||||
// - BOD disable | |||||
// - Power Reduction Register PRR | |||||
// sleep in power down mode | |||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); | |||||
sleep_enable(); | |||||
sei(); | |||||
sleep_cpu(); | |||||
sleep_disable(); | |||||
// Disable watchdog after sleep | |||||
wdt_disable(); | |||||
#endif | |||||
// Send request of USB Wakeup from Suspend to host | |||||
if (USB_Device_RemoteWakeupEnabled) { | |||||
if (wakeup_condition()) { | |||||
suspend_power_down(); | |||||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) { | |||||
USB_Device_SendRemoteWakeup(); | USB_Device_SendRemoteWakeup(); | ||||
} | |||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
#ifndef NO_SUSPEND_POWER_DOWN | |||||
/* watchdog timeout */ | |||||
ISR(WDT_vect) | |||||
{ | |||||
/* wakeup from MCU sleep mode */ | |||||
/* | |||||
// blink LED | |||||
static uint8_t led_state = 0; | |||||
static uint8_t led_count = 0; | |||||
led_count++; | |||||
if ((led_count & 0x07) == 0) { | |||||
led_set((led_state ^= (1<<USB_LED_CAPS_LOCK))); | |||||
} | |||||
*/ | |||||
} | |||||
#endif |
#include "print.h" | #include "print.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "bootloader.h" | |||||
#ifdef PS2_MOUSE_ENABLE | |||||
# include "ps2_mouse.h" | |||||
#endif | |||||
#include "suspend.h" | |||||
#include "host.h" | #include "host.h" | ||||
#include "pjrc.h" | #include "pjrc.h" | ||||
keyboard_init(); | keyboard_init(); | ||||
host_set_driver(pjrc_driver()); | host_set_driver(pjrc_driver()); | ||||
#ifdef SLEEP_LED_ENABLE | |||||
sleep_led_init(); | |||||
#endif | |||||
while (1) { | while (1) { | ||||
keyboard_task(); | |||||
while (suspend) { | |||||
suspend_power_down(); | |||||
if (remote_wakeup && suspend_wakeup_condition()) { | |||||
usb_remote_wakeup(); | |||||
} | |||||
} | |||||
keyboard_task(); | |||||
} | } | ||||
} | } |
#include "usb_extra.h" | #include "usb_extra.h" | ||||
#include "print.h" | #include "print.h" | ||||
#include "util.h" | #include "util.h" | ||||
#include "sleep_led.h" | |||||
#include "suspend.h" | |||||
/************************************************************************** | /************************************************************************** | ||||
USB_CONFIG(); // start USB clock | USB_CONFIG(); // start USB clock | ||||
UDCON = 0; // enable attach resistor | UDCON = 0; // enable attach resistor | ||||
usb_configuration = 0; | usb_configuration = 0; | ||||
UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE); | |||||
suspend = false; | |||||
UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE)|(1<<WAKEUPE); | |||||
sei(); | sei(); | ||||
} | } | ||||
intbits = UDINT; | intbits = UDINT; | ||||
UDINT = 0; | UDINT = 0; | ||||
if (intbits & (1<<SUSPI)) { | |||||
if ((intbits & (1<<SUSPI)) && (UDIEN & (1<<SUSPE)) && usb_configuration) { | |||||
#ifdef SLEEP_LED_ENABLE | |||||
sleep_led_enable(); | |||||
#endif | |||||
UDIEN &= ~(1<<SUSPE); | |||||
UDIEN |= (1<<WAKEUPE); | |||||
suspend = true; | suspend = true; | ||||
} else { | |||||
} | |||||
if ((intbits & (1<<WAKEUPI)) && (UDIEN & (1<<WAKEUPE)) && usb_configuration) { | |||||
suspend_wakeup_init(); | |||||
#ifdef SLEEP_LED_ENABLE | |||||
sleep_led_disable(); | |||||
#endif | |||||
led_set(host_keyboard_leds()); | |||||
UDIEN |= (1<<SUSPE); | |||||
UDIEN &= ~(1<<WAKEUPE); | |||||
suspend = false; | suspend = false; | ||||
} | } | ||||
if (intbits & (1<<EORSTI)) { | if (intbits & (1<<EORSTI)) { |