Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_RCProtocol: IBUS hack for FlySky IA6 receiver #28306

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 55 additions & 5 deletions libraries/AP_RCProtocol/AP_RCProtocol_IBUS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@

#include "AP_RCProtocol_IBUS.h"

static int ia6_hack = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to have an AP_RCProtocol_IBUS_IA6 subclass so that other users can use this modified decoder by using the custom build server.


// decode a full IBUS frame
bool AP_RCProtocol_IBUS::ibus_decode(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe)
bool AP_RCProtocol_IBUS::ibus_decode_std(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe)
{
uint32_t chksum = 96;
uint16_t chksum = 96;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is correct?

ie. the checksum definition must state that your result is modulo UINT16_MAX. If it does not then you may pass the checksum when you shouldn't.


/* check frame boundary markers to avoid out-of-sync cases */
if ((frame[0] != 0x20) || (frame[1] != 0x40)) {
Expand Down Expand Up @@ -52,6 +54,45 @@ bool AP_RCProtocol_IBUS::ibus_decode(const uint8_t frame[IBUS_FRAME_SIZE], uint1
}


// decode a full IBUS frame
bool AP_RCProtocol_IBUS::ibus_decode_ia6(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe)
{
uint16_t chksum = 0;

/* check frame boundary markers to avoid out-of-sync cases */
if (frame[0] != 0x55) {
return false;
}

/* use the decoder matrix to extract channel data */
for (uint8_t channel = 0, pick=1; channel < IBUS_INPUT_CHANNELS; channel++, pick+=2) {
values[channel] = frame[pick] | ((frame[pick+1] & 0x0F)<<8);
chksum += values[channel];
}

uint16_t fr_chksum = frame[29] | (frame[30]<<8);

if (chksum != fr_chksum) {
return false;
}

if ((frame[2]&0xF0) || (frame[8]&0xF0)) {
*ibus_failsafe = true;
} else {
*ibus_failsafe = false;
}

return true;
}

bool AP_RCProtocol_IBUS::ibus_decode(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe)
{
if (ia6_hack) {
return ibus_decode_ia6( frame, values, ibus_failsafe);
}
return ibus_decode_std( frame, values, ibus_failsafe);
}

/*
process an IBUS input pulse of the given width
*/
Expand All @@ -69,23 +110,32 @@ void AP_RCProtocol_IBUS::_process_byte(uint32_t timestamp_us, uint8_t b)
const bool have_frame_gap = (timestamp_us - byte_input.last_byte_us >= 2000U);
byte_input.last_byte_us = timestamp_us;


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad whitespace change

if (have_frame_gap) {
// if we have a frame gap then this must be the start of a new
// frame
byte_input.ofs = 0;
}
if (b != 0x20 && byte_input.ofs == 0) {
// definately not IBUS, missing header byte

if ( !( (b == 0x20) || (b == 0x55) ) && byte_input.ofs == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need a virtual method to return expected header byte

// definitely not IBUS, missing header byte
return;
}

if (byte_input.ofs == 0 && !have_frame_gap) {
// must have a frame gap before the start of a new IBUS frame
return;
}

if (byte_input.ofs == 0)
{
Comment on lines +130 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (byte_input.ofs == 0)
{
if (byte_input.ofs == 0) {

ia6_hack = (b == 0x55)?1:0;
}

byte_input.buf[byte_input.ofs++] = b;

if (byte_input.ofs == sizeof(byte_input.buf)) {
if (byte_input.ofs == (sizeof(byte_input.buf)-ia6_hack)) // IA6 has one byte less
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will need a callback for expected number of bytes in a packet

{
uint16_t values[IBUS_INPUT_CHANNELS];
bool ibus_failsafe = false;
log_data(AP_RCProtocol::IBUS, timestamp_us, byte_input.buf, byte_input.ofs);
Expand Down
2 changes: 2 additions & 0 deletions libraries/AP_RCProtocol/AP_RCProtocol_IBUS.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class AP_RCProtocol_IBUS : public AP_RCProtocol_Backend
void process_byte(uint8_t byte, uint32_t baudrate) override;
private:
void _process_byte(uint32_t timestamp_us, uint8_t byte);
bool ibus_decode_std(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe);
bool ibus_decode_ia6(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe);
bool ibus_decode(const uint8_t frame[IBUS_FRAME_SIZE], uint16_t *values, bool *ibus_failsafe);

SoftSerial ss{115200, SoftSerial::SERIAL_CONFIG_8N1};
Expand Down
Loading