Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-08-08 15:36:40 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2022-08-08 15:36:40 +0300
commit6062133170aac559fff037c8ff45d9e618030f12 (patch)
tree255374f7cab481324ee199e0a36e03db34df0985
parenta7316e7822900f1c4adb806b7b73b36f01937aa6 (diff)
New frequency analyzer
-rw-r--r--applications/subghz/helpers/subghz_frequency_analyzer_worker.c2
-rw-r--r--applications/subghz/scenes/subghz_scene_frequency_analyzer.c12
-rw-r--r--applications/subghz/views/subghz_frequency_analyzer.c216
3 files changed, 188 insertions, 42 deletions
diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c
index 10c5a9ea..0b91a1f4 100644
--- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c
+++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c
@@ -5,7 +5,7 @@
#define TAG "SubghzFrequencyAnalyzerWorker"
-#define SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD -95.0f
+#define SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD -97.0f
static const uint8_t subghz_preset_ook_58khz[][2] = {
{CC1101_MDMCFG4, 0b11110111}, // Rx BW filter is 58.035714kHz
diff --git a/applications/subghz/scenes/subghz_scene_frequency_analyzer.c b/applications/subghz/scenes/subghz_scene_frequency_analyzer.c
index b42acd4d..f067f985 100644
--- a/applications/subghz/scenes/subghz_scene_frequency_analyzer.c
+++ b/applications/subghz/scenes/subghz_scene_frequency_analyzer.c
@@ -17,16 +17,8 @@ void subghz_scene_frequency_analyzer_on_enter(void* context) {
}
bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent event) {
- SubGhz* subghz = context;
- if(event.type == SceneManagerEventTypeCustom) {
- if(event.event == SubGhzCustomEventSceneAnalyzerLock) {
- notification_message(subghz->notifications, &sequence_set_green_255);
- return true;
- } else if(event.event == SubGhzCustomEventSceneAnalyzerUnlock) {
- notification_message(subghz->notifications, &sequence_reset_rgb);
- return true;
- }
- }
+ UNUSED(context);
+ UNUSED(event);
return false;
}
diff --git a/applications/subghz/views/subghz_frequency_analyzer.c b/applications/subghz/views/subghz_frequency_analyzer.c
index d3f77315..fe297c5d 100644
--- a/applications/subghz/views/subghz_frequency_analyzer.c
+++ b/applications/subghz/views/subghz_frequency_analyzer.c
@@ -6,10 +6,31 @@
#include <furi_hal.h>
#include <input/input.h>
#include <notification/notification_messages.h>
+#include <gui/elements.h>
#include "../helpers/subghz_frequency_analyzer_worker.h"
#include <assets_icons.h>
+#define TAG "frequency_analyzer"
+
+#define RSSI_MIN -101
+#define RSSI_MAX -60
+#define RSSI_SCALE 2
+#define TRIGGER_STEP 1
+#define TRIGGER_MIN RSSI_MIN + RSSI_SCALE * 2
+
+static const NotificationSequence sequence_hw_blink = {
+ &message_blink_start_10,
+ &message_blink_set_color_cyan,
+ &message_do_not_reset,
+ NULL,
+};
+
+static const NotificationSequence sequence_hw_blink_stop = {
+ &message_blink_stop,
+ NULL,
+};
+
typedef enum {
SubGhzFrequencyAnalyzerStatusIDLE,
} SubGhzFrequencyAnalyzerStatus;
@@ -20,11 +41,19 @@ struct SubGhzFrequencyAnalyzer {
SubGhzFrequencyAnalyzerCallback callback;
void* context;
bool locked;
+ float rssi_last;
+ uint32_t frequency_last;
+ float trigger;
+ bool triggered;
+ NotificationApp* notifications;
};
typedef struct {
uint32_t frequency;
+ uint32_t frequency_last;
float rssi;
+ float rssi_last;
+ float trigger;
} SubGhzFrequencyAnalyzerModel;
void subghz_frequency_analyzer_set_callback(
@@ -37,33 +66,65 @@ void subghz_frequency_analyzer_set_callback(
subghz_frequency_analyzer->context = context;
}
-void subghz_frequency_analyzer_draw_rssi(Canvas* canvas, float rssi) {
- uint8_t x = 48;
- uint8_t y = 56;
- uint8_t column_number = 0;
+void subghz_frequency_analyzer_draw_rssi(
+ Canvas* canvas,
+ float rssi,
+ float rssi_last,
+ float trigger,
+ uint8_t x,
+ uint8_t y) {
+
+ // Current RSSI
if(rssi) {
- rssi = (rssi + 90) / 3;
+ rssi = (rssi - RSSI_MIN) / RSSI_SCALE;
+ if(rssi > 20) rssi = 20;
+ uint8_t column_number = 0;
for(size_t i = 1; i < (uint8_t)rssi; i++) {
- if(i > 20) break;
if(i % 4) {
column_number++;
canvas_draw_box(canvas, x + 2 * i, y - column_number, 2, 4 + column_number);
}
}
}
+
+ // Last RSSI
+ if(rssi_last) {
+ int max_x = (int)((rssi_last - RSSI_MIN) / RSSI_SCALE - 1) * 2;
+ //if(!(max_x % 8)) max_x -= 2;
+ int max_h = (int)((rssi_last - RSSI_MIN) / RSSI_SCALE - 1) + 4;
+ max_h -= (max_h / 4) + 3;
+ if(max_x > 38) max_h = 38;
+ if(max_h > 19) max_h = 19;
+ if(max_x >= 0 && max_h > 0) {
+ canvas_draw_line(canvas, x + max_x + 1, y - max_h, x + max_x + 1, y + 3);
+ }
+ }
+
+ // Trigger cursor
+ if(trigger >= RSSI_MIN + RSSI_SCALE * 2) {
+ trigger = (trigger - RSSI_MIN) / RSSI_SCALE;
+ uint8_t tr_x = x + 2 * trigger - 2;
+ canvas_draw_dot(canvas, tr_x, y + 4);
+ canvas_draw_line(canvas, tr_x - 1, y + 5, tr_x + 1, y + 5);
+ }
+
+ canvas_draw_line(canvas, x + 2, y + 3, x + 39, y + 3);
}
void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel* model) {
char buffer[64];
+ // Title
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 20, 8, "Frequency Analyzer");
- canvas_draw_str(canvas, 28, 60, "RSSI");
- subghz_frequency_analyzer_draw_rssi(canvas, model->rssi);
+ // RSSI
+ canvas_draw_str(canvas, 33, 62, "RSSI");
+ subghz_frequency_analyzer_draw_rssi(
+ canvas, model->rssi, model->rssi_last, model->trigger, 55, 58);
- //Frequency
+ // Frequency
canvas_set_font(canvas, FontBigNumbers);
snprintf(
buffer,
@@ -71,29 +132,113 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel
"%03ld.%03ld",
model->frequency / 1000000 % 1000,
model->frequency / 1000 % 1000);
- canvas_draw_str(canvas, 8, 35, buffer);
- canvas_draw_icon(canvas, 96, 24, &I_MHz_25x11);
+ canvas_draw_str(canvas, 8, 30, buffer);
+ canvas_draw_icon(canvas, 96, 19, &I_MHz_25x11);
+
+ // Last detected frequency
+ canvas_set_font(canvas, FontSecondary);
+ if(model->frequency_last) {
+ snprintf(
+ buffer,
+ sizeof(buffer),
+ "Last: %03ld.%03ld MHz",
+ model->frequency_last / 1000000 % 1000,
+ model->frequency_last / 1000 % 1000);
+ } else {
+ strcpy(buffer, "Last: ---.--- MHz");
+ }
+ canvas_draw_str(canvas, 9, 42, buffer);
+
+ // Buttons hint
+ elements_button_left(canvas, "T-");
+ elements_button_right(canvas, "T+");
}
bool subghz_frequency_analyzer_input(InputEvent* event, void* context) {
furi_assert(context);
+ SubGhzFrequencyAnalyzer* instance = context;
- if(event->key == InputKeyBack) {
- return false;
+ bool need_redraw = false;
+
+ if(event->key == InputKeyBack) return false;
+
+ if(((event->type == InputTypePress) || (event->type == InputTypeRepeat)) &&
+ ((event->key == InputKeyLeft) || (event->key == InputKeyRight))) {
+ // Trigger setup
+ switch(event->key) {
+ case InputKeyLeft:
+ instance->trigger -= TRIGGER_STEP;
+ if(instance->trigger < RSSI_MIN + RSSI_SCALE * 2) instance->trigger = TRIGGER_MIN;
+ break;
+ default:
+ case InputKeyRight:
+ if(instance->trigger < RSSI_MIN + RSSI_SCALE * 2)
+ instance->trigger = TRIGGER_MIN;
+ else
+ instance->trigger += TRIGGER_STEP;
+ if(instance->trigger > RSSI_MAX) instance->trigger = RSSI_MAX;
+ break;
+ }
+ if(instance->trigger > RSSI_MIN)
+ FURI_LOG_I(TAG, "trigger = %.1f", (double)instance->trigger);
+ else
+ FURI_LOG_I(TAG, "trigger disabled");
+ need_redraw = true;
+ }
+
+ if(need_redraw) {
+ SubGhzFrequencyAnalyzer* instance = context;
+ with_view_model(
+ instance->view, (SubGhzFrequencyAnalyzerModel * model) {
+ model->rssi_last = instance->rssi_last;
+ model->frequency_last = instance->frequency_last;
+ model->trigger = instance->trigger;
+ return true;
+ });
}
return true;
}
+uint32_t round_int(uint32_t value, uint8_t n) {
+ // Round value
+ uint8_t on = n;
+ while(n--) {
+ uint8_t i = value % 10;
+ value /= 10;
+ if(i >= 5) value++;
+ }
+ while(on--) value *= 10;
+ return value;
+}
+
void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, float rssi) {
+ furi_assert(context);
SubGhzFrequencyAnalyzer* instance = context;
+
if((rssi == 0.f) && (instance->locked)) {
- if(instance->callback) {
- instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context);
- }
- } else if((rssi != 0.f) && (!instance->locked)) {
- if(instance->callback) {
- instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context);
+ notification_message(instance->notifications, &sequence_hw_blink);
+ instance->triggered = false;
+ }
+
+ if((rssi != 0.f) && (frequency != 0)) {
+ // Threre is some signal
+ FURI_LOG_I(TAG, "rssi = %.2f, frequency = %d Hz", (double)rssi, frequency);
+ frequency = round_int(frequency, 3); // Round 299999990Hz to 300000000Hz
+ if((instance->trigger <= RSSI_MIN + RSSI_SCALE * 2) || (rssi >= instance->trigger)) {
+ if(!instance->triggered) {
+ // Triggered!
+ instance->triggered = true;
+ instance->rssi_last = rssi;
+ notification_message(instance->notifications, &sequence_hw_blink_stop);
+ notification_message(instance->notifications, &sequence_success);
+ FURI_LOG_D(TAG, "triggered");
+ }
+ // Update values
+ if(rssi > instance->rssi_last) instance->rssi_last = rssi;
+ instance->frequency_last = frequency;
+ } else {
+ instance->triggered = false;
}
}
@@ -101,7 +246,10 @@ void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency,
with_view_model(
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
model->rssi = rssi;
+ model->rssi_last = instance->rssi_last;
model->frequency = frequency;
+ model->frequency_last = instance->frequency_last;
+ model->trigger = instance->trigger;
return true;
});
}
@@ -110,6 +258,10 @@ void subghz_frequency_analyzer_enter(void* context) {
furi_assert(context);
SubGhzFrequencyAnalyzer* instance = context;
+ // Notifications
+ instance->notifications = furi_record_open(RECORD_NOTIFICATION);
+ notification_message(instance->notifications, &sequence_hw_blink);
+
//Start worker
instance->worker = subghz_frequency_analyzer_worker_alloc(instance->context);
@@ -120,10 +272,18 @@ void subghz_frequency_analyzer_enter(void* context) {
subghz_frequency_analyzer_worker_start(instance->worker);
+ instance->rssi_last = 0;
+ instance->frequency_last = 0;
+ instance->trigger = TRIGGER_MIN;
+ instance->triggered = false;
+
with_view_model(
instance->view, (SubGhzFrequencyAnalyzerModel * model) {
model->rssi = 0;
+ model->rssi_last = 0;
model->frequency = 0;
+ model->frequency_last = 0;
+ model->trigger = instance->trigger;
return true;
});
}
@@ -132,21 +292,21 @@ void subghz_frequency_analyzer_exit(void* context) {
furi_assert(context);
SubGhzFrequencyAnalyzer* instance = context;
- //Stop worker
+ // Stop blinking
+ notification_message(instance->notifications, &sequence_hw_blink_stop);
+
+ // Stop worker
if(subghz_frequency_analyzer_worker_is_running(instance->worker)) {
subghz_frequency_analyzer_worker_stop(instance->worker);
}
subghz_frequency_analyzer_worker_free(instance->worker);
- with_view_model(
- instance->view, (SubGhzFrequencyAnalyzerModel * model) {
- model->rssi = 0;
- return true;
- });
+ furi_record_close(RECORD_NOTIFICATION);
}
SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
SubGhzFrequencyAnalyzer* instance = malloc(sizeof(SubGhzFrequencyAnalyzer));
+ furi_assert(instance);
// View allocation and configuration
instance->view = view_alloc();
@@ -158,12 +318,6 @@ SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() {
view_set_enter_callback(instance->view, subghz_frequency_analyzer_enter);
view_set_exit_callback(instance->view, subghz_frequency_analyzer_exit);
- with_view_model(
- instance->view, (SubGhzFrequencyAnalyzerModel * model) {
- model->rssi = 0;
- return true;
- });
-
return instance;
}