Various fixes around Companion trainer mode (#7116)
[opentx.git] / radio / src / sbus.cpp
blobe9b975144efaa5531f569756be2d405926a5018c
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"
22 #include "sbus.h"
24 #define SBUS_FRAME_GAP_DELAY 1000 // 500uS
26 #define SBUS_START_BYTE 0x0F
27 #define SBUS_END_BYTE 0x00
28 #define SBUS_FLAGS_IDX 23
29 #define SBUS_FRAMELOST_BIT 2
30 #define SBUS_FAILSAFE_BIT 3
32 #define SBUS_CH_BITS 11
33 #define SBUS_CH_MASK ((1<<SBUS_CH_BITS) - 1)
35 #define SBUS_CH_CENTER 0x3E0
37 // Range for pulses (ppm input) is [-512:+512]
38 void processSbusFrame(uint8_t * sbus, int16_t * pulses, uint32_t size)
40 if (size != SBUS_FRAME_SIZE || sbus[0] != SBUS_START_BYTE || sbus[SBUS_FRAME_SIZE-1] != SBUS_END_BYTE) {
41 return; // not a valid SBUS frame
43 if ((sbus[SBUS_FLAGS_IDX] & (1<<SBUS_FAILSAFE_BIT)) || (sbus[SBUS_FLAGS_IDX] & (1<<SBUS_FRAMELOST_BIT))) {
44 return; // SBUS invalid frame or failsafe mode
47 sbus++; // skip start byte
49 uint32_t inputbitsavailable = 0;
50 uint32_t inputbits = 0;
51 for (uint32_t i=0; i<MAX_TRAINER_CHANNELS; i++) {
52 while (inputbitsavailable < SBUS_CH_BITS) {
53 inputbits |= *sbus++ << inputbitsavailable;
54 inputbitsavailable += 8;
56 *pulses++ = ((int32_t) (inputbits & SBUS_CH_MASK) - SBUS_CH_CENTER) * 5 / 8;
57 inputbitsavailable -= SBUS_CH_BITS;
58 inputbits >>= SBUS_CH_BITS;
61 ppmInputValidityTimer = PPM_IN_VALID_TIMEOUT;
64 void processSbusInput()
66 #if !defined(SIMU)
67 uint8_t rxchar;
68 uint32_t active = 0;
69 static uint8_t SbusIndex = 0;
70 static uint16_t SbusTimer;
71 static uint8_t SbusFrame[SBUS_FRAME_SIZE];
73 while (sbusGetByte(&rxchar)) {
74 active = 1;
75 if (SbusIndex > SBUS_FRAME_SIZE-1) {
76 SbusIndex = SBUS_FRAME_SIZE-1;
78 SbusFrame[SbusIndex++] = rxchar;
80 if (active) {
81 SbusTimer = getTmr2MHz();
82 return;
84 else {
85 if (SbusIndex) {
86 if ((uint16_t) (getTmr2MHz() - SbusTimer) > SBUS_FRAME_GAP_DELAY) {
87 processSbusFrame(SbusFrame, ppmInput, SbusIndex);
88 SbusIndex = 0;
92 #endif