DIY-Multiprotocol-TX-Module icon indicating copy to clipboard operation
DIY-Multiprotocol-TX-Module copied to clipboard

Support for HotRC / Rlaarlo receivers

Open pascallanger opened this issue 9 months ago • 6 comments

Discussed in https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/discussions/1072

Originally posted by c0ldtech February 11, 2025 It would be nice to have support for the HotRC receivers (which are also being used by Rlaarlo it seems). I'd be more than willing to order a receiver and have it sent to someone if it helps.

pascallanger avatar Mar 04 '25 07:03 pascallanger

@c0ldtech I'll update my findings here

pascallanger avatar Mar 04 '25 07:03 pascallanger

I am willing to provide funds for the purchase of a test Tx-Rx. :) PayPal?

prikrylm avatar Mar 19 '25 06:03 prikrylm

I am willing to provide funds for the purchase of a test Tx-Rx. :) PayPal? Hi Guys I have a selection of HoRc Tx and Rx, I'm happy to test, wreck etc. I have pulled apart a DS-4A and stared a bit of reverse engineering. (I might need some guidance capturing signals off air with my SDR or JTAG dump of the firmware.) Cheers Rod

neutron-modulator avatar Mar 31 '25 00:03 neutron-modulator

Hi Pascal I just received this from AliExpress: ST-Link V2 https://a.aliexpress.com/_msNDlOB Is it going to work to capture the data you require.

Cheers Rod

neutron-modulator avatar May 16 '25 21:05 neutron-modulator

No it's not the right device.... You need a cheap ($10) Saleae 8 channels compatible analyzer for that purpose.

pascallanger avatar May 17 '25 02:05 pascallanger

Cool I'll get that sorted.

On Sat, 17 May 2025, 12:08 pm pascallanger, @.***> wrote:

