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.
22 #include "pulses/pxx2.h"
23 #include "io/frsky_firmware_update.h"
25 uint8_t Pxx2Pulses::addFlag0(uint8_t module
)
27 uint8_t flag0
= g_model
.header
.modelId
[module
] & 0x3F;
28 if (g_model
.moduleData
[module
].failsafeMode
!= FAILSAFE_NOT_SET
&& g_model
.moduleData
[module
].failsafeMode
!= FAILSAFE_RECEIVER
) {
29 if (moduleState
[module
].counter
== 0) {
30 flag0
|= PXX2_CHANNELS_FLAG0_FAILSAFE
;
33 if (moduleState
[module
].mode
== MODULE_MODE_RANGECHECK
) {
34 flag0
|= PXX2_CHANNELS_FLAG0_RANGECHECK
;
36 Pxx2Transport::addByte(flag0
);
40 void Pxx2Pulses::addFlag1(uint8_t module
)
43 if (isModuleXJT(module
)) {
44 static const uint8_t PXX2_XJT_MODULE_SUBTYPES
[] = {0x01, 0x03, 0x02};
45 subType
= PXX2_XJT_MODULE_SUBTYPES
[min
<uint8_t>(g_model
.moduleData
[module
].subType
, 2)];
48 subType
= g_model
.moduleData
[module
].subType
;
50 Pxx2Transport::addByte(subType
<< 4);
53 void Pxx2Pulses::addPulsesValues(uint16_t low
, uint16_t high
)
55 Pxx2Transport::addByte(low
); // Low byte of channel
56 Pxx2Transport::addByte(((low
>> 8) & 0x0F) | (high
<< 4)); // 4 bits each from 2 channels
57 Pxx2Transport::addByte(high
>> 4); // High byte of channel
60 void Pxx2Pulses::addChannels(uint8_t module
)
62 uint16_t pulseValue
= 0;
63 uint16_t pulseValueLow
= 0;
65 uint8_t channel
= g_model
.moduleData
[module
].channelsStart
;
66 uint8_t count
= sentModuleChannels(module
);
68 for (int8_t i
= 0; i
< count
; i
++, channel
++) {
69 int value
= channelOutputs
[channel
] + 2*PPM_CH_CENTER(channel
) - 2*PPM_CENTER
;
70 pulseValue
= limit(1, (value
* 512 / 682) + 1024, 2046);
71 #if defined(DEBUG_LATENCY_RF_ONLY)
72 if (latencyToggleSwitch
)
78 addPulsesValues(pulseValueLow
, pulseValue
);
80 pulseValueLow
= pulseValue
;
84 void Pxx2Pulses::addFailsafe(uint8_t module
)
86 uint16_t pulseValue
= 0;
87 uint16_t pulseValueLow
= 0;
89 uint8_t channel
= g_model
.moduleData
[module
].channelsStart
;
90 uint8_t count
= sentModuleChannels(module
);
92 for (int8_t i
= 0; i
< count
; i
++, channel
++) {
93 if (g_model
.moduleData
[module
].failsafeMode
== FAILSAFE_HOLD
) {
96 else if (g_model
.moduleData
[module
].failsafeMode
== FAILSAFE_NOPULSES
) {
100 int16_t failsafeValue
= g_model
.failsafeChannels
[channel
];
101 if (failsafeValue
== FAILSAFE_CHANNEL_HOLD
) {
104 else if (failsafeValue
== FAILSAFE_CHANNEL_NOPULSE
) {
108 failsafeValue
+= 2*PPM_CH_CENTER(channel
) - 2*PPM_CENTER
;
109 pulseValue
= limit(1, (failsafeValue
* 512 / 682) + 1024, 2046);
113 addPulsesValues(pulseValueLow
, pulseValue
);
115 pulseValueLow
= pulseValue
;
119 void Pxx2Pulses::setupChannelsFrame(uint8_t module
)
121 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_CHANNELS
);
124 uint8_t flag0
= addFlag0(module
);
129 // Failsafe / Channels
130 if (flag0
& PXX2_CHANNELS_FLAG0_FAILSAFE
)
136 void Pxx2Pulses::setupTelemetryFrame(uint8_t module
)
138 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_TELEMETRY
);
139 Pxx2Transport::addByte(outputTelemetryBuffer
.destination
& 0x03);
140 for (uint8_t i
= 0; i
< sizeof(SportTelemetryPacket
); i
++) {
141 Pxx2Transport::addByte(outputTelemetryBuffer
.data
[i
]);
145 void Pxx2Pulses::setupHardwareInfoFrame(uint8_t module
)
147 ModuleInformation
* destination
= moduleState
[module
].moduleInformation
;
149 if (destination
->timeout
== 0) {
150 if (destination
->current
<= destination
->maximum
) {
151 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_HW_INFO
);
152 Pxx2Transport::addByte(destination
->current
);
153 destination
->timeout
= 60; /* 300ms */
154 destination
->current
++;
157 moduleState
[module
].mode
= MODULE_MODE_NORMAL
;
158 setupChannelsFrame(module
);
162 destination
->timeout
--;
163 setupChannelsFrame(module
);
167 void Pxx2Pulses::setupRegisterFrame(uint8_t module
)
169 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_REGISTER
);
171 if (reusableBuffer
.moduleSetup
.pxx2
.registerStep
== REGISTER_RX_NAME_SELECTED
) {
172 Pxx2Transport::addByte(0x01);
173 for (uint8_t i
=0; i
<PXX2_LEN_RX_NAME
; i
++) {
174 Pxx2Transport::addByte(zchar2char(reusableBuffer
.moduleSetup
.pxx2
.registerRxName
[i
]));
176 for (uint8_t i
=0; i
<PXX2_LEN_REGISTRATION_ID
; i
++) {
177 Pxx2Transport::addByte(zchar2char(g_model
.modelRegistrationID
[i
]));
179 Pxx2Transport::addByte(reusableBuffer
.moduleSetup
.pxx2
.registerLoopIndex
);
182 Pxx2Transport::addByte(0);
186 void Pxx2Pulses::setupModuleSettingsFrame(uint8_t module
)
188 ModuleSettings
* destination
= moduleState
[module
].moduleSettings
;
190 if (get_tmr10ms() > destination
->timeout
) {
191 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_TX_SETTINGS
);
193 if (destination
->state
== PXX2_SETTINGS_WRITE
)
194 flag0
|= PXX2_TX_SETTINGS_FLAG0_WRITE
;
195 Pxx2Transport::addByte(flag0
);
196 if (destination
->state
== PXX2_SETTINGS_WRITE
) {
198 if (destination
->externalAntenna
)
199 flag1
|= PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA
;
200 Pxx2Transport::addByte(flag1
);
201 Pxx2Transport::addByte(destination
->txPower
);
203 destination
->timeout
= get_tmr10ms() + 200/*next try in 2s*/;
206 setupChannelsFrame(module
);
210 void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module
)
212 if (get_tmr10ms() > reusableBuffer
.hardwareAndSettings
.receiverSettings
.timeout
) {
213 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_RX_SETTINGS
);
214 uint8_t flag0
= reusableBuffer
.hardwareAndSettings
.receiverSettings
.receiverId
;
215 if (reusableBuffer
.hardwareAndSettings
.receiverSettings
.state
== PXX2_SETTINGS_WRITE
)
216 flag0
|= PXX2_RX_SETTINGS_FLAG0_WRITE
;
217 Pxx2Transport::addByte(flag0
);
218 if (reusableBuffer
.hardwareAndSettings
.receiverSettings
.state
== PXX2_SETTINGS_WRITE
) {
220 if (reusableBuffer
.hardwareAndSettings
.receiverSettings
.telemetryDisabled
)
221 flag1
|= PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED
;
222 if (reusableBuffer
.hardwareAndSettings
.receiverSettings
.pwmRate
)
223 flag1
|= PXX2_RX_SETTINGS_FLAG1_FASTPWM
;
224 if (reusableBuffer
.hardwareAndSettings
.receiverSettings
.fport
)
225 flag1
|= PXX2_RX_SETTINGS_FLAG1_FPORT
;
226 Pxx2Transport::addByte(flag1
);
227 uint8_t outputsCount
= min
<uint8_t>(24, reusableBuffer
.hardwareAndSettings
.receiverSettings
.outputsCount
);
228 for (int i
= 0; i
< outputsCount
; i
++) {
229 Pxx2Transport::addByte(min
<uint8_t>(23, reusableBuffer
.hardwareAndSettings
.receiverSettings
.outputsMapping
[i
]));
232 reusableBuffer
.hardwareAndSettings
.receiverSettings
.timeout
= get_tmr10ms() + 200/*next try in 2s*/;
235 setupChannelsFrame(module
);
239 void Pxx2Pulses::setupAccstBindFrame(uint8_t module
)
241 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_BIND
);
242 Pxx2Transport::addByte(0x01); // DATA0
243 for (uint8_t i
=0; i
<PXX2_LEN_RX_NAME
; i
++) {
244 Pxx2Transport::addByte(0x00);
246 Pxx2Transport::addByte((g_model
.moduleData
[module
].pxx
.receiverHigherChannels
<< 7) + (g_model
.moduleData
[module
].pxx
.receiverTelemetryOff
<< 6));
247 Pxx2Transport::addByte(g_model
.header
.modelId
[module
]);
250 void Pxx2Pulses::setupAccessBindFrame(uint8_t module
)
252 BindInformation
* destination
= moduleState
[module
].bindInformation
;
254 if (destination
->step
== BIND_WAIT
) {
255 if (get_tmr10ms() > destination
->timeout
) {
256 moduleState
[module
].mode
= MODULE_MODE_NORMAL
;
257 destination
->step
= BIND_OK
;
258 POPUP_INFORMATION(STR_BIND_OK
); // TODO rather use the new callback
263 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_BIND
);
265 if (destination
->step
== BIND_INFO_REQUEST
) {
266 Pxx2Transport::addByte(0x02); // DATA0
267 for (uint8_t i
=0; i
<PXX2_LEN_RX_NAME
; i
++) {
268 Pxx2Transport::addByte(destination
->candidateReceiversNames
[destination
->selectedReceiverIndex
][i
]);
271 else if (destination
->step
== BIND_START
) {
272 Pxx2Transport::addByte(0x01); // DATA0
273 for (uint8_t i
=0; i
<PXX2_LEN_RX_NAME
; i
++) {
274 Pxx2Transport::addByte(destination
->candidateReceiversNames
[destination
->selectedReceiverIndex
][i
]);
276 if (isModuleR9MAccess(module
)) {
277 Pxx2Transport::addByte((destination
->lbtMode
<< 6) + (destination
->flexMode
<< 4) + destination
->rxUid
); // RX_UID is the slot index (which is unique and never moved)
280 Pxx2Transport::addByte(destination
->rxUid
); // RX_UID is the slot index (which is unique and never moved)
282 Pxx2Transport::addByte(g_model
.header
.modelId
[module
]);
285 Pxx2Transport::addByte(0x00); // DATA0
286 for (uint8_t i
=0; i
<PXX2_LEN_REGISTRATION_ID
; i
++) {
287 Pxx2Transport::addByte(zchar2char(g_model
.modelRegistrationID
[i
]));
292 void Pxx2Pulses::setupResetFrame(uint8_t module
)
294 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_RESET
);
295 Pxx2Transport::addByte(reusableBuffer
.moduleSetup
.pxx2
.resetReceiverIndex
);
296 Pxx2Transport::addByte(reusableBuffer
.moduleSetup
.pxx2
.resetReceiverFlags
);
297 moduleState
[module
].mode
= MODULE_MODE_NORMAL
;
300 void Pxx2Pulses::setupSpectrumAnalyser(uint8_t module
)
302 if (reusableBuffer
.spectrumAnalyser
.dirty
) {
303 reusableBuffer
.spectrumAnalyser
.dirty
= false;
304 #if defined(PCBHORUS)
305 memclear(&reusableBuffer
.spectrumAnalyser
.max
, sizeof(reusableBuffer
.spectrumAnalyser
.max
));
307 addFrameType(PXX2_TYPE_C_POWER_METER
, PXX2_TYPE_ID_SPECTRUM
);
308 Pxx2Transport::addByte(0x00);
309 Pxx2Transport::addWord(reusableBuffer
.spectrumAnalyser
.freq
);
310 Pxx2Transport::addWord(reusableBuffer
.spectrumAnalyser
.span
);
311 Pxx2Transport::addWord(reusableBuffer
.spectrumAnalyser
.step
);
315 void Pxx2Pulses::setupPowerMeter(uint8_t module
)
317 if (reusableBuffer
.powerMeter
.dirty
) {
318 reusableBuffer
.powerMeter
.dirty
= false;
319 addFrameType(PXX2_TYPE_C_POWER_METER
, PXX2_TYPE_ID_POWER_METER
);
320 Pxx2Transport::addByte(0x00);
321 Pxx2Transport::addWord(reusableBuffer
.powerMeter
.freq
);
325 void Pxx2Pulses::setupShareMode(uint8_t module
)
327 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_SHARE
);
328 Pxx2Transport::addByte(reusableBuffer
.moduleSetup
.pxx2
.shareReceiverIndex
);
331 void Pxx2Pulses::sendOtaUpdate(uint8_t module
, const char * rxName
, uint32_t address
, const char * data
)
335 addFrameType(PXX2_TYPE_C_OTA
, PXX2_TYPE_ID_OTA
);
338 Pxx2Transport::addByte(0x00);
339 for (uint8_t i
=0; i
<PXX2_LEN_RX_NAME
; i
++) {
340 Pxx2Transport::addByte(rxName
[i
]);
344 Pxx2Transport::addByte(0x01);
345 Pxx2Transport::addWord(address
);
346 for (uint8_t i
=0; i
<32; i
++) {
347 Pxx2Transport::addByte(data
[i
]);
351 Pxx2Transport::addByte(0x02);
356 if (module
== EXTERNAL_MODULE
)
357 extmoduleSendNextFrame();
360 void Pxx2Pulses::setupAuthenticationFrame(uint8_t module
, uint8_t mode
, const uint8_t * outputMessage
)
364 addFrameType(PXX2_TYPE_C_MODULE
, PXX2_TYPE_ID_AUTHENTICATION
);
366 Pxx2Transport::addByte(mode
);
368 for (uint8_t i
= 0; i
< 16; i
++) {
369 Pxx2Transport::addByte(outputMessage
[i
]);
376 bool Pxx2Pulses::setupFrame(uint8_t module
)
378 if (moduleState
[module
].mode
== MODULE_MODE_OTA_UPDATE
)
381 if (moduleState
[module
].mode
== MODULE_MODE_AUTHENTICATION
) {
382 moduleState
[module
].mode
= MODULE_MODE_NORMAL
;
388 switch (moduleState
[module
].mode
) {
389 case MODULE_MODE_GET_HARDWARE_INFO
:
390 setupHardwareInfoFrame(module
);
392 case MODULE_MODE_MODULE_SETTINGS
:
393 setupModuleSettingsFrame(module
);
395 case MODULE_MODE_RECEIVER_SETTINGS
:
396 setupReceiverSettingsFrame(module
);
398 case MODULE_MODE_REGISTER
:
399 setupRegisterFrame(module
);
401 case MODULE_MODE_BIND
:
402 if (g_model
.moduleData
[module
].type
== MODULE_TYPE_ISRM_PXX2
&& g_model
.moduleData
[module
].subType
!= MODULE_SUBTYPE_ISRM_PXX2_ACCESS
)
403 setupAccstBindFrame(module
);
404 else if (g_model
.moduleData
[module
].type
== MODULE_TYPE_XJT_LITE_PXX2
)
405 setupAccstBindFrame(module
);
407 setupAccessBindFrame(module
);
409 case MODULE_MODE_RESET
:
410 setupResetFrame(module
);
412 case MODULE_MODE_SPECTRUM_ANALYSER
:
413 setupSpectrumAnalyser(module
);
415 case MODULE_MODE_POWER_METER
:
416 setupPowerMeter(module
);
418 case MODULE_MODE_SHARE
:
419 setupShareMode(module
);
422 if (outputTelemetryBuffer
.isModuleDestination(module
)) {
423 setupTelemetryFrame(module
);
424 outputTelemetryBuffer
.reset();
427 setupChannelsFrame(module
);
432 if (moduleState
[module
].counter
-- == 0) {
433 moduleState
[module
].counter
= 2500;
441 bool Pxx2OtaUpdate::waitStep(uint8_t step
, uint8_t timeout
)
443 OtaUpdateInformation
* destination
= moduleState
[module
].otaUpdateInformation
;
446 watchdogSuspend(100 /*1s*/);
448 while (step
!= destination
->step
) {
449 if (elapsed
++ > timeout
) {
459 const char * Pxx2OtaUpdate::nextStep(uint8_t step
, const char * rxName
, uint32_t address
, const uint8_t * buffer
)
461 OtaUpdateInformation
* destination
= moduleState
[module
].otaUpdateInformation
;
463 destination
->step
= step
;
464 destination
->address
= address
;
466 for (uint8_t retry
= 0;; retry
++) {
467 extmodulePulsesData
.pxx2
.sendOtaUpdate(module
, rxName
, address
, (const char *) buffer
);
468 if (waitStep(step
+ 1, 20)) {
471 else if (retry
== 100) {
472 return "Transfer failed";
477 const char * Pxx2OtaUpdate::doFlashFirmware(const char * filename
)
484 result
= nextStep(OTA_UPDATE_START
, rxName
, 0, nullptr);
489 if (f_open(&file
, filename
, FA_READ
) != FR_OK
) {
490 return "Open file failed";
494 const char * ext
= getFileExtension(filename
);
495 if (ext
&& !strcasecmp(ext
, FRSKY_FIRMWARE_EXT
)) {
496 FrSkyFirmwareInformation
* information
= (FrSkyFirmwareInformation
*) buffer
;
497 if (f_read(&file
, buffer
, sizeof(FrSkyFirmwareInformation
), &count
) != FR_OK
|| count
!= sizeof(FrSkyFirmwareInformation
)) {
499 return "Format error";
501 size
= information
->size
;
504 size
= f_size(&file
);
509 drawProgressScreen(getBasename(filename
), STR_OTA_UPDATE
, done
, size
);
510 if (f_read(&file
, buffer
, sizeof(buffer
), &count
) != FR_OK
) {
512 return "Read file failed";
515 result
= nextStep(OTA_UPDATE_TRANSFER
, nullptr, done
, buffer
);
520 if (count
< sizeof(buffer
)) {
528 return nextStep(OTA_UPDATE_EOF
, nullptr, done
, nullptr);
531 void Pxx2OtaUpdate::flashFirmware(const char * filename
)
535 watchdogSuspend(100 /*1s*/);
538 moduleState
[module
].mode
= MODULE_MODE_OTA_UPDATE
;
539 const char * result
= doFlashFirmware(filename
);
540 moduleState
[module
].mode
= MODULE_MODE_NORMAL
;
542 AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1
);
546 POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR
);
547 SET_WARNING_INFO(result
, strlen(result
), 0);
550 POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS
);
553 watchdogSuspend(100);