diff --git a/radio/src/pulses/ppm.cpp b/radio/src/pulses/ppm.cpp index 5844568de..86970b0bc 100644 --- a/radio/src/pulses/ppm.cpp +++ b/radio/src/pulses/ppm.cpp @@ -21,9 +21,14 @@ #include "opentx.h" -template -void setupPulsesPPM(PpmPulsesData * ppmPulsesData, uint8_t channelsStart, int8_t channelsCount) +// Minimum space after the last PPM pulse in us +#define PPM_SAFE_MARGIN 3000 // 3ms + +template +uint16_t setupPulsesPPM(PpmPulsesData* ppmPulsesData, uint8_t channelsStart, + int8_t channelsCount) { + uint16_t total = 0; int16_t PPM_range = g_model.extendedLimits ? // range of 0.7 .. 1.7msec (512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2; @@ -43,38 +48,60 @@ void setupPulsesPPM(PpmPulsesData * ppmPulsesData, uint8_t channelsStart, int limit((int16_t)-PPM_range, channelOutputs[i], (int16_t)PPM_range) + 2 * PPM_CH_CENTER(i); *ppmPulsesData->ptr++ = v; + total += v; } - // Set the final period to the max - // (a new transfer is issued before it expires) - // debug: set the last period to the ppm_delay - *ppmPulsesData->ptr++ = 2000; - //*ppmPulsesData->ptr++ = 65535; - - // it's needed in case PPM is sent without DMA - // (we stop when we reach this 0) - *ppmPulsesData->ptr = 0; + return total; } void setupPulsesPPMTrainer() { - setupPulsesPPM( + uint16_t total = setupPulsesPPM( &trainerPulsesData.ppm, g_model.trainerData.channelsStart, g_model.trainerData.channelsCount); + + uint16_t rest = PPM_TRAINER_PERIOD_HALF_US(); + if (total < rest + PPM_SAFE_MARGIN * 2) + rest -= total; + else + rest = PPM_SAFE_MARGIN * 2; + + *trainerPulsesData.ppm.ptr++ = rest; + + // stop mark so that IRQ-based sending + // knows when to stop + *trainerPulsesData.ppm.ptr = 0; +} + +static void setupPulsesPPMModule(uint8_t module) +{ + PpmPulsesData* data = nullptr; +#if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM) + if (module == INTERNAL_MODULE) { + data = &intmodulePulsesData.ppm; + } else +#endif + { + data = &extmodulePulsesData.ppm; + } + + setupPulsesPPM(&extmodulePulsesData.ppm, + g_model.moduleData[module].channelsStart, + g_model.moduleData[module].channelsCount); + + // Set the final period to 1ms after which the + // PPM will be switched OFF + *data->ptr++ = PPM_SAFE_MARGIN * 2; } #if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM) void setupPulsesPPMInternalModule() { - setupPulsesPPM(&intmodulePulsesData.ppm, - g_model.moduleData[INTERNAL_MODULE].channelsStart, - g_model.moduleData[INTERNAL_MODULE].channelsCount); + setupPulsesPPMModule(INTERNAL_MODULE); } #endif void setupPulsesPPMExternalModule() { - setupPulsesPPM(&extmodulePulsesData.ppm, - g_model.moduleData[EXTERNAL_MODULE].channelsStart, - g_model.moduleData[EXTERNAL_MODULE].channelsCount); + setupPulsesPPMModule(EXTERNAL_MODULE); } diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 8988588ac..801ff5822 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -119,7 +119,9 @@ typedef Dsm2TimerPulsesData Dsm2PulsesData; #define PPM_DEF_PERIOD 225 /* 22.5ms */ #define PPM_STEP_SIZE 5 /*0.5ms*/ -#define PPM_PERIOD_HALF_US(module) ((g_model.moduleData[module].ppm.frameLength * PPM_STEP_SIZE + PPM_DEF_PERIOD) * 200) /*half us*/ +#define PPM_PERIOD_FL_TO_HALF_US(fl) (((fl)*PPM_STEP_SIZE+PPM_DEF_PERIOD)*200) /* half us*/ +#define PPM_PERIOD_HALF_US(module) PPM_PERIOD_FL_TO_HALF_US(g_model.moduleData[module].ppm.frameLength) /*half us*/ +#define PPM_TRAINER_PERIOD_HALF_US() PPM_PERIOD_FL_TO_HALF_US(g_model.trainerData.frameLength) /*half us*/ #define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2) /*us*/ #define DSM2_BAUDRATE 125000 #define DSM2_PERIOD 22000 /*us*/