2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
26 #include "common/utils.h"
27 #include "common/maths.h"
29 #include "rx/sbus_channels.h"
32 #define SBUS_DIGITAL_CHANNEL_MIN 173
33 #define SBUS_DIGITAL_CHANNEL_MAX 1812
35 STATIC_ASSERT(SBUS_FRAME_SIZE
== sizeof(sbusFrame_t
), SBUS_FRAME_SIZE_doesnt_match_sbusFrame_t
);
37 uint8_t sbus26ChannelsDecode(rxRuntimeConfig_t
*rxRuntimeConfig
, const sbusChannels_t
*channels
, bool highChannels
)
39 uint8_t offset
= highChannels
? 16 : 0
40 uint16_t *sbusChannelData
= rxRuntimeConfig
->channelData
;
41 sbusChannelData
[0 + offset
] = channels
->chan0
;
42 sbusChannelData
[1 + offset
] = channels
->chan1
;
43 sbusChannelData
[2 + offset
] = channels
->chan2
;
44 sbusChannelData
[3 + offset
] = channels
->chan3
;
45 sbusChannelData
[4 + offset
] = channels
->chan4
;
46 sbusChannelData
[5 + offset
] = channels
->chan5
;
47 sbusChannelData
[6 + offset
] = channels
->chan6
;
48 sbusChannelData
[7 + offset
] = channels
->chan7
;
49 sbusChannelData
[8 + offset
] = channels
->chan8
;
50 sbusChannelData
[9 + offset
] = channels
->chan9
;
51 sbusChannelData
[10 + offset
] = channels
->chan10
;
52 sbusChannelData
[11 + offset
] = channels
->chan11
;
53 sbusChannelData
[12 + offset
] = channels
->chan12
;
54 sbusChannelData
[13 + offset
] = channels
->chan13
;
55 sbusChannelData
[14 + offset
] = channels
->chan14
;
56 sbusChannelData
[15 + offset
] = channels
->chan15
;
58 offset
= highChannels
? 0 : 2;
59 if (channels
->flags
& SBUS_FLAG_CHANNEL_DG1
) {
60 sbusChannelData
[32 + offset
] = SBUS_DIGITAL_CHANNEL_MAX
;
62 sbusChannelData
[32 + offset
] = SBUS_DIGITAL_CHANNEL_MIN
;
65 if (channels
->flags
& SBUS_FLAG_CHANNEL_DG2
) {
66 sbusChannelData
[33 + offset
] = SBUS_DIGITAL_CHANNEL_MAX
;
68 sbusChannelData
[33 + offset
] = SBUS_DIGITAL_CHANNEL_MIN
;
71 if (channels
->flags
& SBUS_FLAG_FAILSAFE_ACTIVE
) {
72 // internal failsafe enabled and rx failsafe flag set
73 // RX *should* still be sending valid channel data, so use it.
74 return RX_FRAME_COMPLETE
| RX_FRAME_FAILSAFE
;
77 if (channels
->flags
& SBUS_FLAG_SIGNAL_LOSS
) {
78 // The received data is a repeat of the last valid data so can be considered complete.
79 return RX_FRAME_COMPLETE
| RX_FRAME_DROPPED
;
82 return RX_FRAME_COMPLETE
;
85 uint8_t sbusChannelsDecode(rxRuntimeConfig_t
*rxRuntimeConfig
, const sbusChannels_t
*channels
)
87 uint16_t *sbusChannelData
= rxRuntimeConfig
->channelData
;
88 sbusChannelData
[0] = channels
->chan0
;
89 sbusChannelData
[1] = channels
->chan1
;
90 sbusChannelData
[2] = channels
->chan2
;
91 sbusChannelData
[3] = channels
->chan3
;
92 sbusChannelData
[4] = channels
->chan4
;
93 sbusChannelData
[5] = channels
->chan5
;
94 sbusChannelData
[6] = channels
->chan6
;
95 sbusChannelData
[7] = channels
->chan7
;
96 sbusChannelData
[8] = channels
->chan8
;
97 sbusChannelData
[9] = channels
->chan9
;
98 sbusChannelData
[10] = channels
->chan10
;
99 sbusChannelData
[11] = channels
->chan11
;
100 sbusChannelData
[12] = channels
->chan12
;
101 sbusChannelData
[13] = channels
->chan13
;
102 sbusChannelData
[14] = channels
->chan14
;
103 sbusChannelData
[15] = channels
->chan15
;
105 if (channels
->flags
& SBUS_FLAG_CHANNEL_DG1
) {
106 sbusChannelData
[16] = SBUS_DIGITAL_CHANNEL_MAX
;
108 sbusChannelData
[16] = SBUS_DIGITAL_CHANNEL_MIN
;
111 if (channels
->flags
& SBUS_FLAG_CHANNEL_DG2
) {
112 sbusChannelData
[17] = SBUS_DIGITAL_CHANNEL_MAX
;
114 sbusChannelData
[17] = SBUS_DIGITAL_CHANNEL_MIN
;
117 if (channels
->flags
& SBUS_FLAG_FAILSAFE_ACTIVE
) {
118 // internal failsafe enabled and rx failsafe flag set
119 // RX *should* still be sending valid channel data, so use it.
120 return RX_FRAME_COMPLETE
| RX_FRAME_FAILSAFE
;
123 if (channels
->flags
& SBUS_FLAG_SIGNAL_LOSS
) {
124 // The received data is a repeat of the last valid data so can be considered complete.
125 return RX_FRAME_COMPLETE
| RX_FRAME_DROPPED
;
128 return RX_FRAME_COMPLETE
;
131 uint16_t sbusDecodeChannelValue(uint16_t sbusValue
, bool safeValuesOnly
)
133 // Linear fitting values read from OpenTX-ppmus and comparing with values received by X4R
134 // http://www.wolframalpha.com/input/?i=linear+fit+%7B173%2C+988%7D%2C+%7B1812%2C+2012%7D%2C+%7B993%2C+1500%7D
135 if (safeValuesOnly
) {
136 // Clip channel values to more or less safe values (988 .. 2012)
137 return (5 * constrain(sbusValue
, SBUS_DIGITAL_CHANNEL_MIN
, SBUS_DIGITAL_CHANNEL_MAX
) / 8) + 880;
140 // Use full range of values (11 bit, channel values in range 880 .. 2159)
141 return (5 * constrain(sbusValue
, 0, 2047) / 8) + 880;
145 uint16_t sbusEncodeChannelValue(uint16_t rcValue
)
147 return constrain((((int)rcValue
- 880) * 8 + 4) / 5, SBUS_DIGITAL_CHANNEL_MIN
, SBUS_DIGITAL_CHANNEL_MAX
);
150 static uint16_t sbusChannelsReadRawRC(const rxRuntimeConfig_t
*rxRuntimeConfig
, uint8_t chan
)
152 return sbusDecodeChannelValue(rxRuntimeConfig
->channelData
[chan
], false);
155 void sbusChannelsInit(rxRuntimeConfig_t
*rxRuntimeConfig
)
157 rxRuntimeConfig
->rcReadRawFn
= sbusChannelsReadRawRC
;
158 for (int b
= 0; b
< SBUS_MAX_CHANNEL
; b
++) {
159 rxRuntimeConfig
->channelData
[b
] = (16 * PWM_RANGE_MIDDLE
) / 10 - 1408;