Implement reading firmware on Horus via USB (#5442)
[opentx.git] / radio / src / pulses / pulses_arm.cpp
blob138270d94da635c4baf97d4868450a68a3fa1b8d
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 "opentx.h"
23 uint8_t s_pulses_paused = 0;
24 uint8_t s_current_protocol[NUM_MODULES] = { MODULES_INIT(255) };
25 uint16_t failsafeCounter[NUM_MODULES] = { MODULES_INIT(100) };
26 uint8_t moduleFlag[NUM_MODULES] = { 0 };
28 ModulePulsesData modulePulsesData[NUM_MODULES] __DMA;
29 TrainerPulsesData trainerPulsesData __DMA;
31 #if defined(CROSSFIRE)
32 uint8_t createCrossfireChannelsFrame(uint8_t * frame, int16_t * pulses);
33 #endif
35 uint8_t getRequiredProtocol(uint8_t port)
37 uint8_t required_protocol;
39 switch (port) {
40 #if defined(PCBTARANIS) || defined(PCBHORUS)
41 case INTERNAL_MODULE:
42 switch (g_model.moduleData[INTERNAL_MODULE].type) {
43 #if defined(TARANIS_INTERNAL_PPM)
44 case MODULE_TYPE_PPM:
45 required_protocol = PROTO_PPM;
46 break;
47 #endif
48 case MODULE_TYPE_XJT:
49 required_protocol = PROTO_PXX;
50 break;
51 default:
52 required_protocol = PROTO_NONE;
53 break;
55 break;
56 #endif
58 default:
59 port = EXTERNAL_MODULE; // ensure it's external module only
60 switch (g_model.moduleData[EXTERNAL_MODULE].type) {
61 case MODULE_TYPE_PPM:
62 required_protocol = PROTO_PPM;
63 break;
64 case MODULE_TYPE_XJT:
65 case MODULE_TYPE_R9M:
66 required_protocol = PROTO_PXX;
67 break;
68 case MODULE_TYPE_SBUS:
69 required_protocol = PROTO_SBUS;
70 break;
71 #if defined(MULTIMODULE)
72 case MODULE_TYPE_MULTIMODULE:
73 required_protocol = PROTO_MULTIMODULE;
74 break;
75 #endif
76 #if defined(DSM2)
77 case MODULE_TYPE_DSM2:
78 required_protocol = limit<uint8_t>(PROTO_DSM2_LP45, PROTO_DSM2_LP45+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, PROTO_DSM2_DSMX);
79 // The module is set to OFF during one second before BIND start
81 static tmr10ms_t bindStartTime = 0;
82 if (moduleFlag[EXTERNAL_MODULE] == MODULE_BIND) {
83 if (bindStartTime == 0) bindStartTime = get_tmr10ms();
84 if ((tmr10ms_t)(get_tmr10ms() - bindStartTime) < 100) {
85 required_protocol = PROTO_NONE;
86 break;
89 else {
90 bindStartTime = 0;
93 break;
94 #endif
95 #if defined(CROSSFIRE)
96 case MODULE_TYPE_CROSSFIRE:
97 required_protocol = PROTO_CROSSFIRE;
98 break;
99 #endif
100 default:
101 required_protocol = PROTO_NONE;
102 break;
104 break;
107 if (s_pulses_paused) {
108 required_protocol = PROTO_NONE;
111 #if 0
112 // will need an EEPROM conversion
113 if (moduleFlag[port] == MODULE_OFF) {
114 required_protocol = PROTO_NONE;
116 #endif
118 return required_protocol;
121 void setupPulses(uint8_t port)
123 bool init_needed = false;
124 uint8_t required_protocol = getRequiredProtocol(port);
126 heartbeat |= (HEART_TIMER_PULSES << port);
128 if (s_current_protocol[port] != required_protocol) {
129 init_needed = true;
130 switch (s_current_protocol[port]) { // stop existing protocol hardware
131 case PROTO_PXX:
132 disable_pxx(port);
133 break;
135 #if defined(DSM2)
136 case PROTO_DSM2_LP45:
137 case PROTO_DSM2_DSM2:
138 case PROTO_DSM2_DSMX:
139 disable_dsm2(port);
140 break;
141 #endif
143 #if defined(CROSSFIRE)
144 case PROTO_CROSSFIRE:
145 disable_crossfire(port);
146 break;
147 #endif
149 #if defined(MULTIMODULE)
150 case PROTO_MULTIMODULE:
151 #endif
152 case PROTO_SBUS:
153 disable_sbusOut(port);
154 break;
156 case PROTO_PPM:
157 disable_ppm(port);
158 break;
160 default:
161 disable_no_pulses(port);
162 break;
164 s_current_protocol[port] = required_protocol;
167 // Set up output data here
168 switch (required_protocol) {
169 case PROTO_PXX:
170 setupPulsesPXX(port);
171 scheduleNextMixerCalculation(port, 9);
172 break;
173 case PROTO_SBUS:
174 setupPulsesSbus(port);
175 scheduleNextMixerCalculation(port, (45+g_model.moduleData[port].sbus.refreshRate)/2);
176 break;
178 #if defined(DSM2)
179 case PROTO_DSM2_LP45:
180 case PROTO_DSM2_DSM2:
181 case PROTO_DSM2_DSMX:
182 setupPulsesDSM2(port);
183 scheduleNextMixerCalculation(port, 11);
184 break;
185 #endif
187 #if defined(CROSSFIRE)
188 case PROTO_CROSSFIRE:
189 if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE && !init_needed) {
190 uint8_t * crossfire = modulePulsesData[port].crossfire.pulses;
191 uint8_t len;
192 #if defined(LUA)
193 if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) {
194 memcpy(crossfire, outputTelemetryBuffer, outputTelemetryBufferSize);
195 len = outputTelemetryBufferSize;
196 outputTelemetryBufferTrigger = 0x00;
197 outputTelemetryBufferSize = 0;
199 else
200 #endif
202 len = createCrossfireChannelsFrame(crossfire, &channelOutputs[g_model.moduleData[port].channelsStart]);
204 sportSendBuffer(crossfire, len);
206 scheduleNextMixerCalculation(port, CROSSFIRE_FRAME_PERIOD);
207 break;
208 #endif
210 #if defined(MULTIMODULE)
211 case PROTO_MULTIMODULE:
212 setupPulsesMultimodule(port);
213 scheduleNextMixerCalculation(port, 4);
214 break;
215 #endif
217 case PROTO_PPM:
218 #if defined(PCBSKY9X)
219 case PROTO_NONE:
220 #endif
221 setupPulsesPPMModule(port);
222 scheduleNextMixerCalculation(port, (45+g_model.moduleData[port].ppm.frameLength)/2);
223 break;
225 default:
226 break;
229 if (init_needed) {
230 switch (required_protocol) { // Start new protocol hardware here
231 case PROTO_PXX:
232 init_pxx(port);
233 break;
235 #if defined(DSM2)
236 case PROTO_DSM2_LP45:
237 case PROTO_DSM2_DSM2:
238 case PROTO_DSM2_DSMX:
239 init_dsm2(port);
240 break;
241 #endif
243 #if defined(CROSSFIRE)
244 case PROTO_CROSSFIRE:
245 init_crossfire(port);
246 break;
247 #endif
249 #if defined(MULTIMODULE)
250 case PROTO_MULTIMODULE:
251 #endif
252 case PROTO_SBUS:
253 init_sbusOut(port);
254 break;
257 case PROTO_PPM:
258 init_ppm(port);
259 break;
261 default:
262 init_no_pulses(port);
263 break;