Added command timeout to the AVRISP project so that incorrectly connected targets no longer freeze the device.
Removed string descriptors from the TeensyHID bootloader to reduce its size.
  */\r
 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)\r
 {\r
-       const uint8_t  DescriptorType   = (wValue >> 8);\r
+       const uint8_t DescriptorType = (wValue >> 8);\r
 \r
        void*    Address = NULL;\r
        uint16_t Size    = NO_DESCRIPTOR;\r
 
   *\r
   *  <b>New:</b>\r
   *  - Added TPI programming support for 6-pin ATTINY to the AVRISP programmer project\r
+  *  - Added command timeout counter to the AVRISP project so that the device no longer freezes when incorrectly connected\r
+  *    to a target\r
   *\r
   *  <b>Changed:</b>\r
+  *  - Slowed down bit-banged PDI programming in the AVRISP project slightly to prevent transmission errors\r
   *\r
   *  <b>Fixed:</b>\r
   *\r
 
  *  - "Fingerlicking Wingdinger" (WARNING: Bad Language if no Javascript), a MIDI controller: http://noisybox.net/electronics/wingdinger/\r
  *  - Garmin GPS USB to NMEA standard serial sentence translator: http://github.com/nall/garmin-transmogrifier/tree/master\r
  *  - Generic HID Device Creator : http://generichid.sourceforge.net/\r
- *  - Mobo 4.3, some sort of Audio related device: http://sites.google.com/site/lofturj/mobo4_3\r
+ *  - Mobo 4.3, a USB controlled all band (160-10m) HF SDR transceiver: http://sites.google.com/site/lofturj/mobo4_3\r
  *  - NES Controller USB modification: http://projects.peterpolidoro.net/video/NESUSB.htm\r
  *  - MakeTV Episode Dispenser: http://www.youtube.com/watch?v=BkWUi18hl3g\r
  *  - Opendous-JTAG, an open source JTAG device: http://code.google.com/p/opendous-jtag/\r
 
        ADC_StartReading(VTARGET_ADC_CHANNEL | ADC_RIGHT_ADJUSTED | ADC_REFERENCE_AVCC);\r
        #endif\r
        \r
-       /* Millisecond timer initialization for timeouts and delays */\r
+       /* Millisecond timer initialization for managing the command timeout counter */\r
        OCR0A  = ((F_CPU / 64) / 1000);\r
        TCCR0A = (1 << WGM01);\r
        TCCR0B = ((1 << CS01) | (1 << CS00));\r
 
                 */\r
                static inline void ISPProtocol_DelayMS(uint8_t DelayMS)\r
                {\r
-                       TCNT0 = 0;\r
-                       TIFR0 = (1 << OCF1A);\r
+                       OCR2A  = ((F_CPU / 64) / 1000);\r
+                       TCCR2A = (1 << WGM01);\r
+                       TCCR2B = ((1 << CS01) | (1 << CS00));                   \r
 \r
                        while (DelayMS)\r
                        {\r
-                               if (TIFR0 & (1 << OCF1A))\r
+                               if (TIFR2 & (1 << OCF2A))\r
                                {\r
-                                       TIFR0 = (1 << OCF1A);\r
+                                       TIFR2 = (1 << OCF2A);\r
                                        DelayMS--;\r
                                }\r
                        }\r
+                       \r
+                       TCCR2B = 0;                     \r
                }\r
 \r
        /* Function Prototypes: */\r
 
                        break;\r
                case PROG_MODE_WORD_VALUE_MASK:\r
                case PROG_MODE_PAGED_VALUE_MASK:\r
-                       TCNT0 = 0;\r
-                       TIFR0 = (1 << OCF1A);\r
-                       \r
-                       uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS;\r
-\r
                        do\r
                        {\r
                                SPI_SendByte(ReadMemCommand);\r
                                SPI_SendByte(PollAddress >> 8);\r
                                SPI_SendByte(PollAddress & 0xFF);\r
-\r
-                               if (TIFR0 & (1 << OCF1A))\r
-                               {\r
-                                       TIFR0 = (1 << OCF1A);\r
-                                       TimeoutMS--;\r
-                               }\r
                        }\r
-                       while ((SPI_TransferByte(0x00) != PollValue) && TimeoutMS);\r
+                       while ((SPI_TransferByte(0x00) != PollValue) && TimeoutMSRemaining);\r
 \r
-                       if (!(TimeoutMS))\r
+                       if (!(TimeoutMSRemaining))\r
                         ProgrammingStatus = STATUS_CMD_TOUT;\r
                        \r
                        break;          \r
  */\r
 uint8_t ISPTarget_WaitWhileTargetBusy(void)\r
 {\r
-       TCNT0 = 0;\r
-       TIFR0 = (1 << OCF1A);\r
-                       \r
-       uint8_t TimeoutMS = TARGET_BUSY_TIMEOUT_MS;\r
-       \r
        do\r
        {\r
                SPI_SendByte(0xF0);\r
                SPI_SendByte(0x00);\r
 \r
                SPI_SendByte(0x00);\r
-\r
-               if (TIFR0 & (1 << OCF1A))\r
-               {\r
-                       TIFR0 = (1 << OCF1A);\r
-                       TimeoutMS--;\r
-               }\r
        }\r
-       while ((SPI_ReceiveByte() & 0x01) && TimeoutMS);\r
+       while ((SPI_ReceiveByte() & 0x01) && TimeoutMSRemaining);\r
 \r
-       if (!(TimeoutMS))\r
+       if (!(TimeoutMSRemaining))\r
          return STATUS_RDY_BSY_TOUT;\r
        else\r
          return STATUS_CMD_OK;\r
 
        /* Macros: */\r
                /** Total number of allowable ISP programming speeds supported by the device */\r
                #define TOTAL_ISP_PROGRAMMING_SPEEDS  7\r
-\r
-               /** Timeout in milliseconds of target busy-wait loops waiting for a command to complete */\r
-               #define TARGET_BUSY_TIMEOUT_MS        100\r
-\r
+               \r
        /* Function Prototypes: */\r
                uint8_t ISPTarget_GetSPIPrescalerMask(void);\r
                void    ISPTarget_ChangeTargetResetLine(const bool ResetTarget);\r
 
 bool MustSetAddress;\r
 \r
 \r
+/** ISR for the management of the command execution timeout counter */\r
+ISR(TIMER0_COMPA_vect, ISR_BLOCK)\r
+{\r
+       if (TimeoutMSRemaining)\r
+         TimeoutMSRemaining--;\r
+}\r
+\r
 /** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host.\r
  *  This routine decodes the issued command and passes off the handling of the command to the\r
  *  appropriate function.\r
 {\r
        uint8_t V2Command = Endpoint_Read_Byte();\r
        \r
+       TimeoutMSRemaining = COMMAND_TIMEOUT_MS;\r
+       TIMSK0 |= (1 << OCIE0A);\r
+\r
        switch (V2Command)\r
        {\r
                case CMD_SIGN_ON:\r
                        V2Protocol_UnknownCommand(V2Command);\r
                        break;\r
        }\r
-       \r
+               \r
+       TIMSK0 &= ~(1 << OCIE0A);\r
+\r
        Endpoint_WaitUntilReady();\r
        Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);\r
 }\r
 
        /* Preprocessor Checks: */\r
                #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))\r
                        #undef ENABLE_ISP_PROTOCOL\r
-                       #undef ENABLE_TPI_PROTOCOL\r
                        \r
-                       #if !defined(ENABLE_PDI_PROTOCOL)\r
-                               #define ENABLE_PDI_PROTOCOL\r
+                       #if !defined(ENABLE_XPROG_PROTOCOL)\r
+                               #define ENABLE_XPROG_PROTOCOL\r
                        #endif\r
                #endif\r
 
        /* Macros: */\r
                /** Programmer ID string, returned to the host during the CMD_SIGN_ON command processing */
                #define PROGRAMMER_ID     "AVRISP_MK2"\r
+               \r
+               /** Timeout period for each issued command from the host before it is aborted */\r
+               #define COMMAND_TIMEOUT_MS 200\r
+               \r
+               /** Command timeout counter register, GPIOR for speed */\r
+               #define TimeoutMSRemaining GPIOR1\r
 \r
        /* External Variables: */\r
                extern uint32_t CurrentAddress;\r
 
 static ParameterItem_t ParameterTable[] = \r
        {\r
                { .ParamID          = PARAM_BUILD_NUMBER_LOW,\r
-                 .ParamValue       = (LUFA_VERSION_INTEGER >> 8),\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = (LUFA_VERSION_INTEGER >> 8)        },\r
 \r
                { .ParamID          = PARAM_BUILD_NUMBER_HIGH,\r
-                 .ParamValue       = (LUFA_VERSION_INTEGER & 0xFF),\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = (LUFA_VERSION_INTEGER & 0xFF),     },\r
 \r
                { .ParamID          = PARAM_HW_VER,\r
-                 .ParamValue       = 0x00,\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = 0x00                               },\r
 \r
                { .ParamID          = PARAM_SW_MAJOR,\r
-                 .ParamValue       = 0x01,\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = 0x01                               },\r
 \r
                { .ParamID          = PARAM_SW_MINOR,\r
-                 .ParamValue       = 0x0D,\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = 0x0D                               },\r
 \r
                { .ParamID          = PARAM_VTARGET,\r
-                 .ParamValue       = 0x32,\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = 0x32                               },\r
 \r
                { .ParamID          = PARAM_SCK_DURATION,\r
-                 .ParamValue       = (TOTAL_ISP_PROGRAMMING_SPEEDS - 1),\r
-                 .ParamPrivileges  = PARAM_PRIV_READ | PARAM_PRIV_WRITE },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ | PARAM_PRIV_WRITE,\r
+                 .ParamValue       = (TOTAL_ISP_PROGRAMMING_SPEEDS - 1) },\r
 \r
                { .ParamID          = PARAM_RESET_POLARITY,\r
-                 .ParamValue       = 0x00,\r
-                 .ParamPrivileges  = PARAM_PRIV_WRITE                   },\r
+                 .ParamPrivileges  = PARAM_PRIV_WRITE,\r
+                 .ParamValue       = 0x00                               },\r
 \r
                { .ParamID          = PARAM_STATUS_TGT_CONN,\r
-                 .ParamValue       = 0x00,\r
-                 .ParamPrivileges  = PARAM_PRIV_READ                    },\r
+                 .ParamPrivileges  = PARAM_PRIV_READ,\r
+                 .ParamValue       = 0x00                               },\r
 \r
                { .ParamID          = PARAM_DISCHARGEDELAY,\r
-                 .ParamValue       = 0x00,\r
-                 .ParamPrivileges  = PARAM_PRIV_WRITE                   },\r
+                 .ParamPrivileges  = PARAM_PRIV_WRITE,\r
+                 .ParamValue       = 0x00                               },\r
        };\r
 \r
 \r
 
                typedef struct\r
                {\r
                        const uint8_t ParamID; /**< Parameter ID number to uniquely identify the parameter within the device */\r
+                       const uint8_t ParamPrivileges;  /**< Parameter privileges to allow the host to read or write the parameter's value */\r
                        uint8_t ParamValue; /**< Current parameter's value within the device */\r
-                       uint8_t ParamPrivileges;  /**< Parameter privileges to allow the host to read or write the parameter's value */\r
                } ParameterItem_t;\r
 \r
        /* Function Prototypes: */\r
 
 #include "TINYNVM.h"\r
 \r
 #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)\r
