V2Protocol.c 7.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
             LUFA Library
     Copyright (C) Dean Camera, 2009.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, and distribute this software
  and its documentation for any purpose and without fee is hereby
  granted, provided that the above copyright notice appear in all
  copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *
 *  V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
 */

36
#define  INCLUDE_FROM_V2PROTOCOL_C
37
#include "V2Protocol.h"
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
static const uint8_t SPIMaskFromSCKDuration[] =
	{
		#if (F_CPU == 8000000)
		SPI_SPEED_FCPU_DIV_2,
		#endif
		SPI_SPEED_FCPU_DIV_2, SPI_SPEED_FCPU_DIV_4, SPI_SPEED_FCPU_DIV_8,
		SPI_SPEED_FCPU_DIV_16, SPI_SPEED_FCPU_DIV_32, SPI_SPEED_FCPU_DIV_64
		#if (F_CPU == 16000000)										
		, SPI_SPEED_FCPU_DIV_128
		#endif
	};
	
/* Non-Volatile Parameter Values for EEPROM storage */
uint8_t EEMEM EEPROM_Rest_Polarity;

/* Volatile Parameter Values for RAM storage */
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
84
85
86
	uint8_t SCKDuration = V2Protocol_GetParameter(PARAM_SCK_DURATION);

	if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
	  SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
87
88
89
	  
	SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);	
}
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
{
	if (ResetTarget)
	{
		RESET_LINE_DDR  |= RESET_LINE_MASK;
		
		if (!(V2Protocol_GetParameter(PARAM_RESET_POLARITY)))
		  RESET_LINE_PORT |= RESET_LINE_MASK;
	}
	else
	{
		RESET_LINE_PORT &= ~RESET_LINE_MASK;	
		RESET_LINE_DDR  &= ~RESET_LINE_MASK;
	}
}

static uint8_t V2Protocol_GetParameter(uint8_t ParamID)
{
	/* Find the parameter in the parameter table and retrieve the value */
	for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)
	{
		if (ParamID == ParameterTable[TableIndex].ParameterID)
		  return ParameterTable[TableIndex].ParameterValue;
	}
	
	return 0;
}

static void V2Protocol_SetParameter(uint8_t ParamID, uint8_t Value)
{
	/* The target RESET line polarity is a non-volatile parameter, save to EEPROM when changed */
	if (ParamID == PARAM_RESET_POLARITY)
	  eeprom_write_byte(&EEPROM_Rest_Polarity, Value);

	/* Find the parameter in the parameter table and store the new value */
	for (uint8_t TableIndex = 0; TableIndex < (sizeof(ParameterTable) / sizeof(ParameterTable[0])); TableIndex++)
	{
		if (ParamID == ParameterTable[TableIndex].ParameterID)
		{
			ParameterTable[TableIndex].ParameterValue = Value;
			return;
		}
	}
}

void V2Protocol_Init(void)
{
	/* Target RESET line polarity is a non-volatile value, retrieve current parameter value from EEPROM */
	V2Protocol_SetParameter(PARAM_RESET_POLARITY, eeprom_read_byte(&EEPROM_Rest_Polarity));
}
141
142
143
144

void V2Protocol_ProcessCommand(void)
{
	uint8_t V2Command = Endpoint_Read_Byte();
145
		  
146
147
148
	switch (V2Command)
	{
		case CMD_SIGN_ON:
149
			V2Protocol_Command_SignOn();
150
151
152
			break;
		case CMD_SET_PARAMETER:
		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
164
	printf("COMMAND 0x%02x\r\n", V2Command);

165
	Endpoint_WaitUntilReady();	
166
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);	
167
}
168

169
170
171
static void V2Protocol_Command_Unknown(uint8_t V2Command)
{	
	while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
172
	{
173
174
		Endpoint_ClearOUT();
		while (!(Endpoint_IsOUTReceived()));
175
	}
176
177
178
179
180
181
182
183

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	Endpoint_Write_Byte(V2Command);
	Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
	Endpoint_ClearIN();
}
184

185
static void V2Protocol_Command_SignOn(void)
186
187
188
{
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
189
190
	Endpoint_WaitUntilReady();

191
	V2Protocol_ReconfigureSPI();
192

193
194
195
196
197
198
199
	Endpoint_Write_Byte(CMD_SIGN_ON);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_Write_Byte(PROGRAMMER_ID_LEN);
	Endpoint_Write_Stream_LE(PROGRAMMER_ID, PROGRAMMER_ID_LEN);
	Endpoint_ClearIN();
}

200
static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
201
202
203
204
205
206
{
	uint8_t ParamID    = Endpoint_Read_Byte();
	uint8_t ParamValue = Endpoint_Read_Byte();

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
207
208
	Endpoint_WaitUntilReady();
	
209
	Endpoint_Write_Byte(V2Command);
210
	Endpoint_Write_Byte(STATUS_CMD_OK);
211

212
213
	if (V2Command == CMD_SET_PARAMETER)
	  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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
{
	uint8_t TxBytes = Endpoint_Read_Byte();
	uint8_t RxBytes = Endpoint_Read_Byte();
	uint8_t RxStartAddr = Endpoint_Read_Byte();
	uint8_t TxData[255];
	
	Endpoint_Read_Stream_LE(TxData, TxBytes);
	
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();
	
	Endpoint_Write_Byte(CMD_SPI_MULTI);
	Endpoint_Write_Byte(STATUS_CMD_OK);

	uint8_t CurrTxPos = 0;
	uint8_t CurrRxPos = 0;

	while (CurrTxPos < RxStartAddr)
	{
		if (CurrTxPos < TxBytes)
		  SPI_SendByte(TxData[CurrTxPos]);
		else
		  SPI_SendByte(0);
		
		CurrTxPos++;
	}

	while (CurrRxPos < RxBytes)
	{
		if (CurrTxPos < TxBytes)
252
		  Endpoint_Write_Byte(SPI_TransferByte(TxData[CurrTxPos++]));
253
		else
254
		  Endpoint_Write_Byte(SPI_ReceiveByte());
255
256
257
258
259
260
261
		
		CurrRxPos++;
	}	
	
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_ClearIN();	
}