SubGhz: frequency hopping mode (#671)

* SubGhz: fix assert on worker double stop.
* SubGhz: add hopping mode (315.00, 433.92, 868.00)
* SubGhz: add support for new alarms on the keelog protocol
* SubGhz: update te in princeton protocol
* SubGhz: move static to tests, rename sniffer to hopper/auto, remove delay from timer thread, optimize locking strategy.

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Skorpionm 2021-08-29 17:05:15 +04:00 committed by GitHub
parent 0a8a944e10
commit 663dbbfe9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 185 additions and 93 deletions

View File

@ -5,8 +5,8 @@ ADD_SCENE(subghz, save_name, SaveName)
ADD_SCENE(subghz, save_success, SaveSuccess) ADD_SCENE(subghz, save_success, SaveSuccess)
ADD_SCENE(subghz, saved, Saved) ADD_SCENE(subghz, saved, Saved)
ADD_SCENE(subghz, transmitter, Transmitter) ADD_SCENE(subghz, transmitter, Transmitter)
ADD_SCENE(subghz, static, Static)
ADD_SCENE(subghz, test, Test) ADD_SCENE(subghz, test, Test)
ADD_SCENE(subghz, test_static, TestStatic)
ADD_SCENE(subghz, test_carrier, TestCarrier) ADD_SCENE(subghz, test_carrier, TestCarrier)
ADD_SCENE(subghz, test_packet, TestPacket) ADD_SCENE(subghz, test_packet, TestPacket)
ADD_SCENE(subghz, set_type, SetType) ADD_SCENE(subghz, set_type, SetType)

View File

@ -4,7 +4,6 @@ enum SubmenuIndex {
SubmenuIndexAnalyze, SubmenuIndexAnalyze,
SubmenuIndexRead, SubmenuIndexRead,
SubmenuIndexSaved, SubmenuIndexSaved,
SubmenuIndexStatic,
SubmenuIndexTest, SubmenuIndexTest,
SubmenuIndexAddManualy, SubmenuIndexAddManualy,
}; };
@ -35,8 +34,6 @@ const void subghz_scene_start_on_enter(void* context) {
SubmenuIndexAddManualy, SubmenuIndexAddManualy,
subghz_scene_start_submenu_callback, subghz_scene_start_submenu_callback,
subghz); subghz);
submenu_add_item(
subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_start_submenu_callback, subghz);
submenu_add_item( submenu_add_item(
subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
@ -56,9 +53,6 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze);
return true; return true;
} else if(event.event == SubmenuIndexRead) { } else if(event.event == SubmenuIndexRead) {
// scene_manager_set_scene_state(
// subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
// scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRead);
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver);
@ -73,11 +67,6 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManualy); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManualy);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType);
return true; return true;
} else if(event.event == SubmenuIndexStatic) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexStatic);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStatic);
return true;
} else if(event.event == SubmenuIndexTest) { } else if(event.event == SubmenuIndexTest) {
scene_manager_set_scene_state( scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);

View File

@ -3,6 +3,7 @@
enum SubmenuIndex { enum SubmenuIndex {
SubmenuIndexCarrier, SubmenuIndexCarrier,
SubmenuIndexPacket, SubmenuIndexPacket,
SubmenuIndexStatic,
}; };
void subghz_scene_test_submenu_callback(void* context, uint32_t index) { void subghz_scene_test_submenu_callback(void* context, uint32_t index) {
@ -21,6 +22,8 @@ const void subghz_scene_test_on_enter(void* context) {
subghz); subghz);
submenu_add_item( submenu_add_item(
subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz); subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz);
submenu_add_item(
subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_test_submenu_callback, subghz);
submenu_set_selected_item( submenu_set_selected_item(
subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest)); subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest));
@ -42,6 +45,11 @@ const bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket); subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket);
return true; return true;
} else if(event.event == SubmenuIndexStatic) {
scene_manager_set_scene_state(
subghz->scene_manager, SubGhzSceneTest, SubmenuIndexStatic);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestStatic);
return true;
} }
} }
return false; return false;

View File

