sebmillet / RF433any

GNU Lesser General Public License v3.0
39 stars 4 forks source link

Decoding an known RF signal #9

Closed smolbun closed 10 months ago

smolbun commented 1 year ago

logicanalyzer_out Hi thanks for your work on this library. I'm unclear how does your library decode raw signals, I got 1000100010001000101100010001000101101101101101100010110110110001000100010001000100010001 from Universal Radio Hacker and Decoded: yes, err: 0, code: N, rep: 1, bits: 24, data: f7 04 7f I=6976, LS=312, LL=704, HS=444, HL=856, S=6976, U=0, V=0, Y=312, Z=296 from the library output. How exactly does the decoding process work? Sorry if I've not done enough research prior to asking this.

sebmillet commented 1 year ago

Hello

the code here: https://github.com/sebmillet/RF433any/blob/main/examples/01_main/01_main.ino would produce a clearer output I think. It gives the code to use to decode the signal.

That said, I can try to explain what you got.

code: N = the code is TRI-BIT INVERTED (high-then-low). FYI the usual tri-bit, noted 'T', is low-then-high.

rep: 1 = signal decoded once (it is a common situation that a signal is seen multiple times in a row).

I = Initialization sequence = long sync signal meant to prepare the receiving device.

LS, LL = on the "low" signal, the Short and Long durations respectively. Most frequently "long" is twice as long as "short", that is almost the case here (but not exactly, 312 x 2 = 624, to compare with 704).

HS, HL = on the "high" signal, the Short and Long durations respectively. Same comment as above, we can see HL ~= HS x 2.

S = Separation duration (between two consecutive coding signals), most often S = I.

U, V = rarely used, it means the two first signals (U for the low duration, followed by V for the high duration) are to be ignored in the decoding. This a kind-of "prefix" following INIT sequence, seen on FLO/R telecommands before the real coded signal.

Y = first low ignored. This is used only with the TRI-BIT INVERTED coding (it is the case here). As the signal is made of high-then-low sequences, after the high INIT sequence, there is an initial unused 'low' signal not part of the coding. Most frequently Y ~= LS and it is the case here (again, Y is non-null only with tri-bit inverted, on other coding schemes it is unused and left to zero).

Z = the last low signal duration, before a SEPARATOR or another INIT sequence. Normally the last low is not needed with TRI-BIT INVERTED (it is useful only with TRI-BIT, where the last low is not part of coding), weird it is non-null here, looks like a bug. Anyway we must have Z ~= LS or Z ~= LL (depending on value coded) and it is the case here.

Hope it helps,

Regards.

smolbun commented 1 year ago

Thanks for your response, I'm still quite confused on the concept of Tri-bit encoding. When I decoded it manually, 1000 was 1 and 101 was a 0, the last HIGH signal seems to be redundant. How does one identify if it's a regular Tri-bit or if it's inverted? If possible would you mind walking me through how it's decoded?

sebmillet commented 1 year ago

Hello

First of all, note that "tri-bit" versus "tri-bit inverted" is a matter of convention. I decided that "low-then-high" would be "tri-bit" and "high-then-low" would be "tri-bit inverted" because I had the impression it was the most frequently seen convention (in particular, on RCSwitch library).

In the usual "tribit", you'll see that a "low short" signal is always followed by a "high long" one, whereas a "low long" is always followed by a "high short". That is, if we use "_" for low signal and "-" for high signal, you'll have:

_--    case 1
__-   case 2

then case 1 versus case 2 are arbitrarily translated into "bit is 0" versus "bit is 1", again it is a matter of convention, by default short-then-long is 0 and long-then-short is 1, this can be changed, see below.

In the "tri-bit inverted", the low signal duration and the following high signal duration will not match, that is, you'll not always have "short-then-long" or "long-then-short". This is because on tribit inverted, you don't consider together "low signal and the following high signal duration", but the other way round: "high signal then low signal", that DO HAVE to match.

If you snif the signal (for example using https://github.com/sebmillet/rf433snif, but there's many others around). (The first number is the duration of the LOW signal, the second number is the duration of the HIGH signal.)

TRI-BIT: LOW, HIGH 0, 7020, 1292, 520, 592, 1220, 1288, 524, 588, 1232, 1284, 540, .... you see that the left number matches with the right number: it is "short then long" or "long then short", on each line.

TRI-BIT INVERTED: LOW, HIGH 0, 24100, 2064, 1432, 748, 1424, 768, 720, 1468, 1436, 716, 746, 1452, 1464, .... you see that the right number matches the left number OF THE FOLLOWING LINE: it is "short then long" or "long then short". Because it is high-then-low, the correspondance takes place across lines. Reading top-bottom, 1432 goes with 748 (long-then-short), 1424 goes with 768 (again, long-then-short), 720 goes with 1468 (short-then-long), 1436 goes with 716 (long-then-short), 746 goes with 1452 (short-then-long), und so weiter.

As said above, the decoding consists in differenciating "short-then-long" versus "long-then-short", would it be tribit or tribit-inverted. Once the receiver knows whether it is "short-then-long" or "long-then-short", it simply assigns 0 to "short-then-long" and 1 to "long-then-short" and this produces a stream of bits.

Of course assigning 0 to "short-then-long" and 1 to "long-then-short" is arbitrary and a matter of convention, you can do the opposite. The library RF433any allows to add a parameter when calling decode functions to choose convention. For example the function get_data (used in the examples provided by RF433any) allows a secondary parameter, "convention", that can be RF433ANY_CONV0 (default) or RF433ANY_CONV1. Using RF433ANY_CONV1 will simply invert decoded signal, for example a 24-bit value of f7 04 7f will become 08 fb 80.

Hope it helps,

Regards, Sébastien