mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-16 12:51:47 +00:00
Make software USART used in the XPLAINBridge project directly check and store into the ring buffers, rather than polling from the main program loop to avoid added latency.
This commit is contained in:
parent
9b29d1dc50
commit
79742c5d24
@ -53,13 +53,15 @@
|
|||||||
RingBuff_Data_t Buffer[BUFFER_SIZE];
|
RingBuff_Data_t Buffer[BUFFER_SIZE];
|
||||||
RingBuff_Data_t* In;
|
RingBuff_Data_t* In;
|
||||||
RingBuff_Data_t* Out;
|
RingBuff_Data_t* Out;
|
||||||
|
uint8_t Count;
|
||||||
} RingBuff_t;
|
} RingBuff_t;
|
||||||
|
|
||||||
/* Inline Functions: */
|
/* Inline Functions: */
|
||||||
static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
|
static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
|
||||||
{
|
{
|
||||||
Buffer->In = Buffer->Buffer;
|
Buffer->In = Buffer->Buffer;
|
||||||
Buffer->Out = Buffer->Buffer;
|
Buffer->Out = Buffer->Buffer;
|
||||||
|
Buffer->Count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void RingBuffer_Insert(RingBuff_t* const Buffer, RingBuff_Data_t Data)
|
static inline void RingBuffer_Insert(RingBuff_t* const Buffer, RingBuff_Data_t Data)
|
||||||
@ -68,6 +70,8 @@
|
|||||||
|
|
||||||
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
|
if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
|
||||||
Buffer->In = Buffer->Buffer;
|
Buffer->In = Buffer->Buffer;
|
||||||
|
|
||||||
|
Buffer->Count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
|
static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
|
||||||
@ -77,12 +81,9 @@
|
|||||||
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
|
if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
|
||||||
Buffer->Out = Buffer->Buffer;
|
Buffer->Out = Buffer->Buffer;
|
||||||
|
|
||||||
return Data;
|
Buffer->Count--;
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool RingBuffer_Empty(RingBuff_t* const Buffer)
|
return Data;
|
||||||
{
|
|
||||||
return (Buffer->In == Buffer->Out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,27 +30,16 @@
|
|||||||
this software.
|
this software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* Software UART for both data transmission and reception. This
|
||||||
|
* code continuously monitors the ring buffers set up by the main
|
||||||
|
* project source file and reads/writes data as it becomes available.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "SoftUART.h"
|
#include "SoftUART.h"
|
||||||
|
|
||||||
volatile bool srx_done;
|
static uint8_t TX_BitsRemaining, TX_Data, RX_BitMask, RX_Data;
|
||||||
volatile uint8_t stx_count;
|
|
||||||
static uint8_t srx_data, srx_mask, srx_tmp, stx_data;
|
|
||||||
|
|
||||||
void SoftUART_TxByte(uint8_t Byte)
|
|
||||||
{
|
|
||||||
while (stx_count);
|
|
||||||
|
|
||||||
stx_data = ~Byte;
|
|
||||||
stx_count = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t SoftUART_RxByte(void)
|
|
||||||
{
|
|
||||||
while (!(srx_done));
|
|
||||||
srx_done = false;
|
|
||||||
|
|
||||||
return srx_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftUART_Init(void)
|
void SoftUART_Init(void)
|
||||||
{
|
{
|
||||||
@ -61,8 +50,7 @@ void SoftUART_Init(void)
|
|||||||
EICRA = (1 << ISC01); // -ve edge
|
EICRA = (1 << ISC01); // -ve edge
|
||||||
EIMSK = (1 << INT0); // enable INT0 interrupt
|
EIMSK = (1 << INT0); // enable INT0 interrupt
|
||||||
|
|
||||||
stx_count = 0; // nothing to send
|
TX_BitsRemaining = 0; // nothing to send
|
||||||
srx_done = false; // nothing received
|
|
||||||
STXPORT |= (1 << STX); // TX output
|
STXPORT |= (1 << STX); // TX output
|
||||||
STXDDR |= (1 << STX); // TX output
|
STXDDR |= (1 << STX); // TX output
|
||||||
SRXPORT |= (1 << SRX); // pullup on INT0
|
SRXPORT |= (1 << SRX); // pullup on INT0
|
||||||
@ -73,8 +61,8 @@ ISR(INT0_vect)
|
|||||||
{
|
{
|
||||||
OCR2A = TCNT2 + (BIT_TIME / 8 * 3 / 2); // scan 1.5 bits after start
|
OCR2A = TCNT2 + (BIT_TIME / 8 * 3 / 2); // scan 1.5 bits after start
|
||||||
|
|
||||||
srx_tmp = 0; // clear bit storage
|
RX_Data = 0; // clear bit storage
|
||||||
srx_mask = 1; // bit mask
|
RX_BitMask = (1 << 0); // bit mask
|
||||||
|
|
||||||
TIFR2 = (1 << OCF2A); // clear pending interrupt
|
TIFR2 = (1 << OCF2A); // clear pending interrupt
|
||||||
|
|
||||||
@ -88,19 +76,19 @@ ISR(INT0_vect)
|
|||||||
/* ISR to manage the reception of bits to the transmitter. */
|
/* ISR to manage the reception of bits to the transmitter. */
|
||||||
ISR(TIMER2_COMPA_vect)
|
ISR(TIMER2_COMPA_vect)
|
||||||
{
|
{
|
||||||
if (srx_mask)
|
if (RX_BitMask)
|
||||||
{
|
{
|
||||||
if (SRXPIN & (1 << SRX))
|
if (SRXPIN & (1 << SRX))
|
||||||
srx_tmp |= srx_mask;
|
RX_Data |= RX_BitMask;
|
||||||
|
|
||||||
srx_mask <<= 1;
|
RX_BitMask <<= 1;
|
||||||
|
|
||||||
OCR2A += BIT_TIME / 8; // next bit slice
|
OCR2A += BIT_TIME / 8; // next bit slice
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
srx_done = true; // mark rx data valid
|
RingBuffer_Insert(&UARTtoUSB_Buffer, RX_Data);
|
||||||
srx_data = srx_tmp; // store rx data
|
|
||||||
TIMSK2 = (1 << OCIE2B); // enable tx and wait for start
|
TIMSK2 = (1 << OCIE2B); // enable tx and wait for start
|
||||||
EIMSK |= (1 << INT0); // enable START irq
|
EIMSK |= (1 << INT0); // enable START irq
|
||||||
EIFR = (1 << INTF0); // clear any pending
|
EIFR = (1 << INTF0); // clear any pending
|
||||||
@ -112,20 +100,25 @@ ISR(TIMER2_COMPB_vect)
|
|||||||
{
|
{
|
||||||
OCR2B += BIT_TIME / 8; // next bit slice
|
OCR2B += BIT_TIME / 8; // next bit slice
|
||||||
|
|
||||||
if (stx_count)
|
if (TX_BitsRemaining)
|
||||||
{
|
{
|
||||||
if (--stx_count != 9) // no start bit
|
if (--TX_BitsRemaining != 9) // no start bit
|
||||||
{
|
{
|
||||||
if (!(stx_data & 1)) // test inverted data
|
if (TX_Data & (1 << 0)) // test inverted data
|
||||||
TCCR2A = (1 << COM2B1) | (1 << COM2B0);
|
|
||||||
else
|
|
||||||
TCCR2A = (1 << COM2B1);
|
TCCR2A = (1 << COM2B1);
|
||||||
|
else
|
||||||
|
TCCR2A = (1 << COM2B1) | (1 << COM2B0);
|
||||||
|
|
||||||
stx_data >>= 1; // shift zero in from left
|
TX_Data >>= 1; // shift zero in from left
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TCCR2A = (1 << COM2B1); // START bit
|
TCCR2A = (1 << COM2B1); // START bit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (USBtoUART_Buffer.Count)
|
||||||
|
{
|
||||||
|
TX_Data = ~RingBuffer_Remove(&USBtoUART_Buffer);
|
||||||
|
TX_BitsRemaining = 10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,9 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "../XPLAINBridge.h"
|
||||||
|
#include "LightweightRingBuff.h"
|
||||||
|
|
||||||
/* Macros: */
|
/* Macros: */
|
||||||
#define BAUD 9600
|
#define BAUD 9600
|
||||||
@ -50,24 +53,7 @@
|
|||||||
#define STXPORT PORTD
|
#define STXPORT PORTD
|
||||||
#define STXDDR DDRD
|
#define STXDDR DDRD
|
||||||
|
|
||||||
/* External Variables: */
|
|
||||||
extern volatile bool srx_done;
|
|
||||||
extern volatile uint8_t stx_count;
|
|
||||||
|
|
||||||
/* Inline Functions: */
|
|
||||||
static inline bool SoftUART_IsReady(void)
|
|
||||||
{
|
|
||||||
return !(stx_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool SoftUART_IsReceived(void)
|
|
||||||
{
|
|
||||||
return srx_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Function Prototypes: */
|
/* Function Prototypes: */
|
||||||
void SoftUART_TxByte(uint8_t c);
|
|
||||||
uint8_t SoftUART_RxByte(void);
|
|
||||||
void SoftUART_Init(void);
|
void SoftUART_Init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -125,17 +125,9 @@ void USARTBridge_Task(void)
|
|||||||
RingBuffer_Insert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
|
RingBuffer_Insert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
|
||||||
|
|
||||||
/* Read bytes from the UART receive buffer into the USB IN endpoint */
|
/* Read bytes from the UART receive buffer into the USB IN endpoint */
|
||||||
if (!(RingBuffer_Empty(&UARTtoUSB_Buffer)))
|
if (UARTtoUSB_Buffer.Count)
|
||||||
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
|
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
|
||||||
|
|
||||||
/* Load bytes from the UART transmit buffer into the UART */
|
|
||||||
if (!(RingBuffer_Empty(&USBtoUART_Buffer)) && SoftUART_IsReady())
|
|
||||||
SoftUART_TxByte(RingBuffer_Remove(&USBtoUART_Buffer));
|
|
||||||
|
|
||||||
/* Load bytes from the UART into the UART receive buffer */
|
|
||||||
if (SoftUART_IsReceived())
|
|
||||||
RingBuffer_Insert(&UARTtoUSB_Buffer, SoftUART_RxByte());
|
|
||||||
|
|
||||||
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
|
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@
|
|||||||
#define MODE_PDI_PROGRAMMER true
|
#define MODE_PDI_PROGRAMMER true
|
||||||
|
|
||||||
/* External Variables: */
|
/* External Variables: */
|
||||||
extern bool CurrentFirmwareMode;
|
extern bool CurrentFirmwareMode;
|
||||||
|
extern RingBuff_t UARTtoUSB_Buffer;
|
||||||
|
extern RingBuff_t USBtoUART_Buffer;
|
||||||
|
|
||||||
/* Function Prototypes: */
|
/* Function Prototypes: */
|
||||||
void SetupHardware(void);
|
void SetupHardware(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user