Преглед на файлове

View privdata. Oscilliscope alike view row change.

antirez преди 3 години
родител
ревизия
2459e55db2
променени са 6 файла, в които са добавени 78 реда и са изтрити 24 реда
  1. 4 1
      app.c
  2. 12 4
      app.h
  3. 7 4
      protocols/b4b1.c
  4. 8 2
      protocols/keeloq.c
  5. 12 6
      signal.c
  6. 35 7
      view_info.c

+ 4 - 1
app.c

@@ -100,6 +100,7 @@ static void app_switch_view(ProtoViewApp *app, SwitchViewDirection dir) {
      * the main subview of the view. When re re-enter it we want to see
      * the main thing. */
     app->current_subview[old] = 0;
+    memset(app->view_privdata,0,PROTOVIEW_VIEW_PRIVDATA_LEN);
 }
 
 /* Allocate the application state and initialize a number of stuff.
@@ -125,6 +126,8 @@ ProtoViewApp* protoview_app_alloc() {
     app->current_view = ViewRawPulses;
     for (int j = 0; j < ViewLast; j++) app->current_subview[j] = 0;
     app->direct_sampling_enabled = false;
+    app->view_privdata = malloc(PROTOVIEW_VIEW_PRIVDATA_LEN);
+    memset(app->view_privdata,0,PROTOVIEW_VIEW_PRIVDATA_LEN);
 
     // Signal found and visualization defaults
     app->signal_bestlen = 0;
@@ -134,7 +137,7 @@ ProtoViewApp* protoview_app_alloc() {
     app->signal_offset = 0;
     app->msg_info = NULL;
 
-    //init Worker & Protocol
+    // Init Worker & Protocol
     app->txrx = malloc(sizeof(ProtoViewTxRx));
 
     /* Setup rx worker and environment. */

+ 12 - 4
app.h

@@ -23,8 +23,9 @@
 #include "app_buffer.h"
 
 #define TAG "ProtoView"
-#define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100
-#define BITMAP_SEEK_NOT_FOUND UINT32_MAX
+#define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100 // 100us is 1 pixel by default
+#define BITMAP_SEEK_NOT_FOUND UINT32_MAX // Returned by function as sentinel
+#define PROTOVIEW_VIEW_PRIVDATA_LEN 32 // View specific private data len
 
 #define DEBUG_MSG 1
 
@@ -100,14 +101,14 @@ typedef struct ProtoViewMsgInfo {
     /* 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. */
+    uint32_t pulses_count;      /* 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
+                                   is 'pulses_count/8' rounded to the next
                                    integer. */
 } ProtoViewMsgInfo;
 
@@ -133,6 +134,13 @@ struct ProtoViewApp {
     ProtoViewMsgInfo *msg_info; /* Decoded message info if not NULL. */
     bool direct_sampling_enabled; /* This special view needs an explicit
                                      acknowledge to work. */
+    void *view_privdata;    /* This is a piece of memory of total size
+                               PROTOVIEW_VIEW_PRIVDATA_LEN that it is
+                               initialized to zero when we switch to
+                               a a new view. While the view we are using
+                               is the same, it can be used by the view to
+                               store any kind of info inside, just casting
+                               the pointer to a few specific-data structure. */
 
     /* Raw view apps state. */
     uint32_t us_scale;       /* microseconds per pixel. */

+ 7 - 4
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, start;
+    uint32_t off;
     int j;
     for (j = 0; j < 3; j++) {
         off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]);
@@ -25,7 +25,9 @@ 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;
+    info->start_off = off;
+
+    // Seek data setction. Why -1? Last bit is data.
     off += strlen(sync_patterns[j])-1;
 
     uint8_t d[3]; /* 24 bits of data. */
@@ -34,10 +36,11 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
 
     if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu",decoded);
     if (decoded != 24) return false;
+
+    off += 24*4; // seek to end symbol offset to calculate the length.
+    info->pulses_count = off - info->start_off;
     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->start_off = start;
-    info->pulses_len = 4*24;
     return true;
 }
 

+ 8 - 2
protocols/keeloq.c

@@ -32,9 +32,11 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     const char *sync_pattern = "101010101010101010101010" "0000";
     uint8_t sync_len = 24+4;
     if (numbits-sync_len+sync_len < 3*66) return false;
-    uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern);
+    uint32_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern);
     if (off == BITMAP_SEEK_NOT_FOUND) return false;
-    off += sync_len;
+
+    info->start_off = off;
+    off += sync_len; // Seek start of message.
 
     /* Now there is half the gap left, but we allow from 3 to 7, instead of 5
      * symbols of gap, to avoid missing the signal for a matter of wrong
@@ -54,6 +56,10 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     FURI_LOG_E(TAG, "Keeloq decoded bits: %lu", decoded);
 
     if (decoded < 66) return false; /* Require the full 66 bits. */
+
+    off += decoded+66*3; // Seek end to compute total length.
+    info->pulses_count = off - info->start_off;
+
     bitmap_reverse_bytes(raw,sizeof(raw)); /* Keeloq is LSB first. */
 
     int buttons = raw[7]>>4;

