2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
29 #include "build/debug.h"
31 #include "common/utils.h"
33 #include "drivers/time.h"
35 #include "io/serial.h"
38 #include "telemetry/telemetry.h"
43 #include "rx/sbus_channels.h"
49 * time between frames: 6ms.
50 * time to send frame: 3ms.
52 * Futaba R6208SB/R6303SB
53 * time between frames: 11ms.
54 * time to send frame: 3ms.
57 #define SBUS_TIME_NEEDED_PER_FRAME 3000
59 #define SBUS_STATE_FAILSAFE (1 << 0)
60 #define SBUS_STATE_SIGNALLOSS (1 << 1)
62 #define SBUS_FRAME_SIZE (SBUS_CHANNEL_DATA_LENGTH + 2)
64 #define SBUS_FRAME_BEGIN_BYTE 0x0F
66 #define SBUS_BAUDRATE 100000
68 #if !defined(SBUS_PORT_OPTIONS)
69 #define SBUS_PORT_OPTIONS (SERIAL_STOPBITS_2 | SERIAL_PARITY_EVEN)
72 #define SBUS_DIGITAL_CHANNEL_MIN 173
73 #define SBUS_DIGITAL_CHANNEL_MAX 1812
76 DEBUG_SBUS_FRAME_FLAGS
= 0,
77 DEBUG_SBUS_STATE_FLAGS
,
78 DEBUG_SBUS_FRAME_TIME
,
84 sbusChannels_t channels
;
86 * The endByte is 0x00 on FrSky and some futaba RX's, on Some SBUS2 RX's the value indicates the telemetry byte that is sent after every 4th sbus frame.
88 * See https://github.com/cleanflight/cleanflight/issues/590#issuecomment-101027349
90 * https://github.com/cleanflight/cleanflight/issues/590#issuecomment-101706023
93 } __attribute__ ((__packed__
));
95 typedef union sbusFrame_u
{
96 uint8_t bytes
[SBUS_FRAME_SIZE
];
97 struct sbusFrame_s frame
;
100 typedef struct sbusFrameData_s
{
109 // Receive ISR callback
110 static void sbusDataReceive(uint16_t c
, void *data
)
112 sbusFrameData_t
*sbusFrameData
= data
;
114 const uint32_t nowUs
= micros();
116 const int32_t sbusFrameTime
= nowUs
- sbusFrameData
->startAtUs
;
118 if (sbusFrameTime
> (long)(SBUS_TIME_NEEDED_PER_FRAME
+ 500)) {
119 sbusFrameData
->position
= 0;
122 if (sbusFrameData
->position
== 0) {
123 if (c
!= SBUS_FRAME_BEGIN_BYTE
) {
126 sbusFrameData
->startAtUs
= nowUs
;
129 if (sbusFrameData
->position
< SBUS_FRAME_SIZE
) {
130 sbusFrameData
->frame
.bytes
[sbusFrameData
->position
++] = (uint8_t)c
;
131 if (sbusFrameData
->position
< SBUS_FRAME_SIZE
) {
132 sbusFrameData
->done
= false;
134 sbusFrameData
->done
= true;
135 DEBUG_SET(DEBUG_SBUS
, DEBUG_SBUS_FRAME_TIME
, sbusFrameTime
);
140 static uint8_t sbusFrameStatus(rxRuntimeConfig_t
*rxRuntimeConfig
)
142 sbusFrameData_t
*sbusFrameData
= rxRuntimeConfig
->frameData
;
143 if (!sbusFrameData
->done
) {
144 return RX_FRAME_PENDING
;
146 sbusFrameData
->done
= false;
148 DEBUG_SET(DEBUG_SBUS
, DEBUG_SBUS_FRAME_FLAGS
, sbusFrameData
->frame
.frame
.channels
.flags
);
150 if (sbusFrameData
->frame
.frame
.channels
.flags
& SBUS_FLAG_SIGNAL_LOSS
) {
151 sbusFrameData
->stateFlags
|= SBUS_STATE_SIGNALLOSS
;
152 DEBUG_SET(DEBUG_SBUS
, DEBUG_SBUS_STATE_FLAGS
, sbusFrameData
->stateFlags
);
154 if (sbusFrameData
->frame
.frame
.channels
.flags
& SBUS_FLAG_FAILSAFE_ACTIVE
) {
155 sbusFrameData
->stateFlags
|= SBUS_STATE_FAILSAFE
;
156 DEBUG_SET(DEBUG_SBUS
, DEBUG_SBUS_STATE_FLAGS
, sbusFrameData
->stateFlags
);
159 DEBUG_SET(DEBUG_SBUS
, DEBUG_SBUS_STATE_FLAGS
, sbusFrameData
->stateFlags
);
161 return sbusChannelsDecode(rxRuntimeConfig
, &sbusFrameData
->frame
.frame
.channels
);
164 bool sbusInit(const rxConfig_t
*rxConfig
, rxRuntimeConfig_t
*rxRuntimeConfig
)
166 static uint16_t sbusChannelData
[SBUS_MAX_CHANNEL
];
167 static sbusFrameData_t sbusFrameData
;
169 rxRuntimeConfig
->channelData
= sbusChannelData
;
170 rxRuntimeConfig
->frameData
= &sbusFrameData
;
171 sbusChannelsInit(rxConfig
, rxRuntimeConfig
);
173 rxRuntimeConfig
->channelCount
= SBUS_MAX_CHANNEL
;
174 rxRuntimeConfig
->rxRefreshRate
= 11000;
176 rxRuntimeConfig
->rcFrameStatusFn
= sbusFrameStatus
;
178 const serialPortConfig_t
*portConfig
= findSerialPortConfig(FUNCTION_RX_SERIAL
);
184 bool portShared
= telemetryCheckRxPortShared(portConfig
);
186 bool portShared
= false;
189 serialPort_t
*sBusPort
= openSerialPort(portConfig
->identifier
,
194 portShared
? MODE_RXTX
: MODE_RX
,
195 SBUS_PORT_OPTIONS
| (rxConfig
->serialrx_inverted
? 0 : SERIAL_INVERTED
) | (rxConfig
->halfDuplex
? SERIAL_BIDIR
: 0)
198 if (rxConfig
->rssi_src_frame_errors
) {
199 rssiSource
= RSSI_SOURCE_FRAME_ERRORS
;
204 telemetrySharedPort
= sBusPort
;
208 return sBusPort
!= NULL
;