2 #include "config_legacy.h"
11 #define MODEL_CHANGED bit(1)
12 #define VTX_CHANGED bit(2)
13 #define MAIN_CHANGED bit(3) // catch-all for global config item
14 #define FAN_CHANGED bit(4)
15 #define MOTION_CHANGED bit(5)
16 #define BUTTON_CHANGED bit(6)
17 #define ALL_CHANGED (MODEL_CHANGED | VTX_CHANGED | MAIN_CHANGED | FAN_CHANGED | MOTION_CHANGED | BUTTON_CHANGED)
19 // Really awful but safe(?) type punning of model_config_t/v6_model_config_t to and from uint32_t
20 template<class T
> static const void U32_to_Model(uint32_t const u32
, T
* const model
)
25 uint8_t padding
[sizeof(uint32_t)-sizeof(T
)];
28 } converter
= { .u32
= u32
};
30 *model
= converter
.val
.model
;
33 template<class T
> static const uint32_t Model_to_U32(T
const * const model
)
35 // clear the entire union because the assignment will only fill sizeof(T)
39 uint8_t padding
[sizeof(uint32_t)-sizeof(T
)];
44 converter
.val
.model
= *model
;
48 static uint8_t RateV6toV7(uint8_t rateV6
)
50 #if defined(RADIO_SX127X) || defined(RADIO_LR1121)
57 // 100Hz, 50Hz, 25Hz all move up one
58 // to make room for 100Hz Full
63 case 0: return 4; // 500Hz
64 case 1: return 6; // 250Hz
65 case 2: return 7; // 150Hz
66 case 3: return 9; // 50Hz
67 default: return 4; // 500Hz
72 static uint8_t RatioV6toV7(uint8_t ratioV6
)
74 // All shifted up for Std telem
78 static uint8_t SwitchesV6toV7(uint8_t switchesV6
)
80 // 0 was removed, Wide(2) became 0, Hybrid(1) became 1
83 case 1: return (uint8_t)smHybridOr16ch
;
86 return (uint8_t)smWideOr8ch
;
90 static void ModelV6toV7(v6_model_config_t
const * const v6
, model_config_t
* const v7
)
92 v7
->rate
= RateV6toV7(v6
->rate
);
93 v7
->tlm
= RatioV6toV7(v6
->tlm
);
94 v7
->power
= v6
->power
;
95 v7
->switchMode
= SwitchesV6toV7(v6
->switchMode
);
96 v7
->modelMatch
= v6
->modelMatch
;
97 v7
->dynamicPower
= v6
->dynamicPower
;
98 v7
->boostChannel
= v6
->boostChannel
;
101 static void ModelV7toV8(v7_model_config_t
const * const v7
, model_config_t
* const v8
)
105 v8
->power
= v7
->power
;
106 v8
->switchMode
= v7
->switchMode
;
107 v8
->boostChannel
= v7
->boostChannel
;
108 v8
->dynamicPower
= v7
->dynamicPower
;
109 v8
->modelMatch
= v7
->modelMatch
;
110 v8
->txAntenna
= v7
->txAntenna
;
111 v8
->ptrStartChannel
= v7
->ptrStartChannel
;
112 v8
->ptrEnableChannel
= v7
->ptrEnableChannel
;
113 v8
->linkMode
= v7
->linkMode
;
116 TxConfig::TxConfig() :
117 m_model(m_config
.model_config
)
121 #if defined(PLATFORM_ESP32)
122 void TxConfig::Load()
127 esp_err_t err
= nvs_flash_init();
128 if (err
== ESP_ERR_NVS_NO_FREE_PAGES
|| err
== ESP_ERR_NVS_NEW_VERSION_FOUND
)
130 ESP_ERROR_CHECK(nvs_flash_erase());
131 err
= nvs_flash_init();
133 ESP_ERROR_CHECK( err
);
134 ESP_ERROR_CHECK(nvs_open("ELRS", NVS_READWRITE
, &handle
));
136 // Try to load the version and make sure it is a TX config
137 uint32_t version
= 0;
138 if (nvs_get_u32(handle
, "tx_version", &version
) == ESP_OK
&& ((version
& CONFIG_MAGIC_MASK
) == TX_CONFIG_MAGIC
))
139 version
= version
& ~CONFIG_MAGIC_MASK
;
140 DBGLN("Config version %u", version
);
142 // Can't upgrade from version <5, or when flashing a previous version, just use defaults.
143 if (version
< 5 || version
> TX_CONFIG_VERSION
)
154 if (nvs_get_u32(handle
, "vtx", &value
) == ESP_OK
)
156 m_config
.vtxBand
= value
>> 24;
157 m_config
.vtxChannel
= value
>> 16;
158 m_config
.vtxPower
= value
>> 8;
159 m_config
.vtxPitmode
= value
;
163 if (nvs_get_u8(handle
, "fanthresh", &value8
) == ESP_OK
)
164 m_config
.powerFanThreshold
= value8
;
166 // Both of these were added to config v5 without incrementing the version
167 if (nvs_get_u32(handle
, "fan", &value
) == ESP_OK
)
168 m_config
.fanMode
= value
;
169 if (nvs_get_u32(handle
, "motion", &value
) == ESP_OK
)
170 m_config
.motionMode
= value
;
175 if (nvs_get_u8(handle
, "dvraux", &value8
) == ESP_OK
)
176 m_config
.dvrAux
= value8
;
177 if (nvs_get_u8(handle
, "dvrstartdelay", &value8
) == ESP_OK
)
178 m_config
.dvrStartDelay
= value8
;
179 if (nvs_get_u8(handle
, "dvrstopdelay", &value8
) == ESP_OK
)
180 m_config
.dvrStopDelay
= value8
;
184 // Need to write the dvr defaults
185 m_modified
|= MAIN_CHANGED
;
189 // load button actions
190 if (nvs_get_u32(handle
, "button1", &value
) == ESP_OK
)
191 m_config
.buttonColors
[0].raw
= value
;
192 if (nvs_get_u32(handle
, "button2", &value
) == ESP_OK
)
193 m_config
.buttonColors
[1].raw
= value
;
194 // backpackdisable was actually added after 7, but if not found will default to 0 (enabled)
195 if (nvs_get_u8(handle
, "backpackdisable", &value8
) == ESP_OK
)
196 m_config
.backpackDisable
= value8
;
197 if (nvs_get_u8(handle
, "backpacktlmen", &value8
) == ESP_OK
)
198 m_config
.backpackTlmMode
= value8
;
201 for(unsigned i
=0; i
<CONFIG_TX_MODEL_CNT
; i
++)
203 char model
[10] = "model";
204 itoa(i
, model
+5, 10);
205 if (nvs_get_u32(handle
, model
, &value
) == ESP_OK
)
209 // Upgrade v6 to v7 directly writing to nvs instead of calling Commit() over and over
210 v6_model_config_t v6model
;
211 U32_to_Model(value
, &v6model
);
212 model_config_t
* const newModel
= &m_config
.model_config
[i
];
213 ModelV6toV7(&v6model
, newModel
);
214 nvs_set_u32(handle
, model
, Model_to_U32(newModel
));
219 // Upgrade v7 to v8 directly writing to nvs instead of calling Commit() over and over
220 v7_model_config_t v7model
;
221 U32_to_Model(value
, &v7model
);
222 model_config_t
* const newModel
= &m_config
.model_config
[i
];
223 ModelV7toV8(&v7model
, newModel
);
224 nvs_set_u32(handle
, model
, Model_to_U32(newModel
));
227 if (version
== TX_CONFIG_VERSION
)
229 U32_to_Model(value
, &m_config
.model_config
[i
]);
234 if (version
!= TX_CONFIG_VERSION
)
240 void TxConfig::Load()
243 m_eeprom
->Get(0, m_config
);
245 uint32_t version
= 0;
246 if ((m_config
.version
& CONFIG_MAGIC_MASK
) == TX_CONFIG_MAGIC
)
247 version
= m_config
.version
& ~CONFIG_MAGIC_MASK
;
248 DBGLN("Config version %u", version
);
250 // If version is current, all done
251 if (version
== TX_CONFIG_VERSION
)
254 // Can't upgrade from version <5, or when flashing a previous version, just use defaults.
255 if (version
< 5 || version
> TX_CONFIG_VERSION
)
261 // Upgrade EEPROM, starting with defaults
266 UpgradeEepromV5ToV6();
272 UpgradeEepromV6ToV7();
278 UpgradeEepromV7ToV8();
282 void TxConfig::UpgradeEepromV5ToV6()
284 v5_tx_config_t v5Config
;
285 v6_tx_config_t v6Config
= { 0 }; // default the new fields to 0
287 // Populate the prev version struct from eeprom
288 m_eeprom
->Get(0, v5Config
);
290 // Copy prev values to current config struct
291 // This only workse because v5 and v6 are the same up to the new fields
292 // which have already been set to 0
293 memcpy(&v6Config
, &v5Config
, sizeof(v5Config
));
294 v6Config
.version
= 6U | TX_CONFIG_MAGIC
;
295 m_eeprom
->Put(0, v6Config
);
299 void TxConfig::UpgradeEepromV6ToV7()
301 v6_tx_config_t v6Config
;
303 // Populate the prev version struct from eeprom
304 m_eeprom
->Get(0, v6Config
);
306 // Manual field copying as some fields have moved
307 #define LAZY(member) m_config.member = v6Config.member
312 LAZY(powerFanThreshold
);
320 for (unsigned i
=0; i
<CONFIG_TX_MODEL_CNT
; i
++)
322 ModelV6toV7(&v6Config
.model_config
[i
], &m_config
.model_config
[i
]);
325 m_modified
= ALL_CHANGED
;
328 m_config
.version
= 7U | TX_CONFIG_MAGIC
;
332 void TxConfig::UpgradeEepromV7ToV8()
334 v7_tx_config_t v7Config
;
336 // Populate the prev version struct from eeprom
337 m_eeprom
->Get(0, v7Config
);
339 for (unsigned i
=0; i
<CONFIG_TX_MODEL_CNT
; i
++)
341 ModelV7toV8(&v7Config
.model_config
[i
], &m_config
.model_config
[i
]);
344 m_modified
= ALL_CHANGED
;
347 m_config
.version
= 8U | TX_CONFIG_MAGIC
;
360 #if defined(PLATFORM_ESP32)
361 // Write parts to NVS
362 if (m_modified
& MODEL_CHANGED
)
364 uint32_t value
= Model_to_U32(m_model
);
365 char model
[10] = "model";
366 itoa(m_modelId
, model
+5, 10);
367 nvs_set_u32(handle
, model
, value
);
369 if (m_modified
& VTX_CHANGED
)
372 m_config
.vtxBand
<< 24 |
373 m_config
.vtxChannel
<< 16 |
374 m_config
.vtxPower
<< 8 |
376 nvs_set_u32(handle
, "vtx", value
);
378 if (m_modified
& FAN_CHANGED
)
380 uint32_t value
= m_config
.fanMode
;
381 nvs_set_u32(handle
, "fan", value
);
383 if (m_modified
& MOTION_CHANGED
)
385 uint32_t value
= m_config
.motionMode
;
386 nvs_set_u32(handle
, "motion", value
);
388 if (m_modified
& MAIN_CHANGED
)
390 nvs_set_u8(handle
, "fanthresh", m_config
.powerFanThreshold
);
392 nvs_set_u8(handle
, "backpackdisable", m_config
.backpackDisable
);
393 nvs_set_u8(handle
, "backpacktlmen", m_config
.backpackTlmMode
);
394 nvs_set_u8(handle
, "dvraux", m_config
.dvrAux
);
395 nvs_set_u8(handle
, "dvrstartdelay", m_config
.dvrStartDelay
);
396 nvs_set_u8(handle
, "dvrstopdelay", m_config
.dvrStopDelay
);
398 if (m_modified
& BUTTON_CHANGED
)
400 nvs_set_u32(handle
, "button1", m_config
.buttonColors
[0].raw
);
401 nvs_set_u32(handle
, "button2", m_config
.buttonColors
[1].raw
);
403 nvs_set_u32(handle
, "tx_version", m_config
.version
);
406 // Write the struct to eeprom
407 m_eeprom
->Put(0, m_config
);
415 TxConfig::SetRate(uint8_t rate
)
417 if (GetRate() != rate
)
419 m_model
->rate
= rate
;
420 m_modified
|= MODEL_CHANGED
;
425 TxConfig::SetTlm(uint8_t tlm
)
430 m_modified
|= MODEL_CHANGED
;
435 TxConfig::SetPower(uint8_t power
)
437 if (GetPower() != power
)
439 m_model
->power
= power
;
440 m_modified
|= MODEL_CHANGED
;
445 TxConfig::SetDynamicPower(bool dynamicPower
)
447 if (GetDynamicPower() != dynamicPower
)
449 m_model
->dynamicPower
= dynamicPower
;
450 m_modified
|= MODEL_CHANGED
;
455 TxConfig::SetBoostChannel(uint8_t boostChannel
)
457 if (GetBoostChannel() != boostChannel
)
459 m_model
->boostChannel
= boostChannel
;
460 m_modified
|= MODEL_CHANGED
;
465 TxConfig::SetSwitchMode(uint8_t switchMode
)
467 if (GetSwitchMode() != switchMode
)
469 m_model
->switchMode
= switchMode
;
470 m_modified
|= MODEL_CHANGED
;
475 TxConfig::SetAntennaMode(uint8_t txAntenna
)
477 if (GetAntennaMode() != txAntenna
)
479 m_model
->txAntenna
= txAntenna
;
480 m_modified
|= MODEL_CHANGED
;
485 TxConfig::SetLinkMode(uint8_t linkMode
)
487 if (GetLinkMode() != linkMode
)
489 m_model
->linkMode
= linkMode
;
491 if (linkMode
== TX_MAVLINK_MODE
)
493 m_model
->tlm
= TLM_RATIO_1_2
;
494 m_model
->switchMode
= smHybridOr16ch
; // Force Hybrid / 16ch/2 switch modes for mavlink
496 m_modified
|= MODEL_CHANGED
| MAIN_CHANGED
;
501 TxConfig::SetModelMatch(bool modelMatch
)
503 if (GetModelMatch() != modelMatch
)
505 m_model
->modelMatch
= modelMatch
;
506 m_modified
|= MODEL_CHANGED
;
511 TxConfig::SetVtxBand(uint8_t vtxBand
)
513 if (m_config
.vtxBand
!= vtxBand
)
515 m_config
.vtxBand
= vtxBand
;
516 m_modified
|= VTX_CHANGED
;
521 TxConfig::SetVtxChannel(uint8_t vtxChannel
)
523 if (m_config
.vtxChannel
!= vtxChannel
)
525 m_config
.vtxChannel
= vtxChannel
;
526 m_modified
|= VTX_CHANGED
;
531 TxConfig::SetVtxPower(uint8_t vtxPower
)
533 if (m_config
.vtxPower
!= vtxPower
)
535 m_config
.vtxPower
= vtxPower
;
536 m_modified
|= VTX_CHANGED
;
541 TxConfig::SetVtxPitmode(uint8_t vtxPitmode
)
543 if (m_config
.vtxPitmode
!= vtxPitmode
)
545 m_config
.vtxPitmode
= vtxPitmode
;
546 m_modified
|= VTX_CHANGED
;
551 TxConfig::SetPowerFanThreshold(uint8_t powerFanThreshold
)
553 if (m_config
.powerFanThreshold
!= powerFanThreshold
)
555 m_config
.powerFanThreshold
= powerFanThreshold
;
556 m_modified
|= MAIN_CHANGED
;
561 TxConfig::SetStorageProvider(ELRS_EEPROM
*eeprom
)
570 TxConfig::SetFanMode(uint8_t fanMode
)
572 if (m_config
.fanMode
!= fanMode
)
574 m_config
.fanMode
= fanMode
;
575 m_modified
|= FAN_CHANGED
;
580 TxConfig::SetMotionMode(uint8_t motionMode
)
582 if (m_config
.motionMode
!= motionMode
)
584 m_config
.motionMode
= motionMode
;
585 m_modified
|= MOTION_CHANGED
;
590 TxConfig::SetDvrAux(uint8_t dvrAux
)
592 if (GetDvrAux() != dvrAux
)
594 m_config
.dvrAux
= dvrAux
;
595 m_modified
|= MAIN_CHANGED
;
600 TxConfig::SetDvrStartDelay(uint8_t dvrStartDelay
)
602 if (GetDvrStartDelay() != dvrStartDelay
)
604 m_config
.dvrStartDelay
= dvrStartDelay
;
605 m_modified
|= MAIN_CHANGED
;
610 TxConfig::SetDvrStopDelay(uint8_t dvrStopDelay
)
612 if (GetDvrStopDelay() != dvrStopDelay
)
614 m_config
.dvrStopDelay
= dvrStopDelay
;
615 m_modified
|= MAIN_CHANGED
;
620 TxConfig::SetBackpackDisable(bool backpackDisable
)
622 if (m_config
.backpackDisable
!= backpackDisable
)
624 m_config
.backpackDisable
= backpackDisable
;
625 m_modified
|= MAIN_CHANGED
;
630 TxConfig::SetBackpackTlmMode(uint8_t mode
)
632 if (m_config
.backpackTlmMode
!= mode
)
634 m_config
.backpackTlmMode
= mode
;
635 m_modified
|= MAIN_CHANGED
;
640 TxConfig::SetButtonActions(uint8_t button
, tx_button_color_t
*action
)
642 if (m_config
.buttonColors
[button
].raw
!= action
->raw
) {
643 m_config
.buttonColors
[button
].raw
= action
->raw
;
644 m_modified
|= BUTTON_CHANGED
;
649 TxConfig::SetPTRStartChannel(uint8_t ptrStartChannel
)
651 if (ptrStartChannel
!= m_model
->ptrStartChannel
) {
652 m_model
->ptrStartChannel
= ptrStartChannel
;
653 m_modified
|= MODEL_CHANGED
;
658 TxConfig::SetPTREnableChannel(uint8_t ptrEnableChannel
)
660 if (ptrEnableChannel
!= m_model
->ptrEnableChannel
) {
661 m_model
->ptrEnableChannel
= ptrEnableChannel
;
662 m_modified
|= MODEL_CHANGED
;
667 TxConfig::SetDefaults(bool commit
)
669 // Reset everything to 0/false and then just set anything that zero is not appropriate
670 memset(&m_config
, 0, sizeof(m_config
));
672 m_config
.version
= TX_CONFIG_VERSION
| TX_CONFIG_MAGIC
;
673 m_config
.powerFanThreshold
= PWR_250mW
;
674 m_modified
= ALL_CHANGED
;
678 m_modified
= ALL_CHANGED
;
681 // Set defaults for button 1
682 tx_button_color_t default_actions1
= {
684 .color
= 226, // R:255 G:0 B:182
686 {false, 2, ACTION_BIND
},
687 {true, 0, ACTION_INCREASE_POWER
}
691 m_config
.buttonColors
[0].raw
= default_actions1
.raw
;
693 // Set defaults for button 2
694 tx_button_color_t default_actions2
= {
696 .color
= 3, // R:0 G:0 B:255
698 {false, 1, ACTION_GOTO_VTX_CHANNEL
},
699 {true, 0, ACTION_SEND_VTX
}
703 m_config
.buttonColors
[1].raw
= default_actions2
.raw
;
705 for (unsigned i
=0; i
<CONFIG_TX_MODEL_CNT
; i
++)
708 #if defined(RADIO_SX127X)
709 SetRate(enumRatetoIndex(RATE_LORA_200HZ
));
710 #elif defined(RADIO_LR1121)
711 SetRate(enumRatetoIndex(POWER_OUTPUT_VALUES_COUNT
== 0 ? RATE_LORA_250HZ
: RATE_LORA_200HZ
));
712 #elif defined(RADIO_SX128X)
713 SetRate(enumRatetoIndex(RATE_LORA_2G4_250HZ
));
715 SetPower(POWERMGNT::getDefaultPower());
716 #if defined(PLATFORM_ESP32)
717 // ESP32 nvs needs to commit every model
720 m_modified
|= MODEL_CHANGED
;
726 #if !defined(PLATFORM_ESP32)
727 // ESP8266 just needs one commit
739 * Sets ModelId used for subsequent per-model config gets
740 * Returns: true if the model has changed
743 TxConfig::SetModelId(uint8_t modelId
)
745 model_config_t
*newModel
= &m_config
.model_config
[modelId
];
746 if (newModel
!= m_model
)
757 /////////////////////////////////////////////////////
759 #if defined(TARGET_RX)
761 #if defined(PLATFORM_ESP8266)
762 #include "flash_hal.h"
769 void RxConfig::Load()
772 m_eeprom
->Get(0, m_config
);
774 uint32_t version
= 0;
775 if ((m_config
.version
& CONFIG_MAGIC_MASK
) == RX_CONFIG_MAGIC
)
776 version
= m_config
.version
& ~CONFIG_MAGIC_MASK
;
777 DBGLN("Config version %u", version
);
779 // If version is current, all done
780 if (version
== RX_CONFIG_VERSION
)
782 CheckUpdateFlashedUid(false);
786 // Can't upgrade from version <4, or when flashing a previous version, just use defaults.
787 if (version
< 4 || version
> RX_CONFIG_VERSION
)
790 CheckUpdateFlashedUid(true);
794 // Upgrade EEPROM, starting with defaults
801 m_config
.version
= RX_CONFIG_VERSION
| RX_CONFIG_MAGIC
;
806 void RxConfig::CheckUpdateFlashedUid(bool skipDescrimCheck
)
808 // No binding phrase flashed, nothing to do
809 if (!firmwareOptions
.hasUID
)
811 // If already copied binding info, do not replace
812 if (!skipDescrimCheck
&& m_config
.flash_discriminator
== firmwareOptions
.flash_discriminator
)
815 // Save the new UID along with this discriminator to prevent resetting every boot
816 SetUID(firmwareOptions
.uid
);
817 m_config
.flash_discriminator
= firmwareOptions
.flash_discriminator
;
818 // Reset the power on counter because this is following a flash, may have taken a few boots to flash
819 m_config
.powerOnCounter
= 0;
820 // SetUID should set this but just in case that gets removed, flash_discriminator needs to be saved
826 // ========================================================
829 static void PwmConfigV4(v4_rx_config_pwm_t
const * const v4
, rx_config_pwm_t
* const current
)
831 current
->val
.failsafe
= v4
->val
.failsafe
;
832 current
->val
.inputChannel
= v4
->val
.inputChannel
;
833 current
->val
.inverted
= v4
->val
.inverted
;
836 void RxConfig::UpgradeEepromV4()
838 v4_rx_config_t v4Config
;
839 m_eeprom
->Get(0, v4Config
);
841 if ((v4Config
.version
& ~CONFIG_MAGIC_MASK
) == 4)
843 UpgradeUid(nullptr, v4Config
.isBound
? v4Config
.uid
: nullptr);
844 m_config
.modelId
= v4Config
.modelId
;
845 #if defined(GPIO_PIN_PWM_OUTPUTS)
846 // OG PWMP had only 8 channels
847 for (unsigned ch
=0; ch
<8; ++ch
)
849 PwmConfigV4(&v4Config
.pwmChannels
[ch
], &m_config
.pwmChannels
[ch
]);
855 // ========================================================
858 static void PwmConfigV5(v5_rx_config_pwm_t
const * const v5
, rx_config_pwm_t
* const current
)
860 current
->val
.failsafe
= v5
->val
.failsafe
;
861 current
->val
.inputChannel
= v5
->val
.inputChannel
;
862 current
->val
.inverted
= v5
->val
.inverted
;
863 current
->val
.narrow
= v5
->val
.narrow
;
864 current
->val
.mode
= v5
->val
.mode
;
865 if (v5
->val
.mode
> som400Hz
)
867 current
->val
.mode
+= 1;
871 void RxConfig::UpgradeEepromV5()
873 v5_rx_config_t v5Config
;
874 m_eeprom
->Get(0, v5Config
);
876 if ((v5Config
.version
& ~CONFIG_MAGIC_MASK
) == 5)
878 UpgradeUid(v5Config
.onLoan
? v5Config
.loanUID
: nullptr, v5Config
.isBound
? v5Config
.uid
: nullptr);
879 m_config
.vbat
.scale
= v5Config
.vbatScale
;
880 m_config
.power
= v5Config
.power
;
881 m_config
.antennaMode
= v5Config
.antennaMode
;
882 m_config
.forceTlmOff
= v5Config
.forceTlmOff
;
883 m_config
.rateInitialIdx
= v5Config
.rateInitialIdx
;
884 m_config
.modelId
= v5Config
.modelId
;
886 #if defined(GPIO_PIN_PWM_OUTPUTS)
887 for (unsigned ch
=0; ch
<16; ++ch
)
889 PwmConfigV5(&v5Config
.pwmChannels
[ch
], &m_config
.pwmChannels
[ch
]);
895 // ========================================================
898 static void PwmConfigV6(v6_rx_config_pwm_t
const * const v6
, rx_config_pwm_t
* const current
)
900 current
->val
.failsafe
= v6
->val
.failsafe
;
901 current
->val
.inputChannel
= v6
->val
.inputChannel
;
902 current
->val
.inverted
= v6
->val
.inverted
;
903 current
->val
.narrow
= v6
->val
.narrow
;
904 current
->val
.mode
= v6
->val
.mode
;
907 void RxConfig::UpgradeEepromV6()
909 v6_rx_config_t v6Config
;
910 m_eeprom
->Get(0, v6Config
);
912 if ((v6Config
.version
& ~CONFIG_MAGIC_MASK
) == 6)
914 UpgradeUid(v6Config
.onLoan
? v6Config
.loanUID
: nullptr, v6Config
.isBound
? v6Config
.uid
: nullptr);
915 m_config
.vbat
.scale
= v6Config
.vbatScale
;
916 m_config
.power
= v6Config
.power
;
917 m_config
.antennaMode
= v6Config
.antennaMode
;
918 m_config
.forceTlmOff
= v6Config
.forceTlmOff
;
919 m_config
.rateInitialIdx
= v6Config
.rateInitialIdx
;
920 m_config
.modelId
= v6Config
.modelId
;
922 #if defined(GPIO_PIN_PWM_OUTPUTS)
923 for (unsigned ch
=0; ch
<16; ++ch
)
925 PwmConfigV6(&v6Config
.pwmChannels
[ch
], &m_config
.pwmChannels
[ch
]);
931 // ========================================================
934 void RxConfig::UpgradeEepromV7V8()
936 v7_rx_config_t v7Config
;
937 m_eeprom
->Get(0, v7Config
);
939 bool isV8
= (v7Config
.version
& ~CONFIG_MAGIC_MASK
) == 8;
940 if (isV8
|| (v7Config
.version
& ~CONFIG_MAGIC_MASK
) == 7)
942 UpgradeUid(v7Config
.onLoan
? v7Config
.loanUID
: nullptr, v7Config
.isBound
? v7Config
.uid
: nullptr);
944 m_config
.vbat
.scale
= v7Config
.vbatScale
;
945 m_config
.power
= v7Config
.power
;
946 m_config
.antennaMode
= v7Config
.antennaMode
;
947 m_config
.forceTlmOff
= v7Config
.forceTlmOff
;
948 m_config
.rateInitialIdx
= v7Config
.rateInitialIdx
;
949 m_config
.modelId
= v7Config
.modelId
;
950 m_config
.serialProtocol
= v7Config
.serialProtocol
;
951 m_config
.failsafeMode
= v7Config
.failsafeMode
;
953 #if defined(GPIO_PIN_PWM_OUTPUTS)
954 for (unsigned ch
=0; ch
<16; ++ch
)
956 m_config
.pwmChannels
[ch
].raw
= v7Config
.pwmChannels
[ch
].raw
;
957 if (!isV8
&& m_config
.pwmChannels
[ch
].val
.mode
> somOnOff
)
958 m_config
.pwmChannels
[ch
].val
.mode
+= 1;
964 // ========================================================
967 void RxConfig::UpgradeEepromV9()
969 v9_rx_config_t v9Config
;
970 m_eeprom
->Get(0, v9Config
);
972 if ((v9Config
.version
& ~CONFIG_MAGIC_MASK
) == 9)
974 m_config
.powerOnCounter
= v9Config
.powerOnCounter
;
975 m_config
.forceTlmOff
= v9Config
.forceTlmOff
;
976 m_config
.rateInitialIdx
= v9Config
.rateInitialIdx
;
980 void RxConfig::UpgradeUid(uint8_t *onLoanUid
, uint8_t *boundUid
)
982 // Convert to traditional binding
983 // On loan? Now you own
986 memcpy(m_config
.uid
, onLoanUid
, UID_LEN
);
988 // Compiled in UID? Bind to that
989 else if (firmwareOptions
.hasUID
)
991 memcpy(m_config
.uid
, firmwareOptions
.uid
, UID_LEN
);
992 m_config
.flash_discriminator
= firmwareOptions
.flash_discriminator
;
997 memcpy(m_config
.uid
, boundUid
, UID_LEN
);
1002 memset(m_config
.uid
, 0, UID_LEN
);
1006 bool RxConfig::GetIsBound() const
1008 if (m_config
.bindStorage
== BINDSTORAGE_VOLATILE
)
1010 return UID_IS_BOUND(m_config
.uid
);
1013 bool RxConfig::IsOnLoan() const
1015 if (m_config
.bindStorage
!= BINDSTORAGE_RETURNABLE
)
1017 if (!firmwareOptions
.hasUID
)
1019 return GetIsBound() && memcmp(m_config
.uid
, firmwareOptions
.uid
, UID_LEN
) != 0;
1022 #if defined(PLATFORM_ESP8266)
1023 #define EMPTY_SECTOR ((FS_start - 0x1000 - 0x40200000) / SPI_FLASH_SEC_SIZE) // empty sector before FS area start
1024 static bool erase_power_on_count
= false;
1025 static int realPowerOnCounter
= -1;
1027 RxConfig::GetPowerOnCounter() const
1029 if (realPowerOnCounter
== -1) {
1031 ESP
.flashRead(EMPTY_SECTOR
* SPI_FLASH_SEC_SIZE
, zeros
, sizeof(zeros
));
1032 realPowerOnCounter
= sizeof(zeros
);
1033 for (int i
=0 ; i
<sizeof(zeros
) ; i
++) {
1034 if (zeros
[i
] != 0) {
1035 realPowerOnCounter
= i
;
1040 return realPowerOnCounter
;
1047 #if defined(PLATFORM_ESP8266)
1048 if (erase_power_on_count
)
1050 ESP
.flashEraseSector(EMPTY_SECTOR
);
1051 erase_power_on_count
= false;
1060 // Write the struct to eeprom
1061 m_eeprom
->Put(0, m_config
);
1069 RxConfig::SetUID(uint8_t* uid
)
1071 for (uint8_t i
= 0; i
< UID_LEN
; ++i
)
1073 m_config
.uid
[i
] = uid
[i
];
1079 RxConfig::SetPowerOnCounter(uint8_t powerOnCounter
)
1081 #if defined(PLATFORM_ESP8266)
1082 realPowerOnCounter
= powerOnCounter
;
1083 if (powerOnCounter
== 0)
1085 erase_power_on_count
= true;
1090 byte zeros
[16] = {0};
1091 ESP
.flashWrite(EMPTY_SECTOR
* SPI_FLASH_SEC_SIZE
, zeros
, std::min((size_t)powerOnCounter
, sizeof(zeros
)));
1094 if (m_config
.powerOnCounter
!= powerOnCounter
)
1096 m_config
.powerOnCounter
= powerOnCounter
;
1103 RxConfig::SetModelId(uint8_t modelId
)
1105 if (m_config
.modelId
!= modelId
)
1107 m_config
.modelId
= modelId
;
1113 RxConfig::SetPower(uint8_t power
)
1115 if (m_config
.power
!= power
)
1117 m_config
.power
= power
;
1124 RxConfig::SetAntennaMode(uint8_t antennaMode
)
1126 //0 and 1 is use for gpio_antenna_select
1128 if (m_config
.antennaMode
!= antennaMode
)
1130 m_config
.antennaMode
= antennaMode
;
1136 RxConfig::SetDefaults(bool commit
)
1138 // Reset everything to 0/false and then just set anything that zero is not appropriate
1139 memset(&m_config
, 0, sizeof(m_config
));
1141 m_config
.version
= RX_CONFIG_VERSION
| RX_CONFIG_MAGIC
;
1142 m_config
.modelId
= 0xff;
1143 m_config
.power
= POWERMGNT::getDefaultPower();
1144 if (GPIO_PIN_ANT_CTRL
!= UNDEF_PIN
)
1145 m_config
.antennaMode
= 2; // 2 is diversity
1146 if (GPIO_PIN_NSS_2
!= UNDEF_PIN
)
1147 m_config
.antennaMode
= 0; // 0 is diversity for dual radio
1149 #if defined(GPIO_PIN_PWM_OUTPUTS)
1150 for (int ch
=0; ch
<PWM_MAX_CHANNELS
; ++ch
)
1152 uint8_t mode
= som50Hz
;
1153 // setup defaults for hardware defined I2C pins that are also IO pins
1154 if (ch
< GPIO_PIN_PWM_OUTPUTS_COUNT
)
1156 if (GPIO_PIN_PWM_OUTPUTS
[ch
] == GPIO_PIN_SCL
)
1160 else if (GPIO_PIN_PWM_OUTPUTS
[ch
] == GPIO_PIN_SDA
)
1165 SetPwmChannel(ch
, 512, ch
, false, mode
, false);
1167 SetPwmChannel(2, 0, 2, false, 0, false); // ch2 is throttle, failsafe it to 988
1170 m_config
.teamraceChannel
= AUX7
; // CH11
1172 #if defined(RCVR_INVERT_TX)
1173 m_config
.serialProtocol
= PROTOCOL_INVERTED_CRSF
;
1178 // Prevent rebinding to the flashed UID on first boot
1179 m_config
.flash_discriminator
= firmwareOptions
.flash_discriminator
;
1186 RxConfig::SetStorageProvider(ELRS_EEPROM
*eeprom
)
1194 #if defined(GPIO_PIN_PWM_OUTPUTS)
1196 RxConfig::SetPwmChannel(uint8_t ch
, uint16_t failsafe
, uint8_t inputCh
, bool inverted
, uint8_t mode
, bool narrow
)
1198 if (ch
> PWM_MAX_CHANNELS
)
1201 rx_config_pwm_t
*pwm
= &m_config
.pwmChannels
[ch
];
1202 rx_config_pwm_t newConfig
;
1203 newConfig
.val
.failsafe
= failsafe
;
1204 newConfig
.val
.inputChannel
= inputCh
;
1205 newConfig
.val
.inverted
= inverted
;
1206 newConfig
.val
.mode
= mode
;
1207 newConfig
.val
.narrow
= narrow
;
1208 if (pwm
->raw
== newConfig
.raw
)
1211 pwm
->raw
= newConfig
.raw
;
1216 RxConfig::SetPwmChannelRaw(uint8_t ch
, uint32_t raw
)
1218 if (ch
> PWM_MAX_CHANNELS
)
1221 rx_config_pwm_t
*pwm
= &m_config
.pwmChannels
[ch
];
1222 if (pwm
->raw
== raw
)
1231 RxConfig::SetForceTlmOff(bool forceTlmOff
)
1233 if (m_config
.forceTlmOff
!= forceTlmOff
)
1235 m_config
.forceTlmOff
= forceTlmOff
;
1241 RxConfig::SetRateInitialIdx(uint8_t rateInitialIdx
)
1243 if (m_config
.rateInitialIdx
!= rateInitialIdx
)
1245 m_config
.rateInitialIdx
= rateInitialIdx
;
1250 void RxConfig::SetSerialProtocol(eSerialProtocol serialProtocol
)
1252 if (m_config
.serialProtocol
!= serialProtocol
)
1254 m_config
.serialProtocol
= serialProtocol
;
1259 #if defined(PLATFORM_ESP32)
1260 void RxConfig::SetSerial1Protocol(eSerial1Protocol serialProtocol
)
1262 if (m_config
.serial1Protocol
!= serialProtocol
)
1264 m_config
.serial1Protocol
= serialProtocol
;
1270 void RxConfig::SetTeamraceChannel(uint8_t teamraceChannel
)
1272 if (m_config
.teamraceChannel
!= teamraceChannel
)
1274 m_config
.teamraceChannel
= teamraceChannel
;
1279 void RxConfig::SetTeamracePosition(uint8_t teamracePosition
)
1281 if (m_config
.teamracePosition
!= teamracePosition
)
1283 m_config
.teamracePosition
= teamracePosition
;
1288 void RxConfig::SetFailsafeMode(eFailsafeMode failsafeMode
)
1290 if (m_config
.failsafeMode
!= failsafeMode
)
1292 m_config
.failsafeMode
= failsafeMode
;
1297 void RxConfig::SetBindStorage(rx_config_bindstorage_t value
)
1299 if (m_config
.bindStorage
!= value
)
1301 // If switching away from returnable, revert
1303 m_config
.bindStorage
= value
;
1308 void RxConfig::SetTargetSysId(uint8_t value
)
1310 if (m_config
.targetSysId
!= value
)
1312 m_config
.targetSysId
= value
;
1316 void RxConfig::SetSourceSysId(uint8_t value
)
1318 if (m_config
.sourceSysId
!= value
)
1320 m_config
.sourceSysId
= value
;
1325 void RxConfig::ReturnLoan()
1329 // go back to flashed UID if there is one
1330 // or unbind if there is not
1331 if (firmwareOptions
.hasUID
)
1332 memcpy(m_config
.uid
, firmwareOptions
.uid
, UID_LEN
);
1334 memset(m_config
.uid
, 0, UID_LEN
);