[FL-1755, FL-1756] added LL_DeInit timers, removed Analyze scene, redesigned astomatic frequency change mechanism, updated subghz read scene interface (#677)
* SubGhz: Fix Timer hopping * SubGhz: add display of received packages and their maximum number. redesigned interface, the maximum number of received packages increased to 50 * SubGhz: add clearing history on exit read scene, jump after saving the key into the history of received signals * SubGhz: Fix honoring the width of the icon for transmitter scene * RFID: Fix [FL-1755] freeze after key emulation * SubGhz: drop analyze scene and views * SubGhz: fix save scene * Input, GUI: new event delivery scheme that groups event for complementarity. * Gui: update View Dispatcher documentation * Gui: remove dead code, wait till all input events are delivered in ViewDispatcher in queue mode. * Gui: update comment in ViewDispatcher * FuriHal: fix incorrect clock disable invocation * FuriHal: proper include * SubGhz: properly reset history in receiver view * Gui: correct view switch order and non-complementary events discarding Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		@@ -1,19 +0,0 @@
 | 
			
		||||
#include "../subghz_i.h"
 | 
			
		||||
 | 
			
		||||
const void subghz_scene_analyze_on_enter(void* context) {
 | 
			
		||||
    SubGhz* subghz = context;
 | 
			
		||||
    view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewAnalyze);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bool subghz_scene_analyze_on_event(void* context, SceneManagerEvent event) {
 | 
			
		||||
    SubGhz* subghz = context;
 | 
			
		||||
    if(event.type == SceneManagerEventTypeTick) {
 | 
			
		||||
        notification_message(subghz->notifications, &sequence_blink_blue_10);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void subghz_scene_analyze_on_exit(void* context) {
 | 
			
		||||
    // SubGhz* subghz = context;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
ADD_SCENE(subghz, start, Start)
 | 
			
		||||
ADD_SCENE(subghz, analyze, Analyze)
 | 
			
		||||
ADD_SCENE(subghz, receiver, Receiver)
 | 
			
		||||
ADD_SCENE(subghz, save_name, SaveName)
 | 
			
		||||
ADD_SCENE(subghz, save_success, SaveSuccess)
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,12 @@ const bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent e
 | 
			
		||||
    SubGhz* subghz = context;
 | 
			
		||||
    if(event.type == SceneManagerEventTypeCustom) {
 | 
			
		||||
        if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) {
 | 
			
		||||
            return scene_manager_search_and_switch_to_previous_scene(
 | 
			
		||||
                subghz->scene_manager, SubGhzSceneStart);
 | 
			
		||||
            if(!scene_manager_search_and_switch_to_previous_scene(
 | 
			
		||||
                   subghz->scene_manager, SubGhzSceneReceiver)) {
 | 
			
		||||
                scene_manager_search_and_switch_to_previous_scene(
 | 
			
		||||
                    subghz->scene_manager, SubGhzSceneStart);
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
#include "../subghz_i.h"
 | 
			
		||||
 | 
			
		||||
enum SubmenuIndex {
 | 
			
		||||
    SubmenuIndexAnalyze,
 | 
			
		||||
    SubmenuIndexRead,
 | 
			
		||||
    SubmenuIndexSaved,
 | 
			
		||||
    SubmenuIndexTest,
 | 
			
		||||
@@ -18,12 +17,6 @@ const void subghz_scene_start_on_enter(void* context) {
 | 
			
		||||
    if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) {
 | 
			
		||||
        subghz->state_notifications = NOTIFICATION_IDLE_STATE;
 | 
			
		||||
    }
 | 
			
		||||
    submenu_add_item(
 | 
			
		||||
        subghz->submenu,
 | 
			
		||||
        "Analyze",
 | 
			
		||||
        SubmenuIndexAnalyze,
 | 
			
		||||
        subghz_scene_start_submenu_callback,
 | 
			
		||||
        subghz);
 | 
			
		||||
    submenu_add_item(
 | 
			
		||||
        subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz);
 | 
			
		||||
    submenu_add_item(
 | 
			
		||||
@@ -47,12 +40,7 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
 | 
			
		||||
    SubGhz* subghz = context;
 | 
			
		||||
 | 
			
		||||
    if(event.type == SceneManagerEventTypeCustom) {
 | 
			
		||||
        if(event.event == SubmenuIndexAnalyze) {
 | 
			
		||||
            scene_manager_set_scene_state(
 | 
			
		||||
                subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAnalyze);
 | 
			
		||||
            scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze);
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if(event.event == SubmenuIndexRead) {
 | 
			
		||||
        if(event.event == SubmenuIndexRead) {
 | 
			
		||||
            scene_manager_set_scene_state(
 | 
			
		||||
                subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
 | 
			
		||||
            scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
 | 
			
		||||
 
 | 
			
		||||
@@ -70,13 +70,6 @@ SubGhz* subghz_alloc() {
 | 
			
		||||
    view_dispatcher_add_view(
 | 
			
		||||
        subghz->view_dispatcher, SubGhzViewMenu, submenu_get_view(subghz->submenu));
 | 
			
		||||
 | 
			
		||||
    // Analyze
 | 
			
		||||
    subghz->subghz_analyze = subghz_analyze_alloc();
 | 
			
		||||
    view_dispatcher_add_view(
 | 
			
		||||
        subghz->view_dispatcher,
 | 
			
		||||
        SubGhzViewAnalyze,
 | 
			
		||||
        subghz_analyze_get_view(subghz->subghz_analyze));
 | 
			
		||||
 | 
			
		||||
    // Receiver
 | 
			
		||||
    subghz->subghz_receiver = subghz_receiver_alloc();
 | 
			
		||||
    view_dispatcher_add_view(
 | 
			
		||||
@@ -159,10 +152,6 @@ void subghz_free(SubGhz* subghz) {
 | 
			
		||||
    view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic);
 | 
			
		||||
    subghz_test_static_free(subghz->subghz_test_static);
 | 
			
		||||
 | 
			
		||||
    // Analyze
 | 
			
		||||
    view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze);
 | 
			
		||||
    subghz_analyze_free(subghz->subghz_analyze);
 | 
			
		||||
 | 
			
		||||
    // Receiver
 | 
			
		||||
    view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewReceiver);
 | 
			
		||||
    subghz_receiver_free(subghz->subghz_receiver);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
#include <furi.h>
 | 
			
		||||
#include <m-string.h>
 | 
			
		||||
 | 
			
		||||
#define SUBGHZ_HISTORY_MAX 20
 | 
			
		||||
#define SUBGHZ_HISTORY_MAX 50
 | 
			
		||||
 | 
			
		||||
typedef struct SubGhzHistoryStruct SubGhzHistoryStruct;
 | 
			
		||||
 | 
			
		||||
@@ -88,7 +88,10 @@ SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, u
 | 
			
		||||
    instance->data.param1 = instance->history[idx].te;
 | 
			
		||||
    return &instance->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) {
 | 
			
		||||
    furi_assert(instance);
 | 
			
		||||
    string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX);
 | 
			
		||||
}
 | 
			
		||||
void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) {
 | 
			
		||||
    if(instance->history[idx].code_count_bit < 33) {
 | 
			
		||||
        string_printf(
 | 
			
		||||
 
 | 
			
		||||
@@ -18,5 +18,6 @@ uint16_t subghz_history_get_item(SubGhzHistory* instance);
 | 
			
		||||
uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx);
 | 
			
		||||
const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx);
 | 
			
		||||
void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx);
 | 
			
		||||
void subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output);
 | 
			
		||||
void subghz_history_add_to_history(SubGhzHistory* instance, void* context);
 | 
			
		||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "subghz.h"
 | 
			
		||||
#include "views/subghz_analyze.h"
 | 
			
		||||
#include "views/subghz_receiver.h"
 | 
			
		||||
#include "views/subghz_transmitter.h"
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +58,6 @@ struct SubGhz {
 | 
			
		||||
    char text_store[SUBGHZ_TEXT_STORE_SIZE + 1];
 | 
			
		||||
    uint8_t state_notifications;
 | 
			
		||||
 | 
			
		||||
    SubghzAnalyze* subghz_analyze;
 | 
			
		||||
    SubghzReceiver* subghz_receiver;
 | 
			
		||||
    SubghzTransmitter* subghz_transmitter;
 | 
			
		||||
 | 
			
		||||
@@ -71,7 +69,6 @@ struct SubGhz {
 | 
			
		||||
typedef enum {
 | 
			
		||||
    SubGhzViewMenu,
 | 
			
		||||
 | 
			
		||||
    SubGhzViewAnalyze,
 | 
			
		||||
    SubGhzViewDialogEx,
 | 
			
		||||
    SubGhzViewReceiver,
 | 
			
		||||
    SubGhzViewPopup,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,233 +0,0 @@
 | 
			
		||||
#include "subghz_analyze.h"
 | 
			
		||||
#include "../subghz_i.h"
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <furi.h>
 | 
			
		||||
#include <furi-hal.h>
 | 
			
		||||
#include <input/input.h>
 | 
			
		||||
#include <gui/elements.h>
 | 
			
		||||
#include <notification/notification-messages.h>
 | 
			
		||||
 | 
			
		||||
#include <lib/subghz/subghz_worker.h>
 | 
			
		||||
#include <lib/subghz/protocols/subghz_protocol.h>
 | 
			
		||||
 | 
			
		||||
#include <assets_icons.h>
 | 
			
		||||
 | 
			
		||||
struct SubghzAnalyze {
 | 
			
		||||
    View* view;
 | 
			
		||||
    SubGhzWorker* worker;
 | 
			
		||||
    SubGhzProtocol* protocol;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t frequency;
 | 
			
		||||
    uint32_t real_frequency;
 | 
			
		||||
    uint32_t counter;
 | 
			
		||||
    string_t text;
 | 
			
		||||
    uint16_t scene;
 | 
			
		||||
    SubGhzProtocolCommon parser;
 | 
			
		||||
} SubghzAnalyzeModel;
 | 
			
		||||
 | 
			
		||||
static const char subghz_symbols[] = {'-', '\\', '|', '/'};
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_draw(Canvas* canvas, SubghzAnalyzeModel* model) {
 | 
			
		||||
    char buffer[64];
 | 
			
		||||
 | 
			
		||||
    canvas_set_color(canvas, ColorBlack);
 | 
			
		||||
    canvas_set_font(canvas, FontPrimary);
 | 
			
		||||
 | 
			
		||||
    snprintf(
 | 
			
		||||
        buffer,
 | 
			
		||||
        sizeof(buffer),
 | 
			
		||||
        "Analyze: %03ld.%03ldMHz %c",
 | 
			
		||||
        model->real_frequency / 1000000 % 1000,
 | 
			
		||||
        model->real_frequency / 1000 % 1000,
 | 
			
		||||
        subghz_symbols[model->counter % 4]);
 | 
			
		||||
    canvas_draw_str(canvas, 0, 8, buffer);
 | 
			
		||||
 | 
			
		||||
    switch(model->scene) {
 | 
			
		||||
    case 1:
 | 
			
		||||
        canvas_draw_icon(canvas, 0, 10, &I_RFIDDolphinReceive_97x61);
 | 
			
		||||
        canvas_invert_color(canvas);
 | 
			
		||||
        canvas_draw_box(canvas, 80, 12, 20, 20);
 | 
			
		||||
        canvas_invert_color(canvas);
 | 
			
		||||
        canvas_draw_icon(canvas, 75, 18, &I_sub1_10px);
 | 
			
		||||
        elements_multiline_text_aligned(
 | 
			
		||||
            canvas, 90, 38, AlignCenter, AlignTop, "Detecting\r\nSubGhz");
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        canvas_set_font(canvas, FontSecondary);
 | 
			
		||||
        elements_multiline_text(canvas, 0, 18, string_get_cstr(model->text));
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool subghz_analyze_input(InputEvent* event, void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = context;
 | 
			
		||||
 | 
			
		||||
    if(event->type != InputTypeShort) return false;
 | 
			
		||||
 | 
			
		||||
    if(event->key == InputKeyBack) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            bool model_updated = false;
 | 
			
		||||
 | 
			
		||||
            if(event->key == InputKeyLeft) {
 | 
			
		||||
                if(model->frequency > 0) model->frequency--;
 | 
			
		||||
                model_updated = true;
 | 
			
		||||
            } else if(event->key == InputKeyRight) {
 | 
			
		||||
                if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
 | 
			
		||||
                model_updated = true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(model_updated) {
 | 
			
		||||
                furi_hal_subghz_idle();
 | 
			
		||||
                model->real_frequency =
 | 
			
		||||
                    furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
 | 
			
		||||
                furi_hal_subghz_rx();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return model_updated;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_text_callback(string_t text, void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = context;
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            model->counter++;
 | 
			
		||||
            string_set(model->text, text);
 | 
			
		||||
            model->scene = 0;
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_protocol_callback(SubGhzProtocolCommon* parser, void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = context;
 | 
			
		||||
    char buffer[64];
 | 
			
		||||
    snprintf(
 | 
			
		||||
        buffer,
 | 
			
		||||
        sizeof(buffer),
 | 
			
		||||
        "%s\r\n"
 | 
			
		||||
        "K:%lX%lX\r\n"
 | 
			
		||||
        "SN:%lX\r\n"
 | 
			
		||||
        "BTN:%X",
 | 
			
		||||
        parser->name,
 | 
			
		||||
        (uint32_t)(parser->code_found >> 32),
 | 
			
		||||
        (uint32_t)(parser->code_found & 0x00000000FFFFFFFF),
 | 
			
		||||
        parser->serial,
 | 
			
		||||
        parser->btn);
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            model->counter++;
 | 
			
		||||
            model->parser = *parser;
 | 
			
		||||
            string_set(model->text, buffer);
 | 
			
		||||
            model->scene = 0;
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_enter(void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = context;
 | 
			
		||||
 | 
			
		||||
    furi_hal_subghz_reset();
 | 
			
		||||
    furi_hal_subghz_idle();
 | 
			
		||||
    furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            model->frequency = subghz_frequencies_433_92;
 | 
			
		||||
            model->real_frequency =
 | 
			
		||||
                furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
 | 
			
		||||
            model->scene = 1;
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
 | 
			
		||||
 | 
			
		||||
    furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz_analyze->worker);
 | 
			
		||||
 | 
			
		||||
    subghz_worker_start(subghz_analyze->worker);
 | 
			
		||||
 | 
			
		||||
    furi_hal_subghz_flush_rx();
 | 
			
		||||
    furi_hal_subghz_rx();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_exit(void* context) {
 | 
			
		||||
    furi_assert(context);
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = context;
 | 
			
		||||
 | 
			
		||||
    subghz_worker_stop(subghz_analyze->worker);
 | 
			
		||||
 | 
			
		||||
    furi_hal_subghz_stop_async_rx();
 | 
			
		||||
    furi_hal_subghz_sleep();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SubghzAnalyze* subghz_analyze_alloc() {
 | 
			
		||||
    SubghzAnalyze* subghz_analyze = furi_alloc(sizeof(SubghzAnalyze));
 | 
			
		||||
 | 
			
		||||
    // View allocation and configuration
 | 
			
		||||
    subghz_analyze->view = view_alloc();
 | 
			
		||||
    view_allocate_model(subghz_analyze->view, ViewModelTypeLocking, sizeof(SubghzAnalyzeModel));
 | 
			
		||||
    view_set_context(subghz_analyze->view, subghz_analyze);
 | 
			
		||||
    view_set_draw_callback(subghz_analyze->view, (ViewDrawCallback)subghz_analyze_draw);
 | 
			
		||||
    view_set_input_callback(subghz_analyze->view, subghz_analyze_input);
 | 
			
		||||
    view_set_enter_callback(subghz_analyze->view, subghz_analyze_enter);
 | 
			
		||||
    view_set_exit_callback(subghz_analyze->view, subghz_analyze_exit);
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            string_init(model->text);
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    subghz_analyze->worker = subghz_worker_alloc();
 | 
			
		||||
    subghz_analyze->protocol = subghz_protocol_alloc();
 | 
			
		||||
 | 
			
		||||
    subghz_worker_set_overrun_callback(
 | 
			
		||||
        subghz_analyze->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
 | 
			
		||||
    subghz_worker_set_pair_callback(
 | 
			
		||||
        subghz_analyze->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
 | 
			
		||||
    subghz_worker_set_context(subghz_analyze->worker, subghz_analyze->protocol);
 | 
			
		||||
 | 
			
		||||
    subghz_protocol_load_keeloq_file(
 | 
			
		||||
        subghz_analyze->protocol, "/ext/assets/subghz/keeloq_mfcodes");
 | 
			
		||||
    subghz_protocol_load_nice_flor_s_file(
 | 
			
		||||
        subghz_analyze->protocol, "/ext/assets/subghz/nice_floor_s_rx");
 | 
			
		||||
    subghz_protocol_enable_dump_text(
 | 
			
		||||
        subghz_analyze->protocol, subghz_analyze_text_callback, subghz_analyze);
 | 
			
		||||
 | 
			
		||||
    return subghz_analyze;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_free(SubghzAnalyze* subghz_analyze) {
 | 
			
		||||
    furi_assert(subghz_analyze);
 | 
			
		||||
 | 
			
		||||
    subghz_protocol_free(subghz_analyze->protocol);
 | 
			
		||||
    subghz_worker_free(subghz_analyze->worker);
 | 
			
		||||
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_analyze->view, (SubghzAnalyzeModel * model) {
 | 
			
		||||
            string_clear(model->text);
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
    view_free(subghz_analyze->view);
 | 
			
		||||
    free(subghz_analyze);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze) {
 | 
			
		||||
    furi_assert(subghz_analyze);
 | 
			
		||||
    return subghz_analyze->view;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <gui/view.h>
 | 
			
		||||
 | 
			
		||||
typedef struct SubghzAnalyze SubghzAnalyze;
 | 
			
		||||
 | 
			
		||||
SubghzAnalyze* subghz_analyze_alloc();
 | 
			
		||||
 | 
			
		||||
void subghz_analyze_free(SubghzAnalyze* subghz_analyze);
 | 
			
		||||
 | 
			
		||||
View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze);
 | 
			
		||||
@@ -14,8 +14,8 @@
 | 
			
		||||
#define MAX_LEN_PX 100
 | 
			
		||||
#define MENU_ITEMS 4
 | 
			
		||||
 | 
			
		||||
#define COUNT_FREQUNCY_SCANER 3
 | 
			
		||||
const uint32_t subghz_frequencies_scanner[] = {
 | 
			
		||||
#define COUNT_FREQUNCY_HOPPER 3
 | 
			
		||||
const uint32_t subghz_frequencies_hopper[] = {
 | 
			
		||||
    /* 300 - 348 */
 | 
			
		||||
    315000000,
 | 
			
		||||
    /* 387 - 464 */
 | 
			
		||||
@@ -35,6 +35,7 @@ typedef enum {
 | 
			
		||||
    SubGhzHopperStateOFF,
 | 
			
		||||
    SubGhzHopperStatePause,
 | 
			
		||||
    SubGhzHopperStateRunnig,
 | 
			
		||||
    SubGhzHopperStateRSSITimeOut,
 | 
			
		||||
} SubGhzHopperState;
 | 
			
		||||
 | 
			
		||||
static const Icon* ReceiverItemIcons[] = {
 | 
			
		||||
@@ -51,6 +52,7 @@ struct SubghzReceiver {
 | 
			
		||||
    SubGhzProtocol* protocol;
 | 
			
		||||
    osTimerId timer;
 | 
			
		||||
    SubGhzHopperState hopper_state;
 | 
			
		||||
    uint8_t hopper_timeout;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -62,8 +64,6 @@ typedef struct {
 | 
			
		||||
    uint8_t temp_frequency;
 | 
			
		||||
    uint32_t real_frequency;
 | 
			
		||||
 | 
			
		||||
    uint8_t tab_idx;
 | 
			
		||||
    uint8_t menu_idx;
 | 
			
		||||
    uint16_t idx;
 | 
			
		||||
    uint16_t list_offset;
 | 
			
		||||
    uint16_t history_item;
 | 
			
		||||
@@ -146,6 +146,7 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
 | 
			
		||||
    bool scrollbar = model->history_item > 4;
 | 
			
		||||
    string_t str_buff;
 | 
			
		||||
    char buffer[64];
 | 
			
		||||
    uint32_t frequency;
 | 
			
		||||
    string_init(str_buff);
 | 
			
		||||
 | 
			
		||||
    canvas_clear(canvas);
 | 
			
		||||
@@ -174,15 +175,25 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
 | 
			
		||||
            elements_scrollbar_pos(canvas, 126, 0, 49, model->idx, model->history_item);
 | 
			
		||||
        }
 | 
			
		||||
        canvas_set_color(canvas, ColorBlack);
 | 
			
		||||
        canvas_set_font(canvas, FontPrimary);
 | 
			
		||||
        canvas_set_font(canvas, FontSecondary);
 | 
			
		||||
 | 
			
		||||
        elements_button_left(canvas, "Conf");
 | 
			
		||||
        if((model->real_frequency / 1000 % 10) > 4) {
 | 
			
		||||
            frequency = model->real_frequency + 10000;
 | 
			
		||||
        } else {
 | 
			
		||||
            frequency = model->real_frequency;
 | 
			
		||||
        }
 | 
			
		||||
        snprintf(
 | 
			
		||||
            buffer,
 | 
			
		||||
            sizeof(buffer),
 | 
			
		||||
            "%03ld.%03ld  OOK",
 | 
			
		||||
            model->real_frequency / 1000000 % 1000,
 | 
			
		||||
            model->real_frequency / 1000 % 1000);
 | 
			
		||||
        canvas_draw_str(canvas, 60, 61, buffer);
 | 
			
		||||
        elements_button_left(canvas, "Config");
 | 
			
		||||
            "%03ld.%02ld",
 | 
			
		||||
            frequency / 1000000 % 1000,
 | 
			
		||||
            frequency / 10000 % 100);
 | 
			
		||||
        canvas_draw_str(canvas, 40, 62, buffer);
 | 
			
		||||
        canvas_draw_str(canvas, 75, 62, "AM");
 | 
			
		||||
        subghz_history_get_text_space_left(model->history, str_buff);
 | 
			
		||||
        canvas_draw_str(canvas, 94, 62, string_get_cstr(str_buff));
 | 
			
		||||
        canvas_draw_line(canvas, 38, 51, 125, 51);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case ReceiverSceneStart:
 | 
			
		||||
@@ -194,15 +205,27 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
 | 
			
		||||
        canvas_set_font(canvas, FontPrimary);
 | 
			
		||||
        canvas_draw_str(canvas, 63, 40, "Scanning...");
 | 
			
		||||
        canvas_set_color(canvas, ColorBlack);
 | 
			
		||||
        canvas_set_font(canvas, FontPrimary);
 | 
			
		||||
        canvas_set_font(canvas, FontSecondary);
 | 
			
		||||
        elements_button_left(canvas, "Conf");
 | 
			
		||||
        canvas_invert_color(canvas);
 | 
			
		||||
        canvas_draw_box(canvas, 38, 52, 10, 10);
 | 
			
		||||
        canvas_invert_color(canvas);
 | 
			
		||||
        if((model->real_frequency / 1000 % 10) > 4) {
 | 
			
		||||
            frequency = model->real_frequency + 10000;
 | 
			
		||||
        } else {
 | 
			
		||||
            frequency = model->real_frequency;
 | 
			
		||||
        }
 | 
			
		||||
        snprintf(
 | 
			
		||||
            buffer,
 | 
			
		||||
            sizeof(buffer),
 | 
			
		||||
            "%03ld.%03ld  OOK",
 | 
			
		||||
            model->real_frequency / 1000000 % 1000,
 | 
			
		||||
            model->real_frequency / 1000 % 1000);
 | 
			
		||||
        canvas_draw_str(canvas, 60, 61, buffer);
 | 
			
		||||
        elements_button_left(canvas, "Config");
 | 
			
		||||
            "%03ld.%02ld",
 | 
			
		||||
            frequency / 1000000 % 1000,
 | 
			
		||||
            frequency / 10000 % 100);
 | 
			
		||||
        canvas_draw_str(canvas, 40, 62, buffer);
 | 
			
		||||
        canvas_draw_str(canvas, 75, 62, "AM");
 | 
			
		||||
        subghz_history_get_text_space_left(model->history, str_buff);
 | 
			
		||||
        canvas_draw_str(canvas, 94, 62, string_get_cstr(str_buff));
 | 
			
		||||
        canvas_draw_line(canvas, 48, 51, 125, 51);
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case ReceiverSceneConfig:
 | 
			
		||||
@@ -264,6 +287,14 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
 | 
			
		||||
    switch(scene) {
 | 
			
		||||
    case ReceiverSceneMain:
 | 
			
		||||
        if(event->key == InputKeyBack) {
 | 
			
		||||
            with_view_model(
 | 
			
		||||
                subghz_receiver->view, (SubghzReceiverModel * model) {
 | 
			
		||||
                    model->idx = 0;
 | 
			
		||||
                    model->list_offset = 0;
 | 
			
		||||
                    model->history_item = 0;
 | 
			
		||||
                    subghz_history_clean(model->history);
 | 
			
		||||
                    return true;
 | 
			
		||||
                });
 | 
			
		||||
            return false;
 | 
			
		||||
        } else if(event->key == InputKeyUp) {
 | 
			
		||||
            with_view_model(
 | 
			
		||||
@@ -456,32 +487,41 @@ static void subghz_receiver_timer_callback(void* context) {
 | 
			
		||||
    SubghzReceiver* subghz_receiver = context;
 | 
			
		||||
 | 
			
		||||
    switch(subghz_receiver->hopper_state) {
 | 
			
		||||
    case SubGhzHopperStateOFF:
 | 
			
		||||
    case SubGhzHopperStatePause:
 | 
			
		||||
        return;
 | 
			
		||||
        break;
 | 
			
		||||
    case SubGhzHopperStatePause:
 | 
			
		||||
        osTimerStart(subghz_receiver->timer, 1024 / 10);
 | 
			
		||||
    case SubGhzHopperStateOFF:
 | 
			
		||||
        osTimerStop(subghz_receiver->timer);
 | 
			
		||||
        return;
 | 
			
		||||
        break;
 | 
			
		||||
    case SubGhzHopperStateRSSITimeOut:
 | 
			
		||||
        if(subghz_receiver->hopper_timeout != 0) {
 | 
			
		||||
            subghz_receiver->hopper_timeout--;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    float rssi = -127.0f;
 | 
			
		||||
    with_view_model(
 | 
			
		||||
        subghz_receiver->view, (SubghzReceiverModel * model) {
 | 
			
		||||
            // See RSSI Calculation timings in CC1101 17.3 RSSI
 | 
			
		||||
            rssi = furi_hal_subghz_get_rssi();
 | 
			
		||||
            if(subghz_receiver->hopper_state != SubGhzHopperStateRSSITimeOut) {
 | 
			
		||||
                // See RSSI Calculation timings in CC1101 17.3 RSSI
 | 
			
		||||
                rssi = furi_hal_subghz_get_rssi();
 | 
			
		||||
 | 
			
		||||
            // Stay if RSSI is high enough
 | 
			
		||||
            if(rssi > -90.0f) {
 | 
			
		||||
                osTimerStart(subghz_receiver->timer, 1024 / 4);
 | 
			
		||||
                return false;
 | 
			
		||||
                // Stay if RSSI is high enough
 | 
			
		||||
                if(rssi > -90.0f) {
 | 
			
		||||
                    subghz_receiver->hopper_timeout = 10;
 | 
			
		||||
                    subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut;
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                osTimerStart(subghz_receiver->timer, 1024 / 10);
 | 
			
		||||
                subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Select next frequency
 | 
			
		||||
            if(model->frequency < COUNT_FREQUNCY_SCANER - 1) {
 | 
			
		||||
            if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) {
 | 
			
		||||
                model->frequency++;
 | 
			
		||||
            } else {
 | 
			
		||||
                model->frequency = 0;
 | 
			
		||||
@@ -491,7 +531,7 @@ static void subghz_receiver_timer_callback(void* context) {
 | 
			
		||||
            subghz_rx_end(subghz_receiver->worker);
 | 
			
		||||
            subghz_protocol_reset(subghz_receiver->protocol);
 | 
			
		||||
            model->real_frequency =
 | 
			
		||||
                subghz_rx(subghz_receiver->worker, subghz_frequencies_scanner[model->frequency]);
 | 
			
		||||
                subghz_rx(subghz_receiver->worker, subghz_frequencies_hopper[model->frequency]);
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        });
 | 
			
		||||
@@ -553,7 +593,7 @@ SubghzReceiver* subghz_receiver_alloc() {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    subghz_receiver->timer =
 | 
			
		||||
        osTimerNew(subghz_receiver_timer_callback, osTimerOnce, subghz_receiver, NULL);
 | 
			
		||||
        osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL);
 | 
			
		||||
    subghz_receiver->hopper_state = SubGhzHopperStateOFF;
 | 
			
		||||
    return subghz_receiver;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,6 @@
 | 
			
		||||
#include <gui/elements.h>
 | 
			
		||||
#include <notification/notification-messages.h>
 | 
			
		||||
 | 
			
		||||
//#include <assets_icons.h>
 | 
			
		||||
#include <gui/icon_i.h>
 | 
			
		||||
 | 
			
		||||
struct SubghzTransmitter {
 | 
			
		||||
    View* view;
 | 
			
		||||
    SubghzTransmitterCallback callback;
 | 
			
		||||
@@ -64,7 +61,7 @@ static void subghz_transmitter_button_right(Canvas* canvas, const char* str) {
 | 
			
		||||
    const uint8_t string_width = canvas_string_width(canvas, str);
 | 
			
		||||
    const Icon* icon = &I_ButtonCenter_7x7;
 | 
			
		||||
    const uint8_t icon_offset = 3;
 | 
			
		||||
    const uint8_t icon_width_with_offset = icon->width + icon_offset;
 | 
			
		||||
    const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset;
 | 
			
		||||
    const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
 | 
			
		||||
 | 
			
		||||
    const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user