4 #include <avr/interrupt.h>
8 #include "suspend_avr.h"
20 #endif /* AUDIO_ENABLE */
22 #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
27 #define wdt_intr_enable(value) \
28 __asm__ __volatile__ ( \
29 "in __tmp_reg__,__SREG__" "\n\t" \
33 "out __SREG__,__tmp_reg__" "\n\t" \
36 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
37 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
38 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
39 _BV(WDIE) | (value & 0x07)) ) \
44 /** \brief Suspend idle
48 void suspend_idle(uint8_t time)
51 set_sleep_mode(SLEEP_MODE_IDLE);
58 #ifndef NO_SUSPEND_POWER_DOWN
59 /** \brief Power down MCU with watchdog timer
61 * wdto: watchdog timer timeout defined in <avr/wdt.h>
73 static uint8_t wdt_timeout = 0;
75 /** \brief Run keyboard level Power down
79 __attribute__ ((weak))
80 void suspend_power_down_user (void) { }
81 /** \brief Run keyboard level Power down
85 __attribute__ ((weak))
86 void suspend_power_down_kb(void) {
87 suspend_power_down_user();
94 static void power_down(uint8_t wdto)
97 if (USB_DeviceState == DEVICE_STATE_Configured) return;
101 // Watchdog Interrupt Mode
102 wdt_intr_enable(wdto);
104 #ifdef BACKLIGHT_ENABLE
108 // Turn off LED indicators
112 // This sometimes disables the start-up noise, so it's been disabled
114 #endif /* AUDIO_ENABLE */
115 #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
116 #ifdef RGBLIGHT_ANIMATIONS
117 rgblight_timer_disable();
119 rgblight_disable_noeeprom();
121 suspend_power_down_kb();
123 // TODO: more power saving
124 // See PicoPower application note
125 // - I/O port input with pullup
128 // - Power Reduction Register PRR
129 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
135 // Disable watchdog after sleep
140 /** \brief Suspend power down
144 void suspend_power_down(void)
146 #ifndef NO_SUSPEND_POWER_DOWN
147 power_down(WDTO_15MS);
151 __attribute__ ((weak)) void matrix_power_up(void) {}
152 __attribute__ ((weak)) void matrix_power_down(void) {}
153 bool suspend_wakeup_condition(void)
158 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
159 if (matrix_get_row(r)) return true;
164 /** \brief run user level code immediately after wakeup
168 __attribute__ ((weak))
169 void suspend_wakeup_init_user(void) { }
171 /** \brief run keyboard level code immediately after wakeup
175 __attribute__ ((weak))
176 void suspend_wakeup_init_kb(void) {
177 suspend_wakeup_init_user();
179 /** \brief run immediately after wakeup
183 void suspend_wakeup_init(void)
185 // clear keyboard state
187 #ifdef BACKLIGHT_ENABLE
190 led_set(host_keyboard_leds());
191 #if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
192 #ifdef BOOTLOADER_TEENSY
195 rgblight_enable_noeeprom();
196 #ifdef RGBLIGHT_ANIMATIONS
197 rgblight_timer_enable();
200 suspend_wakeup_init_kb();
203 #ifndef NO_SUSPEND_POWER_DOWN
204 /* watchdog timeout */
207 // compensate timer for sleep
208 switch (wdt_timeout) {
210 timer_count += 15 + 2; // WDTO_15MS + 2(from observation)