+#warning TPI Protocol support is currently incomplete and is not suitable for general use.\r
 \r
 /** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read.\r
  *\r
  */\r
 bool TINYNVM_WaitWhileNVMBusBusy(void)\r
 {\r
-       TCNT0 = 0;\r
-       TIFR0 = (1 << OCF1A);\r
-                       \r
-       uint8_t TimeoutMS = TINY_NVM_BUSY_TIMEOUT_MS;\r
-       \r
        /* Poll the STATUS register to check to see if NVM access has been enabled */\r
-       while (TimeoutMS)\r
+       while (TimeoutMSRemaining)\r
        {\r
                /* Send the SLDCS command to read the TPI STATUS register to see the NVM bus is active */\r
                XPROGTarget_SendByte(TPI_CMD_SLDCS | TPI_STATUS_REG);\r
                if (XPROGTarget_ReceiveByte() & TPI_STATUS_NVM)\r
                  return true;\r
-\r
-               if (TIFR0 & (1 << OCF1A))\r
-               {\r
-                       TIFR0 = (1 << OCF1A);\r
-                       TimeoutMS--;\r
-               }\r
        }\r
        \r
        return false;\r
 
                #endif\r
 \r
        /* Defines: */\r
-               #define TINY_NVM_BUSY_TIMEOUT_MS       100\r
+               #define TINY_NVM_REG_NVMCSR            0x32\r
+               #define TINY_NVM_REG_NVMCMD            0x33\r
+\r
+               #define TINY_NVM_CMD_NOOP              0x00\r
+               #define TINY_NVM_CMD_CHIPERASE         0x10\r
+               #define TINY_NVM_CMD_SECTIONERASE      0x14\r
+               #define TINY_NVM_CMD_WORDWRITE         0x1D\r
 \r
        /* Function Prototypes: */\r
                bool TINYNVM_WaitWhileNVMBusBusy(void);\r
 
 void XMEGANVM_SendAddress(const uint32_t AbsoluteAddress)\r
 {\r
        /* Send the given 32-bit address to the target, LSB first */\r
-       XPROGTarget_SendByte(AbsoluteAddress &  0xFF);\r
-       XPROGTarget_SendByte(AbsoluteAddress >> 8);\r
-       XPROGTarget_SendByte(AbsoluteAddress >> 16);\r
-       XPROGTarget_SendByte(AbsoluteAddress >> 24);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[0]);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[1]);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[2]);\r
+       XPROGTarget_SendByte(((uint8_t*)&AbsoluteAddress)[3]);\r
 }\r
 \r
 /** Busy-waits while the NVM controller is busy performing a NVM operation, such as a FLASH page read or CRC\r
  */\r
 bool XMEGANVM_WaitWhileNVMBusBusy(void)\r
 {\r
-       TCNT0 = 0;\r
-       TIFR0 = (1 << OCF1A);\r
-                       \r
-       uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS;\r
-       \r
        /* Poll the STATUS register to check to see if NVM access has been enabled */\r
-       while (TimeoutMS)\r
+       while (TimeoutMSRemaining)\r
        {\r
                /* Send the LDCS command to read the PDI STATUS register to see the NVM bus is active */\r
                XPROGTarget_SendByte(PDI_CMD_LDCS | PDI_STATUS_REG);\r
                if (XPROGTarget_ReceiveByte() & PDI_STATUS_NVM)\r
                  return true;\r
-\r
-               if (TIFR0 & (1 << OCF1A))\r
-               {\r
-                       TIFR0 = (1 << OCF1A);\r
-                       TimeoutMS--;\r
-               }\r
        }\r
        \r
        return false;\r
  */\r
 bool XMEGANVM_WaitWhileNVMControllerBusy(void)\r
 {\r
-       TCNT0 = 0;\r
-       TIFR0 = (1 << OCF1A);\r
-                       \r
-       uint8_t TimeoutMS = XMEGA_NVM_BUSY_TIMEOUT_MS;\r
-       \r
        /* Poll the NVM STATUS register while the NVM controller is busy */\r
-       while (TimeoutMS)\r
+       while (TimeoutMSRemaining)\r
        {\r
                /* Send a LDS command to read the NVM STATUS register to check the BUSY flag */\r
                XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
                /* Check to see if the BUSY flag is still set */\r
                if (!(XPROGTarget_ReceiveByte() & (1 << 7)))\r
                  return true;\r
-\r
-               if (TIFR0 & (1 << OCF1A))\r
-               {\r
-                       TIFR0 = (1 << OCF1A);\r
-                       TimeoutMS--;\r
-               }\r
        }\r
        \r
        return false;\r
        if (!(XMEGANVM_WaitWhileNVMControllerBusy()))\r
          return false;\r
        \r
-       *CRCDest = 0;\r
+       uint32_t MemoryCRC = 0;\r
        \r
        /* Read the first generated CRC byte value */\r
        XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT0);\r
-       *CRCDest  = XPROGTarget_ReceiveByte();\r
+       MemoryCRC  = XPROGTarget_ReceiveByte();\r
 \r
        /* Read the second generated CRC byte value */\r
        XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT1);\r
