diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c index 88aa4a18c..d95c6655a 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -72,6 +72,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { .frequency_coarse = 0, .rssi_coarse = 0, .frequency_fine = 0, .rssi_fine = 0}; float rssi = 0; uint32_t frequency = 0; + float rssi_temp = 0; + uint32_t frequency_temp = 0; CC1101Status status; //Start CC1101 @@ -195,6 +197,9 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { TAG, "=:%lu:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine); instance->sample_hold_counter = 20; + rssi_temp = frequency_rssi.rssi_fine; + frequency_temp = frequency_rssi.frequency_fine; + if(instance->filVal) { frequency_rssi.frequency_fine = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( @@ -203,7 +208,10 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { // Deliver callback if(instance->pair_callback) { instance->pair_callback( - instance->context, frequency_rssi.frequency_fine, frequency_rssi.rssi_fine); + instance->context, + frequency_rssi.frequency_fine, + frequency_rssi.rssi_fine, + true); } } else if( // Deliver results coarse (frequency_rssi.rssi_coarse > instance->trigger_level) && @@ -215,6 +223,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { (double)frequency_rssi.rssi_coarse); instance->sample_hold_counter = 20; + rssi_temp = frequency_rssi.rssi_coarse; + frequency_temp = frequency_rssi.frequency_coarse; if(instance->filVal) { frequency_rssi.frequency_coarse = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( @@ -225,14 +235,22 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { instance->pair_callback( instance->context, frequency_rssi.frequency_coarse, - frequency_rssi.rssi_coarse); + frequency_rssi.rssi_coarse, + true); } } else { if(instance->sample_hold_counter > 0) { instance->sample_hold_counter--; + if(instance->sample_hold_counter == 18) { + if(instance->pair_callback) { + instance->pair_callback( + instance->context, frequency_temp, rssi_temp, false); + } + } } else { instance->filVal = 0; - if(instance->pair_callback) instance->pair_callback(instance->context, 0, 0); + if(instance->pair_callback) + instance->pair_callback(instance->context, 0, 0, false); } } } diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h index 3b93f60ad..eba4409ce 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.h @@ -5,8 +5,11 @@ typedef struct SubGhzFrequencyAnalyzerWorker SubGhzFrequencyAnalyzerWorker; -typedef void ( - *SubGhzFrequencyAnalyzerWorkerPairCallback)(void* context, uint32_t frequency, float rssi); +typedef void (*SubGhzFrequencyAnalyzerWorkerPairCallback)( + void* context, + uint32_t frequency, + float rssi, + bool signal); typedef struct { uint32_t frequency_coarse; diff --git a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c index 1a0992f94..eef646356 100644 --- a/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c +++ b/applications/main/subghz/scenes/subghz_scene_frequency_analyzer.c @@ -1,8 +1,20 @@ #include "../subghz_i.h" +#include "../views/subghz_frequency_analyzer.h" #include #define TAG "SubGhzSceneFrequencyAnalyzer" +static const NotificationSequence sequence_saved = { + &message_blink_stop, + &message_blue_0, + &message_green_255, + &message_red_0, + &message_vibro_on, + &message_delay_100, + &message_vibro_off, + NULL, +}; + void subghz_scene_frequency_analyzer_callback(SubGhzCustomEvent event, void* context) { furi_assert(context); SubGhz* subghz = context; @@ -24,7 +36,28 @@ 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 == SubGhzCustomEventViewReceiverOK) { + if(event.event == SubGhzCustomEventSceneAnalyzerLock) { + notification_message(subghz->notifications, &sequence_set_green_255); + switch(subghz_frequency_analyzer_feedback_level( + subghz->subghz_frequency_analyzer, + SubGHzFrequencyAnalyzerFeedbackLevelAll, + false)) { + case SubGHzFrequencyAnalyzerFeedbackLevelAll: + notification_message(subghz->notifications, &sequence_success); + break; + case SubGHzFrequencyAnalyzerFeedbackLevelVibro: + notification_message(subghz->notifications, &sequence_single_vibro); + break; + case SubGHzFrequencyAnalyzerFeedbackLevelMute: + break; + } + notification_message(subghz->notifications, &sequence_display_backlight_on); + return true; + } else if(event.event == SubGhzCustomEventSceneAnalyzerUnlock) { + notification_message(subghz->notifications, &sequence_reset_rgb); + return true; + } else if(event.event == SubGhzCustomEventViewReceiverOK) { + notification_message(subghz->notifications, &sequence_saved); uint32_t frequency = subghz_frequency_analyzer_get_frequency_to_save(subghz->subghz_frequency_analyzer); if(frequency > 0) { diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index aed21b698..bf0ed6f5b 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -18,46 +18,35 @@ #define RSSI_SCALE 2 #define TRIGGER_STEP 1 -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 = { +// &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, -}; +// static const NotificationSequence sequence_hw_blink_stop = { +// &message_blink_stop, +// NULL, +// }; -static const NotificationSequence sequence_saved = { - &message_blink_stop, - &message_blue_0, - &message_green_255, - &message_red_0, - &message_vibro_on, - &message_delay_100, - &message_vibro_off, - NULL, -}; - -static const NotificationSequence sequence_frequency = { - &message_display_backlight_on, - &message_green_255, - &message_vibro_on, - &message_delay_100, - &message_green_0, - &message_blue_255, - &message_vibro_off, - &message_delay_100, - &message_blue_0, - &message_green_255, - &message_vibro_on, - &message_delay_100, - &message_green_0, - &message_vibro_off, - NULL, -}; +// static const NotificationSequence sequence_frequency = { +// &message_display_backlight_on, +// &message_green_255, +// &message_vibro_on, +// &message_delay_100, +// &message_green_0, +// &message_blue_255, +// &message_vibro_off, +// &message_delay_100, +// &message_blue_0, +// &message_green_255, +// &message_vibro_on, +// &message_delay_100, +// &message_green_0, +// &message_vibro_off, +// NULL, +// }; //static const NotificationSequence sequence_not_saved = { // &message_blink_stop, @@ -85,7 +74,8 @@ struct SubGhzFrequencyAnalyzer { SubGhzFrequencyAnalyzerCallback callback; void* context; bool locked; - uint8_t feedback_level; // 0 - no feedback, 1 - vibro only, 2 - vibro and sound + SubGHzFrequencyAnalyzerFeedbackLevel + feedback_level; // 0 - no feedback, 1 - vibro only, 2 - vibro and sound float rssi_last; uint32_t frequency_last; uint32_t frequency_last_vis; @@ -97,9 +87,11 @@ typedef struct { uint32_t frequency_last; uint32_t frequency_to_save; float rssi; + uint32_t history_frequency[3]; + bool signal; float rssi_last; float trigger; - uint8_t feedback_level; + SubGHzFrequencyAnalyzerFeedbackLevel feedback_level; } SubGhzFrequencyAnalyzerModel; void subghz_frequency_analyzer_set_callback( @@ -121,7 +113,9 @@ void subghz_frequency_analyzer_draw_rssi( uint8_t y) { // Current RSSI if(rssi) { - if(rssi > RSSI_MAX) rssi = RSSI_MAX; + if(rssi > RSSI_MAX) { + rssi = RSSI_MAX; + } rssi = (rssi - RSSI_MIN) / RSSI_SCALE; uint8_t column_number = 0; for(size_t i = 0; i <= (uint8_t)rssi; i++) { @@ -151,6 +145,31 @@ void subghz_frequency_analyzer_draw_rssi( canvas_draw_line(canvas, x, y + 3, x + (RSSI_MAX - RSSI_MIN) * 2 / RSSI_SCALE, y + 3); } +static void subghz_frequency_analyzer_history_frequency_draw( + Canvas* canvas, + SubGhzFrequencyAnalyzerModel* model) { + char buffer[64]; + uint8_t x = 66; + uint8_t y = 43; + + canvas_set_font(canvas, FontKeyboard); + for(uint8_t i = 0; i < 3; i++) { + if(model->history_frequency[i]) { + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld", + model->history_frequency[i] / 1000000 % 1000, + model->history_frequency[i] / 1000 % 1000); + canvas_draw_str(canvas, x, y + i * 10, buffer); + } else { + canvas_draw_str(canvas, x, y + i * 10, "---.---"); + } + canvas_draw_str(canvas, x + 44, y + i * 10, "MHz"); + } + canvas_set_font(canvas, FontSecondary); +} + void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel* model) { char buffer[64]; @@ -164,6 +183,9 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel subghz_frequency_analyzer_draw_rssi( canvas, model->rssi, model->rssi_last, model->trigger, 57, 58); + // Last detected frequency + subghz_frequency_analyzer_history_frequency_draw(canvas, model); + // Frequency canvas_set_font(canvas, FontBigNumbers); snprintf( @@ -172,31 +194,37 @@ void subghz_frequency_analyzer_draw(Canvas* canvas, SubGhzFrequencyAnalyzerModel "%03ld.%03ld", model->frequency / 1000000 % 1000, model->frequency / 1000 % 1000); + if(model->signal) { + canvas_draw_box(canvas, 4, 12, 121, 22); + canvas_set_color(canvas, ColorWhite); + } else { + } + 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); + // 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); switch(model->feedback_level) { - case 2: + case SubGHzFrequencyAnalyzerFeedbackLevelMute: canvas_draw_icon(canvas, 128 - 8 - 1, 1, &I_Volup_8x6); break; - case 1: + case SubGHzFrequencyAnalyzerFeedbackLevelVibro: canvas_draw_icon(canvas, 128 - 8 - 1, 1, &I_Voldwn_6x6); break; - case 0: + case SubGHzFrequencyAnalyzerFeedbackLevelAll: canvas_draw_icon(canvas, 128 - 8 - 1, 1, &I_Voldwn_6x6); canvas_set_color(canvas, ColorWhite); canvas_draw_box(canvas, 128 - 2 - 1 - 2, 1, 2, 6); @@ -242,7 +270,9 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { bool need_redraw = false; - if(event->key == InputKeyBack) return false; + if(event->key == InputKeyBack) { + return false; + } if(((event->type == InputTypePress) || (event->type == InputTypeRepeat)) && ((event->key == InputKeyLeft) || (event->key == InputKeyRight))) { @@ -303,8 +333,8 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { frequency_candidate); #endif model->frequency_to_save = frequency_candidate; - notification_message(instance->notifications, &sequence_saved); - notification_message(instance->notifications, &sequence_hw_blink); + // notification_message(instance->notifications, &sequence_saved); + // notification_message(instance->notifications, &sequence_hw_blink); updated = true; } }, @@ -326,10 +356,10 @@ bool subghz_frequency_analyzer_input(InputEvent* event, void* context) { // First device receive short, then when user release button we get long if(event->type == InputTypeLong) { #ifdef FURI_DEBUG - FURI_LOG_I(TAG, "Longpress!"); + FURI_LOG_I(TAG, "Long press!"); #endif // Stop blinking - notification_message(instance->notifications, &sequence_hw_blink_stop); + //notification_message(instance->notifications, &sequence_hw_blink_stop); // Stop worker if(subghz_frequency_analyzer_worker_is_running(instance->worker)) { @@ -369,43 +399,63 @@ uint32_t round_int(uint32_t value, uint8_t n) { return value; } -void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, float rssi) { - furi_assert(context); +void subghz_frequency_analyzer_pair_callback( + void* context, + uint32_t frequency, + float rssi, + bool signal) { SubGhzFrequencyAnalyzer* instance = context; - if((rssi == 0.f) && (instance->locked)) { - notification_message(instance->notifications, &sequence_hw_blink); - instance->frequency_last_vis = instance->frequency_last; - } - - if((rssi != 0.f) && (frequency != 0)) { - // Threre is some signal + if(instance->callback) { + instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context); + } + //update history + with_view_model( + instance->view, + SubGhzFrequencyAnalyzerModel * model, + { + model->history_frequency[2] = model->history_frequency[1]; + model->history_frequency[1] = model->history_frequency[0]; + model->history_frequency[0] = model->frequency; + }, + false); + } else if((rssi != 0.f) && (!instance->locked)) { + // There is some signal FURI_LOG_I(TAG, "rssi = %.2f, frequency = %ld Hz", (double)rssi, frequency); frequency = round_int(frequency, 3); // Round 299999990Hz to 300000000Hz - if(!instance->locked) { - // Triggered! - instance->rssi_last = rssi; - notification_message(instance->notifications, &sequence_hw_blink_stop); - switch(instance->feedback_level) { - case 1: // 1 - only vibro - notification_message(instance->notifications, &sequence_frequency); - break; - case 2: // 2 - vibro and beep - notification_message(instance->notifications, &sequence_success); - break; - default: // 0 - no feedback - notification_message(instance->notifications, &sequence_display_backlight_on); - break; - } + // Triggered! + instance->rssi_last = rssi; + if(instance->callback) { + instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context); + } + } - FURI_LOG_D(TAG, "triggered"); - } - // Update values - if(rssi >= instance->rssi_last) { - instance->rssi_last = rssi; - instance->frequency_last = frequency; - } + // Added code + // if((rssi != 0.f) && (frequency != 0)) { + // if(!instance->locked) { + // // Triggered! + // instance->rssi_last = rssi; + // notification_message(instance->notifications, &sequence_hw_blink_stop); + // + // switch(instance->feedback_level) { + // case 1: // 1 - only vibro + // notification_message(instance->notifications, &sequence_frequency); + // break; + // case 2: // 2 - vibro and beep + // notification_message(instance->notifications, &sequence_success); + // break; + // default: // 0 - no feedback + // notification_message(instance->notifications, &sequence_display_backlight_on); + // break; + // } + // } + // } + + // Update values + if(rssi >= instance->rssi_last && (frequency != 0)) { + instance->rssi_last = rssi; + instance->frequency_last = frequency; } instance->locked = (rssi != 0.f); @@ -416,6 +466,7 @@ void subghz_frequency_analyzer_pair_callback(void* context, uint32_t frequency, model->rssi = rssi; model->rssi_last = instance->rssi_last; model->frequency = frequency; + model->signal = signal; model->frequency_last = instance->frequency_last_vis; model->trigger = subghz_frequency_analyzer_worker_get_trigger_level(instance->worker); model->feedback_level = instance->feedback_level; @@ -427,9 +478,9 @@ 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); + // TODO: check 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); @@ -453,6 +504,9 @@ void subghz_frequency_analyzer_enter(void* context) { model->rssi = 0; model->rssi_last = 0; model->frequency = 0; + model->history_frequency[2] = 0; + model->history_frequency[1] = 0; + model->history_frequency[0] = 0; model->frequency_last = 0; model->frequency_to_save = 0; model->trigger = RSSI_MIN; @@ -464,8 +518,8 @@ void subghz_frequency_analyzer_exit(void* context) { furi_assert(context); SubGhzFrequencyAnalyzer* instance = context; - // Stop blinking - notification_message(instance->notifications, &sequence_hw_blink_stop); + // TODO: Check Stop blinking + //notification_message(instance->notifications, &sequence_hw_blink_stop); // Stop worker if(subghz_frequency_analyzer_worker_is_running(instance->worker)) { @@ -478,7 +532,6 @@ void subghz_frequency_analyzer_exit(void* context) { SubGhzFrequencyAnalyzer* subghz_frequency_analyzer_alloc() { SubGhzFrequencyAnalyzer* instance = malloc(sizeof(SubGhzFrequencyAnalyzer)); - furi_assert(instance); instance->feedback_level = 2; @@ -519,9 +572,9 @@ uint32_t subghz_frequency_analyzer_get_frequency_to_save(SubGhzFrequencyAnalyzer return frequency; } -uint8_t subghz_frequency_analyzer_feedback_level( +SubGHzFrequencyAnalyzerFeedbackLevel subghz_frequency_analyzer_feedback_level( SubGhzFrequencyAnalyzer* instance, - uint8_t level, + SubGHzFrequencyAnalyzerFeedbackLevel level, bool update) { furi_assert(instance); if(update) { diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.h b/applications/main/subghz/views/subghz_frequency_analyzer.h index 196d69c79..928fae770 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.h +++ b/applications/main/subghz/views/subghz_frequency_analyzer.h @@ -3,6 +3,12 @@ #include #include "../helpers/subghz_custom_event.h" +typedef enum { + SubGHzFrequencyAnalyzerFeedbackLevelAll, + SubGHzFrequencyAnalyzerFeedbackLevelVibro, + SubGHzFrequencyAnalyzerFeedbackLevelMute +} SubGHzFrequencyAnalyzerFeedbackLevel; + typedef struct SubGhzFrequencyAnalyzer SubGhzFrequencyAnalyzer; typedef void (*SubGhzFrequencyAnalyzerCallback)(SubGhzCustomEvent event, void* context); @@ -20,7 +26,7 @@ View* subghz_frequency_analyzer_get_view(SubGhzFrequencyAnalyzer* subghz_static) uint32_t subghz_frequency_analyzer_get_frequency_to_save(SubGhzFrequencyAnalyzer* instance); -uint8_t subghz_frequency_analyzer_feedback_level( +SubGHzFrequencyAnalyzerFeedbackLevel subghz_frequency_analyzer_feedback_level( SubGhzFrequencyAnalyzer* instance, - uint8_t level, + SubGHzFrequencyAnalyzerFeedbackLevel level, bool update);