Subversion Repositories HomeAutomation

Rev

Rev 270 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
270 johboh 1
#include "DownloadState.h"
2
 
3
 
4
 
5
static HexFile * hf;
6
//static CSerial * serial;
7
static SerialConnection * serial;
8
 
9
static HANDLE  hRunMutex;                   // "Keep Running" mutex 
10
 
11
void downloadState(void *pMyID);
12
 
13
typedef enum { SEND_START, WAIT_ACK, SEND_PGM_DATA, WAIT_OWN_PACKET, WAIT_PGM_ACK, RESEND_ADDR, WAIT_DONE, SEND_DONE, DONE, WAIT_ADDR_ACK,DEBUG_STATE1,DEBUG_STATE2 } dState;
14
 
15
 
16
void downloadState(void *pMyID)
17
{
18
	long lLastError = 0;
19
 
20
	dState pgs = SEND_START;
21
	DWORD t = 0;
22
	CanProtoMessage * outCm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));
23
	CanProtoMessage * cm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));
24
	unsigned char data[8];
25
	unsigned char byteSent = 0;
26
	unsigned long currentAddress = 0;
27
	unsigned char bytesToWrite[PACKET_LENGTH];
28
 
29
	while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT )
30
	{
31
 
32
		bool hasMessage = serial->getMessage(cm);
33
		if (hasMessage) 
34
		{
35
			unsigned char *dtmp = cm->getData();
36
			for(int i=0;i<8;i++) data[i]=dtmp[i];
37
			printf("[%ld] Has message\n",GetTickCount());
38
		}
39
 
40
		switch(pgs)
41
		{
42
			 case SEND_START:
43
				// Send boot start packet to target.
44
				// and wait for ack.
45
				currentAddress = hf->getAddrLower();
46
				data[RID_INDEX] = TARGET_ID;
47
				data[ADDRU_INDEX] = (unsigned char)((currentAddress & 0xFF0000) >> 16);
48
				data[ADDRH_INDEX] = (unsigned char)((currentAddress & 0xFF00) >> 8);
49
				data[ADDRL_INDEX] = (unsigned char)(currentAddress & 0xFF);
50
				outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_INIT, MY_NID, MY_ID, 8, data);
51
				outCm->getBytes(bytesToWrite);
52
				serial->write(bytesToWrite,PACKET_LENGTH);
53
				t = GetTickCount();
54
				pgs = WAIT_ACK;
55
			break;
56
 
57
 
58
			case WAIT_ACK:
59
 
60
				// Check for timeout, resend start packet in that case..
61
				if ((GetTickCount() - t) > TIMEOUT_MS)
62
				{
63
					pgs = SEND_START;
64
				}
65
 
66
				// If received ack.
67
				if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
68
				{
69
					// If no error
70
					if (data[ERR_INDEX] == ERR_NO_ERROR)
71
					{
72
						// Start sending program data..
73
						byteSent = 0;
74
						pgs = SEND_PGM_DATA;
75
					}
76
					else 
77
					{ 
78
						// else resend start..
79
						pgs = SEND_START;
80
					}
81
				}
82
			break;
83
 
84
			case SEND_PGM_DATA:
85
				// Send program data.
86
				for (int i = 0; i < 8; i++)
87
				{ 
88
					// Populate data.
89
					data[i] = hf->getByte(currentAddress + i + byteSent);
90
				}
91
				outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, (unsigned int)((unsigned int)((unsigned int)(floor(((double)byteSent/8.0)))<<2) + (FUNCC_BOOT_PGM)), MY_NID, MY_ID, 8, data);
92
				outCm->getBytes(bytesToWrite);
93
				serial->write(bytesToWrite,PACKET_LENGTH);
94
				t = GetTickCount();
95
				pgs = WAIT_OWN_PACKET;
96
			break;
97
 
98
			case WAIT_OWN_PACKET:
99
				// Wait reciving own packet, if timeout, resend last.
100
				if ((GetTickCount() - t) > TIMEOUT_MS)
101
				{
102
					//pgs = dState.SEND_PGM_DATA;
103
					pgs = RESEND_ADDR;
104
				}
105
 
106
				// If received own packet..
107
				if (hasMessage && outCm->equals(cm))
