FrSky D16 protocol (X series TX/RX compatible) - RC Groups
Thread Tools
Sep 17, 2015, 08:24 PM
jry
jry
Registered User
Discussion

FrSky D16 protocol (X series TX/RX compatible)


I didn't find any information about FrSky D16 protocol. Inspired by two essential reverse engineering efforts http://openrcforums.com/forum/viewtopic.php?f=52&t=667 and https://www.rcgroups.com/forums/show....php?t=1667453 I would like to shed some light on D16 protocol.

Edit: basic protocol description follows in this post, for detailed information you need to read this thread. Thanks to Midelic!

CC2500 initialization
Code:
[00] (0x30) RESET
[01] (0x02 0x06) GDO0_INV = 0 / GDO0_CFG = 6
[03] (0x00 0x06) GDO2_INV = 0 / GDO2_CFG = 6
[05] (0x17 0x0C) CCA_MODE = 0 (Always) / RXOFF_MODE = 3 / TXOFF_MODE = 0
[07] (0x18 0x18) FS_AUTOCAL = 0x01 / PO_TIMEOUT = 2 (Expire count 64 Approx. 149  155 s)
[09] (0x06 0x1E) PKTLEN=0x1E
[11] (0x07 0x04) PQT = 0  / CRC_AUTOFLUSH = 0 / APPEND_STATUS = 1 / ADR_CHK = 0 (No address check)
[13] (0x08 0x01) WHITE_DATA = 0 / PKT_FORMAT = 0 / CC2400_EN = 0 / CRC_EN = 0 / LENGTH_CONFIG = 1
[15] (0x3E 0xFF) PATABLE(0) = 0xFF (+1dBm)
[17] (0x0B 0x0A) FREQ_IF = 0x0A (IF = 253.906kHz)
[19] (0x0C 0x00) FREQOFF = 0
[21] (0x0D 0x5C)
[23] (0x0E 0x76)
[25] (0x0F 0x27) FREQ = 0x5C7627 (F = 2404MHz)
[27] (0x10 0x7B) CHANBW_E = 1 / CHANBW_M = 3 / BW = 232.143kHz / DRATE_E = 0x0B
[29] (0x11 0x61) DRATE_M = 0x61 Bitrate = 70023 bps
[31] (0x12 0x13) MOD_FORMAT = 1 (GFSK) / SYNC_MODE = 3 (30/32 sync word bits detected)
[33] (0x13 0x23) FEC_EN = Disable / NUM_PREAMBLE = 2 (4 bytes) / CHANSPC_E = 3
[35] (0x14 0x7A) CHANSPC_M = 0x7A Channel Spacing = 299927Hz
[37] (0x15 0x51) DEVIATION_E = 5 / DEVIATION_M = 1 / Deviation = 57129Hz
[39] (0x1B 0x43) MAX_DVGA_GAIN = 1 / MAX_LNA_GAIN = 0 / MAGN_TARGET = 3
[41] (0x19 0x16) FOC_BS_CS_GATE = 0 / FOC_PRE_K = 2 / FOC_POST_K = 1 / FOC_LIMIT = 2
[43] (0x1A 0x6C) BS_PRE_KI = 1 (2KI) / BS_PRE_KP = 2 (3KP) / BS_POST_KI = 1 (KI /2) / BS_POST_KP = 1 (Kp) / BS_LIMIT = 0 
[45] (0x1C 0x40) AGCCTRL1 = 0x40
[47] (0x1D 0x91) AGCCTRL0 = 0x91
[49] (0x21 0x56) FREND1
[51] (0x22 0x10) FREND0: LODIV_BUF_CURRENT = 1
[53] (0x23 0xA9) FSCAL3 = 0xA9
[55] (0x24 0x0A) FSCAL2 = 0x0A
[57] (0x25 0x00) FSCAL1 = 0x00
[59] (0x26 0x11) FSCAL0 = 0x11
[61] (0x29 0x59) FSTEST = 0x59  (Same as specified in datasheet)
[63] (0x2C 0x88) TEST2 = 0x88 (Same as specified in datasheet and by SmartRF sw)
[65] (0x2D 0x31) TEST1 = 0x31 (Same as specified in datasheet and by SmartRF sw)
[67] (0x2E 0x0B) TEST0 = 0x0B (Same as specified in datasheet and by SmartRF sw)
[69] (0x03 0x07) FIFOTHR = 0x07
[71] (0x09 0x00) ADDR = 0
[73] (0x36) SIDLE
[74] (0x36) SIDLE
[75] (0x0A 0x00) Channel = 0x00
[77] (0x33) SCAL
Bind TX > RX packets
Code:
[00] PKLEN  1D 1D 1D 1D 1D 1D 1D 1D 1D 1D
[01] CONST  03 03 03 03 03 03 03 03 03 03
[02] CONST  01 01 01 01 01 01 01 01 01 01
[03] TXID1  B3 B3 B3 B3 B3 B3 B3 B3 B3 B3
[04] TXID2  FD FD FD FD FD FD FD FD FD FD
[05] PKIDX  00 05 0A 0F 14 19 1E 23 28 2D
[06] HOPS1  02 70 DE 61 CF 52 C0 43 B1 34
[07] HOPS2  D4 57 C5 48 B6 39 A7 2A 98 1B
[08] HOPS3  BB 3E AC 2F 9D 20 8E 11 7F 00
[09] HOPS4  A2 25 93 16 84 07 75 E3 66 1D
[10] HOPS5  89 0C 7A E8 6B D9 5C CA 4D 03
[11] CONST  02 02 02 02 02 02 02 02 02 02
[12] RXNUM  15 15 15 15 15 15 15 15 15 15
[13] CONST  00 00 00 00 00 00 00 00 00 00
[14] CONST  00 00 00 00 00 00 00 00 00 00
[15] CONST  00 00 00 00 00 00 00 00 00 00
[16] CONST  00 00 00 00 00 00 00 00 00 00
[17] CONST  00 00 00 00 00 00 00 00 00 00
[18] CONST  00 00 00 00 00 00 00 00 00 00
[19] CONST  00 00 00 00 00 00 00 00 00 00
[20] CONST  00 00 00 00 00 00 00 00 00 00
[21] CONST  00 00 00 00 00 00 00 00 00 00
[22] CONST  00 00 00 00 00 00 00 00 00 00
[23] CONST  00 00 00 00 00 00 00 00 00 00
[24] CONST  00 00 00 00 00 00 00 00 00 00
[25] CONST  00 00 00 00 00 00 00 00 00 00
[26] CONST  00 00 00 00 00 00 00 00 00 00
[27] CONST  00 00 00 00 00 00 00 00 00 00
[28] CHKS1  57 C1 64 C2 CD 14 C3 04 CE 6E
[29] CHKS2  5C 34 74 93 D1 7A A5 C1 02 4E