@ -1,15 +1,15 @@
#include "../subghz_i.h" #include "../subghz_i.h"
const void subghz_scene_static_on_enter(void* context) { const void subghz_scene_test_static_on_enter(void* context) {
SubGhz* subghz = context; SubGhz* subghz = context;
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewStatic); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewStatic);
} }
const bool subghz_scene_static_on_event(void* context, SceneManagerEvent event) { const bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) {
// SubGhz* subghz = context; // SubGhz* subghz = context;
return false; return false;
} }
const void subghz_scene_static_on_exit(void* context) { const void subghz_scene_test_static_on_exit(void* context) {
// SubGhz* subghz = context; // SubGhz* subghz = context;
} }

View File

@ -121,9 +121,11 @@ SubGhz* subghz_alloc() {
subghz_test_packet_get_view(subghz->subghz_test_packet)); subghz_test_packet_get_view(subghz->subghz_test_packet));
// Static send // Static send
subghz->subghz_static = subghz_static_alloc(); subghz->subghz_test_static = subghz_test_static_alloc();
view_dispatcher_add_view( view_dispatcher_add_view(
subghz->view_dispatcher, SubGhzViewStatic, subghz_static_get_view(subghz->subghz_static)); subghz->view_dispatcher,
SubGhzViewStatic,
subghz_test_static_get_view(subghz->subghz_test_static));
//init Worker & Protocol //init Worker & Protocol
subghz->worker = subghz_worker_alloc(); subghz->worker = subghz_worker_alloc();
@ -155,7 +157,7 @@ void subghz_free(SubGhz* subghz) {
// Static // Static
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic); view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic);
subghz_static_free(subghz->subghz_static); subghz_test_static_free(subghz->subghz_test_static);
// Analyze // Analyze
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze); view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze);

View File

@ -4,8 +4,8 @@
#include "views/subghz_analyze.h" #include "views/subghz_analyze.h"
#include "views/subghz_receiver.h" #include "views/subghz_receiver.h"
#include "views/subghz_transmitter.h" #include "views/subghz_transmitter.h"
#include "views/subghz_static.h"
#include "views/subghz_test_static.h"
#include "views/subghz_test_carrier.h" #include "views/subghz_test_carrier.h"
#include "views/subghz_test_packet.h" #include "views/subghz_test_packet.h"
@ -62,8 +62,8 @@ struct SubGhz {
SubghzAnalyze* subghz_analyze; SubghzAnalyze* subghz_analyze;
SubghzReceiver* subghz_receiver; SubghzReceiver* subghz_receiver;
SubghzTransmitter* subghz_transmitter; SubghzTransmitter* subghz_transmitter;
SubghzStatic* subghz_static;
SubghzTestStatic* subghz_test_static;
SubghzTestCarrier* subghz_test_carrier; SubghzTestCarrier* subghz_test_carrier;
SubghzTestPacket* subghz_test_packet; SubghzTestPacket* subghz_test_packet;
}; };

View File

