905214c6de06cb3c25b090817552f7af20254b28
[pub/USBasp.git] / Projects / Unfinished / AVRISP / Lib / V2Protocol.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 *
33 * V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
34 */
35
36 #define INCLUDE_FROM_V2PROTOCOL_C
37 #include "V2Protocol.h"
38
39 /* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
40 static const uint8_t SPIMaskFromSCKDuration[] =
41 {
42 #if (F_CPU == 8000000)
43 SPI_SPEED_FCPU_DIV_2,
44 #endif
45 SPI_SPEED_FCPU_DIV_2, SPI_SPEED_FCPU_DIV_4, SPI_SPEED_FCPU_DIV_8,
46 SPI_SPEED_FCPU_DIV_16, SPI_SPEED_FCPU_DIV_32, SPI_SPEED_FCPU_DIV_64
47 #if (F_CPU == 16000000)
48 , SPI_SPEED_FCPU_DIV_128
49 #endif
50 };
51
52 /* Non-Volatile Parameter Values for EEPROM storage */
53 uint8_t EEMEM EEPROM_Rest_Polarity;
54
55 /* Volatile Parameter Values for RAM storage */
56 static ParameterItem_t ParameterTable[] =
57 {
58 { .ParameterID = PARAM_BUILD_NUMBER_LOW,
59 .ParameterValue = (LUFA_VERSION_INTEGER >> 8) },
60 { .ParameterID = PARAM_BUILD_NUMBER_HIGH,
61 .ParameterValue = (LUFA_VERSION_INTEGER & 0xFF) },
62 { .ParameterID = PARAM_HW_VER,
63 .ParameterValue = 0x01 },
64 { .ParameterID = PARAM_SW_MAJOR,
65 .ParameterValue = 0x01 },
66 { .ParameterID = PARAM_SW_MINOR,
67 .ParameterValue = 0x00 },
68 { .ParameterID = PARAM_VTARGET,
69 .ParameterValue = 0x00 },
70 { .ParameterID = PARAM_SCK_DURATION,
71 .ParameterValue = sizeof(SPIMaskFromSCKDuration) },
72 { .ParameterID = PARAM_RESET_POLARITY,
73 .ParameterValue = 0x01 },
74 { .ParameterID = PARAM_STATUS_TGT_CONN,
75 .ParameterValue = 0x00 },
76 { .ParameterID = PARAM_DISCHARGEDELAY,
77 .ParameterValue = 0x00 },
78 };
79
80
81 static void V2Protocol_ReconfigureSPI(void)
82 {
83 uint8_t SCKDuration = V2Protocol_GetParameter(PARAM_SCK_DURATION);
84
85 if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
86 SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
87
88 SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);
89 }
90
91 static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
92 {
93 if (ResetTarget)
94 {
95 RESET_LINE_DDR |= RESET_LINE_MASK;
96
97 if (!(V2Protocol_GetParameter(PARAM_RESET_POLARITY)))
98 RESET_LINE_PORT |= RESET_LINE_MASK;
99 }
100 else
101 {
102 RESET_LINE_PORT &= ~RESET_LINE_MASK;
103 RESET_LINE_DDR &= ~RESET_LINE_MASK;
104 }
105 }
106
107 static uint8_t V2Protocol_GetParameter(uint8_t ParamID)
108 {
109 /* Find the parameter in the parameter table and retrieve the value */
110 for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)
111 {
112 if (ParamID == ParameterTable[TableIndex].ParameterID)
113 return ParameterTable[TableIndex].ParameterValue;
114 }
115
116 return 0;
117 }
118
119 static void V2Protocol_SetParameter(uint8_t ParamID, uint8_t Value)
120 {
121 /* The target RESET line polarity is a non-volatile parameter, save to EEPROM when changed */
122 if (ParamID == PARAM_RESET_POLARITY)
123 eeprom_write_byte(&EEPROM_Rest_Polarity, Value);
124
125 /* Find the parameter in the parameter table and store the new value */
126 for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)
127 {
128 if (ParamID == ParameterTable[TableIndex].ParameterID)
129 {
130 ParameterTable[TableIndex].ParameterValue = Value;
131 return;
132 }
133 }
134 }
135
136 void V2Protocol_Init(void)
137 {
138 /* Target RESET line polarity is a non-volatile value, retrieve current parameter value from EEPROM */
139 V2Protocol_SetParameter(PARAM_RESET_POLARITY, eeprom_read_byte(&EEPROM_Rest_Polarity));
140 }
141
142 void V2Protocol_ProcessCommand(void)
143 {
144 uint8_t V2Command = Endpoint_Read_Byte();
145
146 switch (V2Command)
147 {
148 case CMD_SIGN_ON:
149 V2Protocol_Command_SignOn();
150 break;
151 case CMD_SET_PARAMETER:
152 case CMD_GET_PARAMETER:
153 V2Protocol_Command_GetSetParam(V2Command);
154 break;
155 case CMD_SPI_MULTI:
156 V2Protocol_Command_SPIMulti();
157 break;
158 default:
159 V2Protocol_Command_Unknown(V2Command);
160 break;
161 }
162
163 printf("COMMAND 0x%02x\r\n", V2Command);
164
165 Endpoint_WaitUntilReady();
166 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
167 }
168
169 static void V2Protocol_Command_Unknown(uint8_t V2Command)
170 {
171 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
172 {
173 Endpoint_ClearOUT();
174 while (!(Endpoint_IsOUTReceived()));
175 }
176
177 Endpoint_ClearOUT();
178 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
179
180 Endpoint_Write_Byte(V2Command);
181 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
182 Endpoint_ClearIN();
183 }
184
185 static void V2Protocol_Command_SignOn(void)
186 {
187 Endpoint_ClearOUT();
188 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
189 Endpoint_WaitUntilReady();
190
191 V2Protocol_ReconfigureSPI();
192
193 Endpoint_Write_Byte(CMD_SIGN_ON);
194 Endpoint_Write_Byte(STATUS_CMD_OK);
195 Endpoint_Write_Byte(PROGRAMMER_ID_LEN);
196 Endpoint_Write_Stream_LE(PROGRAMMER_ID, PROGRAMMER_ID_LEN);
197 Endpoint_ClearIN();
198 }
199
200 static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
201 {
202 uint8_t ParamID = Endpoint_Read_Byte();
203 uint8_t ParamValue = Endpoint_Read_Byte();
204
205 Endpoint_ClearOUT();
206 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
207 Endpoint_WaitUntilReady();
208
209 Endpoint_Write_Byte(V2Command);
210 Endpoint_Write_Byte(STATUS_CMD_OK);
211
212 if (V2Command == CMD_SET_PARAMETER)
213 V2Protocol_SetParameter(ParamID, ParamValue);
214 else
215 Endpoint_Write_Byte(V2Protocol_GetParameter(ParamID));
216
217 Endpoint_ClearIN();
218 }
219
220 static void V2Protocol_Command_SPIMulti(void)
221 {
222 uint8_t TxBytes = Endpoint_Read_Byte();
223 uint8_t RxBytes = Endpoint_Read_Byte();
224 uint8_t RxStartAddr = Endpoint_Read_Byte();
225 uint8_t TxData[255];
226
227 Endpoint_Read_Stream_LE(TxData, TxBytes);
228
229 Endpoint_ClearOUT();
230 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
231 Endpoint_WaitUntilReady();
232
233 Endpoint_Write_Byte(CMD_SPI_MULTI);
234 Endpoint_Write_Byte(STATUS_CMD_OK);
235
236 uint8_t CurrTxPos = 0;
237 uint8_t CurrRxPos = 0;
238
239 while (CurrTxPos < RxStartAddr)
240 {
241 if (CurrTxPos < TxBytes)
242 SPI_SendByte(TxData[CurrTxPos]);
243 else
244 SPI_SendByte(0);
245
246 CurrTxPos++;
247 }
248
249 while (CurrRxPos < RxBytes)
250 {
251 if (CurrTxPos < TxBytes)
252 Endpoint_Write_Byte(SPI_TransferByte(TxData[CurrTxPos++]));
253 else
254 Endpoint_Write_Byte(SPI_ReceiveByte());
255
256 CurrRxPos++;
257 }
258
259 Endpoint_Write_Byte(STATUS_CMD_OK);
260 Endpoint_ClearIN();
261 }