USB Suspend for arm_atsam protocol
Rewrote USB state tracking for implementation of suspend state. Updated suspend.c in entirety. Main subtasks (generally hardware related) are now run prior to keyboard task.anne_pro
parent
563fe23e53
commit
cec203ea80
|
|
@ -1,17 +1,85 @@
|
||||||
/* Copyright 2017 Fred Sundvik
|
#include "matrix.h"
|
||||||
|
#include "i2c_master.h"
|
||||||
|
#include "led_matrix.h"
|
||||||
|
#include "suspend.h"
|
||||||
|
|
||||||
|
/** \brief Suspend idle
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* FIXME: needs doc
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
void suspend_idle(uint8_t time) {
|
||||||
|
/* Note: Not used anywhere currently */
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Run user level Power down
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void suspend_power_down_user (void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Run keyboard level Power down
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void suspend_power_down_kb(void) {
|
||||||
|
suspend_power_down_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Suspend power down
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
void suspend_power_down(void)
|
||||||
|
{
|
||||||
|
I2C3733_Control_Set(0); //Disable LED driver
|
||||||
|
|
||||||
|
suspend_power_down_kb();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak)) void matrix_power_up(void) {}
|
||||||
|
__attribute__ ((weak)) void matrix_power_down(void) {}
|
||||||
|
bool suspend_wakeup_condition(void) {
|
||||||
|
matrix_power_up();
|
||||||
|
matrix_scan();
|
||||||
|
matrix_power_down();
|
||||||
|
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
|
||||||
|
if (matrix_get_row(r)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief run user level code immediately after wakeup
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void suspend_wakeup_init_user(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief run keyboard level code immediately after wakeup
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void suspend_wakeup_init_kb(void) {
|
||||||
|
suspend_wakeup_init_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief run immediately after wakeup
|
||||||
|
*
|
||||||
|
* FIXME: needs doc
|
||||||
|
*/
|
||||||
|
void suspend_wakeup_init(void) {
|
||||||
|
/* If LEDs are set to enabled, enable the hardware */
|
||||||
|
if (led_enabled) {
|
||||||
|
I2C3733_Control_Set(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend_wakeup_init_kb();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -261,8 +261,9 @@ uint8_t I2C3733_Init_Control(void)
|
||||||
{
|
{
|
||||||
DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
|
DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
|
||||||
|
|
||||||
srdata.bit.SDB_N = 1;
|
//Hardware state shutdown on boot
|
||||||
SPI_WriteSRData();
|
//USB state machine will enable driver when communication is ready
|
||||||
|
I2C3733_Control_Set(0);
|
||||||
|
|
||||||
CLK_delay_ms(1);
|
CLK_delay_ms(1);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
//From keyboard's directory
|
//From keyboard's directory
|
||||||
#include "config_led.h"
|
#include "config_led.h"
|
||||||
|
|
||||||
|
uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes
|
||||||
|
|
||||||
void main_subtasks(void);
|
void main_subtasks(void);
|
||||||
uint8_t keyboard_leds(void);
|
uint8_t keyboard_leds(void);
|
||||||
void send_keyboard(report_keyboard_t *report);
|
void send_keyboard(report_keyboard_t *report);
|
||||||
|
|
@ -62,12 +64,6 @@ void send_keyboard(report_keyboard_t *report)
|
||||||
{
|
{
|
||||||
uint32_t irqflags;
|
uint32_t irqflags;
|
||||||
|
|
||||||
if (usb_state == USB_STATE_POWERDOWN)
|
|
||||||
{
|
|
||||||
udc_remotewakeup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NKRO_ENABLE
|
#ifdef NKRO_ENABLE
|
||||||
if (!keymap_config.nkro)
|
if (!keymap_config.nkro)
|
||||||
{
|
{
|
||||||
|
|
@ -161,41 +157,56 @@ void send_consumer(uint16_t data)
|
||||||
#endif //EXTRAKEY_ENABLE
|
#endif //EXTRAKEY_ENABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t g_drvid;
|
|
||||||
uint8_t g_usb_sleeping = 0;
|
|
||||||
|
|
||||||
void main_subtask_usb_state(void)
|
void main_subtask_usb_state(void)
|
||||||
{
|
{
|
||||||
if (usb_state == USB_STATE_POWERDOWN)
|
static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
|
||||||
|
uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register
|
||||||
|
|
||||||
|
if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED
|
||||||
{
|
{
|
||||||
if (!g_usb_sleeping)
|
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||||
|
|
||||||
|
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If previously not SUSPENDED
|
||||||
{
|
{
|
||||||
g_usb_sleeping = 1;
|
suspend_power_down(); //Run suspend routine
|
||||||
if (led_enabled)
|
g_usb_state = fsmstate_now; //Save current USB state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //Else if USB SLEEPING
|
||||||
{
|
{
|
||||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||||
|
|
||||||
|
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //If previously not SLEEPING
|
||||||
{
|
{
|
||||||
I2C3733_Control_Set(0);
|
suspend_power_down(); //Run suspend routine
|
||||||
|
g_usb_state = fsmstate_now; //Save current USB state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_ON_Val) //Else if USB ON
|
||||||
|
{
|
||||||
|
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) //If previously not ON
|
||||||
|
{
|
||||||
|
if (fsmstate_on_delay == 0) //If ON delay timer is cleared
|
||||||
|
{
|
||||||
|
fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer
|
||||||
|
}
|
||||||
|
else if (CLK_get_ms() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
|
||||||
|
{
|
||||||
|
suspend_wakeup_init(); //Run wakeup routine
|
||||||
|
g_usb_state = fsmstate_now; //Save current USB state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else //Else if USB is in a state not being tracked
|
||||||
else if (g_usb_sleeping)
|
|
||||||
{
|
{
|
||||||
g_usb_sleeping = 0;
|
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||||
if (led_enabled)
|
|
||||||
{
|
|
||||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
|
||||||
{
|
|
||||||
I2C3733_Control_Set(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_subtask_led(void)
|
void main_subtask_led(void)
|
||||||
{
|
{
|
||||||
if (g_usb_sleeping) return;
|
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) return; //Only run LED tasks if USB is operating
|
||||||
|
|
||||||
led_matrix_task();
|
led_matrix_task();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,8 +286,8 @@ int main(void)
|
||||||
|
|
||||||
i2c_led_q_init();
|
i2c_led_q_init();
|
||||||
|
|
||||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
for (uint8_t drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++)
|
||||||
I2C_LED_Q_ONOFF(g_drvid); //Queue data
|
I2C_LED_Q_ONOFF(drvid); //Queue data
|
||||||
|
|
||||||
keyboard_setup();
|
keyboard_setup();
|
||||||
|
|
||||||
|
|
@ -294,10 +305,21 @@ int main(void)
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
keyboard_task();
|
|
||||||
|
|
||||||
main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
|
main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
|
||||||
|
|
||||||
|
if (g_usb_state == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val || g_usb_state == USB_FSMSTATUS_FSMSTATE_SLEEP_Val)
|
||||||
|
{
|
||||||
|
if (suspend_wakeup_condition())
|
||||||
|
{
|
||||||
|
udc_remotewakeup(); //Send remote wakeup signal
|
||||||
|
wait_ms(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard_task();
|
||||||
|
|
||||||
#ifdef CONSOLE_ENABLE
|
#ifdef CONSOLE_ENABLE
|
||||||
if (CLK_get_ms() > next_print)
|
if (CLK_get_ms() > next_print)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,6 @@
|
||||||
#include "samd51j18a.h"
|
#include "samd51j18a.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
volatile uint8_t usb_state;
|
|
||||||
|
|
||||||
//! Sequence process running each \c SEQUENCE_PERIOD ms
|
//! Sequence process running each \c SEQUENCE_PERIOD ms
|
||||||
#define SEQUENCE_PERIOD 150
|
#define SEQUENCE_PERIOD 150
|
||||||
|
|
||||||
|
|
@ -72,12 +70,12 @@ static void ui_wakeup_handler(void)
|
||||||
|
|
||||||
void ui_init(void)
|
void ui_init(void)
|
||||||
{
|
{
|
||||||
usb_state = USB_STATE_POWERUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_powerdown(void)
|
void ui_powerdown(void)
|
||||||
{
|
{
|
||||||
usb_state = USB_STATE_POWERDOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_wakeup_enable(void)
|
void ui_wakeup_enable(void)
|
||||||
|
|
@ -92,7 +90,7 @@ void ui_wakeup_disable(void)
|
||||||
|
|
||||||
void ui_wakeup(void)
|
void ui_wakeup(void)
|
||||||
{
|
{
|
||||||
usb_state = USB_STATE_POWERUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_process(uint16_t framenumber)
|
void ui_process(uint16_t framenumber)
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,6 @@
|
||||||
#ifndef _UI_H_
|
#ifndef _UI_H_
|
||||||
#define _UI_H_
|
#define _UI_H_
|
||||||
|
|
||||||
extern volatile uint8_t usb_state;
|
|
||||||
|
|
||||||
#define USB_STATE_UNKNOWN 0
|
|
||||||
#define USB_STATE_POWERDOWN 1
|
|
||||||
#define USB_STATE_POWERUP 2
|
|
||||||
|
|
||||||
//! \brief Initializes the user interface
|
//! \brief Initializes the user interface
|
||||||
void ui_init(void);
|
void ui_init(void);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue