FrSky Hardware / Software / RF protocol hacking

Love the 9x? Use FRSky? Post your questions and answers here!
Post Reply
User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

FrSky Hardware / Software / RF protocol hacking

Post by Kilrah » Wed Apr 11, 2012 9:35 am

Well, some insights at least...

Following the discussion in this thread, as I had nothing to do on that free Monday I did what I suggested:
Kilrah wrote:Someone will have to tap a logic analyzer between the STM32 and the CC2500 at some point :D
As a starter, a couple of high res pictures of a D8RSP, identical to a D8RII (click for larger size, apparently photobucket didn't keep my 17MP files...):

Bottom:

Image

Top:

Image

Logic analyser connections:

Image

So I tapped the SPI connection between the receiver's main processor (STMicro STM103C8) and the RF chip (Texas Instruments CC2500) and went on to capture one dataset in the following conditions:
  • Radio on and previously bound
  • Capture from time receiver is powered up
Which gave me a nice big bunch of transitions to look at. The captured file is attached at the bottom of the post.

The whole thing expectedly starts by a RESET of the CC2500, then a rather large stream of register writes to initialise the chip. I've decoded about half of it, then went on to the more interesting stuff, maybe to come back later:

Format is:
Sequence number - Data - What it actually means on the registers (Description). Shouldn't be line-wrapped, but forum decides otherwise.

Code: Select all

01 - (0x30) RESET
02 - (0x02 0x06) GDO0_INV = 0 / GDO0_CFG = 6 (Asserts when sync word has been sent / received, and de-asserts at the end of the packet. In RX, the pin will de-assert when the optional address check fails or the RX FIFO overflows. In TX the pin will de-assert if the TX FIFO underflows)
03 - (0x00 0x06) GDO2_INV = 0 / GDO2_CFG = 6 (Asserts when sync word has been sent / received, and de-asserts at the end of the packet. In RX, the pin will de-assert when the optional address check fails or the RX FIFO overflows. In TX the pin will de-assert if the TX FIFO underflows)
04 - (0x17 0x0C) CCA_MODE = 0 (Always) / RXOFF_MODE = 0x11 (Select what should happen when a packet has been received - Stay in RX) / TXOFF_MODE = 0 (Select what should happen when a packet has been sent (TX) - IDLE)
05 - (0x18 0x18) FS_AUTOCAL = 0x01 (Automatically calibrate when going from IDLE to RX or TX (or FSTXON)) / PO_TIMEOUT = 0x10 (Programs the number of times the six-bit ripple counter must expire after XOSC has stabilized before CHP_RDYn goes low. - Expire count 64 Approx. 149 – 155 µs)
06 - (0x06 0x19) PKTLEN=0x19
07 - (0x07 0x04) PQT = 0 (When PQT=0 a sync word is always accepted.) / CRC_AUTOFLUSH = 0 / APPEND_STATUS = 1 (When enabled, two status bytes will be appended to the payload of the packet. The status bytes contain RSSI and LQI values, as well as the CRC OK flag.) / ADR_CHK = 0 (No address check)
08 - (0x08 0x05) WHITE_DATA = 0 / PKT_FORMAT = 0 (Normal mode, use FIFOs for RX and TX) / CC2400_EN = 0 / CRC_EN = 1 (CRC calculation in TX and CRC check in RX enabled) / LENGTH_CONFIG = 1 (Variable packet length mode. Packet length configured by the first byte after sync word)
09 - (0x3E 0xFF) PATABLE(0) = 0xFF (+1dBm)
10 - (0x0B 0x08) FREQ_IF = 0x08 (IF = 203.125kHz)
11 - (0x0C 0x00) FREQOFF = 0
12 - (0x0D 0x5C 0x0E 0x76 0x0F 0x27) FREQ = 0x5C7627 (F = 2404MHz)
13 - (0x10 0xAA) CHANBW_E = 0x10 / CHANBW_M = 0x10 Sets the decimation ratio for the delta-sigma ADC input stream and thus the channel bandwidth. BW = 135.417kHz / DRATE_E = 0x0A
14 - (0x11 0x39) DRATE_M = 0x39 Bitrate = 31044 bps
15 - (0x12 0x11) MOD_FORMAT = 0x01 (GFSK) / SYNC_MODE = 0x01 (15/16 sync word bits detected)
16 - (0x13 0x23) FEC_EN = Disable / NUM_PREAMBLE = 0x02 (4 bytes) / CHANSPC_E = 0x03
17 - (0x14 0x7A) CHANSPC_M = 0x7A Channel Spacing = 299927Hz
18 - (0x15 0x42) DEVIATION_E = 0x100 / DEVIATION_M = 0x02 Deviation mantissa, interpreted as a 4-bit value with MSB implicit 1. Deviation = 31738Hz
19 - (0x19 0x16) FOC_BS_CS_GATE = 0 / FOC_PRE_K = 0x10 (The frequency compensation loop gain to be used before a sync word is detected. - 3K) / FOC_POST_K = 1 (The frequency compensation loop gain to be used after a sync word is detected. - K/2) / FOC_LIMIT = 0x10 (The saturation point for the frequency offset compensation algorithm - ±BWCHAN/4)
20 - (0x1A 0x6C) BS_PRE_KI = 0x01 (2KI) / BS_PRE_KP = 0x10 (3KP) / BS_POST_KI = 1 (KI /2) / BS_POST_KP = 1 (Kp) / BS_LIMIT = 0 (No data rate offset compensation performed)
21 - (0x1B 0x03) MAX_DVGA_GAIN = 0 (All gain settings can be used) / MAX_LNA_GAIN = 0 (Maximum possible LNA + LNA 2 gain) / MAGN_TARGET = 0x011 (Target amplitude from channel filter = 33dB)
... not finished decoding initialisation
Not terribly interesting at this point, which is why I didn't go further yet. One thing to note is the 31kbps RF baudrate and 300kHz channel spacing. The chip apparently computes the channels itself, once configured changing channel is just an affair of writing to a 1-byte channel number register.

Following this, the actual "routine" communications start:

Code: Select all

First channel set
(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x53) CHANNR = 0x53
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters
[1.39ms]
(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.

[100ms]

(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x8E 0x00 0x01 0x38 0xF9 0xCB 0x54 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55) 
(0xFF) Burst access to RX FIFO - 2 bytes (0x72 0xB1)

[0.5ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0xA3) CHANNR = 0xA3
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.37ms]

(0x3A) SFRX Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states.
(0x3B) SFTX Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states.
(0x7F) Burst access to TX FIFO - 18 bytes (0x11 0x85 0x2D 0x7B 0x85 0x0F 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00)
(0x35) 0x35 STX In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: Only go to TX if channel is clear.

[7.47ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x08) CHANNR = 0x08
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.39ms]

