Make TX volatge for simu more flexible (#7124)
[opentx.git] / companion / src / firmwares / generalsettings.cpp
blob22934cf579c1c1abdc527007f7d243bdfe356436
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
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.
21 #include "generalsettings.h"
23 #include "appdata.h"
24 #include "eeprominterface.h"
25 #include "radiodataconversionstate.h"
27 const uint8_t chout_ar[] = { // First number is 0..23 -> template setup, Second is relevant channel out
28 1,2,3,4 , 1,2,4,3 , 1,3,2,4 , 1,3,4,2 , 1,4,2,3 , 1,4,3,2,
29 2,1,3,4 , 2,1,4,3 , 2,3,1,4 , 2,3,4,1 , 2,4,1,3 , 2,4,3,1,
30 3,1,2,4 , 3,1,4,2 , 3,2,1,4 , 3,2,4,1 , 3,4,1,2 , 3,4,2,1,
31 4,1,2,3 , 4,1,3,2 , 4,2,1,3 , 4,2,3,1 , 4,3,1,2 , 4,3,2,1
34 bool GeneralSettings::switchPositionAllowedTaranis(int index) const
36 if (index == 0)
37 return true;
39 div_t qr = div(abs(index)-1, 3);
41 if (index < 0 && switchConfig[qr.quot] != Board::SWITCH_3POS)
42 return false;
43 else if (qr.rem == 1)
44 return switchConfig[qr.quot] == Board::SWITCH_3POS;
45 else
46 return switchConfig[qr.quot] != Board::SWITCH_NOT_AVAILABLE;
49 bool GeneralSettings::switchSourceAllowedTaranis(int index) const
51 return switchConfig[index] != Board::SWITCH_NOT_AVAILABLE;
54 bool GeneralSettings::isPotAvailable(int index) const
56 if (index < 0 || index > getBoardCapability(getCurrentBoard(), Board::Pots))
57 return false;
58 return potConfig[index] != Board::POT_NONE;
61 bool GeneralSettings::isSliderAvailable(int index) const
63 if (index < 0 || index > getBoardCapability(getCurrentBoard(), Board::Sliders))
64 return false;
65 return sliderConfig[index] != Board::SLIDER_NONE;
68 GeneralSettings::GeneralSettings()
70 memset(reinterpret_cast<void *>(this), 0, sizeof(GeneralSettings));
72 contrast = 25;
74 for (int i=0; i < CPN_MAX_ANALOGS; ++i) {
75 calibMid[i] = 0x200;
76 calibSpanNeg[i] = 0x180;
77 calibSpanPos[i] = 0x180;
80 Firmware * firmware = Firmware::getCurrentVariant();
81 Board::Type board = firmware->getBoard();
83 // vBatWarn is voltage in 100mV, vBatMin is in 100mV but with -9V offset, vBatMax has a -12V offset
84 vBatWarn = 90;
85 if (IS_TARANIS_X9E(board) || IS_HORUS_X12S(board)) {
86 // NI-MH 9.6V
87 vBatWarn = 87;
88 vBatMin = -5; //8,5V
89 vBatMax = -5; //11,5V
91 else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) {
92 // Lipo 2S
93 vBatWarn = 66;
94 vBatMin = -23; // 6.7V
95 vBatMax = -37; // 8.3V
97 else if (IS_TARANIS(board)) {
98 // NI-MH 7.2V, X9D, X9D+ and X7
99 vBatWarn = 65;
100 vBatMin = -30; //6V
101 vBatMax = -40; //8V
104 setDefaultControlTypes(board);
106 backlightMode = 3; // keys and sticks
107 // backlightBright = 0; // 0 = 100%
109 if (IS_HORUS(board)) {
110 backlightOffBright = 20;
113 if (IS_ARM(board)) {
114 speakerVolume = 12;
117 if (IS_HORUS(board)) {
118 strcpy(bluetoothName, "Horus");
120 else if (IS_TARANIS_X9E(board) || IS_TARANIS_SMALL(board)) {
121 strcpy(bluetoothName, "Taranis");
124 templateSetup = g.profile[g.sessionId()].channelOrder();
125 stickMode = g.profile[g.sessionId()].defaultMode();
127 QString t_calib = g.profile[g.sessionId()].stickPotCalib();
128 int potsnum = getBoardCapability(getCurrentBoard(), Board::Pots);
129 if (!t_calib.isEmpty()) {
130 QString t_trainercalib=g.profile[g.sessionId()].trainerCalib();
131 int8_t t_txVoltageCalibration=(int8_t)g.profile[g.sessionId()].txVoltageCalibration();
132 int8_t t_txCurrentCalibration=(int8_t)g.profile[g.sessionId()].txCurrentCalibration();
133 int8_t t_PPM_Multiplier=(int8_t)g.profile[g.sessionId()].ppmMultiplier();
134 uint8_t t_stickMode=(uint8_t)g.profile[g.sessionId()].gsStickMode();
135 uint8_t t_vBatWarn=(uint8_t)g.profile[g.sessionId()].vBatWarn();
136 QString t_DisplaySet=g.profile[g.sessionId()].display();
137 QString t_BeeperSet=g.profile[g.sessionId()].beeper();
138 QString t_HapticSet=g.profile[g.sessionId()].haptic();
139 QString t_SpeakerSet=g.profile[g.sessionId()].speaker();
140 QString t_CountrySet=g.profile[g.sessionId()].countryCode();
142 if ((t_calib.length()==(CPN_MAX_STICKS+potsnum)*12) && (t_trainercalib.length()==16)) {
143 QString Byte;
144 int16_t byte16;
145 bool ok;
146 for (int i=0; i<(CPN_MAX_STICKS+potsnum); i++) {
147 Byte=t_calib.mid(i*12,4);
148 byte16=(int16_t)Byte.toInt(&ok,16);
149 if (ok)
150 calibMid[i]=byte16;
151 Byte=t_calib.mid(4+i*12,4);
152 byte16=(int16_t)Byte.toInt(&ok,16);
153 if (ok)
154 calibSpanNeg[i]=byte16;
155 Byte=t_calib.mid(8+i*12,4);
156 byte16=(int16_t)Byte.toInt(&ok,16);
157 if (ok)
158 calibSpanPos[i]=byte16;
160 for (int i=0; i<4; i++) {
161 Byte=t_trainercalib.mid(i*4,4);
162 byte16=(int16_t)Byte.toInt(&ok,16);
163 if (ok)
164 trainer.calib[i]=byte16;
166 txCurrentCalibration=t_txCurrentCalibration;
167 txVoltageCalibration=t_txVoltageCalibration;
168 vBatWarn=t_vBatWarn;
169 PPM_Multiplier=t_PPM_Multiplier;
170 stickMode = t_stickMode;
172 if ((t_DisplaySet.length()==6) && (t_BeeperSet.length()==4) && (t_HapticSet.length()==6) && (t_SpeakerSet.length()==6)) {
173 uint8_t byte8u;
174 int8_t byte8;
175 bool ok;
176 byte8=(int8_t)t_DisplaySet.mid(0,2).toInt(&ok,16);
177 if (ok)
178 optrexDisplay=(byte8==1 ? true : false);
179 byte8u=(uint8_t)t_DisplaySet.mid(2,2).toUInt(&ok,16);
180 if (ok)
181 contrast=byte8u;
182 byte8u=(uint8_t)t_DisplaySet.mid(4,2).toUInt(&ok,16);
183 if (ok)
184 backlightBright=byte8u;
185 byte8=(int8_t)t_BeeperSet.mid(0,2).toUInt(&ok,16);
186 if (ok)
187 beeperMode=(BeeperMode)byte8;
188 byte8=(int8_t)t_BeeperSet.mid(2,2).toInt(&ok,16);
189 if (ok)
190 beeperLength=byte8;
191 byte8=(int8_t)t_HapticSet.mid(0,2).toUInt(&ok,16);
192 if (ok)
193 hapticMode=(BeeperMode)byte8;
194 byte8=(int8_t)t_HapticSet.mid(2,2).toInt(&ok,16);
195 if (ok)
196 hapticStrength=byte8;
197 byte8=(int8_t)t_HapticSet.mid(4,2).toInt(&ok,16);
198 if (ok)
199 hapticLength=byte8;
200 byte8u=(uint8_t)t_SpeakerSet.mid(0,2).toUInt(&ok,16);
201 if (ok)
202 speakerMode=byte8u;
203 byte8u=(uint8_t)t_SpeakerSet.mid(2,2).toUInt(&ok,16);
204 if (ok)
205 speakerPitch=byte8u;
206 byte8u=(uint8_t)t_SpeakerSet.mid(4,2).toUInt(&ok,16);
207 if (ok)
208 speakerVolume=byte8u;
209 if (t_CountrySet.length()==6) {
210 byte8u=(uint8_t)t_CountrySet.mid(0,2).toUInt(&ok,16);
211 if (ok)
212 countryCode=byte8u;
213 byte8u=(uint8_t)t_CountrySet.mid(2,2).toUInt(&ok,16);
214 if (ok)
215 imperial=byte8u;
216 QString chars = t_CountrySet.mid(4, 2);
217 ttsLanguage[0] = chars[0].toLatin1();
218 ttsLanguage[1] = chars[1].toLatin1();
223 strcpy(themeName, "default");
224 ThemeOptionData option1 = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
225 memcpy(&themeOptionValue[0], option1, sizeof(ThemeOptionData));
226 ThemeOptionData option2 = { 0x03, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0 };
227 memcpy(&themeOptionValue[1], option2, sizeof(ThemeOptionData));
230 void GeneralSettings::setDefaultControlTypes(Board::Type board)
232 for (int i=0; i<getBoardCapability(board, Board::FactoryInstalledSwitches); i++) {
233 switchConfig[i] = Boards::getSwitchInfo(board, i).config;
236 // TODO: move to Boards, like with switches
237 if (IS_HORUS(board)) {
238 potConfig[0] = Board::POT_WITH_DETENT;
239 potConfig[1] = Board::POT_MULTIPOS_SWITCH;
240 potConfig[2] = Board::POT_WITH_DETENT;
242 else if (IS_TARANIS_XLITE(board)) {
243 potConfig[0] = Board::POT_WITHOUT_DETENT;
244 potConfig[1] = Board::POT_WITHOUT_DETENT;
246 else if (IS_TARANIS_X7(board)) {
247 potConfig[0] = Board::POT_WITHOUT_DETENT;
248 potConfig[1] = Board::POT_WITH_DETENT;
250 else if (IS_TARANIS(board)) {
251 potConfig[0] = Board::POT_WITH_DETENT;
252 potConfig[1] = Board::POT_WITH_DETENT;
254 else if (IS_JUMPER_T12(board)) {
255 potConfig[0] = Board::POT_WITH_DETENT;
256 potConfig[1] = Board::POT_WITH_DETENT;
258 else {
259 potConfig[0] = Board::POT_WITHOUT_DETENT;
260 potConfig[1] = Board::POT_WITHOUT_DETENT;
261 potConfig[2] = Board::POT_WITHOUT_DETENT;
264 if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board)) {
265 sliderConfig[0] = Board::SLIDER_WITH_DETENT;
266 sliderConfig[1] = Board::SLIDER_WITH_DETENT;
267 sliderConfig[2] = Board::SLIDER_WITH_DETENT;
268 sliderConfig[3] = Board::SLIDER_WITH_DETENT;
270 else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) {
271 sliderConfig[0] = Board::SLIDER_WITH_DETENT;
272 sliderConfig[1] = Board::SLIDER_WITH_DETENT;
276 int GeneralSettings::getDefaultStick(unsigned int channel) const
278 if (channel >= CPN_MAX_STICKS)
279 return -1;
280 else
281 return chout_ar[4*templateSetup + channel] - 1;
284 RawSource GeneralSettings::getDefaultSource(unsigned int channel) const
286 int stick = getDefaultStick(channel);
287 if (stick >= 0)
288 return RawSource(SOURCE_TYPE_STICK, stick);
289 else
290 return RawSource(SOURCE_TYPE_NONE);
293 int GeneralSettings::getDefaultChannel(unsigned int stick) const
295 for (int i=0; i<4; i++){
296 if (getDefaultStick(i) == (int)stick)
297 return i;
299 return -1;
302 void GeneralSettings::convert(RadioDataConversionState & cstate)
304 // Here we can add explicit conversions when moving from one board to another
306 cstate.setOrigin(tr("Radio Settings"));
308 setDefaultControlTypes(cstate.toType); // start with default switches/pots/sliders
310 // Try to intelligently copy any custom control names
312 // SE and SG are skipped on X7 board
313 if (IS_TARANIS_X7(cstate.toType)) {
314 if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
315 strncpy(switchName[4], switchName[5], sizeof(switchName[4]));
316 strncpy(switchName[5], switchName[7], sizeof(switchName[5]));
319 else if (IS_TARANIS_X7(cstate.fromType)) {
320 if (IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) {
321 strncpy(switchName[5], switchName[4], sizeof(switchName[5]));
322 strncpy(switchName[7], switchName[5], sizeof(switchName[7]));
326 if (IS_JUMPER_T12(cstate.toType)) {
327 if (IS_TARANIS_X9(cstate.fromType) || IS_HORUS(cstate.fromType)) {
328 strncpy(switchName[4], switchName[5], sizeof(switchName[0]));
329 strncpy(switchName[5], switchName[7], sizeof(switchName[0]));
333 else if (IS_JUMPER_T12(cstate.fromType)) {
334 if (IS_TARANIS_X9(cstate.toType) || IS_HORUS(cstate.toType)) {
335 strncpy(switchName[5], switchName[4], sizeof(switchName[0]));
336 strncpy(switchName[7], switchName[5], sizeof(switchName[0]));
340 // LS and RS sliders are after 2 aux sliders on X12 and X9E
341 if ((IS_HORUS_X12S(cstate.toType) || IS_TARANIS_X9E(cstate.toType)) && !IS_HORUS_X12S(cstate.fromType) && !IS_TARANIS_X9E(cstate.fromType)) {
342 strncpy(sliderName[0], sliderName[2], sizeof(sliderName[0]));
343 strncpy(sliderName[1], sliderName[3], sizeof(sliderName[1]));
345 else if (!IS_TARANIS_X9E(cstate.toType) && !IS_HORUS_X12S(cstate.toType) && (IS_HORUS_X12S(cstate.fromType) || IS_TARANIS_X9E(cstate.fromType))) {
346 strncpy(sliderName[2], sliderName[0], sizeof(sliderName[2]));
347 strncpy(sliderName[3], sliderName[1], sizeof(sliderName[3]));
350 if (IS_HORUS(cstate.toType)) {
351 // 6P switch is only on Horus (by default)
352 if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) == 2) {
353 strncpy(potName[2], potName[1], sizeof(potName[2]));
354 potName[1][0] = '\0';
358 if (IS_TARANIS(cstate.toType)) {
359 // No S3 pot on Taranis boards by default
360 if (cstate.fromBoard.getCapability(Board::FactoryInstalledPots) > 2)
361 strncpy(potName[1], potName[2], sizeof(potName[1]));
363 contrast = qBound<int>(getCurrentFirmware()->getCapability(MinContrast), contrast, getCurrentFirmware()->getCapability(MaxContrast));
366 // TODO: Would be nice at this point to have GUI pause and ask the user to set up any custom hardware they have on the destination radio.
368 // Convert all global functions (do this after HW adjustments)
369 for (int i=0; i<CPN_MAX_SPECIAL_FUNCTIONS; i++) {
370 customFn[i].convert(cstate.withComponentIndex(i));