+ 12 - 6
signal.c

@@ -136,7 +136,6 @@ void scan_for_signal(ProtoViewApp *app) {
                                        than a few samples it's very easy to
                                        mistake noise for signal. */
 
-    ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo));
     uint32_t i = 0;
 
     while (i < copy->total-1) {
@@ -144,10 +143,15 @@ void scan_for_signal(ProtoViewApp *app) {
 
         /* For messages that are long enough, attempt decoding. */
         if (thislen > minlen) {
+            /* Allocate the message information that some decoder may
+             * fill, in case it is able to decode a message. */
+            ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo));
             init_msg_info(info,app);
+
             uint32_t saved_idx = copy->idx; /* Save index, see later. */
+
             /* decode_signal() expects the detected signal to start
-             * from index .*/
+             * from index zero .*/
             raw_samples_center(copy,i);
             bool decoded = decode_signal(copy,thislen,info);
             copy->idx = saved_idx; /* Restore the index as we are scanning
@@ -175,6 +179,8 @@ void scan_for_signal(ProtoViewApp *app) {
                 else if (DetectedSamples->short_pulse_dur < 145)
                     app->us_scale = 30;
             } else {
+                /* If the structure was not filled, discard it. Otherwise
+                 * now the owner is app->msg_info. */
                 free_msg_info(info);
             }
         }
@@ -571,13 +577,13 @@ bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
         /* 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.
+         * pulses_count will be set to zero. */
+        if (info->pulses_count) {
+            info->bits_bytes = (info->pulses_count+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);
+                        info->pulses_count);
         }
     }
     free(bitmap);

+ 35 - 7
view_info.c

@@ -9,6 +9,14 @@ enum {
     SubViewInfoLast, /* Just a sentinel. */
 };
 
+/* Our view private data. */
+typedef struct {
+    /* Our save view displays an oscilloscope-alike resampled signal,
+     * so that the user can see what they are saving. With left/right
+     * you can move to next rows. Here we store where we are. */
+    uint32_t signal_display_start_row;
+} InfoViewPrivData;
+
 /* Render the view with the detected message information. */
 static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) {
     /* Protocol name as title. */
@@ -33,22 +41,31 @@ static void render_subview_main(Canvas *const canvas, ProtoViewApp *app) {
 
 /* Render view with save option. */
 static void render_subview_save(Canvas *const canvas, ProtoViewApp *app) {
+    InfoViewPrivData *privdata = app->view_privdata;
+
+    /* Display our signal in digital form: here we don't show the
+     * signal with the exact timing of the received samples, but as it
+     * is in its logic form, in exact multiples of the short pulse length. */
     uint8_t rows = 6;
-    uint8_t rowheight = 8;
+    uint8_t rowheight = 11;
     uint8_t bitwidth = 4;
     uint8_t bitheight = 5;
-    uint32_t idx = 0;
+    uint32_t idx = privdata->signal_display_start_row * (128/4);
     bool prevbit = false;
-    for (uint8_t y = bitheight; y < rows*rowheight; y += rowheight) {
+    for (uint8_t y = bitheight+12; y <= rows*rowheight; y += rowheight) {
         for (uint8_t x = 5; x < 128; x += 4) {
             bool bit = bitmap_get(app->msg_info->bits,
                                   app->msg_info->bits_bytes,idx++);
-            uint8_t prevy = y + prevbit*bitheight - 1;
-            uint8_t thisy = y + bit*bitheight - 1;
+            uint8_t prevy = y + prevbit*(bitheight*-1) - 1;
+            uint8_t thisy = y + bit*(bitheight*-1) - 1;
             canvas_draw_line(canvas,x,prevy,x,thisy);
             canvas_draw_line(canvas,x,thisy,x+bitwidth-1,thisy);
+            prevbit = bit;
         }
     }
+
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 6, "ok: save, < >: slide rows");
 }
 
 /* Render the selected subview of this view. */
@@ -69,10 +86,21 @@ void render_view_info(Canvas *const canvas, ProtoViewApp *app) {
 /* Handle input for the info view. */
 void process_input_info(ProtoViewApp *app, InputEvent input) {
     if (process_subview_updown(app,input,SubViewInfoLast)) return;
-    if (input.type == InputTypeShort) {
-        if (input.key == InputKeyOk) {
+    InfoViewPrivData *privdata = app->view_privdata;
+    int subview = get_current_subview(app);
+
+    /* Main subview. */
+    if (subview == SubViewInfoMain) {
+        if (input.type == InputTypeShort && input.key == InputKeyOk) {
             /* Reset the current sample to capture the next. */
             reset_current_signal(app);
         }
+    } else if (subview == SubViewInfoSave) {
+    /* Save subview. */
+        if (input.type == InputTypePress && input.key == InputKeyRight) {
+            privdata->signal_display_start_row++;
+        } else if (input.type == InputTypePress && input.key == InputKeyLeft) {
+            privdata->signal_display_start_row--;
+        }
     }
 }