@ -14,6 +14,16 @@
#define MAX_LEN_PX 100 #define MAX_LEN_PX 100
#define MENU_ITEMS 4 #define MENU_ITEMS 4
#define COUNT_FREQUNCY_SCANER 3
const uint32_t subghz_frequencies_scanner[] = {
/* 300 - 348 */
315000000,
/* 387 - 464 */
433920000, /* LPD433 mid */
/* 779 - 928 */
868350000,
};
typedef enum { typedef enum {
ReceiverSceneStart, ReceiverSceneStart,
ReceiverSceneMain, ReceiverSceneMain,
@ -21,6 +31,12 @@ typedef enum {
ReceiverSceneInfo, ReceiverSceneInfo,
} SubghzReceiverScene; } SubghzReceiverScene;
typedef enum {
SubGhzHopperStateOFF,
SubGhzHopperStatePause,
SubGhzHopperStateRunnig,
} SubGhzHopperState;
static const Icon* ReceiverItemIcons[] = { static const Icon* ReceiverItemIcons[] = {
[TYPE_PROTOCOL_UNKNOWN] = &I_quest_7x8, [TYPE_PROTOCOL_UNKNOWN] = &I_quest_7x8,
[TYPE_PROTOCOL_STATIC] = &I_unlock_7x8, [TYPE_PROTOCOL_STATIC] = &I_unlock_7x8,
@ -33,6 +49,8 @@ struct SubghzReceiver {
void* context; void* context;
SubGhzWorker* worker; SubGhzWorker* worker;
SubGhzProtocol* protocol; SubGhzProtocol* protocol;
osTimerId timer;
SubGhzHopperState hopper_state;
}; };
typedef struct { typedef struct {
@ -188,13 +206,18 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
break; break;
case ReceiverSceneConfig: case ReceiverSceneConfig:
snprintf( if(model->frequency < subghz_frequencies_count) {
buffer, snprintf(
sizeof(buffer), buffer,
"Frequency: < %03ld.%03ldMHz >", sizeof(buffer),
model->real_frequency / 1000000 % 1000, "Frequency: < %03ld.%03ldMHz >",
model->real_frequency / 1000 % 1000); model->real_frequency / 1000000 % 1000,
canvas_draw_str(canvas, 0, 8, buffer); model->real_frequency / 1000 % 1000);
canvas_draw_str(canvas, 0, 8, buffer);
} else {
canvas_draw_str(canvas, 0, 8, "Frequency: <auto>");
}
elements_button_center(canvas, "Save"); elements_button_center(canvas, "Save");
break; break;
@ -255,6 +278,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
return true; return true;
}); });
} else if(event->key == InputKeyLeft) { } else if(event->key == InputKeyLeft) {
subghz_receiver->hopper_state = SubGhzHopperStatePause;
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
model->scene = ReceiverSceneConfig; model->scene = ReceiverSceneConfig;
@ -295,6 +319,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
subghz_rx_end(subghz_receiver->worker); subghz_rx_end(subghz_receiver->worker);
model->real_frequency = model->real_frequency =
subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]);
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
model->scene = ReceiverSceneMain; model->scene = ReceiverSceneMain;
return true; return true;
}); });
@ -303,6 +328,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context); subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context);
return false; return false;
} else if(can_be_saved && event->key == InputKeyOk && event->type == InputTypePress) { } else if(can_be_saved && event->key == InputKeyOk && event->type == InputTypePress) {
subghz_receiver->hopper_state = SubGhzHopperStatePause;
subghz_rx_end(subghz_receiver->worker); subghz_rx_end(subghz_receiver->worker);
subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context); subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context);
return true; return true;
@ -318,6 +344,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
model->frequency = model->temp_frequency; model->frequency = model->temp_frequency;
model->real_frequency = subghz_frequencies[model->frequency]; model->real_frequency = subghz_frequencies[model->frequency];
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
if(subghz_history_get_item(model->history) == 0) { if(subghz_history_get_item(model->history) == 0) {
model->scene = ReceiverSceneStart; model->scene = ReceiverSceneStart;
} else { } else {
@ -329,9 +356,16 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
} else if(event->key == InputKeyOk) { } else if(event->key == InputKeyOk) {
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
subghz_rx_end(subghz_receiver->worker); if(model->frequency < subghz_frequencies_count) {
model->real_frequency = subghz_rx_end(subghz_receiver->worker);
subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); model->real_frequency = subghz_rx(
subghz_receiver->worker, subghz_frequencies[model->frequency]);
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
} else {
osTimerStart(subghz_receiver->timer, 1024 / 10);
subghz_receiver->hopper_state = SubGhzHopperStateRunnig;
}
if(subghz_history_get_item(model->history) == 0) { if(subghz_history_get_item(model->history) == 0) {
model->scene = ReceiverSceneStart; model->scene = ReceiverSceneStart;
} else { } else {
@ -349,7 +383,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
if(model->frequency > 0) model->frequency--; if(model->frequency > 0) model->frequency--;
model_updated = true; model_updated = true;
} else if(event->key == InputKeyRight) { } else if(event->key == InputKeyRight) {
if(model->frequency < subghz_frequencies_count - 1) model->frequency++; if(model->frequency < subghz_frequencies_count) model->frequency++;
model_updated = true; model_updated = true;
} }
if(model_updated) { if(model_updated) {
@ -364,6 +398,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
if(event->key == InputKeyBack) { if(event->key == InputKeyBack) {
return false; return false;
} else if(event->key == InputKeyLeft) { } else if(event->key == InputKeyLeft) {
subghz_receiver->hopper_state = SubGhzHopperStatePause;
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
model->temp_frequency = model->frequency; model->temp_frequency = model->frequency;
@ -416,6 +451,52 @@ void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* conte
subghz_receiver_update_offset(subghz_receiver); subghz_receiver_update_offset(subghz_receiver);
} }
static void subghz_receiver_timer_callback(void* context) {
furi_assert(context);
SubghzReceiver* subghz_receiver = context;
switch(subghz_receiver->hopper_state) {
case SubGhzHopperStateOFF:
return;
break;
case SubGhzHopperStatePause:
osTimerStart(subghz_receiver->timer, 1024 / 10);
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();
// Stay if RSSI is high enough
if(rssi > -90.0f) {
osTimerStart(subghz_receiver->timer, 1024 / 4);
return false;
} else {
osTimerStart(subghz_receiver->timer, 1024 / 10);
}
// Select next frequency
if(model->frequency < COUNT_FREQUNCY_SCANER - 1) {
model->frequency++;
} else {
model->frequency = 0;
}
// Restart radio
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]);
return true;
});
}
void subghz_receiver_enter(void* context) { void subghz_receiver_enter(void* context) {
furi_assert(context); furi_assert(context);
SubghzReceiver* subghz_receiver = context; SubghzReceiver* subghz_receiver = context;
@ -441,6 +522,7 @@ void subghz_receiver_enter(void* context) {
void subghz_receiver_exit(void* context) { void subghz_receiver_exit(void* context) {
furi_assert(context); furi_assert(context);
SubghzReceiver* subghz_receiver = context; SubghzReceiver* subghz_receiver = context;
osTimerStop(subghz_receiver->timer);
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
string_clean(model->text); string_clean(model->text);
@ -469,6 +551,10 @@ SubghzReceiver* subghz_receiver_alloc() {
model->history = subghz_history_alloc(); model->history = subghz_history_alloc();
return true; return true;
}); });
subghz_receiver->timer =
osTimerNew(subghz_receiver_timer_callback, osTimerOnce, subghz_receiver, NULL);
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
return subghz_receiver; return subghz_receiver;
} }
@ -481,6 +567,7 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) {
subghz_history_free(model->history); subghz_history_free(model->history);
return false; return false;
}); });
osTimerDelete(subghz_receiver->timer);
view_free(subghz_receiver->view); view_free(subghz_receiver->view);
free(subghz_receiver); free(subghz_receiver);
} }
@ -529,4 +616,4 @@ void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, st
"Preset: %d\n", "Preset: %d\n",
(int)frequency, (int)frequency,
(int)preset); (int)preset);
} }