(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x90 0x00 0x01 0x38 0xF9 0xCB 0x54 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55)
(0xFF) Burst access to RX FIFO - 2 bytes (0x72 0xB1)

[0.5ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x58) CHANNR = 0x58
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.39ms]

(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.

[6.93ms]

(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x90 0x00 0x01 0x38 0xF9 0xCB 0x54 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55)
(0xFF) Burst access to RX FIFO - 2 bytes (0x72 0xB1)

[0.5ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x58) CHANNR = 0x58
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.39ms]

(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.

[6.93ms]

(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x91 0x00 0x01 0x38 0xF9 0xCB 0x54 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55)
(0xFF) Burst access to RX FIFO - 2 bytes (0x72 0xB1)

[0.5ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0xA8) CHANNR = 0xA8
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.39ms]

(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.

[6.93ms]

(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x92 0x00 0x01 0x38 0xF9 0xCB 0x55 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55)
(0xFF) Burst access to RX FIFO - 2 bytes (0x6D 0xB1)

[0.5ms]


(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x0D) CHANNR = 0x0D
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.37ms]

(0x3A) SFRX Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states.
(0x3B) SFTX Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states.
(0x7F) Burst access to TX FIFO - 18 bytes (0x11 0x85 0x2D 0x7E 0x86 0x3C 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00)
(0x35) 0x35 STX In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: Only go to TX if channel is clear.