-       *CRCDest |= ((uint16_t)XPROGTarget_ReceiveByte() << 8);\r
+       MemoryCRC |= ((uint16_t)XPROGTarget_ReceiveByte() << 8);\r
 \r
        /* Read the third generated CRC byte value */\r
        XPROGTarget_SendByte(PDI_CMD_LDS | (PDI_DATSIZE_4BYTES << 2));\r
        XMEGANVM_SendNVMRegAddress(XMEGA_NVM_REG_DAT2);\r
-       *CRCDest |= ((uint32_t)XPROGTarget_ReceiveByte() << 16);\r
+       MemoryCRC |= ((uint32_t)XPROGTarget_ReceiveByte() << 16);\r
+       \r
+       *CRCDest = MemoryCRC;\r
        \r
        return true;\r
 }\r
  *\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
-bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize)\r
+bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize)\r
 {\r
        /* Wait until the NVM controller is no longer busy */\r
        if (!(XMEGANVM_WaitWhileNVMControllerBusy()))\r
                \r
        /* Send a LD command with indirect access and postincrement to read out the bytes */\r
        XPROGTarget_SendByte(PDI_CMD_LD | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);\r
-       for (uint16_t i = 0; i < ReadSize; i++)\r
+       while (ReadSize--)\r
          *(ReadBuffer++) = XPROGTarget_ReceiveByte();\r
        \r
        return true;\r
  *  \return Boolean true if the command sequence complete successfully\r
  */\r
 bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,\r
-                               const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,\r
-                               const uint8_t* WriteBuffer, const uint16_t WriteSize)\r
+                              const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,\r
+                              const uint8_t* WriteBuffer, uint16_t WriteSize)\r
 {\r
        if (PageMode & XPRG_PAGEMODE_ERASE)\r
        {\r
                        \r
                /* Send a ST command with indirect access and postincrement to write the bytes */\r
                XPROGTarget_SendByte(PDI_CMD_ST | (PDI_POINTER_INDIRECT_PI << 2) | PDI_DATSIZE_1BYTE);\r
-               for (uint16_t i = 0; i < WriteSize; i++)\r
+               while (WriteSize--)\r
                  XPROGTarget_SendByte(*(WriteBuffer++));\r
        }\r
        \r
 
                #endif\r
 \r
        /* Defines: */\r
-               #define XMEGA_NVM_BUSY_TIMEOUT_MS            100\r
-               \r
                #define XMEGA_NVM_REG_ADDR0                  0x00\r
                #define XMEGA_NVM_REG_ADDR1                  0x01\r
                #define XMEGA_NVM_REG_ADDR2                  0x02\r
                bool XMEGANVM_WaitWhileNVMBusBusy(void);\r
                bool XMEGANVM_WaitWhileNVMControllerBusy(void);\r
                bool XMEGANVM_GetMemoryCRC(const uint8_t CRCCommand, uint32_t* const CRCDest);\r
-               bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, const uint16_t ReadSize);\r
+               bool XMEGANVM_ReadMemory(const uint32_t ReadAddress, uint8_t* ReadBuffer, uint16_t ReadSize);\r
                bool XMEGANVM_WriteByteMemory(const uint8_t WriteCommand, const uint32_t WriteAddress, const uint8_t* WriteBuffer);\r
                bool XMEGANVM_WritePageMemory(const uint8_t WriteBuffCommand, const uint8_t EraseBuffCommand,\r
                                              const uint8_t WritePageCommand, const uint8_t PageMode, const uint32_t WriteAddress,\r
-                                             const uint8_t* WriteBuffer, const uint16_t WriteSize);\r
+                                             const uint8_t* WriteBuffer, uint16_t WriteSize);\r
                bool XMEGANVM_EraseMemory(const uint8_t EraseCommand, const uint32_t Address);\r
 \r
 #endif\r
 
 \r
 #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)\r
 /** Base absolute address for the target's NVM controller */\r
