@@ -47,5 +47,11 @@ ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||
OPT_DEFS += -DMOUSE_ENABLE | |||
endif | |||
ifdef SLEEP_LED_ENABLE | |||
SRC += $(COMMON_DIR)/sleep_led.c | |||
OPT_DEFS += -DSLEEP_LED_ENABLE | |||
endif | |||
# Search Path | |||
VPATH += $(TOP_DIR)/common |
@@ -0,0 +1,84 @@ | |||
#include <stdint.h> | |||
#include <avr/io.h> | |||
#include <avr/interrupt.h> | |||
#include <avr/pgmspace.h> | |||
#include "led.h" | |||
#include "sleep_led.h" | |||
/* Software PWM | |||
* ______ ______ __ | |||
* | ON |___OFF___| ON |___OFF___| .... | |||
* |<-------------->|<-------------->|<- .... | |||
* PWM period PWM period | |||
* | |||
* 256 interrupts/period[resolution] | |||
* 64 periods/second[frequency] | |||
* 256*64 interrupts/second | |||
* F_CPU/(256*64) clocks/interrupt | |||
*/ | |||
#define SLEEP_LED_TIMER_TOP F_CPU/(256*64) | |||
void sleep_led_init(void) | |||
{ | |||
/* Timer1 setup */ | |||
/* CTC mode */ | |||
TCCR1B |= _BV(WGM12); | |||
/* Clock selelct: clk/1 */ | |||
TCCR1B |= _BV(CS10); | |||
/* Set TOP value */ | |||
uint8_t sreg = SREG; | |||
cli(); | |||
OCR1AH = (SLEEP_LED_TIMER_TOP>>8)&0xff; | |||
OCR1AL = SLEEP_LED_TIMER_TOP&0xff; | |||
SREG = sreg; | |||
} | |||
void sleep_led_enable(void) | |||
{ | |||
/* Enable Compare Match Interrupt */ | |||
TIMSK1 |= _BV(OCIE1A); | |||
} | |||
void sleep_led_disable(void) | |||
{ | |||
/* Disable Compare Match Interrupt */ | |||
TIMSK1 &= ~_BV(OCIE1A); | |||
} | |||
/* Breathing Sleep LED brighness(PWM On period) table | |||
* (32[steps] * 8[duration]) / 64[PWM periods/s] = 4 second breath cycle | |||
*/ | |||
static const uint8_t breathing_table[32] PROGMEM = { | |||
0, 0, 0, 2, 9, 21, 37, 56, 78, 127, 151, 175, 197, 216, 232, 244, | |||
254, 244, 216, 197, 175, 151, 127, 78, 56, 37, 21, 9, 2, 0, 0, 0 | |||
}; | |||
ISR(TIMER1_COMPA_vect) | |||
{ | |||
/* Software PWM | |||
* timer:1111 1111 1111 1111 | |||
* \----/\-/ \-------/+--- count(0-255) | |||
* | +--------------- duration of step(8) | |||
* +-------------------- index of step table(0-31) | |||
*/ | |||
static union { | |||
uint16_t row; | |||
struct { | |||
uint8_t count:8; | |||
uint8_t duration:3; | |||
uint8_t index:5; | |||
} pwm; | |||
} timer = { .row = 0 }; | |||
timer.row++; | |||
// LED on | |||
if (timer.pwm.count == 0) { | |||
led_set(1<<USB_LED_CAPS_LOCK); | |||
} | |||
// LED off | |||
if (timer.pwm.count == pgm_read_byte(&breathing_table[timer.pwm.index])) { | |||
led_set(0); | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
#ifndef SLEEP_LED_H | |||
#define SLEEP_LED_H | |||
#define NO_SUSPEND_POWER_DOWN | |||
void sleep_led_init(void); | |||
void sleep_led_enable(void); | |||
void sleep_led_disable(void); | |||
#endif |
@@ -36,12 +36,20 @@ | |||
this software. | |||
*/ | |||
#include <avr/sleep.h> | |||
#include <avr/wdt.h> | |||
#include "report.h" | |||
#include "host.h" | |||
#include "host_driver.h" | |||
#include "keyboard.h" | |||
#include "action.h" | |||
#include "matrix.h" | |||
#include "led.h" | |||
#include "sendchar.h" | |||
#include "debug.h" | |||
#ifdef SLEEP_LED_ENABLE | |||
#include "sleep_led.h" | |||
#endif | |||
#include "descriptor.h" | |||
#include "lufa.h" | |||
@@ -140,10 +148,9 @@ static void Console_Task(void) | |||
* 2) EVENT_USB_Device_Reset | |||
* 3) EVENT_USB_Device_Wake | |||
*/ | |||
#include "led.h" | |||
#include "matrix.h" | |||
void EVENT_USB_Device_Connect(void) | |||
{ | |||
led_set(0x1f); // all on | |||
} | |||
void EVENT_USB_Device_Disconnect(void) | |||
@@ -156,17 +163,21 @@ void EVENT_USB_Device_Reset(void) | |||
void EVENT_USB_Device_Suspend() | |||
{ | |||
#ifdef SLEEP_LED_ENABLE | |||
sleep_led_enable(); | |||
#endif | |||
} | |||
#include "action.h" | |||
void EVENT_USB_Device_WakeUp() | |||
{ | |||
// initialize | |||
matrix_init(); | |||
clear_keyboard(); | |||
// turn off LED | |||
led_set(0); | |||
#ifdef SLEEP_LED_ENABLE | |||
sleep_led_disable(); | |||
#endif | |||
led_set(host_keyboard_leds()); | |||
} | |||
void EVENT_USB_Device_StartOfFrame(void) | |||
@@ -493,7 +504,6 @@ static void SetupHardware(void) | |||
} | |||
#include "matrix.h" | |||
static bool wakeup_condition(void) | |||
{ | |||
matrix_scan(); | |||
@@ -503,8 +513,6 @@ static bool wakeup_condition(void) | |||
return false; | |||
} | |||
#include <avr/sleep.h> | |||
#include <avr/wdt.h> | |||
#define wdt_intr_enable(value) \ | |||
__asm__ __volatile__ ( \ | |||
"in __tmp_reg__,__SREG__" "\n\t" \ | |||
@@ -527,11 +535,15 @@ int main(void) | |||
SetupHardware(); | |||
keyboard_init(); | |||
host_set_driver(&lufa_driver); | |||
#ifdef SLEEP_LED_ENABLE | |||
sleep_led_init(); | |||
#endif | |||
sei(); | |||
while (1) { | |||
// while suspend | |||
while (USB_DeviceState == DEVICE_STATE_Suspended) { | |||
#ifndef NO_SUSPEND_POWER_DOWN | |||
// Enable watchdog to wake from MCU sleep | |||
cli(); | |||
wdt_reset(); | |||
@@ -558,6 +570,7 @@ int main(void) | |||
// Disable watchdog after sleep | |||
wdt_disable(); | |||
#endif | |||
// Send request of USB Wakeup from Suspend to host | |||
if (USB_Device_RemoteWakeupEnabled) { | |||
@@ -575,9 +588,12 @@ int main(void) | |||
} | |||
} | |||
/* watchdog timeout during sleep */ | |||
#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; | |||
@@ -585,4 +601,6 @@ ISR(WDT_vect) | |||
if ((led_count & 0x07) == 0) { | |||
led_set((led_state ^= (1<<USB_LED_CAPS_LOCK))); | |||
} | |||
*/ | |||
} | |||
#endif |