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"
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
39 div_t qr
= div(abs(index
)-1, 3);
41 if (index
< 0 && switchConfig
[qr
.quot
] != Board::SWITCH_3POS
)
44 return switchConfig
[qr
.quot
] == Board::SWITCH_3POS
;
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
))
58 return potConfig
[index
] != Board::POT_NONE
;
61 bool GeneralSettings::isSliderAvailable(int index
) const
63 if (index
< 0 || index
> getBoardCapability(getCurrentBoard(), Board::Sliders
))
65 return sliderConfig
[index
] != Board::SLIDER_NONE
;
68 GeneralSettings::GeneralSettings()
70 memset(reinterpret_cast<void *>(this), 0, sizeof(GeneralSettings
));
74 for (int i
=0; i
< CPN_MAX_ANALOGS
; ++i
) {
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
85 if (IS_TARANIS_X9E(board
) || IS_HORUS_X12S(board
)) {
91 else if (IS_TARANIS_XLITE(board
) || IS_HORUS_X10(board
) || IS_JUMPER_T16(board
)) {
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
104 setDefaultControlTypes(board
);
106 backlightMode
= 3; // keys and sticks
107 // backlightBright = 0; // 0 = 100%
109 if (IS_HORUS(board
)) {
110 backlightOffBright
= 20;
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)) {
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);
151 Byte
=t_calib
.mid(4+i
*12,4);
152 byte16
=(int16_t)Byte
.toInt(&ok
,16);
154 calibSpanNeg
[i
]=byte16
;
155 Byte
=t_calib
.mid(8+i
*12,4);
156 byte16
=(int16_t)Byte
.toInt(&ok
,16);
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);
164 trainer
.calib
[i
]=byte16
;
166 txCurrentCalibration
=t_txCurrentCalibration
;
167 txVoltageCalibration
=t_txVoltageCalibration
;
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)) {
176 byte8
=(int8_t)t_DisplaySet
.mid(0,2).toInt(&ok
,16);
178 optrexDisplay
=(byte8
==1 ? true : false);
179 byte8u
=(uint8_t)t_DisplaySet
.mid(2,2).toUInt(&ok
,16);
182 byte8u
=(uint8_t)t_DisplaySet
.mid(4,2).toUInt(&ok
,16);
184 backlightBright
=byte8u
;
185 byte8
=(int8_t)t_BeeperSet
.mid(0,2).toUInt(&ok
,16);
187 beeperMode
=(BeeperMode
)byte8
;
188 byte8
=(int8_t)t_BeeperSet
.mid(2,2).toInt(&ok
,16);
191 byte8
=(int8_t)t_HapticSet
.mid(0,2).toUInt(&ok
,16);
193 hapticMode
=(BeeperMode
)byte8
;
194 byte8
=(int8_t)t_HapticSet
.mid(2,2).toInt(&ok
,16);
196 hapticStrength
=byte8
;
197 byte8
=(int8_t)t_HapticSet
.mid(4,2).toInt(&ok
,16);
200 byte8u
=(uint8_t)t_SpeakerSet
.mid(0,2).toUInt(&ok
,16);
203 byte8u
=(uint8_t)t_SpeakerSet
.mid(2,2).toUInt(&ok
,16);
206 byte8u
=(uint8_t)t_SpeakerSet
.mid(4,2).toUInt(&ok
,16);
208 speakerVolume
=byte8u
;
209 if (t_CountrySet
.length()==6) {
210 byte8u
=(uint8_t)t_CountrySet
.mid(0,2).toUInt(&ok
,16);
213 byte8u
=(uint8_t)t_CountrySet
.mid(2,2).toUInt(&ok
,16);
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
;
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
)
281 return chout_ar
[4*templateSetup
+ channel
] - 1;
284 RawSource
GeneralSettings::getDefaultSource(unsigned int channel
) const
286 int stick
= getDefaultStick(channel
);
288 return RawSource(SOURCE_TYPE_STICK
, stick
);
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
)
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
));