diff --git a/LUFA/Drivers/USB/Class/Device/CDC.c b/LUFA/Drivers/USB/Class/Device/CDC.c
index 026ac269af32082dcd68202e1c19cd5e2cd0db14..39154608e46f7b200959970a2f539ccf8477dbf3 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.c
+++ b/LUFA/Drivers/USB/Class/Device/CDC.c
@@ -133,7 +133,7 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
 }
 
 uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
-                              char* const Data,
+                              const char* const Data,
                               const uint16_t Length)
 {
 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
@@ -219,20 +219,21 @@ uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterface
 
 int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
 {
-	uint8_t ReceivedByte = -1;
-
 	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
-	  return 0;
+	  return -1;
+
+	int16_t ReceivedByte = -1;
 
 	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpointNumber);
 	
-	if (!(Endpoint_IsOUTReceived()))
-	  return -1;
-	else if (Endpoint_BytesInEndpoint())
-	  ReceivedByte = Endpoint_Read_Byte();
+	if (Endpoint_IsOUTReceived())
+	{
+		if (Endpoint_BytesInEndpoint())
+		  ReceivedByte = Endpoint_Read_Byte();
 	
-	if (!(Endpoint_BytesInEndpoint()))
-	  Endpoint_ClearOUT();
+		if (!(Endpoint_BytesInEndpoint()))
+		  Endpoint_ClearOUT();
+	}
 	
 	return ReceivedByte;
 }
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h
index 3ada8f7afb2257c19bf1c23403b071a2bd571d4d..1b0b86810a17234167b2e24e56b33ed1787b954b 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.h
+++ b/LUFA/Drivers/USB/Class/Device/CDC.h
@@ -214,7 +214,7 @@
 			 *  \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
 			 */
 			uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
-			                              char* const Data,
+			                              const char* const Data,
 			                              const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
 			
 			/** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.c b/LUFA/Drivers/USB/Class/Host/CDC.c
index 5fb232c099b74d10c2c89427f0c32182a3358734..b9e4c9ebfefc5b90e09716137524248637017a79 100644
--- a/LUFA/Drivers/USB/Class/Host/CDC.c
+++ b/LUFA/Drivers/USB/Class/Host/CDC.c
@@ -205,7 +205,6 @@ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
 	  return;
 	
 	Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber);
-	Pipe_SetPipeToken(PIPE_TOKEN_IN);
 	Pipe_Unfreeze();
 
 	if (Pipe_IsINReceived())
@@ -285,7 +284,7 @@ uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
 }
 
 uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
-                            char* const Data,
+                            const char* const Data,
                             const uint16_t Length)
 {
 	if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
@@ -333,7 +332,6 @@ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
 	  return 0;
 	
 	Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
-	Pipe_SetPipeToken(PIPE_TOKEN_IN);
 	Pipe_Unfreeze();
 
 	if (Pipe_IsINReceived())
@@ -360,25 +358,25 @@ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo
 
 int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
 {
-	uint8_t ReceivedByte = -1;
-
 	if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
-	  return 0;
+	  return -1;
 	  
+	int16_t ReceivedByte = -1;
+
 	Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber);
-	Pipe_SetPipeToken(PIPE_TOKEN_IN);
 	Pipe_Unfreeze();
 
-	if (!(Pipe_IsINReceived()))
-	  return -1;
-	else if (Pipe_BytesInPipe())
-	  ReceivedByte = Pipe_Read_Byte();
+	if (Pipe_IsINReceived())
+	{
+		if (Pipe_BytesInPipe())
+		  ReceivedByte = Pipe_Read_Byte();
 
-	if (!(Pipe_BytesInPipe()))
-	  Pipe_ClearIN();
-		
-	Pipe_Freeze();
+		if (!(Pipe_BytesInPipe()))
+		  Pipe_ClearIN();
+	}
 	
+	Pipe_Freeze();
+
 	return ReceivedByte;
 }
 
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h
index 56bcf3147727f4186180565e1cda3674288cd47c..3e9d055e4512e872eaea055b6a71cc847dacf278 100644
--- a/LUFA/Drivers/USB/Class/Host/CDC.h
+++ b/LUFA/Drivers/USB/Class/Host/CDC.h
@@ -217,7 +217,7 @@
 			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
 			 */
 			uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