[7.47ms]

(0x36) SIDLE Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable.
(0x0A 0x5D) CHANNR = 0x5D
(0x23 0x89) Set Frequency Synthesizer Calibration Parameters

[1.39ms]

(0x34) SRX Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1.

[6.93ms]

(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFB) RXBYTES Overflow and number of bytes in the RX FIFO (0x14)
(0xDB) 
(0xFF) Burst access to RX FIFO - 1 byte (0x11)
(0xFF) Burst access to RX FIFO - 2 bytes (0x85 0x2D)
(0xFF) Burst access to RX FIFO - 15 bytes (0x94 0x00 0x01 0x38 0xF9 0xCB 0x55 0x89 0x85 0xCB 0xCB 0xCB 0xCB 0x88 0x55)
(0xFF) Burst access to RX FIFO - 2 bytes (0x73 0xB0)

etc
A lot of stuff that makes a rather simple pattern evident:
  • The RF frame period is 9ms
  • Channel hops every frame
  • Every 4th frame is a downlink frame. So we get 3 uplink frames, one downlink, and repeat
  • Packet size is constant, an uplink frame always contains 20 bytes, a downlink frame always contains 18 bytes
This is where I started doing several tests to look into the actual transmitted data. I started by setting CH1 to "Servo Test" on the 9x to see how it moved, I went on doing various other combinations, compare with the same receiver bound to another TX, connecting voltages to A1/A2, varying RSSI with range check mode, connecting hub,...
The frames look like this, FrSky were nice enough to break down the uplink buffer reads into 4 parts, hinting at particular meanings for each. That's what the breaks are. The downlink frame is in one write.

Code: Select all

CH1 oscillating 

11 	85 2D 	64 08 01 8E CB CB CB 88 88 CB CB CB CB 88 88 	5D AF
11 	85 2D 	65 08 01 BC CB CB CB 88 88 CB CB CB CB 88 88	5B AF
11 	85 2D	66 08 01 BC CB CB CB 88 88 CB CB CB CB 88 88	5D B0

11 85 2D 60 77 5F 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D 	68 08 01 DA CB CB CB 88 88 CB CB CB CB 88 88	5E AD
11 	85 2D	69 08 01 DA CB CB CB 88 88 CB CB CB CB 88 88	19 AC
11 	85 2D	6A 08 01 F9 CB CB CB 88 88 CB CB CB CB 88 88	27 B0

11 85 2D 60 77 66 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D	6C 08 01 17 CB CB CB 89 88 CB CB CB CB 88 88	1B AE
11 	85 2D	6D 08 01 17 CB CB CB 89 88 CB CB CB CB 88 88	28 AF
11 	85 2D	6E 08 01 17 CB CB CB 89 88 CB CB CB CB 88 88	29 B0

11 85 2D 60 77 5C 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D	70 08 01 45 CB CB CB 89 88 CB CB CB CB 88 88	1B AF
11 	85 2D	71 08 01 64 CB CB CB 89 88 CB CB CB CB 88 88	2A B0
11 	85 2D	72 08 01 64 CB CB CB 89 88 CB CB CB CB 88 88	29 AE

11 85 2D 5F 76 51 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D	74 08 01 83 CB CB CB 89 88 CB CB CB CB 88 88	1E B1
11 	85 2D	75 08 01 83 CB CB CB 89 88 CB CB CB CB 88 88	29 B0
11 	85 2D	76 08 01 A1 CB CB CB 89 88 CB CB CB CB 88 88	28 AF

11 85 2D 60 77 52 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D	78 08 01 A1 CB CB CB 89 88 CB CB CB CB 88 88	1B B0
11 	85 2D	79 08 01 D0 CB CB CB 89 88 CB CB CB CB 88 88	29 B1
11 	85 2D	7A 08 01 D0 CB CB CB 89 88 CB CB CB CB 88 88	2C AE

11 85 2D 60 77 53 00 00 00 00 00 00 00 00 00 00 00 00

