1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-13 19:40:20 +03:00

Fixes #2579: Added support for Trainer signal alarm

- added alarm “Trainer signal lost” & “Trainer signal recovered”.
- moved PPM capture code to trainer_input.{h,cpp}
This commit is contained in:
Raphael Coeffic 2015-07-28 23:05:36 +02:00
parent 3d461b771f
commit f6bff9683d
12 changed files with 185 additions and 78 deletions

View file

@ -1058,7 +1058,7 @@ ifeq ($(GUI), YES)
CPPDEFS += -DGUI
endif
CPPSRC += opentx.cpp functions.cpp strhelpers.cpp $(PULSESSRC) switches.cpp curves.cpp mixer.cpp stamp.cpp $(GUISRC) $(EEPROMSRC) timers.cpp
CPPSRC += opentx.cpp functions.cpp strhelpers.cpp $(PULSESSRC) switches.cpp curves.cpp mixer.cpp stamp.cpp $(GUISRC) $(EEPROMSRC) timers.cpp trainer_input.cpp
ifeq ($(GUI), YES)
GUISRC += gui/$(GUIDIRECTORY)/lcd.cpp gui/$(GUIDIRECTORY)/splash.cpp gui/$(GUIDIRECTORY)/fonts.cpp

View file

@ -169,6 +169,8 @@ const char * const audioFilenames[] = {
"swr_red",
"telemko",
"telemok",
"trainko",
"trainok",
#if defined(PCBSKY9X)
"highmah",
"hightemp",

View file

@ -331,6 +331,8 @@ void audioStart();
#define AUDIO_RXBATT_RED() audioEvent(AU_RXBATT_RED)
#define AUDIO_TELEMETRY_LOST() audioEvent(AU_TELEMETRY_LOST)
#define AUDIO_TELEMETRY_BACK() audioEvent(AU_TELEMETRY_BACK)
#define AUDIO_TRAINER_LOST() audioEvent(AU_TRAINER_LOST)
#define AUDIO_TRAINER_BACK() audioEvent(AU_TRAINER_BACK)
#define AUDIO_HEARTBEAT()

View file

@ -455,7 +455,7 @@ void evalInputs(uint8_t mode)
}
#endif
if (mode <= e_perout_mode_inactive_flight_mode && isFunctionActive(FUNCTION_TRAINER+ch) && ppmInValid) {
if (mode <= e_perout_mode_inactive_flight_mode && isFunctionActive(FUNCTION_TRAINER+ch) && IS_TRAINER_INPUT_VALID()) {
// trainer mode
TrainerMix* td = &g_eeGeneral.trainer.mix[ch];
if (td->mode) {
@ -662,7 +662,7 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms)
#define MIXER_LINE_DISABLE() (mixCondition = true, mixEnabled = 0)
if (mixEnabled && md->srcRaw >= MIXSRC_FIRST_TRAINER && md->srcRaw <= MIXSRC_LAST_TRAINER && !ppmInValid) {
if (mixEnabled && md->srcRaw >= MIXSRC_FIRST_TRAINER && md->srcRaw <= MIXSRC_LAST_TRAINER && !IS_TRAINER_INPUT_VALID()) {
MIXER_LINE_DISABLE();
}

View file

@ -155,7 +155,7 @@ void per10ms()
#endif
if (trimsCheckTimer) trimsCheckTimer--;
if (ppmInValid) ppmInValid--;
if (g_ppmInputValidityTimer) g_ppmInputValidityTimer--;
#if defined(CPUARM)
if (trimsDisplayTimer)
@ -1714,6 +1714,7 @@ void doMixerCalculations()
s_cnt_1s += 1;
logicalSwitchesTimerTick();
checkTrainerSignalWarning();
if (s_cnt_1s >= 10) { // 1sec
s_cnt_1s -= 10;
@ -2068,10 +2069,6 @@ void checkBattery()
}
}
int16_t g_ppmIns[NUM_TRAINER];
uint8_t ppmInState = 0; // 0=unsync 1..8= wait for value i-1
uint8_t ppmInValid = 0;
#if !defined(SIMU) && !defined(CPUARM)
volatile uint8_t g_tmr16KHz; //continuous timer 16ms (16MHz/1024/256) -- 8-bit counter overflow
@ -2153,26 +2150,7 @@ ISR(TIMER3_CAPT_vect) // G: High frequency noise can cause stack overflo with IS
PAUSE_PPMIN_INTERRUPT();
sei(); // enable other interrupts
uint16_t val = (capture - lastCapt) / 2;
// G: We process g_ppmIns immediately here, to make servo movement as smooth as possible
// while under trainee control
if (val>4000 && val < 16000) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses)
ppmInState = 1; // triggered
}
else {
if (ppmInState>0 && ppmInState<=8) {
if (val>800 && val<2200) { // if valid pulse-width range
ppmInValid = PPM_IN_VALID_TIMEOUT;
g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500) * (uint8_t)(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough.
}
else {
ppmInState = 0; // not triggered
}
}
}
lastCapt = capture;
captureTrainerPulses(capture);
cli(); // disable other interrupts for stack pops before this function's RETI
RESUME_PPMIN_INTERRUPT();