View File

@ -36,8 +36,13 @@ void subghz_receiver_set_protocol(
SubghzReceiver* subghz_receiver, SubghzReceiver* subghz_receiver,
SubGhzProtocolCommon* protocol_result, SubGhzProtocolCommon* protocol_result,
SubGhzProtocol* protocol); SubGhzProtocol* protocol);
SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver); SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver);
void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker); void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker);
uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver); uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver);
FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver); FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver);
void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output); void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output);

View File

@ -1,11 +0,0 @@
#pragma once
#include <gui/view.h>
typedef struct SubghzStatic SubghzStatic;
SubghzStatic* subghz_static_alloc();
void subghz_static_free(SubghzStatic* subghz_static);
View* subghz_static_get_view(SubghzStatic* subghz_static);

View File

@ -1,4 +1,4 @@
#include "subghz_static.h" #include "subghz_test_static.h"
#include "../subghz_i.h" #include "../subghz_i.h"
#include <math.h> #include <math.h>
@ -8,30 +8,30 @@
#include <notification/notification-messages.h> #include <notification/notification-messages.h>
#include <lib/subghz/protocols/subghz_protocol_princeton.h> #include <lib/subghz/protocols/subghz_protocol_princeton.h>
static const uint32_t subghz_static_keys[] = { static const uint32_t subghz_test_static_keys[] = {
0x0074BADE, 0x0074BADE,
0x0074BADD, 0x0074BADD,
0x0074BADB, 0x0074BADB,
0x00E34A4E, 0x00E34A4E,
}; };
struct SubghzStatic { struct SubghzTestStatic {
View* view; View* view;
SubGhzEncoderPrinceton* encoder; SubGhzEncoderPrinceton* encoder;
}; };
typedef enum { typedef enum {
SubghzStaticStatusRx, SubghzTestStaticStatusRx,
SubghzStaticStatusTx, SubghzTestStaticStatusTx,
} SubghzStaticStatus; } SubghzTestStaticStatus;
typedef struct { typedef struct {
uint8_t frequency; uint8_t frequency;
uint32_t real_frequency; uint32_t real_frequency;
uint8_t button; uint8_t button;
} SubghzStaticModel; } SubghzTestStaticModel;
void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) { void subghz_test_static_draw(Canvas* canvas, SubghzTestStaticModel* model) {
char buffer[64]; char buffer[64];
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
@ -52,24 +52,21 @@ void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) {
canvas_draw_str(canvas, 0, 31, buffer); canvas_draw_str(canvas, 0, 31, buffer);
} }
bool subghz_static_input(InputEvent* event, void* context) { bool subghz_test_static_input(InputEvent* event, void* context) {
furi_assert(context); furi_assert(context);
SubghzStatic* instance = context; SubghzTestStatic* instance = context;
if(event->key == InputKeyBack) { if(event->key == InputKeyBack) {
return false; return false;
} }
with_view_model( with_view_model(
instance->view, (SubghzStaticModel * model) { instance->view, (SubghzTestStaticModel * model) {
bool reconfigure = false;
if(event->type == InputTypeShort) { if(event->type == InputTypeShort) {
if(event->key == InputKeyLeft) { if(event->key == InputKeyLeft) {
if(model->frequency > 0) model->frequency--; if(model->frequency > 0) model->frequency--;
reconfigure = true;
} else if(event->key == InputKeyRight) { } else if(event->key == InputKeyRight) {
if(model->frequency < subghz_frequencies_count - 1) model->frequency++; if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
reconfigure = true;
} else if(event->key == InputKeyDown) { } else if(event->key == InputKeyDown) {
if(model->button > 0) model->button--; if(model->button > 0) model->button--;
} else if(event->key == InputKeyUp) { } else if(event->key == InputKeyUp) {
@ -77,28 +74,29 @@ bool subghz_static_input(InputEvent* event, void* context) {
} }
} }
if(reconfigure) { model->real_frequency = subghz_frequencies[model->frequency];
furi_hal_subghz_idle();
model->real_frequency =
furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
furi_hal_subghz_tx();
}
if(event->key == InputKeyOk) { if(event->key == InputKeyOk) {
NotificationApp* notification = furi_record_open("notification");
if(event->type == InputTypePress) { if(event->type == InputTypePress) {
NotificationApp* notification = furi_record_open("notification");
notification_message_block(notification, &sequence_set_red_255); notification_message_block(notification, &sequence_set_red_255);
FURI_LOG_I("SubghzTestStatic", "TX Start");
furi_hal_subghz_idle();
furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
subghz_encoder_princeton_set( subghz_encoder_princeton_set(
instance->encoder, subghz_static_keys[model->button], 20); instance->encoder, subghz_test_static_keys[model->button], 10000);
furi_hal_subghz_start_async_tx( furi_hal_subghz_start_async_tx(
subghz_encoder_princeton_yield, instance->encoder); subghz_encoder_princeton_yield, instance->encoder);
while(!furi_hal_subghz_is_async_tx_complete()) osDelay(33); } else if(event->type == InputTypeRelease) {
FURI_LOG_I("SubghzTestStatic", "TX Stop");
furi_hal_subghz_stop_async_tx(); furi_hal_subghz_stop_async_tx();
notification_message(notification, &sequence_reset_red); notification_message(notification, &sequence_reset_red);
furi_record_close("notification");
} }
furi_record_close("notification");
} }
return true; return true;
@ -107,9 +105,9 @@ bool subghz_static_input(InputEvent* event, void* context) {
return true; return true;
} }
void subghz_static_enter(void* context) { void subghz_test_static_enter(void* context) {
furi_assert(context); furi_assert(context);
SubghzStatic* instance = context; SubghzTestStatic* instance = context;
furi_hal_subghz_reset(); furi_hal_subghz_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
@ -118,47 +116,44 @@ void subghz_static_enter(void* context) {
hal_gpio_write(&gpio_cc1101_g0, false); hal_gpio_write(&gpio_cc1101_g0, false);
with_view_model( with_view_model(
instance->view, (SubghzStaticModel * model) { instance->view, (SubghzTestStaticModel * model) {
model->frequency = subghz_frequencies_433_92; model->frequency = subghz_frequencies_433_92;
model->real_frequency = model->real_frequency = subghz_frequencies[model->frequency];
furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
model->button = 0; model->button = 0;
return true; return true;
}); });
furi_hal_subghz_tx();
} }
void subghz_static_exit(void* context) { void subghz_test_static_exit(void* context) {
furi_assert(context); furi_assert(context);
furi_hal_subghz_sleep(); furi_hal_subghz_sleep();
} }
SubghzStatic* subghz_static_alloc() { SubghzTestStatic* subghz_test_static_alloc() {
SubghzStatic* instance = furi_alloc(sizeof(SubghzStatic)); SubghzTestStatic* instance = furi_alloc(sizeof(SubghzTestStatic));
// View allocation and configuration // View allocation and configuration
instance->view = view_alloc(); instance->view = view_alloc();
view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzStaticModel)); view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzTestStaticModel));
view_set_context(instance->view, instance); view_set_context(instance->view, instance);
view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_static_draw); view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_test_static_draw);
view_set_input_callback(instance->view, subghz_static_input); view_set_input_callback(instance->view, subghz_test_static_input);
view_set_enter_callback(instance->view, subghz_static_enter); view_set_enter_callback(instance->view, subghz_test_static_enter);
view_set_exit_callback(instance->view, subghz_static_exit); view_set_exit_callback(instance->view, subghz_test_static_exit);
instance->encoder = subghz_encoder_princeton_alloc(); instance->encoder = subghz_encoder_princeton_alloc();
return instance; return instance;
} }
void subghz_static_free(SubghzStatic* instance) { void subghz_test_static_free(SubghzTestStatic* instance) {
furi_assert(instance); furi_assert(instance);
subghz_encoder_princeton_free(instance->encoder); subghz_encoder_princeton_free(instance->encoder);
view_free(instance->view); view_free(instance->view);
free(instance); free(instance);
} }
View* subghz_static_get_view(SubghzStatic* instance) { View* subghz_test_static_get_view(SubghzTestStatic* instance) {
furi_assert(instance); furi_assert(instance);
return instance->view; return instance->view;
} }

View File

@ -0,0 +1,11 @@
#pragma once
#include <gui/view.h>
typedef struct SubghzTestStatic SubghzTestStatic;
SubghzTestStatic* subghz_test_static_alloc();
void subghz_test_static_free(SubghzTestStatic* subghz_static);
View* subghz_test_static_get_view(SubghzTestStatic* subghz_static);

View File

@ -65,7 +65,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
//Simple Learning //Simple Learning
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -78,7 +79,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -88,7 +90,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
// Simple Learning // Simple Learning
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -102,7 +105,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
} }
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -114,7 +118,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -129,7 +134,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
if((decrypt >> 28 == btn) && if((decrypt >> 28 == btn) &&
((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) ||
((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) {
instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->manufacture_name = string_get_cstr(manufacture_code->name);
instance->common.cnt = decrypt & 0x0000FFFF; instance->common.cnt = decrypt & 0x0000FFFF;
return 1; return 1;
@ -453,4 +459,4 @@ void subghz_decoder_keeloq_to_load_protocol(
instance->common.code_last_found = data->code_found; instance->common.code_last_found = data->code_found;
instance->common.code_last_count_bit = data->code_count_bit; instance->common.code_last_count_bit = data->code_count_bit;
subghz_protocol_keeloq_check_remote_controller(instance); subghz_protocol_keeloq_check_remote_controller(instance);
} }

View File

@ -5,7 +5,7 @@
* *
*/ */
#define SUBGHZ_PT_SHORT 450 #define SUBGHZ_PT_SHORT 400
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30) #define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
@ -86,7 +86,7 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
instance->common.code_min_count_bit_for_found = 24; instance->common.code_min_count_bit_for_found = 24;
instance->common.te_short = SUBGHZ_PT_SHORT; //150; instance->common.te_short = SUBGHZ_PT_SHORT; //150;
instance->common.te_long = SUBGHZ_PT_LONG; //450; instance->common.te_long = SUBGHZ_PT_LONG; //450;
instance->common.te_delta = 200; //50; instance->common.te_delta = 250; //50;
instance->common.type_protocol = TYPE_PROTOCOL_STATIC; instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
instance->common.to_save_string = instance->common.to_save_string =