Rename PDIProtocol.c/.h to XPROGProtocol.c/.h as it will now handle both TPI and...
[pub/USBasp.git] / Projects / AVRISP / Lib / V2Protocol.c
index 304eef4..eae2e83 100644 (file)
 #define  INCLUDE_FROM_V2PROTOCOL_C\r
 #include "V2Protocol.h"\r
 \r
-ParameterItem_t ParameterTable[] EEMEM = \r
-       {\r
-               { .ParameterID    = PARAM_BUILD_NUMBER_LOW,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_BUILD_NUMBER_HIGH,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_HW_VER,\r
-                 .ParameterValue = 0x01                    },\r
-               { .ParameterID    = PARAM_SW_MAJOR,\r
-                 .ParameterValue = 0x01                    },\r
-               { .ParameterID    = PARAM_SW_MINOR,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_VTARGET,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_SCK_DURATION,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_RESET_POLARITY,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_STATUS_TGT_CONN,\r
-                 .ParameterValue = 0x00                    },\r
-               { .ParameterID    = PARAM_DISCHARGEDELAY,\r
-                 .ParameterValue = 0x00                    },\r
-       };\r
-
-void V2Protocol_ProcessCommand(void)
-{
-       uint8_t V2Command = Endpoint_Read_Byte();\r
-                 \r
-       printf("COMMAND %d\r\n", V2Command);\r
+/** Current memory address for FLASH/EEPROM memory read/write commands */\r
+uint32_t CurrentAddress;\r
+\r
+/** Flag to indicate that the next read/write operation must update the device's current address */\r
+bool MustSetAddress;\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
+void V2Protocol_ProcessCommand(void)\r
+{\r
+       uint8_t V2Command = Endpoint_Read_Byte();\r
+       \r
+       Serial_TxByte(V2Command);\r
+       \r
        switch (V2Command)\r
        {\r
                case CMD_SIGN_ON:\r
-                       V2Protocol_ProcessCmdSignOn();\r
+                       V2Protocol_SignOn();\r
                        break;\r
                case CMD_SET_PARAMETER:\r
-                       V2Protocol_ProcessCmdSetParam();\r
-                       break;\r
                case CMD_GET_PARAMETER:\r
-                       V2Protocol_ProcessCmdGetParam();\r
+                       V2Protocol_GetSetParam(V2Command);\r
+                       break;\r
+               case CMD_LOAD_ADDRESS:\r
+                       V2Protocol_LoadAddress();\r
+                       break;\r
+               case CMD_RESET_PROTECTION:\r
+                       V2Protocol_ResetProtection();\r
+                       break;\r
+#if defined(ENABLE_ISP_PROTOCOL)\r
+               case CMD_ENTER_PROGMODE_ISP:\r
+                       ISPProtocol_EnterISPMode();\r
+                       break;\r
+               case CMD_LEAVE_PROGMODE_ISP:\r
+                       ISPProtocol_LeaveISPMode();\r
+                       break;\r
+               case CMD_PROGRAM_FLASH_ISP:\r
+               case CMD_PROGRAM_EEPROM_ISP:\r
+                       ISPProtocol_ProgramMemory(V2Command);                   \r
+                       break;\r
+               case CMD_READ_FLASH_ISP:\r
+               case CMD_READ_EEPROM_ISP:\r
+                       ISPProtocol_ReadMemory(V2Command);\r
+                       break;\r
+               case CMD_CHIP_ERASE_ISP:\r
+                       ISPProtocol_ChipErase();\r
+                       break;\r
+               case CMD_READ_FUSE_ISP:\r
+               case CMD_READ_LOCK_ISP:\r
+               case CMD_READ_SIGNATURE_ISP:\r
+               case CMD_READ_OSCCAL_ISP:\r
+                       ISPProtocol_ReadFuseLockSigOSCCAL(V2Command);\r
                        break;\r
+               case CMD_PROGRAM_FUSE_ISP:\r
+               case CMD_PROGRAM_LOCK_ISP:\r
+                       ISPProtocol_WriteFuseLock(V2Command);\r
+                       break;\r
+               case CMD_SPI_MULTI:\r
+                       ISPProtocol_SPIMulti();\r
+                       break;\r
+#endif\r
+#if defined(ENABLE_PDI_PROTOCOL)\r
+               case CMD_XPROG_SETMODE:\r
+                       PDIProtocol_XPROG_SetMode();\r
+                       break;\r
+               case CMD_XPROG:\r
+                       PDIProtocol_XPROG_Command();\r
+                       break;\r
+#endif\r
+#if defined(ENABLE_TPI_PROTOCOL)\r
+               // TODO\r
+#endif\r
                default:\r
-                       Endpoint_ClearOUT();\r
-                       Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
-                       Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);\r
-                       Endpoint_ClearIN();\r
+                       V2Protocol_UnknownCommand(V2Command);\r
                        break;\r
        }\r
        \r
-       /* Reset Endpoint direction to OUT ready for next command */\r
-       Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);        
+       Endpoint_WaitUntilReady();\r
+       Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);\r
 }\r
 \r
