State of SBUS

Hi there,
I know that probably most of the work was spent in the Reach project and congratz for this :smile:
However, I am a bit curious about the state of SBUS. Theoretically, it might be possible to make it work as the signal processing is the same.
Does anyone has an idea what might have to be done to read the signal and process it via the DMA?


1 Like

What I learnt about SBUS vs CPPM is the signal processing is 10 times more intensive and there is no DMA because there is no decoder chip just GPIO.

The library used to read the pin should be fast enough but maybe some generic serial library is needed on top. CPU utilization would also go up.

The main problem I see is lack of official documentation, making it unecessarily difficult and uncertain compatability. There are some reverse engineering blogs and source snippets out there, but if a company were to implement it properly they should really be approaching Futaba and signing some sort of NDA. I wonder how 3DR did it for the Pixhawk then, or if they have a decoder chip with the Futaba logic buried inside. FrSky copied SBUS for their receivers so does that mean an NDA is also required with them to cross-check compatibility (if it was a Chinese rip-off and not the same SBUS as invented by Futaba).

1 Like

Regarding SBUS - it requires more processing which leads to performance degradation. Probably the decoding should be possible with some research and optimization. We have it in our task list but are a little bit busy with other stuff.

Just a question, is this a working SBUS protocol?

If so, and if processing is a performance problem, would it be possible to put reading in thread, and processing in a 50 Hz loop.
It also looks like that the code can be vectorized?! This could give additional 30-100% processing speed, but probably the compiler does already so :frowning:

Best, Daniel

That’s a good example I also stumbled upon and earmarked as a guide for my implementation, probably the best :wink:

Not sure about vectoring as a lot of different masking and shifting is going on there which cannot be batched into processor instructions any better than the C++ compiler will do normally. But it’s good to keep such features in mind. For super time critical snippets, dropping down to assembly for specific processors would help more (the rest still supported by a slower C language code block). I wonder if they did that for the Pixhawk or Arduino until now, if that sort of thing is acceptable to the APM team.

Yes the classic architecture for such things is a “driver” (at least a high priority thread if not an actual OS driver module) filling a ring buffer then the consumer thread picking up the latest results when it can/should (i.e. 50hz) maybe also some error correction or averaging of the extra unread information (which could not be processed quick enough) rather than just dumping it.

Along the same lines, a full SBUS implementation should also use the AUX connector to output SBUS. But to start with I think a lot of people would be happy with input only, to connect their digital receivers directly to Navio.

p.s. people interested in things like OneShot often are aware SBUS is also a way to increase response times, so they may want the user thread to check much more often than 50hz. Should be configurable then or in the same place of APM where they are thinking about supporting OneShot (that’s an ongoing duscussion).

In AP, the implementation is not efficient. However, I did no benchmarks and there could be the chance that nothing will change :smiley:
This is what I had in mind. I will make some benchmark when I have more time.
I was also thinking about moving the SBUS processing into a pthread and synchronize it with input in AP_HAL.
I am pretty optimistic that this code can be better optimized than the cross dependency loop in AP :slight_smile:

void SBUS::process() {
    (_buffer[24] != SBUS_ENDBYTE) ? return _errorFrames++ : _goodFrames++;

    _channels[0]  = ((_buffer[1]     |  _buffer[2]  <<8)                    & 0x07FF);
    _channels[1]  = ((_buffer[2] >>3 |  _buffer[3]  <<5)                    & 0x07FF);
    _channels[2]  = ((_buffer[3] >>6 |  _buffer[4]  <<2   |_buffer[5]<<10)  & 0x07FF);
    _channels[3]  = ((_buffer[5] >>1 |  _buffer[6]  <<7)                    & 0x07FF);
    _channels[4]  = ((_buffer[6] >>4 |  _buffer[7]  <<4)                    & 0x07FF);
    _channels[5]  = ((_buffer[7] >>7 |  _buffer[8]  <<1   |_buffer[9]<<9)   & 0x07FF);
    _channels[6]  = ((_buffer[9] >>2 |  _buffer[10] <<6)                    & 0x07FF);
    _channels[7]  = ((_buffer[10]>>5 |  _buffer[11] <<3)                    & 0x07FF);
    _channels[8]  = ((_buffer[12]    |  _buffer[13] <<8)                    & 0x07FF);
    _channels[9]  = ((_buffer[13]>>3 |  _buffer[14] <<5)                    & 0x07FF);
    _channels[10] = ((_buffer[14]>>6 |  _buffer[15] <<2   |_buffer[16]<<10) & 0x07FF);
    _channels[11] = ((_buffer[16]>>1 |  _buffer[17] <<7)                    & 0x07FF);
    _channels[12] = ((_buffer[17]>>4 |  _buffer[18] <<4)                    & 0x07FF);
    _channels[13] = ((_buffer[18]>>7 |  _buffer[19] <<1   |_buffer[20]<<9)  & 0x07FF);
    _channels[14] = ((_buffer[20]>>2 |  _buffer[21] <<6)                    & 0x07FF);
    _channels[15] = ((_buffer[21]>>5 |  _buffer[22] <<3)                    & 0x07FF);

    ((_buffer[23])      & 0x0001) ? _channels[16] = 2047: _channels[16] = 0;
    ((_buffer[23] >> 1) & 0x0001) ? _channels[17] = 2047: _channels[17] = 0;
    ((_buffer[23] >> 3) & 0x0001) ? _failsafe = SBUS_FAILSAFE_ACTIVE : _failsafe = SBUS_FAILSAFE_INACTIVE;

    if ((_buffer[23] >> 2) & 0x0001) {
    // Estimate timing
    _lastGoodFrame = millis();
1 Like

With slightly modified code for 10.000.000 calls in a VM:

AP_SBUS is my new implementation …

time AP_SBUS: 187 ms
time AP: 3502 ms


So after visiting the new homepage I think the new NAVIO2 has answered all our requirements (RC co-processor). Well done Emlid! Although as I have quite a few Navio boards I think I will strive to get good RC input support on the older boards, besides the protocol level programming is interesting. No idea how many were sold but I guess there are enough users out there to make good use of SBUS support in code rather than hardware.

1 Like

Does this mean S.Bus “is” now supported? I was all ready to pull the trigger on one of these boards until I read that S.Bus is not supported and that is a total show stopper for me. All of my RX’s are s.bus and I have no plans on buying any other RX’s just to be able to use this kit.

if it is such a drain on the RPI then maybe offload it to say a Teensy 3.2? None of my RX’s support cPPM so I am guessing I will have to put off buying the Navio2 until S.Bus is fully supported :frowning:


The talk was about Navio+, which does not properly support SBUS.
Navio2 works with SBUS without any problems (we did offload it by using a separate IO micro-controller).