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.
24 #define BITLEN_SBUS (10*2) // 100000 Baud => 10uS per bit
27 /* The protocol reuse some the DSM2 definitions where they are identical */
30 #if defined(PPM_PIN_SERIAL)
31 void sendByteSbus(uint8_t b
)
35 putDsm2SerialBit(0); // Start bit
36 for (uint8_t i
=0; i
<8; i
++) { // 8 data Bits
37 putDsm2SerialBit(b
& 1);
38 parity
= parity
^ (b
& 1);
41 putDsm2SerialBit(!parity
); // Even Parity bit
43 putDsm2SerialBit(1); // Stop bit
44 putDsm2SerialBit(1); // Stop bit
47 static void _send_level(uint8_t v
)
49 /* Copied over from DSM, this looks doubious and in my logic analyzer
50 output the low->high is about 2 ns late */
51 if (modulePulsesData
[EXTERNAL_MODULE
].dsm2
.index
& 1)
56 *modulePulsesData
[EXTERNAL_MODULE
].dsm2
.ptr
++ = v
- 1;
57 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.index
+=1;
58 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.rest
-=v
;
61 void sendByteSbus(uint8_t b
) //max 11 changes 0 10 10 10 10 P 1
66 uint8_t len
= BITLEN_SBUS
; //max val: 10*20 < 256
67 for (uint8_t i
=0; i
<=9; i
++) { //8Bits + 1Parity + Stop=1
68 bool nlev
= b
& 1; //lsb first
69 parity
= parity
^ (uint8_t)nlev
;
78 b
= (b
>>1) | 0x80; //shift in ones for stop bit and parity
80 b
= b
^ parity
; // lowest bit is one from previous line
82 _send_level(len
+ BITLEN_SBUS
); // enlarge the last bit to be two stop bits long
87 #define SBUS_NORMAL_CHANS 16
88 #define SBUS_CHAN_BITS 11
91 /* Definitions from CleanFlight/BetaFlight */
93 #define SBUS_FLAG_CHANNEL_17 (1 << 0)
94 #define SBUS_FLAG_CHANNEL_18 (1 << 1)
95 #define SBUS_FLAG_SIGNAL_LOSS (1 << 2)
96 #define SBUS_FLAG_FAILSAFE_ACTIVE (1 << 3)
97 #define SBUS_FRAME_BEGIN_BYTE 0x0F
99 #define SBUS_CHAN_CENTER 992
101 inline int getChannelValue(uint8_t port
, int channel
)
103 int ch
= g_model
.moduleData
[port
].channelsStart
+channel
;
104 // We will ignore 17 and 18th if that brings us over the limit
107 return channelOutputs
[ch
] + 2 * PPM_CH_CENTER(ch
) - 2*PPM_CENTER
;
110 void setupPulsesSbus(uint8_t port
)
112 #if defined(PPM_PIN_SERIAL)
113 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.serialByte
= 0;
114 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.serialBitCount
= 0;
116 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.rest
= SBUS_PERIOD_HALF_US
;
117 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.index
= 0;
120 modulePulsesData
[EXTERNAL_MODULE
].dsm2
.ptr
= modulePulsesData
[EXTERNAL_MODULE
].dsm2
.pulses
;
123 sendByteSbus(SBUS_FRAME_BEGIN_BYTE
);
126 uint8_t bitsavailable
= 0;
128 // byte 1-22, channels 0..2047, limits not really clear (B
129 for (int i
=0; i
<SBUS_NORMAL_CHANS
; i
++) {
130 int value
= getChannelValue(port
, i
);
132 value
= value
*8/10 + SBUS_CHAN_CENTER
;
133 bits
|= limit(0, value
, 2047) << bitsavailable
;
134 bitsavailable
+= SBUS_CHAN_BITS
;
135 while (bitsavailable
>= 8) {
136 sendByteSbus((uint8_t) (bits
& 0xff));
144 if (getChannelValue(port
, 16) > 0)
145 flags
|=SBUS_FLAG_CHANNEL_17
;
146 if (getChannelValue(port
, 17) > 0)
147 flags
|=SBUS_FLAG_CHANNEL_18
;
151 // last byte, always 0x0