[30] RSSI   2B 2C 2C 2C 2B 2A 2B 2B 2B 2B
[31] C/LQI  B2 B2 B1 B1 B1 B1 B1 B0 B1 B2

Notes:
Packet sent by TX every 9ms.
Ten packets needed to transfer whole HOPS table.
Only first 47 values from HOPS tables are used.
RXNUM is set on TX side - model/receiver match.
Checksum is calculated for bytes from [03] to [27].
RSSI and CRC_OK/LQI status bytes are appended on RX side.
Standard TX > RX packets
Code:
[00] PKLEN  1D 1D 1D 1D 1D 1D 1D 1D 1D 1D
[01] TXID1  DD DD DD DD DD DD DD DD DD DD
[02] TXID2  6D 6D 6D 6D 6D 6D 6D 6D 6D 6D
[03] CONST  02 02 02 02 02 02 02 02 02 02
[04] PKCTR  DE DA D6 D2 CE CA C6 C2 ED E9
[05] RSCTR  0A 0A 0A 0A 0A 0A 0A 0A 0A 0A
[06] RXNUM  16 16 16 16 16 16 16 16 16 16
[07] FLAGS  00 00 00 00 00 00 00 00 00 00
[08] CONST  00 00 00 00 00 00 00 00 00 00
[09] CHNLS  00 00 00 00 00 00 00 00 00 00
[10] CHNLS  04 0C 04 0C 04 0C 04 0C 04 0C
[11] CHNLS  40 C0 40 C0 40 C0 40 C0 40 C0
[12] CHNLS  00 00 00 00 00 00 00 00 00 00
[13] CHNLS  04 0C 04 0C 04 0C 04 0C 04 0C
[14] CHNLS  40 C0 40 C0 40 C0 40 C0 40 C0
[15] CHNLS  00 00 00 00 00 00 00 00 00 00
[16] CHNLS  04 0C 04 0C 04 0C 04 0C 04 0C
[17] CHNLS  40 C0 40 C0 40 C0 40 C0 40 C0
[18] CHNLS  00 00 00 00 00 00 00 00 00 00
[19] CHNLS  04 0C 04 0C 04 0C 04 0C 04 0C
[20] CHNLS  40 C0 40 C0 40 C0 40 C0 40 C0
[21] ?????  08 08 08 08 08 08 08 08 08 08
[22] CONST  00 00 00 00 00 00 00 00 00 00
[23] CONST  00 00 00 00 00 00 00 00 00 00
[24] CONST  00 00 00 00 00 00 00 00 00 00
[25] CONST  00 00 00 00 00 00 00 00 00 00
[26] CONST  00 00 00 00 00 00 00 00 00 00
[27] CONST  00 00 00 00 00 00 00 00 00 00
[28] CHKS1  AB 47 52 BE 48 A4 B1 5D 49 A5
[29] CHKS2  DB 93 70 38 9F D7 34 7C 66 2E

