Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
Detected OOK package	2019-10-03 11:49:46
Analyzing pulses...
Total count:  237,  width: 744.45 ms		(186112 S)
Pulse width distribution:
 [ 0] count:  237,  width:  508 us [496;516]	( 127 S)
Gap width distribution:
 [ 0] count:  154,  width: 1932 us [1924;1944]	( 483 S)
 [ 1] count:   70,  width: 3884 us [3876;3896]	( 971 S)
 [ 2] count:    5,  width:  468 us [460;476]	( 117 S)
 [ 3] count:    6,  width: 8520 us [8516;8532]	(2130 S)
 [ 4] count:    1,  width:  708 us [708;708]	( 177 S)
Pulse period distribution:
 [ 0] count:  154,  width: 2440 us [2432;2456]	( 610 S)
 [ 1] count:   70,  width: 4392 us [4380;4408]	(1098 S)
 [ 2] count:    5,  width:  972 us [972;980]	( 243 S)
 [ 3] count:    6,  width: 9032 us [9028;9040]	(2258 S)
 [ 4] count:    1,  width: 1220 us [1220;1220]	( 305 S)
Level estimates [high, low]:  15939,   1378
RSSI: -0.1 dB SNR: 10.6 dB Noise: -10.7 dB
Frequency offsets [F1, F2]:   18554,      0	(+70.8 kHz, +0.0 kHz)
Guessing modulation: Pulse Position Modulation with fixed pulse width
Attempting demodulation... short_width: 468, long_width: 708, reset_limit: 8536, sync_width: 0
Use a flex decoder with -X 'n=name,m=OOK_PPM,s=468,l=708,g=712,r=8536'
pulse_demod_ppm(): Analyzer Device 
bitbuffer:: Number of rows: 25 
[00] { 0}           : 
[01] { 0}           : 
[02] { 0}           : 
[03] { 0}           : 
[04] { 0}           : 
[05] { 0}           : 
[06] { 0}           : 
[07] { 0}           : 
[08] { 0}           : 
[09] { 0}           : 
[10] { 0}           : 
[11] { 0}           : 
[12] { 0}           : 
[13] { 0}           : 
[14] { 0}           : 
[15] { 0}           : 
[16] { 0}           : 
[17] { 0}           : 
[18] { 0}           : 
[19] { 0}           : 
[20] { 0}           : 
[21] { 0}           : 
[22] { 0}           : 
[23] { 0}           : 
[24] { 0}           : 
... Maximum number of rows reached. Message is likely truncated.

So, this is showing us that it detected OOK modulation but when it tries to convert to bits, it fails... 

What is an OOK package?

On Off Keying is a form of Amplitude Shift Keying (ASK) limited to two values. If you use ASK with only two values, you are essentially using OOK.

...

  • zoom in on the first burst.
  • Set the signal view to Demodulated.

Image Removed

Data:

1110 0110 1000 0001 0011 0110 0001 0011  (E6813613)

Rolling Code: 1110 0110 (E6)

Status: 1000 (8)

Temperature: 0001 0011 0110 (136) = 31.0 C

Hash: 0001 0011 (13)

0.5 ms pulse

2 ms off for 0

4 ms off for 1

0.5 ms for stop bit

...

Looking at the entire signal, we see that it sends the identical information 7 times. 


This particular signal starts every bit by turning ON the RF signal and then turning if off for either 2 or 4 milliseconds. Staying off for 2 ms signifies a value of 0 while staying off for 4 ms signifies a value of 1.


What we deduced from looking at the signal:

PulseDelay
On Pulse0.5 ms
0 value2 ms off between On Pulse
1 value

4 ms off between On Pulse

Stop Pulse0.5 ms

9 ms delay between repeats

repeat the whole thing a total of 7 times.


If we look at just one of the pulses, we see that it contains 32 bits or 4 bytes:

Image Added

We received the following data:

1110 0110 1000 0001 0011 0110 0001 0011  (E6 81 36 13 hex)



The Protocol

The protocol for this device is publish at the following URL: 

http://www.osengr.org/WxShield/Downloads/Weather-Sensor-RF-Protocols.pdf


The protocol for the AcuRite 00606TX is:

Image Added From Protocol Doc:


All in nibbles (4 bits). 

Rolling Code(2), Status(1), Temperature (signed binary), Hash Code

Image Removed

AcuRite 00606TX and 00782W3


Data being sent:

NiblePurposeOur ValueDescription
1-2Rolling CodeE6

The rolling code randomly generated when the transmitter powers up.

After the receiver receives it's first rolling code, it will not accept messages with a different code unless rebooted.

3Status8

A status of 8 signifies that the batter is ok

...

.

The status nibble's MSB is a "battery okay" flag which is normally one. It goes to zero when the battery drops below about 2.6 volts or so.

