diff --git a/Projects/AVRISP/AVRISP.txt b/Projects/AVRISP/AVRISP.txt
index c15c27fa673d55bf8a2184058051ea8d4b2fb86a..9dd2f119fe1918b0bdd06b49e18c3c5840b2f016 100644
--- a/Projects/AVRISP/AVRISP.txt
+++ b/Projects/AVRISP/AVRISP.txt
@@ -109,7 +109,7 @@
  *  <b><sup>2</sup></b> <i>See \ref SSec_Options section</i>
  *
  *
- *  Connections to the device for PDI programming (when enabled):
+ *  Connections to the device for PDI programming<b><sup>1</sup></b> (when enabled):
  *
  *  <table>
  *   <tr>
@@ -149,6 +149,9 @@
  *   </tr>
  *  </table>
  *
+ *  <b><sup>1</sup></b> When PDI_VIA_HARDWARE_USART is set, the AVR's Tx and Rx become the DATA line when connected together
+ *                      via a pair of 300 ohm resistors, and the AVR's XCK pin becomes CLOCK.
+ *
  *  \section SSec_Options Project Options
  *
  *  The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
@@ -192,5 +195,11 @@
  *    <td>Makefile CDEFS</td>
  *    <td>Define to enable XMEGA PDI programming protocol support. <i>Ignored when compiled for the XPLAIN board.</i></td>  
  *   </tr>
+ *   <tr>
+ *    <td>PDI_VIA_HARDWARE_USART</td>
+ *    <td>Makefile CDEFS</td>
+ *    <td>Define to force the PDI protocol (when enabled) to use the hardware USART instead of bit-banging to match the official
+ *        AVRISP pinout. <i>Automatically set when compiled for the XPLAIN board.</i></td>  
+ *   </tr>
  *  </table>
  */
diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c
index 864d4e9c345800ea357aa4c7ac7f3fe395579e6d..c1e7bf2ee6e246da7ef3e62de72888b6a0cd6e47 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.c
+++ b/Projects/AVRISP/Lib/PDIProtocol.c
@@ -104,18 +104,13 @@ static void PDIProtocol_EnterXPROGMode(void)
 	Endpoint_ClearOUT();
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
 	
-	PDIDATA_LINE_DDR  |= PDIDATA_LINE_MASK;
-	PDICLOCK_LINE_DDR |= PDICLOCK_LINE_MASK;
-	
-	/* Must hold DATA line high for at least 90nS to enable PDI interface */
-	PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
-	asm volatile ("NOP"::);
-	asm volatile ("NOP"::);
-	
-	/* Toggle CLOCK line 16 times within 100uS of the original 90nS timeout to keep PDI interface enabled */
-	for (uint8_t i = 0; i < 16; i++)
-	  TOGGLE_PDI_CLOCK;
+	/* Enable PDI programming mode with the attached target */
+	PDITarget_EnableTargetPDI();
 	
+	/* Store the RESET ket into the RESET PDI register to complete the handshake */
+	PDITarget_SendByte(PDI_CMD_STCS | PD_RESET_REG);	
+	PDITarget_SendByte(PDI_RESET_KEY);
+
 	/* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
 	PDITarget_SendByte(PDI_CMD_KEY);	
 	for (uint8_t i = 0; i < sizeof(PDI_NVMENABLE_KEY); i++)
@@ -140,14 +135,8 @@ static void PDIProtocol_LeaveXPROGMode(void)
 	Endpoint_ClearOUT();
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
 	
-	/* Set DATA and CLOCK lines to inputs */
-	PDIDATA_LINE_DDR   &= ~PDIDATA_LINE_MASK;
-	PDICLOCK_LINE_DDR  &= ~PDICLOCK_LINE_MASK;
-	
-	/* Tristate DATA and CLOCK lines */
-	PDIDATA_LINE_PORT  &= ~PDIDATA_LINE_MASK;
-	PDICLOCK_LINE_PORT &= ~PDICLOCK_LINE_MASK;
-	
+	PDITarget_DisableTargetPDI();
+
 	Endpoint_Write_Byte(CMD_XPROG);
 	Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);
 	Endpoint_Write_Byte(XPRG_ERR_OK);
diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c
index a0bbf7dfa11f7f2ea9b976ffad231064c6caf2e4..9a94e9a4e7fc8a7653a189c1b248457ca6e43518 100644
--- a/Projects/AVRISP/Lib/PDITarget.c
+++ b/Projects/AVRISP/Lib/PDITarget.c
@@ -38,90 +38,191 @@
 #define  INCLUDE_FROM_PDITARGET_C
 #include "PDITarget.h"
 
-/** Writes a given byte to the attached XMEGA device, using a RS232 frame via software through the
- *  PDI interface.
- *
- *  \param[in] Byte  Byte to send to the attached device
- */
-void PDITarget_SendByte(uint8_t Byte)
-{
-	uint8_t LogicOneBits = 0;
+#if !defined(PDI_VIA_HARDWARE_USART)
+volatile bool     IsSending;
+volatile uint16_t DataBits;
+volatile uint8_t  BitCount;
 
-	// One Start Bit
-	PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
+ISR(TIMER0_COMPA_vect, ISR_BLOCK)
+{
+	BITBANG_PDICLOCK_PORT ^= BITBANG_PDICLOCK_MASK;
 
-	TOGGLE_PDI_CLOCK;
+	/* If not sending or receiving, just exit */
+	if (!(BitCount))
+	  return;
 	
-	// Eight Data Bits
-	for (uint8_t i = 0; i < 8; i++)
+	/* Check to see if the current clock state is on the rising or falling edge */
+	bool IsRisingEdge = (BITBANG_PDICLOCK_PORT & BITBANG_PDICLOCK_MASK);
+
+	if (IsSending && !IsRisingEdge)
 	{
-		if (Byte & 0x01)
-		{
-			PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
-			LogicOneBits++;
-		}
+		if (DataBits & 0x01)
+		  BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
 		else
-		{
-			PDIDATA_LINE_PORT |=  PDIDATA_LINE_MASK;
-		}
-		
-		Byte >>= 1;
+		  BITBANG_PDIDATA_PORT |=  BITBANG_PDIDATA_MASK;		  
 
-		TOGGLE_PDI_CLOCK;
+		DataBits >>= 1;
+		BitCount--;
 	}
+	else if (!IsSending && IsRisingEdge)
+	{
+		/* Wait for the start bit when receiving */
+		if ((BitCount == BITS_IN_FRAME) && (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK))
+		  return;
+	
+		if (BITBANG_PDIDATA_PORT & BITBANG_PDIDATA_MASK)
+		  DataBits |= (1 << (BITS_IN_FRAME - 1));
 
-	// Even Parity Bit
-	if (LogicOneBits & 0x01)
-	  PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
-	else
-	  PDIDATA_LINE_PORT |=  PDIDATA_LINE_MASK;
-
-	TOGGLE_PDI_CLOCK;
+		DataBits >>= 1;
+		BitCount--;
+	}
+}
 
-	// Two Stop Bits
-	PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
+void PDITarget_EnableTargetPDI(void)
+{
+	/* Set DATA and CLOCK lines to outputs */
+	BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;
+	BITBANG_PDICLOCK_DDR |= BITBANG_PDICLOCK_MASK;
 	
-	TOGGLE_PDI_CLOCK;
-	TOGGLE_PDI_CLOCK;
+	/* Set DATA line high for 90ns to disable /RESET functionality */
+	BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+	asm volatile ("NOP"::);
+	asm volatile ("NOP"::);
+
+	/* Fire timer compare ISR every 160 cycles */
+	OCR0A   = 20;
+	TCCR0A  = (1 << WGM01);
+	TCCR0B  = (1 << CS01);
+	TIMSK0  = (1 << OCIE0A);
 }
 
-/** Reads a given byte from the attached XMEGA device, encoded in a RS232 frame through the PDI interface.
- *
- *  \return Received byte from the attached device
- */
-uint8_t PDITarget_ReceiveByte(void)
+void PDITarget_DisableTargetPDI(void)
 {
-	uint8_t ReceivedByte = 0;
-
-	PDIDATA_LINE_DDR &= ~PDIDATA_LINE_MASK;
+	/* Set DATA and CLOCK lines to inputs */
+	BITBANG_PDIDATA_DDR   &= ~BITBANG_PDIDATA_MASK;
+	BITBANG_PDICLOCK_DDR  &= ~BITBANG_PDICLOCK_MASK;
+	
+	/* Tristate DATA and CLOCK lines */
+	BITBANG_PDIDATA_PORT  &= ~BITBANG_PDIDATA_MASK;
+	BITBANG_PDICLOCK_PORT &= ~BITBANG_PDICLOCK_MASK;
 
-	// One Start Bit
-	while (PDIDATA_LINE_PIN & PDIDATA_LINE_MASK);
-	  TOGGLE_PDI_CLOCK;
+	TCCR0B  = 0;
+}
 
-	TOGGLE_PDI_CLOCK;
+void PDITarget_SendByte(uint8_t Byte)
+{
+	bool IsOddBitsSet = false;
 	
-	// Eight Data Bits
+	/* Compute Even parity bit */
 	for (uint8_t i = 0; i < 8; i++)
 	{
-		if (!(PDIDATA_LINE_PIN & PDIDATA_LINE_MASK))
-			ReceivedByte |= 0x80;
+		if (Byte & (1 << i))
+		  IsOddBitsSet = !(IsOddBitsSet);
+	}
 
-		ReceivedByte >>= 1;
+	/* Data shifted out LSB first, START DATA PARITY STOP STOP */
+	DataBits  = ((uint16_t)IsOddBitsSet << 10) | ((uint16_t)Byte << 1) | (1 << 0);
 
-		TOGGLE_PDI_CLOCK;	
-	}
+	BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+	BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;
 
-	// Even Parity Bit (discarded)
-	TOGGLE_PDI_CLOCK;
+	IsSending = true;
+	BitCount  = BITS_IN_FRAME;
+	while (BitCount);
+
+	BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
+	BITBANG_PDIDATA_DDR  &= ~BITBANG_PDIDATA_MASK;
+}
+
+uint8_t PDITarget_ReceiveByte(void)
+{
+	IsSending = false;
+	BitCount  = BITS_IN_FRAME;
+	while (BitCount);
+
+	return (DataBits >> 1);
+}
 
