aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common/avr
diff options
context:
space:
mode:
authorRyan <fauxpark@gmail.com>2021-02-25 15:54:25 +1100
committerGitHub <noreply@github.com>2021-02-25 15:54:25 +1100
commit39694d5eb0b7e48e06f9544600041fbbedfff956 (patch)
tree2427bbf89b955330f793fd7dad3502cfc1e19de9 /tmk_core/common/avr
parent46f4422a87bf7e3aa52bd8770b14f8361d198e06 (diff)
downloadqmk_firmware-39694d5eb0b7e48e06f9544600041fbbedfff956.tar.gz
qmk_firmware-39694d5eb0b7e48e06f9544600041fbbedfff956.zip
V-USB suspend refactor (#11891)
Diffstat (limited to 'tmk_core/common/avr')
-rw-r--r--tmk_core/common/avr/sleep_led.c2
-rw-r--r--tmk_core/common/avr/suspend.c95
-rw-r--r--tmk_core/common/avr/suspend_avr.h25
3 files changed, 67 insertions, 55 deletions
diff --git a/tmk_core/common/avr/sleep_led.c b/tmk_core/common/avr/sleep_led.c
index 63dcc2afd..9a3b52abe 100644
--- a/tmk_core/common/avr/sleep_led.c
+++ b/tmk_core/common/avr/sleep_led.c
@@ -90,7 +90,7 @@ void sleep_led_toggle(void) {
90 * 90 *
91 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle 91 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
92 * 92 *
93 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 93 * https://www.wolframalpha.com/input/?i=sin%28x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
94 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } 94 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
95 */ 95 */
96static const uint8_t breathing_table[64] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 96static const uint8_t breathing_table[64] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, 255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index 86c3df040..cb505ab32 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -4,7 +4,6 @@
4#include <avr/interrupt.h> 4#include <avr/interrupt.h>
5#include "matrix.h" 5#include "matrix.h"
6#include "action.h" 6#include "action.h"
7#include "suspend_avr.h"
8#include "suspend.h" 7#include "suspend.h"
9#include "timer.h" 8#include "timer.h"
10#include "led.h" 9#include "led.h"
@@ -13,6 +12,9 @@
13#ifdef PROTOCOL_LUFA 12#ifdef PROTOCOL_LUFA
14# include "lufa.h" 13# include "lufa.h"
15#endif 14#endif
15#ifdef PROTOCOL_VUSB
16# include "vusb.h"
17#endif
16 18
17#ifdef BACKLIGHT_ENABLE 19#ifdef BACKLIGHT_ENABLE
18# include "backlight.h" 20# include "backlight.h"
@@ -52,7 +54,25 @@ __attribute__((weak)) void suspend_power_down_user(void) {}
52 */ 54 */
53__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); } 55__attribute__((weak)) void suspend_power_down_kb(void) { suspend_power_down_user(); }
54 56
55#ifndef NO_SUSPEND_POWER_DOWN 57#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
58
59// clang-format off
60#define wdt_intr_enable(value) \
61__asm__ __volatile__ ( \
62 "in __tmp_reg__,__SREG__" "\n\t" \
63 "cli" "\n\t" \
64 "wdr" "\n\t" \
65 "sts %0,%1" "\n\t" \
66 "out __SREG__,__tmp_reg__" "\n\t" \
67 "sts %0,%2" "\n\t" \
68 : /* no outputs */ \
69 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
70 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
71 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | _BV(WDIE) | (value & 0x07))) \
72 : "r0" \
73)
74// clang-format on
75
56/** \brief Power down MCU with watchdog timer 76/** \brief Power down MCU with watchdog timer
57 * 77 *
58 * wdto: watchdog timer timeout defined in <avr/wdt.h> 78 * wdto: watchdog timer timeout defined in <avr/wdt.h>
@@ -74,37 +94,11 @@ static uint8_t wdt_timeout = 0;
74 * FIXME: needs doc 94 * FIXME: needs doc
75 */ 95 */
76static void power_down(uint8_t wdto) { 96static void power_down(uint8_t wdto) {
77# ifdef PROTOCOL_LUFA
78 if (USB_DeviceState == DEVICE_STATE_Configured) return;
79# endif
80 wdt_timeout = wdto; 97 wdt_timeout = wdto;
81 98
82 // Watchdog Interrupt Mode 99 // Watchdog Interrupt Mode
83 wdt_intr_enable(wdto); 100 wdt_intr_enable(wdto);
84 101
85# ifdef BACKLIGHT_ENABLE
86 backlight_set(0);
87# endif
88
89 // Turn off LED indicators
90 uint8_t leds_off = 0;
91# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
92 if (is_backlight_enabled()) {
93 // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
94 leds_off |= (1 << USB_LED_CAPS_LOCK);
95 }
96# endif
97 led_set(leds_off);
98
99# ifdef AUDIO_ENABLE
100 // This sometimes disables the start-up noise, so it's been disabled
101 // stop_all_notes();
102# endif /* AUDIO_ENABLE */
103# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
104 rgblight_suspend();
105# endif
106 suspend_power_down_kb();
107
108 // TODO: more power saving 102 // TODO: more power saving
109 // See PicoPower application note 103 // See PicoPower application note
110 // - I/O port input with pullup 104 // - I/O port input with pullup
@@ -127,10 +121,46 @@ static void power_down(uint8_t wdto) {
127 * FIXME: needs doc 121 * FIXME: needs doc
128 */ 122 */
129void suspend_power_down(void) { 123void suspend_power_down(void) {
124#ifdef PROTOCOL_LUFA
125 if (USB_DeviceState == DEVICE_STATE_Configured) return;
126#endif
127#ifdef PROTOCOL_VUSB
128 if (!vusb_suspended) return;
129#endif
130
130 suspend_power_down_kb(); 131 suspend_power_down_kb();
131 132
132#ifndef NO_SUSPEND_POWER_DOWN 133#ifndef NO_SUSPEND_POWER_DOWN
134 // Turn off backlight
135# ifdef BACKLIGHT_ENABLE
136 backlight_set(0);
137# endif
138
139 // Turn off LED indicators
140 uint8_t leds_off = 0;
141# if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
142 if (is_backlight_enabled()) {
143 // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
144 leds_off |= (1 << USB_LED_CAPS_LOCK);
145 }
146# endif
147 led_set(leds_off);
148
149 // Turn off audio
150# ifdef AUDIO_ENABLE
151 // This sometimes disables the start-up noise, so it's been disabled
152 // stop_all_notes();
153# endif
154
155 // Turn off underglow
156# if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
157 rgblight_suspend();
158# endif
159
160 // Enter sleep state if possible (ie, the MCU has a watchdog timeout interrupt)
161# if defined(WDT_vect)
133 power_down(WDTO_15MS); 162 power_down(WDTO_15MS);
163# endif
134#endif 164#endif
135} 165}
136 166
@@ -164,17 +194,24 @@ __attribute__((weak)) void suspend_wakeup_init_kb(void) { suspend_wakeup_init_us
164void suspend_wakeup_init(void) { 194void suspend_wakeup_init(void) {
165 // clear keyboard state 195 // clear keyboard state
166 clear_keyboard(); 196 clear_keyboard();
197
198 // Turn on backlight
167#ifdef BACKLIGHT_ENABLE 199#ifdef BACKLIGHT_ENABLE
168 backlight_init(); 200 backlight_init();
169#endif 201#endif
202
203 // Restore LED indicators
170 led_set(host_keyboard_leds()); 204 led_set(host_keyboard_leds());
205
206 // Wake up underglow
171#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE) 207#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
172 rgblight_wakeup(); 208 rgblight_wakeup();
173#endif 209#endif
210
174 suspend_wakeup_init_kb(); 211 suspend_wakeup_init_kb();
175} 212}
176 213
177#ifndef NO_SUSPEND_POWER_DOWN 214#if !defined(NO_SUSPEND_POWER_DOWN) && defined(WDT_vect)
178/* watchdog timeout */ 215/* watchdog timeout */
179ISR(WDT_vect) { 216ISR(WDT_vect) {
180 // compensate timer for sleep 217 // compensate timer for sleep
diff --git a/tmk_core/common/avr/suspend_avr.h b/tmk_core/common/avr/suspend_avr.h
deleted file mode 100644
index 6df048f3b..000000000
--- a/tmk_core/common/avr/suspend_avr.h
+++ /dev/null
@@ -1,25 +0,0 @@
1#pragma once
2
3#include <stdint.h>
4#include <stdbool.h>
5#include <avr/sleep.h>
6#include <avr/wdt.h>
7#include <avr/interrupt.h>
8
9// clang-format off
10#define wdt_intr_enable(value) \
11__asm__ __volatile__ ( \
12 "in __tmp_reg__,__SREG__" "\n\t" \
13 "cli" "\n\t" \
14 "wdr" "\n\t" \
15 "sts %0,%1" "\n\t" \
16 "out __SREG__,__tmp_reg__" "\n\t" \
17 "sts %0,%2" "\n\t" \
18 : /* no outputs */ \
19 : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
20 "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
21 "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
22 _BV(WDIE) | (value & 0x07)) ) \
23 : "r0" \
24)
25// clang-format on