-			                            char* const Data,
+			                            const char* const Data,
 			                            const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
 			
 			/** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
diff --git a/LUFA/Drivers/USB/Class/Host/RNDIS.c b/LUFA/Drivers/USB/Class/Host/RNDIS.c
index b189535f004eb1379dbab6b6dc616c4a95fca698..cddd5cbb589e9ee43eff83ff284a308f8ebedd19 100644
--- a/LUFA/Drivers/USB/Class/Host/RNDIS.c
+++ b/LUFA/Drivers/USB/Class/Host/RNDIS.c
@@ -386,12 +386,9 @@ bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfac
 	  return false;
 
 	Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
-	Pipe_SetPipeToken(PIPE_TOKEN_IN);
 	
 	Pipe_Unfreeze();
-
-	PacketWaiting = Pipe_IsINReceived();
-	
+	PacketWaiting = Pipe_IsINReceived();	
 	Pipe_Freeze();
 	
 	return PacketWaiting;
@@ -407,7 +404,6 @@ uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceIn
 	  return PIPE_READYWAIT_DeviceDisconnected;
 
 	Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipeNumber);
-	Pipe_SetPipeToken(PIPE_TOKEN_IN);
 	Pipe_Unfreeze();
 	
 	if (!(Pipe_IsReadWriteAllowed()))
diff --git a/LUFA/ManPages/LUFAPoweredProjects.txt b/LUFA/ManPages/LUFAPoweredProjects.txt
index bc3935302a6b74e035d83cc16f10b2ca49b3900e..abb0e02ddda13bfce505786c09f9ff02d8b66f31 100644
--- a/LUFA/ManPages/LUFAPoweredProjects.txt
+++ b/LUFA/ManPages/LUFAPoweredProjects.txt
@@ -61,6 +61,7 @@
  *  - SD Card reader: http://elasticsheep.com/2010/04/teensy2-usb-mass-storage-with-an-sd-card/
  *  - SEGA Megadrive/Genesis Development Cartridge: http://www.makestuff.eu/wordpress/?page_id=398
  *  - Stripe Snoop, a Magnetic Card reader: http://www.ossguy.com/ss_usb/
+ *  - Touchscreen Input Device: http://capnstech.blogspot.com/2010/07/touchscreen-update.html
  *  - USB Interface for Playstation Portable Devices: http://forums.ps2dev.org/viewtopic.php?t=11001
  *  - Userial, a USB to Serial converter with SPI, I2C and other protocols: http://www.tty1.net/userial/
  *  - XUM1541, a Commodore 64 floppy drive to USB adapter: http://www.root.org/~nate/c64/xum1541/
diff --git a/Projects/Benito/Benito.c b/Projects/Benito/Benito.c
index ac1e064d58c9be1ef9414c9b2c057c463c21438d..88005eeb0a7d67f35e10b7739aa9fa07bb6e21fc 100644
--- a/Projects/Benito/Benito.c
+++ b/Projects/Benito/Benito.c
@@ -127,13 +127,14 @@ int main(void)
 			  LEDs_TurnOffLEDs(LEDMASK_RX);
 
 			/* Check if the receive buffer flush period has expired */
-			if (!(--FlushPeriodRemaining) || (Tx_Buffer.Count > 200))
+			RingBuff_Count_t BufferCount = RingBuffer_GetCount(&Tx_Buffer);
+			if (!(--FlushPeriodRemaining) || (BufferCount > 200))
 			{
 				/* Echo bytes from the target to the host via the virtual serial port */
-				if (Tx_Buffer.Count)
+				if (BufferCount)
 				{
-					while (Tx_Buffer.Count)
-					  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&Tx_Buffer));
+					while (BufferCount--)
+					  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&Tx_Buffer));
 
 					LEDs_TurnOnLEDs(LEDMASK_RX);
 					PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS;
diff --git a/Projects/Benito/Lib/LightweightRingBuff.h b/Projects/Benito/Lib/LightweightRingBuff.h
index 2faef438288eafa71a709b2dabe175858046af1b..cb0f6112a2c50a7f414d4ce2b805b93754a7b7c5 100644
--- a/Projects/Benito/Lib/LightweightRingBuff.h
+++ b/Projects/Benito/Lib/LightweightRingBuff.h
@@ -44,10 +44,19 @@
 
 	/* Defines: */
 		/** Size of each ring buffer, in data elements - must be between 1 and 255. */
