Просмотр исходного кода

Copy signal representation in the info structure.

antirez 3 лет назад
Родитель
Сommit
25bc81ac47
3 измененных файлов с 130 добавлено и 7 удалено
  1. 13 1
      app.h
  2. 4 2
      protocols/b4b1.c
  3. 113 4
      signal.c

+ 13 - 1
app.h

@@ -97,7 +97,18 @@ typedef struct ProtoViewMsgInfo {
     char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */
     char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */
     char info4[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 4. */
-    uint64_t len;       /* Bits consumed from the stream. */
+    /* Low level information of the detected signal: the following are filled
+     * by the protocol decoding function: */
+    uint32_t start_off;         /* Pulses start offset in the bitmap. */
+    uint32_t pulses_len;        /* Number of pulses of the full message. */
+    /* The following are passed already filled to the decoder. */
+    uint32_t short_pulse_dur;   /* Microseconds duration of the short pulse. */
+    /* The following are filled by ProtoView core after the decoder returned
+     * success. */
+    uint8_t *bits;              /* Bitmap with the signal. */
+    uint32_t bits_bytes;        /* Number of full bytes in the bitmap, that
+                                   is 'pulses_len/8' rounded to the next
+                                   integer. */
 } ProtoViewMsgInfo;
 
 struct ProtoViewApp {
@@ -162,6 +173,7 @@ void reset_current_signal(ProtoViewApp *app);
 void scan_for_signal(ProtoViewApp *app);
 bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos);
 void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val);
+void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff, uint8_t *s, uint32_t slen, uint32_t soff, uint32_t count);
 void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat);
 void bitmap_reverse_bytes(uint8_t *p, uint32_t len);
 bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits);

+ 4 - 2
protocols/b4b1.c

@@ -17,7 +17,7 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
         "1000000000000000000000000000000001", /* 32 zero bits. */
     };
 
-    uint32_t off;
+    uint32_t off, start;
     int j;
     for (j = 0; j < 3; j++) {
         off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]);
@@ -25,6 +25,7 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     }
     if (off == BITMAP_SEEK_NOT_FOUND) return false;
     if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu",off);
+    start = off;
     off += strlen(sync_patterns[j])-1;
 
     uint8_t d[3]; /* 24 bits of data. */
@@ -35,7 +36,8 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     if (decoded != 24) return false;
     snprintf(info->name,PROTOVIEW_MSG_STR_LEN,"PT/SC remote");
     snprintf(info->raw,PROTOVIEW_MSG_STR_LEN,"%02X%02X%02X",d[0],d[1],d[2]);
-    info->len = off+(4*24);
+    info->start_off = start;
+    info->pulses_len = 4*24;
     return true;
 }
 

+ 113 - 4
signal.c

@@ -4,7 +4,7 @@
 #include "app.h"
 
 bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info);
-void initialize_msg_info(ProtoViewMsgInfo *i);
+void initialize_msg_info(ProtoViewMsgInfo *i, ProtoViewApp *app);
 
 /* =============================================================================
  * Raw signal detection
@@ -143,7 +143,7 @@ void scan_for_signal(ProtoViewApp *app) {
 
         /* For messages that are long enough, attempt decoding. */
         if (thislen > minlen) {
-            initialize_msg_info(info);
+            initialize_msg_info(info,app);
             uint32_t saved_idx = copy->idx; /* Save index, see later. */
             /* decode_signal() expects the detected signal to start
              * from index .*/
@@ -215,6 +215,100 @@ bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos) {
     return (b[byte] & (1<<bit)) != 0;
 }
 