11 	85 2D	7C 08 01 EF CB CB CB 89 88 CB CB CB CB 88 88	20 AF
11 	85 2D	7D 08 01 EF CB CB CB 89 88 CB CB CB CB 88 88	2E AF
11 	85 2D	7E 08 01 0D CB CB CB 8A 88 CB CB CB CB 88 88	2A B0

11 85 2D 60 77 53 00 00 00 00 00 00 00 00 00 00 00 00
So, the conclusions I have up to now are the following:
The uplink frame consists in:
  • 0x11, fixed header
  • A 2-byte TX identifier. This one will change when bound to another TX
  • A 1-byte frame counter. It includes downlink frames even if not transmitted in them
  • 14 bytes of channel data. Haven't managed to crack down the arrangement yet, but it looks messy. It's so not straightforward that I wouldn't be surprised if there's some encoding going on
  • 2 bytes which are most likely a checksum
And the downlink frame:
  • 0x11, fixed header
  • The same 2-byte TX identifier
  • 1 byte for A0 (plain ADC value)
  • 1 byte for A1 (plain ADC value)
  • 1 byte for RSSI (plain value too)
  • 12 bytes of user data if any, they're transmitted as 0x00 if nothing's connected
That's for a start. Downlink frame was easy, Uplink a little less so, this channel data is more complicated. 14 bytes = 8 14-bit words, could be an insight... but they certainly aren't simply concatenated.
My oscillating CH1 seemed to hint at the 7th byte being the LSB, but the MSBs were somewhere in the 11th byte. CH2 seemed to affect the 2nd and 11th bytes.

The interesting thing is that apart from this detail it's a very easy transmission scheme. Wouldn't be hard to replicate :)
I haven't yet looked into how antenna and TX/RX switching was implemented.
Attachments
Frsky D8RSP startup with radio.zip
Read with Logic software available at http://www.saleae.com/downloads/
(373.77 KiB) Downloaded 335 times
Last edited by Kilrah on Sun Apr 15, 2012 1:51 pm, edited 1 time in total.

User avatar
MikeB
9x Developer
Posts: 15651
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: FrSky RF protocol hacking

Post by MikeB » Wed Apr 11, 2012 2:09 pm

That all look interesting, well done.
From the PXX protocol, I'd guess each channel is 12 bits. I think the first 2 of the 14 bytes may not be channel data, again from PXX, a byte of flags (08) and a byte of receiver number (01). I believe there is a way of setting the receiver failsafe from the Tx module, may need a flag for this.
PXX says the 12 bit data is from 1200 (800uS) to 3300 (2200uS). Looks to me like there may be 4 bytes of least sig data for channels 1-4, followed by 4 nibbles packed into 2 bytes for most sig. data for these channels, then the same for channels 5-8.

Mike.
ersky9x/er9x developer
The difficult we do immediately,
The impossible takes a little longer!

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky RF protocol hacking

Post by Kilrah » Wed Apr 11, 2012 2:21 pm

Having some flags would make sense. The 2nd byte actually never changed in my tests. However I did get the first byte to change depending on what channel values I was feeding to the TX module. Got some 08, 00, 02, 04.

The PXX format limits might be "arbitrary", as according to my tests here in PPM mode the FrSky stuff will happily transmit anything between (at least) 100us to 2550us over RF.

One thing that is strange is that if you check the uplink frame:
11 85 2D 66 08 01 BC CB CB CB 88 88 CB CB CB CB 88 88 5D B0

There are 7 0xCBs in there. I never managed to get those to change, whether all channel neutrals, CH1-4 at +100% and 5-8 at neutral, or CH1-4 at +100%, CH5-8 at -100%. Same for the 3 rightmost 0x88s, never moved. That's the strange bit. If there are 10 bytes that serve no purpose, it would start to seem tight to transfer all the info... which is why I suggested some encoding. One possiblity would be if they encoded say the first channel, then only differences between CH2 and CH1, then between CH3 and CH2, or something like this. Would make sense to see repetitions in this case, as I had blocks of at least 4 consecutive channels having same value => difference = 0. This combined by the LSB "alone" (the 0xCBs) and some bytes holding high order nibbles (would be the 0x88s in this case). Bytes 4-7 would then be LSB's for CH1-4, 8-9 the high nibbles, then same for CH5-8.
Those are the only cases I checked so far. To find out more I guess one would have to set all channels neutral, then take 4-5 different readings for each channel, one at a time.