108
				{
109
 
110
					byteSent += 8;
111
 
112
					// Check if 64 bytes sent or not..
113
					if (byteSent == 64)
114
					{
115
						// Yes, wait for ack.
116
						t = GetTickCount();
117
						pgs = WAIT_PGM_ACK;
118
					}
119
					else
120
					{ 
121
						// No, send more.
122
						pgs = SEND_PGM_DATA;
123
					}
124
 
125
				}
126
			break;
127
 
128
 
129
			case WAIT_PGM_ACK:
130
				// Wait for pgm ack.
131
				if ((GetTickCount() - t) > 2*TIMEOUT_MS)
132
				{
133
					// Woops, error. Resend address and start over.
134
					pgs = RESEND_ADDR;
135
				}
136
 
137
				// If received ack.
138
				if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
139
				{
140
					// If no error
141
					if (data[ERR_INDEX] == ERR_NO_ERROR)
142
					{
143
						currentAddress += 64;
144
						// Check if end.
145
						if (currentAddress > hf->getAddrUpper())
146
						{
147
							// Yes, we are done, send done.
148
							pgs = SEND_DONE;
149
						}
150
						else
151
						{ 
152
							// More to write.
153
							byteSent = 0;
154
							pgs = SEND_PGM_DATA;
155
						}
156
					}
157
					else
158
					{
159
						// else resend start..
160
						pgs = RESEND_ADDR;
161
					}
162
				}
163
			break;
164
 
165
 
166
			case SEND_DONE:
167
				// Send done
168
				outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_DONE, MY_NID, MY_ID, 8, data);
169
				outCm->getBytes(bytesToWrite);
170
				serial->write(bytesToWrite,PACKET_LENGTH);
171
				t = GetTickCount();
172
				pgs = WAIT_DONE;
173
			break;
174
 
175
			case RESEND_ADDR:
176
				// Resend addr.
177
				data[RID_INDEX] = TARGET_ID;
178
				data[ADDRU_INDEX] = (byte)((currentAddress & 0xFF0000) >> 16);
179
				data[ADDRH_INDEX] = (byte)((currentAddress & 0xFF00) >> 8);
180
				data[ADDRL_INDEX] = (byte)(currentAddress & 0xFF);
181
				outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_ADDR, MY_NID, MY_ID, 8, data);
182
				outCm->getBytes(bytesToWrite);
183
				serial->write(bytesToWrite,PACKET_LENGTH);
184
				t = GetTickCount();
185
				pgs = WAIT_ADDR_ACK;
186
			break;
187
 
188
 
189
			case WAIT_ADDR_ACK:
190
				// Check for timeout, resend addr packet in that case..
191
				if ((GetTickCount() - t) > TIMEOUT_MS)
192
				{
193
					pgs = RESEND_ADDR;
194
				}
195
 
196
				// If received ack.
197
				if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
198
				{
199
					// If no error
200
					if (data[ERR_INDEX] == ERR_NO_ERROR)
201
					{
202
						// Start sending program data..
203
						byteSent = 0;
204
						pgs = SEND_PGM_DATA;
205
					}
206
					else
207
					{
208
						// else resend addr..
209
						pgs = RESEND_ADDR;
210
					}
211
				}
212
			break;
213
 
214
			case WAIT_DONE:
215
				// Check for timeout, resend done packet in that case..
216
				if ((GetTickCount() - t) > TIMEOUT_MS)
217
				{
218
					pgs = SEND_DONE;
219
				}
220
 
221
				// If received ack.
222
				if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID)
223
				{
224
					// If no error
225
					if (data[ERR_INDEX] == ERR_NO_ERROR)
226
					{
227
						// Start sending program data..
228
						byteSent = 0;
229
						pgs = DONE;
230
					}
231
					else
232
					{
233
						// else resend addr..
234
						pgs = RESEND_ADDR;
235
					}
236
				}
237
			break;
238
 
239
			case DONE:
240
				downloadStop();
241
				printf("DONE!\n");
242
			break;
243
		}
244
	}
245
 
246
	return;
247
}
248
 
249
 
250
void downloadStart(SerialConnection * ser,HexFile *hex)
251
{
252
	hf = hex;
253
	serial = ser;
254
	hRunMutex = CreateMutex( NULL, TRUE, NULL );      // Set 
255
	_beginthread( downloadState, 0, 0 );
256
 
257
}
258
 
259
void downloadStop( void )
260
{
261
	ReleaseMutex( hRunMutex );
262
	CloseHandle( hRunMutex );
263
}
264