+/* Copy 'count' bits from the bitmap 's' of 'slen' total bytes, to the
+ * bitmap 'd' of 'dlen' total bytes. The bits are copied starting from
+ * offset 'soff' of the source bitmap to the offset 'doff' of the
+ * destination bitmap. */
+void bitmap_copy(uint8_t *d, uint32_t dlen, uint32_t doff,
+                 uint8_t *s, uint32_t slen, uint32_t soff,
+                 uint32_t count)
+{
+    /* If we are byte-aligned in both source and destination, use a fast
+     * path for the number of bytes we can consume this way. */
+    if ((doff & 7) == 0 && (soff & 7) == 0) {
+        uint32_t didx = doff/8;
+        uint32_t sidx = soff/8;
+        while(count > 8 && didx < dlen && sidx < slen) {
+            d[didx++] = s[sidx++];
+            count -= 8;
+        }
+        doff = didx * 8;
+        soff = sidx * 8;
+        /* Note that if we entered this path, the count at the end
+         * of the loop will be < 8. */
+    }
+
+    /* Copy the bits needed to reach an offset where we can copy
+     * two half bytes of src to a full byte of destination. */
+    while(count > 8 && (doff&7) != 0) {
+        bool bit = bitmap_get(s,slen,soff++);
+        bitmap_set(d,dlen,doff++,bit);
+        count--;
+    }
+
+    /* If we are here and count > 8, we have an offset that is byte aligned
+     * to the destination bitmap, but not aligned to the source bitmap.
+     * We can copy fast enough by shifting each two bytes of the original
+     * bitmap.
+     *
+     * This is how it works:
+     *
+     *  dst:
+     *  +--------+--------+--------+
+     *  | 0      | 1      | 2      |
+     *  |        |        |        | <- data to fill
+     *  +--------+--------+--------+
+     *            ^
+     *            |
+     *            doff = 8
+     *
+     *  src:
+     *  +--------+--------+--------+
+     *  | 0      | 1      | 2      |
+     *  |hellowod|ld!HELLO|WORLDS!!| <- data to copy
+     *  +--------+--------+--------+
+     *               ^
+     *               |
+     *               soff = 11
+     *
+     *  skew = 11%8 = 3
+     *  each destination byte in dst will receive:
+     *
+     *  dst[doff/8] = (src[soff/8] << skew) | (src[soff/8+1] >> (8-skew))
+     *
+     *  dstbyte = doff/8 = 8/8 = 1
+     *  srcbyte = soff/8 = 11/8 = 1
+     *
+     *  so dst[1] will get:
+     *  src[1] << 3, that is "ld!HELLO" << 3 = "HELLO..."
+     *      xored with
+     *  src[2] << 5, that is "WORLDS!!" >> 5 = ".....WOR"
+     *  That is "HELLOWOR"
+     */
+    if (count > 8) {
+        uint8_t skew = soff % 8; /* Don't worry, compiler will optimize. */
+        uint32_t didx = doff/8;
+        uint32_t sidx = soff/8;
+        while(count > 8 && didx < dlen && sidx < slen) {
+            d[didx] = ((s[sidx] << skew) |
+                       (s[sidx+1] >> (8-skew)));
+            sidx++;
+            didx++;
+            count -= 8;
+        }
+        soff = sidx*8;
+        doff = didx*8;
+    }
+
+    /* Here count is guaranteed to be < 8.
+     * Copy the final bits bit by bit. */
+    while(count) {
+        bool bit = bitmap_get(s,slen,soff++);
+        bitmap_set(d,dlen,doff++,bit);
+        count--;
+    }
+}
+
 /* We decode bits assuming the first bit we receive is the MSB
  * (see bitmap_set/get functions). Certain devices send data
  * encoded in the reverse way. */
@@ -410,8 +504,10 @@ ProtoViewDecoder *Decoders[] = {
 
 /* Reset the message info structure before passing it to the decoding
  * functions. */
-void initialize_msg_info(ProtoViewMsgInfo *i) {
+void initialize_msg_info(ProtoViewMsgInfo *i, ProtoViewApp *app) {
+    UNUSED(app);
     memset(i,0,sizeof(ProtoViewMsgInfo));
+    i->short_pulse_dur = DetectedSamples->short_pulse_dur;
 }
 
 /* This function is called when a new signal is detected. It converts it
@@ -458,7 +554,20 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
     if (!decoded) {
         FURI_LOG_E(TAG, "No decoding possible");
     } else {
-        FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3, info->info4);
+        FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s,%s]",
+            info->name, info->raw, info->info1, info->info2,
+            info->info3, info->info4);
+        /* The message was correctly decoded: fill the info structure
+         * with the decoded signal. The decoder may not implement offset/len
+         * filling of the structure. In such case we have no info and
+         * pulses_len will be set to zero. */
+        if (info->pulses_len) {
+            info->bits_bytes = (info->pulses_len+7)/8; // Round to full byte.
+            info->bits = malloc(info->bits_bytes);
+            bitmap_copy(info->bits,info->bits_bytes,0,
+                        bitmap,bitmap_size,info->start_off,
+                        info->pulses_len);
+        }
     }
     free(bitmap);
     return decoded;