Переглянути джерело

Up/down change scale. Better short pulse computation.

antirez 3 роки тому
батько
коміт
860879eece
3 змінених файлів з 39 додано та 22 видалено
  1. 0 2
      TODO
  2. 38 20
      app.c
  3. 1 0
      app.h

+ 0 - 2
TODO

@@ -3,8 +3,6 @@ Core improvements
 
 
 - Detection of non Manchester and non RZ encoded signals. Not sure if there are any signals that are not self clocked widely used in RF. Note that the current approach already detects encodings using short high + long low and long high + short low to encode 0 and 1. In addition to the current classifier, it is possible to add one that checks for a sequence of pulses that are all multiples of some base length. This should detect, for instance, even NRZ encodings where 1 and 0 are just clocked as they are.
 - Detection of non Manchester and non RZ encoded signals. Not sure if there are any signals that are not self clocked widely used in RF. Note that the current approach already detects encodings using short high + long low and long high + short low to encode 0 and 1. In addition to the current classifier, it is possible to add one that checks for a sequence of pulses that are all multiples of some base length. This should detect, for instance, even NRZ encodings where 1 and 0 are just clocked as they are.
 
 
-- Min pulse length shown in the UI should be the average of the shortest class instead of the shortest found in the sequence.
-
 Features
 Features
 ========
 ========
 
 

+ 38 - 20
app.c

@@ -21,11 +21,11 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry;
  *
  *
  * The 'idx' argument is the first sample to render in the circular
  * The 'idx' argument is the first sample to render in the circular
  * buffer. */
  * buffer. */
-void render_signal(Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) {
+void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) {
     canvas_set_color(canvas, ColorBlack);
     canvas_set_color(canvas, ColorBlack);
 
 
     int rows = 8;
     int rows = 8;
-    uint32_t time_per_pixel = 100;
+    uint32_t time_per_pixel = app->us_scale;
     bool level = 0;
     bool level = 0;
     uint32_t dur = 0;
     uint32_t dur = 0;
     for (int row = 0; row < rows ; row++) {
     for (int row = 0; row < rows ; row++) {
@@ -71,7 +71,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
     } classes[SEARCH_CLASSES];
     } classes[SEARCH_CLASSES];
 
 
     memset(classes,0,sizeof(classes));
     memset(classes,0,sizeof(classes));
-    uint32_t minlen = 80, maxlen = 4000; /* Depends on data rate, here we
+    uint32_t minlen = 40, maxlen = 4000; /* Depends on data rate, here we
                                             allow for high and low. */
                                             allow for high and low. */
     uint32_t len = 0; /* Observed len of coherent samples. */
     uint32_t len = 0; /* Observed len of coherent samples. */
     s->short_pulse_dur = 0;
     s->short_pulse_dur = 0;
@@ -79,7 +79,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
         bool level;
         bool level;
         uint32_t dur;
         uint32_t dur;
         raw_samples_get(s, j, &level, &dur);
         raw_samples_get(s, j, &level, &dur);
-        if (dur < minlen || dur > maxlen) return len;
+        if (dur < minlen || dur > maxlen) break; /* return. */
 
 
         /* Let's see if it matches a class we already have or if we
         /* Let's see if it matches a class we already have or if we
          * can populate a new (yet empty) class. */
          * can populate a new (yet empty) class. */
@@ -88,7 +88,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
             if (classes[k].count[level] == 0) {
             if (classes[k].count[level] == 0) {
                 classes[k].dur[level] = dur;
                 classes[k].dur[level] = dur;
                 classes[k].count[level] = 1;
                 classes[k].count[level] = 1;
-                break;
+                break; /* Sample accepted. */
             } else {
             } else {
                 uint32_t classavg = classes[k].dur[level];
                 uint32_t classavg = classes[k].dur[level];
                 uint32_t count = classes[k].count[level];
                 uint32_t count = classes[k].count[level];
@@ -103,22 +103,30 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
                     classavg = ((classavg * count) + dur) / (count+1);
                     classavg = ((classavg * count) + dur) / (count+1);
                     classes[k].dur[level] = classavg;
                     classes[k].dur[level] = classavg;
                     classes[k].count[level]++;
                     classes[k].count[level]++;
-                    break;
+                    break; /* Sample accepted. */
                 }
                 }
             }
             }
         }
         }
 
 
-        if (k == SEARCH_CLASSES) { /* No match, return. */
-            return len;
-        } else {
-            /* Update the buffer setting the shortest pulse we found
-             * among the three classes. This will be used when scaling
-             * for visualization. */
-            if (s->short_pulse_dur == 0 || dur < s->short_pulse_dur)
-                s->short_pulse_dur = dur;
-        }
+        if (k == SEARCH_CLASSES) break; /* No match, return. */
+
+        /* If we are here, we accepted this sample. Try with the next
+         * one. */
         len++;
         len++;
     }
     }