-	// Two Stop Bits
-	TOGGLE_PDI_CLOCK;
-	TOGGLE_PDI_CLOCK;
+void PDITarget_SendBreak(void)
+{
+	DataBits  = 0;
+
+	BITBANG_PDIDATA_PORT |= BITBANG_PDIDATA_MASK;
+	BITBANG_PDIDATA_DDR  |= BITBANG_PDIDATA_MASK;
+
+	IsSending = true;
+	BitCount  = BITS_IN_FRAME;
+	while (BitCount);
+
+	BITBANG_PDIDATA_PORT &= ~BITBANG_PDIDATA_MASK;
+	BITBANG_PDIDATA_DDR  &= ~BITBANG_PDIDATA_MASK;
+}
+#else
+void PDITarget_EnableTargetPDI(void)
+{
+	/* Set Tx and XCK as outputs, Rx as input */
+	DDRD |=  (1 << 5) | (1 << 3);
+	DDRD &= ~(1 << 2);
 	
-	PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK;
+	/* Set DATA line high for 90ns to disable /RESET functionality */
+	PORTD |= (1 << 3);
+	asm volatile ("NOP"::);
+	asm volatile ("NOP"::);
 	
-	return ReceivedByte;
+	/* Set up the synchronous USART for XMEGA communications - 
+	   8 data bits, even parity, 2 stop bits */
+	UBRR1  = 10;
+	UCSR1B = (1 << TXEN1);
+	UCSR1C = (1 << UMSEL10) | (1 << UPM11) | (1 << USBS1) | (1 << UCSZ11) | (1 << UCSZ10) | (1 << UCPOL1);
+
+	PDITarget_SendBreak();
+	PDITarget_SendBreak();
 }
 
+void PDITarget_DisableTargetPDI(void)
+{
+	/* Turn of receiver and transmitter of the USART, clear settings */
+	UCSR1B = 0;
+	UCSR1C = 0;
+
+	/* Set all USART lines as input, tristate */
+	DDRD  &= ~(1 << 5) | (1 << 3);
+	PORTD &= ~((1 << 5) | (1 << 3) | (1 << 2));
+}
+
+void PDITarget_SendByte(uint8_t Byte)
+{
+	UCSR1B &= ~(1 << RXEN1);
+	UCSR1B |=  (1 << TXEN1);
+
+	UDR1 = Byte;
+
+	while (!(UCSR1A & (1 << TXC1)));
+	UCSR1A |=  (1 << TXC1);
+}
+
+uint8_t PDITarget_ReceiveByte(void)
+{
+	UCSR1B &= ~(1 << TXEN1);
+	UCSR1B |=  (1 << RXEN1);
+
+	while (!(UCSR1A & (1 << RXC1)));
+	UCSR1A |=  (1 << RXC1);
+	
+	return UDR1;
+}
+
+void PDITarget_SendBreak(void)
+{
+	UCSR1B &= ~(1 << RXEN1);
+	UCSR1B |= (1 << TXEN1);
+
+	for (uint8_t i = 0; i < BITS_IN_FRAME; i++)
+	{
+		while (PIND & (1 << 5));
+		while (!(PIND & (1 << 5)));
+	}
+}
+#endif
+
 #endif