-		#define BUFFER_SIZE      255
+		#define BUFFER_SIZE         255
 		
 		/** Type of data to store into the buffer. */
-		#define RingBuff_Data_t  uint8_t
+		#define RingBuff_Data_t     uint8_t
+
+		/** Datatype which may be used to store the count of data stored in a buffer, retrieved
+		 *  via a call to \ref RingBuffer_GetCount().
+		 */
+		#if (BUFFER_SIZE <= 0xFF)
+			#define RingBuff_Count_t   uint8_t
+		#else
+			#define RingBuff_Count_t   uint16_t
+		#endif
 
 	/* Type Defines: */
 		/** Type define for a new ring buffer object. Buffers should be initialized via a call to
@@ -58,11 +67,11 @@
 			RingBuff_Data_t  Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */
 			RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
 			RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
-			uint8_t          Count; /**< Total number of bytes stored in the circular buffer */
+			RingBuff_Count_t Count;
 		} RingBuff_t;
 	
 	/* Inline Functions: */
-		/** Initialises a ring buffer ready for use. Buffers must be initialized via this function
+		/** Initializes a ring buffer ready for use. Buffers must be initialized via this function
 		 *  before any operations are called upon them. Already initialized buffers may be reset
 		 *  by re-initializing them using this function.
 		 *
@@ -70,74 +79,73 @@
 		 */
 		static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
 		{
-			Buffer->In    = Buffer->Buffer;
-			Buffer->Out   = Buffer->Buffer;
-			Buffer->Count = 0;
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->In  = Buffer->Buffer;
+				Buffer->Out = Buffer->Buffer;
+			}
 		}
 		
-		/** Atomically determines if the specified ring buffer contains any free space. This should
-		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
-		 *  buffer overrun.
+		/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
+		 *  by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that
+		 *  the buffer cannot be modified while the computation takes place. This value should be cached
+		 *  when reading out the contents of the buffer, so that as small a time as possible is spent
+		 *  in an atomic lock.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *  \note The value returned by this function is guaranteed to only be the minimum number of bytes
+		 *        stored in the given buffer; this value may change as other threads write new data and so
+		 *        the returned number should be used only to determine how many successive reads may safely
+		 *        be performed on the buffer.
 		 *
-		 *  \return Boolean true if the buffer contains no free space, false otherwise
-		 */		 
-		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+		 *  \param[in] Buffer  Pointer to a ring buffer structure whose count is to be computed
+		 */
+		static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
 		{
-			bool IsFull;
+			RingBuff_Count_t Count;
 			
 			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 			{
-				IsFull = (Buffer->Count == BUFFER_SIZE);
+				Count = Buffer->Count;
 			}
 			
-			return IsFull;
+			return Count;
 		}
 		
-		/** Atomically inserts an element into the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any free space. This should
+		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
+		 *  buffer overrun.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
-		 *  \param[in]     Data    Data element to insert into the buffer
-		 */
-		static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer,
-		                                           const RingBuff_Data_t Data)
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
 		{
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				*Buffer->In = Data;
-			
-				if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->In = Buffer->Buffer;
-				  
-				Buffer->Count++;
-			}
+			return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
 		}
 