-uint32_t XPROG_Param_NVMBase = 0x010001C0;\r
+uint32_t XPROG_Param_NVMBase    = 0x010001C0;\r
 \r
 /** Size in bytes of the target's EEPROM page */\r
 uint32_t XPROG_Param_EEPageSize;\r
 /** Currently selected XPROG programming protocol */\r
 uint8_t  XPROG_SelectedProtocol = XPRG_PROTOCOL_PDI;\r
 \r
-\r
 /** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI/TPI\r
  *  programming.\r
  */\r
 
        BITBANG_TPIDATA_PORT |= BITBANG_TPIDATA_MASK;\r
 \r
        /* Fire timer capture ISR every 100 cycles to manage the software USART */\r
-       OCR1A   = 80;\r
+       OCR1A   = 100;\r
        TCCR1B  = (1 << WGM13) | (1 << WGM12) | (1 << CS10);\r
        TIMSK1  = (1 << ICIE1);\r
        \r
        asm volatile ("NOP"::);\r
 \r
        /* Fire timer compare ISR every 100 cycles to manage the software USART */\r
-       OCR1A   = 80;\r
+       OCR1A   = 100;\r
        TCCR1B  = (1 << WGM12) | (1 << CS10);\r
        TIMSK1  = (1 << OCIE1A);\r
        \r
        }\r
 \r
        /* Wait until a byte has been received before reading */\r
