1 /* Steelmate TPMS FSK protocol
3 * Copyright © 2016 Benjamin Larsson
4 * Copyright © 2016 John Jore
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Packet payload: 9 bytes.
12 * Bytes 2 to 9 are inverted Manchester with swaped MSB/LSB:
15 * [00] {72} 00 00 7f 3c f0 d7 ad 8e fa
16 * After translating 00 00 01 c3 f0 14 4a 8e a0
17 * SS SS AA II II PP TT BB CC
19 * A = preamble, (0x01)
21 * P = Pressure as double the PSI, 0x14 = 10 PSI
22 * T = Temperature in Fahrenheit, 0x4a = 74 'F
23 * B = Battery as half the millivolt, 0x8e = 2.84 V
24 * C = Checksum, adding bytes 2 to 7 modulo 256 = byte 8,(0x01+0xc3+0xf0+0x14+0x4a+0x8e) modulus 256 = 0xa0
29 #include "pulse_demod.h"
32 static int steelmate_callback(bitbuffer_t *bitbuffer) {
33 //if (debug_output >= 1) {
34 // fprintf(stdout, "Steelmate TPMS decoder\n");
35 // bitbuffer_print(bitbuffer);
36 // fprintf(stdout, "\n");
39 char time_str[LOCAL_TIME_BUFLEN];
40 local_time_str(0, time_str);
41 bitrow_t *bb = bitbuffer->bb;
43 //Loop through each row of data
44 for (int i = 0; i < bitbuffer->num_rows; i++)
46 //Payload is inverted Manchester encoded, and reversed MSB/LSB order
47 uint8_t preAmble, ID1, ID2, p1, tempFahrenheit, tmpbattery_mV, payload_checksum, calculated_checksum;
48 uint16_t sensorID, battery_mV;
53 //Length must be 72 bits to be considered a valid packet
54 if (bitbuffer->bits_per_row[i] != 72)
57 //Valid preamble? (Note, the data is still wrong order at this point. Correct pre-amble: 0x00 0x00 0x01)
58 if (bb[i][0] != 0x00 || bb[i][1] != 0x00 || bb[i][2] != 0x7f)
62 preAmble = ~reverse8(bb[i][2]);
65 ID1 = ~reverse8(bb[i][3]);
66 ID2 = ~reverse8(bb[i][4]);
68 //Pressure is stored as twice the PSI
69 p1 = ~reverse8(bb[i][5]);
71 //Temperature is stored in Fahrenheit. Note that the datasheet claims operational to -40'C, but can only express values from -17.8'C
72 tempFahrenheit = ~reverse8(bb[i][6]);
74 //Battery voltage is stored as half the mV
75 tmpbattery_mV = ~reverse8(bb[i][7]);
77 //Checksum is a sum of all the other values
78 payload_checksum = ~reverse8(bb[i][8]);
79 calculated_checksum = preAmble + ID1 + ID2 + p1 + tempFahrenheit + tmpbattery_mV;
80 if (payload_checksum != calculated_checksum)
83 sensorID = (ID1 << 8) + ID2;
84 sprintf(sensorIDhex, "0x%04x", sensorID);
85 pressurePSI = (float)p1 / 2;
86 battery_mV = tmpbattery_mV * 2;
88 data = data_make("time", "", DATA_STRING, time_str,
89 "type", "", DATA_STRING, "TPMS",
90 "make", "", DATA_STRING, "Steelmate",
91 "id", "", DATA_STRING, sensorIDhex,
92 "pressure_PSI", "", DATA_DOUBLE, pressurePSI,
93 "temperature_F", "", DATA_DOUBLE, (float)tempFahrenheit,
94 "battery_mV", "", DATA_INT, battery_mV,
95 "checksum", "", DATA_STRING, "OK",
97 data_acquired_handler(data);
102 //Was not a Steelmate TPMS after all
106 static char *output_fields[] = {
118 r_device steelmate = {
119 .name = "Steelmate TPMS",
120 .modulation = FSK_PULSE_MANCHESTER_ZEROBIT,
124 .json_callback = &steelmate_callback,
126 .fields = output_fields,