diff --git a/Projects/AVRISP/Lib/PDITarget.h b/Projects/AVRISP/Lib/PDITarget.h
index 00ce68bb3016697f107138806b1eb7270dc87b24..272655594561c15f410324f52dd948b134d7e1af 100644
--- a/Projects/AVRISP/Lib/PDITarget.h
+++ b/Projects/AVRISP/Lib/PDITarget.h
@@ -38,6 +38,7 @@
 
 	/* Includes: */
 		#include <avr/io.h>
+		#include <avr/interrupt.h>
 		#include <stdbool.h>
 		
 		#include <LUFA/Common/Common.h>
@@ -53,25 +54,20 @@
 
 	/* Defines: */
 		#if BOARD == BOARD_XPLAIN
-			#define PDIDATA_LINE_PORT     PORTD
-			#define PDIDATA_LINE_DDR      DDRD
-			#define PDIDATA_LINE_PIN      PIND
-			#define PDIDATA_LINE_MASK     (1 << 2)
-			
-			#define PDICLOCK_LINE_PORT    PORTD
-			#define PDICLOCK_LINE_DDR     DDRD
-			#define PDICLOCK_LINE_MASK    (1 << 5)
+			#define PDI_VIA_HARDWARE_USART
 		#else
-			#define PDIDATA_LINE_PORT     PORTB
-			#define PDIDATA_LINE_DDR      DDRB
-			#define PDIDATA_LINE_PIN      PINB
-			#define PDIDATA_LINE_MASK     (1 << 3)
+			#define BITBANG_PDIDATA_PORT     PORTB
+			#define BITBANG_PDIDATA_DDR      DDRB
+			#define BITBANG_PDIDATA_PIN      PINB
+			#define BITBANG_PDIDATA_MASK     (1 << 3)
 			
-			#define PDICLOCK_LINE_PORT    RESET_LINE_PORT
-			#define PDICLOCK_LINE_DDR     RESET_LINE_DDR
-			#define PDICLOCK_LINE_MASK    RESET_LINE_MASK
+			#define BITBANG_PDICLOCK_PORT    RESET_LINE_PORT
+			#define BITBANG_PDICLOCK_DDR     RESET_LINE_DDR
+			#define BITBANG_PDICLOCK_MASK    RESET_LINE_MASK
 		#endif
 		
+		#define BITS_IN_FRAME         12
+		
 		#define PDI_CMD_LDS           0x00
 		#define PDI_CMD_LD            0x20
 		#define PDI_CMD_STS           0x40
@@ -89,14 +85,12 @@
 
 		#define PDI_RESET_KEY         0x59
 		#define PDI_NVMENABLE_KEY     (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}
-
-		#define TOGGLE_PDI_CLOCK      MACROS{ PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK; \
-		                                      asm volatile ("NOP" ::);                  \
-		                                      PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK; \
-		                                      asm volatile ("NOP" ::);                  }MACROE
 		
 	/* Function Prototypes: */
+		void    PDITarget_EnableTargetPDI(void);
+		void    PDITarget_DisableTargetPDI(void);
 		void    PDITarget_SendByte(uint8_t Byte);
 		uint8_t PDITarget_ReceiveByte(void);
+		void    PDITarget_SendBreak(void);
 
 #endif
diff --git a/Projects/AVRISP/makefile b/Projects/AVRISP/makefile
index b215a22a2439de71cf1cc004e29ad4ab50c63b14..6eebb2b3384ddc7ac01c9b10bc7db992a90ccdf7 100644
--- a/Projects/AVRISP/makefile
+++ b/Projects/AVRISP/makefile
@@ -60,7 +60,7 @@
 
 
 # MCU name
-MCU = at90usb162
+MCU = at90usb1287
 
 
 # Target board (see library "Board Types" documentation, USER or blank for projects not requiring