5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
24 #define PRIM_REQ_POWERUP (0)
25 #define PRIM_REQ_VERSION (1)
26 #define PRIM_CMD_DOWNLOAD (3)
27 #define PRIM_DATA_WORD (4)
28 #define PRIM_DATA_EOF (5)
30 #define PRIM_ACK_POWERUP (0x80)
31 #define PRIM_ACK_VERSION (0x81)
32 #define PRIM_REQ_DATA_ADDR (0x82)
33 #define PRIM_END_DOWNLOAD (0x83)
34 #define PRIM_DATA_CRC_ERR (0x84)
36 enum SportUpdateState
{
48 uint8_t sportUpdateState
= SPORT_IDLE
;
49 uint32_t sportUpdateAddr
= 0;
51 void sportOutputPushByte(uint8_t byte
)
53 if (byte
== 0x7E || byte
== 0x7D) {
54 telemetryOutputPushByte(0x7D);
55 telemetryOutputPushByte(0x20 ^ byte
);
58 telemetryOutputPushByte(byte
);
62 bool isSportOutputBufferAvailable()
64 return (outputTelemetryBufferSize
== 0 && outputTelemetryBufferTrigger
== 0x7E);
67 // TODO merge it with S.PORT update function when finished
68 void sportOutputPushPacket(SportTelemetryPacket
* packet
)
72 for (uint8_t i
=1; i
<sizeof(SportTelemetryPacket
); i
++) {
73 uint8_t byte
= packet
->raw
[i
];
74 sportOutputPushByte(byte
);
76 crc
+= crc
>> 8; // 0-100
80 telemetryOutputPushByte(0xFF-crc
);
81 telemetryOutputSetTrigger(packet
->raw
[0]); // physicalId
84 void sportProcessUpdatePacket(uint8_t * packet
)
86 if (packet
[0]==0x5E && packet
[1]==0x50) {
88 case PRIM_ACK_POWERUP
:
89 if (sportUpdateState
== SPORT_POWERUP_REQ
) {
90 sportUpdateState
= SPORT_POWERUP_ACK
;
94 case PRIM_ACK_VERSION
:
95 if (sportUpdateState
== SPORT_VERSION_REQ
) {
96 sportUpdateState
= SPORT_VERSION_ACK
;
97 // SportVersion[0] = packet[3] ;
98 // SportVersion[1] = packet[4] ;
99 // SportVersion[2] = packet[5] ;
100 // SportVersion[3] = packet[6] ;
101 // SportVerValid = 1 ;
105 case PRIM_REQ_DATA_ADDR
:
106 if (sportUpdateState
== SPORT_DATA_TRANSFER
) {
107 sportUpdateAddr
= *((uint32_t *)(&packet
[3]));
108 sportUpdateState
= SPORT_DATA_REQ
;
112 case PRIM_END_DOWNLOAD
:
113 sportUpdateState
= SPORT_COMPLETE
;
116 case PRIM_DATA_CRC_ERR
:
117 sportUpdateState
= SPORT_FAIL
;
123 bool sportWaitState(SportUpdateState state
, int timeout
)
129 watchdogSuspend(timeout
/ 10);
130 for (int i
=timeout
/2; i
>=0; i
--) {
132 while (telemetryGetByte(&byte
)) {
133 processFrskyTelemetryData(byte
);
135 if (sportUpdateState
== state
) {
138 else if (sportUpdateState
== SPORT_FAIL
) {
147 void sportClearPacket(uint8_t * packet
)
149 memset(packet
+2, 0, 6);
152 // TODO merge this function
153 void sportWritePacket(uint8_t * packet
)
155 uint8_t * ptr
= outputTelemetryBuffer
;
158 packet
[7] = crc16(packet
, 7);
159 for (int i
=0; i
<8; i
++) {
160 if (packet
[i
] == 0x7E || packet
[i
] == 0x7D) {
162 *ptr
++ = 0x20 ^ packet
[i
];
168 sportSendBuffer(outputTelemetryBuffer
, ptr
-outputTelemetryBuffer
);
171 const char * sportUpdatePowerOn(ModuleIndex module
)
175 sportUpdateState
= SPORT_POWERUP_REQ
;
176 sportWaitState(SPORT_IDLE
, 500); // Clear the fifo
178 telemetryInit(PROTOCOL_FRSKY_SPORT
);
180 #if defined(PCBTARANIS) || defined(PCBHORUS)
181 if (module
== INTERNAL_MODULE
)
182 INTERNAL_MODULE_ON();
184 SPORT_UPDATE_POWER_ON();
187 sportWaitState(SPORT_IDLE
, 50); // Clear the fifo
189 for (int i
=0; i
<10; i
++) {
191 sportClearPacket(packet
);
193 packet
[1] = PRIM_REQ_POWERUP
;
194 sportWritePacket(packet
);
195 if (sportWaitState(SPORT_POWERUP_ACK
, 100))
199 if (telemetryProtocol
!= PROTOCOL_FRSKY_SPORT
) {
200 return TR("Not responding", "Not S.Port 1");
203 if (!IS_FRSKY_SPORT_PROTOCOL()) {
204 return TR("Not responding", "Not S.Port 2");
207 if (IS_PCBREV_40()) {
208 return TR("Bottom pin no resp", "Bottom pin not responding");
211 return TR("Module pin no resp", "Module pin not responding");
214 return TR("Not responding", "Module not responding");
218 const char * sportUpdateReqVersion()
221 sportWaitState(SPORT_IDLE
, 20); // Clear the fifo
222 sportUpdateState
= SPORT_VERSION_REQ
;
223 for (int i
=0; i
<10; i
++) {
225 sportClearPacket(packet
) ;
227 packet
[1] = PRIM_REQ_VERSION
;
228 sportWritePacket(packet
);
229 if (sportWaitState(SPORT_VERSION_ACK
, 200))
232 return "Version request failed";
235 const char * sportUpdateUploadFile(const char *filename
)
238 uint32_t buffer
[1024/4];
242 if (f_open(&file
, filename
, FA_READ
) != FR_OK
) {
243 return "Error opening file";
246 sportWaitState(SPORT_IDLE
, 200); // Clear the fifo
247 sportUpdateState
= SPORT_DATA_TRANSFER
;
248 sportClearPacket(packet
) ;
250 packet
[1] = PRIM_CMD_DOWNLOAD
;
251 // Stop here for testing
252 sportWritePacket(packet
);
255 if (f_read(&file
, buffer
, 1024, &count
) != FR_OK
) {
257 return "Error reading file";
262 for (UINT i
=0; i
<count
; i
++) {
263 if (!sportWaitState(SPORT_DATA_REQ
, 2000)) {
264 return "Module refused data";
267 packet
[1] = PRIM_DATA_WORD
;
268 packet
[6] = sportUpdateAddr
& 0x000000FF;
269 uint32_t offset
= ( sportUpdateAddr
& 1023 ) >> 2; // 32 bit word offset into buffer
270 uint32_t *data
= (uint32_t *)(&packet
[2]);
271 *data
= buffer
[offset
];
272 sportUpdateState
= SPORT_DATA_TRANSFER
,
273 sportWritePacket(packet
);
275 drawProgressBar(STR_WRITING
, file
.fptr
, file
.obj
.objsize
);
286 const char * sportUpdateEnd()
289 if (!sportWaitState(SPORT_DATA_REQ
, 2000))
290 return "Module refused data";
291 sportClearPacket(packet
);
293 packet
[1] = PRIM_DATA_EOF
;
294 sportWritePacket(packet
);
295 if (!sportWaitState(SPORT_COMPLETE
, 2000)) {
296 return "Module rejected firmware";
301 void sportFlashDevice(ModuleIndex module
, const char * filename
)
305 #if defined(PCBTARANIS) || defined(PCBHORUS)
306 uint8_t intPwr
= IS_INTERNAL_MODULE_ON();
307 uint8_t extPwr
= IS_EXTERNAL_MODULE_ON();
308 INTERNAL_MODULE_OFF();
309 EXTERNAL_MODULE_OFF();
312 watchdogSuspend(2000);
316 const char * result
= sportUpdatePowerOn(module
);
317 if (!result
) result
= sportUpdateReqVersion();
318 if (!result
) result
= sportUpdateUploadFile(filename
);
319 if (!result
) result
= sportUpdateEnd();
322 POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR
);
323 SET_WARNING_INFO(result
, strlen(result
), 0);
326 #if defined(PCBTARANIS) || defined(PCBHORUS)
327 INTERNAL_MODULE_OFF();
328 SPORT_UPDATE_POWER_OFF();
331 sportWaitState(SPORT_IDLE
, 500); // Clear the fifo
333 #if defined(PCBTARANIS) || defined(PCBHORUS)
335 INTERNAL_MODULE_ON();
337 EXTERNAL_MODULE_ON();
340 sportUpdateState
= SPORT_IDLE
;
346 void sportProcessPacket(uint8_t * packet
)
349 if (sportUpdateState
!= SPORT_IDLE
) {
350 sportProcessUpdatePacket(packet
); // Uses different chksum
355 sportProcessTelemetryPacket(packet
);