Make TX volatge for simu more flexible (#7124)
[opentx.git] / companion / src / firmwares / er9x / er9xeeprom.cpp
blob82655d1d3aa282d45f8b5fbbdf7102a45563ab06
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 <algorithm>
22 #include "er9xeeprom.h"
23 #include "helpers.h"
24 #include <QObject>
26 RawSwitch er9xToSwitch(int8_t sw)
28 uint8_t swa = abs(sw);
29 if (swa == 0)
30 return RawSwitch(SWITCH_TYPE_NONE);
31 else if (swa <= 9)
32 return RawSwitch(SWITCH_TYPE_SWITCH, sw);
33 else if (swa <= 21)
34 return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-9 : sw+9);
35 else if (sw == 22)
36 return RawSwitch(SWITCH_TYPE_ON);
37 else if (sw == -22)
38 return RawSwitch(SWITCH_TYPE_OFF);
39 else if (swa <= 22+9)
40 return RawSwitch(SWITCH_TYPE_SWITCH, sw > 0 ? sw-22 : sw+22);
41 else
42 return RawSwitch(SWITCH_TYPE_VIRTUAL, sw > 0 ? sw-22-9 : sw+22+9);
45 t_Er9xTrainerMix::t_Er9xTrainerMix()
47 memset(this, 0, sizeof(t_Er9xTrainerMix));
50 t_Er9xTrainerMix::operator TrainerMix()
52 TrainerMix c9x;
53 c9x.src = srcChn;
54 c9x.swtch = er9xToSwitch(swtch);
55 c9x.weight = (25 * studWeight) / 8;
56 c9x.mode = mode;
57 return c9x;
60 t_Er9xTrainerData::t_Er9xTrainerData()
62 memset(reinterpret_cast<void *>(this), 0, sizeof(t_Er9xTrainerData));
65 t_Er9xTrainerData::operator TrainerData ()
67 TrainerData c9x;
68 for (int i=0; i<CPN_MAX_STICKS; i++) {
69 c9x.calib[i] = calib[i];
70 c9x.mix[i] = mix[i];
72 return c9x;
75 t_Er9xGeneral::t_Er9xGeneral()
77 memset(reinterpret_cast<void *>(this), 0, sizeof(t_Er9xGeneral));
80 Er9xGeneral::operator GeneralSettings ()
82 GeneralSettings result;
83 result.version = myVers;
84 for (int i=0; i<CPN_MAX_STICKSnPOTS; i++) {
85 result.calibMid[i] = calibMid[i];
86 result.calibSpanNeg[i] = calibSpanNeg[i];
87 result.calibSpanPos[i] = calibSpanPos[i];
90 result.currModelIndex = currModel;
91 result.contrast = contrast;
92 result.vBatWarn = vBatWarn;
93 result.txVoltageCalibration = txVoltageCalibration;
94 result.trainer = trainer;
96 result.view = std::min((uint8_t)4, view);
97 result.disableThrottleWarning = disableThrottleWarning;
98 result.disableMemoryWarning = disableMemoryWarning;
100 switch (beeperVal) {
101 case 0:
102 result.beeperMode = GeneralSettings::BEEPER_QUIET;
103 break;
104 case 1:
105 result.beeperMode = GeneralSettings::BEEPER_NOKEYS;
106 break;
107 default:
108 result.beeperMode = GeneralSettings::BEEPER_ALL;
109 result.beeperLength = beeperVal - 4;
110 break;
113 result.disableAlarmWarning = disableAlarmWarning;
114 result.stickMode = std::max((uint8_t)0, std::min(stickMode, (uint8_t)3));
115 result.inactivityTimer = inactivityTimer + 10;
116 result.minuteBeep = minuteBeep;
117 result.preBeep = preBeep;
118 result.flashBeep = flashBeep;
119 result.splashMode = disableSplashScreen;
121 result.backlightMode = 0;
122 if (lightSw == 22) {
123 result.backlightMode = 4;
125 else if (lightAutoOff) {
126 result.backlightMode |= 1;
127 result.backlightDelay = lightAutoOff;
129 else if (lightOnStickMove) {
130 result.backlightMode |= 2;
131 result.backlightDelay = lightOnStickMove;
134 result.templateSetup = templateSetup;
135 result.PPM_Multiplier = PPM_Multiplier;
136 getEEPROMString(result.ownerName, ownerName, sizeof(ownerName));
137 result.speakerPitch = speakerPitch;
138 result.hapticStrength = hapticStrength - 3;
139 result.speakerMode = speakerMode;
140 return result;
143 t_Er9xLimitData::t_Er9xLimitData()
145 memset(this, 0, sizeof(t_Er9xLimitData));
148 t_Er9xLimitData::operator LimitData ()
150 LimitData c9x;
151 c9x.min = 10*(min-100);
152 c9x.max = 10*(max+100);
153 c9x.revert = revert;
154 c9x.offset = offset;
155 return c9x;
158 t_Er9xMixData::t_Er9xMixData()
160 memset(this, 0, sizeof(t_Er9xMixData));
163 t_Er9xMixData::operator MixData ()
165 MixData c9x;
166 c9x.destCh = destCh;
167 if (abs(weight)>125) {
168 int gvar;
169 if (weight>0) {
170 gvar=weight-125;
171 } else {
172 gvar=weight+131;
174 gvar+=10000;
175 c9x.weight=gvar;
176 } else {
177 c9x.weight = weight;
179 if (abs(sOffset)>125) {
180 int gvar;
181 if (sOffset>0) {
182 gvar=sOffset-125;
183 } else {
184 gvar=sOffset+131;
186 gvar+=10000;
187 c9x.sOffset=gvar;
188 } else {
189 c9x.sOffset=sOffset;
191 c9x.swtch = er9xToSwitch(swtch);
193 if (srcRaw == 0) {
194 c9x.srcRaw = RawSource(SOURCE_TYPE_NONE);
196 else if (srcRaw <= 7) {
197 c9x.srcRaw = RawSource(SOURCE_TYPE_STICK, srcRaw-1);
199 else if (srcRaw == 8) {
200 c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
202 else if (srcRaw == 9) {
203 if (swtch < 0) {
204 c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch < -3 ? -swtch-3 : -swtch);
205 c9x.weight = -weight;
207 else if (swtch > 0) {
208 c9x.srcRaw = RawSource(SOURCE_TYPE_SWITCH, swtch > 3 ? swtch-3 : swtch);
210 else {
211 c9x.srcRaw = RawSource(SOURCE_TYPE_MAX);
213 if (mltpx != MLTPX_REP)
214 c9x.swtch = RawSwitch(SWITCH_TYPE_NONE);
216 else if (srcRaw <= 12) {
217 c9x.srcRaw = RawSource(SOURCE_TYPE_CYC, srcRaw-10);
219 else if (srcRaw <= 20) {
220 c9x.srcRaw = RawSource(SOURCE_TYPE_PPM, srcRaw-13);
222 else if (srcRaw <=37) {
223 c9x.srcRaw = RawSource(SOURCE_TYPE_CH, srcRaw-21);
225 else {
226 c9x.srcRaw = RawSource(SOURCE_TYPE_GVAR, srcRaw-38);
229 if (differential==1) {
230 c9x.curve.type = CurveReference::CURVE_REF_DIFF;
231 c9x.curve.value = differential;
233 else if (curve > 6) {
234 c9x.curve.type = CurveReference::CURVE_REF_CUSTOM;
235 c9x.curve.value = curve - 6;
237 else if (curve > 0) {
238 c9x.curve.type = CurveReference::CURVE_REF_FUNC;
239 c9x.curve.value = curve;
242 // c9x.lateOffset=lateOffset;
243 c9x.delayUp = delayUp;
244 c9x.delayDown = delayDown;
245 c9x.speedUp = speedUp;
246 c9x.speedDown = speedDown;
247 c9x.carryTrim = carryTrim;
248 c9x.mltpx = (MltpxValue)mltpx;
249 c9x.mixWarn = mixWarn;
250 // c9x.enableFmTrim=enableFmTrim;
251 return c9x;
254 RawSource er9xToSource(int8_t value)
256 if (value == 0) {
257 return RawSource(SOURCE_TYPE_NONE);
259 else if (value <= 7) {
260 return RawSource(SOURCE_TYPE_STICK, value - 1);
262 else if (value == 8) {
263 return RawSource(SOURCE_TYPE_MAX);
265 else if (value == 9) {
266 return RawSource(SOURCE_TYPE_MAX);
268 else if (value <= 12) {
269 return RawSource(SOURCE_TYPE_CYC, value-10);
271 else if (value <= 20) {
272 return RawSource(SOURCE_TYPE_PPM, value-13);
274 else if (value <= 36) {
275 return RawSource(SOURCE_TYPE_CH, value-21);
277 else {
278 return RawSource(SOURCE_TYPE_TELEMETRY, value-36);
282 Er9xLogicalSwitchData::operator LogicalSwitchData ()
284 LogicalSwitchData c9x;
285 c9x.func = func;
286 c9x.val1 = v1;
287 c9x.val2 = v2;
289 if ((c9x.func >= LS_FN_VPOS && c9x.func <= LS_FN_ANEG) || c9x.func >= LS_FN_EQUAL) {
290 c9x.val1 = er9xToSource(v1).toValue();
293 if (c9x.func >= LS_FN_EQUAL) {
294 c9x.val2 = er9xToSource(v2).toValue();
297 if (c9x.func >= LS_FN_AND && c9x.func <= LS_FN_XOR) {
298 c9x.val1 = er9xToSwitch(v1).toValue();
299 c9x.val2 = er9xToSwitch(v2).toValue();
302 return c9x;
306 t_Er9xSafetySwData::t_Er9xSafetySwData()
308 memset(this, 0, sizeof(t_Er9xSafetySwData));
311 t_Er9xFrSkyChannelData::t_Er9xFrSkyChannelData()
313 memset(this, 0, sizeof(t_Er9xFrSkyChannelData));
316 t_Er9xFrSkyChannelData::operator FrSkyChannelData ()
318 FrSkyChannelData c9x;
319 c9x.ratio = ratio;
320 c9x.alarms[0].value = alarms_value[0];
321 c9x.alarms[0].level = alarms_level & 3;
322 c9x.alarms[0].greater = alarms_greater & 1;
323 c9x.alarms[1].value = alarms_value[1];
324 c9x.alarms[1].level = (alarms_level >> 2) & 3;
325 c9x.alarms[1].greater = (alarms_greater >> 1) & 1;
326 if (type==2) {
327 c9x.type = 0;
328 c9x.multiplier=1;
329 } else {
330 c9x.type = type;
332 return c9x;
335 t_Er9xFrSkyData::t_Er9xFrSkyData()
337 memset(reinterpret_cast<void *>(this), 0, sizeof(t_Er9xFrSkyData));
340 t_Er9xFrSkyData::operator FrSkyData ()
342 FrSkyData c9x;
343 c9x.channels[0] = channels[0];
344 c9x.channels[1] = channels[1];
345 return c9x;
348 RawSwitch getEr9xTimerMode(int mode)
351 if (mode <= -33)
352 return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+33));
353 else if (mode <= -1)
354 return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+1));
355 else if (mode < 16)
356 return TimerMode(mode);
357 else if (mode < 16+21)
358 return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16));
359 else
360 return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16-21));
362 return RawSwitch();
365 t_Er9xModelData::operator ModelData ()
367 ModelData c9x;
368 c9x.used = true;
369 getEEPROMString(c9x.name, name, sizeof(name));
370 c9x.timers[0].mode = getEr9xTimerMode(tmrMode);
371 c9x.timers[0].val = tmrVal;
372 switch(protocol) {
373 case 1:
374 c9x.moduleData[0].protocol = PULSES_PXX_DJT;
375 break;
376 case 2:
377 c9x.moduleData[0].protocol = PULSES_DSM2;
378 break;
379 case 3:
380 c9x.moduleData[0].protocol = PULSES_PPM16;
381 break;
382 default:
383 c9x.moduleData[0].protocol = PULSES_PPM;
384 break;
386 c9x.moduleData[0].ppm.frameLength=ppmFrameLength;
387 c9x.moduleData[0].channelsCount = 8 + 2 * ppmNCH;
388 c9x.thrTrim = thrTrim;
389 c9x.trimInc = trimInc-2;
390 c9x.moduleData[0].ppm.delay = 300 + 50 * ppmDelay;
391 c9x.customFn[0].func = FuncInstantTrim;
392 if (trimSw) {
393 c9x.customFn[0].swtch = er9xToSwitch(trimSw);
395 c9x.beepANACenter = beepANACenter;
396 c9x.moduleData[0].ppm.pulsePol = pulsePol;
397 c9x.extendedLimits = extendedLimits;
398 c9x.swashRingData.elevatorWeight = swashInvertELE ? -100 : 100;
399 c9x.swashRingData.aileronWeight = swashInvertAIL ? -100 : 100;
400 c9x.swashRingData.collectiveWeight = swashInvertCOL ? -100 : 100;
401 c9x.swashRingData.type = swashType;
402 c9x.swashRingData.collectiveSource = er9xToSource(swashCollectiveSource);
403 c9x.swashRingData.value = swashRingValue;
405 for (int i=0; i<ER9X_MAX_MIXERS; i++) {
406 Er9xMixData mix = mixData[i];
407 c9x.mixData[i] = mix;
410 for (int i=0; i<ER9X_NUM_CHNOUT; i++)
411 c9x.limitData[i] = limitData[i];
413 // expoData
414 int e = 0;
415 for (int ch = 0; ch < 4 && e < CPN_MAX_EXPOS; ch++) {
416 for (int dr = 0, pos = 0; dr < 3 && e < CPN_MAX_EXPOS; dr++, pos++) {
417 if ((dr == 0 && !expoData[ch].drSw1) || (dr == 1 && !expoData[ch].drSw2))
418 dr = 2;
419 if (dr == 2 && !expoData[ch].expo[0][0][0] && !expoData[ch].expo[0][0][1] && !expoData[ch].expo[0][1][0] && !expoData[ch].expo[0][1][1])
420 break;
421 if (expoData[ch].drSw1 && !expoData[ch].drSw2) {
422 c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? expoData[ch].drSw1 : 0);
423 pos = dr == 0 ? 1 : 0;
425 else {
426 c9x.expoData[e].swtch = er9xToSwitch(dr == 0 ? -expoData[ch].drSw1 : (dr == 1 ? -expoData[ch].drSw2 : 0));
428 c9x.expoData[e].chn = ch;
429 if (expoData[ch].expo[pos][0][0]) {
430 c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
431 c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][0];
433 c9x.expoData[e].weight = 100 + expoData[ch].expo[pos][1][0];
434 if (expoData[ch].expo[pos][0][0] == expoData[ch].expo[pos][0][1] && expoData[ch].expo[pos][1][0] == expoData[ch].expo[pos][1][1]) {
435 c9x.expoData[e++].mode = 3;
437 else {
438 c9x.expoData[e].mode = 2;
439 if (e < CPN_MAX_EXPOS - 1) {
440 c9x.expoData[e + 1].swtch = c9x.expoData[e].swtch;
441 c9x.expoData[++e].chn = ch;
442 c9x.expoData[e].mode = 1;
443 if (expoData[ch].expo[pos][0][1]) {
444 c9x.expoData[e].curve.type = CurveReference::CURVE_REF_EXPO;
445 c9x.expoData[e].curve.value = expoData[ch].expo[pos][0][1];
447 c9x.expoData[e++].weight = 100 + expoData[ch].expo[pos][1][1];
453 for (int i=0; i<CPN_MAX_STICKS; i++)
454 c9x.flightModeData[0].trim[i] = trim[i];
456 for (int i=0; i<ER9X_MAX_CURVE5; i++) {
457 c9x.curves[i].count = 5;
458 for (int j = 0; j < 5; j++) {
459 c9x.curves[i].points[j].x = -100 + 50 * i;
460 c9x.curves[i].points[j].y = curves5[i][j];
463 for (int i=0; i<ER9X_MAX_CURVE9; i++) {
464 c9x.curves[ER9X_MAX_CURVE5 + i].count = 9;
465 for (int j = 0; j < 9; j++) {
466 c9x.curves[ER9X_MAX_CURVE5 + i].points[j].x = -100 + 25 * i;
467 c9x.curves[ER9X_MAX_CURVE5 + i].points[j].y = curves9[i][j];
471 for (int i=0; i<ER9X_NUM_CSW; i++)
472 c9x.logicalSw[i] = logicalSw[i];
474 // for (int i=0; i<ER9X_NUM_CHNOUT; i++)
475 // c9x.safetySw[i] = safetySw[i];
477 c9x.frsky = frsky;
478 c9x.frsky.usrProto=FrSkyUsrProto;
479 return c9x;