Versions Compared

Key

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

...

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:

...

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


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.

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.

...

• 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.


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


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

...

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);
}


Sending Temperatures to the Receiver


Code

Code Block


References

...