diff options
| -rw-r--r-- | tmk_core/common/arm_atsam/suspend.c | 90 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/i2c_master.c | 5 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/main_arm_atsam.c | 80 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/ui.c | 8 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/usb/ui.h | 6 |
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 | 10 | void 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. | 19 | void suspend_power_down_user (void) { |
| 20 | |||
| 21 | } | ||
| 22 | |||
| 23 | /** \brief Run keyboard level Power down | ||
| 24 | * | ||
| 25 | * FIXME: needs doc | ||
| 26 | */ | ||
| 27 | __attribute__ ((weak)) | ||
| 28 | void suspend_power_down_kb(void) { | ||
| 29 | suspend_power_down_user(); | ||
| 30 | } | ||
| 31 | |||
| 32 | /** \brief Suspend power down | ||
| 33 | * | ||
| 34 | * FIXME: needs doc | ||
| 35 | */ | ||
| 36 | void 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) {} | ||
| 45 | bool 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)) | ||
| 60 | void 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)) | ||
| 69 | void 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 | */ |
| 77 | void 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 | ||
| 34 | uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes | ||
| 35 | |||
| 34 | void main_subtasks(void); | 36 | void main_subtasks(void); |
| 35 | uint8_t keyboard_leds(void); | 37 | uint8_t keyboard_leds(void); |
| 36 | void send_keyboard(report_keyboard_t *report); | 38 | void 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 | ||
| 164 | uint8_t g_drvid; | ||
| 165 | uint8_t g_usb_sleeping = 0; | ||
| 166 | |||
| 167 | void main_subtask_usb_state(void) | 160 | void 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 | ||
| 196 | void main_subtask_led(void) | 206 | void 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 | ||
| 55 | volatile 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 | ||
| 73 | void ui_init(void) | 71 | void ui_init(void) |
| 74 | { | 72 | { |
| 75 | usb_state = USB_STATE_POWERUP; | 73 | |
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | void ui_powerdown(void) | 76 | void ui_powerdown(void) |
| 79 | { | 77 | { |
| 80 | usb_state = USB_STATE_POWERDOWN; | 78 | |
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | void ui_wakeup_enable(void) | 81 | void ui_wakeup_enable(void) |
| @@ -92,7 +90,7 @@ void ui_wakeup_disable(void) | |||
| 92 | 90 | ||
| 93 | void ui_wakeup(void) | 91 | void ui_wakeup(void) |
| 94 | { | 92 | { |
| 95 | usb_state = USB_STATE_POWERUP; | 93 | |
| 96 | } | 94 | } |
| 97 | 95 | ||
| 98 | void ui_process(uint16_t framenumber) | 96 | void 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 | ||
| 50 | extern 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 |
| 57 | void ui_init(void); | 51 | void ui_init(void); |
| 58 | 52 | ||
