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