-       while (!(UCSR1A & (1 << RXC1)));\r
+       while (!(UCSR1A & (1 << RXC1)) && TimeoutMSRemaining);\r
        return UDR1;\r
 #else\r
        /* Switch to Rx mode if currently in Tx mode */\r
 \r
        /* Wait until a byte has been received before reading */\r
        SoftUSART_BitCount = BITS_IN_USART_FRAME;\r
-       while (SoftUSART_BitCount);\r
-       \r
+       while (SoftUSART_BitCount && TimeoutMSRemaining);\r
+\r
        /* Throw away the parity and stop bits to leave only the data (start bit is already discarded) */\r
        return (uint8_t)SoftUSART_Data;\r
 #endif\r
 
                #include <stdbool.h>\r
                \r
                #include <LUFA/Common/Common.h>\r
+               \r
+               #include "../V2Protocol.h"\r
        \r
        /* Preprocessor Checks: */\r
                #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))\r
 
 /*\r
-             LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
-              \r
-  dean [at] fourwalledcubicle [dot] com\r
-      www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
          USB Missile Launcher Demo\r
         Copyright (C) Dave Fletcher, 2009.\r
          fletch at fletchtronics dot net\r
  *  \param[in] Report  Report data to send.\r
  *  \param[in] ReportSize  Report length in bytes.\r
  */\r
