core: lufa: Fix console output and init sequence
console_putc:
Linux: works very well in general
Windows: also works very well and connection seems to be faster than Linux
Mac: to be: confirmed
NOTE: long session of matrix_print still blocks keyboard_task in main loop
and prevents it from sending keyboard report.
XT protocol buffer overflow occurs when slamng on keys
TODO: check when print functions are called in ISR
This commit is contained in:
parent
6632802c79
commit
ffb52ab0c9
1 changed files with 98 additions and 120 deletions
|
|
@ -43,6 +43,7 @@
|
|||
#include "action.h"
|
||||
#include "led.h"
|
||||
#include "sendchar.h"
|
||||
#include "ringbuf.h"
|
||||
#include "debug.h"
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
#include "sleep_led.h"
|
||||
|
|
@ -89,60 +90,97 @@ host_driver_t lufa_driver = {
|
|||
* Console
|
||||
******************************************************************************/
|
||||
#ifdef CONSOLE_ENABLE
|
||||
static void Console_Task(void)
|
||||
#define SENDBUF_SIZE 256
|
||||
static uint8_t sbuf[SENDBUF_SIZE];
|
||||
static ringbuf_t sendbuf = {
|
||||
.buffer = sbuf,
|
||||
.head = 0,
|
||||
.tail = 0,
|
||||
.size_mask = SENDBUF_SIZE - 1
|
||||
};
|
||||
|
||||
static bool console_putc(uint8_t c)
|
||||
{
|
||||
// return immediately if called while interrupt
|
||||
if (!(SREG & (1<<SREG_I)))
|
||||
goto EXIT;;
|
||||
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
goto EXIT;;
|
||||
|
||||
uint8_t ep = Endpoint_GetCurrentEndpoint();
|
||||
|
||||
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
|
||||
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
|
||||
goto EXIT_RESTORE_EP;
|
||||
}
|
||||
|
||||
// write from buffer to endpoint bank
|
||||
while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
|
||||
Endpoint_Write_8(ringbuf_get(&sendbuf));
|
||||
|
||||
// clear bank when it is full
|
||||
if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
}
|
||||
|
||||
// write c to bank directly if there is no others in buffer
|
||||
if (ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
|
||||
Endpoint_Write_8(c);
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
return true;
|
||||
}
|
||||
|
||||
EXIT_RESTORE_EP:
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
EXIT:
|
||||
return ringbuf_put(&sendbuf, c);
|
||||
}
|
||||
|
||||
static void console_flush(void)
|
||||
{
|
||||
/* Device must be connected and configured for the task to run */
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
||||
uint8_t ep = Endpoint_GetCurrentEndpoint();
|
||||
|
||||
#if 0
|
||||
// TODO: impl receivechar()/recvchar()
|
||||
Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
|
||||
|
||||
/* Check to see if a packet has been sent from the host */
|
||||
if (Endpoint_IsOUTReceived())
|
||||
{
|
||||
/* Check to see if the packet contains data */
|
||||
if (Endpoint_IsReadWriteAllowed())
|
||||
{
|
||||
/* Create a temporary buffer to hold the read in report from the host */
|
||||
uint8_t ConsoleData[CONSOLE_EPSIZE];
|
||||
|
||||
/* Read Console Report Data */
|
||||
Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
|
||||
|
||||
/* Process Console Report Data */
|
||||
//ProcessConsoleHIDReport(ConsoleData);
|
||||
}
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IN packet */
|
||||
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
|
||||
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
return;
|
||||
}
|
||||
|
||||
// fill empty bank
|
||||
while (Endpoint_IsReadWriteAllowed())
|
||||
Endpoint_Write_8(0);
|
||||
// write from buffer to endpoint bank
|
||||
while (!ringbuf_is_empty(&sendbuf) && Endpoint_IsReadWriteAllowed()) {
|
||||
Endpoint_Write_8(ringbuf_get(&sendbuf));
|
||||
|
||||
// flash senchar packet
|
||||
if (Endpoint_IsINReady()) {
|
||||
// clear bank when it is full
|
||||
if (!Endpoint_IsReadWriteAllowed() && Endpoint_IsINReady()) {
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
}
|
||||
|
||||
// clear bank when there are chars in bank
|
||||
if (Endpoint_BytesInEndpoint() && Endpoint_IsINReady()) {
|
||||
// Windows needs to fill packet with 0
|
||||
while (Endpoint_IsReadWriteAllowed()) {
|
||||
Endpoint_Write_8(0);
|
||||
}
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
}
|
||||
#else
|
||||
static void Console_Task(void)
|
||||
|
||||
static void console_task(void)
|
||||
{
|
||||
static uint16_t fn = 0;
|
||||
if (fn == USB_Device_GetFrameNumber()) {
|
||||
return;
|
||||
}
|
||||
fn = USB_Device_GetFrameNumber();
|
||||
console_flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -205,24 +243,10 @@ void EVENT_USB_Device_WakeUp()
|
|||
hook_usb_wakeup();
|
||||
}
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
static bool console_flush = false;
|
||||
#define CONSOLE_FLUSH_SET(b) do { \
|
||||
uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
|
||||
} while (0)
|
||||
|
||||
// called every 1ms
|
||||
void EVENT_USB_Device_StartOfFrame(void)
|
||||
{
|
||||
static uint8_t count;
|
||||
if (++count % 50) return;
|
||||
count = 0;
|
||||
|
||||
if (!console_flush) return;
|
||||
Console_Task();
|
||||
console_flush = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Event handler for the USB_ConfigurationChanged event.
|
||||
* This is fired when the host sets the current configuration of the USB device after enumeration.
|
||||
|
|
@ -419,7 +443,7 @@ static uint8_t keyboard_leds(void)
|
|||
|
||||
static void send_keyboard(report_keyboard_t *report)
|
||||
{
|
||||
uint8_t timeout = 255;
|
||||
uint8_t timeout = 128;
|
||||
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return;
|
||||
|
|
@ -531,72 +555,21 @@ static void send_consumer(uint16_t data)
|
|||
* sendchar
|
||||
******************************************************************************/
|
||||
#ifdef CONSOLE_ENABLE
|
||||
#define SEND_TIMEOUT 5
|
||||
int8_t sendchar(uint8_t c)
|
||||
{
|
||||
#ifdef LUFA_DEBUG_SUART
|
||||
#ifdef LUFA_DEBUG_SUART
|
||||
xmit(c);
|
||||
#endif
|
||||
// Not wait once timeouted.
|
||||
// Because sendchar() is called so many times, waiting each call causes big lag.
|
||||
static bool timeouted = false;
|
||||
#endif
|
||||
|
||||
// prevents Console_Task() from running during sendchar() runs.
|
||||
// or char will be lost. These two function is mutually exclusive.
|
||||
CONSOLE_FLUSH_SET(false);
|
||||
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
return -1;
|
||||
|
||||
uint8_t ep = Endpoint_GetCurrentEndpoint();
|
||||
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
|
||||
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
if (timeouted && !Endpoint_IsReadWriteAllowed()) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
|
||||
timeouted = false;
|
||||
|
||||
uint8_t timeout = SEND_TIMEOUT;
|
||||
while (!Endpoint_IsReadWriteAllowed()) {
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
if (Endpoint_IsStalled()) {
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
if (!(timeout--)) {
|
||||
timeouted = true;
|
||||
goto ERROR_EXIT;
|
||||
}
|
||||
_delay_ms(1);
|
||||
}
|
||||
|
||||
Endpoint_Write_8(c);
|
||||
|
||||
// send when bank is full
|
||||
if (!Endpoint_IsReadWriteAllowed()) {
|
||||
while (!(Endpoint_IsINReady()));
|
||||
Endpoint_ClearIN();
|
||||
} else {
|
||||
CONSOLE_FLUSH_SET(true);
|
||||
}
|
||||
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
return 0;
|
||||
ERROR_EXIT:
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
return -1;
|
||||
bool r = console_putc(c);
|
||||
return (r ? 0 : -1);
|
||||
}
|
||||
#else
|
||||
int8_t sendchar(uint8_t c)
|
||||
{
|
||||
#ifdef LUFA_DEBUG_SUART
|
||||
#ifdef LUFA_DEBUG_SUART
|
||||
xmit(c);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -622,7 +595,6 @@ static void setup_usb(void)
|
|||
|
||||
USB_Init();
|
||||
|
||||
// for Console_Task
|
||||
USB_Device_EnableSOFEvents();
|
||||
}
|
||||
|
||||
|
|
@ -635,15 +607,22 @@ int main(void)
|
|||
SUART_OUT_DDR |= (1<<SUART_OUT_BIT);
|
||||
SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
|
||||
#endif
|
||||
print_set_sendchar(sendchar);
|
||||
print("\r\ninit\n");
|
||||
|
||||
// setup sendchar: DO NOT USE print functions before this line
|
||||
print_set_sendchar(sendchar);
|
||||
host_set_driver(&lufa_driver);
|
||||
|
||||
print("Keyboard init.\n");
|
||||
hook_early_init();
|
||||
keyboard_setup();
|
||||
setup_usb();
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_init();
|
||||
#endif
|
||||
|
||||
sei();
|
||||
|
||||
/* wait for USB startup & debug output */
|
||||
/* wait for USB startup */
|
||||
while (USB_DeviceState != DEVICE_STATE_Configured) {
|
||||
#if defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
;
|
||||
|
|
@ -652,8 +631,11 @@ int main(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
keyboard_init();
|
||||
|
||||
/* wait for Console startup */
|
||||
// TODO: long delay often works anyhoo but proper startup would be better
|
||||
// 1000ms delay of hid_listen may affect this
|
||||
uint16_t delay = 2000;
|
||||
while (delay--) {
|
||||
#ifndef INTERRUPT_CONTROL_ENDPOINT
|
||||
|
|
@ -662,17 +644,9 @@ int main(void)
|
|||
_delay_ms(1);
|
||||
}
|
||||
|
||||
print("USB configured.\n");
|
||||
|
||||
/* init modules */
|
||||
keyboard_init();
|
||||
host_set_driver(&lufa_driver);
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
sleep_led_init();
|
||||
#endif
|
||||
hook_late_init();
|
||||
|
||||
print("Keyboard start.\n");
|
||||
hook_late_init();
|
||||
while (1) {
|
||||
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||
#ifdef LUFA_DEBUG
|
||||
|
|
@ -683,6 +657,10 @@ int main(void)
|
|||
|
||||
keyboard_task();
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
console_task();
|
||||
#endif
|
||||
|
||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_USBTask();
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue