From 7ae91099e9b356d3f9fe14b41a53a6af1161690c Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Mon, 8 Feb 2010 03:16:09 +0000
Subject: [PATCH] Fix AVRISP-MKII clone project's TPI Chip Erase command
 processing - ensure erase location is the high byte in the given address
 space, check NVMBUSY for completion rather than the NVM Bus Enable bit.

Change If-Else chains over to switch statements in XPROGProtocol.c for clarity.
---
 .../DualVirtualSerial/DualVirtualSerial.txt   |   1 -
 .../DualVirtualSerial/DualVirtualSerial.txt   |   1 -
 LUFA/Drivers/USB/Class/Device/CDC.h           |  11 +-
 LUFA/Drivers/USB/Class/Host/CDC.h             |  13 +-
 LUFA/ManPages/VIDAndPIDValues.txt             |   2 +-
 Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c      |   8 +-
 Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h      |   1 +
 .../AVRISP-MKII/Lib/XPROG/XPROGProtocol.c     | 124 ++++++++++--------
 Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h  |   2 +-
 9 files changed, 93 insertions(+), 70 deletions(-)

diff --git a/Demos/Device/ClassDriver/DualVirtualSerial/DualVirtualSerial.txt b/Demos/Device/ClassDriver/DualVirtualSerial/DualVirtualSerial.txt
index 40b7c5a85..b1ba267a3 100644
--- a/Demos/Device/ClassDriver/DualVirtualSerial/DualVirtualSerial.txt
+++ b/Demos/Device/ClassDriver/DualVirtualSerial/DualVirtualSerial.txt
@@ -13,7 +13,6 @@
  *  - Series 7 USB AVRs
  *  - Series 6 USB AVRs
  *  - Series 4 USB AVRs
- *  - Series 2 USB AVRs
  *
  *  \section SSec_Info USB Information:
  *
diff --git a/Demos/Device/LowLevel/DualVirtualSerial/DualVirtualSerial.txt b/Demos/Device/LowLevel/DualVirtualSerial/DualVirtualSerial.txt
index 40b7c5a85..b1ba267a3 100644
--- a/Demos/Device/LowLevel/DualVirtualSerial/DualVirtualSerial.txt
+++ b/Demos/Device/LowLevel/DualVirtualSerial/DualVirtualSerial.txt
@@ -13,7 +13,6 @@
  *  - Series 7 USB AVRs
  *  - Series 6 USB AVRs
  *  - Series 4 USB AVRs
- *  - Series 2 USB AVRs
  *
  *  \section SSec_Info USB Information:
  *
diff --git a/LUFA/Drivers/USB/Class/Device/CDC.h b/LUFA/Drivers/USB/Class/Device/CDC.h
index d248868cd..e6a2bfd5c 100644
--- a/LUFA/Drivers/USB/Class/Device/CDC.h
+++ b/LUFA/Drivers/USB/Class/Device/CDC.h
@@ -104,12 +104,13 @@
 					struct
 					{
 						uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
-											   *   masks.
+											   *   masks. This value is updated each time \ref CDC_Device_USBTask() is called.
 											   */
 						uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
-											   *   masks.
+											   *   masks - to notify the host of changes to these values, call the
+											   *   \ref CDC_Device_SendControlLineStateChange() function.
 											   */
-					} ControlLineStates;
+					} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
 
 					struct
 					{
@@ -121,7 +122,9 @@
 											  *   CDCDevice_LineCodingParity_t enum
 											  */
 						uint8_t  DataBits; /**< Bits of data per character of the virtual serial port */
-					} LineEncoding;			
+					} LineEncoding;	/** Line encoding used in the virtual serial port, for the device's information. This is generally
+					                 *  only used if the virtual serial port data is to be reconstructed on a physical UART.
+					                 */		
 				} State; /**< State data for the USB class interface within the device. All elements in this section
 				          *   are reset to their defaults when the interface is enumerated.
 				          */
diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h
index 466f141db..9433c59fa 100644
--- a/LUFA/Drivers/USB/Class/Host/CDC.h
+++ b/LUFA/Drivers/USB/Class/Host/CDC.h
@@ -92,12 +92,13 @@
 					struct
 					{
 						uint8_t HostToDevice; /**< Control line states from the host to device, as a set of CDC_CONTROL_LINE_OUT_*
-											   *   masks.
+											   *   masks - to notify the device of changes to these values, call the
+											   *   \ref CDC_Host_SendControlLineStateChange() function.
 											   */
 						uint8_t DeviceToHost; /**< Control line states from the device to host, as a set of CDC_CONTROL_LINE_IN_*
-											   *   masks.
+											   *   masks. This value is updated each time \ref CDC_Host_USBTask() is called.
 											   */
-					} ControlLineStates;
+					} ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
 					
 					struct
 					{
@@ -109,7 +110,11 @@
 											  *   CDCDevice_LineCodingParity_t enum
 											  */
 						uint8_t  DataBits; /**< Bits of data per character of the virtual serial port */
-					} LineEncoding;
+					} LineEncoding; /** Line encoding used in the virtual serial port, for the device's information. This is generally
+					                 *  only used if the virtual serial port data is to be reconstructed on a physical UART. When set
+					                 *  by the host application, the \ref CDC_Host_SetLineEncoding() function must be called to push
+					                 *  the changes to the device.
+					                 */
 				} State; /**< State data for the USB class interface within the device. All elements in this section
 						  *   <b>may</b> be set to initial values, but may also be ignored to default to sane values when
 						  *   the interface is enumerated.
diff --git a/LUFA/ManPages/VIDAndPIDValues.txt b/LUFA/ManPages/VIDAndPIDValues.txt
index 339fd47b2..5c17d52fc 100644
--- a/LUFA/ManPages/VIDAndPIDValues.txt
+++ b/LUFA/ManPages/VIDAndPIDValues.txt
@@ -193,7 +193,7 @@
  *     0x204D
  *    </td>
  *    <td>
- *     Keyboard and Mouse Combination Demo Application
+ *     Combined Keyboard and Mouse Demo Application
  *    </td>
  *   </tr>
  *
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c
index f327a47e8..34ffb1e7b 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c
+++ b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.c
@@ -204,13 +204,13 @@ bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint16_t Address)
 	TINYNVM_SendWriteNVMRegister(XPROG_Param_NVMCMDRegAddr);
 	XPROGTarget_SendByte(EraseCommand);
 
-	/* Write to a location within the target address space to start the erase process */
-	TINYNVM_SendPointerAddress(Address);
+	/* Write to a high byte location within the target address space to start the erase process */
+	TINYNVM_SendPointerAddress(Address | 0x0001);
 	XPROGTarget_SendByte(TPI_CMD_SST | TPI_POINTER_INDIRECT);
 	XPROGTarget_SendByte(0x00);
 
-	/* Wait until the NVM bus is ready again */
-	if (!(TINYNVM_WaitWhileNVMBusBusy()))
+	/* Wait until the NVM controller is no longer busy */
+	if (!(TINYNVM_WaitWhileNVMControllerBusy()))
 	  return false;
 	
 	return true;
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h
index f8aa14068..223bbccfd 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h
+++ b/Projects/AVRISP-MKII/Lib/XPROG/TINYNVM.h
@@ -63,6 +63,7 @@
 
 	/* Function Prototypes: */		
 		bool TINYNVM_WaitWhileNVMBusBusy(void);
+		bool TINYNVM_WaitWhileNVMControllerBusy(void);
 		bool TINYNVM_ReadMemory(const uint16_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadLength);
 		bool TINYNVM_WriteMemory(const uint16_t WriteAddress, uint8_t* WriteBuffer, uint16_t WriteLength);
 		bool TINYNVM_EraseMemory(const uint8_t EraseCommand, const uint16_t Address);
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c
index e7b57da17..24305dc20 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c
+++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGProtocol.c
@@ -208,27 +208,38 @@ static void XPROGProtocol_Erase(void)
 	Endpoint_ClearOUT();
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
 	
-	uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP;
-	
 	if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
 	{
+		uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP;
+	
 		/* Determine which NVM command to send to the device depending on the memory to erase */
-		if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP)
-		  EraseCommand = XMEGA_NVM_CMD_CHIPERASE;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP_PAGE)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT_PAGE)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM_PAGE)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE;
-		else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG)
-		  EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG;
+		switch (Erase_XPROG_Params.MemoryType)
+		{
+			case XPRG_ERASE_CHIP:
+				EraseCommand = XMEGA_NVM_CMD_CHIPERASE;
+				break;
+			case XPRG_ERASE_APP:
+				EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC;
+				break;
+			case XPRG_ERASE_BOOT:
+				EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC;
+				break;
+			case XPRG_ERASE_EEPROM:
+				EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM;
+				break;
+			case XPRG_ERASE_APP_PAGE:
+				EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE;
+				break;
+			case XPRG_ERASE_BOOT_PAGE:
+				EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE;
+				break;
+			case XPRG_ERASE_EEPROM_PAGE:
+				EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE;
+				break;
+			case XPRG_ERASE_USERSIG:
+				EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG;
+				break;
+		}
 		
 		/* Erase the target memory, indicate timeout if ocurred */
 		if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