View file

@ -1127,10 +1127,8 @@ extern uint8_t g_vbat100mV;
extern uint8_t g_beepCnt;
extern uint8_t g_beepVal[5];
extern uint8_t ppmInState; //0=unsync 1..8= wait for value i-1
extern uint8_t ppmInValid;
#define PPM_IN_VALID_TIMEOUT 100
extern int16_t g_ppmIns[NUM_TRAINER];
#include "trainer_input.h"
extern int32_t chans[NUM_CHNOUT];
extern int16_t ex_chans[NUM_CHNOUT]; // Outputs (before LIMITS) of the last perMain
extern int16_t channelOutputs[NUM_CHNOUT];
@ -1392,6 +1390,8 @@ enum AUDIO_SOUNDS {
AU_SWR_RED,
AU_TELEMETRY_LOST,
AU_TELEMETRY_BACK,
AU_TRAINER_LOST,
AU_TRAINER_BACK,
#endif
#if defined(PCBSKY9X)
AU_TX_MAH_HIGH,

View file

@ -87,7 +87,7 @@ void processSbusFrame(uint8_t *sbus, int16_t *pulses, uint32_t size)
inputbits >>= SBUS_CH_BITS;
}
ppmInValid = PPM_IN_VALID_TIMEOUT;
g_ppmInputValidityTimer = PPM_IN_VALID_TIMEOUT;
}
void processSbusInput()

View file

@ -248,31 +248,10 @@ void start_timer4()
extern "C" void TC3_IRQHandler() //capture ppm in at 2MHz
{
static uint16_t lastCapt ;
uint16_t capture = TC1->TC_CHANNEL[0].TC_RA ;
(void) TC1->TC_CHANNEL[0].TC_SR ; // Acknowledge the interrupt
uint16_t val = ((uint16_t)(capture - lastCapt)) / 2;
// G: We process g_ppmIns immediately here, to make servo movement as smooth as possible
// while under trainee control
if (val>4000 && val<19000) { // G: Prioritize reset pulse. (Needed when less than 16 incoming pulses)
ppmInState = 1; // triggered
}
else {
if (ppmInState>0 && ppmInState<=16) {
if (val>800 && val<2200) { // if valid pulse-width range
ppmInValid = PPM_IN_VALID_TIMEOUT;
g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough.
}
else {
ppmInState = 0; // not triggered
}
}
}
lastCapt = capture;
captureTrainerPulses(capture);
}
void init_trainer_capture()

View file

@ -121,8 +121,6 @@ void stop_trainer_capture()
extern "C" void TIM3_IRQHandler()
{
uint16_t capture = 0;
static uint16_t lastCapt ;
uint16_t val ;
bool doCapture = false ;
// What mode? in or out?
@ -139,25 +137,7 @@ extern "C" void TIM3_IRQHandler()
}
if (doCapture) {
val = (uint16_t)(capture - lastCapt) / 2 ;
lastCapt = capture;
// We process g_ppmInsright here to make servo movement as smooth as possible
// while under trainee control
if (val>4000 && val<19000) { // G: Prioritize reset pulse. (Needed when less than 16 incoming pulses)
ppmInState = 1; // triggered
}
else {
if (ppmInState>0 && ppmInState<=16) {
if (val>800 && val<2200) {
ppmInValid = PPM_IN_VALID_TIMEOUT;
g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough.
}
else {
ppmInState = 0; // not triggered
}
}
}
captureTrainerPulses(capture);
}
// PPM out compare interrupt

View file

