From c6d6bdae0a6fa5604174428787ff3c415ca73fad Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Wed, 12 Oct 2011 05:31:35 +0000
Subject: [PATCH] Added reliability patches to the AVRISP-MKII Clone project's
 PDI/TPI protocols (thanks to Justin Mattair).

---
 LUFA/ManPages/ChangeLog.txt                  |  2 +-
 Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c    | 19 ++++++++++++-------
 Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c | 19 +++++++++----------
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt
index b3bda78c9..1b3003f80 100644
--- a/LUFA/ManPages/ChangeLog.txt
+++ b/LUFA/ManPages/ChangeLog.txt
@@ -24,7 +24,7 @@
   *  - Core:
   *   - None
   *  - Library Applications:
-  *   - None
+  *   - Added reliability patches to the AVRISP-MKII Clone project's PDI/TPI protocols (thanks to Justin Mattair)
   *
   *  \section Sec_ChangeLog111009 Version 111009
   *  <b>New:</b>
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c
index e4f1186b0..71fa78222 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c
+++ b/Projects/AVRISP-MKII/Lib/XPROG/XMEGANVM.c
@@ -149,13 +149,18 @@ void XMEGANVM_DisablePDI(void)
 {
 	XMEGANVM_WaitWhileNVMBusBusy();
 
-	/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
-	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
-	XPROGTarget_SendByte(0x00);
-
-	/* Do it twice to make sure it takes effect (silicon bug?) */
-	XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
-	XPROGTarget_SendByte(0x00);
+	/* Clear the RESET key in the RESET PDI register to allow the XMEGA to run - must perform this until the 
+	 * change takes effect, as in some cases it takes multiple writes (silicon bug?).
+	 */
+	do
+	{
+		/* Clear reset register */
+		XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
+		XPROGTarget_SendByte(0x00);
+	
+		/* Read back the reset register, check to see if it took effect */
+		XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_RESET_REG);
+	} while (XPROGTarget_ReceiveByte() != 0x00);
 
 	XPROGTarget_DisableTargetPDI();
 }
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c
index 065cd0965..58df78559 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c
+++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.c
@@ -92,7 +92,8 @@ void XPROGTarget_EnableTargetTPI(void)
 void XPROGTarget_DisableTargetPDI(void)
 {
 	/* Switch to Rx mode to ensure that all pending transmissions are complete */
-	XPROGTarget_SetRxMode();
+	if (IsSending)
+	  XPROGTarget_SetRxMode();
 
 	/* Turn off receiver and transmitter of the USART, clear settings */
 	UCSR1A  = ((1 << TXC1) | (1 << RXC1));
@@ -108,7 +109,8 @@ void XPROGTarget_DisableTargetPDI(void)
 void XPROGTarget_DisableTargetTPI(void)
 {
 	/* Switch to Rx mode to ensure that all pending transmissions are complete */
-	XPROGTarget_SetRxMode();
+	if (IsSending)
+	  XPROGTarget_SetRxMode();
 
 	/* Turn off receiver and transmitter of the USART, clear settings */
 	UCSR1A |= (1 << TXC1) | (1 << RXC1);
@@ -169,19 +171,16 @@ void XPROGTarget_SendIdle(void)
 		/* Wait for a full cycle of the clock */
 		while (PIND & (1 << 5));
 		while (!(PIND & (1 << 5)));
+		while (PIND & (1 << 5));
 	}
 }
 
 static void XPROGTarget_SetTxMode(void)
 {
-    /* Need to do nothing for a full frame to send a BREAK - only one cycle should be needed, however
-	 * there are reports that sometimes the interface will get stuck in some environments. */
-    for (uint8_t i = 0; i < BITS_IN_USART_FRAME; i++)
-    {
-        /* Wait for a full cycle of the clock */
-        while (PIND & (1 << 5));
-        while (!(PIND & (1 << 5)));
-    }
+	/* Wait for a full cycle of the clock */
+	while (PIND & (1 << 5));
+	while (!(PIND & (1 << 5)));
+	while (PIND & (1 << 5));
 
 	PORTD  |=  (1 << 3);
 	DDRD   |=  (1 << 3);
-- 
GitLab