aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tmk_core/common/arm_atsam/suspend.c90
-rw-r--r--tmk_core/protocol/arm_atsam/i2c_master.c5
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.c80
-rw-r--r--tmk_core/protocol/arm_atsam/usb/ui.c8
-rw-r--r--tmk_core/protocol/arm_atsam/usb/ui.h6
5 files changed, 136 insertions, 53 deletions
diff --git a/tmk_core/common/arm_atsam/suspend.c b/tmk_core/common/arm_atsam/suspend.c
index 01d1930ea..e34965df6 100644
--- a/tmk_core/common/arm_atsam/suspend.c
+++ b/tmk_core/common/arm_atsam/suspend.c
@@ -1,17 +1,85 @@
1/* Copyright 2017 Fred Sundvik 1#include "matrix.h"
2#include "i2c_master.h"
3#include "led_matrix.h"
4#include "suspend.h"
5
6/** \brief Suspend idle
2 * 7 *
3 * This program is free software: you can redistribute it and/or modify 8 * FIXME: needs doc
4 * it under the terms of the GNU General Public License as published by 9 */
5 * the Free Software Foundation, either version 2 of the License, or 10void suspend_idle(uint8_t time) {
6 * (at your option) any later version. 11 /* Note: Not used anywhere currently */
12}
13
14/** \brief Run user level Power down
7 * 15 *
8 * This program is distributed in the hope that it will be useful, 16 * FIXME: needs doc
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 */
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18__attribute__ ((weak))
11 * GNU General Public License for more details. 19void suspend_power_down_user (void) {
20
21}
22
23/** \brief Run keyboard level Power down
24 *
25 * FIXME: needs doc
26 */
27__attribute__ ((weak))
28void suspend_power_down_kb(void) {
29 suspend_power_down_user();
30}
31
32/** \brief Suspend power down
33 *
34 * FIXME: needs doc
35 */
36void suspend_power_down(void)
37{
38 I2C3733_Control_Set(0); //Disable LED driver
39
40 suspend_power_down_kb();
41}
42
43__attribute__ ((weak)) void matrix_power_up(void) {}
44__attribute__ ((weak)) void matrix_power_down(void) {}
45bool suspend_wakeup_condition(void) {
46 matrix_power_up();
47 matrix_scan();
48 matrix_power_down();
49 for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
50 if (matrix_get_row(r)) return true;
51 }
52 return false;
53}
54
55/** \brief run user level code immediately after wakeup
56 *
57 * FIXME: needs doc
58 */
59__attribute__ ((weak))
60void suspend_wakeup_init_user(void) {
61
62}
63
64/** \brief run keyboard level code immediately after wakeup
65 *
66 * FIXME: needs doc
67 */
68__attribute__ ((weak))
69void suspend_wakeup_init_kb(void) {
70 suspend_wakeup_init_user();
71}
72
73/** \brief run immediately after wakeup
12 * 74 *
13 * You should have received a copy of the GNU General Public License 75 * FIXME: needs doc
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */ 76 */
77void suspend_wakeup_init(void) {
78 /* If LEDs are set to enabled, enable the hardware */
79 if (led_enabled) {
80 I2C3733_Control_Set(1);
81 }
16 82
83 suspend_wakeup_init_kb();
84}
17 85
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c
index 4f5a79e89..ece9ee5db 100644
--- a/tmk_core/protocol/arm_atsam/i2c_master.c
+++ b/tmk_core/protocol/arm_atsam/i2c_master.c
@@ -261,8 +261,9 @@ uint8_t I2C3733_Init_Control(void)
261{ 261{
262 DBGC(DC_I2C3733_INIT_CONTROL_BEGIN); 262 DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
263 263
264 srdata.bit.SDB_N = 1; 264 //Hardware state shutdown on boot
265 SPI_WriteSRData(); 265 //USB state machine will enable driver when communication is ready
266 I2C3733_Control_Set(0);
266 267
267 CLK_delay_ms(1); 268 CLK_delay_ms(1);
268 269
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
index d3dc272ee..13034a05d 100644
--- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c
+++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
@@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
31//From keyboard's directory 31//From keyboard's directory
32#include "config_led.h" 32#include "config_led.h"
33 33
34uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes
35
34void main_subtasks(void); 36void main_subtasks(void);
35uint8_t keyboard_leds(void); 37uint8_t keyboard_leds(void);
36void send_keyboard(report_keyboard_t *report); 38void send_keyboard(report_keyboard_t *report);
@@ -62,12 +64,6 @@ void send_keyboard(report_keyboard_t *report)
62{ 64{
63 uint32_t irqflags; 65 uint32_t irqflags;
64 66
65 if (usb_state == USB_STATE_POWERDOWN)
66 {
67 udc_remotewakeup();
68 return;
69 }
70
71#ifdef NKRO_ENABLE 67#ifdef NKRO_ENABLE
72 if (!keymap_config.nkro) 68 if (!keymap_config.nkro)
73 { 69 {
@@ -161,41 +157,56 @@ void send_consumer(uint16_t data)
161#endif //EXTRAKEY_ENABLE 157#endif //EXTRAKEY_ENABLE
162} 158}
163 159
164uint8_t g_drvid;
165uint8_t g_usb_sleeping = 0;
166
167void main_subtask_usb_state(void) 160void main_subtask_usb_state(void)
168{ 161{
169 if (usb_state == USB_STATE_POWERDOWN) 162 static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
163 uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register
164
165 if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED
170 { 166 {
171 if (!g_usb_sleeping) 167 fsmstate_on_delay = 0; //Clear ON delay timer
168
169 if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If previously not SUSPENDED
172 { 170 {
173 g_usb_sleeping = 1; 171 suspend_power_down(); //Run suspend routine
174 if (led_enabled) 172 g_usb_state = fsmstate_now; //Save current USB state
175 {
176 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
177 {
178 I2C3733_Control_Set(0);
179 }
180 }
181 } 173 }
182 } 174 }
183 else if (g_usb_sleeping) 175 else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //Else if USB SLEEPING
184 { 176 {
185 g_usb_sleeping = 0; 177 fsmstate_on_delay = 0; //Clear ON delay timer
186 if (led_enabled) 178
179 if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //If previously not SLEEPING
187 { 180 {
188 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++) 181 suspend_power_down(); //Run suspend routine
182 g_usb_state = fsmstate_now; //Save current USB state
183 }
184 }
185 else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_ON_Val) //Else if USB ON
186 {
187 if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) //If previously not ON
188 {
189 if (fsmstate_on_delay == 0) //If ON delay timer is cleared
189 { 190 {
190 I2C3733_Control_Set(1); 191 fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer
192 }
193 else if (CLK_get_ms() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
194 {
195 suspend_wakeup_init(); //Run wakeup routine
196 g_usb_state = fsmstate_now; //Save current USB state
191 } 197 }
192 } 198 }
193 } 199 }
200 else //Else if USB is in a state not being tracked
201 {
202 fsmstate_on_delay = 0; //Clear ON delay timer
203 }
194} 204}
195 205
196void main_subtask_led(void) 206void main_subtask_led(void)
197{ 207{
198 if (g_usb_sleeping) return; 208 if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) return; //Only run LED tasks if USB is operating
209
199 led_matrix_task(); 210 led_matrix_task();
200} 211}
201 212
@@ -275,8 +286,8 @@ int main(void)
275 286
276 i2c_led_q_init(); 287 i2c_led_q_init();
277 288
278 for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++) 289 for (uint8_t drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++)
279 I2C_LED_Q_ONOFF(g_drvid); //Queue data 290 I2C_LED_Q_ONOFF(drvid); //Queue data
280 291
281 keyboard_setup(); 292 keyboard_setup();
282 293
@@ -294,10 +305,21 @@ int main(void)
294 305
295 while (1) 306 while (1)
296 { 307 {
297 keyboard_task();
298
299 main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals 308 main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
300 309
310 if (g_usb_state == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val || g_usb_state == USB_FSMSTATUS_FSMSTATE_SLEEP_Val)
311 {
312 if (suspend_wakeup_condition())
313 {
314 udc_remotewakeup(); //Send remote wakeup signal
315 wait_ms(50);
316 }
317
318 continue;
319 }
320
321 keyboard_task();
322
301#ifdef CONSOLE_ENABLE 323#ifdef CONSOLE_ENABLE
302 if (CLK_get_ms() > next_print) 324 if (CLK_get_ms() > next_print)
303 { 325 {
diff --git a/tmk_core/protocol/arm_atsam/usb/ui.c b/tmk_core/protocol/arm_atsam/usb/ui.c
index 031678b64..70a619109 100644
--- a/tmk_core/protocol/arm_atsam/usb/ui.c
+++ b/tmk_core/protocol/arm_atsam/usb/ui.c
@@ -52,8 +52,6 @@
52#include "samd51j18a.h" 52#include "samd51j18a.h"
53#include "ui.h" 53#include "ui.h"
54 54
55volatile uint8_t usb_state;
56
57//! Sequence process running each \c SEQUENCE_PERIOD ms 55//! Sequence process running each \c SEQUENCE_PERIOD ms
58#define SEQUENCE_PERIOD 150 56#define SEQUENCE_PERIOD 150
59 57
@@ -72,12 +70,12 @@ static void ui_wakeup_handler(void)
72 70
73void ui_init(void) 71void ui_init(void)
74{ 72{
75 usb_state = USB_STATE_POWERUP; 73
76} 74}
77 75
78void ui_powerdown(void) 76void ui_powerdown(void)
79{ 77{
80 usb_state = USB_STATE_POWERDOWN; 78
81} 79}
82 80
83void ui_wakeup_enable(void) 81void ui_wakeup_enable(void)
@@ -92,7 +90,7 @@ void ui_wakeup_disable(void)
92 90
93void ui_wakeup(void) 91void ui_wakeup(void)
94{ 92{
95 usb_state = USB_STATE_POWERUP; 93
96} 94}
97 95
98void ui_process(uint16_t framenumber) 96void ui_process(uint16_t framenumber)
diff --git a/tmk_core/protocol/arm_atsam/usb/ui.h b/tmk_core/protocol/arm_atsam/usb/ui.h
index 3d899e669..d1c767d45 100644
--- a/tmk_core/protocol/arm_atsam/usb/ui.h
+++ b/tmk_core/protocol/arm_atsam/usb/ui.h
@@ -47,12 +47,6 @@
47#ifndef _UI_H_ 47#ifndef _UI_H_
48#define _UI_H_ 48#define _UI_H_
49 49
50extern volatile uint8_t usb_state;
51
52#define USB_STATE_UNKNOWN 0
53#define USB_STATE_POWERDOWN 1
54#define USB_STATE_POWERUP 2
55
56//! \brief Initializes the user interface 50//! \brief Initializes the user interface
57void ui_init(void); 51void ui_init(void);
58 52