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.
24 // menus stack must be aligned to 8 bytes otherwise printf for %f does not work!
25 TaskStack
<MENUS_STACK_SIZE
> _ALIGNED(8) menusStack
;
28 TaskStack
<MIXER_STACK_SIZE
> mixerStack
;
31 TaskStack
<AUDIO_STACK_SIZE
> audioStack
;
33 OS_MutexID audioMutex
;
34 OS_MutexID mixerMutex
;
47 void TaskStack
<SIZE
>::paint()
49 for (uint32_t i
=0; i
<SIZE
; i
++) {
50 stack
[i
] = 0x55555555;
54 uint16_t getStackAvailable(void * address
, uint16_t size
)
56 uint32_t * array
= (uint32_t *)address
;
58 while (i
< size
&& array
[i
] == 0x55555555) {
77 #if defined(STM32) && !defined(SIMU)
80 return ((unsigned char *)&_estack
- (unsigned char *)&_main_stack_start
) / 4;
83 uint16_t stackAvailable()
85 return getStackAvailable(&_main_stack_start
, stackSize());
89 volatile uint16_t timeForcePowerOffPressed
= 0;
91 void resetForcePowerOffRequest()
93 timeForcePowerOffPressed
= 0;
96 bool isForcePowerOffRequested()
98 if (pwrOffPressed()) {
99 if (timeForcePowerOffPressed
== 0) {
100 timeForcePowerOffPressed
= get_tmr10ms();
103 uint16_t delay
= (uint16_t)get_tmr10ms() - timeForcePowerOffPressed
;
104 if (delay
> 1000/*10s*/) {
110 resetForcePowerOffRequest();
115 uint32_t nextMixerTime
[NUM_MODULES
];
117 void mixerTask(void * pdata
)
119 static uint32_t lastRunTime
;
120 s_pulses_paused
= true;
125 if (main_thread_running
== 0)
129 #if defined(PCBTARANIS)
135 if (isForcePowerOffRequested()) {
139 uint32_t now
= CoGetOSTime();
141 #if !defined(SIMU) && defined(STM32)
142 if ((now
- lastRunTime
) >= (usbStarted() ? 5 : 10)) { // run at least every 20ms (every 10ms if USB is active)
144 if ((now
- lastRunTime
) >= 10) { // run at least every 20ms
148 else if (now
== nextMixerTime
[0]) {
152 else if (now
== nextMixerTime
[1]) {
157 continue; // go back to sleep
162 if (!s_pulses_paused
) {
163 uint16_t t0
= getTmr2MHz();
165 DEBUG_TIMER_START(debugTimerMixer
);
166 CoEnterMutexSection(mixerMutex
);
167 doMixerCalculations();
168 DEBUG_TIMER_START(debugTimerMixerCalcToUsage
);
169 DEBUG_TIMER_SAMPLE(debugTimerMixerIterval
);
170 CoLeaveMutexSection(mixerMutex
);
171 DEBUG_TIMER_STOP(debugTimerMixer
);
173 #if defined(USB_JOYSTICK) && !defined(SIMU)
177 #if defined(TELEMETRY_FRSKY) || defined(TELEMETRY_MAVLINK)
178 DEBUG_TIMER_START(debugTimerTelemetryWakeup
);
180 DEBUG_TIMER_STOP(debugTimerTelemetryWakeup
);
183 #if defined(BLUETOOTH)
187 if (heartbeat
== HEART_WDT_CHECK
) {
192 t0
= getTmr2MHz() - t0
;
193 if (t0
> maxMixerDuration
) maxMixerDuration
= t0
;
198 void scheduleNextMixerCalculation(uint8_t module
, uint16_t delay
)
200 // Schedule next mixer calculation time,
201 // for now assume mixer calculation takes 2 ms.
202 nextMixerTime
[module
] = (uint32_t)CoGetOSTime() + (delay
)/2 - 1/*2ms*/;
203 DEBUG_TIMER_STOP(debugTimerMixerCalcToUsage
);
206 #define MENU_TASK_PERIOD_TICKS 25 // 50ms
208 #if defined(COLORLCD) && defined(CLI)
209 bool perMainEnabled
= true;
212 void menusTask(void * pdata
)
216 #if defined(PWR_BUTTON_PRESS)
218 uint32_t pwr_check
= pwrCheck();
219 if (pwr_check
== e_power_off
) {
222 else if (pwr_check
== e_power_press
) {
223 CoTickDelay(MENU_TASK_PERIOD_TICKS
);
227 while (pwrCheck() != e_power_off
) {
229 uint32_t start
= (uint32_t)CoGetOSTime();
230 DEBUG_TIMER_START(debugTimerPerMain
);
231 #if defined(COLORLCD) && defined(CLI)
232 if (perMainEnabled
) {
238 DEBUG_TIMER_STOP(debugTimerPerMain
);
239 // TODO remove completely massstorage from sky9x firmware
240 uint32_t runtime
= ((uint32_t)CoGetOSTime() - start
);
241 // deduct the thread run-time from the wait, if run-time was more than
242 // desired period, then skip the wait all together
243 if (runtime
< MENU_TASK_PERIOD_TICKS
) {
244 CoTickDelay(MENU_TASK_PERIOD_TICKS
- runtime
);
247 resetForcePowerOffRequest();
250 if (main_thread_running
== 0)
259 #if defined(PCBHORUS)
265 boardOff(); // Only turn power off if necessary
276 mixerTaskId
= CoCreateTask(mixerTask
, NULL
, 5, &mixerStack
.stack
[MIXER_STACK_SIZE
-1], MIXER_STACK_SIZE
);
277 menusTaskId
= CoCreateTask(menusTask
, NULL
, 10, &menusStack
.stack
[MENUS_STACK_SIZE
-1], MENUS_STACK_SIZE
);
280 // TODO move the SIMU audio in this task
281 audioTaskId
= CoCreateTask(audioTask
, NULL
, 7, &audioStack
.stack
[AUDIO_STACK_SIZE
-1], AUDIO_STACK_SIZE
);
284 audioMutex
= CoCreateMutex();
285 mixerMutex
= CoCreateMutex();