Closed Serge-45 closed 4 months ago
Hi Serge, the 6b8b is not the standard DC-balanced linecode you find in the web. They wrote their own encoding scheme.
when I started investigatin the pixmob-batch, I switched to BigEndian in transmition. whitch one you use does not matter. the plain values are encoded and directly send. If you like LE encoding more, you 'll have to change the dictTable to { 0x84, 0xac ... }, change the preamble from 0x55 to 0xaa and reverse the for-loop in transmitByte. but keep in mind - that does not change anything.
Sueppchen
Hi Sueppchen, Thanks for your answers. Ok for their own 6b8b encoding. I wonder how you manage to get the translation table ? Ok for BE/LE, I'm keeping the BE encoding in order to align with the notation in the blue_xx.txt files. I'm trying to find a bit of logic in the CRC values, but no discovery so far... Serge
i got the table with a mixture of the given values at daniel Weidmanns site, guessing and some bruteforcing... th blue_xx.txt files are only a stage - lets call it collection. the final files are the blue_x.list files. all values in that files are proofed to work. you don't need the 6b8b encoded values... for crc calculations I create them by dictTable. that will save space... I got 27 different RGB-triplets with all the same 47,49 (0x2f + 0x31) CRC... but I didn't get any checksum - algorithm which has the same behavior.
For CRC, they may use different strategies, knowing that the input message is made of 7x6 bits, and the transmitted CRC is 2x6 bits :
Another approach would be to input the 7x6 bits in a CRC-12 calculation, and split the result as 6+6 bits. I think this approach is less probable, as the necessary programing is more complex and less usual.
i Wrote a python script what did all this... ...I will upload it in /crcBrute it can do following things with the complete frame:
it can do following things with each byte bevor CRC is calculated:
then CRC16 is calculated with various options (init value, key, reflect input, reflect output, xor the output...)
the result is processed:
maybe lower bits could be cut..
I think it is not to complicated. things like crc12 must be written in code. A crc16 engine is in the processor implemented to check the uploaded code. that is cheep. stitching all bits together to a long number is complicated... and the result is 54 bit long (or 42 bit if shorted)
I had implemented this function but I do not find the file... so...later.
ok, done... it was already in the file. so I added some comments to find the place to change.next time I add shift one bit and cut one bit and other crazy stuff in the output section... ideas welcome :-)
Great ! In the meantime, I did some testing with an Arduino directly connected to the P03 of the MCU, no RF module. The bit transmission duration can be shortened to 440µs, and the gap between two messages can be reduced to 3ms. This may increase a bit the testing rate. As well, I'm sending a "StayAlive" command only every 64 tested values, as the MCU is falling asleep after about 1.5 minute with no message or wrong message.
yes, that is possible to speed things up, but the processor needs time to settle up the PWM pins. so... have you tested how far away you are from real checksum (I was between 1 and 2)? official time for ,,background color" is 60sec until it disappears. The stay-alive-message is background color: black.
Great achievement ! Based on the data you got, I've been able to calculate the CRC value for given G, R and B values. See attached code.
New version, including calculation for all BLUE values, and for some values of ATTACK/RANDOM. New function setCRC(byte *message). crc.ino.txt
Last version with all values for RELEASE/HOLD values ! crc.ino.txt
hej, nice job. I will update the readme and the files as soon as possible.
I've created diagrams explaining the pulse shape and the use of the background color (when RELEASE = 0). Feel free to add them in the file list. ATTACK and RELEASE phases cannot be interrupted by a new incoming message, but HOLD phase can be.
Background timeout range is from about 0.5 second to about 60 seconds according to the HOLD value (from 0 to 7) in the message setting the background color.
ok... your tables are great... how did you get there?
I took them to the python-ckeck-value-script and let it only test the ,,not found" values.
most of them are crcA odd and crcB 63 or crcA even and crcB 5 ... surprise. the Question is, why this values can not be found by the normal bruteforce method.
I think they don't do it with tables in the processor in most cases there are the basic bit and byte manipuation operands: shift left, shift right, swap, rotate left, rotate right, and, or, xor. all that could be done with plain values(6 byte or 8 byte), or 6b8b values (LE or BE) possible scenario is:
repeat everything between dashes until all bytes are received
when the checksum algorithm is found, I will continue with group and eeprom storage. but without knowing the checksum it is impossible to guess what is right and what will possible fry the batch.
nice diagram, attack is running before led lights up and is also running when the hold value is reached... when I checked the attack and release values with the logic analyzer, I wondered why there where values of 86ms and 48 ms and so on until I tested without A and R ramps
Well, here are some info from what I discovered:
by analyzing all the CRC values you had in your files, I detected that each of the bytes of the message has a specific effect on the CRC, and independantly from each other. For example, the XOR of the CRCs for "X1 X2 X3 10 X5 X6 X7 X8" and "X1 X2 X3 11 X5 X6 X7 X8" is always the same, whatever the values for X1...X8. By testing the 64 possible values for this byte, I built the table relative to this byte.
yes, there is likely an algorithm rather that raw tables, but I haven't discovered (yet!) any logic in the values of the CRC tables
I really think that CRC calculation occurs before the 6b8b conversion, as all recognized CRC values are part of the 6b8b dictionnary
about detection, I've seen that there is a minimal threshold for the LED output to be activated. This means that in case of very slow attack and/or very low value of brightness, the first change on LED output will be a bit delayed. This is probably due to the calculation of the attack ramp (PWM ratio) with a rounding to zero for very low values (<=3?). When attack is short, the reaction time is always about 9ms after the end of the message. If you request a very low value (let's say 0x0f) with a very long attack (0x7), the first change on LED output may occur only after a couple of seconds. Exactly same thing for the release ramp. This put additional difficulties in the bruteforce detection!
tests show as well that we must have about 3ms gap between two successive messages. If not, the second message is ignored. This may explain the 86ms you detected sometimes.
I wrote my own bruteforce program based on timer interrupt for sending data and PIN change interrupt to detect activity.
I'm starting to explore the 1st byte (mode ?). I've got some (strange) reactions with mode=2. You can test it! Changing mode from 0 to 2 requires to XOR the CRC by 0x3D30.
I've tested as well the last byte (group ?). Reaction only detected for group=1 on my pixmob device (CRC xor is 0x2F16).
Let's continue!
Updated crc.ino file, able to manage MOD=2 and GRP=1 crc.ino.txt
Here is the com.ino file used for sending messages and detecting activity on an Arduino UNO board. See comments for PINs connections. com.ino.txt
For information, if you play with background color, it could be usefull to reset to "no background". For this, I use
{0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02} // set black color as background
I also use this message as a "keep-alive" message during long bruteforce scanning.
Hi! Thanks for the invitation to contribute. May I create some folders and files to keep trace of my discoveries ? Let me know how you would like to organize it.
I changed your tables to be 0 based (so my initial-Value is 32 02) for the modus have a look @ https://github.com/danielweidman/pixmob-ir-reverse-engineering/issues/8 for a description of the mode byte. maybe they didn't change that for the RF.
also the initial 0xEE would give an matrix of 8x8 bit user data
I think, the behavior of your mode 2 and mode 4 is same saved value in eeprom. did you read it? I have 3 example files in /eeprom
maybe I will do some tests today evening
I adopted your tables into my script and... used mod=2:
when message arrives, eeprom is read. in my case
mode=0 --> normal operation
mode seems to be divided into bits:
bit0: unknown
bit1: is memory mode
memory mode:
byte 2 = 0xEESSSS (end end start start start start)
maybe the missing 2 End-bits are coded into mode itself
byte 3 = Attack + random
byte 4 = release + hold
byte 5 = unknown changing the value has no effect
byte 6 = same like byte 5
byte 7 = could be group
there are 16 memorys each containing 4 bytes from 0x10 to 0x4F
it is always played from start to end (if start is after end all 16 are played)
when you get mode 4 working, you could reverse the byte5 and byte7 table values - because its not group and random anymore
Hi Sueppchen ! Congratulation for your investigations on PixMob, very impressive ! I'm starting also in discovering this device. I've got a question about the 6b8b encoding. I cannot match the dictTable you use in advanced.ino with the description of the 6b8b encoding (found at https://en.wikipedia.org/wiki/6b/8b_encoding for instance). Is this another encoding ? Do you include the BigEndian transformation prior to the 6b8b encoding or after ? Thanks for your help ! Serge