schrader.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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. uint32_t decoded =
  29. convert_from_line_code(raw,sizeof(raw),bits,numbytes,off,
  30. "01","10"); /* Manchester code. */
  31. FURI_LOG_E(TAG, "Schrader TPMS decoded bits: %lu", decoded);
  32. if (decoded < 64) return false; /* Require the full 8 bytes. */
  33. raw[0] |= 0xf0; // Fix the preamble nibble for checksum computation.
  34. uint8_t cksum = crc8(raw,sizeof(raw)-1,0xf0,0x7);
  35. if (cksum != raw[7]) {
  36. FURI_LOG_E(TAG, "Schrader TPMS checksum mismatch");
  37. return false;
  38. }
  39. info->pulses_count = (off+8*8*2) - info->start_off;
  40. float kpa = (float)raw[5]*2.5;
  41. int temp = raw[6]-50;
  42. snprintf(info->name,sizeof(info->name),"%s","Schrader TPMS");
  43. snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X",
  44. raw[0],raw[1],raw[2],raw[3],raw[4],raw[5],
  45. raw[6],raw[7]);
  46. snprintf(info->info1,sizeof(info->info1),"Tire ID %01X%02X%02X%02X",
  47. raw[1]&7,raw[2],raw[3],raw[4]); /* Only 28 bits of ID, not 32. */
  48. snprintf(info->info2,sizeof(info->info2),"Pressure %.2f kpa", (double)kpa);
  49. snprintf(info->info3,sizeof(info->info3),"Temperature %d C", temp);
  50. return true;
  51. }
  52. ProtoViewDecoder SchraderTPMSDecoder = {
  53. "Schrader TPMS", decode
  54. };