-		/** Atomically retrieves an element from the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any data. This should
+		 *  be tested before removing data from the buffer, to ensure that the buffer does not
+		 *  underflow.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
+		 *  If the data is to be removed in a loop, store the total number of bytes stored in the
+		 *  buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
+		 *  to reduce the time spent in atomicity locks.
 		 *
-		 *  \return Next data element stored in the buffer
-		 */
-		static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
+		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
 		{
-			RingBuff_Data_t Data;
-			
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				Data = *Buffer->Out;
-			
-				if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->Out = Buffer->Buffer;
-				  
-				Buffer->Count--;
-			}
-
-			return Data;
+			return (RingBuffer_GetCount(Buffer) == 0);
 		}
 
 		/** Inserts an element into the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may insert into a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
 		 *  \param[in]     Data    Data element to insert into the buffer
@@ -149,11 +157,18 @@
 			
 			if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->In = Buffer->Buffer;
-				  
-			Buffer->Count++;
+
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count++;
+			}
 		}
 
-		/** Retrieves an element from the ring buffer.
+		/** Removes an element from the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may remove from a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
 		 *
@@ -165,11 +180,13 @@
 			
 			if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->Out = Buffer->Buffer;
-				  
-			Buffer->Count--;
 
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count--;
+			}
+			
 			return Data;
 		}
 
 #endif
- 
diff --git a/Projects/USBtoSerial/Lib/LightweightRingBuff.h b/Projects/USBtoSerial/Lib/LightweightRingBuff.h
index 2faef438288eafa71a709b2dabe175858046af1b..cb0f6112a2c50a7f414d4ce2b805b93754a7b7c5 100644
--- a/Projects/USBtoSerial/Lib/LightweightRingBuff.h
+++ b/Projects/USBtoSerial/Lib/LightweightRingBuff.h
@@ -44,10 +44,19 @@
 
 	/* Defines: */
 		/** Size of each ring buffer, in data elements - must be between 1 and 255. */
-		#define BUFFER_SIZE      255
+		#define BUFFER_SIZE         255
 		
 		/** Type of data to store into the buffer. */
-		#define RingBuff_Data_t  uint8_t
+		#define RingBuff_Data_t     uint8_t
+
+		/** Datatype which may be used to store the count of data stored in a buffer, retrieved
+		 *  via a call to \ref RingBuffer_GetCount().
+		 */
+		#if (BUFFER_SIZE <= 0xFF)
+			#define RingBuff_Count_t   uint8_t
+		#else
+			#define RingBuff_Count_t   uint16_t
+		#endif
 
 	/* Type Defines: */
 		/** Type define for a new ring buffer object. Buffers should be initialized via a call to
@@ -58,11 +67,11 @@
 			RingBuff_Data_t  Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */
 			RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
 			RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
-			uint8_t          Count; /**< Total number of bytes stored in the circular buffer */
+			RingBuff_Count_t Count;
 		} RingBuff_t;
 	
 	/* Inline Functions: */
-		/** Initialises a ring buffer ready for use. Buffers must be initialized via this function
+		/** Initializes a ring buffer ready for use. Buffers must be initialized via this function
 		 *  before any operations are called upon them. Already initialized buffers may be reset
 		 *  by re-initializing them using this function.
 		 *
@@ -70,74 +79,73 @@
 		 */
 		static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
 		{
-			Buffer->In    = Buffer->Buffer;
-			Buffer->Out   = Buffer->Buffer;
-			Buffer->Count = 0;
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->In  = Buffer->Buffer;
+				Buffer->Out = Buffer->Buffer;
+			}
 		}
 		
-		/** Atomically determines if the specified ring buffer contains any free space. This should
-		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
-		 *  buffer overrun.
+		/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
+		 *  by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that
+		 *  the buffer cannot be modified while the computation takes place. This value should be cached
+		 *  when reading out the contents of the buffer, so that as small a time as possible is spent
+		 *  in an atomic lock.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *  \note The value returned by this function is guaranteed to only be the minimum number of bytes
+		 *        stored in the given buffer; this value may change as other threads write new data and so
+		 *        the returned number should be used only to determine how many successive reads may safely
+		 *        be performed on the buffer.
 		 *
-		 *  \return Boolean true if the buffer contains no free space, false otherwise
-		 */		 
-		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+		 *  \param[in] Buffer  Pointer to a ring buffer structure whose count is to be computed
+		 */
+		static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
 		{
-			bool IsFull;
+			RingBuff_Count_t Count;
 			
 			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 			{
-				IsFull = (Buffer->Count == BUFFER_SIZE);
+				Count = Buffer->Count;
 			}
 			
-			return IsFull;
+			return Count;
 		}
 		
-		/** Atomically inserts an element into the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any free space. This should
+		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
+		 *  buffer overrun.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
-		 *  \param[in]     Data    Data element to insert into the buffer
-		 */
-		static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer,
-		                                           const RingBuff_Data_t Data)
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
 		{
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				*Buffer->In = Data;
-			
-				if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->In = Buffer->Buffer;
-				  
-				Buffer->Count++;
-			}
+			return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
 		}
 