-void Send_Command_Report(uint8_t *Report, uint16_t ReportSize)\r
+void Send_Command_Report(uint8_t* const Report, const uint16_t ReportSize)\r
 {\r
        memcpy(CmdBuffer, Report, 8);\r
        WriteNextReport(CmdBuffer, ReportSize);\r
  *\r
  *  \param[in] Command  One of the command constants.\r
  */\r
-void Send_Command(uint8_t* Command)\r
+void Send_Command(uint8_t* const Command)\r
 {\r
        if ((CmdState == CMD_STOP && Command != CMD_STOP) ||\r
                (CmdState != CMD_STOP && Command == CMD_STOP))\r
  *  \param[in] ReportOUTData  Buffer containing the report to send to the device\r
  *  \param[in] ReportLength  Length of the report to send\r
  */\r
-void WriteNextReport(uint8_t* ReportOUTData, uint16_t ReportLength)\r
+void WriteNextReport(uint8_t* const ReportOUTData, const uint16_t ReportLength)\r
 {\r
        /* Select and unfreeze HID data OUT pipe */\r
        Pipe_SelectPipe(HID_DATA_OUT_PIPE);\r
 
                void SetupHardware(void);\r
 \r
                void Read_Joystick_Status(void);\r
-        void Send_Command_Report(uint8_t* Report, uint16_t ReportSize);\r
-        void Send_Command(uint8_t* Command);\r
+        void Send_Command_Report(uint8_t* const Report, const uint16_t ReportSize);\r
+        void Send_Command(uint8_t* const Command);\r
 \r
                void HID_Host_Task(void);\r
 \r
                void EVENT_USB_Host_DeviceEnumerationComplete(void);\r
 \r
                void DiscardNextReport(void);\r
-               void WriteNextReport(uint8_t* ReportOUTData, uint16_t ReportLength);\r
+               void WriteNextReport(uint8_t* const ReportOUTData, const uint16_t ReportLength);\r
                \r
 #endif\r