What are the prerequisites to correctly detect CRSF RX protocol?

I implementnt CRSF protocol for my radio system (QLRS) and it simply sends two kind of frames only, CRSF_FRAMETYPE_RC_CHANNELS_PACKED = 0x16, and CRSF_FRAMETYPE_LINK_STATISTICS = 0x14.
It works fine with betaflihgt FC, the channels values are correctly read by FC, but arduplane version 4.2.2 does not recognize RX.
Should I somehow care about the timing or kind of handshaking ? now the RC channels frames are send every 4ms, and link stats every 100ms.
I found the method void AP_RCProtocol_CRSF::_process_byte(uint32_t timestamp_us, uint8_t byte) and it looks like implementing crsf frame begining in very simply way, just assuming that frames may not be started received in the middle. Or maybe I dont get how it works. This part is confusing. If the CRC is wrong all received bytes are skipped, and it will never sync… Or maybe it would, if it detects gap in the transmission, or some other mechanism I don’t understand …

        // we consumed the partial frame, reset
        _frame_ofs = 0;

        // bad CRC (payload start is +1 from frame start, so need to subtract that from frame length to get index)
        if (_frame_crc != _frame.payload[_frame.length - 2]) {

In my opinion it should be something like this

if (frame_crc != fcProtoCrsfDecodedFrame.payload[fcProtoCrsfDecodedFrame.length - 2]) 
	// wrong CRC we should parse whole frame again startin at +1 char 
	// we are skiping first byte			
	for (i=1; i< lastFrameSize; i++)
		fcProtoCrsfProcSingleByte( ((uint8_t*)&fcProtoCrsfDecodedFrame)[i]);

Best regards

If we get a bad CRC we just drop the frame and start again. No reason why it shouldn’t work with just these two frame types. What board are you testing on?

But how do you ensure, that you start process the frame from it’s beginning? I mean how do you ensure that frame _frame_ofs variable is set to zero when first byte of the frame is read ?
Is it handled by this piece of coding?

    if (_frame_ofs > 0 && (timestamp_us - _start_frame_time_us) > CRSF_FRAME_TIMEOUT_US) {
        _frame_ofs = 0;

If not, when the crc is wrong, you are in the middle of current or next frame, and next time you start processing data not from first byte of the frame…

I’m using old pixhawk 2.4.8, but as I mentioned it works correct with TBS rx, it’s not working with my own developed RX, and I’m looking for the reasons…

I mean, the fc starts to process data at point n1 (it’s not begining of the frame), then according to random data (frame length) it’s calculate wrong CRC at point 2, and start processing data from next byte after point 2, then it fails again in point 3, and point 4 … what is the chance to start from real frame beginning?

It relies on the timeout check at the beginning. But you are right, 10ms could mean that it ends up in the wrong place continuously. The issue is that the inter-frame time is variable - you can’t tell what it should be until you have negotiated. We could shorten that timeout to CRSF_INTER_FRAME_TIME_US_250HZ but this was actually raised a little while ago because thread scheduling can cause delays here.

So this should solve the potential issue :slight_smile:

I doubt that with a LRS system you get new rc data at rates of 250 Hz, or even 100 Hz … so simply send a new rc CRSF frame only when you indeed get new data - anything else doesn’t make sense anyhow, along with the stats CRSF frame somewhat later… your gaps will be large enough and you won’t have any issues at all (and CRC errors should not happen often anyhow)
that’s what I do in mLRS, and it works great

it is IMHO correct however that AP’s CRSF implementation may struggle at high rates. I think the proper solution would be to do the timeout reset to flag a new frame in the isr or where ever the uart is low-level handled. Your “solution” won’t be really a solution, IMHO, as it is also based on assumptions, which may not be true

Thank for your feedback. I increased gaps to 12 ms, and the arduplance fc started to receive data.
But still it looks quite weird, need to investigate more.
And my proposal is a working proposal, and the best one. We don’t have any unique byte sequence to detect begin of a frame, so we need use kind of “window” sliding over incoming serial data, and trying to calculate CRC. When it’s matched it means that we received correct frame. And it would work depend less gaps between frames, bytes, serial transmission errors.
The approaches based on time gaps is good for students projects, not for mature FC :slightly_smiling_face:

still my RX is not getting any telemetry data from FC, need to play with that…

it is then very surprising you are considering CRSF in the first place … and surprising you mature are not aware of the failure rate of 8 bit crc in up to 64 bytes long messages … anyway, good luck :wink:

1 Like

Anyway, I do something wrong.
This is signal generated by genuine TBS rx, rc packet channels frames come every 6s, and except of those frames, we can sometimes see link stat frames…
And the FC is sending telemetry…

But when I do it in similar way the FC is not sending any telemetry data :frowning:
Any idea what i’m doing wrong

I found out that, missing native CRSF telemetry stream is connected only to Pixhawk 2.4.8 I used for testing.
When i try the same, with old Ominbus F4 board everything works fine.
The Pixhawk FC’s telemetry port is working fine with mavlink but not setup to be used with CRSF.