-static ParameterItem_t* V2Protocol_GetParameterItem(uint8_t ParamID)\r
+/** Handler for unknown V2 protocol commands. This discards all sent data and returns a\r
+ *  STATUS_CMD_UNKNOWN status back to the host.\r
+ *\r
+ *  \param[in] V2Command  Issued V2 Protocol command byte from the host\r
+ */\r
+static void V2Protocol_UnknownCommand(const uint8_t V2Command)\r
 {\r
-       for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)\r
+       /* Discard all incoming data */\r
+       while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)\r
        {\r
-               if (ParamID == eeprom_read_byte(&ParameterTable[TableIndex].ParameterID))\r
-                 return &ParameterTable[TableIndex];\r
+               Endpoint_ClearOUT();\r
+               Endpoint_WaitUntilReady();\r
        }\r
-       \r
-       return NULL;\r
-}
-
-static void V2Protocol_ProcessCmdSignOn(void)\r
+\r
+       Endpoint_ClearOUT();\r
+       Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
+\r
+       Endpoint_Write_Byte(V2Command);\r
+       Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);\r
+       Endpoint_ClearIN();\r
+}\r
+\r
+/** Handler for the CMD_SIGN_ON command, returning the programmer ID string to the host. */\r
+static void V2Protocol_SignOn(void)\r
 {\r
        Endpoint_ClearOUT();\r
        Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
-       \r
+\r
        Endpoint_Write_Byte(CMD_SIGN_ON);\r
        Endpoint_Write_Byte(STATUS_CMD_OK);\r
-       Endpoint_Write_Byte(PROGRAMMER_ID_LEN);\r
-       Endpoint_Write_Stream_LE(PROGRAMMER_ID, PROGRAMMER_ID_LEN);\r
+       Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);\r
+       Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));\r
        Endpoint_ClearIN();\r
 }\r
 \r
-static void V2Protocol_ProcessCmdSetParam(void)\r
+/** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function\r
+ *  as no ISP short-circuit protection is currently implemented.\r
+ */\r
+static void V2Protocol_ResetProtection(void)\r
 {\r
-       uint8_t ParamID    = Endpoint_Read_Byte();\r
-       uint8_t ParamValue = Endpoint_Read_Byte();\r
+       Endpoint_ClearOUT();\r
+       Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
+       \r
+       Endpoint_Write_Byte(CMD_RESET_PROTECTION);\r
+       Endpoint_Write_Byte(STATUS_CMD_OK);\r
+       Endpoint_ClearIN();     \r
+}\r
+\r
 \r
-       ParameterItem_t* ParameterItem = V2Protocol_GetParameterItem(ParamID);\r
+/** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or\r
+ *  getting a device parameter's value from the parameter table.\r
+ *\r
+ *  \param[in] V2Command  Issued V2 Protocol command byte from the host\r
+ */\r
+static void V2Protocol_GetSetParam(const uint8_t V2Command)\r
+{\r
+       uint8_t ParamID = Endpoint_Read_Byte();\r
+       uint8_t ParamValue;\r
        \r
+       if (V2Command == CMD_SET_PARAMETER)\r
+         ParamValue = Endpoint_Read_Byte();\r
+\r
        Endpoint_ClearOUT();\r
        Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
-\r
-       if (ParameterItem != NULL)\r
+       \r
+       Endpoint_Write_Byte(V2Command);\r
+       \r
+       uint8_t ParamPrivs = V2Params_GetParameterPrivileges(ParamID);\r
+       \r
+       if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))\r
        {\r
-               eeprom_write_byte(&ParameterItem->ParameterValue, ParamValue);\r
-\r
-               Endpoint_Write_Byte(CMD_SET_PARAMETER);\r
-               Endpoint_Write_Byte(STATUS_CMD_OK);     \r
+               Endpoint_Write_Byte(STATUS_CMD_OK);\r
+               V2Params_SetParameterValue(ParamID, ParamValue);\r
        }\r
-       else\r
+       else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))\r
        {\r
+               Endpoint_Write_Byte(STATUS_CMD_OK);\r
+               Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));\r
+       }\r
+       else\r
+       {       \r
                Endpoint_Write_Byte(STATUS_CMD_FAILED);\r
        }\r
 \r
        Endpoint_ClearIN();\r
 }\r
 \r
-static void V2Protocol_ProcessCmdGetParam(void)\r
+/** Handler for the CMD_LOAD_ADDRESS command, loading the given device address into a\r
+ *  global storage variable for later use, and issuing LOAD EXTENDED ADDRESS commands\r
+ *  to the attached device as required.\r
+ */\r
+static void V2Protocol_LoadAddress(void)\r
 {\r
-       uint8_t ParamID    = Endpoint_Read_Byte();\r
+       Endpoint_Read_Stream_BE(&CurrentAddress, sizeof(CurrentAddress));\r
 \r
-       ParameterItem_t* ParameterItem = V2Protocol_GetParameterItem(ParamID);\r
-       \r
        Endpoint_ClearOUT();\r
        Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);\r
+       \r
+       MustSetAddress = true;\r
 \r
-       if (ParameterItem != NULL)\r
-       {\r
-               Endpoint_Write_Byte(CMD_GET_PARAMETER);\r
-               Endpoint_Write_Byte(STATUS_CMD_OK);\r
-               Endpoint_Write_Byte(eeprom_read_byte(&ParameterItem->ParameterValue));  \r
-       }\r
-       else\r
-       {\r
-               Endpoint_Write_Byte(STATUS_CMD_FAILED);\r
-       }\r
-\r
-       Endpoint_ClearIN();     \r
+       Endpoint_Write_Byte(CMD_LOAD_ADDRESS);\r
+       Endpoint_Write_Byte(STATUS_CMD_OK);\r
+       Endpoint_ClearIN();\r
 }\r