@ -0,0 +1,69 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "trainer_input.h"
int16_t g_ppmIns[NUM_TRAINER];
uint8_t g_ppmInputValidityTimer;
#if defined(CPUARM)
#include "audio_arm.h"
void checkTrainerSignalWarning()
{
enum PpmInValidState_t {
PPM_IN_IS_NOT_USED=0,
PPM_IN_IS_VALID,
PPM_IN_INVALID
};
static uint8_t ppmInputValidState = PPM_IN_IS_NOT_USED;
if(g_ppmInputValidityTimer && (ppmInputValidState == PPM_IN_IS_NOT_USED)) {
ppmInputValidState = PPM_IN_IS_VALID;
}
else if (!g_ppmInputValidityTimer && (ppmInputValidState == PPM_IN_IS_VALID)) {
ppmInputValidState = PPM_IN_INVALID;
AUDIO_TRAINER_LOST();
}
else if (g_ppmInputValidityTimer && (ppmInputValidState == PPM_IN_INVALID)) {
ppmInputValidState = PPM_IN_IS_VALID;
AUDIO_TRAINER_BACK();
}
}
#endif

89
radio/src/trainer_input.h Normal file
View file

@ -0,0 +1,89 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef trainer_input_h
#define trainer_input_h
#include "myeeprom.h"
// Trainer input channels
extern int16_t g_ppmIns[NUM_TRAINER];
// Timer gets decremented in per10ms()
#define PPM_IN_VALID_TIMEOUT 100 // 1s
extern uint8_t g_ppmInputValidityTimer;
#define IS_TRAINER_INPUT_VALID() (g_ppmInputValidityTimer != 0)
#if defined(CPUARM)
void checkTrainerSignalWarning();
#else
#define checkTrainerSignalWarning()
#endif
// Needs to be inlined to avoid slow function calls in ISR routines
inline void captureTrainerPulses(uint16_t capture)
{
static uint16_t lastCapt=0;
static uint8_t channelNumber=0;
uint16_t val = (uint16_t)(capture - lastCapt) / 2;
lastCapt = capture;
// We process g_ppmInsright here to make servo movement as smooth as possible
// while under trainee control
//
// G: Prioritize reset pulse. (Needed when less than 16 incoming pulses)
//
if (val>4000 && val<19000) {
channelNumber = 1; // triggered
}
else {
if ((channelNumber > 0) && (channelNumber <= NUM_TRAINER)) {
if (val>800 && val<2200) {
g_ppmInputValidityTimer = PPM_IN_VALID_TIMEOUT;
g_ppmIns[channelNumber++ - 1] =
//+-500 != 512, but close enough.
(int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10;
}
else {
channelNumber = 0; // not triggered
}
}
}
}
#endif

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
@ -186,6 +186,8 @@ def ttsEn():
(u"radio antenna defective", "swr_red", NO_ALTERNATE),
(u"telemetry lost", "telemko", NO_ALTERNATE),
(u"telemetry recovered", "telemok", NO_ALTERNATE),
(u"trainer signal lost", "trainko", NO_ALTERNATE),
(u"trainer signal recovered", "trainok", NO_ALTERNATE),
]:
systemSounds.append((s, filename(f, a)))
for i, (s, f) in enumerate([
@ -282,6 +284,8 @@ def ttsFr():
(u"Antenne défectueuse", "swr_red", NO_ALTERNATE),
(u"Plus de télémétrie", "telemko", NO_ALTERNATE),
(u"Télémétrie retrouvée", "telemok", NO_ALTERNATE),
(u"Signal écolage perdu", "trainko", NO_ALTERNATE),
(u"Signal écolage retrouvé", "trainok", NO_ALTERNATE),
]:
systemSounds.append((s, filename(f, a)))
for i, (s, f) in enumerate([
@ -599,6 +603,10 @@ def ttsDe():
(u"Funksignal schlecht!", "rssi_org", NO_ALTERNATE),
(u"Funksignal kritisch!", "rssi_red", NO_ALTERNATE),
(u"Problem mit der sender Antenna", "swr_red", NO_ALTERNATE),
(u"Telemetrie verloren", "telemko", NO_ALTERNATE),
(u"Telemetrie wiederhergestellt", "telemok", NO_ALTERNATE),
(u"Schülersignal verloren", "trainko", NO_ALTERNATE),
(u"Schülersignal wiederhergestellt", "trainok", NO_ALTERNATE),
]:
systemSounds.append((s, filename(f, a)))
for i, s in enumerate(["Timer", "Timer", "Sendung", "Empfang", "A1", "A2", "Hoehe", "Motor",