@@ -277,36 +288,33 @@ static void XPROGProtocol_WriteMemory(void)
 		uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
 		uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
 		bool    PagedMemory      = true;
-
-		if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
-		{
-			WriteCommand     = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
-		}
-		else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
-		{
-			WriteCommand     = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
-		}
-		else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
-		{
-			WriteCommand     = XMEGA_NVM_CMD_WRITEEEPROMPAGE;
-			WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
-			EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
-		}
-		else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
-		{
-			/* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
-			WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
-			WriteCommand     = XMEGA_NVM_CMD_WRITEUSERSIG;
-		}
-		else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
-		{
-			WriteCommand     = XMEGA_NVM_CMD_WRITEFUSE;
-			PagedMemory      = false;
-		}
-		else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS)
+		
+		switch (WriteMemory_XPROG_Params.MemoryType)
 		{
-			WriteCommand     = XMEGA_NVM_CMD_WRITELOCK;
-			PagedMemory      = false;
+			case XPRG_MEM_TYPE_APPL:
+				WriteCommand     = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
+				break;
+			case XPRG_MEM_TYPE_BOOT:
+				WriteCommand     = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
+				break;
+			case XPRG_MEM_TYPE_EEPROM:
+				WriteCommand     = XMEGA_NVM_CMD_WRITEEEPROMPAGE;
+				WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
+				EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;			
+				break;
+			case XPRG_MEM_TYPE_USERSIG:
+				/* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
+				WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
+				WriteCommand     = XMEGA_NVM_CMD_WRITEUSERSIG;
+				break;
+			case XPRG_MEM_TYPE_FUSE:
+				WriteCommand     = XMEGA_NVM_CMD_WRITEFUSE;
+				PagedMemory      = false;
+				break;
+			case XPRG_MEM_TYPE_LOCKBITS:
+				WriteCommand     = XMEGA_NVM_CMD_WRITELOCK;
+				PagedMemory      = false;
+				break;
 		}
 		
 		/* Send the appropriate memory write commands to the device, indicate timeout if occurred */
@@ -394,21 +402,29 @@ static void XPROGProtocol_ReadCRC(void)
 	} ReadCRC_XPROG_Params;
 	
 	Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params), NO_STREAM_CALLBACK);
+
 	Endpoint_ClearOUT();
 	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
 	
-	uint8_t  CRCCommand = XMEGA_NVM_CMD_NOOP;
 	uint32_t MemoryCRC;
 
 	if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
 	{
+		uint8_t CRCCommand;
+
 		/* Determine which NVM command to send to the device depending on the memory to CRC */
-		if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP)
-		  CRCCommand = XMEGA_NVM_CMD_APPCRC;
-		else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT)
-		  CRCCommand = XMEGA_NVM_CMD_BOOTCRC;
-		else
-		  CRCCommand = XMEGA_NVM_CMD_FLASHCRC;
+		switch (ReadCRC_XPROG_Params.CRCType)
+		{
+			case XPRG_CRC_APP:
+				CRCCommand = XMEGA_NVM_CMD_APPCRC;
+				break;
+			case XPRG_CRC_BOOT:
+				CRCCommand = XMEGA_NVM_CMD_BOOTCRC;
+				break;
+			default:
+				CRCCommand = XMEGA_NVM_CMD_FLASHCRC;
+				break;
+		}
 		
 		/* Perform and retrieve the memory CRC, indicate timeout if occurred */
 		if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC)))
diff --git a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h
index 41bc14a1a..bc2953dd2 100644
--- a/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h
+++ b/Projects/AVRISP-MKII/Lib/XPROG/XPROGTarget.h
@@ -131,7 +131,7 @@
 		#define TPI_NVMENABLE_KEY          (uint8_t[]){0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF}
 
 		#define TPI_POINTER_INDIRECT       0
-		#define TPI_POINTER_INDIRECT_PI    (1 << 2)
+		#define TPI_POINTER_INDIRECT_PI    4
 		
 	/* Function Prototypes: */
 		void    XPROGTarget_EnableTargetPDI(void);
-- 
GitLab