schrader.c 2.3 KB

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