|
| 1 | +/** @file |
| 2 | + TPMS TyreGuard 400 from Davies Craig. |
| 3 | +
|
| 4 | + Copyright (C) 2022 R ALVERGNAT |
| 5 | +
|
| 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. |
| 10 | +*/ |
| 11 | +/** |
| 12 | +TPMS TyreGuard 400 from Davies Craig. |
| 13 | +
|
| 14 | +- Type: TPMS |
| 15 | +- Freq: 434.1 MHz |
| 16 | +- Modulation: ASK -> OOK_MC_ZEROBIT (Manchester Code with fixed leading zero bit) |
| 17 | +- Symbol duration: 100us (same for l or 0) |
| 18 | +- Length: 22 bytes long |
| 19 | +
|
| 20 | +Packet layout: |
| 21 | +
|
| 22 | + bytes : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
| 23 | + coded : S/P S/P S/P S/P S/P S/P S/P ID ID ID ID ID ID ID Pr Pr Temp Temp Flg Flg CRC CRC |
| 24 | +
|
| 25 | +- S/P : preamble/sync "0xfd5fd5f" << always fixed |
| 26 | +- ID : 6 bytes long start with 0x6b????? ex 0x6b20d21 |
| 27 | +- Pr : Last 2 bytes of pressure in psi ex : 0xe8 means XX232 psi (for XX see flags bytes) |
| 28 | +- Temp : Temperature in °C offset by +40 ex : 0x2f means (47-40)=+7°C |
| 29 | +- Flg : Flags bytes => should be read in binary format : |
| 30 | + - Bit 73 : Unknown ; maybe the 20th MSB pressure bit? The sensor is not capable to reach this so high pressure |
| 31 | + - Bit 74 : add 1024 psi (19th MSB pressure bit) |
| 32 | + - Bit 75 : add 512 psi (18th MSB pressure bit) |
| 33 | + - Bit 76 : add 256 psi (17th MSB pressure bit) |
| 34 | + - Bit 77 : Acknoldge pressure leaking 1=Ack 0=No_ack (nothing to report) |
| 35 | + - Bit 78 : Unknown |
| 36 | + - Bit 79 : Leaking pressure detected 1=Leak 0=No leak (nothing to report) |
| 37 | + - Bit 80 : Leaking pressure detected 1=Leak 0=No leak (nothing to report) |
| 38 | +- CRC : CRC poly 0x31 start value 0xdd final 0x00 from 1st bit 80th bits |
| 39 | +
|
| 40 | +To peer a new sensor to the unit, bit 79 and 80 has to be both to 1. |
| 41 | +
|
| 42 | +NOTE: In the datasheet, it is said that the sensor can report low batterie. During my tests/reseach i'm not able to see this behavior. I have fuzzed all bits nothing was reported to the reader. |
| 43 | +
|
| 44 | +Flex decoder: |
| 45 | +
|
| 46 | + -X "n=TPMS,m=OOK_MC_ZEROBIT,s=100,l=100,r=500,preamble=fd5fd5f" |
| 47 | +
|
| 48 | + decoder { |
| 49 | + name = TPMS-TYREGUARD400, |
| 50 | + modulation = OOK_MC_ZEROBIT, |
| 51 | + short = 100, |
| 52 | + long = 100, |
| 53 | + gap = 0, |
| 54 | + reset = 500, |
| 55 | + preamble = fd5fd5f, |
| 56 | + get = id:@0:{28}, |
| 57 | + get = pression:@57:{8}, |
| 58 | + get = temp:@65:{8}, |
| 59 | + get = flags:@73:{8}, |
| 60 | + get = add_psi:@74:{3}:[0:no 1:256 2:512 3:768 4:1024 5:1280 6:1536 7:1792], |
| 61 | + get = AckLeaking:@77:{1}:[1: yes 0:no], |
| 62 | + get = Leaking_detected:@79:{2}:[0:no 1:yes 2:yes], |
| 63 | + get = CRC:@81:{8}, |
| 64 | + } |
| 65 | +
|
| 66 | +*/ |
| 67 | + |
| 68 | +#include "decoder.h" |
| 69 | + |
| 70 | +#define TPMS_TYREGUARD400_MESSAGE_BITLEN 88 |
| 71 | + |
| 72 | +static int tpms_tyreguard400_decode(r_device *decoder, bitbuffer_t *bitbuffer, unsigned row, unsigned bitpos) |
| 73 | +{ |
| 74 | + uint8_t b[(TPMS_TYREGUARD400_MESSAGE_BITLEN + 7) / 8]; |
| 75 | + |
| 76 | + // Extract the message |
| 77 | + bitbuffer_extract_bytes(bitbuffer, row, bitpos, b, TPMS_TYREGUARD400_MESSAGE_BITLEN); |
| 78 | + |
| 79 | + //CRC poly 0x31 start value 0xdd final 0x00 from 1st bit to 80bits |
| 80 | + if (crc8(b, 11, 0x31, 0xdd) != 0) { |
| 81 | + decoder_log_bitrow(decoder, 2, __func__, b, TPMS_TYREGUARD400_MESSAGE_BITLEN, "CRC error"); |
| 82 | + return DECODE_FAIL_MIC; |
| 83 | + } |
| 84 | + |
| 85 | + uint8_t flags = b[9]; |
| 86 | + //int bat_low = flags & 0x1; // TBC ?!? |
| 87 | + int peering_request = flags & 0x3; // bytes = 0b00000011 |
| 88 | + int ack_leaking = flags & 0x8; // byte = 0b00001000 :: NOTA ack_leaking = 1 means ack ;; ack_leaking=0 nothing to do |
| 89 | + |
| 90 | + // test if bits 1st or 2nd is set to 1 of 0b000000XX |
| 91 | + int leaking = flags & 0x3; |
| 92 | + |
| 93 | + //int add256 = (flags & 0x10) >> 4; // bytes = 0b000X0000 |
| 94 | + //int add512 = (flags & 0x20) >> 5; // bytes = 0b00X00000 |
| 95 | + //int add1024 = (flags & 0x40) >> 6; // bytes = 0b0X000000 |
| 96 | + |
| 97 | + char id_str[8]; |
| 98 | + sprintf(id_str, "%07x", (uint32_t)(((b[3] & 0xf)<<24)) | (b[4]<<16) | (b[5]<<8) | b[6]); // 28 bits ID |
| 99 | + char flags_str[3]; |
| 100 | + sprintf(flags_str, "%02x", flags); |
| 101 | + |
| 102 | + //id = (b[4] << 8) |
| 103 | + int pressure_kpa = b[7] | ((flags & 0x70) << 4); |
| 104 | + int temp_c = b[8] - 40; |
| 105 | + |
| 106 | + /* clang-format off */ |
| 107 | + data_t *data = data_make( |
| 108 | + "model", "Model", DATA_STRING, "TyreGuard400", |
| 109 | + "type", "Type", DATA_STRING, "TPMS", |
| 110 | + "id", "ID", DATA_STRING, id_str, |
| 111 | +// "flags", "Flags", DATA_STRING, flags_str, |
| 112 | + "pressure_kPa", "Pressure", DATA_FORMAT, "%.1f kPa", DATA_DOUBLE, (double)pressure_kpa, |
| 113 | + "temperature_C", "Temperature", DATA_FORMAT, "%.0f C", DATA_DOUBLE, (double)temp_c, |
| 114 | + "peering_request", "Peering req", DATA_INT, peering_request, |
| 115 | + "leaking", "Leaking detected", DATA_INT, leaking, |
| 116 | + "ack_leaking", "Ack leaking", DATA_INT, ack_leaking, |
| 117 | +// "add256", "", DATA_INT, add256, |
| 118 | +// "add512", "", DATA_INT, add512, |
| 119 | +// "add1024", "", DATA_INT, add1024, |
| 120 | +// "battery_ok", "Batt OK", DATA_INT, !bat_low, |
| 121 | + "mic", "Integrity", DATA_STRING, "CRC", |
| 122 | + NULL); |
| 123 | + /* clang-format on */ |
| 124 | + |
| 125 | + decoder_output_data(decoder, data); |
| 126 | + return 1; |
| 127 | +} |
| 128 | + |
| 129 | +/** @sa tpms_tyreguard400_decode() */ |
| 130 | +static int tpms_tyreguard400_callback(r_device *decoder, bitbuffer_t *bitbuffer) |
| 131 | +{ |
| 132 | + //uint8_t const tyreguard_frame_sync[] = {0xf, 0xd5, 0xfd, 0x5f} |
| 133 | + uint8_t const tyreguard_frame_sync[] = {0xfd, 0x5f, 0xd5, 0xf0}; // needs to shift sync to align bytes 28x bits usefull |
| 134 | + |
| 135 | + int ret = 0; |
| 136 | + int events = 0; |
| 137 | + |
| 138 | + for (int row = 0; row < bitbuffer->num_rows; ++row) { |
| 139 | + if (bitbuffer->bits_per_row[row] < TPMS_TYREGUARD400_MESSAGE_BITLEN) { |
| 140 | + // bail out of this "too short" row early |
| 141 | + if (decoder->verbose >= 2) { |
| 142 | + // Output the bad row, only for message level debug / deciphering. |
| 143 | + decoder_logf_bitrow(decoder, 2, __func__, bitbuffer->bb[row], bitbuffer->bits_per_row[row], |
| 144 | + "Bad message in row %d need %d bits got %d", |
| 145 | + row, TPMS_TYREGUARD400_MESSAGE_BITLEN, bitbuffer->bits_per_row[row]); |
| 146 | + } |
| 147 | + continue; // DECODE_ABORT_LENGTH |
| 148 | + } |
| 149 | + |
| 150 | + unsigned bitpos = 0; |
| 151 | + |
| 152 | + // Find a preamble with enough bits after it that it could be a complete packet |
| 153 | + while ((bitpos = bitbuffer_search(bitbuffer, row, bitpos, tyreguard_frame_sync, 28)) + TPMS_TYREGUARD400_MESSAGE_BITLEN <= |
| 154 | + bitbuffer->bits_per_row[row]) { |
| 155 | + |
| 156 | + if (decoder->verbose >= 2) { |
| 157 | + decoder_logf_bitrow(decoder, 2, __func__, bitbuffer->bb[row], bitbuffer->bits_per_row[row], |
| 158 | + "Find bitpos with preamble row %d at %u", row, bitpos); |
| 159 | + } |
| 160 | + |
| 161 | + ret = tpms_tyreguard400_decode(decoder, bitbuffer, row, bitpos); |
| 162 | + if (ret > 0) |
| 163 | + events += ret; |
| 164 | + |
| 165 | + bitpos += TPMS_TYREGUARD400_MESSAGE_BITLEN; |
| 166 | + } |
| 167 | + } |
| 168 | + // (Only) for future regression tests. |
| 169 | + if ((decoder->verbose >= 3) & (events == 0)) { |
| 170 | + decoder_logf(decoder, 3, __func__, "Bad transmission"); |
| 171 | + } |
| 172 | + |
| 173 | + return events > 0 ? events : ret; |
| 174 | +} |
| 175 | + |
| 176 | +static char *output_fields[] = { |
| 177 | + "model", |
| 178 | + "type", |
| 179 | + "id", |
| 180 | +// "flags", |
| 181 | + "pressure_kPa", |
| 182 | + "temperature_C", |
| 183 | + "peering_request", |
| 184 | + "leaking", |
| 185 | + "ack_leaking", |
| 186 | +// "add256", |
| 187 | +// "add512", |
| 188 | +// "add1024", |
| 189 | +// "battery_ok", |
| 190 | + "mic", |
| 191 | + NULL, |
| 192 | +}; |
| 193 | + |
| 194 | +r_device tpms_tyreguard400 = { |
| 195 | + .name = "TyreGuard 400 TPMS", |
| 196 | + .modulation = OOK_PULSE_MANCHESTER_ZEROBIT, |
| 197 | + .short_width = 100, |
| 198 | + .long_width = 100, |
| 199 | + .gap_limit = 0, |
| 200 | + .reset_limit = 500, |
| 201 | + .decode_fn = &tpms_tyreguard400_callback, |
| 202 | + .fields = output_fields, |
| 203 | +}; |
0 commit comments