...

Temperature is a signed 12-bit value with resolution of 0.1C. For example, 25.6C is encoded as the value 256 (0x100 hexadecimal). A value of -0.1C is encoded as -1 (0xFFF hexadecimal).

...

4-6Temperature136

The temperature with 1 decimal place. 

A temperature of 31.0C = 31.0*10 = 310 dec = 136 hex

7-8Hash13Hash computed using 


Checksum/Hash

This sensor does not use a simple checksum or even a more advanced CRC. Instead data integrity is verified by a hash code, generated by multiplying the message bits with the byte sequence generated by a linear feedback shift register (LFSR). This algorithm has been referred to as "an LFSR-based Toeplitz hash" in some of the literature.

Hash Algorithm

1. Generate LSFR sequence equal to the length of the message.

In our case, our message is 32 bits long, so we will need 32 values.


  • Start with an 8-bit register initialized to the value 0x7C (0111 1100)
  • Generate a number of values equal to the message size in bits by repeating the following operations once for each bit.

• Rotate the register right one bit.

• If the bit shifted out of the LSB and into the MSB during the rotation was a one, then exclusive-or the value 0x18 into the register (i.e. flip the state of bits 3 and 4). Do this after the rotate operation.

• The register value after these two operations is the sequence value to be stored. Perform these steps once for each bit in the message. If the message contains 40 bits for example (as with the F007TH message) then you will need to generate a sequence of 40 bytes. Because this sequence does not depend on the data message contents and can be pre-computed once and stored to save time.

Image Added


Start ValueShift Right

XOR with 0x18 if MSB =1

(flip bits 3 and 4)

XorValue
10111 1100 (0x7C)→ 0011 1110 NO -0011 1110 (0x3e)
20011 1110 (0x3e)→ 0001 1111NO-0001 1111 (0x1f)
30001 1111 (0x1f)→ 1000 1111YESxor 0x181001 0111 (0x97)
41001 0111 (0x97)→ 1100 1011YESxor 0x181101 0011 (0xd3)
51101 0011 (0xd3)→ 1110 1001YESxor 0x181111 0001 (0xf1)
...




321000 0110 (0x86)→ 0100 0011NO-0100 0011 (0x43)


Values

Image Added


2.   Combines the LSFR sequence with message bits to form the final hash value

To compute the message hash value, sequence through the 24 message bits in the order they were received. Since everything here is big-endian, that means proceeding from MSB to LSB. Start by initializing the hash register to the value 0x00. As the message bits are read, for every bit in the message that is a one, exclusive-or the corresponding value (+5) from the LSFR sequence into the hash register.

For example, if the 10th bit is a one, then take the 15th value from the LFSR sequence and exclusive-or it into the hash register. If the message were all zeros, then nothing would be added to the hash register and the result would be the initial value of 0x00.

From MSB to LSB for message 1110 0110 1000 0001 0011 0110  (E6 81 36 hex)

Register ValueIndexValueValue=1?Calculation

New Register Value

(xor with LSFR Sequence starting at the 5th (0xF1)

0023 -MSB1Yes00 xor f1f1
f1221Yesf1 xor e011
11211Yes11 xor 7061
...




1300No-13


Hash Code

Code Block
#define MESSAGE_SIZE 32
#define OFFSET 4

uint8_t LSFR_sequence[MESSAGE_SIZE] = {0};

void calculateLSFR() {
	int i;
	uint8_t reg = 0x7C;
	uint8_t temp_reg = 0;

	for (i = 0; i < MESSAGE_SIZE; i++) {
		temp_reg = reg & 0x01;
		reg >>= 1;
		reg |= (temp_reg << 7);

		if (temp_reg) {
			reg ^= 0x18;
		}

		LSFR_sequence[i] = reg;
		//printf("%02x\n", LSFR_sequence[i]);
	}
}

uint8_t combineLSFR(uint8_t len, uint8_t *data) {
	uint8_t hash_reg = 0; // not 0x64
	int byte_idx, bit_idx;
	uint8_t byte, bit;
	//printf("***COMBINE\n");

	for (byte_idx = 0; byte_idx < len; byte_idx++) {
		for (bit_idx = 7; bit_idx >= 0; bit_idx--) {
			bit = (data[byte_idx] & (1 << bit_idx)) >> bit_idx;
			if (bit) {
				hash_reg ^= LSFR_sequence[byte_idx * 8 + (7 - bit_idx) + OFFSET];
				//printf("[%d]: %02x\n", byte_idx * 8 + (7 - bit_idx), hash_reg);
			}
			bit = 0;
		}
	}

	return hash_reg;
}

uint8_t Checksum(int length, uint8_t *buff) {
	calculateLSFR();
	return combineLSFR(length, buff);
}

...


References

...