From 39694d5eb0b7e48e06f9544600041fbbedfff956 Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 25 Feb 2021 15:54:25 +1100 Subject: V-USB suspend refactor (#11891) --- tmk_core/common/avr/suspend.c | 95 ++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 29 deletions(-) (limited to 'tmk_core/common/avr/suspend.c') diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index 86c3df040a..cb505ab329 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -4,7 +4,6 @@ #include #include "matrix.h" #include "action.h" -#include "suspend_avr.h" #include "suspend.h" #include "timer.h" #include "led.h" @@ -13,6 +12,9 @@ #ifdef PROTOCOL_LUFA # include "lufa.h" #endif +#ifdef PROTOCOL_VUSB +# include "vusb.h" +#endif #ifdef BACKLIGHT_ENABLE # include "backlight.h" @@ -52,7 +54,25 @@ __attribute__((weak)) void suspend_power_down_user(void) {} */ __attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); } -#ifndef NO_SUSPEND_POWER_DOWN +#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) + +// clang-format off +#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" \ +) +// clang-format on + /** \brief Power down MCU with watchdog timer * * wdto: watchdog timer timeout defined in @@ -74,37 +94,11 @@ static uint8_t wdt_timeout = 0; * FIXME: needs doc */ static void power_down(uint8_t wdto) { -# ifdef PROTOCOL_LUFA - if (USB_DeviceState == DEVICE_STATE_Configured) return; -# endif wdt_timeout = wdto; // Watchdog Interrupt Mode wdt_intr_enable(wdto); -# ifdef BACKLIGHT_ENABLE - backlight_set(0); -# endif - - // Turn off LED indicators - uint8_t leds_off = 0; -# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) - if (is_backlight_enabled()) { - // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off - leds_off |= (1 << USB_LED_CAPS_LOCK); - } -# endif - led_set(leds_off); - -# ifdef AUDIO_ENABLE - // This sometimes disables the start-up noise, so it's been disabled - // stop_all_notes(); -# endif /* AUDIO_ENABLE */ -# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) - rgblight_suspend(); -# endif - suspend_power_down_kb(); - // TODO: more power saving // See PicoPower application note // - I/O port input with pullup @@ -127,10 +121,46 @@ static void power_down(uint8_t wdto) { * FIXME: needs doc */ void suspend_power_down(void) { +#ifdef PROTOCOL_LUFA + if (USB_DeviceState == DEVICE_STATE_Configured) return; +#endif +#ifdef PROTOCOL_VUSB + if (!vusb_suspended) return; +#endif + suspend_power_down_kb(); #ifndef NO_SUSPEND_POWER_DOWN + // Turn off backlight +# ifdef BACKLIGHT_ENABLE + backlight_set(0); +# endif + + // Turn off LED indicators + uint8_t leds_off = 0; +# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) + if (is_backlight_enabled()) { + // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off + leds_off |= (1 << USB_LED_CAPS_LOCK); + } +# endif + led_set(leds_off); + + // Turn off audio +# ifdef AUDIO_ENABLE + // This sometimes disables the start-up noise, so it's been disabled + // stop_all_notes(); +# endif + + // Turn off underglow +# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) + rgblight_suspend(); +# endif + + // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt) +# if defined(WDT_vect) power_down(WDTO_15MS); +# endif #endif } @@ -164,17 +194,24 @@ __attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_us void suspend_wakeup_init(void) { // clear keyboard state clear_keyboard(); + + // Turn on backlight #ifdef BACKLIGHT_ENABLE backlight_init(); #endif + + // Restore LED indicators led_set(host_keyboard_leds()); + + // Wake up underglow #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) rgblight_wakeup(); #endif + suspend_wakeup_init_kb(); } -#ifndef NO_SUSPEND_POWER_DOWN +#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect) /* watchdog timeout */ ISR(WDT_vect) { // compensate timer for sleep -- cgit v1.2.3