From 66201a05e9d5793880b27519affff7132f6630ea Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Fri, 11 Dec 2009 04:04:34 +0000
Subject: [PATCH] Fix PDI code - must send NVM enable key least significant
 byte first, need to make sure Tx and Rx is switched correctly including
 disabling the output on the Tx line when receiving.

---
 Projects/AVRISP/Lib/PDIProtocol.c | 12 ++++---
 Projects/AVRISP/Lib/PDITarget.c   | 54 ++++++++++++++++++++++++-------
 Projects/AVRISP/makefile          |  2 +-
 3 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/Projects/AVRISP/Lib/PDIProtocol.c b/Projects/AVRISP/Lib/PDIProtocol.c
index 28bd54071..32a74c586 100644
--- a/Projects/AVRISP/Lib/PDIProtocol.c
+++ b/Projects/AVRISP/Lib/PDIProtocol.c
@@ -111,18 +111,20 @@ static void PDIProtocol_EnterXPROGMode(void)
 
 	/* 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++)
-	  PDITarget_SendByte(PDI_NVMENABLE_KEY[i]);
+	for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
+	  PDITarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
 
 	/* Poll the STATUS register to check to see if NVM access has been enabled */
-	uint8_t NVMAttemptsRemaining = 200;
-	while (NVMAttemptsRemaining--)
+	uint8_t NVMAttemptsRemaining = 150;
+	while (NVMAttemptsRemaining)
 	{
 		_delay_ms(1);
-		PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG);
 
+		PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG);
 		if (PDITarget_ReceiveByte() & PDI_STATUS_NVM)
 		  break;
+
+		NVMAttemptsRemaining--;
 	}
 	
 	Endpoint_Write_Byte(CMD_XPROG);
diff --git a/Projects/AVRISP/Lib/PDITarget.c b/Projects/AVRISP/Lib/PDITarget.c
index d012a1beb..22a4d019a 100644
--- a/Projects/AVRISP/Lib/PDITarget.c
+++ b/Projects/AVRISP/Lib/PDITarget.c
@@ -38,8 +38,9 @@
 #define  INCLUDE_FROM_PDITARGET_C
 #include "PDITarget.h"
 
-#if !defined(PDI_VIA_HARDWARE_USART)
 volatile bool     IsSending;
+
+#if !defined(PDI_VIA_HARDWARE_USART)
 volatile uint16_t DataBits;
 volatile uint8_t  BitCount;
 
@@ -192,31 +193,60 @@ void PDITarget_DisableTargetPDI(void)
 
 void PDITarget_SendByte(uint8_t Byte)
 {
-	UCSR1B &= ~(1 << RXEN1);
-	UCSR1B |=  (1 << TXEN1);
+	/* Switch to Tx mode if currently in Rx mode */
+	if (!(IsSending))
+	{
+		PORTD  |=  (1 << 3);
+		DDRD   |=  (1 << 3);
 
+		UCSR1B &= ~(1 << RXEN1);
+		UCSR1B |=  (1 << TXEN1);
+		
+		IsSending = true;
+	}
+	
+	/* Wait until there is space in the hardware Tx buffer before writing */
+	while (!(UCSR1A & (1 << UDRE1)));
 	UDR1 = Byte;
-
-	while (!(UCSR1A & (1 << TXC1)));
-	UCSR1A |=  (1 << TXC1);
 }
 
 uint8_t PDITarget_ReceiveByte(void)
 {
-	UCSR1B &= ~(1 << TXEN1);
-	UCSR1B |=  (1 << RXEN1);
+	/* Switch to Rx mode if currently in Tx mode */
+	if (IsSending)
+	{
+		while (!(UCSR1A & (1 << TXC1)));
+		UCSR1A |=  (1 << TXC1);
 
+		UCSR1B &= ~(1 << TXEN1);
+		UCSR1B |=  (1 << RXEN1);
+
+		DDRD   &= ~(1 << 3);
+		PORTD  &= ~(1 << 3);
+		
+		IsSending = false;
+	}
+
+	/* Wait until a byte has been received before reading */
 	while (!(UCSR1A & (1 << RXC1)));
-	UCSR1A |=  (1 << RXC1);
-	
 	return UDR1;
 }
 
 void PDITarget_SendBreak(void)
 {
-	UCSR1B &= ~(1 << RXEN1);
-	UCSR1B |=  (1 << TXEN1);
+	/* Switch to Tx mode if currently in Rx mode */
+	if (!(IsSending))
+	{
+		PORTD  |=  (1 << 3);
+		DDRD   |=  (1 << 3);
+
+		UCSR1B &= ~(1 << RXEN1);
+		UCSR1B |=  (1 << TXEN1);
+		
+		IsSending = true;
+	}
 
+	/* Need to do nothing for a full frame to send a BREAK */
 	for (uint8_t i = 0; i <= BITS_IN_FRAME; i++)
 	{
 		/* Wait for rising edge of clock */
diff --git a/Projects/AVRISP/makefile b/Projects/AVRISP/makefile
index 37c0e722b..003eaa57a 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  = XPLAIN
+BOARD = XPLAIN
 
 
 # Processor frequency.
-- 
GitLab