diff options
| author | tmk <nobody@nowhere> | 2013-03-27 15:23:57 +0900 | 
|---|---|---|
| committer | tmk <nobody@nowhere> | 2013-03-27 15:23:57 +0900 | 
| commit | 969cc4f812e3f86213f97adf340e3c7160fc639e (patch) | |
| tree | ad3719c0dd8cce043c235fd2d7e30c8bcd65f7af | |
| parent | 1f19176867b1b1f760c0ec41cd78fbb6832d29ad (diff) | |
| parent | ac509aa079bb090017886b5d7e32240ef16a1196 (diff) | |
| download | firmware-969cc4f812e3f86213f97adf340e3c7160fc639e.tar.gz firmware-969cc4f812e3f86213f97adf340e3c7160fc639e.tar.bz2 firmware-969cc4f812e3f86213f97adf340e3c7160fc639e.zip  | |
Merge branch 'suspend_fix'
| -rw-r--r-- | common.mk | 2 | ||||
| -rw-r--r-- | common/command.c | 8 | ||||
| -rw-r--r-- | common/sleep_led.h | 13 | ||||
| -rw-r--r-- | common/suspend.c | 70 | ||||
| -rw-r--r-- | common/suspend.h | 32 | ||||
| -rw-r--r-- | keyboard/gh60/Makefile.lufa | 9 | ||||
| -rw-r--r-- | keyboard/gh60/Makefile.pjrc | 3 | ||||
| -rw-r--r-- | protocol/lufa/lufa.c | 87 | ||||
| -rw-r--r-- | protocol/pjrc/main.c | 17 | ||||
| -rw-r--r-- | protocol/pjrc/usb.c | 23 | 
10 files changed, 171 insertions, 93 deletions
@@ -10,6 +10,7 @@ SRC +=	$(COMMON_DIR)/host.c \  	$(COMMON_DIR)/print.c \  	$(COMMON_DIR)/debug.c \  	$(COMMON_DIR)/bootloader.c \ +	$(COMMON_DIR)/suspend.c \  	$(COMMON_DIR)/util.c @@ -58,6 +59,7 @@ endif  ifdef SLEEP_LED_ENABLE      SRC += $(COMMON_DIR)/sleep_led.c      OPT_DEFS += -DSLEEP_LED_ENABLE +    OPT_DEFS += -DNO_SUSPEND_POWER_DOWN  endif 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/>.  #include "bootloader.h"  #include "layer_switch.h"  #include "eeconfig.h" +#include "sleep_led.h" +#include "led.h"  #include "command.h"  #ifdef MOUSEKEY_ENABLE @@ -152,6 +154,12 @@ static bool command_common(uint8_t code)  {      static host_driver_t *host_driver = 0;      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          case KC_E:              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 @@  #ifndef SLEEP_LED_H  #define SLEEP_LED_H -#define NO_SUSPEND_POWER_DOWN + +#ifdef SLEEP_LED_ENABLE  void sleep_led_init(void);  void sleep_led_enable(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 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 @@ +#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 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 @@ +#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 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 = ../..  TARGET_DIR = .  # project specific files -SRC +=	keymap.c \ +SRC =	keymap.c \  	matrix.c \  	led.c @@ -96,6 +96,13 @@ F_USB = $(F_CPU)  #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  #   comment out to disable the options.  # 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  #   examples use this variable to calculate timings.  Do not add a "UL" here.  F_CPU = 16000000 +  # Boot Section Size in bytes  #   Teensy halfKay   512  #   Atmel DFU loader 4096  #   LUFA bootloader  4096  OPT_DEFS += -DBOOT_SIZE=4096 +  # Build Options  #   comment out to disable the options.  # @@ -82,6 +84,7 @@ MOUSEKEY_ENABLE = yes	# Mouse keys(+5000)  EXTRAKEY_ENABLE = yes	# Audio control and System control(+600)  CONSOLE_ENABLE = yes    # Console for debug  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)  #PS2_MOUSE_ENABLE = yes	# PS/2 mouse(TrackPoint) support 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 @@    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 "suspend.h"  #include "descriptor.h"  #include "lufa.h" @@ -170,9 +168,7 @@ void EVENT_USB_Device_Suspend()  void EVENT_USB_Device_WakeUp()  { -    // initialize -    matrix_init(); -    clear_keyboard(); +    suspend_wakeup_init();  #ifdef SLEEP_LED_ENABLE      sleep_led_disable(); @@ -503,32 +499,6 @@ static void SetupHardware(void)      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)  { @@ -541,42 +511,10 @@ int main(void)      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(); - -            // 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(); -                }              }          } @@ -587,20 +525,3 @@ int main(void)  #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 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 @@  #include "print.h"  #include "debug.h"  #include "util.h" -#include "bootloader.h" -#ifdef PS2_MOUSE_ENABLE -#   include "ps2_mouse.h" -#endif +#include "suspend.h"  #include "host.h"  #include "pjrc.h" @@ -55,7 +52,17 @@ int main(void)      keyboard_init();      host_set_driver(pjrc_driver()); +#ifdef SLEEP_LED_ENABLE +    sleep_led_init(); +#endif      while (1) { -       keyboard_task();  +        while (suspend) { +            suspend_power_down(); +            if (remote_wakeup && suspend_wakeup_condition()) { +                usb_remote_wakeup(); +            } +        } + +        keyboard_task();       }  } 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 @@  #include "usb_extra.h"  #include "print.h"  #include "util.h" +#include "sleep_led.h" +#include "suspend.h"  /************************************************************************** @@ -595,7 +597,8 @@ void usb_init(void)          USB_CONFIG();				// start USB clock          UDCON = 0;				// enable attach resistor  	usb_configuration = 0; -        UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE); +        suspend = false; +        UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE)|(1<<WAKEUPE);  	sei();  } @@ -631,9 +634,23 @@ ISR(USB_GEN_vect)          intbits = UDINT;          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; -        } 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;          }          if (intbits & (1<<EORSTI)) {  | 
