[FL-1496] SubGhz: Library, Cli, Application (#543)
* ApiHal: set frequency and path in one go. Drivers: proper frequency registers calculation for CC1101. Update subghz cli to match new api. * SubGhz: preparation for parsers porting, tim2 sharing * ApiHal: add interrupts API, move all TIM2 related things there. * SubGhz: refactor protocol lib and add keeloq. * SubGhz: proper init_set for keeloq manafacture key * SubGhz: port more protocols to lib * SubGhz: load keeloq manufacture keys from sd card (if any). * SubGhz: format output from protocols. * SubGhz: use default frequency in subghz_rx cli command. * SubGhz: keeloq key types * Fix compillation error when internal storage disabled * SubGhz: minor cleanup * SubGhz: properly handle timeout and reset signal in subghz_rx * SubGhz: Worker, Capture View. Furi: emulate thread join. * SubGhz: free strings on keeloq key load end * SubGhz: update protocols reporting API, app refactoring and capture view, update API HAL usage. * SubGhz: update dump formatting * ApiHal: backport subghz preset to F5 * ApiHal: backport subghz frequency range to F5
This commit is contained in:
@@ -184,7 +184,8 @@ const FlipperApplication FLIPPER_APPS[] = {
|
||||
#endif
|
||||
|
||||
#ifdef APP_SUBGHZ
|
||||
{.app = subghz_app, .name = "Sub-1 GHz", .stack_size = 1024, .icon = A_Sub1ghz_14},
|
||||
// TODO: decrease stack after SD API refactoring
|
||||
{.app = subghz_app, .name = "Sub-1 GHz", .stack_size = 4096, .icon = A_Sub1ghz_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_LF_RFID
|
||||
|
@@ -1,83 +1,33 @@
|
||||
#include "subghz_i.h"
|
||||
|
||||
const SubGhzFrequency subghz_frequencies[] = {
|
||||
/* 301 */
|
||||
{
|
||||
.frequency = 301000000,
|
||||
.path = ApiHalSubGhzPath315,
|
||||
},
|
||||
/* 315 */
|
||||
{
|
||||
.frequency = 315000000,
|
||||
.path = ApiHalSubGhzPath315,
|
||||
},
|
||||
/* 346 - 385 */
|
||||
{
|
||||
.frequency = 346000000,
|
||||
.path = ApiHalSubGhzPath315,
|
||||
},
|
||||
{
|
||||
.frequency = 385000000,
|
||||
.path = ApiHalSubGhzPath315,
|
||||
},
|
||||
/* LPD433 first, mid, last channels */
|
||||
{
|
||||
.frequency = 433075000,
|
||||
.path = ApiHalSubGhzPath433,
|
||||
},
|
||||
{
|
||||
.frequency = 433920000,
|
||||
.path = ApiHalSubGhzPath433,
|
||||
},
|
||||
{
|
||||
.frequency = 434775000,
|
||||
.path = ApiHalSubGhzPath433,
|
||||
},
|
||||
/* 438.9 - 781 */
|
||||
{
|
||||
.frequency = 438900000,
|
||||
.path = ApiHalSubGhzPath433,
|
||||
},
|
||||
{
|
||||
.frequency = 463000000,
|
||||
.path = ApiHalSubGhzPath433,
|
||||
},
|
||||
{
|
||||
.frequency = 781000000,
|
||||
.path = ApiHalSubGhzPath868,
|
||||
},
|
||||
/* 868.35 */
|
||||
{
|
||||
.frequency = 868350000,
|
||||
.path = ApiHalSubGhzPath868,
|
||||
},
|
||||
/* 915 */
|
||||
{
|
||||
.frequency = 915000000,
|
||||
.path = ApiHalSubGhzPath868,
|
||||
},
|
||||
/* 925 */
|
||||
{
|
||||
.frequency = 925000000,
|
||||
.path = ApiHalSubGhzPath868,
|
||||
},
|
||||
const uint32_t subghz_frequencies[] = {
|
||||
/* 300 - 348 */
|
||||
300000000,
|
||||
315000000,
|
||||
348000000,
|
||||
/* 387 - 464 */
|
||||
387000000,
|
||||
433075000, /* LPD433 first */
|
||||
433920000, /* LPD433 mid */
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
464000000,
|
||||
/* 779 - 928 */
|
||||
779000000,
|
||||
868350000,
|
||||
915000000,
|
||||
925000000,
|
||||
928000000,
|
||||
};
|
||||
|
||||
const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(SubGhzFrequency);
|
||||
const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t);
|
||||
const uint32_t subghz_frequencies_433_92 = 5;
|
||||
|
||||
void subghz_menu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(index == 0) {
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTestBasic);
|
||||
} else if(index == 1) {
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTestPacket);
|
||||
} else if(index == 2) {
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewStatic);
|
||||
}
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, index);
|
||||
}
|
||||
|
||||
uint32_t subghz_exit(void* context) {
|
||||
@@ -98,14 +48,25 @@ SubGhz* subghz_alloc() {
|
||||
|
||||
// Menu
|
||||
subghz->submenu = submenu_alloc();
|
||||
submenu_add_item(subghz->submenu, "Basic Test", 0, subghz_menu_callback, subghz);
|
||||
submenu_add_item(subghz->submenu, "Packet Test", 1, subghz_menu_callback, subghz);
|
||||
submenu_add_item(subghz->submenu, "Static Code", 2, subghz_menu_callback, subghz);
|
||||
submenu_add_item(subghz->submenu, "Capture", SubGhzViewCapture, subghz_menu_callback, subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Basic Test", SubGhzViewTestBasic, subghz_menu_callback, subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Packet Test", SubGhzViewTestPacket, subghz_menu_callback, subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu, "Static Code", SubGhzViewStatic, subghz_menu_callback, subghz);
|
||||
|
||||
View* submenu_view = submenu_get_view(subghz->submenu);
|
||||
view_set_previous_callback(submenu_view, subghz_exit);
|
||||
view_dispatcher_add_view(subghz->view_dispatcher, SubGhzViewMenu, submenu_view);
|
||||
|
||||
// Capture
|
||||
subghz->subghz_capture = subghz_capture_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher,
|
||||
SubGhzViewCapture,
|
||||
subghz_capture_get_view(subghz->subghz_capture));
|
||||
|
||||
// Basic Test Module
|
||||
subghz->subghz_test_basic = subghz_test_basic_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@@ -150,6 +111,10 @@ void subghz_free(SubGhz* subghz) {
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu);
|
||||
submenu_free(subghz->submenu);
|
||||
|
||||
// Capture
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewCapture);
|
||||
subghz_capture_free(subghz->subghz_capture);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(subghz->view_dispatcher);
|
||||
|
||||
|
161
applications/subghz/subghz_cli.c
Executable file → Normal file
161
applications/subghz/subghz_cli.c
Executable file → Normal file
@@ -1,6 +1,11 @@
|
||||
#include "subghz_cli.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <stream_buffer.h>
|
||||
|
||||
#define CC1101_FREQUENCY_RANGE_STR \
|
||||
"300000000...348000000 or 387000000...464000000 or 779000000...928000000"
|
||||
|
||||
static const uint8_t subghz_test_packet_data[] = {
|
||||
0x30, // 48bytes to transmit
|
||||
@@ -9,6 +14,15 @@ static const uint8_t subghz_test_packet_data[] = {
|
||||
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
|
||||
};
|
||||
|
||||
bool subghz_check_frequency_range(uint32_t frequency) {
|
||||
if(!(frequency >= 300000000 && frequency <= 348000000) &&
|
||||
!(frequency >= 387000000 && frequency <= 464000000) &&
|
||||
!(frequency >= 779000000 && frequency <= 928000000)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_cli_init() {
|
||||
Cli* cli = furi_record_open("cli");
|
||||
|
||||
@@ -16,12 +30,14 @@ void subghz_cli_init() {
|
||||
cli_add_command(cli, "subghz_rx_carrier", subghz_cli_command_rx_carrier, NULL);
|
||||
cli_add_command(cli, "subghz_tx_pt", subghz_cli_command_tx_pt, NULL);
|
||||
cli_add_command(cli, "subghz_rx_pt", subghz_cli_command_rx_pt, NULL);
|
||||
cli_add_command(cli, "subghz_tx", subghz_cli_command_tx, NULL);
|
||||
cli_add_command(cli, "subghz_rx", subghz_cli_command_rx, NULL);
|
||||
|
||||
furi_record_close("cli");
|
||||
}
|
||||
|
||||
void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
|
||||
uint32_t frequency;
|
||||
uint32_t frequency = 0;
|
||||
int ret = sscanf(string_get_cstr(args), "%lu", &frequency);
|
||||
if(ret != 1) {
|
||||
printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
|
||||
@@ -29,23 +45,17 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(frequency < 300000000 || frequency > 925000000) {
|
||||
printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency);
|
||||
if(!subghz_check_frequency_range(frequency)) {
|
||||
printf(
|
||||
"Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency);
|
||||
return;
|
||||
}
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync);
|
||||
frequency = api_hal_subghz_set_frequency(frequency);
|
||||
frequency = api_hal_subghz_set_frequency_and_path(frequency);
|
||||
printf("Transmitting at frequency %lu Hz\r\n", frequency);
|
||||
printf("Press CTRL+C to stop\r\n");
|
||||
if(frequency < 400000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath315);
|
||||
} else if(frequency < 500000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath433);
|
||||
} else {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath868);
|
||||
}
|
||||
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
hal_gpio_write(&gpio_cc1101_g0, false);
|
||||
@@ -62,7 +72,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
|
||||
void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
|
||||
uint32_t frequency;
|
||||
uint32_t frequency = 0;
|
||||
int ret = sscanf(string_get_cstr(args), "%lu", &frequency);
|
||||
if(ret != 1) {
|
||||
printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
|
||||
@@ -70,23 +80,17 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(frequency < 300000000 || frequency > 925000000) {
|
||||
printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency);
|
||||
if(!subghz_check_frequency_range(frequency)) {
|
||||
printf(
|
||||
"Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency);
|
||||
return;
|
||||
}
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync);
|
||||
frequency = api_hal_subghz_set_frequency(frequency);
|
||||
frequency = api_hal_subghz_set_frequency_and_path(frequency);
|
||||
printf("Receiving at frequency %lu Hz\r\n", frequency);
|
||||
printf("Press CTRL+C to stop\r\n");
|
||||
if(frequency < 400000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath315);
|
||||
} else if(frequency < 500000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath433);
|
||||
} else {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath868);
|
||||
}
|
||||
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
@@ -103,7 +107,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
|
||||
void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) {
|
||||
uint32_t frequency;
|
||||
uint32_t frequency = 0;
|
||||
uint32_t pattern;
|
||||
uint32_t count;
|
||||
|
||||
@@ -120,8 +124,9 @@ void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(frequency < 300000000 || frequency > 925000000) {
|
||||
printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency);
|
||||
if(!subghz_check_frequency_range(frequency)) {
|
||||
printf(
|
||||
"Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency);
|
||||
return;
|
||||
}
|
||||
if(pattern > 1) {
|
||||
@@ -133,14 +138,7 @@ void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) {
|
||||
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket);
|
||||
|
||||
frequency = api_hal_subghz_set_frequency(frequency);
|
||||
if(frequency < 400000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath315);
|
||||
} else if(frequency < 500000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath433);
|
||||
} else {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath868);
|
||||
}
|
||||
frequency = api_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
uint8_t status = api_hal_subghz_get_status();
|
||||
@@ -163,7 +161,7 @@ void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
|
||||
void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) {
|
||||
uint32_t frequency;
|
||||
uint32_t frequency = 0;
|
||||
|
||||
int ret = sscanf(string_get_cstr(args), "%lu", &frequency);
|
||||
if(ret != 1) {
|
||||
@@ -172,8 +170,9 @@ void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(frequency < 300000000 || frequency > 925000000) {
|
||||
printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency);
|
||||
if(!subghz_check_frequency_range(frequency)) {
|
||||
printf(
|
||||
"Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", frequency);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -181,14 +180,7 @@ void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) {
|
||||
api_hal_subghz_idle();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket);
|
||||
|
||||
frequency = api_hal_subghz_set_frequency(frequency);
|
||||
if(frequency < 400000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath315);
|
||||
} else if(frequency < 500000000) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath433);
|
||||
} else {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPath868);
|
||||
}
|
||||
frequency = api_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
uint8_t status = api_hal_subghz_get_status();
|
||||
@@ -216,3 +208,84 @@ void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) {
|
||||
api_hal_subghz_set_path(ApiHalSubGhzPathIsolate);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
|
||||
#include <fl_subghz/protocols/subghz_protocol.h>
|
||||
|
||||
volatile bool subghz_cli_overrun = false;
|
||||
|
||||
void subghz_cli_command_rx_callback(
|
||||
ApiHalSubGhzCaptureLevel level,
|
||||
uint32_t duration,
|
||||
void* context) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
LevelPair pair = {.level = level, .duration = duration};
|
||||
if(subghz_cli_overrun) {
|
||||
subghz_cli_overrun = false;
|
||||
pair.level = ApiHalSubGhzCaptureLevelOverrun;
|
||||
}
|
||||
size_t ret =
|
||||
xStreamBufferSendFromISR(context, &pair, sizeof(LevelPair), &xHigherPriorityTaskWoken);
|
||||
if(sizeof(LevelPair) != ret) subghz_cli_overrun = true;
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
uint32_t frequency = 433920000;
|
||||
if(string_size(args)) {
|
||||
int ret = sscanf(string_get_cstr(args), "%lu", &frequency);
|
||||
if(ret != 1) {
|
||||
printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency);
|
||||
cli_print_usage("subghz_rx", "<Frequency in HZ>", string_get_cstr(args));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!subghz_check_frequency_range(frequency)) {
|
||||
printf(
|
||||
"Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n",
|
||||
frequency);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_idle();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPresetMP);
|
||||
|
||||
SubGhzProtocol* protocol = subghz_protocol_alloc();
|
||||
subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_enable_dump(protocol, NULL, NULL);
|
||||
|
||||
frequency = api_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
StreamBufferHandle_t rx_stream =
|
||||
xStreamBufferCreate(sizeof(LevelPair) * 1024, sizeof(LevelPair));
|
||||
|
||||
api_hal_subghz_set_capture_callback(subghz_cli_command_rx_callback, rx_stream);
|
||||
api_hal_subghz_enable_capture();
|
||||
|
||||
api_hal_subghz_flush_rx();
|
||||
api_hal_subghz_rx();
|
||||
|
||||
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
|
||||
LevelPair pair;
|
||||
while(!cli_cmd_interrupt_received(cli)) {
|
||||
int ret = xStreamBufferReceive(rx_stream, &pair, sizeof(LevelPair), 10);
|
||||
if(ret == sizeof(LevelPair)) {
|
||||
if(pair.level == ApiHalSubGhzCaptureLevelOverrun) {
|
||||
printf(".");
|
||||
subghz_protocol_reset(protocol);
|
||||
} else {
|
||||
subghz_protocol_parse(protocol, pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subghz_protocol_free(protocol);
|
||||
vStreamBufferDelete(rx_stream);
|
||||
api_hal_subghz_disable_capture();
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
@@ -11,3 +11,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context);
|
||||
void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context);
|
||||
|
||||
void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context);
|
||||
|
||||
void subghz_cli_command_tx(Cli* cli, string_t args, void* context);
|
||||
|
||||
void subghz_cli_command_rx(Cli* cli, string_t args, void* context);
|
||||
|
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz.h"
|
||||
#include "subghz_test_basic.h"
|
||||
#include "subghz_test_packet.h"
|
||||
#include "subghz_static.h"
|
||||
#include "views/subghz_capture.h"
|
||||
#include "views/subghz_test_basic.h"
|
||||
#include "views/subghz_test_packet.h"
|
||||
#include "views/subghz_static.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
@@ -11,12 +12,7 @@
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t frequency;
|
||||
uint8_t path;
|
||||
} SubGhzFrequency;
|
||||
|
||||
extern const SubGhzFrequency subghz_frequencies[];
|
||||
extern const uint32_t subghz_frequencies[];
|
||||
extern const uint32_t subghz_frequencies_count;
|
||||
extern const uint32_t subghz_frequencies_433_92;
|
||||
|
||||
@@ -27,6 +23,8 @@ struct SubGhz {
|
||||
|
||||
Submenu* submenu;
|
||||
|
||||
SubghzCapture* subghz_capture;
|
||||
|
||||
SubghzTestBasic* subghz_test_basic;
|
||||
|
||||
SubghzTestPacket* subghz_test_packet;
|
||||
@@ -36,6 +34,7 @@ struct SubGhz {
|
||||
|
||||
typedef enum {
|
||||
SubGhzViewMenu,
|
||||
SubGhzViewCapture,
|
||||
SubGhzViewTestBasic,
|
||||
SubGhzViewTestPacket,
|
||||
SubGhzViewStatic,
|
||||
|
188
applications/subghz/views/subghz_capture.c
Normal file
188
applications/subghz/views/subghz_capture.c
Normal file
@@ -0,0 +1,188 @@
|
||||
#include "subghz_capture.h"
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <notification/notification-messages.h>
|
||||
|
||||
#include <fl_subghz/subghz_worker.h>
|
||||
#include <fl_subghz/protocols/subghz_protocol.h>
|
||||
|
||||
struct SubghzCapture {
|
||||
View* view;
|
||||
SubGhzWorker* worker;
|
||||
SubGhzProtocol* protocol;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t frequency;
|
||||
uint32_t real_frequency;
|
||||
uint32_t counter;
|
||||
string_t text;
|
||||
} SubghzCaptureModel;
|
||||
|
||||
static const char subghz_symbols[] = {'-', '\\', '|', '/'};
|
||||
|
||||
void subghz_capture_draw(Canvas* canvas, SubghzCaptureModel* model) {
|
||||
char buffer[64];
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"Capture: %03ld.%03ldMHz %c",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000,
|
||||
subghz_symbols[model->counter % 4]);
|
||||
canvas_draw_str(canvas, 2, 12, buffer);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text(canvas, 0, 24, string_get_cstr(model->text));
|
||||
}
|
||||
|
||||
bool subghz_capture_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzCapture* subghz_capture = context;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
with_view_model(
|
||||
subghz_capture->view, (SubghzCaptureModel * model) {
|
||||
bool reconfigure = false;
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->frequency > 0) model->frequency--;
|
||||
reconfigure = true;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
|
||||
reconfigure = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(reconfigure) {
|
||||
api_hal_subghz_idle();
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_rx();
|
||||
}
|
||||
|
||||
return reconfigure;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_capture_text_callback(string_t text, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzCapture* subghz_capture = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_capture->view, (SubghzCaptureModel * model) {
|
||||
model->counter++;
|
||||
string_set(model->text, text);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void subghz_capture_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzCapture* subghz_capture = context;
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_idle();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPresetMP);
|
||||
|
||||
with_view_model(
|
||||
subghz_capture->view, (SubghzCaptureModel * model) {
|
||||
model->frequency = subghz_frequencies_433_92;
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
|
||||
return true;
|
||||
});
|
||||
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
api_hal_subghz_set_capture_callback(subghz_worker_rx_callback, subghz_capture->worker);
|
||||
api_hal_subghz_enable_capture();
|
||||
|
||||
subghz_worker_start(subghz_capture->worker);
|
||||
|
||||
api_hal_subghz_flush_rx();
|
||||
api_hal_subghz_rx();
|
||||
}
|
||||
|
||||
void subghz_capture_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzCapture* subghz_capture = context;
|
||||
|
||||
subghz_worker_stop(subghz_capture->worker);
|
||||
|
||||
api_hal_subghz_disable_capture();
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
||||
uint32_t subghz_capture_back(void* context) {
|
||||
return SubGhzViewMenu;
|
||||
}
|
||||
|
||||
SubghzCapture* subghz_capture_alloc() {
|
||||
SubghzCapture* subghz_capture = furi_alloc(sizeof(SubghzCapture));
|
||||
|
||||
// View allocation and configuration
|
||||
subghz_capture->view = view_alloc();
|
||||
view_allocate_model(subghz_capture->view, ViewModelTypeLocking, sizeof(SubghzCaptureModel));
|
||||
view_set_context(subghz_capture->view, subghz_capture);
|
||||
view_set_draw_callback(subghz_capture->view, (ViewDrawCallback)subghz_capture_draw);
|
||||
view_set_input_callback(subghz_capture->view, subghz_capture_input);
|
||||
view_set_enter_callback(subghz_capture->view, subghz_capture_enter);
|
||||
view_set_exit_callback(subghz_capture->view, subghz_capture_exit);
|
||||
view_set_previous_callback(subghz_capture->view, subghz_capture_back);
|
||||
|
||||
with_view_model(
|
||||
subghz_capture->view, (SubghzCaptureModel * model) {
|
||||
string_init(model->text);
|
||||
return true;
|
||||
});
|
||||
|
||||
subghz_capture->worker = subghz_worker_alloc();
|
||||
subghz_capture->protocol = subghz_protocol_alloc();
|
||||
|
||||
subghz_worker_set_overrun_callback(
|
||||
subghz_capture->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||
subghz_worker_set_pair_callback(
|
||||
subghz_capture->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||
subghz_worker_set_context(subghz_capture->worker, subghz_capture->protocol);
|
||||
|
||||
subghz_protocol_load_keeloq_file(subghz_capture->protocol, "/assets/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_enable_dump(
|
||||
subghz_capture->protocol, subghz_capture_text_callback, subghz_capture);
|
||||
|
||||
return subghz_capture;
|
||||
}
|
||||
|
||||
void subghz_capture_free(SubghzCapture* subghz_capture) {
|
||||
furi_assert(subghz_capture);
|
||||
|
||||
subghz_protocol_free(subghz_capture->protocol);
|
||||
subghz_worker_free(subghz_capture->worker);
|
||||
|
||||
with_view_model(
|
||||
subghz_capture->view, (SubghzCaptureModel * model) {
|
||||
string_clear(model->text);
|
||||
return true;
|
||||
});
|
||||
view_free(subghz_capture->view);
|
||||
free(subghz_capture);
|
||||
}
|
||||
|
||||
View* subghz_capture_get_view(SubghzCapture* subghz_capture) {
|
||||
furi_assert(subghz_capture);
|
||||
return subghz_capture->view;
|
||||
}
|
11
applications/subghz/views/subghz_capture.h
Normal file
11
applications/subghz/views/subghz_capture.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct SubghzCapture SubghzCapture;
|
||||
|
||||
SubghzCapture* subghz_capture_alloc();
|
||||
|
||||
void subghz_capture_free(SubghzCapture* subghz_capture);
|
||||
|
||||
View* subghz_capture_get_view(SubghzCapture* subghz_capture);
|
@@ -1,5 +1,5 @@
|
||||
#include "subghz_static.h"
|
||||
#include "subghz_i.h"
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
@@ -30,7 +30,6 @@ typedef enum {
|
||||
typedef struct {
|
||||
uint8_t frequency;
|
||||
uint32_t real_frequency;
|
||||
ApiHalSubGhzPath path;
|
||||
uint8_t button;
|
||||
} SubghzStaticModel;
|
||||
|
||||
@@ -51,21 +50,8 @@ void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) {
|
||||
model->real_frequency / 1000 % 1000,
|
||||
model->real_frequency % 1000);
|
||||
canvas_draw_str(canvas, 2, 24, buffer);
|
||||
// Path
|
||||
char* path_name = "Unknown";
|
||||
if(model->path == ApiHalSubGhzPathIsolate) {
|
||||
path_name = "isolate";
|
||||
} else if(model->path == ApiHalSubGhzPath433) {
|
||||
path_name = "433MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath315) {
|
||||
path_name = "315MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath868) {
|
||||
path_name = "868MHz";
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name);
|
||||
canvas_draw_str(canvas, 2, 36, buffer);
|
||||
snprintf(buffer, sizeof(buffer), "Key: %d", model->button);
|
||||
canvas_draw_str(canvas, 2, 48, buffer);
|
||||
canvas_draw_str(canvas, 2, 36, buffer);
|
||||
}
|
||||
|
||||
bool subghz_static_input(InputEvent* event, void* context) {
|
||||
@@ -91,14 +77,12 @@ bool subghz_static_input(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyUp) {
|
||||
if(model->button < 3) model->button++;
|
||||
}
|
||||
model->path = subghz_frequencies[model->frequency].path;
|
||||
}
|
||||
|
||||
if(reconfigure) {
|
||||
api_hal_subghz_idle();
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
api_hal_subghz_set_path(model->path);
|
||||
api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_tx();
|
||||
}
|
||||
|
||||
@@ -154,10 +138,8 @@ void subghz_static_enter(void* context) {
|
||||
subghz_static->view, (SubghzStaticModel * model) {
|
||||
model->frequency = subghz_frequencies_433_92;
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
model->path = subghz_frequencies[model->frequency].path;
|
||||
api_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]);
|
||||
model->button = 0;
|
||||
api_hal_subghz_set_path(model->path);
|
||||
return true;
|
||||
});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#include "subghz_test_basic.h"
|
||||
#include "subghz_i.h"
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
@@ -98,7 +98,7 @@ bool subghz_test_basic_input(InputEvent* event, void* context) {
|
||||
}
|
||||
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_set_path(model->path);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ void subghz_test_basic_enter(void* context) {
|
||||
subghz_test_basic->view, (SubghzTestBasicModel * model) {
|
||||
model->frequency = subghz_frequencies_433_92; // 433
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
model->path = ApiHalSubGhzPathIsolate; // isolate
|
||||
model->rssi = 0.0f;
|
||||
model->status = SubghzTestBasicModelStatusRx;
|
@@ -1,5 +1,5 @@
|
||||
#include "subghz_test_packet.h"
|
||||
#include "subghz_i.h"
|
||||
#include "../subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
@@ -106,7 +106,7 @@ bool subghz_test_packet_input(InputEvent* event, void* context) {
|
||||
}
|
||||
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_set_path(model->path);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ void subghz_test_packet_enter(void* context) {
|
||||
subghz_test_packet->view, (SubghzTestPacketModel * model) {
|
||||
model->frequency = subghz_frequencies_433_92;
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency].frequency);
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
model->path = ApiHalSubGhzPathIsolate; // isolate
|
||||
model->rssi = 0.0f;
|
||||
model->status = SubghzTestPacketModelStatusRx;
|
Reference in New Issue
Block a user