diff options
| author | tmk <nobody@nowhere> | 2013-03-16 17:30:18 +0900 |
|---|---|---|
| committer | tmk <nobody@nowhere> | 2013-03-16 17:30:18 +0900 |
| commit | e4589f808eba875d7bf74fb470d5d1ce9ed41123 (patch) | |
| tree | f68e720804c1c82109c1de19dc3cc7d9eb2cabf0 | |
| parent | b78c654693014c60ced089648c29f46939d23437 (diff) | |
| parent | f0c5f1b910ecf9536e5b95cc4ca9a43b0f4b2c36 (diff) | |
| download | qmk_firmware-e4589f808eba875d7bf74fb470d5d1ce9ed41123.tar.gz qmk_firmware-e4589f808eba875d7bf74fb470d5d1ce9ed41123.zip | |
Merge branch 'remote_wakeup'
| -rw-r--r-- | common.mk | 6 | ||||
| -rw-r--r-- | common/sleep_led.c | 84 | ||||
| -rw-r--r-- | common/sleep_led.h | 10 | ||||
| -rw-r--r-- | keyboard/gh60/Makefile.lufa | 1 | ||||
| -rw-r--r-- | protocol/lufa/lufa.c | 128 |
5 files changed, 225 insertions, 4 deletions
| @@ -47,5 +47,11 @@ ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) | |||
| 47 | OPT_DEFS += -DMOUSE_ENABLE | 47 | OPT_DEFS += -DMOUSE_ENABLE |
| 48 | endif | 48 | endif |
| 49 | 49 | ||
| 50 | ifdef SLEEP_LED_ENABLE | ||
| 51 | SRC += $(COMMON_DIR)/sleep_led.c | ||
| 52 | OPT_DEFS += -DSLEEP_LED_ENABLE | ||
| 53 | endif | ||
| 54 | |||
| 55 | |||
| 50 | # Search Path | 56 | # Search Path |
| 51 | VPATH += $(TOP_DIR)/common | 57 | VPATH += $(TOP_DIR)/common |
diff --git a/common/sleep_led.c b/common/sleep_led.c new file mode 100644 index 000000000..edf68c352 --- /dev/null +++ b/common/sleep_led.c | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | #include <stdint.h> | ||
| 2 | #include <avr/io.h> | ||
| 3 | #include <avr/interrupt.h> | ||
| 4 | #include <avr/pgmspace.h> | ||
| 5 | #include "led.h" | ||
| 6 | #include "sleep_led.h" | ||
| 7 | |||
| 8 | /* Software PWM | ||
| 9 | * ______ ______ __ | ||
| 10 | * | ON |___OFF___| ON |___OFF___| .... | ||
| 11 | * |<-------------->|<-------------->|<- .... | ||
| 12 | * PWM period PWM period | ||
| 13 | * | ||
| 14 | * 256 interrupts/period[resolution] | ||
| 15 | * 64 periods/second[frequency] | ||
| 16 | * 256*64 interrupts/second | ||
| 17 | * F_CPU/(256*64) clocks/interrupt | ||
| 18 | */ | ||
| 19 | #define SLEEP_LED_TIMER_TOP F_CPU/(256*64) | ||
| 20 | |||
| 21 | void sleep_led_init(void) | ||
| 22 | { | ||
| 23 | /* Timer1 setup */ | ||
| 24 | /* CTC mode */ | ||
| 25 | TCCR1B |= _BV(WGM12); | ||
| 26 | /* Clock selelct: clk/1 */ | ||
| 27 | TCCR1B |= _BV(CS10); | ||
| 28 | /* Set TOP value */ | ||
| 29 | uint8_t sreg = SREG; | ||
| 30 | cli(); | ||
| 31 | OCR1AH = (SLEEP_LED_TIMER_TOP>>8)&0xff; | ||
| 32 | OCR1AL = SLEEP_LED_TIMER_TOP&0xff; | ||
| 33 | SREG = sreg; | ||
| 34 | } | ||
| 35 | |||
| 36 | void sleep_led_enable(void) | ||
| 37 | { | ||
| 38 | /* Enable Compare Match Interrupt */ | ||
| 39 | TIMSK1 |= _BV(OCIE1A); | ||
| 40 | } | ||
| 41 | |||
| 42 | void sleep_led_disable(void) | ||
| 43 | { | ||
| 44 | /* Disable Compare Match Interrupt */ | ||
| 45 | TIMSK1 &= ~_BV(OCIE1A); | ||
| 46 | } | ||
| 47 | |||
| 48 | |||
| 49 | /* Breathing Sleep LED brighness(PWM On period) table | ||
| 50 | * (32[steps] * 8[duration]) / 64[PWM periods/s] = 4 second breath cycle | ||
| 51 | */ | ||
| 52 | static const uint8_t breathing_table[32] PROGMEM = { | ||
| 53 | 0, 0, 0, 2, 9, 21, 37, 56, 78, 127, 151, 175, 197, 216, 232, 244, | ||
| 54 | 254, 244, 216, 197, 175, 151, 127, 78, 56, 37, 21, 9, 2, 0, 0, 0 | ||
| 55 | }; | ||
| 56 | |||
| 57 | ISR(TIMER1_COMPA_vect) | ||
| 58 | { | ||
| 59 | /* Software PWM | ||
| 60 | * timer:1111 1111 1111 1111 | ||
| 61 | * \----/\-/ \-------/+--- count(0-255) | ||
| 62 | * | +--------------- duration of step(8) | ||
| 63 | * +-------------------- index of step table(0-31) | ||
| 64 | */ | ||
| 65 | static union { | ||
| 66 | uint16_t row; | ||
| 67 | struct { | ||
| 68 | uint8_t count:8; | ||
| 69 | uint8_t duration:3; | ||
| 70 | uint8_t index:5; | ||
| 71 | } pwm; | ||
| 72 | } timer = { .row = 0 }; | ||
| 73 | |||
| 74 | timer.row++; | ||
| 75 | |||
| 76 | // LED on | ||
| 77 | if (timer.pwm.count == 0) { | ||
| 78 | led_set(1<<USB_LED_CAPS_LOCK); | ||
| 79 | } | ||
| 80 | // LED off | ||
| 81 | if (timer.pwm.count == pgm_read_byte(&breathing_table[timer.pwm.index])) { | ||
| 82 | led_set(0); | ||
| 83 | } | ||
| 84 | } | ||
diff --git a/common/sleep_led.h b/common/sleep_led.h new file mode 100644 index 000000000..aebdbeaa5 --- /dev/null +++ b/common/sleep_led.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #ifndef SLEEP_LED_H | ||
| 2 | #define SLEEP_LED_H | ||
| 3 | |||
| 4 | #define NO_SUSPEND_POWER_DOWN | ||
| 5 | |||
| 6 | void sleep_led_init(void); | ||
| 7 | void sleep_led_enable(void); | ||
| 8 | void sleep_led_disable(void); | ||
| 9 | |||
| 10 | #endif | ||
diff --git a/keyboard/gh60/Makefile.lufa b/keyboard/gh60/Makefile.lufa index a5ff609a7..8042ff3f4 100644 --- a/keyboard/gh60/Makefile.lufa +++ b/keyboard/gh60/Makefile.lufa | |||
| @@ -103,6 +103,7 @@ BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000) | |||
| 103 | MOUSEKEY_ENABLE = yes # Mouse keys(+4700) | 103 | MOUSEKEY_ENABLE = yes # Mouse keys(+4700) |
| 104 | EXTRAKEY_ENABLE = yes # Audio control and System control(+450) | 104 | EXTRAKEY_ENABLE = yes # Audio control and System control(+450) |
| 105 | CONSOLE_ENABLE = yes # Console for debug(+400) | 105 | CONSOLE_ENABLE = yes # Console for debug(+400) |
| 106 | SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend | ||
| 106 | #NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA | 107 | #NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA |
| 107 | #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support | 108 | #PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support |
| 108 | 109 | ||
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index 98c3a68ff..127dece54 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c | |||
| @@ -36,12 +36,20 @@ | |||
| 36 | this software. | 36 | this software. |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | #include <avr/sleep.h> | ||
| 40 | #include <avr/wdt.h> | ||
| 39 | #include "report.h" | 41 | #include "report.h" |
| 40 | #include "host.h" | 42 | #include "host.h" |
| 41 | #include "host_driver.h" | 43 | #include "host_driver.h" |
| 42 | #include "keyboard.h" | 44 | #include "keyboard.h" |
| 45 | #include "action.h" | ||
| 46 | #include "matrix.h" | ||
| 47 | #include "led.h" | ||
| 43 | #include "sendchar.h" | 48 | #include "sendchar.h" |
| 44 | #include "debug.h" | 49 | #include "debug.h" |
| 50 | #ifdef SLEEP_LED_ENABLE | ||
| 51 | #include "sleep_led.h" | ||
| 52 | #endif | ||
| 45 | 53 | ||
| 46 | #include "descriptor.h" | 54 | #include "descriptor.h" |
| 47 | #include "lufa.h" | 55 | #include "lufa.h" |
| @@ -133,16 +141,45 @@ static void Console_Task(void) | |||
| 133 | /******************************************************************************* | 141 | /******************************************************************************* |
| 134 | * USB Events | 142 | * USB Events |
| 135 | ******************************************************************************/ | 143 | ******************************************************************************/ |
| 136 | /** Event handler for the USB_Connect event. */ | 144 | /* |
| 145 | * Event Order of Plug in: | ||
| 146 | * 0) EVENT_USB_Device_Connect | ||
| 147 | * 1) EVENT_USB_Device_Suspend | ||
| 148 | * 2) EVENT_USB_Device_Reset | ||
| 149 | * 3) EVENT_USB_Device_Wake | ||
| 150 | */ | ||
| 137 | void EVENT_USB_Device_Connect(void) | 151 | void EVENT_USB_Device_Connect(void) |
| 138 | { | 152 | { |
| 153 | led_set(0x1f); // all on | ||
| 139 | } | 154 | } |
| 140 | 155 | ||
| 141 | /** Event handler for the USB_Disconnect event. */ | ||
| 142 | void EVENT_USB_Device_Disconnect(void) | 156 | void EVENT_USB_Device_Disconnect(void) |
| 143 | { | 157 | { |
| 144 | } | 158 | } |
| 145 | 159 | ||
| 160 | void EVENT_USB_Device_Reset(void) | ||
| 161 | { | ||
| 162 | } | ||
| 163 | |||
| 164 | void EVENT_USB_Device_Suspend() | ||
| 165 | { | ||
| 166 | #ifdef SLEEP_LED_ENABLE | ||
| 167 | sleep_led_enable(); | ||
| 168 | #endif | ||
| 169 | } | ||
| 170 | |||
| 171 | void EVENT_USB_Device_WakeUp() | ||
| 172 | { | ||
| 173 | // initialize | ||
| 174 | matrix_init(); | ||
| 175 | clear_keyboard(); | ||
| 176 | |||
| 177 | #ifdef SLEEP_LED_ENABLE | ||
| 178 | sleep_led_disable(); | ||
| 179 | #endif | ||
| 180 | led_set(host_keyboard_leds()); | ||
| 181 | } | ||
| 182 | |||
| 146 | void EVENT_USB_Device_StartOfFrame(void) | 183 | void EVENT_USB_Device_StartOfFrame(void) |
| 147 | { | 184 | { |
| 148 | Console_Task(); | 185 | Console_Task(); |
| @@ -466,17 +503,83 @@ static void SetupHardware(void) | |||
| 466 | USB_Device_EnableSOFEvents(); | 503 | USB_Device_EnableSOFEvents(); |
| 467 | } | 504 | } |
| 468 | 505 | ||
| 506 | |||
| 507 | static bool wakeup_condition(void) | ||
| 508 | { | ||
| 509 | matrix_scan(); | ||
| 510 | for (uint8_t r = 0; r < MATRIX_ROWS; r++) { | ||
| 511 | if (matrix_get_row(r)) return true; | ||
| 512 | } | ||
| 513 | return false; | ||
| 514 | } | ||
| 515 | |||
| 516 | #define wdt_intr_enable(value) \ | ||
| 517 | __asm__ __volatile__ ( \ | ||
| 518 | "in __tmp_reg__,__SREG__" "\n\t" \ | ||
| 519 | "cli" "\n\t" \ | ||
| 520 | "wdr" "\n\t" \ | ||
| 521 | "sts %0,%1" "\n\t" \ | ||
| 522 | "out __SREG__,__tmp_reg__" "\n\t" \ | ||
| 523 | "sts %0,%2" "\n\t" \ | ||
| 524 | : /* no outputs */ \ | ||
| 525 | : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \ | ||
| 526 | "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \ | ||
| 527 | "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \ | ||
| 528 | _BV(WDIE) | (value & 0x07)) ) \ | ||
| 529 | : "r0" \ | ||
| 530 | ) | ||
| 531 | |||
| 469 | int main(void) __attribute__ ((weak)); | 532 | int main(void) __attribute__ ((weak)); |
| 470 | int main(void) | 533 | int main(void) |
| 471 | { | 534 | { |
| 472 | SetupHardware(); | 535 | SetupHardware(); |
| 473 | keyboard_init(); | 536 | keyboard_init(); |
| 474 | host_set_driver(&lufa_driver); | 537 | host_set_driver(&lufa_driver); |
| 538 | #ifdef SLEEP_LED_ENABLE | ||
| 539 | sleep_led_init(); | ||
| 540 | #endif | ||
| 475 | sei(); | 541 | sei(); |
| 476 | 542 | ||
| 477 | // TODO: can't print here | ||
| 478 | debug("LUFA init\n"); | ||
| 479 | while (1) { | 543 | while (1) { |
| 544 | // while suspend | ||
| 545 | while (USB_DeviceState == DEVICE_STATE_Suspended) { | ||
| 546 | #ifndef NO_SUSPEND_POWER_DOWN | ||
| 547 | // Enable watchdog to wake from MCU sleep | ||
| 548 | cli(); | ||
| 549 | wdt_reset(); | ||
| 550 | |||
| 551 | // Watchdog Interrupt and System Reset Mode | ||
| 552 | //wdt_enable(WDTO_1S); | ||
| 553 | //WDTCSR |= _BV(WDIE); | ||
| 554 | |||
| 555 | // Watchdog Interrupt Mode | ||
| 556 | wdt_intr_enable(WDTO_120MS); | ||
| 557 | |||
| 558 | // TODO: more power saving | ||
| 559 | // See PicoPower application note | ||
| 560 | // - I/O port input with pullup | ||
| 561 | // - prescale clock | ||
| 562 | // - BOD disable | ||
| 563 | // - Power Reduction Register PRR | ||
| 564 | // sleep in power down mode | ||
| 565 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); | ||
| 566 | sleep_enable(); | ||
| 567 | sei(); | ||
| 568 | sleep_cpu(); | ||
| 569 | sleep_disable(); | ||
| 570 | |||
| 571 | // Disable watchdog after sleep | ||
| 572 | wdt_disable(); | ||
| 573 | #endif | ||
| 574 | |||
| 575 | // Send request of USB Wakeup from Suspend to host | ||
| 576 | if (USB_Device_RemoteWakeupEnabled) { | ||
| 577 | if (wakeup_condition()) { | ||
| 578 | USB_Device_SendRemoteWakeup(); | ||
| 579 | } | ||
| 580 | } | ||
| 581 | } | ||
| 582 | |||
| 480 | keyboard_task(); | 583 | keyboard_task(); |
| 481 | 584 | ||
| 482 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | 585 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) |
| @@ -484,3 +587,20 @@ int main(void) | |||
| 484 | #endif | 587 | #endif |
| 485 | } | 588 | } |
| 486 | } | 589 | } |
| 590 | |||
| 591 | #ifndef NO_SUSPEND_POWER_DOWN | ||
| 592 | /* watchdog timeout */ | ||
| 593 | ISR(WDT_vect) | ||
| 594 | { | ||
| 595 | /* wakeup from MCU sleep mode */ | ||
| 596 | /* | ||
| 597 | // blink LED | ||
| 598 | static uint8_t led_state = 0; | ||
| 599 | static uint8_t led_count = 0; | ||
| 600 | led_count++; | ||
| 601 | if ((led_count & 0x07) == 0) { | ||
| 602 | led_set((led_state ^= (1<<USB_LED_CAPS_LOCK))); | ||
| 603 | } | ||
| 604 | */ | ||
| 605 | } | ||
| 606 | #endif | ||
