Thread Tools
Sep 17, 2015, 07:24 PM
jry
jry
Registered User
Thread OP
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 02:58 AM.
Sign up now
to remove ads between posts
Sep 18, 2015, 04:59 AM
Registered User
Is basically HDLC.
Why reverse engineering when you can check the OpenTx code ?
Sep 18, 2015, 05: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, 05:14 AM
jry
jry
Registered User
Thread OP
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, 05:22 AM
Registered User
midelic's Avatar
This data is only at bind or for both bind and data?
Sep 18, 2015, 05: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, 05:25 AM
jry
jry
Registered User
Thread OP
Both - bind and data.
Sep 18, 2015, 05:25 AM
Registered User
midelic's Avatar
OK sorry. I see.
Oh it is like Christmas,Nice gift.
Thanks!.
Sep 18, 2015, 05:33 AM
jry
jry
Registered User
Thread OP
Please let us know what you have found.

I will try to capture also XJT part.
Sep 18, 2015, 06: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, 01: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, 04:56 PM
jry
jry
Registered User
Thread OP
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, 05: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 01:43 PM.
Sep 19, 2015, 11:41 AM
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 02:38 PM.
Sep 19, 2015, 12: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 04:28 PM.


Quick Reply
Message:

Thread Tools