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 "er9xeeprom.h"
26 RawSwitch
er9xToSwitch(int8_t sw
)
28 uint8_t swa
= abs(sw
);
30 return RawSwitch(SWITCH_TYPE_NONE
);
32 return RawSwitch(SWITCH_TYPE_SWITCH
, sw
);
34 return RawSwitch(SWITCH_TYPE_VIRTUAL
, sw
> 0 ? sw
-9 : sw
+9);
36 return RawSwitch(SWITCH_TYPE_ON
);
38 return RawSwitch(SWITCH_TYPE_OFF
);
40 return RawSwitch(SWITCH_TYPE_SWITCH
, sw
> 0 ? sw
-22 : sw
+22);
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()
54 c9x
.swtch
= er9xToSwitch(swtch
);
55 c9x
.weight
= (25 * studWeight
) / 8;
60 t_Er9xTrainerData::t_Er9xTrainerData()
62 memset(reinterpret_cast<void *>(this), 0, sizeof(t_Er9xTrainerData
));
65 t_Er9xTrainerData::operator TrainerData ()
68 for (int i
=0; i
<CPN_MAX_STICKS
; i
++) {
69 c9x
.calib
[i
] = calib
[i
];
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
;
102 result
.beeperMode
= GeneralSettings::BEEPER_QUIET
;
105 result
.beeperMode
= GeneralSettings::BEEPER_NOKEYS
;
108 result
.beeperMode
= GeneralSettings::BEEPER_ALL
;
109 result
.beeperLength
= beeperVal
- 4;
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;
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
;
143 t_Er9xLimitData::t_Er9xLimitData()
145 memset(this, 0, sizeof(t_Er9xLimitData
));
148 t_Er9xLimitData::operator LimitData ()
151 c9x
.min
= 10*(min
-100);
152 c9x
.max
= 10*(max
+100);
158 t_Er9xMixData::t_Er9xMixData()
160 memset(this, 0, sizeof(t_Er9xMixData
));
163 t_Er9xMixData::operator MixData ()
167 if (abs(weight
)>125) {
179 if (abs(sOffset
)>125) {
191 c9x
.swtch
= er9xToSwitch(swtch
);
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) {
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
);
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);
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;
254 RawSource
er9xToSource(int8_t value
)
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);
278 return RawSource(SOURCE_TYPE_TELEMETRY
, value
-36);
282 Er9xLogicalSwitchData::operator LogicalSwitchData ()
284 LogicalSwitchData c9x
;
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();
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
;
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;
335 t_Er9xFrSkyData::t_Er9xFrSkyData()
337 memset(reinterpret_cast<void *>(this), 0, sizeof(t_Er9xFrSkyData
));
340 t_Er9xFrSkyData::operator FrSkyData ()
343 c9x
.channels
[0] = channels
[0];
344 c9x
.channels
[1] = channels
[1];
348 RawSwitch
getEr9xTimerMode(int mode
)
352 return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+33));
354 return TimerMode(TMRMODE_FIRST_NEG_SWITCH+(mode+1));
356 return TimerMode(mode);
357 else if (mode < 16+21)
358 return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16));
360 return TimerMode(TMRMODE_FIRST_SWITCH+(mode-16-21));
365 t_Er9xModelData::operator ModelData ()
369 getEEPROMString(c9x
.name
, name
, sizeof(name
));
370 c9x
.timers
[0].mode
= getEr9xTimerMode(tmrMode
);
371 c9x
.timers
[0].val
= tmrVal
;
374 c9x
.moduleData
[0].protocol
= PULSES_PXX_DJT
;
377 c9x
.moduleData
[0].protocol
= PULSES_DSM2
;
380 c9x
.moduleData
[0].protocol
= PULSES_PPM16
;
383 c9x
.moduleData
[0].protocol
= PULSES_PPM
;
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
;
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
];
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
))
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])
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;
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;
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];
478 c9x
.frsky
.usrProto
=FrSkyUsrProto
;