aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-03-27 15:23:57 +0900
committertmk <nobody@nowhere>2013-03-27 15:23:57 +0900
commit969cc4f812e3f86213f97adf340e3c7160fc639e (patch)
treead3719c0dd8cce043c235fd2d7e30c8bcd65f7af
parent1f19176867b1b1f760c0ec41cd78fbb6832d29ad (diff)
parentac509aa079bb090017886b5d7e32240ef16a1196 (diff)
downloadqmk_firmware-969cc4f812e3f86213f97adf340e3c7160fc639e.tar.gz
qmk_firmware-969cc4f812e3f86213f97adf340e3c7160fc639e.zip
Merge branch 'suspend_fix'
-rw-r--r--common.mk2
-rw-r--r--common/command.c8
-rw-r--r--common/sleep_led.h13
-rw-r--r--common/suspend.c70
-rw-r--r--common/suspend.h32
-rw-r--r--keyboard/gh60/Makefile.lufa9
-rw-r--r--keyboard/gh60/Makefile.pjrc3
-rw-r--r--protocol/lufa/lufa.c87
-rw-r--r--protocol/pjrc/main.c17
-rw-r--r--protocol/pjrc/usb.c23
10 files changed, 171 insertions, 93 deletions
diff --git a/common.mk b/common.mk
index de1c6c360..fa31b3c46 100644
--- a/common.mk
+++ b/common.mk
@@ -10,6 +10,7 @@ SRC += $(COMMON_DIR)/host.c \
10 $(COMMON_DIR)/print.c \ 10 $(COMMON_DIR)/print.c \
11 $(COMMON_DIR)/debug.c \ 11 $(COMMON_DIR)/debug.c \
12 $(COMMON_DIR)/bootloader.c \ 12 $(COMMON_DIR)/bootloader.c \
13 $(COMMON_DIR)/suspend.c \
13 $(COMMON_DIR)/util.c 14 $(COMMON_DIR)/util.c
14 15
15 16
@@ -58,6 +59,7 @@ endif
58ifdef SLEEP_LED_ENABLE 59ifdef SLEEP_LED_ENABLE
59 SRC += $(COMMON_DIR)/sleep_led.c 60 SRC += $(COMMON_DIR)/sleep_led.c
60 OPT_DEFS += -DSLEEP_LED_ENABLE 61 OPT_DEFS += -DSLEEP_LED_ENABLE
62 OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
61endif 63endif
62 64
63 65
diff --git a/common/command.c b/common/command.c
index cb98e1d5f..b29333883 100644
--- a/common/command.c
+++ b/common/command.c
@@ -28,6 +28,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
28#include "bootloader.h" 28#include "bootloader.h"
29#include "layer_switch.h" 29#include "layer_switch.h"
30#include "eeconfig.h" 30#include "eeconfig.h"
31#include "sleep_led.h"
32#include "led.h"
31#include "command.h" 33#include "command.h"
32 34
33#ifdef MOUSEKEY_ENABLE 35#ifdef MOUSEKEY_ENABLE
@@ -152,6 +154,12 @@ static bool command_common(uint8_t code)
152{ 154{
153 static host_driver_t *host_driver = 0; 155 static host_driver_t *host_driver = 0;
154 switch (code) { 156 switch (code) {
157 case KC_Z:
158 // test breathing sleep LED
159 print("Sleep LED test\n");
160 sleep_led_toggle();
161 led_set(host_keyboard_leds());
162 break;
155#ifdef BOOTMAGIC_ENABLE 163#ifdef BOOTMAGIC_ENABLE
156 case KC_E: 164 case KC_E:
157 print("eeprom config\n"); 165 print("eeprom config\n");
diff --git a/common/sleep_led.h b/common/sleep_led.h
index aebdbeaa5..6bdcf558a 100644
--- a/common/sleep_led.h
+++ b/common/sleep_led.h
@@ -1,10 +1,21 @@
1#ifndef SLEEP_LED_H 1#ifndef SLEEP_LED_H
2#define SLEEP_LED_H 2#define SLEEP_LED_H
3 3
4#define NO_SUSPEND_POWER_DOWN 4
5#ifdef SLEEP_LED_ENABLE
5 6
6void sleep_led_init(void); 7void sleep_led_init(void);
7void sleep_led_enable(void); 8void sleep_led_enable(void);
8void sleep_led_disable(void); 9void sleep_led_disable(void);
10void sleep_led_toggle(void);
11
12#else
13
14#define sleep_led_init()
15#define sleep_led_enable()
16#define sleep_led_disable()
17#define sleep_led_toggle()
18
19#endif
9 20
10#endif 21#endif
diff --git a/common/suspend.c b/common/suspend.c
new file mode 100644
index 000000000..6029fe7ff
--- /dev/null
+++ b/common/suspend.c
@@ -0,0 +1,70 @@
1#include "suspend.h"
2#include "matrix.h"
3#include "action.h"
4
5
6void suspend_power_down(void)
7{
8#ifndef NO_SUSPEND_POWER_DOWN
9 // Enable watchdog to wake from MCU sleep
10 cli();
11 wdt_reset();
12
13 // Watchdog Interrupt and System Reset Mode
14 //wdt_enable(WDTO_1S);
15 //WDTCSR |= _BV(WDIE);
16
17 // Watchdog Interrupt Mode
18 wdt_intr_enable(WDTO_120MS);
19
20 // TODO: more power saving
21 // See PicoPower application note
22 // - I/O port input with pullup
23 // - prescale clock
24 // - BOD disable
25 // - Power Reduction Register PRR
26 // sleep in power down mode
27 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
28 sleep_enable();
29 sei();
30 sleep_cpu();
31 sleep_disable();
32
33 // Disable watchdog after sleep
34 wdt_disable();
35#endif
36}
37
38bool suspend_wakeup_condition(void)
39{
40 matrix_scan();
41 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
42 if (matrix_get_row(r)) return true;
43 }
44 return false;
45}
46
47// run immediately after wakeup
48void suspend_wakeup_init(void)
49{
50 // clear matrix and keyboard state
51 matrix_init();
52 clear_keyboard();
53}
54
55#ifndef NO_SUSPEND_POWER_DOWN
56/* watchdog timeout */
57ISR(WDT_vect)
58{
59 /* wakeup from MCU sleep mode */
60/*
61 // blink LED
62 static uint8_t led_state = 0;
63 static uint8_t led_count = 0;
64 led_count++;
65 if ((led_count & 0x07) == 0) {
66 led_set((led_state ^= (1<<USB_LED_CAPS_LOCK)));
67 }
68*/
69}
70#endif
diff --git a/common/suspend.h b/common/suspend.h
new file mode 100644
index 000000000..1c1e41ac3
--- /dev/null
+++ b/common/suspend.h
@@ -0,0 +1,32 @@
1#ifndef SUSPEND_H
2#define SUSPEND_H
3
4#include <stdint.h>
5#include <stdbool.h>
6#include <avr/sleep.h>
7#include <avr/wdt.h>
8#include <avr/interrupt.h>
9
10
11#define wdt_intr_enable(value) \
12__asm__ __volatile__ ( \
13 "in __tmp_reg__,__SREG__" "\n\t" \
14 "cli" "\n\t" \
15 "wdr" "\n\t" \
16 "sts %0,%1" "\n\t" \
17 "out __SREG__,__tmp_reg__" "\n\t" \
18 "sts %0,%2" "\n\t" \
19 : /* no outputs */ \
20 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
21 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
22 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
23 _BV(WDIE) | (value & 0x07)) ) \
24 : "r0" \
25)
26
27
28void suspend_power_down(void);
29bool suspend_wakeup_condition(void);
30void suspend_wakeup_init(void);
31
32#endif
diff --git a/keyboard/gh60/Makefile.lufa b/keyboard/gh60/Makefile.lufa
index f153bc311..278f966de 100644
--- a/keyboard/gh60/Makefile.lufa
+++ b/keyboard/gh60/Makefile.lufa
@@ -48,7 +48,7 @@ TOP_DIR = ../..
48TARGET_DIR = . 48TARGET_DIR = .
49 49
50# project specific files 50# project specific files
51SRC += keymap.c \ 51SRC = keymap.c \
52 matrix.c \ 52 matrix.c \
53 led.c 53 led.c
54 54
@@ -96,6 +96,13 @@ F_USB = $(F_CPU)
96#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT 96#OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
97 97
98 98
99# Boot Section Size in bytes
100# Teensy halfKay 512
101# Atmel DFU loader 4096
102# LUFA bootloader 4096
103OPT_DEFS += -DBOOT_SIZE=4096
104
105
99# Build Options 106# Build Options
100# comment out to disable the options. 107# comment out to disable the options.
101# 108#
diff --git a/keyboard/gh60/Makefile.pjrc b/keyboard/gh60/Makefile.pjrc
index 290f7cb87..c12334fca 100644
--- a/keyboard/gh60/Makefile.pjrc
+++ b/keyboard/gh60/Makefile.pjrc
@@ -68,12 +68,14 @@ MCU = atmega32u4
68# examples use this variable to calculate timings. Do not add a "UL" here. 68# examples use this variable to calculate timings. Do not add a "UL" here.
69F_CPU = 16000000 69F_CPU = 16000000
70 70
71
71# Boot Section Size in bytes 72# Boot Section Size in bytes
72# Teensy halfKay 512 73# Teensy halfKay 512
73# Atmel DFU loader 4096 74# Atmel DFU loader 4096
74# LUFA bootloader 4096 75# LUFA bootloader 4096
75OPT_DEFS += -DBOOT_SIZE=4096 76OPT_DEFS += -DBOOT_SIZE=4096
76 77
78
77# Build Options 79# Build Options
78# comment out to disable the options. 80# comment out to disable the options.
79# 81#
@@ -82,6 +84,7 @@ MOUSEKEY_ENABLE = yes # Mouse keys(+5000)
82EXTRAKEY_ENABLE = yes # Audio control and System control(+600) 84EXTRAKEY_ENABLE = yes # Audio control and System control(+600)
83CONSOLE_ENABLE = yes # Console for debug 85CONSOLE_ENABLE = yes # Console for debug
84COMMAND_ENABLE = yes # Commands for debug and configuration 86COMMAND_ENABLE = yes # Commands for debug and configuration
87SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
85NKRO_ENABLE = yes # USB Nkey Rollover(+500) 88NKRO_ENABLE = yes # USB Nkey Rollover(+500)
86#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support 89#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support
87 90
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c
index 127dece54..7c7072090 100644
--- a/protocol/lufa/lufa.c
+++ b/protocol/lufa/lufa.c
@@ -36,20 +36,18 @@
36 this software. 36 this software.
37*/ 37*/
38 38
39#include <avr/sleep.h>
40#include <avr/wdt.h>
41#include "report.h" 39#include "report.h"
42#include "host.h" 40#include "host.h"
43#include "host_driver.h" 41#include "host_driver.h"
44#include "keyboard.h" 42#include "keyboard.h"
45#include "action.h" 43#include "action.h"
46#include "matrix.h"
47#include "led.h" 44#include "led.h"
48#include "sendchar.h" 45#include "sendchar.h"
49#include "debug.h" 46#include "debug.h"
50#ifdef SLEEP_LED_ENABLE 47#ifdef SLEEP_LED_ENABLE
51#include "sleep_led.h" 48#include "sleep_led.h"
52#endif 49#endif
50#include "suspend.h"
53 51
54#include "descriptor.h" 52#include "descriptor.h"
55#include "lufa.h" 53#include "lufa.h"
@@ -170,9 +168,7 @@ void EVENT_USB_Device_Suspend()
170 168
171void EVENT_USB_Device_WakeUp() 169void EVENT_USB_Device_WakeUp()
172{ 170{
173 // initialize 171 suspend_wakeup_init();
174 matrix_init();
175 clear_keyboard();
176 172
177#ifdef SLEEP_LED_ENABLE 173#ifdef SLEEP_LED_ENABLE
178 sleep_led_disable(); 174 sleep_led_disable();
@@ -503,32 +499,6 @@ static void SetupHardware(void)
503 USB_Device_EnableSOFEvents(); 499 USB_Device_EnableSOFEvents();
504} 500}
505 501
506
507static 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
532int main(void) __attribute__ ((weak)); 502int main(void) __attribute__ ((weak));
533int main(void) 503int main(void)
534{ 504{
@@ -541,42 +511,10 @@ int main(void)
541 sei(); 511 sei();
542 512
543 while (1) { 513 while (1) {
544 // while suspend
545 while (USB_DeviceState == DEVICE_STATE_Suspended) { 514 while (USB_DeviceState == DEVICE_STATE_Suspended) {
546#ifndef NO_SUSPEND_POWER_DOWN 515 suspend_power_down();
547 // Enable watchdog to wake from MCU sleep 516 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
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(); 517 USB_Device_SendRemoteWakeup();
579 }
580 } 518 }
581 } 519 }
582 520
@@ -587,20 +525,3 @@ int main(void)
587#endif 525#endif
588 } 526 }
589} 527}
590
591#ifndef NO_SUSPEND_POWER_DOWN
592/* watchdog timeout */
593ISR(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
diff --git a/protocol/pjrc/main.c b/protocol/pjrc/main.c
index 776bfee9d..5f15dbf89 100644
--- a/protocol/pjrc/main.c
+++ b/protocol/pjrc/main.c
@@ -31,10 +31,7 @@
31#include "print.h" 31#include "print.h"
32#include "debug.h" 32#include "debug.h"
33#include "util.h" 33#include "util.h"
34#include "bootloader.h" 34#include "suspend.h"
35#ifdef PS2_MOUSE_ENABLE
36# include "ps2_mouse.h"
37#endif
38#include "host.h" 35#include "host.h"
39#include "pjrc.h" 36#include "pjrc.h"
40 37
@@ -55,7 +52,17 @@ int main(void)
55 52
56 keyboard_init(); 53 keyboard_init();
57 host_set_driver(pjrc_driver()); 54 host_set_driver(pjrc_driver());
55#ifdef SLEEP_LED_ENABLE
56 sleep_led_init();
57#endif
58 while (1) { 58 while (1) {
59 keyboard_task(); 59 while (suspend) {
60 suspend_power_down();
61 if (remote_wakeup && suspend_wakeup_condition()) {
62 usb_remote_wakeup();
63 }
64 }
65
66 keyboard_task();
60 } 67 }
61} 68}
diff --git a/protocol/pjrc/usb.c b/protocol/pjrc/usb.c
index f4c6f81f5..a9fbc4638 100644
--- a/protocol/pjrc/usb.c
+++ b/protocol/pjrc/usb.c
@@ -33,6 +33,8 @@
33#include "usb_extra.h" 33#include "usb_extra.h"
34#include "print.h" 34#include "print.h"
35#include "util.h" 35#include "util.h"
36#include "sleep_led.h"
37#include "suspend.h"
36 38
37 39
38/************************************************************************** 40/**************************************************************************
@@ -595,7 +597,8 @@ void usb_init(void)
595 USB_CONFIG(); // start USB clock 597 USB_CONFIG(); // start USB clock
596 UDCON = 0; // enable attach resistor 598 UDCON = 0; // enable attach resistor
597 usb_configuration = 0; 599 usb_configuration = 0;
598 UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE); 600 suspend = false;
601 UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE)|(1<<WAKEUPE);
599 sei(); 602 sei();
600} 603}
601 604
@@ -631,9 +634,23 @@ ISR(USB_GEN_vect)
631 634
632 intbits = UDINT; 635 intbits = UDINT;
633 UDINT = 0; 636 UDINT = 0;
634 if (intbits & (1<<SUSPI)) { 637 if ((intbits & (1<<SUSPI)) && (UDIEN & (1<<SUSPE)) && usb_configuration) {
638#ifdef SLEEP_LED_ENABLE
639 sleep_led_enable();
640#endif
641 UDIEN &= ~(1<<SUSPE);
642 UDIEN |= (1<<WAKEUPE);
635 suspend = true; 643 suspend = true;
636 } else { 644 }
645 if ((intbits & (1<<WAKEUPI)) && (UDIEN & (1<<WAKEUPE)) && usb_configuration) {
646 suspend_wakeup_init();
647#ifdef SLEEP_LED_ENABLE
648 sleep_led_disable();
649#endif
650 led_set(host_keyboard_leds());
651
652 UDIEN |= (1<<SUSPE);
653 UDIEN &= ~(1<<WAKEUPE);
637 suspend = false; 654 suspend = false;
638 } 655 }
639 if (intbits & (1<<EORSTI)) { 656 if (intbits & (1<<EORSTI)) {