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.
23 RTOS_TASK_HANDLE menusTaskId
;
24 RTOS_DEFINE_STACK(menusStack
, MENUS_STACK_SIZE
);
26 RTOS_TASK_HANDLE mixerTaskId
;
27 RTOS_DEFINE_STACK(mixerStack
, MIXER_STACK_SIZE
);
29 RTOS_TASK_HANDLE audioTaskId
;
30 RTOS_DEFINE_STACK(audioStack
, AUDIO_STACK_SIZE
);
32 RTOS_MUTEX_HANDLE audioMutex
;
33 RTOS_MUTEX_HANDLE mixerMutex
;
55 volatile uint16_t timeForcePowerOffPressed
= 0;
57 bool isForcePowerOffRequested()
59 if (pwrOffPressed()) {
60 if (timeForcePowerOffPressed
== 0) {
61 timeForcePowerOffPressed
= get_tmr10ms();
64 uint16_t delay
= (uint16_t)get_tmr10ms() - timeForcePowerOffPressed
;
65 if (delay
> 1000/*10s*/) {
71 resetForcePowerOffRequest();
76 bool isModuleSynchronous(uint8_t module
)
78 uint8_t protocol
= moduleState
[module
].protocol
;
79 if (protocol
== PROTOCOL_CHANNELS_PXX2_HIGHSPEED
|| protocol
== PROTOCOL_CHANNELS_PXX2_LOWSPEED
|| protocol
== PROTOCOL_CHANNELS_CROSSFIRE
|| protocol
== PROTOCOL_CHANNELS_NONE
)
81 #if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
82 if (protocol
== PROTOCOL_CHANNELS_PXX1_SERIAL
)
88 void sendSynchronousPulses()
90 #if defined(HARDWARE_INTERNAL_MODULE)
91 if (isModuleSynchronous(INTERNAL_MODULE
)) {
92 if (setupPulsesInternalModule())
93 intmoduleSendNextFrame();
97 if (isModuleSynchronous(EXTERNAL_MODULE
)) {
98 if (setupPulsesExternalModule())
99 extmoduleSendNextFrame();
103 uint32_t nextMixerTime
[NUM_MODULES
];
105 TASK_FUNCTION(mixerTask
)
107 static uint32_t lastRunTime
;
108 s_pulses_paused
= true;
111 #if defined(PCBTARANIS) && defined(SBUS)
120 #if defined(BLUETOOTH)
127 if (pwrCheck() == e_power_off
) {
131 if (isForcePowerOffRequested()) {
136 uint32_t now
= RTOS_GET_MS();
139 if (now
- lastRunTime
>= 10) {
140 // run at least every 10ms
144 #if defined(INTMODULE_USART) && defined(INTMODULE_HEARTBEAT)
145 if ((moduleState
[INTERNAL_MODULE
].protocol
== PROTOCOL_CHANNELS_PXX2_HIGHSPEED
|| moduleState
[INTERNAL_MODULE
].protocol
== PROTOCOL_CHANNELS_PXX1_SERIAL
) && heartbeatCapture
.valid
&& heartbeatCapture
.timestamp
> lastRunTime
) {
150 if (now
== nextMixerTime
[0]) {
155 if (now
== nextMixerTime
[1]) {
161 continue; // go back to sleep
166 if (!s_pulses_paused
) {
167 uint16_t t0
= getTmr2MHz();
169 DEBUG_TIMER_START(debugTimerMixer
);
170 RTOS_LOCK_MUTEX(mixerMutex
);
171 doMixerCalculations();
172 DEBUG_TIMER_START(debugTimerMixerCalcToUsage
);
173 DEBUG_TIMER_SAMPLE(debugTimerMixerIterval
);
174 RTOS_UNLOCK_MUTEX(mixerMutex
);
175 DEBUG_TIMER_STOP(debugTimerMixer
);
177 #if defined(STM32) && !defined(SIMU)
178 if (getSelectedUsbMode() == USB_JOYSTICK_MODE
) {
183 #if defined(PCBSKY9X) && !defined(SIMU)
187 DEBUG_TIMER_START(debugTimerTelemetryWakeup
);
189 DEBUG_TIMER_STOP(debugTimerTelemetryWakeup
);
191 if (heartbeat
== HEART_WDT_CHECK
) {
196 t0
= getTmr2MHz() - t0
;
197 if (t0
> maxMixerDuration
)
198 maxMixerDuration
= t0
;
200 sendSynchronousPulses();
205 void scheduleNextMixerCalculation(uint8_t module
, uint16_t period_ms
)
207 // Schedule next mixer calculation time,
209 if (isModuleSynchronous(module
)) {
210 nextMixerTime
[module
] += period_ms
/ RTOS_MS_PER_TICK
;
211 if (nextMixerTime
[module
] < RTOS_GET_TIME()) {
212 // we are late ... let's add some small delay
213 nextMixerTime
[module
] = (uint32_t) RTOS_GET_TIME() + (period_ms
/ RTOS_MS_PER_TICK
);
217 // for now assume mixer calculation takes 2 ms.
218 nextMixerTime
[module
] = (uint32_t) RTOS_GET_TIME() + (period_ms
/ RTOS_MS_PER_TICK
);
221 DEBUG_TIMER_STOP(debugTimerMixerCalcToUsage
);
224 #define MENU_TASK_PERIOD_TICKS (50 / RTOS_MS_PER_TICK) // 50ms
226 #if defined(COLORLCD) && defined(CLI)
227 bool perMainEnabled
= true;
230 TASK_FUNCTION(menusTask
)
234 #if defined(PWR_BUTTON_PRESS)
236 uint32_t pwr_check
= pwrCheck();
237 if (pwr_check
== e_power_off
) {
240 else if (pwr_check
== e_power_press
) {
241 RTOS_WAIT_TICKS(MENU_TASK_PERIOD_TICKS
);
245 while (pwrCheck() != e_power_off
) {
247 uint32_t start
= (uint32_t)RTOS_GET_TIME();
248 DEBUG_TIMER_START(debugTimerPerMain
);
249 #if defined(COLORLCD) && defined(CLI)
250 if (perMainEnabled
) {
256 DEBUG_TIMER_STOP(debugTimerPerMain
);
257 // TODO remove completely massstorage from sky9x firmware
258 uint32_t runtime
= ((uint32_t)RTOS_GET_TIME() - start
);
259 // deduct the thread run-time from the wait, if run-time was more than
260 // desired period, then skip the wait all together
261 if (runtime
< MENU_TASK_PERIOD_TICKS
) {
262 RTOS_WAIT_TICKS(MENU_TASK_PERIOD_TICKS
- runtime
);
265 resetForcePowerOffRequest();
272 #if defined(PCBHORUS)
278 boardOff(); // Only turn power off if necessary
291 RTOS_CREATE_TASK(mixerTaskId
, mixerTask
, "mixer", mixerStack
, MIXER_STACK_SIZE
, MIXER_TASK_PRIO
);
292 RTOS_CREATE_TASK(menusTaskId
, menusTask
, "menus", menusStack
, MENUS_STACK_SIZE
, MENUS_TASK_PRIO
);
295 RTOS_CREATE_TASK(audioTaskId
, audioTask
, "audio", audioStack
, AUDIO_STACK_SIZE
, AUDIO_TASK_PRIO
);
298 RTOS_CREATE_MUTEX(audioMutex
);
299 RTOS_CREATE_MUTEX(mixerMutex
);