pascallanger left a comment (pascallanger/DIY-Multiprotocol-TX-Module#1082) https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues/1082#issuecomment-2887964523

No it's not the right device.... You need a cheap ($10) Saleae 8 channels compatible analyzer for that purpose.

— Reply to this email directly, view it on GitHub https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues/1082#issuecomment-2887964523, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXYD47VQMJS43NICHGDEUL262KZDAVCNFSM6AAAAABYI3H7OOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQOBXHE3DINJSGM . You are receiving this because you commented.Message ID: @.*** com>

neutron-modulator avatar May 17 '25 21:05 neutron-modulator

Is there any progress on this?

baronKanon avatar Jul 29 '25 07:07 baronKanon

My first time in this forum. Any problems or help needed on this protocol?

aetrfan avatar Aug 25 '25 11:08 aetrfan

Hi all! I finally got some time to take apart my RC transmitter HotRC CT-8A. I soldered wires on the RF module and after some try and error I found the correct pinout. For the sake of completeness, looking at the RF module with the antenna plug on the top, pinout is: 1: CSn [D4 in PulseView dump] 2: CLK [D0 in PulseView dump] 3: MOSI [D2 in PulseView dump] 4: MISO [D4 in PulseView dump] 5: don't know 6: 3v3 7: likely IRQ 8: likely CE 9: don't know 10: GND https://github.com/motorello/hotrc_RF_SPI_dumps/blob/main/RF-SPI_pinout.png

The RF chip has no silkscreen on it, the PA/LNB frontend is a AT2401C.

My findings as of now are the following:

  • when switching on the transmitter, after all the RF initialiazion registers, the TX broacasts, using REG 0x07, on RF channel 0x21 the list of the RF channels that will be used for hopping: MOSI 07 01 21 MOSI 32 14 8A 74 A4 33 23 55 41 0F 73 19 2D 69 37 05 5F 4B 24 56 42 10 23 55 41 0F 73 19 2D 69 37 05 5F 4B are the channels used for frequency hopping and the TX always begins with the second one (0x55)

  • after the successful connection with the receiver: MOSI 07 01 55 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 41 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 0F MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 73 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 19 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 2D MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 69 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 05 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 5F MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 4B MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B MOSI 07 01 23 MOSI 32 0C 80 4C 64 22 96 B0 84 25 2C 61 09 4B

  • the packet containing RC channels information is written on register 0x32 and is 13 bytes long, no CRC I've found so far

  • the bytes are sent LSByte first

  • all the 8 channels have the same precision and are encoded on 11 bits (somehow similar to the SBUS protocol, as far as I know)

  • the first two bytes of the "RC channels packet" do not change over time and over receivers (I tested with two different, in my case the are always 0x0C 0x80): maybe they could carry information of RC channels 9 and 10 on 8 bit each...

  • starting from the third byte, the 8 RC channels are encoded (I've tried to represent the pattern, it is easier to swap the sequence to LSByte first, so that bits on every channel are contiguous): https://github.com/motorello/hotrc_RF_SPI_dumps/blob/main/RC-channels.png

  • trims are changing the middle values of the channels (they are not carried out on separate bytes)

  • in normal conditions (receiver connected), packets are transmitted every 5ms (200Hz)

  • the time spent to send 13 bytes seems to be around 1460us, which means 1460/13/8 = 14us/bit which means 1000000us/14us = around 71kbps (so likely the raw bitrate could be 250kbps)

  • all the SPI transactions are made with at least 3 bytes (likely one byte for register address and two for payload) -> I didn't manage to find RF chips that always use two bytes of payload, but my knowledge is very limited

  • it seems that the RF also uses some kind of strobes : A4, A5, A6, A7, B0, B2 are always used with two following FF FF

I didn't look at the binding workflow yet, but I've dumped it as well. I didn't analyze how the telemetry works yet.

I've created a temporary GitHub repo with some SPI dumps (https://github.com/motorello/hotrc_RF_SPI_dumps):

  • 'dump-BINDING_RX-in-binding_TX-off-on_bind_automatically_RX-F04A' -> binding workflow: transmitter OFF, receiver in binding, transmitter ON
  • 'dump-RX-off_TX-off-on_RX-on_RX-off_TX-on-off_RX-F04A' -> receiver OFF, transmitter OFF, transmitter ON, receiver ON, transmitter OFF
  • 'dump-CH1-M-L-M-H-M_CH2-M-L-M-H-M_RX-F04A' -> RC channel 1: from mid to low, to mid, to high, to mid; then RC channel 2, same pattern
  • 'dump-CH3-L-M-H-M-L_CH4-L-M-H-M-L_throw90' > RC channel 3: from mid to low, to mid, to high, to mid (100% throw); then RC channel 4, same pattern
  • 'dump-CH5-L-M-H-M-L_CH6-L-M-H-M-L_CH7-L-M-H-M-L_CH8-L-M-H-M-L_throw90' -> same as before but for CH5, CH6, CH7, CH8 (90% throw)
  • 'dump-CH5-L-M-H-M-L_CH6-L-M-H-M-L_CH7-L-M-H-M-L_CH8-L-M-H-M-L_throw100' -> same as before: CH5, CH6, CH7, CH8 (100% throw)

I have also wrote some one-liner to create csv files ready to be used in Excel/LibreCalc starting from the PulseView SPI decoder (right-click > export all annotations), maybe it can help someone:

spiDumpFile=MY_SPI_DECODED.txt

## packet as sent via SPI
sed -E '/ bits:/d; / data:/d; s/ SPI: (M[OI]+S[IO]+) transfers: /\t\1\t/g; s/-[0-9]+//g; s/ /\t/g' \
 $spiDumpFile | sort -n -k1,1 -k2,2r \
 > ${spiDumpFile/.txt/-ReadyForExcel.csv}

## MSB and LSB in one file
awk '{ printf "\nMSB\t%s", $0 }; { printf "\nLSB\t%s\t%s\t%s", $1, $2, $3 }; { for (i = NF; i > 3; i--)  printf "\t%s", $i } ' \
 ${spiDumpFile/.txt/-ReadyForExcel.csv} \
 | sed '/^$/d' \
 > ${spiDumpFile/.txt/-ReadyForExcel-MSB+LSB.csv}

I'd love to write some code to support this new protocol (today I also bought a CT-10B transmitter as I'm curious to see where the channels 9 and 10 are encoded...), but I need some initial guidance or suggestions on which RF chip could be used for HotRC (A7105? CC2500?).

Feel free to ask for additional SPI dumps, the transmitter is here open and wires hooked up to Sigrok.

Cheers! Francesco

motorello avatar Nov 11 '25 16:11 motorello

Ok, it turned out that the RF transceiver is a LT8910, which is why the data payload is always 2 bytes. I'm pasting below the full initialization sequence for completeness. The configuration per se is not that bad, no scramble, no whitening, no FEC, easy hopping sequence. BUT: the data rate is 125Kbps, which is not supported by NRF24L01. This is bad since we cannot use the wonderful emulation layer that Pascal already developed in 2016, if I recall correctly. I don't know, if someone managed to use some undocumented register in NRF24 to get 125Kbps data rate... Otherwise, I fear it is needed to write a similar emulation layer on top of CC2500. I will study the datasheet in spare time.

This is the full initialization SPI dump, together with some my notes:

DELTA TIME us SIGNAL REG R/W MOSI REG PKT-0 PKT-1 REG/REPL BITS-P-0 BITS-P-1 NOTES
0 MOSI 00 W 00 6F E0 00h (0d) 01101111 11100000 Recommended on datasheet
0 MISO 00 00 00 01 00000000 00000000 00000001
709,773 MOSI 02 W 02 66 17 02h (2d) 01100110 00010111 Recommended on datasheet
709,773 MISO 01 02 01 01 00000001 00000001 00000001
108 MOSI 04 W 04 9C C9 04h (4d) 10011100 11001001 Recommended on datasheet
108 MISO 01 04 80 01 00000001 10000000 00000001
106 MOSI 05 W 05 66 37 05h (5d) 01100110 00110111 Recommended on datasheet
106 MISO 01 05 01 81 00000001 00000001 10000001
105 MOSI 07 W 07 00 00 07h (7d) 00000000 00000000 TX_EN: 0 RX_EN: 0 RF_CH: 0d / 00h
105 MISO 01 07 01 01 00000001 00000001 00000001
106 MOSI 08 W 08 6C 90 08h (8d) 01101100 10010000 Recommended on datasheet
106 MISO 01 08 01 01 00000001 00000001 00000001
107 MOSI 09 W 09 1F C0 09h (9d) 00011111 11000000 PA_PWCTR: 0001 (1d); PA_GN: 1111 (15d)
107 MISO 01 09 81 81 00000001 10000001 10000001
108 MOSI 0B W 0B 00 08 0Bh (11d) 00000000 00001000 Recommended on datasheet
108 MISO 01 0B 01 01 00000001 00000001 00000001
107 MOSI 0D W 0D 48 BD 0Dh (13d) 01001000 10111101 Recommended on datasheet
107 MISO 81 0D 01 01 10000001 00000001 00000001
113 MOSI 16 W 16 00 FF 16h (22d) 00000000 11111111 Recommended on datasheet
113 MISO 01 16 01 01 00000001 00000001 00000001
107 MOSI 17 W 17 80 05 17h (23d) 10000000 00000101 TxRx_VCO_CAL_EN: 1
107 MISO 00 17 00 01 00000000 00000000 00000001
108 MOSI 18 W 18 00 67 18h (24d) 00000000 01100111 Recommended on datasheet
108 MISO 01 18 81 01 00000001 10000001 00000001
107 MOSI 1A W 1A 19 E0 1Ah (26d) 00011001 11100000 Recommended on datasheet
107 MISO 01 1A 01 01 00000001 00000001 00000001
106 MOSI 1B W 1B 13 00 1Bh (27d) 00010011 00000000 XI_trim: 00000
106 MISO 01 1B 00 01 00000001 00000000 00000001
106 MOSI 20 W 20 48 00 20h (32d) 01001000 00000000 PREAMBLE_LEN: 010 (3 bytes); SYNCWORD_LEN: 01 (32 bits → {Reg39[15:0],Reg36[15:0]); TRAILER_LEN: 000 (4 bits); DATA_PACKET_TYPE: 00 (NRZ law data); FEC_TYPE: 00 (No FEC); BRCLK_SEL: 000 (keep low)
106 MISO 01 20 01 80 00000001 00000001 10000000
105 MOSI 21 W 21 3F C7 21h (33d) 00111111 11000111 VCO_ON_DELAY_CNT: 3Fh (63 us); TX_PA_OFF_DELAY: 11 (4us + 3us); TX_PA_ON_DELAY: 00111 (7 us)
105 MISO 01 21 01 80 00000001 00000001 10000000
106 MOSI 22 W 22 20 00 22h (34d) 00100000 00000000 TX_CW_DLY: 20h (32 us); TX_SW_ON_DELAY: 000000 (0 us)
106 MISO 01 22 01 01 00000001 00000001 00000001
106 MOSI 23 W 23 03 00 23h (35d) 00000011 00000000 RE-TRANSMIT_TIMES: 0011 (3 times); SCRAMBLE_DATA: 0000000 (no Scramble)
106 MISO 80 23 80 01 10000000 10000000 00000001
108 MOSI 28 W 28 44 01 28h (40d) 01000100 00000001 FIFO_EMPTY_THRESHOLD: 01000 (8d); FIFO_FULL_THRESHOLD: 10000 (16d); SYNCWORD_THRESHOLD: 000001 (0 errors allowed)
108 MISO 01 28 01 81 00000001 00000001 10000001
107 MOSI 29 W 29 B4 00 29h (41d) 10110100 00000000 CRC_ON: 1; SCRAMBLE_ON: 0; PACK_LENGTH_EN: 1 (1st byte is payload length); FW_TERM_TX: 1; AUTO_ACK: 0 PKT_FIFO_POLARITY: 1 (FIFO flag Active low); CRC_INITIAL_DATA: 0
107 MISO 01 29 01 01 00000001 00000001 00000001
128 MOSI 2A W 2A FD B0 2Ah (42d) 11111101 10110000 SCAN_RSSI_CH_NO: 111111 (63d); Rx_ACK_TIME: B0h (176 us)
128 MISO 01 2A 00 00 00000001 00000000 00000000
117 MOSI 2C W 2C 08 00 2Ch (44d) 00001000 00000000 DATARATE: 1000 (8d → 125 Kbps)
117 MISO 01 2C 01 01 00000001 00000001 00000001
107 MOSI AC R 2C FF FF 2Ch (44d) 11111111 11111111
107 MISO 01 2C 88 00 00000001 10001000 00000000
3,298 MOSI AC R 2C FF FF 2Ch (44d) 11111111 11111111
3,298 MISO 80 2C 00 01 10000000 00000000 00000001
3,438 MOSI 2D W 2D 05 52 2Dh (45d) 00000101 01010010 Best value is 0552H when data rate is 125Kbps
3,438 MISO 01 2D 81 81 00000001 10000001 10000001
114 MOSI 34 W 34 80 80 34h (52d) 10000000 10000000 CLR_W_PTR: 1; CLR_R_PTR: 1
114 MISO 01 34 81 01 00000001 10000001 00000001
121 MOSI 27 W 27 12 34 27h (39d) 00010010 00110100 SYNC_WORD[1]: 1234h (MSWord)
121 MISO 01 27 01 01 00000001 00000001 00000001
107 MOSI 24 W 24 56 78 24h (36d) 01010110 01111000 SYNC_WORD[0]: 5678h (LSWord)
107 MISO 01 24 01 01 00000001 00000001 00000001
106 MOSI 09 W 09 48 00 09h (9d) 01001000 00000000 PA_PWCTR: 0001 (1d); PA_GN: 1111 (15d)
106 MISO 80 09 01 01 10000000 00000001 00000001
119 MOSI 34 W 34 80 80 34h (52d) 10000000 10000000 CLR_W_PTR: 1; CLR_R_PTR: 1
119 MISO 00 34 01 01 00000000 00000001 00000001
109 MOSI 07 W 07 00 A1 07h (7d) 00000000 10100001 TX_EN: 0; RX_EN: 1; RF_CH: 33d / 21h
109 MISO 01 07 01 01 00000001 00000001 00000001
2,445 MOSI A4 R 24 FF FF 24h (36d) 11111111 11111111 reads SYNC_WORD @ 36 (24h)
2,445 MISO 32 24 53 7C 00110010 01010011 01111100
1,237 MOSI A5 R 25 FF FF 25h (37d) 11111111 11111111 reads SYNC_WORD @ 37 (25h)
1,237 MISO 33 25 00 00 00110011 00000000 00000000
1,281 MOSI A6 R 26 FF FF 26h (38d) 11111111 11111111 reads SYNC_WORD @ 38 (26h)
1,281 MISO 13 26 00 00 00010011 00000000 00000000
1,314 MOSI A7 R 27 FF FF 27h (39d) 11111111 11111111 reads SYNC_WORD @ 39 (27h)
1,314 MISO 12 27 02 30 00010010 00000010 00110000
1,665,875 MOSI 27 W 27 12 34 27h (39d) 00010010 00110100 SYNC_WORD[1]: 1234h (MSWord)
1,665,875 MISO 12 27 12 12 00010010 00010010 00010010
132 MOSI 24 W 24 56 78 24h (36d) 01010110 01111000 SYNC_WORD[0]: 5678h (LSWord)
132 MISO 13 24 1A 12 00010011 00011010 00010010
3,240 MOSI A4 R 24 FF FF 24h (36d) 11111111 11111111 reads SYNC_WORD @ 36 (24h)
3,240 MISO 1A 24 56 78 00011010 01010110 01111000
1,227 MOSI A5 R 25 FF FF 25h (37d) 11111111 11111111 reads SYNC_WORD @ 37 (25h)
1,227 MISO 02 25 00 00 00000010 00000000 00000000
1,291 MOSI A6 R 26 FF FF 26h (38d) 11111111 11111111 reads SYNC_WORD @ 38 (26h)
1,291 MISO 12 26 00 00 00010010 00000000 00000000
1,201 MOSI A7 R 27 FF FF 27h (39d) 11111111 11111111 reads SYNC_WORD @ 39 (27h)
1,201 MISO 1A 27 12 30 00011010 00010010 00110000
1,510 MOSI 87 R 07 FF FF 07h (7d) 11111111 11111111
1,510 MISO 02 07 00 20 00000010 00000000 00100000

I will keep on investigating on this.

Ciao, Francesco

motorello avatar Nov 13 '25 18:11 motorello