Eachine H1 a.k.a. Mini Ninja
- alibenpeng
- Topic Author
- Offline
I've got me one of these and none of the protocols I've tested so far seems to work (and I've tested all but the "expensive" ones like FrSky or DSMX). The transceiver is nothing I've ever seen before (picture attached) and also completely unmarked. All 2.4GHz transceivers I've seen so far come in TQFP packages, not in SOIC, SOP, or whatever this is.
I've tried to trace data on the SPI bus (or what I believe to be the SPI bus), but they look all broken. The clock signal looks irregular and at ~87kHz it is way too slow for an SPI clock.
Also, those traces were quite hard to capture, as connecting wires to those pins seems to derail the signals and it took quite a few tries to capture a successfull bind, for example. Especially the clock signal seems to be VERY sensitive to the "antenna" that is the LA wire. I had to keep it extremely short to be able to capture anything on it without breaking communications between MCU and transceiver.
Can anybody tell me what I'm looking at, or give me some advice on how to make a proper capture?
Thanks,
Ali
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
SeByDocky already captured SPI data for the Eachine H1.
Its using LT8910 RF chip, which is not yet supported by deviation, protocol looks easy to do, I've already analyzed it.
Here is my script to decode LT8910 SPI commands exported from Salae Logic as .csv plus one of the captures from SeByDocky exported to .csv.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
I'll search this evening and post details on protocol ... no need to do that work twice.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
RF chip init:
1.2832 0 WRITE REG 0 (00) DATA: 6F E0 STATUS: 81 81
1.2835 1 WRITE REG 1 (01) DATA: 56 81 STATUS: 01 01
1.2839 2 WRITE REG 2 (02) DATA: 66 17 STATUS: 00 00
1.2842 3 WRITE REG 4 (04) DATA: 9C C9 STATUS: 01 01
1.2845 4 WRITE REG 5 (05) DATA: 66 37 STATUS: 01 01
1.2848 5 WRITE 7_RXTX_CHNL (07) DATA: 00 30 STATUS: 01 01
1.2852 6 WRITE REG 8 (08) DATA: 6C 90 STATUS: 01 81
1.2855 7 WRITE 9_PA_CTRL (09) DATA: 48 00 STATUS: 81 81
1.2858 8 WRITE 10_OSC_XTAL_EN (0A) DATA: 7F FD STATUS: 81 81
1.2861 9 WRITE 11_RSSI_PDN (0B) DATA: 00 08 STATUS: 01 00
1.2864 10 WRITE REG 12 (0C) DATA: 00 00 STATUS: 01 01
1.2868 11 WRITE REG 13 (0D) DATA: 48 BD STATUS: 01 01
1.2871 12 WRITE REG 22 (16) DATA: 00 FF STATUS: 01 01
1.2874 13 WRITE 23_VCO_CAL_EN (17) DATA: 80 05 STATUS: 01 01
1.2877 14 WRITE REG 24 (18) DATA: 00 67 STATUS: 01 01
1.2880 15 WRITE REG 25 (19) DATA: 16 59 STATUS: 00 00
1.2884 16 WRITE REG 26 (1A) DATA: 19 E0 STATUS: 01 01
1.2887 17 WRITE REG 27 (1B) DATA: 13 00 STATUS: 01 01
1.2890 18 WRITE REG 28 (1C) DATA: 18 00 STATUS: 01 01
1.2893 19 WRITE 32_AIRFMT (20) DATA: 48 00 STATUS: 01 01
1.2897 20 WRITE REG 33 (21) DATA: 3F C7 STATUS: 01 01
1.2900 21 WRITE REG 34 (22) DATA: 20 00 STATUS: 01 00
1.2903 22 WRITE 35_PWRCONFIG (23) DATA: 03 00 STATUS: 01 81
1.2906 23 WRITE 36_SYNCWORD0 (24) DATA: FD 07 STATUS: 81 80
1.2910 24 WRITE 37_SYNCWORD1 (25) DATA: 55 01 STATUS: 00 01
1.2913 25 WRITE 38_SYNCWORD2 (26) DATA: 02 03 STATUS: 01 01
1.2916 26 WRITE 39_SYNCWORD3 (27) DATA: 04 05 STATUS: 01 01
1.2919 27 WRITE 40_THRESH (28) DATA: 44 02 STATUS: 01 01
1.2923 28 WRITE 41_PKTCONF (29) DATA: B0 00 STATUS: 01 00
1.2926 29 WRITE REG 42 (2A) DATA: FD B0 STATUS: 01 01
1.2929 30 WRITE 43_RSSI (2B) DATA: 00 0F STATUS: 01 01
1.2932 31 READ 36_SYNCWORD0 (A4) DATA: 00 00 STATUS: FF 07
1.2936 32 WRITE 52_TXRX_RWPTRS (34) DATA: 80 80 STATUS: 81 01
1.2939 33 WRITE 7_RXTX_CHNL (07) DATA: 00 8A STATUS: 81 81
Bind packet:
1.3961 366 READ 48_STATUS (B0) DATA: 00 00 STATUS: 1A 16
1.3964 367 WRITE 52_TXRX_RWPTRS (34) DATA: 80 80 STATUS: 12 12
1.3967 368 WRITE 50_TXRX_FIFO (32)
DATA: 18 a9 dd 7d 09 3c 14 01 fd 00 09 00 00 00 00 00 00 00 00
STATUS: 12 12 12 12 12 12 12 12 12 12 13 12 12 10 12 10 1a 12 13
1.3987 369 WRITE 7_RXTX_CHNL (07) DATA: 01 0A STATUS: 12 12
1.3990 370 READ 48_STATUS (B0) DATA: 00 00 STATUS: 81 C0
1.3994 371 WRITE 7_RXTX_CHNL (07) DATA: 00 0A STATUS: 01 01
1.3997 372 WRITE 52_TXRX_RWPTRS (34) DATA: 80 80 STATUS: 01 01
1.4000 373 WRITE 7_RXTX_CHNL (07) DATA: 00 8A STATUS: 01 01
Data packets:
9.6582 76085 WRITE 7_RXTX_CHNL (07) DATA: 01 17 STATUS: 01 01
9.6585 76086 READ 48_STATUS (B0) DATA: 00 00 STATUS: 04 0E
9.6588 76087 READ 48_STATUS (B0) DATA: 00 00 STATUS: 09 40
9.6591 76088 WRITE 7_RXTX_CHNL (07) DATA: 00 17 STATUS: 00 01
9.6612 76089 WRITE 52_TXRX_RWPTRS (34) DATA: 80 80 STATUS: 01 01
9.6615 76090 WRITE 50_TXRX_FIFO (32)
DATA: 18 49 02 02 09 02 01 02 88 00 00 7f 7f 32 20 40 40 00 d0
STATUS: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 81 01
9.6636 76091 WRITE 7_RXTX_CHNL (07) DATA: 01 26 STATUS: 00 81
9.6639 76092 READ 48_STATUS (B0) DATA: 00 00 STATUS: 37 0C
9.6642 76093 READ 48_STATUS (B0) DATA: 00 00 STATUS: 0D 40
9.6645 76094 WRITE 7_RXTX_CHNL (07) DATA: 00 26 STATUS: 01 01
9.6666 76095 WRITE 52_TXRX_RWPTRS (34) DATA: 80 80 STATUS: 01 00
9.6669 76096 WRITE 50_TXRX_FIFO (32)
DATA: 18 49 02 02 09 03 01 02 88 00 00 7f 7f 32 20 40 40 00 d0
STATUS: 01 01 01 01 01 01 01 81 01 01 01 01 01 00 01 01 01 01 01
9.6690 76097 WRITE 7_RXTX_CHNL (07) DATA: 01 3C STATUS: 01 01
9.6693 76098 READ 48_STATUS (B0) DATA: 00 00 STATUS: 04 18
Distilled:
Bind sends packets on RF channel 0a and 8a, data is
18 a9 dd 7d 09 3c 14 01 fd 00 09 00 00 00 00 00 00 00 00
Data sends packets on RF channels 13, 17, 26 and 3C (for this TX ID) which look like
18 49 02 02 09 03 01 02 88 00 00 80 80 32 20 40 40 00 d2
...
18 49 02 02 09 03 01 02 88 00 00 7f 7f 32 20 40 40 00 d0
...
18 49 02 02 09 01 01 02 88 00 00 43 7f 32 20 40 40 00 94
18 49 02 02 09 02 01 02 88 00 00 4c 7f 32 20 40 40 00 9d
18 49 02 02 09 03 01 02 88 00 00 56 7f 32 20 40 40 00 a7
18 49 02 02 09 00 01 02 88 00 00 74 7f 32 20 40 40 00 c5
18 49 02 02 09 01 01 02 88 00 00 7f 7f 32 20 40 40 00 d0
...
second byte is 0x49 to mark data packet, sixth byte counts 0-3 between packets.
Since I do not own this quad, I cannot help more w/o more dumps, especially the 'TX ID' in bind packet and the resulting channel sequence are from interest.
Note that the very same LT8910 RF chip can be found in a small quadcopter called 'CX033 Nano' (PSX-Style controller, not really from CX, this one: www.amazon.com/CX033-Wireless-Control-Qu...rcraft/dp/B00M0E1K80 ) and in Eachine CG022 - both I do own. Protocol of these are (both) different, but also mostly understood by me. CX033 Transmitter has small board with LT8910 RF chip on it, which should be easy to transplant for Arduino/Deviation usage.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
I looked at the packet format in search of a possible match within our four "deviated" chips. According to the init sequence it should look like this:
3 Bytes Preamble, either As or 5s,
4 Bytes Address, FD075501 (although registers 38 and 39 are also set, no idea why),
then a mysterious 4 bit trailer, I couldn't find out anything about,
1 byte payload length,
n bytes payload,
2 bytes crc.
And the whole thing is then NRZ encoeded and GFSK modulated. Oh, and the chip only supports 1MBit data rate, it seems.
Out of our "favourite four", the CYRF and the nRF24 are the only ones that have a 1MBit data rate with GFSK modulation, and the nRF24's old, not enhanced, shock burst format looks promisingly close to what we need. The only thing I can't see right now, is how to shoehorn those four trailer bits in there, whatever they might be.
I've also ordered one of these puppies , so I can do what this guy did . That should help a lot with the troubleshooting, if we ever get that far.
The only thing really bugging me is that I can't seem to get a proper SPI capture from my TX. All I get is bs-data, stuff like a MISO line that is always high (it does go low at some point, so it is not shorted to VCC). I've even tried two different logic analyzers with not the same, but equally unusable results. There must be something really fishy going on here, or I have forgotten how to use a logic analyzer overnight.
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
I'll check your setup this evening, sounds like some pins are not really the proper ones
Reagarding Down-converter based 2.4GHz sniffing: This will only work until the protocol starts to channel-hop - which is okay in this scenario, but makes its unusable to check any issues with frequency hopping (simply, the SDR cannot switch channels fast enough, as far as I know).
I've thought about emulating it with nRF before, but yet had no idea how to start.
You can send almost anything as _real_ payload (including preambles and headers of LT8910) and just ignore that NRF protocol header and footer being added automagically.
Can make receipting harder for LT chip (in case NRF has similar sync, as it has), but it should sync to its own preambles within ANY random data.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
Also, the clock frequency in SeBy's captures is also only ~90kHz, as are mine, so that seems to be normal. But it turned out that I also misread the datasheet. Those timings there were the absolute minimums, and there are no maximums specified, so the slow clock shouldn't be a problem.
I don't really grasp the "real payload" bit you're talking about. What else is there apart from the stuff in the "packet format" diagram? I always imagined that when the TX turns on, the transmission starts with the preamble bits and ends with the CRC, and that's it. But I agree, in the end it wouldn't make a difference, unless the LT deploys a similar kind of sorcery.
I'm also still wondering about that misterious 4 bit long trailer, and how to find out what's in there. With that the RTL-SDR sniffing might help, but it'll be a while until the downconverter arrives.
On finding a starting point with the nRF: I will try to bluntly hardcode a bind packet, and just try brute forcing those trailer bits. There are only for of them after all. I don't really expect it to work on the first try, but with the work you already did, I think all the pieces are there.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
btoschi wrote:
which means 0x18 bytes payload, a9 indicates bind packets, then follows TX ID (not sure, but should be there) which (most propably) affects the RF channels for data phase.18 a9 dd 7d 09 3c 14 01 fd 00 09 00 00 00 00 00 00 00 00
Wait, shouldn't there be 24 bytes there?
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
CX033 writes 0x0a first, followed by 0x09 bytes (thus they're writing total bytes including length, which is wrong according to manual).
The datasheet is not very precise there, but for me it looks like a programming bug in H1 transmitter (C-source with 0x18 instead of 18), and I'm pretty sure the LT8910 simply sends out non-initialized data (or zeroes, if the chip is brave) for the missing 6 bytes.
You should be able to see that when sniffing with SDR.
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
alibenpeng wrote: I don't really grasp the "real payload" bit you're talking about. What else is there apart from the stuff in the "packet format" diagram? I always imagined that when the TX turns on, the transmission starts with the preamble bits and ends with the CRC, and that's it.
LT8910 Packets:
Preamble | SYNC | Trailer | Payload | (CRC)
^ 1010... or 0101... matches continuation in first bits of SYNC byte
^ Think of "MAC-Address"
NRF Packets (without Shockburst):
Preamble | Address | Payload
1 byte 3-5bytes 0-32bytes
You can see, NRF packets without enhanced shockburst and LT8910 format are looking very similar besides the 'trailer'.
With ANY RF chip you can send the proper formed packet of LT8910 (Preamble + SYNC + Trailer + Payload + CRC) as "Payload" and all is fine. Only thing stopping you could be maximum allowed packet length.
With NRF you could even misuse the NRF Address to form up the (Preamble+) SYNC bytes (depends on Preamble length) and make the first 4 bits of your payload form the 'trailer' (or missign parts of SYNC). Just pad last byte with "something" (zeroes, randoms, the chips won't care after receiving and decoding a full packet).
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
btoschi wrote: With ANY RF chip you can send the proper formed packet of LT8910 (Preamble + SYNC + Trailer + Payload + CRC) as "Payload" and all is fine. Only thing stopping you could be maximum allowed packet length.
I get it. The receiver will ignore anything before it's own preamble+address as noise.
btoschi wrote: With NRF you could even misuse the NRF Address to form up the (Preamble+) SYNC bytes (depends on Preamble length) and make the first 4 bits of your payload form the 'trailer' (or missign parts of SYNC). Just pad last byte with "something" (zeroes, randoms, the chips won't care after receiving and decoding a full packet).
That's what I'm trying to do right now.
I've started out with a copy of the YD717 as a template, because I'm already familiar with the protocol and it uses the nRF. I've already adjusted the init sequence to match the settings of the lt8910, set the address length to 5 bytes, the first two being 0xAA, then the first three sync-bytes (0xFD0755).
The first byte of the "real" payload will be the last sync byte (0x01), followed by four trailer bits, and then the original payload + CRC.
Right now I'm working on how to calculate the CRC and then right-shift the packet array by 12 bits, so I can insert the last address byte and the trailer. My C skills aren't the greatest, so that's a bit of a challenge.
Please Log in or Create an account to join the conversation.
- SeByDocKy
- Offline
- Posts: 1016
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
Exactly.alibenpeng wrote: I get it. The receiver will ignore anything before it's own preamble+address as noise.
I'm always low on time, but I can help with C/C++/... when needed.alibenpeng wrote: My C skills aren't the greatest, so that's a bit of a challenge.
Are you coding (prototyping) with Deviation or using Arduino ?
Latter one is still painful (compared with most of my Linux based toolchains), but slightly faster than compiling and uploading to Devo, mostly thanks to smaller binary size plus automated upload.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
I've also got the CRC generation and bit shifting of the payload packet working, so I was even able to send a few first (unsuccessfull) bind packets.
What I've done is make the CRC polynomial configurable (only among the 4 most common, not a free 16 bit number) via the model_opts dialog and rotate the trailer with every bind packet that gets sent out.
But without being able to sniff packets from the air, this is about as far as I'll get. Hopefully the down converter gets here soon...
I am coding directly in Deviation, with the emu and lots of debugging, to see if my code even does what it's supposed to, and if I got something worth testing, I flash it to my Devo8. I've used to go the Arduino/AVR route when I built my own PPM modules for the 9X (using/porting Deviation protocol code).
BTW, I've got a Makefile based toolchain for the AVR that includes the Arduino libs. The Arduino IDE just wasn't bearable. I'm a Linux Admin by trade, so, by definition, my coding skills are limited and I feel strongly about the text editor I use.
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
btoschi wrote: Bind sends packets on RF channel 0a and 8a, data is
which means 0x18 bytes payload, a9 indicates bind packets, then follows TX ID (not sure, but should be there) which (most propably) affects the RF channels for data phase.18 a9 dd 7d 09 3c 14 01 fd 00 09 00 00 00 00 00 00 00 00
I've looked into that, and my findings differ a bit:
The bind packet gets sent out on only one (randomly chosen at startup) channel, not two. Only the 0x0A write has the TX_EN bit set.
The first four bytes after the length byte (0x18) are different on every TX startup, so they must contain what we are after.
Here is the bind packet structure as I understand it:
18: length
a9: These 4 bytes are different on every startup
dd:
7d:
09:
3c: These 4 bytes are always the same (also on my own TX)
14:
01:
fd:
09: This is always equal to the last byte of the "random" 4 bytes
00: 8 bytes zeros, these are always there.
00:
00:
00:
00:
00:
00:
00:
The first four bytes of the data packets are also different on each startup, and except for the fourth byte, differ from those in the bind packet:
18: length
49:
02:
02:
09: This is always the same as the last of the random bytes in the bind packet
0x: 00-03, sequence no.
Payload
The channels used with these packets are 0x13, 0x17, 0x26, and 0x3c.
So there must be a way to get from the 4 "random" bytes in the bind packet to the 4 channels that are used for the hopping sequence. I made a few more captures, to see if there is a pattern, but other than the findings already reported, I couldn't find anything so far, but still, here are the pairings:
a9 dd 7d 09: bind (ch 0a)
13 17 26 3c: channels
7a bc ff 37: bind (ch 08)
11 15 30 3D: channels
78 be df 57: bind (ch 06)
0f 17 2e 3f: channels
c1 75 aa 8c: bind (ch 13)
0d 19 26 38: channels
2d 09 3e f8: bind (ch 06)
10 16 24 3b: channels
65 d1 2c 0a: bind (ch 11)
0b 1b 30 3d: channels
a8 8e ed 49: bind (ch 09)
12 23 2d 40: channels
One more thing might be important, and that's the channel the bind packet gets sent on.
All this assumes that the channel hopping sequence is not negotiated and the TX is calling all the shots.
If it actually is negotiated, we'd have to look at the answer in the FIFO after the last bind packet, but I'm still far from figuring that one out. Again, the first four bytes after the length byte are similar (often the same or only one off) to the ones in the bind packet, but the rest of the packet makes absolutely no sense at all to me.
I've attached a few files to compare, with (hopefully) all the relevant data.
Please Log in or Create an account to join the conversation.
- btoschi
- Offline
- Posts: 151
Regarding the 0a/8a bind channel, I've most propably overlooked that only with 0a the actual transmission bit is set - did not spent too much time on these protocols and I've learned most LT8910 features during investigation, as such my first findings are most propably wrong on many things (be warned )
I'll check if I can check this evening ... My last evening-task (repairing a dead Phantom 2 Vision) finished successfully.
Side note on the Phantom: How can one build such over-computerized thing and not giving any opportunity to read error codes via PC / App ??? (Did I mention no GPS details, ... ???) Most things are accessible via WiFi protocol - see www.rcgroups.com/forums/showthread.php?t=2212861 .
Please Log in or Create an account to join the conversation.
- alibenpeng
- Topic Author
- Offline
I've got my downconverter delivered, only to find out I've ordered the wrong one. I got one for 2.2-2.4GHz, while what I needed was one for 2.4-2.6GHz. Which is what I now ordered.
I'll be back in another few weeks, then, I guess..
Please Log in or Create an account to join the conversation.
- victzh
- Offline
- Posts: 1386
And do you have a link to it - I failed to find it on aliexpress.
Please Log in or Create an account to join the conversation.
- Home
- Forum
- Development
- Protocol Development
- Eachine H1 a.k.a. Mini Ninja