schrader.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
  2. * See the LICENSE file for information about the license.
  3. *
  4. * Schrader TPMS. Usually 443.92 Mhz OOK, 120us pulse len.
  5. *
  6. * 500us high pulse + Preamble + Manchester coded bits where:
  7. * 1 = 10
  8. * 0 = 01
  9. *
  10. * 60 bits of data total (first 4 nibbles is the preamble, 0xF).
  11. *
  12. * Used in FIAT-Chrysler, Mercedes, ... */
  13. #include "../../app.h"
  14. #define USE_TEST_VECTOR 0
  15. static const char *test_vector = "000000111101010101011010010110010110101001010110100110011001100101010101011010100110100110011010101010101010101010101010101010101010101010101010";
  16. static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) {
  17. if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */
  18. bitmap_set_pattern(bits,numbytes,0,test_vector);
  19. numbits = strlen(test_vector);
  20. }
  21. if (numbits < 64) return false; /* Preamble + data. */
  22. const char *sync_pattern = "1111010101" "01011010";
  23. uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern);
  24. if (off == BITMAP_SEEK_NOT_FOUND) return false;
  25. FURI_LOG_E(TAG, "Schrader TPMS gap+preamble found");
  26. info->start_off = off;
  27. off += 10; /* Skip just the long pulse and the first 3 bits of sync, so
  28. that we have the first byte of data with the sync nibble
  29. 0011 = 0x3. */
  30. uint8_t raw[8];
  31. uint8_t id[4];
  32. uint32_t decoded =
  33. convert_from_line_code(raw,sizeof(raw),bits,numbytes,off,
  34. "01","10"); /* Manchester code. */
  35. FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded);
  36. if (decoded < 64) return false; /* Require the full 8 bytes. */
  37. raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation.
  38. uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7);
  39. if (cksum != raw[7]) {
  40. FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch");
  41. return false;
  42. }
  43. info->pulses_count = (off+8*8*2) - info->start_off;
  44. float kpa = (float)raw[5]*2.5;
  45. int temp = raw[6]-50;
  46. id[0] = raw[1]&7;
  47. id[1] = raw[2];
  48. id[2] = raw[3];
  49. id[3] = raw[4];
  50. fieldset_add_bytes(info->fieldset,"Tire ID",id,4*2);
  51. fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2);
  52. fieldset_add_int(info->fieldset,"Temperature C",temp,8);
  53. return true;
  54. }
  55. ProtoViewDecoder SchraderTPMSDecoder = {
  56. .name = "Schrader TPMS",
  57. .decode = decode,
  58. .get_fields = NULL,
  59. .build_message = NULL
  60. };