Skip to content

Commit

Permalink
Up/down change scale. Better short pulse computation.
Browse files Browse the repository at this point in the history
  • Loading branch information
antirez committed Dec 29, 2022
1 parent a81c90b commit 860879e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 22 deletions.
2 changes: 0 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -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.

- Min pulse length shown in the UI should be the average of the shortest class instead of the shortest found in the sequence.

Features
========

Expand Down
58 changes: 38 additions & 20 deletions app.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ extern const SubGhzProtocolRegistry protoview_protocol_registry;
*
* The 'idx' argument is the first sample to render in the circular
* 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);

int rows = 8;
uint32_t time_per_pixel = 100;
uint32_t time_per_pixel = app->us_scale;
bool level = 0;
uint32_t dur = 0;
for (int row = 0; row < rows ; row++) {
Expand Down Expand Up @@ -71,15 +71,15 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
} classes[SEARCH_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. */
uint32_t len = 0; /* Observed len of coherent samples. */
s->short_pulse_dur = 0;
for (uint32_t j = idx; j < idx+100; j++) {
bool level;
uint32_t 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
* can populate a new (yet empty) class. */
Expand All @@ -88,7 +88,7 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
if (classes[k].count[level] == 0) {
classes[k].dur[level] = dur;
classes[k].count[level] = 1;
break;
break; /* Sample accepted. */
} else {
uint32_t classavg = classes[k].dur[level];
uint32_t count = classes[k].count[level];
Expand All @@ -103,22 +103,30 @@ uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
classavg = ((classavg * count) + dur) / (count+1);
classes[k].dur[level] = classavg;
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++;
}

/* 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;
}

Expand All @@ -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
* 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++) {
uint32_t thislen = search_coherent_signal(copy,i);
Expand All @@ -143,7 +153,8 @@ void scan_for_signal(ProtoViewApp *app) {
raw_samples_copy(DetectedSamples,copy);
DetectedSamples->idx = (DetectedSamples->idx+i)%
DetectedSamples->total;
FURI_LOG_E(TAG, "Displayed sample updated");
FURI_LOG_E(TAG, "Displayed sample updated (%d samples)",
(int)thislen);
}
}
raw_samples_free(copy);
Expand Down Expand Up @@ -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) {
UNUSED(ctx);
ProtoViewApp *app = ctx;

/* Clear screen. */
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, 0, 0, 127, 63);

/* Show signal. */
render_signal(canvas, DetectedSamples, 0);
render_signal(app, canvas, DetectedSamples, 0);

/* Show signal information. */
char buf[64];
Expand Down Expand Up @@ -223,8 +234,9 @@ ProtoViewApp* protoview_app_alloc() {
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));

// Signal found
// Signal found and visualization defaults
app->signal_bestlen = 0;
app->us_scale = 100;

//init Worker & Protocol
app->txrx = malloc(sizeof(ProtoViewTxRx));
Expand Down Expand Up @@ -306,12 +318,18 @@ int32_t protoview_app_entry(void* p) {
while(app->running) {
FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
if (qstat == FuriStatusOk) {
uint32_t scale_step = app->us_scale > 50 ? 50 : 10;
if (input.key == InputKeyBack) {
app->running = 0;
} else if (input.key == InputKeyOk) {
app->signal_bestlen = 0;
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);
} else {
static int c = 0;
Expand Down
1 change: 1 addition & 0 deletions app.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct ProtoViewApp {
SubGhzSetting *setting;
int running; /* Once false exists the app. */
uint32_t signal_bestlen; /* Longest coherent signal observed so far. */
uint32_t us_scale; /* microseconds per pixel. */
};

void radio_begin(ProtoViewApp* app);
Expand Down

0 comments on commit 860879e

Please sign in to comment.