[30] RSSI   34 41 3F 3B 25 3E 3E 2A 3A 3E
[31] C/LQI  B0 B0 B2 B0 B2 B0 B0 B1 B0 B2

Notes:
Packet sent by TX every 9ms.
Two packets needed to transfer 16 channels.
RSCTR increase every 4 on/off cycles of TX.
FLAGS 00 - standard packet
      10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
      20 - range check packet
[21] ????? is related to RX > TX telemetry[05]
Checksum is calculated for bytes from [03] to [27].
RSSI and CRC_OK/LQI status bytes are appended on RX side.
Telemetry RX > TX packets
Code:
[00] PKLEN  0E 0E 0E 0E 0E 0E 0E 0E 0E 0E
[01] TXID1  DD DD DD DD DD DD DD DD DD DD
[02] TXID2  6D 6D 6D 6D 6D 6D 6D 6D 6D 6D
[03] CONST  02 02 02 02 02 02 02 02 02 02
[04] RS/RB  2C D0 2C CE 2C CE 2C CD 2C CC
[05] ?????  03 10 21 32 03 10 21 32 03 10
[06] STRM1  00 00 06 03 00 00 00 00 00 00
[07] STRM2  00 00 7E 00 00 00 00 00 00 00
[08] STRM3  00 00 1A 00 00 00 00 00 00 00
[09] STRM4  00 00 10 00 00 00 00 00 00 00
[10] STRM5  03 03 03 03 03 03 03 03 03 03
[11] STRM6  F1 F1 F1 F1 F1 F1 F1 F1 F1 F1
[12] STRM7  D1 D1 D0 D0 D0 D0 D0 D0 D0 D0
[13] CHKS1  0A FE 1F 73 1B 51 3B 6B 1B 63
[14] CHKS2  54 83 08 42 DD 72 46 A9 DD F9

Notes:
Packet sent by RX every 9ms.
RS/RB means RSSI or RxBt value for odd or even packet.
[05] ????? is related to standard TX > RX frame[21]
STRM1-7 is continuous FrSky S.Port telemetry stream.
Checksum is calculated for bytes from [03] to [12].
Setup:
Taranis X9D Plus with internal FrSky XJT TX.
FrSky X4R-SB RX.
Both RX and TX flashed with latest non-EU firmware.
Capturing X4R-SB SPI communication with CC2500.
Capturing from power up.

x4rsb_thr_down.zip:
TX running and already bound to RX.
RX powered on.
Throttle set down.

