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 "io/frsky_pxx2.h"
23 #include "pulses/pxx2.h"
25 uint8_t s_pulses_paused
= 0;
26 ModuleState moduleState
[NUM_MODULES
];
27 InternalModulePulsesData intmodulePulsesData __DMA
;
28 ExternalModulePulsesData extmodulePulsesData __DMA
;
29 TrainerPulsesData trainerPulsesData __DMA
;
31 void ModuleState::startBind(BindInformation
* destination
, ModuleCallback bindCallback
)
33 bindInformation
= destination
;
34 callback
= bindCallback
;
35 mode
= MODULE_MODE_BIND
;
37 bindInformation
->candidateReceiversCount
= 2;
38 strcpy(bindInformation
->candidateReceiversNames
[0], "SimuRX1");
39 strcpy(bindInformation
->candidateReceiversNames
[1], "SimuRX2");
43 uint8_t getModuleType(uint8_t module
)
45 uint8_t type
= g_model
.moduleData
[module
].type
;
47 #if defined(HARDWARE_INTERNAL_MODULE)
48 if (module
== INTERNAL_MODULE
&& isInternalModuleAvailable(type
)) {
53 if (module
== EXTERNAL_MODULE
&& isExternalModuleAvailable(type
)) {
57 return MODULE_TYPE_NONE
;
60 uint8_t getRequiredProtocol(uint8_t module
)
64 switch (getModuleType(module
)) {
66 protocol
= PROTOCOL_CHANNELS_PPM
;
69 case MODULE_TYPE_XJT_PXX1
:
70 #if defined(INTMODULE_USART)
71 if (module
== INTERNAL_MODULE
) {
72 protocol
= PROTOCOL_CHANNELS_PXX1_SERIAL
;
76 protocol
= PROTOCOL_CHANNELS_PXX1_PULSES
;
79 case MODULE_TYPE_R9M_PXX1
:
80 protocol
= PROTOCOL_CHANNELS_PXX1_PULSES
;
83 #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
84 case MODULE_TYPE_R9M_LITE_PXX1
:
85 case MODULE_TYPE_R9M_LITE_PRO_PXX1
:
86 protocol
= PROTOCOL_CHANNELS_PXX1_SERIAL
;
89 case MODULE_TYPE_R9M_LITE_PXX2
:
90 protocol
= PROTOCOL_CHANNELS_PXX2_LOWSPEED
;
94 case MODULE_TYPE_ISRM_PXX2
:
95 case MODULE_TYPE_R9M_PXX2
:
96 #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
97 case MODULE_TYPE_XJT_LITE_PXX2
:
98 case MODULE_TYPE_R9M_LITE_PRO_PXX2
:
100 protocol
= PROTOCOL_CHANNELS_PXX2_HIGHSPEED
;
103 case MODULE_TYPE_SBUS
:
104 protocol
= PROTOCOL_CHANNELS_SBUS
;
107 #if defined(MULTIMODULE)
108 case MODULE_TYPE_MULTIMODULE
:
109 protocol
= PROTOCOL_CHANNELS_MULTIMODULE
;
114 case MODULE_TYPE_DSM2
:
115 protocol
= limit
<uint8_t>(PROTOCOL_CHANNELS_DSM2_LP45
, PROTOCOL_CHANNELS_DSM2_LP45
+g_model
.moduleData
[module
].rfProtocol
, PROTOCOL_CHANNELS_DSM2_DSMX
);
116 // The module is set to OFF during one second before BIND start
118 static tmr10ms_t bindStartTime
= 0;
119 if (moduleState
[module
].mode
== MODULE_MODE_BIND
) {
120 if (bindStartTime
== 0) bindStartTime
= get_tmr10ms();
121 if ((tmr10ms_t
)(get_tmr10ms() - bindStartTime
) < 100) {
122 protocol
= PROTOCOL_CHANNELS_NONE
;
133 #if defined(CROSSFIRE)
134 case MODULE_TYPE_CROSSFIRE
:
135 protocol
= PROTOCOL_CHANNELS_CROSSFIRE
;
140 protocol
= PROTOCOL_CHANNELS_NONE
;
144 if (s_pulses_paused
) {
145 protocol
= PROTOCOL_CHANNELS_NONE
;
149 // will need an EEPROM conversion
150 if (moduleState
[module
].mode
== MODULE_OFF
) {
151 protocol
= PROTOCOL_CHANNELS_NONE
;
158 void enablePulsesExternalModule(uint8_t protocol
)
160 // start new protocol hardware here
164 case PROTOCOL_CHANNELS_PXX1_PULSES
:
165 extmodulePxx1PulsesStart();
169 #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
170 case PROTOCOL_CHANNELS_PXX1_SERIAL
:
171 extmodulePxx1SerialStart();
176 case PROTOCOL_CHANNELS_DSM2_LP45
:
177 case PROTOCOL_CHANNELS_DSM2_DSM2
:
178 case PROTOCOL_CHANNELS_DSM2_DSMX
:
179 extmoduleSerialStart(DSM2_BAUDRATE
, DSM2_PERIOD
* 2000, false);
183 #if defined(CROSSFIRE)
184 case PROTOCOL_CHANNELS_CROSSFIRE
:
185 EXTERNAL_MODULE_ON();
189 #if defined(PXX2) && defined(EXTMODULE_USART)
190 case PROTOCOL_CHANNELS_PXX2_HIGHSPEED
:
191 extmoduleInvertedSerialStart(PXX2_HIGHSPEED_BAUDRATE
);
194 case PROTOCOL_CHANNELS_PXX2_LOWSPEED
:
195 extmoduleInvertedSerialStart(PXX2_LOWSPEED_BAUDRATE
);
199 #if defined(MULTIMODULE)
200 case PROTOCOL_CHANNELS_MULTIMODULE
:
201 extmoduleSerialStart(MULTIMODULE_BAUDRATE
, MULTIMODULE_PERIOD
* 2000, true);
206 case PROTOCOL_CHANNELS_SBUS
:
207 extmoduleSerialStart(SBUS_BAUDRATE
, SBUS_PERIOD_HALF_US
, false);
212 case PROTOCOL_CHANNELS_PPM
:
222 void setupPulsesExternalModule(uint8_t protocol
)
226 case PROTOCOL_CHANNELS_PXX1_PULSES
:
227 extmodulePulsesData
.pxx
.setupFrame(EXTERNAL_MODULE
);
228 scheduleNextMixerCalculation(EXTERNAL_MODULE
, PXX_PULSES_PERIOD
);
232 #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
233 case PROTOCOL_CHANNELS_PXX1_SERIAL
:
234 extmodulePulsesData
.pxx_uart
.setupFrame(EXTERNAL_MODULE
);
235 scheduleNextMixerCalculation(EXTERNAL_MODULE
, EXTMODULE_PXX1_SERIAL_PERIOD
);
240 case PROTOCOL_CHANNELS_PXX2_HIGHSPEED
:
241 case PROTOCOL_CHANNELS_PXX2_LOWSPEED
:
242 extmodulePulsesData
.pxx2
.setupFrame(EXTERNAL_MODULE
);
243 scheduleNextMixerCalculation(EXTERNAL_MODULE
, PXX2_PERIOD
);
248 case PROTOCOL_CHANNELS_SBUS
:
250 scheduleNextMixerCalculation(EXTERNAL_MODULE
, SBUS_PERIOD
);
255 case PROTOCOL_CHANNELS_DSM2_LP45
:
256 case PROTOCOL_CHANNELS_DSM2_DSM2
:
257 case PROTOCOL_CHANNELS_DSM2_DSMX
:
259 scheduleNextMixerCalculation(EXTERNAL_MODULE
, DSM2_PERIOD
);
263 #if defined(CROSSFIRE)
264 case PROTOCOL_CHANNELS_CROSSFIRE
:
265 setupPulsesCrossfire();
266 scheduleNextMixerCalculation(EXTERNAL_MODULE
, CROSSFIRE_PERIOD
);
270 #if defined(MULTIMODULE)
271 case PROTOCOL_CHANNELS_MULTIMODULE
:
272 setupPulsesMultiExternalModule();
273 scheduleNextMixerCalculation(EXTERNAL_MODULE
, MULTIMODULE_PERIOD
);
278 case PROTOCOL_CHANNELS_PPM
:
279 setupPulsesPPMExternalModule();
280 scheduleNextMixerCalculation(EXTERNAL_MODULE
, PPM_PERIOD(EXTERNAL_MODULE
));
289 #if defined(HARDWARE_INTERNAL_MODULE)
290 static void enablePulsesInternalModule(uint8_t protocol
)
292 // start new protocol hardware here
295 #if defined(PXX1) && !defined(INTMODULE_USART)
296 case PROTOCOL_CHANNELS_PXX1_PULSES
:
297 intmodulePxx1PulsesStart();
301 #if defined(PXX1) && defined(INTMODULE_USART)
302 case PROTOCOL_CHANNELS_PXX1_SERIAL
:
303 intmodulePxx1SerialStart();
308 case PROTOCOL_CHANNELS_PXX2_HIGHSPEED
:
309 intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE
, true, USART_Parity_No
, USART_StopBits_1
, USART_WordLength_8b
);
310 #if defined(HARDWARE_INTERNAL_MODULE) && defined(INTERNAL_MODULE_PXX2) && defined(ACCESS_LIB)
311 globalData
.authenticationCount
= 0;
316 #if defined(INTERNAL_MODULE_MULTI)
317 case PROTOCOL_CHANNELS_MULTIMODULE
:
318 intmodulePulsesData
.multi
.initFrame();
319 intmoduleSerialStart(MULTIMODULE_BAUDRATE
, true, USART_Parity_Even
, USART_StopBits_2
, USART_WordLength_9b
);
320 intmoduleTimerStart(MULTIMODULE_PERIOD
);
328 bool setupPulsesInternalModule(uint8_t protocol
)
331 #if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
332 case PROTOCOL_CHANNELS_PXX1_PULSES
:
333 intmodulePulsesData
.pxx
.setupFrame(INTERNAL_MODULE
);
334 scheduleNextMixerCalculation(INTERNAL_MODULE
, INTMODULE_PXX1_SERIAL_PERIOD
);
338 #if defined(PXX1) && defined(INTMODULE_USART)
339 case PROTOCOL_CHANNELS_PXX1_SERIAL
:
340 intmodulePulsesData
.pxx_uart
.setupFrame(INTERNAL_MODULE
);
341 #if !defined(INTMODULE_HEARTBEAT)
342 scheduleNextMixerCalculation(INTERNAL_MODULE
, INTMODULE_PXX1_SERIAL_PERIOD
);
348 case PROTOCOL_CHANNELS_PXX2_HIGHSPEED
:
350 bool result
= intmodulePulsesData
.pxx2
.setupFrame(INTERNAL_MODULE
);
351 if (moduleState
[INTERNAL_MODULE
].mode
== MODULE_MODE_SPECTRUM_ANALYSER
|| moduleState
[INTERNAL_MODULE
].mode
== MODULE_MODE_POWER_METER
) {
352 scheduleNextMixerCalculation(INTERNAL_MODULE
, PXX2_TOOLS_PERIOD
);
354 #if !defined(INTMODULE_HEARTBEAT)
356 scheduleNextMixerCalculation(INTERNAL_MODULE
, PXX2_PERIOD
);
363 #if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM)
364 case PROTOCOL_CHANNELS_PPM
:
365 setupPulsesPPMInternalModule();
366 scheduleNextMixerCalculation(INTERNAL_MODULE
, PPM_PERIOD(INTERNAL_MODULE
));
370 #if defined(INTERNAL_MODULE_MULTI)
371 case PROTOCOL_CHANNELS_MULTIMODULE
:
372 setupPulsesMultiInternalModule();
373 scheduleNextMixerCalculation(INTERNAL_MODULE
, MULTIMODULE_PERIOD
);
382 bool setupPulsesInternalModule()
384 uint8_t protocol
= getRequiredProtocol(INTERNAL_MODULE
);
386 heartbeat
|= (HEART_TIMER_PULSES
<< INTERNAL_MODULE
);
388 if (moduleState
[INTERNAL_MODULE
].protocol
!= protocol
) {
390 moduleState
[INTERNAL_MODULE
].protocol
= protocol
;
391 enablePulsesInternalModule(protocol
);
395 return setupPulsesInternalModule(protocol
);
400 bool setupPulsesExternalModule()
402 uint8_t protocol
= getRequiredProtocol(EXTERNAL_MODULE
);
404 heartbeat
|= (HEART_TIMER_PULSES
<< EXTERNAL_MODULE
);
406 if (moduleState
[EXTERNAL_MODULE
].protocol
!= protocol
) {
408 moduleState
[EXTERNAL_MODULE
].protocol
= protocol
;
409 enablePulsesExternalModule(protocol
);
413 setupPulsesExternalModule(protocol
);
418 void setCustomFailsafe(uint8_t moduleIndex
)
420 if (moduleIndex
< NUM_MODULES
) {
421 for (int ch
=0; ch
<MAX_OUTPUT_CHANNELS
; ch
++) {
422 if (ch
< g_model
.moduleData
[moduleIndex
].channelsStart
|| ch
>= sentModuleChannels(moduleIndex
) + g_model
.moduleData
[moduleIndex
].channelsStart
) {
423 g_model
.failsafeChannels
[ch
] = 0;
425 else if (g_model
.failsafeChannels
[ch
] < FAILSAFE_CHANNEL_HOLD
) {
426 g_model
.failsafeChannels
[ch
] = channelOutputs
[ch
];