-		/** Atomically retrieves an element from the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any data. This should
+		 *  be tested before removing data from the buffer, to ensure that the buffer does not
+		 *  underflow.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
+		 *  If the data is to be removed in a loop, store the total number of bytes stored in the
+		 *  buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
+		 *  to reduce the time spent in atomicity locks.
 		 *
-		 *  \return Next data element stored in the buffer
-		 */
-		static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
+		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
 		{
-			RingBuff_Data_t Data;
-			
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				Data = *Buffer->Out;
-			
-				if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->Out = Buffer->Buffer;
-				  
-				Buffer->Count--;
-			}
-
-			return Data;
+			return (RingBuffer_GetCount(Buffer) == 0);
 		}
 
 		/** Inserts an element into the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may insert into a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
 		 *  \param[in]     Data    Data element to insert into the buffer
@@ -149,11 +157,18 @@
 			
 			if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->In = Buffer->Buffer;
-				  
-			Buffer->Count++;
+
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count++;
+			}
 		}
 
-		/** Retrieves an element from the ring buffer.
+		/** Removes an element from the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may remove from a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
 		 *
@@ -165,11 +180,13 @@
 			
 			if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->Out = Buffer->Buffer;
-				  
-			Buffer->Count--;
 
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count--;
+			}
+			
 			return Data;
 		}
 
 #endif
- 
diff --git a/Projects/USBtoSerial/USBtoSerial.c b/Projects/USBtoSerial/USBtoSerial.c
index 4f3fcf524d8a3291095200692d1569da724e95d3..c2ecc7cf4bc134d8dcf26887ada0808792415528 100644
--- a/Projects/USBtoSerial/USBtoSerial.c
+++ b/Projects/USBtoSerial/USBtoSerial.c
@@ -84,21 +84,22 @@ int main(void)
 		/* Read bytes from the USB OUT endpoint into the USART transmit buffer */
 		int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
 		if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUSART_Buffer)))
-		  RingBuffer_AtomicInsert(&USBtoUSART_Buffer, (uint8_t)ReceivedByte);		
+		  RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte);		
 		
-		/* Check if the UART receive buffer flush timer has expired */
-		if (TIFR0 & (1 << TOV0))
+		/* Check if the UART receive buffer flush timer has expired or the buffer is nearly full */
+		RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
+		if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
 		{
 			TIFR0 |= (1 << TOV0);
 
 			/* Read bytes from the USART receive buffer into the USB IN endpoint */
-			while (USARTtoUSB_Buffer.Count)
-			  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&USARTtoUSB_Buffer));
+			while (BufferCount--)
+			  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&USARTtoUSB_Buffer));
 		}
 		
 		/* Load the next byte from the USART transmit buffer into the USART */
-		if (USBtoUSART_Buffer.Count)
-		  Serial_TxByte(RingBuffer_AtomicRemove(&USBtoUSART_Buffer));
+		if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer)))
+		  Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer));
 		
 		CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
 		USB_USBTask();
diff --git a/Projects/XPLAINBridge/Lib/LightweightRingBuff.h b/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
index 2faef438288eafa71a709b2dabe175858046af1b..cb0f6112a2c50a7f414d4ce2b805b93754a7b7c5 100644
--- a/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
+++ b/Projects/XPLAINBridge/Lib/LightweightRingBuff.h
@@ -44,10 +44,19 @@
 
 	/* Defines: */
 		/** Size of each ring buffer, in data elements - must be between 1 and 255. */
-		#define BUFFER_SIZE      255
+		#define BUFFER_SIZE         255
 		
 		/** Type of data to store into the buffer. */
-		#define RingBuff_Data_t  uint8_t
+		#define RingBuff_Data_t     uint8_t
+
+		/** Datatype which may be used to store the count of data stored in a buffer, retrieved
+		 *  via a call to \ref RingBuffer_GetCount().
+		 */
+		#if (BUFFER_SIZE <= 0xFF)
+			#define RingBuff_Count_t   uint8_t
+		#else
+			#define RingBuff_Count_t   uint16_t
+		#endif
 
 	/* Type Defines: */
 		/** Type define for a new ring buffer object. Buffers should be initialized via a call to
@@ -58,11 +67,11 @@
 			RingBuff_Data_t  Buffer[BUFFER_SIZE]; /**< Internal ring buffer data, referenced by the buffer pointers. */
 			RingBuff_Data_t* In; /**< Current storage location in the circular buffer */
 			RingBuff_Data_t* Out; /**< Current retrieval location in the circular buffer */