x4rsb_thr_up.zip:
Same as x4rsb_thr_down.zip, but throttle up.

x4rsb_bind_notx.zip:
TX off.
RX powered with F/S button pressed.

x4rsb_bind_ch1_8_rcvno08_fshold.zip:
TX running in binding mode: Channel Range CH1-8, Receiver No. 08, Failsafe mode: Hold.
RX powered with F/S button pressed.

xjt_x4rsb.zip with both X4R-SB and XJT captured. See REDME.TXT for details.

x4rsb_xjt_ch0_txonoff.zip:
Logic analyzer on RX
RX running (already bound to TX)
TX turned on/off several times (waiting for green led on RX each time)

xjt_x4rsb_-100.zip
Logic analyzer on TX
RX (binded) alreading running & waiting for TX
TX powered on
One channel (0, 1, 7, 8, 14, or 15) set to -100%
Other 15 channels set to 0%
Last edited by jry; Oct 08, 2015 at 03:58 AM.
Sign up now
to remove ads between posts
Sep 18, 2015, 05:59 AM
Registered User
Is basically HDLC.
Why reverse engineering when you can check the OpenTx code ?
Sep 18, 2015, 06:04 AM
Registered User
midelic's Avatar
Excellent.
I'm not at home and want to have a look.
Can you convert the spi dump to text file?
I can start coding for this one RX immediately.
Sep 18, 2015, 06:14 AM
jry
jry
Registered User
Updated first post with SPI CSV export. If you will need another export with some specific TX configuration, just let me know.
Sep 18, 2015, 06:22 AM
Registered User
midelic's Avatar
This data is only at bind or for both bind and data?
Sep 18, 2015, 06:24 AM
I don't want to "Switch Now"
pmackenzie's Avatar
Quote:
Originally Posted by renatoa
Is basically HDLC.
Why reverse engineering when you can check the OpenTx code ?
OPentx has nothing to do with the RF modules protocol.
Sep 18, 2015, 06:25 AM
jry
jry
Registered User
Both - bind and data.
Sep 18, 2015, 06:25 AM
Registered User
midelic's Avatar
OK sorry. I see.
Oh it is like Christmas,Nice gift.
Thanks!.
Sep 18, 2015, 06:33 AM
jry
jry
Registered User
Please let us know what you have found.

I will try to capture also XJT part.
Sep 18, 2015, 07:14 AM
Registered User
Quote:
Originally Posted by pmackenzie
OPentx has nothing to do with the RF modules protocol.
I thought he means PXX... not over the air stuff.
Sep 18, 2015, 02:26 PM
Registered User
midelic's Avatar
@jry
I had a look inside.
There is no bind data.Only normal data.
Can you have a spi comm dump at binding time ?
Sep 18, 2015, 05:56 PM
jry
jry
Registered User
First post is updated with captured bind procedure.

D16 protocol has several bind options on TX side: channel range, receiver no (model match), failsafe mode. I did some tests and for example Receiver No. is on row 0.683409625,14331,0x00,0x08 in x4rsb_bind_ch1_8_rcvno08_fshold.spi.csv. It would be possible to find out other options there too.
Sep 18, 2015, 06:29 PM
Registered User
midelic's Avatar
Thanks !
It is very similar with D8 Frsky protocol.

30 bytes uplink frame
15 bytes downlink telemetry frame
9 ms between RX frames
alternate 1 RX frame 1 telemetry frame. all in 9ms .

1 byte is frame length 0x1D(29)
2 bytes 0xDD,0x6D (txid0,txid1)
27 bytes of data ...Unknown yet.
Last edited by midelic; Sep 20, 2015 at 02:43 PM.
Sep 19, 2015, 12:41 PM
Registered User
midelic's Avatar
I have some news.
some details about protocol.
Code:
Bind Frame

