Frsky bidirectional telemetry implementation

Hi what radio, receiver version and protocol?

hi x8r sbus+sport connection with 10 in serial1_protocol parameter

RX firmware version? ACCST D16 1 or 2, bidirectional support is all about having the corrrect firmware

Old module with D16 v1
I don’t know firmware date but can flash it with X8R X6R FW20180322 i think…

go for latest D16 v1

so i flash latest x8r_fcc_180322 and xjt_noneu_170317
and no effect. i see RS in right corner, ardupilot messages like 100: CRT Bad Compass
and “…loading” at center (((

So. Can I debug it somehow ?

is it copter or plane?

It is a Plane…

ok, I just tested on X8R latest LBT firmware on Horus and working just fine, really no idea what could be wrong, perhepas the inverter?

ok ))) i’m going to flash LBT firmware ))))

how to enable loging in [LOGS] folder?

you cannot log sport, LOGS folder is for OpenTX logging

Alex, i’m sorry it was my mistake. I build master branch in your fork. now i switched to frsky_telem_bidirectional and rebuild it. everything is work! thank you for your support!

1 Like

Hi Alex, the Taranis Lite and R-XSR arrived, so I’ll be looking at F.Port when I get the chance.

Going back to CRC in mavlite, I still can’t get the checksum to equal 0x39 for the example parameter. Looking at your image below, are all fields added in, and in sequence from top to bottom? And the 0x32 framing byte?

Hi Eric,
CRC includes all 6 bytes used for the transport so appid and data.

CRC: idx=0, byte=00, crc=00
CRC: idx=1, byte=11, crc=11
CRC: idx=2, byte=16, crc=27
CRC: idx=3, byte=71, crc=98
CRC: idx=4, byte=3D, crc=D5
CRC: idx=5, byte=0A, crc=DF
CRC: idx=0, byte=01, crc=E0
CRC: idx=1, byte=3E, crc=1E
CRC: idx=2, byte=41, crc=5F
CRC: idx=3, byte=54, crc=B3
CRC: idx=4, byte=43, crc=F6
CRC: idx=5, byte=5F, crc=55
CRC: idx=0, byte=02, crc=57
CRC: idx=1, byte=52, crc=A9
CRC: idx=2, byte=41, crc=EA
CRC: idx=3, byte=54, crc=3E
CRC: idx=4, byte=5F, crc=9D
CRC: idx=5, byte=52, crc=EF
CRC: idx=0, byte=03, crc=F2
CRC: idx=1, byte=4C, crc=3E
CRC: idx=2, byte=4C, crc=8A
CRC: idx=3, byte=5F, crc=E9
CRC: idx=4, byte=50, crc=39
CRC: idx=5, byte=39, crc=39
TX(MSG) -> pkts=4, state=7, id=22, len=17, name=ATC_RAT_RLL_P, value=0.135000
RX -> 1100:0A3D7116
RX -> 3E01:5F435441
RX -> 5202:525F5441
RX -> 4C03:39505F4C

This is the parser, you can see all bytes are taken into account

void MAVLITE::mavlite_tx_parse(uint8_t* byte,uint8_t offset,  mavlite_message_t* txmsg, mavlite_status_t* status)
{
    switch (status->parse_state) {
        case PARSE_STATE_IDLE:
        case PARSE_STATE_ERROR:
            if ( offset == 0 ) {
                *byte = 0x00;
                status->parse_state = PARSE_STATE_GOT_START;
                mavlite_update_checksum(txmsg, *byte);
            } else {
                status->parse_state = PARSE_STATE_ERROR;
            }
            break;
        case PARSE_STATE_GOT_START:
            *byte = txmsg->len;
            status->parse_state = PARSE_STATE_GOT_LEN;
            mavlite_update_checksum(txmsg, *byte);
            break;
        case PARSE_STATE_GOT_LEN:
            *byte = txmsg->msgid;
            status->parse_state = PARSE_STATE_GOT_MSGID;
            mavlite_update_checksum(txmsg, *byte);
            break;
        case PARSE_STATE_GOT_MSGID:
            *byte = txmsg->payload[status->payload_next_byte++];
            status->parse_state = PARSE_STATE_GOT_PAYLOAD;
            mavlite_update_checksum(txmsg, *byte);
            break;
        case PARSE_STATE_GOT_SEQ:
            if ( status->payload_next_byte < txmsg->len ) {
                *byte = txmsg->payload[status->payload_next_byte++];
                status->parse_state = PARSE_STATE_GOT_PAYLOAD;
                mavlite_update_checksum(txmsg, *byte);
            } else {
                *byte = txmsg->checksum;
                status->parse_state = PARSE_STATE_MESSAGE_RECEIVED;
            }
            break;
        case PARSE_STATE_GOT_PAYLOAD:
            if ( offset == 0) {
                *byte = ++status->current_rx_seq;
                mavlite_update_checksum(txmsg, *byte);
                status->parse_state = PARSE_STATE_GOT_SEQ;
            } else {
                if ( status->payload_next_byte < txmsg->len ) {
                    *byte = txmsg->payload[status->payload_next_byte++];
                    mavlite_update_checksum(txmsg, *byte);
                } else {
                    *byte = txmsg->checksum;
                    status->parse_state = PARSE_STATE_MESSAGE_RECEIVED;
                }
            }
            break;
        case PARSE_STATE_MESSAGE_RECEIVED:
            break;
    }
}

and this is some simple code to reproduce the same result

#include <stdio.h>
#include <stdint.h>

void update_crc(uint8_t* crc, uint8_t c)
{
*crc += c; //0-1FF
*crc += *crc >> 8;
*crc &= 0xFF;
}

int main()
{
uint8_t crc=0;

uint8_t bytes[23] = {
    0x00,0x11,
    0x16,0x71,0x3D,0x0A,
    
    0x01,0x3E,
    0x41,0x54,0x43,0x5F,
    
    0x02,0x52,
    0x41,0x54,0x5F,0x52,
    
    0x03,0x4C,
    0x4C,0x5F,0x50
};
for (uint8_t i=0;i<sizeof(bytes);i++) {
    update_crc(&crc,bytes[i]);
    
    printf("%d: %02X -> %02X\n",i, bytes[i], crc);
}

}

Alex, thank you for taking the time to write this up. I really appreciate it. I’ve been staring at this on and off for a week. :frowning:

My code differs from yours here:

uint8_t crc=0;

I’m using 16 bits;

I’m sure yours is correct, but I wonder if this line

*crc += *crc >> 8;

can have any effect, other than to always add in 0? The high four bits ( > 255) are always dropped.

Hi Eric,
yes I noticed that too yesterday, while writing the examples, crc should be calculated by adding to an int16 otherwise no use for the >> 8.
Problem is lua behaves differently and I wasn’t able to make the crc work so I used the workaround to add to an uint8_t which yields a CRC that matches the lua one.
Sorry for not making this clear, I forgot about this “fix”, I’d like to go deeper and find why lua can match the uint8 one and not the int16 one

Ok, no problem Alex. I figured you had a good reason.

It’s different from the passthru one in 2 respects though.

  1. The issue mentioned above. So crc must be calculated in OpenTX?
  2. For passthough, we 1s complement the CRC as a last step.
    byte = 0xFF-CRC;

yes my mavlite library calculates/verifies CRCs in lua when sending/receiving mavlite messages if this was your question.
As for the 1s complement you’re right, my algo is simpler and skips that pass. I send the plain CRC and not the 1s complement of it.