-			uint8_t          Count; /**< Total number of bytes stored in the circular buffer */
+			RingBuff_Count_t Count;
 		} RingBuff_t;
 	
 	/* Inline Functions: */
-		/** Initialises a ring buffer ready for use. Buffers must be initialized via this function
+		/** Initializes a ring buffer ready for use. Buffers must be initialized via this function
 		 *  before any operations are called upon them. Already initialized buffers may be reset
 		 *  by re-initializing them using this function.
 		 *
@@ -70,74 +79,73 @@
 		 */
 		static inline void RingBuffer_InitBuffer(RingBuff_t* const Buffer)
 		{
-			Buffer->In    = Buffer->Buffer;
-			Buffer->Out   = Buffer->Buffer;
-			Buffer->Count = 0;
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->In  = Buffer->Buffer;
+				Buffer->Out = Buffer->Buffer;
+			}
 		}
 		
-		/** Atomically determines if the specified ring buffer contains any free space. This should
-		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
-		 *  buffer overrun.
+		/** Retrieves the minimum number of bytes stored in a particular buffer. This value is computed
+		 *  by entering an atomic lock on the buffer while the IN and OUT locations are fetched, so that
+		 *  the buffer cannot be modified while the computation takes place. This value should be cached
+		 *  when reading out the contents of the buffer, so that as small a time as possible is spent
+		 *  in an atomic lock.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *  \note The value returned by this function is guaranteed to only be the minimum number of bytes
+		 *        stored in the given buffer; this value may change as other threads write new data and so
+		 *        the returned number should be used only to determine how many successive reads may safely
+		 *        be performed on the buffer.
 		 *
-		 *  \return Boolean true if the buffer contains no free space, false otherwise
-		 */		 
-		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
+		 *  \param[in] Buffer  Pointer to a ring buffer structure whose count is to be computed
+		 */
+		static inline RingBuff_Count_t RingBuffer_GetCount(RingBuff_t* const Buffer)
 		{
-			bool IsFull;
+			RingBuff_Count_t Count;
 			
 			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
 			{
-				IsFull = (Buffer->Count == BUFFER_SIZE);
+				Count = Buffer->Count;
 			}
 			
-			return IsFull;
+			return Count;
 		}
 		
-		/** Atomically inserts an element into the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any free space. This should
+		 *  be tested before storing data to the buffer, to ensure that no data is lost due to a
+		 *  buffer overrun.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
-		 *  \param[in]     Data    Data element to insert into the buffer
-		 */
-		static inline void RingBuffer_AtomicInsert(RingBuff_t* const Buffer,
-		                                           const RingBuff_Data_t Data)
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsFull(RingBuff_t* const Buffer)
 		{
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				*Buffer->In = Data;
-			
-				if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->In = Buffer->Buffer;
-				  
-				Buffer->Count++;
-			}
+			return (RingBuffer_GetCount(Buffer) == BUFFER_SIZE);
 		}
 