LEN|	Fixed|	Fixed|	txid1|	txid2|	IDX(/5)|	HOP liST 50 ch|2|RX_Num|				
1D	3	1	DD	6D	0	0	64	c8	41	A5	2	8
1D	3	1	DD	6D	5	1E	82	E6	5f	c3	2	8
1D	3	1	DD	6d	0A	3C	A0	19	7D	e1	2	8
1D	3	1	DD	6D	0F	5B	BE	37	9B	14	2	8
1D	3	1	DD	6D	14	78	DD	55	B9	32	2	8
1D	3	1	DD	6D	19	96	0F	73	D7	50	2	8
1D	3	1	DD	6D	1E	B4	2D	91	0A	6E	2	8
1D	3	1	DD	6D	23	D2	4B	AF	28	8C	2	8
1D	3	1	DD	6D	28	5	69	CD	46	AA	2	8
1D	3	1	DD	6D	2D	23	87	0	1D	3	2	8

Hopping sequence
   
64	7D	96	AF	C8
				
E1	0F	28	41	5B
				
73	8C	A5	BE	D7
				
5	1E	37	50	69
				
82	9B	B4	CD	E6
				
14	2D	46	5F	78
				
91	AA	C3	DD	0A
				
23	3C	55	6E	87
				
A0	89	D2	0	19
				
32	4B			


47 Channels list similar with D8
Hopping sequence/algorithm /code     
channr+=12;
if (channr>=listLength) channr -= listLength;

edit:It is not the same all the time or for all TX It follows a different hopping pattern.algorithm.

Aditionally 
1.Calibration of all channels at start(Precalibration).
2.Loading FSCAL registers with precalibration data  before each channel hop. allowing code working faster.



Sample 
Data Frame every   9ms   
30bytes                                                                                                                  
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29   30 31
LEN |TX0|TX1| 0x02
1D DD 6D  2  2 3 2 1 0 40 0 4 80 FA 3 10 0 1 10 38 0 0 0 0 0 0 B6 7C       51  B2

Telemetry frame every 9 ms
15bytes
0      1    2    3    4    5    6    7    8    9    10    11    12   13   14
LEN | TX0 |TX1 |0x02| 
0x0E 0xDD 0x6D 0x02   0x24 0x21 0x00 0x00 0x00 0x00 0x00 0x00  0x00  0x28 0x04
I need to identify some bytes more.I don't have tools with me.
I believe some bytes on bind frame is related with some options from Taranis at bind maybe Failsafe.
Also to identify the rest of the bytes on data frame.

@jry
Can you have a file with Throtle high?
I want to see which bytes changing. and do some calculations.
Last edited by midelic; Sep 24, 2015 at 03:38 PM.
Sep 19, 2015, 01:26 PM
Registered User
midelic's Avatar
Full bind frame
Code:
LENGTH|Fixed|Fixed|txid1|txid2|IDX(/5)|5 channels| 2 |RX_NUM|15 zero bytes|CheckSum(2bytes??|RSSI/LQi/CRC 2bytes|	
1D	3	1	DD	6D	0	0	64	c8	41	A5	2	8   000000000000000     c4 8D                   1D B2
1D	3	1	DD	6D	5	1E	82	E6	5f	c3	2	8   000000000000000     AE 02                   1D B2
1D	3	1	DD	6d	0A	3C	A0	19	7D	e1	2	8   000000000000000     1F 62                   1E B2
1D	3	1	DD	6D	0F	5B	BE	37	9B	14	2	8   000000000000000     F4 89                   1D B2
1D	3	1	DD	6D	14	78	DD	55	B9	32	2	8   000000000000000     76 B1                   26 B1
1D	3	1	DD	6D	19	96	0F	73	D7	50	2	8   000000000000000     35 CD                   26 B2
1D	3	1	DD	6D	1E	B4	2D	91	0A	6E	2	8   000000000000000     01 A3                   26 B2
1D	3	1	DD	6D	23	D2	4B	AF	28	8C	2	8   000000000000000     B8 A7                   26 B2
1D	3	1	DD	6D	28	5	69	CD	46	AA	2	8   000000000000000     6F 2C                   1F B0
1D	3	1	DD	6D	2D	23	87	0	1D	3	2	8   000000000000000     E0 76                   1F B2
Last edited by midelic; Sep 23, 2015 at 05:28 PM.


Thread Tools