+
+    /* Update the buffer setting the shortest pulse we found
+     * among the three classes. This will be used when scaling
+     * for visualization. */
+    for (int j = 0; j < SEARCH_CLASSES; j++) {
+        for (int level = 0; level < 2; level++) {
+            if (s->short_pulse_dur == 0 ||
+                s->short_pulse_dur > classes[j].dur[level])
+            {
+                s->short_pulse_dur = classes[j].dur[level];
+            }
+        }
+    }
     return len;
     return len;
 }
 }
 
 
@@ -134,7 +142,9 @@ void scan_for_signal(ProtoViewApp *app) {
 
 
     /* Try to seek on data that looks to have a regular high low high low
     /* Try to seek on data that looks to have a regular high low high low
      * pattern. */
      * pattern. */
-    uint32_t minlen = 10;           /* Min run of coherent samples. */
+    uint32_t minlen = 13;           /* Min run of coherent samples. Up to
+                                       12 samples it's very easy to mistake
+                                       noise for signal. */
 
 
     for (uint32_t i = 0; i < copy->total-1; i++) {
     for (uint32_t i = 0; i < copy->total-1; i++) {
         uint32_t thislen = search_coherent_signal(copy,i);
         uint32_t thislen = search_coherent_signal(copy,i);
@@ -143,7 +153,8 @@ void scan_for_signal(ProtoViewApp *app) {
             raw_samples_copy(DetectedSamples,copy);
             raw_samples_copy(DetectedSamples,copy);
             DetectedSamples->idx = (DetectedSamples->idx+i)%
             DetectedSamples->idx = (DetectedSamples->idx+i)%
                                    DetectedSamples->total;
                                    DetectedSamples->total;
-            FURI_LOG_E(TAG, "Displayed sample updated");
+            FURI_LOG_E(TAG, "Displayed sample updated (%d samples)",
+                (int)thislen);
         }
         }
     }
     }
     raw_samples_free(copy);
     raw_samples_free(copy);
@@ -177,14 +188,14 @@ void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const cha
 }
 }
 
 
 static void render_callback(Canvas *const canvas, void *ctx) {
 static void render_callback(Canvas *const canvas, void *ctx) {
-    UNUSED(ctx);
+    ProtoViewApp *app = ctx;
 
 
     /* Clear screen. */
     /* Clear screen. */
     canvas_set_color(canvas, ColorWhite);
     canvas_set_color(canvas, ColorWhite);
     canvas_draw_box(canvas, 0, 0, 127, 63);
     canvas_draw_box(canvas, 0, 0, 127, 63);
 
 
     /* Show signal. */
     /* Show signal. */
-    render_signal(canvas, DetectedSamples, 0);
+    render_signal(app, canvas, DetectedSamples, 0);
 
 
     /* Show signal information. */
     /* Show signal information. */
     char buf[64];
     char buf[64];
@@ -223,8 +234,9 @@ ProtoViewApp* protoview_app_alloc() {
     gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
     gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
     app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
     app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
 
 
-    // Signal found
+    // Signal found and visualization defaults
     app->signal_bestlen = 0;
     app->signal_bestlen = 0;
+    app->us_scale = 100;
 
 
     //init Worker & Protocol
     //init Worker & Protocol
     app->txrx = malloc(sizeof(ProtoViewTxRx));
     app->txrx = malloc(sizeof(ProtoViewTxRx));
@@ -306,12 +318,18 @@ int32_t protoview_app_entry(void* p) {
     while(app->running) {
     while(app->running) {
         FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
         FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
         if (qstat == FuriStatusOk) {
         if (qstat == FuriStatusOk) {
+            uint32_t scale_step = app->us_scale > 50 ? 50 : 10;
             if (input.key == InputKeyBack) {
             if (input.key == InputKeyBack) {
                 app->running = 0;
                 app->running = 0;
             } else if (input.key == InputKeyOk) {
             } else if (input.key == InputKeyOk) {
                 app->signal_bestlen = 0;
                 app->signal_bestlen = 0;
                 raw_samples_reset(DetectedSamples);
                 raw_samples_reset(DetectedSamples);
+            } else if (input.key == InputKeyDown) {
+                if (app->us_scale < 500) app->us_scale += scale_step;
+            } else if (input.key == InputKeyUp) {
+                if (app->us_scale > 10) app->us_scale -= scale_step;
             }
             }
+
             FURI_LOG_E(TAG, "Main Loop - Input: %u", input.key);
             FURI_LOG_E(TAG, "Main Loop - Input: %u", input.key);
         } else {
         } else {
             static int c = 0;
             static int c = 0;

+ 1 - 0
app.h

@@ -45,6 +45,7 @@ struct ProtoViewApp {
     SubGhzSetting *setting;
     SubGhzSetting *setting;
     int running;             /* Once false exists the app. */
     int running;             /* Once false exists the app. */
     uint32_t signal_bestlen; /* Longest coherent signal observed so far. */
     uint32_t signal_bestlen; /* Longest coherent signal observed so far. */
+    uint32_t us_scale;       /* microseconds per pixel. */
 };
 };
 
 
 void radio_begin(ProtoViewApp* app);
 void radio_begin(ProtoViewApp* app);