-		/** Atomically retrieves an element from the ring buffer.
+		/** Atomically determines if the specified ring buffer contains any data. This should
+		 *  be tested before removing data from the buffer, to ensure that the buffer does not
+		 *  underflow.
 		 *
-		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
+		 *  If the data is to be removed in a loop, store the total number of bytes stored in the
+		 *  buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
+		 *  to reduce the time spent in atomicity locks.
 		 *
-		 *  \return Next data element stored in the buffer
-		 */
-		static inline RingBuff_Data_t RingBuffer_AtomicRemove(RingBuff_t* const Buffer)
+		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
+		 *
+		 *  \return Boolean true if the buffer contains no free space, false otherwise
+		 */		 
+		static inline bool RingBuffer_IsEmpty(RingBuff_t* const Buffer)
 		{
-			RingBuff_Data_t Data;
-			
-			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
-			{
-				Data = *Buffer->Out;
-			
-				if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
-				  Buffer->Out = Buffer->Buffer;
-				  
-				Buffer->Count--;
-			}
-
-			return Data;
+			return (RingBuffer_GetCount(Buffer) == 0);
 		}
 
 		/** Inserts an element into the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may insert into a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to insert into
 		 *  \param[in]     Data    Data element to insert into the buffer
@@ -149,11 +157,18 @@
 			
 			if (++Buffer->In == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->In = Buffer->Buffer;
-				  
-			Buffer->Count++;
+
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count++;
+			}
 		}
 
-		/** Retrieves an element from the ring buffer.
+		/** Removes an element from the ring buffer.
+		 *
+		 *  \note Only one execution thread (main program thread or an ISR) may remove from a single buffer
+		 *        otherwise data corruption may occur. Insertion and removal may occur from different execution
+		 *        threads.
 		 *
 		 *  \param[in,out] Buffer  Pointer to a ring buffer structure to retrieve from
 		 *
@@ -165,11 +180,13 @@
 			
 			if (++Buffer->Out == &Buffer->Buffer[BUFFER_SIZE])
 			  Buffer->Out = Buffer->Buffer;
-				  
-			Buffer->Count--;
 
+			ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+			{
+				Buffer->Count--;
+			}
+			
 			return Data;
 		}
 
 #endif
- 
diff --git a/Projects/XPLAINBridge/Lib/SoftUART.c b/Projects/XPLAINBridge/Lib/SoftUART.c
index 05dd8a4b5144e7d3e05d43fa16fa87406b44acbc..b96b45f4d059e3a15e6000669d077bd59728a532 100644
--- a/Projects/XPLAINBridge/Lib/SoftUART.c
+++ b/Projects/XPLAINBridge/Lib/SoftUART.c
@@ -140,7 +140,7 @@ ISR(TIMER3_COMPA_vect, ISR_BLOCK)
 		TX_Data >>= 1;
 		TX_BitsRemaining--;
 	}
-	else if (USBtoUART_Buffer.Count && !(RX_BitsRemaining))
+	else if (!(RX_BitsRemaining) && !(RingBuffer_IsEmpty(&USBtoUART_Buffer)))
 	{
 		/* Start bit - TX line low */
 		STXPORT &= ~(1 << STX);
diff --git a/Projects/XPLAINBridge/XPLAINBridge.c b/Projects/XPLAINBridge/XPLAINBridge.c
index 7272fd825664b12409c0d0aad900eb44f35f6b30..f02fe9bade25e1585b33ab29050ead01ec3355ba 100644
--- a/Projects/XPLAINBridge/XPLAINBridge.c
+++ b/Projects/XPLAINBridge/XPLAINBridge.c
@@ -36,8 +36,8 @@
 
 #include "XPLAINBridge.h"
 
-/* Current firmware mode, making the device behave as either a programmer or a USART bridge */
-bool CurrentFirmwareMode = MODE_PDI_PROGRAMMER;
+/** Current firmware mode, making the device behave as either a programmer or a USART bridge */
+bool CurrentFirmwareMode = MODE_USART_BRIDGE;
 
 /** LUFA CDC Class driver interface configuration and state information. This structure is
  *  passed to all CDC Class driver functions, so that multiple instances of the same class
@@ -122,16 +122,17 @@ void UARTBridge_Task(void)
 	/* Read bytes from the USB OUT endpoint into the UART transmit buffer */
 	int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
 	if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
-	  RingBuffer_AtomicInsert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
+	  RingBuffer_Insert(&USBtoUART_Buffer, ReceivedByte);
 	
-	/* Check if the UART receive buffer flush timer has expired */
-	if (TIFR0 & (1 << TOV0))
+	/* Check if the UART receive buffer flush timer has expired or buffer is nearly full */
+	RingBuff_Count_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
+	if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
 	{
 		TIFR0 |= (1 << TOV0);
 
 		/* Read bytes from the UART receive buffer into the USB IN endpoint */
-		while (UARTtoUSB_Buffer.Count)
-		  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&UARTtoUSB_Buffer));
+		while (BufferCount--)
+		  CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&UARTtoUSB_Buffer));
 	}
 
 	CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
@@ -184,6 +185,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
 		/* Initialize ring buffers used to hold serial data between USB and software UART interfaces */
 		RingBuffer_InitBuffer(&USBtoUART_Buffer);
 		RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
+		
+		/* Start the software USART */
+		SoftUART_Init();
 	}
 	else
 	{