User avatar
MikeB
9x Developer
Posts: 15651
Joined: Tue Dec 27, 2011 1:24 pm
Country: -
Location: Poole, Dorset, UK

Re: FrSky RF protocol hacking

Post by MikeB » Wed Apr 11, 2012 2:46 pm

0x8CB is 2251 decimal. Divide by 1.5 and you get almost exactly 1500 (uS), so I reckon somewhere you do have the PXX encoding values (1.5 * pulse width in uS).

Mike.
ersky9x/er9x developer
The difficult we do immediately,
The impossible takes a little longer!

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky RF protocol hacking

Post by Kilrah » Wed Apr 11, 2012 3:44 pm

Yeah, but as I mentioned those 0x8CB come for channels that are at neutral, but also for some that are -100% and +100%, hence my difference suggestion...

I guess the best thing would be to take one of my devboards, and code a quick and dirty SPI sniffer/parser that displays those 12 bytes on an LCD in realtime. Then by looking at it while moving the sticks it will quickly be obvious what does what. Much easier than taking dozens of snapshots of test cases.


schlie
Posts: 49
Joined: Mon Mar 19, 2012 8:55 pm
Country: -

Re: FrSky RF protocol hacking

Post by schlie » Wed Apr 11, 2012 5:35 pm

Kilrah wrote:Yeah, but as I mentioned those 0x8CB come for channels that are at neutral, but also for some that are -100% and +100%, hence my difference suggestion...
As Mike suspects, as do I, as 0x8CB seems a likely value for a "neutral" channel value; thereby possibly:

Code: Select all

| Chan ID |Cntr| 1L | 2L |1H 2H| 3L | 4L | 5L | 6L |3H 4H|5H 6H| 7L | 8L | 9L | AL |7H 8H|9H AH| CheckSum  |
| 11 | 85 | 2D | 66 | 08 | 0 1 | BC | CB | CB | CB | 8 8 | 8 8 | CB | CB | CB | CB | 8 8 | 8 8 | 5 D | B 0 |
implying they could transmit as many as 10 12bit channel values (or equivalent data) in 7ms intervals:

channel 1 = 0x066 = 102 * 0.66_us = 68us
channel 2 = 0x108 = 264 * 0.66_us = 176us
channel 3 = 0x8BC = 2236 * 0.66_us = 1489us (near center channel)
channel 4 - channel 10 = 0x8CB = 2251 * 0.66_us = ~1500us (center channel)

