From f0b4d796297cd4be311b8596c8308bad218adabd Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Wed, 16 Dec 2009 08:03:04 +0000
Subject: [PATCH] Slightly speed up software USART in the AVRISP project -
 faster parity computation, ensure received data is byte aligned when receive
 is complete by throwing away the start bit during reception.

---
 Projects/AVRISP/Lib/PDITarget.c | 20 +++++++++++++-------
 Projects/AVRISP/Lib/PDITarget.h | 12 +++++++++++-
 Projects/AVRISP/makefile        |  2 +-
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c
index a8fe21e9b..e21942a1f 100644
--- a/Projects/AVRISP/Lib/PDITarget.c
+++ b/Projects/AVRISP/Lib/PDITarget.c
@@ -70,8 +70,10 @@ ISR(TIMER1_COMPA_vect, ISR_BLOCK)
 		if ((SoftUSART_BitCount == BITS_IN_FRAME) && (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK))
 		  return;
 	
+		/* Shift in the bit one less than the frame size in position, so that the start bit will eventually
+		 * be discarded leaving the data to be byte-aligned for quick access */
 		if (BITBANG_PDIDATA_PIN & BITBANG_PDIDATA_MASK)
-		  SoftUSART_Data |= (1 << BITS_IN_FRAME);
+		  SoftUSART_Data |= (1 << (BITS_IN_FRAME - 1));
 
 		SoftUSART_Data >>= 1;
 		SoftUSART_BitCount--;
@@ -82,6 +84,7 @@ ISR(TIMER1_COMPA_vect, ISR_BLOCK)
 		if (!IsSending)
 		  return;
 
+		/* Set the data line to the next bit value */
 		if (SoftUSART_Data & 0x01)
 		  BITBANG_PDIDATA_PORT |=  BITBANG_PDIDATA_MASK;
 		else
@@ -196,17 +199,20 @@ void PDITarget_SendByte(uint8_t Byte)
 	bool    EvenParityBit = false;
 	uint8_t ParityData    = Byte;
 
-	/* Compute Even parity bit */
-	for (uint8_t i = 0; i < 8; i++)
+	/* Compute Even parity - while a bit is still set, chop off lowest bit and toggle parity bit */
+	while (ParityData)
 	{
-		EvenParityBit ^= ParityData & 0x01;
-		ParityData    >>= 1;
+		EvenParityBit ^= true;
+		ParityData    &= (ParityData - 1);
 	}
 
+	/* Calculate the new USART frame data here while while we wait for a previous byte (if any) to finish sending */
+	uint16_t NewUSARTData = ((1 << 11) | (1 << 10) | ((uint16_t)EvenParityBit << 9) | ((uint16_t)Byte << 1) | (0 << 0));
+
 	while (SoftUSART_BitCount);
 
 	/* Data shifted out LSB first, START DATA PARITY STOP STOP */
-	SoftUSART_Data     = ((uint16_t)EvenParityBit << 9) | ((uint16_t)Byte << 1) | (1 << 10) | (1 << 11);
+	SoftUSART_Data     = NewUSARTData;
 	SoftUSART_BitCount = BITS_IN_FRAME;
 #endif
 }
@@ -253,7 +259,7 @@ uint8_t PDITarget_ReceiveByte(void)
 	while (SoftUSART_BitCount);
 	
 	/* Throw away the start, parity and stop bits to leave only the data */
-	return (uint8_t)(SoftUSART_Data >> 1);
+	return (uint8_t)SoftUSART_Data;
 #endif
 }
 
diff --git a/Projects/AVRISP/Lib/PDITarget.h b/Projects/AVRISP/Lib/PDITarget.h
index 03083fcb6..2a704b3d8 100644
--- a/Projects/AVRISP/Lib/PDITarget.h
+++ b/Projects/AVRISP/Lib/PDITarget.h
@@ -54,7 +54,17 @@
 
 	/* Defines: */
 		#if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
-			#define PDI_VIA_HARDWARE_USART
+//			#define PDI_VIA_HARDWARE_USART
+
+			#define BITBANG_PDIDATA_PORT     PORTD
+			#define BITBANG_PDIDATA_DDR      DDRD
+			#define BITBANG_PDIDATA_PIN      PIND
+			#define BITBANG_PDIDATA_MASK     (1 << 3)
+			
+			#define BITBANG_PDICLOCK_PORT    PORTD
+			#define BITBANG_PDICLOCK_DDR     DDRD
+			#define BITBANG_PDICLOCK_PIN     PIND
+			#define BITBANG_PDICLOCK_MASK    (1 << 5)
 		#else
 			#define BITBANG_PDIDATA_PORT     PORTB
 			#define BITBANG_PDIDATA_DDR      DDRB
diff --git a/Projects/AVRISP/makefile b/Projects/AVRISP/makefile
index 2b6a1e858..23e27c52d 100644
--- a/Projects/AVRISP/makefile
+++ b/Projects/AVRISP/makefile
@@ -66,7 +66,7 @@ MCU = at90usb1287
 # Target board (see library "Board Types" documentation, USER or blank for projects not requiring
 # LUFA board drivers). If USER is selected, put custom board drivers in a directory called 
 # "Board" inside the application directory.
-BOARD = USBKEY
+BOARD = XPLAIN
 
 
 # Processor frequency.
-- 
GitLab