فهرست منبع

Renault TPMS encoder.

antirez 3 سال پیش
والد
کامیت
2f003976fc
3فایلهای تغییر یافته به همراه82 افزوده شده و 3 حذف شده
  1. 56 3
      protocols/tpms/renault.c
  2. 25 0
      raw_samples.c
  3. 1 0
      raw_samples.h

+ 56 - 3
protocols/tpms/renault.c

@@ -50,18 +50,71 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 
     info->pulses_count = (off+8*9*2) - info->start_off;
 
-    float kpa = 0.75 *((uint32_t)((raw[0]&3)<<8) | raw[1]);
+    uint8_t flags = raw[0]>>2;
+    float kpa = 0.75 * ((uint32_t)((raw[0]&3)<<8) | raw[1]);
     int temp = raw[2]-30;
 
     fieldset_add_bytes(info->fieldset,"Tire ID",raw+3,3*2);
     fieldset_add_float(info->fieldset,"Pressure kpa",kpa,2);
     fieldset_add_int(info->fieldset,"Temperature C",temp,8);
+    fieldset_add_hex(info->fieldset,"Flags",flags,6);
+    fieldset_add_bytes(info->fieldset,"Unknown1",raw+6,2);
+    fieldset_add_bytes(info->fieldset,"Unknown2",raw+7,2);
     return true;
 }
 
+/* Give fields and defaults for the signal creator. */
+static void get_fields(ProtoViewFieldSet *fieldset) {
+    uint8_t default_id[3]= {0xAB, 0xCD, 0xEF};
+    fieldset_add_bytes(fieldset,"Tire ID",default_id,3*2);
+    fieldset_add_float(fieldset,"Pressure kpa",123,2);
+    fieldset_add_int(fieldset,"Temperature C",20,8);
+    // We don't know what flags are, but 1B is a common value.
+    fieldset_add_hex(fieldset,"Flags",0x1b,6);
+    fieldset_add_bytes(fieldset,"Unknown1",(uint8_t*)"\xff",2);
+    fieldset_add_bytes(fieldset,"Unknown2",(uint8_t*)"\xff",2);
+}
+
+/* Create a Renault TPMS signal, according to the fields provided. */
+static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fieldset)
+{
+    uint32_t te = 50; // Short pulse duration in microseconds.
+
+    // Preamble + sync
+    const char *psync = "01010101010101010101010101010110";
+    const char *p = psync;
+    while(*p) {
+        raw_samples_add_or_update(samples,*p == '1',te);
+        p++;
+    }
+
+    // Data, 9 bytes
+    uint8_t data[9] = {0};
+    unsigned int raw_pressure = fieldset->fields[1]->fvalue * 4 / 3;
+    data[0] = fieldset->fields[3]->uvalue << 2; // Flags
+    data[0] |= (raw_pressure >> 8) & 3; // Pressure kpa high 2 bits
+    data[1] = raw_pressure & 0xff;      // Pressure kpa low 8 bits
+    data[2] = fieldset->fields[2]->value + 30; // Temperature C
+    memcpy(data+3,fieldset->fields[0]->bytes,6); // ID, 24 bits.
+    data[6] = fieldset->fields[4]->bytes[0];  // Unknown 1
+    data[7] = fieldset->fields[5]->bytes[0];  // Unknown 2
+    data[8] = crc8(data,8,0,7);
+
+    // Generate Manchester code for each bit
+    for (uint32_t j = 0; j < 9*8; j++) {
+        if (bitmap_get(data,sizeof(data),j)) {
+            raw_samples_add_or_update(samples,true,te);
+            raw_samples_add_or_update(samples,false,te);
+        } else {
+            raw_samples_add_or_update(samples,false,te);
+            raw_samples_add_or_update(samples,true,te);
+        }
+    }
+}
+
 ProtoViewDecoder RenaultTPMSDecoder = {
     .name = "Renault TPMS",
     .decode = decode,
-    .get_fields = NULL,
-    .build_message = NULL
+    .get_fields = get_fields,
+    .build_message = build_message
 };

+ 25 - 0
raw_samples.c

@@ -48,6 +48,31 @@ void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) {
     furi_mutex_release(s->mutex);
 }
 
+/* This is like raw_samples_add(), however in case a sample of the
+ * same level of the previous one is added, the duration of the last
+ * sample is updated instead. Needed mainly for the decoders build_message()
+ * methods: it is simpler to write an encoder of a signal like that,
+ * just creating messages piece by piece.
+ *
+ * This function is a bit slower so the internal data sampling should
+ * be performed with raw_samples_add(). */
+void raw_samples_add_or_update(RawSamplesBuffer *s, bool level, uint32_t dur) {
+    furi_mutex_acquire(s->mutex,FuriWaitForever);
+    uint32_t previdx = (s->idx-1) % RAW_SAMPLES_NUM;
+    if (s->samples[previdx].level == level &&
+        s->samples[previdx].dur != 0)
+    {
+        /* Update the last sample: it has the same level. */
+        s->samples[previdx].dur += dur;
+    } else {
+        /* Add a new sample. */
+        s->samples[s->idx].level = level;
+        s->samples[s->idx].dur = dur;
+        s->idx = (s->idx+1) % RAW_SAMPLES_NUM;
+    }
+    furi_mutex_release(s->mutex);
+}
+
 /* Get the sample from the buffer. It is possible to use out of range indexes
  * as 'idx' because the modulo operation will rewind back from the start. */
 void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur)

+ 1 - 0
raw_samples.h

@@ -26,6 +26,7 @@ RawSamplesBuffer *raw_samples_alloc(void);
 void raw_samples_reset(RawSamplesBuffer *s);
 void raw_samples_center(RawSamplesBuffer *s, uint32_t offset);
 void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur);
+void raw_samples_add_or_update(RawSamplesBuffer *s, bool level, uint32_t dur);
 void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur);
 void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src);
 void raw_samples_free(RawSamplesBuffer *s);