From 79742c5d24929442175953c796a1834e45a93d0d Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Wed, 26 May 2010 06:59:55 +0000
Subject: [PATCH] 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.

---
 .../XPLAINBridge/Lib/LightweightRingBuff.h    | 13 ++--
 Projects/XPLAINBridge/Lib/SoftUART.c          | 61 ++++++++-----------
 Projects/XPLAINBridge/Lib/SoftUART.h          | 20 +-----
 Projects/XPLAINBridge/XPLAINBridge.c          | 12 +---
 Projects/XPLAINBridge/XPLAINBridge.h          |  4 +-
 5 files changed, 42 insertions(+), 68 deletions(-)

diff --git a/Projects/XPLAINBridge/Lib/LightweightRingBuff.h b/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
index 16e890c07..31430ddd4 100644
--- a/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
+++ b/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
@@ -53,13 +53,15 @@
 			RingBuff_Data_t  Buffer[BUFFER_SIZE];
 			RingBuff_Data_t* In;
 			RingBuff_Data_t* Out;
+			uint8_t          Count;
 		} RingBuff_t;
 	
 	/* Inline Functions: */
 		static inline void RingBuffer_InitBuffer(RingBuff_t* const 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)
@@ -68,6 +70,8 @@
 		
 			if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->In = Buffer->Buffer;
+			  
+			Buffer->Count++;
 		}
 
 		static inline RingBuff_Data_t RingBuffer_Remove(RingBuff_t* const Buffer)
@@ -77,12 +81,9 @@
 			if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->Out = Buffer->Buffer;
 			  
-			return Data;
-		}
+			Buffer->Count--;
 
-		static inline bool RingBuffer_Empty(RingBuff_t* const Buffer)
-		{
-			return (Buffer->In == Buffer->Out);
+			return Data;
 		}
 
 #endif
diff --git a/Projects/XPLAINBridge/Lib/SoftUART.c b/Projects/XPLAINBridge/Lib/SoftUART.c
index 5e589f3d7..18d5c01bd 100644
--- a/Projects/XPLAINBridge/Lib/SoftUART.c
+++ b/Projects/XPLAINBridge/Lib/SoftUART.c
@@ -30,27 +30,16 @@
   this software.
 */
 
-#include "SoftUART.h"
-
-volatile bool    srx_done;
-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);
+/** \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.
+ */
 
-	stx_data  = ~Byte;
-	stx_count = 10;
-}
-
-uint8_t SoftUART_RxByte(void)
-{
-	while (!(srx_done));
-	srx_done = false;
+#include "SoftUART.h"
 
-	return srx_data;
-}
+static uint8_t TX_BitsRemaining, TX_Data, RX_BitMask, RX_Data;
 
 void SoftUART_Init(void)
 {
@@ -61,8 +50,7 @@ void SoftUART_Init(void)
 	EICRA  = (1 << ISC01);					// -ve edge
 	EIMSK  = (1 << INT0);					// enable INT0 interrupt
 
-	stx_count = 0;							// nothing to send
-	srx_done  = false;						// nothing received
+	TX_BitsRemaining = 0;					// nothing to send
 	STXPORT |= (1 << STX);					// TX output
 	STXDDR  |= (1 << STX);					// TX output
 	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
 
-	srx_tmp  = 0;							// clear bit storage
-	srx_mask = 1;							// bit mask
+	RX_Data    = 0;							// clear bit storage
+	RX_BitMask = (1 << 0);					// bit mask
 
 	TIFR2 = (1 << OCF2A);					// clear pending interrupt
 
@@ -88,19 +76,19 @@ ISR(INT0_vect)
 /* ISR to manage the reception of bits to the transmitter. */
 ISR(TIMER2_COMPA_vect)
 {
-	if (srx_mask)
+	if (RX_BitMask)
 	{
 		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
 	}
 	else
 	{
-		srx_done  = true;					// mark rx data valid
-		srx_data  = srx_tmp;				// store rx data
+		RingBuffer_Insert(&UARTtoUSB_Buffer, RX_Data);
+
 		TIMSK2    = (1 << OCIE2B);			// enable tx and wait for start
 		EIMSK    |= (1 << INT0);			// enable START irq
 		EIFR      = (1 << INTF0);			// clear any pending
@@ -112,20 +100,25 @@ ISR(TIMER2_COMPB_vect)
 {
 	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
-			  TCCR2A = (1 << COM2B1) | (1 << COM2B0);
-			else
+			if (TX_Data & (1 << 0))			// test inverted data
 			  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
 		{
 			TCCR2A = (1 << COM2B1);			// START bit
 		}
 	}
+	else if (USBtoUART_Buffer.Count)
+	{
+		TX_Data = ~RingBuffer_Remove(&USBtoUART_Buffer);
+		TX_BitsRemaining = 10;
+	}
 } 
diff --git a/Projects/XPLAINBridge/Lib/SoftUART.h b/Projects/XPLAINBridge/Lib/SoftUART.h
index 416490d8d..e54d4a9ae 100644
--- a/Projects/XPLAINBridge/Lib/SoftUART.h
+++ b/Projects/XPLAINBridge/Lib/SoftUART.h
@@ -37,6 +37,9 @@
 		#include <avr/io.h>
 		#include <avr/interrupt.h>
 		#include <stdbool.h>
+		
+		#include "../XPLAINBridge.h"
+		#include "LightweightRingBuff.h"
 
 	/* Macros: */
 		#define BAUD       9600
@@ -50,24 +53,7 @@
 		#define STXPORT    PORTD
 		#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: */
-		void    SoftUART_TxByte(uint8_t c);
-		uint8_t SoftUART_RxByte(void);
 		void    SoftUART_Init(void);
 
 #endif
\ No newline at end of file
diff --git a/Projects/XPLAINBridge/XPLAINBridge.c b/Projects/XPLAINBridge/XPLAINBridge.c
index 5798c21a5..d92e2b493 100644
--- a/Projects/XPLAINBridge/XPLAINBridge.c
+++ b/Projects/XPLAINBridge/XPLAINBridge.c
@@ -125,17 +125,9 @@ void USARTBridge_Task(void)
 	  RingBuffer_Insert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
 	
 	/* 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));
-	
-	/* 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);
 }
 
diff --git a/Projects/XPLAINBridge/XPLAINBridge.h b/Projects/XPLAINBridge/XPLAINBridge.h
index ddb5b0e0c..72e90463d 100644
--- a/Projects/XPLAINBridge/XPLAINBridge.h
+++ b/Projects/XPLAINBridge/XPLAINBridge.h
@@ -77,7 +77,9 @@
 		#define MODE_PDI_PROGRAMMER      true
 
 	/* External Variables: */
-		extern bool CurrentFirmwareMode;
+		extern bool       CurrentFirmwareMode;
+		extern RingBuff_t UARTtoUSB_Buffer;
+		extern RingBuff_t USBtoUART_Buffer;
 		
 	/* Function Prototypes: */
 		void SetupHardware(void);
-- 
GitLab