(However as noted by Kilrah, this intrepretation doesn't explain the lower than expected channel values; being off by what would expected a near the minim pulse width value for a channel? Possibly values are multiplexed between odd/even frames?)

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky RF protocol hacking

Post by Kilrah » Wed Apr 11, 2012 9:58 pm

What you label as 1L (4th byte) is for sure a frame counter. I'm also quite sure about the first byte (0x11) being a fixed header, and the next 2 being the TX's ID. Your 3L sure has to do with CH1 (It's the only one I can trace so far, leave it to me :mrgreen: )
I'd go with Mike for at least 1 byte for flags, most likely the 6th, mybe the 5th too.
So I doubt one could have 10 channels in there. Also, FrSky has always been an 8-channel system so far.

As both the TX and RX are easily reflashable, this is of little importance, for the upcoming PXX/16CH firmware FrSky could completely redesign the protocol if they saw fit. Don't take the current implementation as being set in stone or expect it to have reserve for improvement... I wouldn't be surprised if the frame structure completely changed with the next FW.

We used to have non-upgradeable devices, where protocols had to be ready at day one for all the potential improvements one would want to be able to do in the future, but now it's easy to tell the user "if you want this new feature, you have to upgrade the firmware", so even an upgrade from 8CH to 10CH could be done by a complete rewrite if necessary, no need to plan for that too much in advance...

Ideally I'd see an alternative firmware... by the looks of it it wouldn't be a very hard task. Keep a few things, but with more flexibility. No dependence on them releasing their upgrades, and... no need to understand their silly frame format :mrgreen:

schlie
Posts: 49
Joined: Mon Mar 19, 2012 8:55 pm
Country: -

Re: FrSky RF protocol hacking

Post by schlie » Wed Apr 11, 2012 11:02 pm

Kilrah wrote:What you label as 1L (4th byte) is for sure a frame counter. I'm also quite sure about the first byte (0x11) being a fixed header, ...
Yes, please disregard, as I mislabeled the first byte, and thereby at least the immediately following labels were wrong. However there does appear to be 12 bytes forming two groups of 4 channels of 12bits each; but am at a loss if multiple channel values were encoded in the frame data captured, as only 1 byte of the data within that group appears to be affected. So will look forward to learning more as you continue your analysis. But for posterity, I've updated it below:

|Flag| Chan ID |Cnt| ?? | ?? | 1L | 2L | 3L | 4L |1H 2H|3H 4H| 5L | 6L | 7L | 8L |5H 6H|7H 8H| CheckSum |
| 11 | 85 | 2D | 66 | 08 | 01 | BC | CB | CB | CB | 8 8 | 8 8 | CB | CB | CB | CB | 8 8 | 8 8 | 5 D | B 0 |

Implying they transmit (something ??) along with as many as 8 12bit channels (or equivalent data) in 7ms intervals:

channel 1 = 0x8BC = 2236 * 0.66_us = 1489us (? near center channel)
channel 2 - channel 8 = 0x8CB = 2251 * 0.66_us = ~1500us (? center channel)

shaddi
Posts: 8
Joined: Thu Jan 05, 2012 9:57 am
Country: -
Location: Munich, Germany

Re: FrSky RF protocol hacking

Post by shaddi » Thu Apr 12, 2012 9:33 pm

Kilrah wrote:Ideally I'd see an alternative firmware... by the looks of it it wouldn't be a very hard task. Keep a few things, but with more flexibility. No dependence on them releasing their upgrades, and... no need to understand their silly frame format :mrgreen:
+1 for that!! I have to stop dreaming about the endless possibilities :D

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky Hardware / Software / RF protocol hacking

Post by Kilrah » Sun Apr 15, 2012 2:11 pm

OK, with some help from Jhsa I found the datasheets from the other active components (attached at end of post):
RF switches (2x): RDAES02
RF PA/LNA: RDAT212

I have then looked into the firmware upgrade procedure / Bootloader. I was hoping to find the standard STM32 bootloader, but it's unfortunately not the case.
They seem to have their own bootloader, when the receiver is in upgrade mode it will send its ID regularly (the one you see in the FrSky flasher once you've selected a file plus a few bytes).
Once the flasher has read that it sends 8 0x03's to initiate programming, to which the receiver responds 0x06 when it's ready. The flasher then sends a 0x02, and sends the firmware file in blocks of 0x400 bytes plus 2 stop bytes, and goes on with a 0x02 and the next block once the receiver has sent a 0x06 to indicate it's ready again.
The serial port is configured as 115200,8N1, INVERTED. The firmware file (.frk) is transmitted as is, so it seems to be a binary file, most likely written to flash as is as well.

It unfortunately seems that there is no "real" bootloader, but the upgrade function is part of the firmware. I.e. if transfer fails or a corrupt file is sent, the receiver is dead.
Attachments
frsky D8RII upgrade to cppm firmware logic capture.zip
(262.49 KiB) Downloaded 275 times
fdd_rx_rev2_cppm_build110314.zip
(32.19 KiB) Downloaded 209 times
frsky D8RII upgrade to cppm firmware request view.zip
(102.39 KiB) Downloaded 225 times
RDAT212.pdf
(856.75 KiB) Downloaded 292 times
RDAES02.pdf
(28.89 KiB) Downloaded 371 times

User avatar
Rob Thomson
Site Admin
Posts: 4535
Joined: Tue Dec 27, 2011 11:34 am
Country: United Kingdom
Location: Albury, Guildford
Contact:

FrSky Hardware / Software / RF protocol hacking

Post by Rob Thomson » Sun Apr 15, 2012 4:48 pm

On the note of the incorrect file being sent... I have happily loaded a receiver firmware to a transmitter module - and then reverted after the bad load.

Not ever done an rx... Maybe that is different?


Sent from my iPhone using Tapatalk
Slope Soaring, FPV, and pretty much anything 'high tech'
...........if you think it should be in the wiki.. ask me for wiki access, then go add it!

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky Hardware / Software / RF protocol hacking

Post by Kilrah » Sun Apr 15, 2012 5:06 pm

I guess the hardware is so similar that the code will run on both and still allow you to reflash (same UART used, etc)...

After all, apart from the few different I/Os, the RX could be used as TX and vice versa...

User avatar
Rob Thomson
Site Admin
Posts: 4535
Joined: Tue Dec 27, 2011 11:34 am
Country: United Kingdom
Location: Albury, Guildford
Contact:

FrSky Hardware / Software / RF protocol hacking

Post by Rob Thomson » Sun Apr 15, 2012 5:10 pm

True! Probably exactly the case!


Sent from my iPhone using Tapatalk
Slope Soaring, FPV, and pretty much anything 'high tech'
...........if you think it should be in the wiki.. ask me for wiki access, then go add it!

bertrand35
9x Developer
Posts: 2764
Joined: Fri Dec 30, 2011 11:11 pm
Country: -

Re: FrSky Hardware / Software / RF protocol hacking

Post by bertrand35 » Tue Jun 12, 2012 12:52 pm

So ...

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky Hardware / Software / RF protocol hacking

Post by Kilrah » Tue Jun 12, 2012 2:29 pm

So...!
Kilrah wrote:It unfortunately seems that there is no "real" bootloader, but the upgrade function is part of the firmware. I.e. if transfer fails or a corrupt file is sent, the receiver is dead.
This wasn't "innocent" of course... I found it out simply because I tried creating a simple "blinking led" program for an STM32 just to see, built a .bin, renamed the .bin to .frk, and flashed it with the frsky flasher program. It got accepted and flashed, but then all I had was a dead receiver, and not even a blinking LED. No way to reconnect to the flasher program, so no more doubt, FrSky doesn't use a proper bootloader but the flashing function is part of the firmware, so without a running fw -> no more flashing.
On a closer look, it seems that frsky actually encrypt their firmware images. What's pretty revealing is that firstly a receiver .frk file is exactly 32768 bytes, and then that it doesn't have any padding, patterns, repeats or anything typical of a real binary file. So their fw files are encrypted, the frsky flasher sends them down to the device unaltered (confirmed by the logic captures I posted in the OP), and the device firmware actually takes care of decrypting and flashing the code. No wonder my blinking LED program wouldn't work, as it was treated as an encrypted file and "decrypted".
That's where I stopped in April as I left for 2 weeks abroad and then didn't really have enough hope to get back to it once I was back.

However Bertrand pointed out last week that STMs might be like the SAMs used on the ersky board, and have a permanent factory-installed bootloader. Luckily it is indeed the case, so I downloaded the official ST flasher app and had a try. The bootloader is called by holding the dedicated BOOT0 pin high and the BOOT1 pin (shared with PB2, which is servo output CH3 on a D8R*) low during RESET. BOOT1 is OK as it's pulled low by the existing circuitry, however BOOT0 is unconnected and requires soldering to the processor pin.
Next I tried communicating with the bootloader using the FUC-2 cable I have, and the receiver's side RS232 pins. No luck, but I then remembered that frsky are using inverted RS232 in their wiring (talk about making things easy...). So instead of losing time messing around and making an inverter I simply soldered 2 wires directly on the processor side and used a standard 3.3V usb->serial adapter I had around.
DSC09447_ss.jpg
And here's a happy connected bootloader :D
Processor was read-protected, so no way of getting the unencrypted image back. The flasher program has a big "erase device" you have to press before you can go any further.

So there you go, I went searching for a decent IDE for STM32 and stopped on Atollic TrueStudio, I has the advantage of having profiles and templates for that exact processor, so when you create a new project you've got all the basic structure, standard libraries and hardware drivers included.

I started with a really quick and dirty couple of lines to see if I could actually get anything to run on this thing, and the answer is yes :D
Pretty useless, but shows it works - GPIO and UART are initialised, pressing the button toggles the LEDs, and puts out which one is on at 4800baud on the UART.

http://www.youtube.com/watch?v=6vOrdgCkUdk

So there we are, I'm now into understanding how to use the supplied libraries how they're meant to be - really seems every manufacturer must have his own coding philosophy!

Basically I'm able to program that thing, I have most of the circuit worked out, and I know how to initialise and use the RF chip from the initialisation sequence I've sniffed earlier. Seeing the excellent performance we get out of that frsky gear there's no reason to look further, we can just reuse that setup as is. Once this initialization is done, the rest is very straightforward.
The last little thing I have to work out from the hardware is how antenna switching is done. Just beep the connections to see where they go and run the logic analyzer once to see the timing.
Once this and the low level software stuff is worked out, we should pretty quickly be able to get to the fun stuff, no "middle" layer to break through!

One nice thing to note, hardware in the TX and RX modules is pretty much identical, and the upcoming radio will most likely be very similar. Those STM32s they use are very powerful (equivalent to the ARM used on the ersky board), apart from the number of I/Os a current receiver could well run an entire radio with ease, so I doubt they'll get overly creative. The DHT-U must be the closest, same STM32 with an LCD and a couple of buttons. They'll just add more inputs.

For reflashing I plan to give a way to invoke the permanent bootloader from the firmware, so it would be easy to reflash. The problem is only the first user flashing process, because this involves setting that BOOT0 pin high, and it's quite tight to solder in there, more than the telemetry mod. But who knows... if FrSky are nice we could maybe send them a small loader app they could encrypt with their frk format, so that the first flashing could be done using the frsky loader?

bertrand35
9x Developer
Posts: 2764
Joined: Fri Dec 30, 2011 11:11 pm
Country: -

Re: FrSky Hardware / Software / RF protocol hacking

Post by bertrand35 » Tue Jun 12, 2012 2:52 pm

Excellent idea! It would be the invert of a trojan ...
After all it seems to me that is not a problem to solder something there for the first "flashing" after going to the open source side, and then remove the wire.
Bertrand.

Cesco1
Posts: 1
Joined: Thu Aug 16, 2012 4:51 pm
Country: -

Re: FrSky Hardware / Software / RF protocol hacking

Post by Cesco1 » Thu Aug 16, 2012 5:01 pm

Hi,

My old DJT module, an early build with a piggyback rf board, has serious telemetry range issues. Measuring the stuff i did notice the PA on the RDAT212 is never turned off (SWPA + SWTX always high). Only LNA is turned on during telemetry slot, off during transmit. Could someone confirm this is wrong and the reason for telemetry range issues?

btw i can read bind-data and channel data with an arduino connected to the rf board. I can post the source if there is some intrest.

Edit:
Problem solved. It was a solder bridge on the piggyback SWPA connector.

davx
Posts: 210
Joined: Sun Sep 15, 2013 7:01 am
Country: -

Re: FrSky Hardware / Software / RF protocol hacking

Post by davx » Thu Sep 26, 2013 9:01 am

Hi Cesco1,

I've got the same module and I've range problems.
I'm not as advanced as you are (by far) in electronic and it would be nice if you could develop how you solved this issue.

Thanks.

User avatar
midelic
Posts: 77
Joined: Mon Dec 23, 2013 9:57 pm
Country: -

Re: FrSky Hardware / Software / RF protocol hacking

Post by midelic » Sat Mar 01, 2014 7:11 pm

@Kilrah,
By chance do you have the logic sample data for a Frsky Rx at binding........?

User avatar
Kilrah
Posts: 9560
Joined: Sat Feb 18, 2012 6:56 pm
Country: Switzerland

Re: FrSky Hardware / Software / RF protocol hacking

Post by Kilrah » Sun Mar 02, 2014 12:55 pm

I'm afraid not.

Post Reply

Return to “The FRSKY Forum”