mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-11-28 11:26:32 +03:00
Merge branch 'flipperdevices:dev' into dev
This commit is contained in:
commit
ab6b423436
@ -5,6 +5,7 @@
|
||||
#include <task_control_block.h>
|
||||
#include <time.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <loader/loader.h>
|
||||
|
||||
// Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'`
|
||||
#define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d"
|
||||
@ -146,6 +147,20 @@ void cli_command_vibro(Cli* cli, string_t args, void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
void cli_command_debug(Cli* cli, string_t args, void* context) {
|
||||
if(!string_cmp(args, "0")) {
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug);
|
||||
loader_update_menu();
|
||||
printf("Debug disabled.");
|
||||
} else if(!string_cmp(args, "1")) {
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagDebug);
|
||||
loader_update_menu();
|
||||
printf("Debug enabled.");
|
||||
} else {
|
||||
cli_print_usage("debug", "<1|0>", string_get_cstr(args));
|
||||
}
|
||||
}
|
||||
|
||||
void cli_command_led(Cli* cli, string_t args, void* context) {
|
||||
// Get first word as light name
|
||||
NotificationMessage notification_led_message;
|
||||
@ -348,6 +363,7 @@ void cli_commands_init(Cli* cli) {
|
||||
|
||||
cli_add_command(cli, "date", CliCommandFlagParallelSafe, cli_command_date, NULL);
|
||||
cli_add_command(cli, "log", CliCommandFlagParallelSafe, cli_command_log, NULL);
|
||||
cli_add_command(cli, "debug", CliCommandFlagDefault, cli_command_debug, NULL);
|
||||
cli_add_command(cli, "ps", CliCommandFlagParallelSafe, cli_command_ps, NULL);
|
||||
cli_add_command(cli, "free", CliCommandFlagParallelSafe, cli_command_free, NULL);
|
||||
cli_add_command(cli, "free_blocks", CliCommandFlagParallelSafe, cli_command_free_blocks, NULL);
|
||||
|
@ -211,12 +211,11 @@ void gui_redraw(Gui* gui) {
|
||||
}
|
||||
|
||||
canvas_commit(gui->canvas);
|
||||
if(gui->canvas_callback) {
|
||||
gui->canvas_callback(
|
||||
canvas_get_buffer(gui->canvas),
|
||||
canvas_get_buffer_size(gui->canvas),
|
||||
gui->canvas_callback_context);
|
||||
}
|
||||
for
|
||||
M_EACH(p, gui->canvas_callback_pair, CanvasCallbackPairArray_t) {
|
||||
p->callback(
|
||||
canvas_get_buffer(gui->canvas), canvas_get_buffer_size(gui->canvas), p->context);
|
||||
}
|
||||
gui_unlock(gui);
|
||||
}
|
||||
|
||||
@ -396,24 +395,36 @@ void gui_view_port_send_to_back(Gui* gui, ViewPort* view_port) {
|
||||
gui_unlock(gui);
|
||||
}
|
||||
|
||||
void gui_set_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) {
|
||||
void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) {
|
||||
furi_assert(gui);
|
||||
gui_lock(gui);
|
||||
gui->canvas_callback = callback;
|
||||
gui->canvas_callback_context = context;
|
||||
gui_unlock(gui);
|
||||
|
||||
if(callback != NULL) {
|
||||
gui_update(gui);
|
||||
}
|
||||
const CanvasCallbackPair p = {callback, context};
|
||||
|
||||
gui_lock(gui);
|
||||
|
||||
furi_assert(CanvasCallbackPairArray_count(gui->canvas_callback_pair, p) == 0);
|
||||
CanvasCallbackPairArray_push_back(gui->canvas_callback_pair, p);
|
||||
|
||||
gui_unlock(gui);
|
||||
gui_update(gui);
|
||||
}
|
||||
|
||||
GuiCanvasCommitCallback gui_get_framebuffer_callback(Gui* gui) {
|
||||
void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context) {
|
||||
furi_assert(gui);
|
||||
|
||||
const CanvasCallbackPair p = {callback, context};
|
||||
|
||||
gui_lock(gui);
|
||||
GuiCanvasCommitCallback callback = gui->canvas_callback;
|
||||
|
||||
furi_assert(CanvasCallbackPairArray_count(gui->canvas_callback_pair, p) == 1);
|
||||
CanvasCallbackPairArray_remove_val(gui->canvas_callback_pair, p);
|
||||
|
||||
gui_unlock(gui);
|
||||
return callback;
|
||||
}
|
||||
|
||||
size_t gui_get_framebuffer_size(Gui* gui) {
|
||||
furi_assert(gui);
|
||||
return canvas_get_buffer_size(gui->canvas);
|
||||
}
|
||||
|
||||
void gui_set_lockdown(Gui* gui, bool lockdown) {
|
||||
@ -437,9 +448,12 @@ Gui* gui_alloc() {
|
||||
}
|
||||
// Drawing canvas
|
||||
gui->canvas = canvas_init();
|
||||
CanvasCallbackPairArray_init(gui->canvas_callback_pair);
|
||||
|
||||
// Input
|
||||
gui->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL);
|
||||
gui->input_events = furi_record_open("input_events");
|
||||
|
||||
furi_check(gui->input_events);
|
||||
furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui);
|
||||
|
||||
|
@ -68,7 +68,7 @@ void gui_view_port_send_to_front(Gui* gui, ViewPort* view_port);
|
||||
*/
|
||||
void gui_view_port_send_to_back(Gui* gui, ViewPort* view_port);
|
||||
|
||||
/** Set gui canvas commit callback
|
||||
/** Add gui canvas commit callback
|
||||
*
|
||||
* This callback will be called upon Canvas commit Callback dispatched from GUI
|
||||
* thread and is time critical
|
||||
@ -77,16 +77,22 @@ void gui_view_port_send_to_back(Gui* gui, ViewPort* view_port);
|
||||
* @param callback GuiCanvasCommitCallback
|
||||
* @param context GuiCanvasCommitCallback context
|
||||
*/
|
||||
void gui_set_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context);
|
||||
void gui_add_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context);
|
||||
|
||||
/** Get gui canvas commit callback
|
||||
*
|
||||
* Can be used to check if some application is using framebufer
|
||||
/** Remove gui canvas commit callback
|
||||
*
|
||||
* @param gui Gui instance
|
||||
* @return GuiCanvasCommitCallback
|
||||
* @param callback GuiCanvasCommitCallback
|
||||
* @param context GuiCanvasCommitCallback context
|
||||
*/
|
||||
GuiCanvasCommitCallback gui_get_framebuffer_callback(Gui* gui);
|
||||
void gui_remove_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback, void* context);
|
||||
|
||||
/** Get gui canvas frame buffer size
|
||||
* *
|
||||
* @param gui Gui instance
|
||||
* @return size_t size of frame buffer in bytes
|
||||
*/
|
||||
size_t gui_get_framebuffer_size(Gui* gui);
|
||||
|
||||
/** Set lockdown mode
|
||||
*
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <furi.h>
|
||||
#include <m-array.h>
|
||||
#include <m-algo.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "canvas.h"
|
||||
@ -42,6 +43,17 @@
|
||||
|
||||
ARRAY_DEF(ViewPortArray, ViewPort*, M_PTR_OPLIST);
|
||||
|
||||
typedef struct {
|
||||
GuiCanvasCommitCallback callback;
|
||||
void* context;
|
||||
} CanvasCallbackPair;
|
||||
|
||||
ARRAY_DEF(CanvasCallbackPairArray, CanvasCallbackPair, M_POD_OPLIST);
|
||||
|
||||
#define M_OPL_CanvasCallbackPairArray_t() ARRAY_OPLIST(CanvasCallbackPairArray, M_POD_OPLIST)
|
||||
|
||||
ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t);
|
||||
|
||||
/** Gui structure */
|
||||
struct Gui {
|
||||
// Thread and lock
|
||||
@ -52,8 +64,7 @@ struct Gui {
|
||||
bool lockdown;
|
||||
ViewPortArray_t layers[GuiLayerMAX];
|
||||
Canvas* canvas;
|
||||
GuiCanvasCommitCallback canvas_callback;
|
||||
void* canvas_callback_context;
|
||||
CanvasCallbackPairArray_t canvas_callback_pair;
|
||||
|
||||
// Input
|
||||
osMessageQueueId_t input_queue;
|
||||
|
@ -623,7 +623,7 @@ RpcSession* rpc_session_open(Rpc* rpc) {
|
||||
rpc_add_handler(session, PB_Main_stop_session_tag, &rpc_handler);
|
||||
|
||||
session->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(session->thread, "RPC Session");
|
||||
furi_thread_set_name(session->thread, "RpcSessionWorker");
|
||||
furi_thread_set_stack_size(session->thread, 2048);
|
||||
furi_thread_set_context(session->thread, session);
|
||||
furi_thread_set_callback(session->thread, rpc_session_worker);
|
||||
@ -666,9 +666,10 @@ void rpc_add_handler(RpcSession* session, pb_size_t message_tag, RpcHandler* han
|
||||
RpcHandlerDict_set_at(session->handlers, message_tag, *handler);
|
||||
}
|
||||
|
||||
void rpc_send_and_release(RpcSession* session, PB_Main* message) {
|
||||
void rpc_send(RpcSession* session, PB_Main* message) {
|
||||
furi_assert(session);
|
||||
furi_assert(message);
|
||||
|
||||
pb_ostream_t ostream = PB_OSTREAM_SIZING;
|
||||
|
||||
#if SRV_RPC_DEBUG
|
||||
@ -695,6 +696,10 @@ void rpc_send_and_release(RpcSession* session, PB_Main* message) {
|
||||
osMutexRelease(session->callbacks_mutex);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void rpc_send_and_release(RpcSession* session, PB_Main* message) {
|
||||
rpc_send(session, message);
|
||||
pb_release(&PB_Main_msg, message);
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,25 @@
|
||||
|
||||
#define TAG "RpcGui"
|
||||
|
||||
typedef enum {
|
||||
RpcGuiWorkerFlagTransmit = (1 << 0),
|
||||
RpcGuiWorkerFlagExit = (1 << 1),
|
||||
} RpcGuiWorkerFlag;
|
||||
|
||||
#define RpcGuiWorkerFlagAny (RpcGuiWorkerFlagTransmit | RpcGuiWorkerFlagExit)
|
||||
|
||||
typedef struct {
|
||||
RpcSession* session;
|
||||
Gui* gui;
|
||||
|
||||
// Receive part
|
||||
ViewPort* virtual_display_view_port;
|
||||
uint8_t* virtual_display_buffer;
|
||||
|
||||
// Transmit
|
||||
PB_Main* transmit_frame;
|
||||
FuriThread* transmit_thread;
|
||||
|
||||
bool virtual_display_not_empty;
|
||||
bool is_streaming;
|
||||
} RpcGuiSystem;
|
||||
@ -17,25 +31,35 @@ typedef struct {
|
||||
static void
|
||||
rpc_system_gui_screen_stream_frame_callback(uint8_t* data, size_t size, void* context) {
|
||||
furi_assert(data);
|
||||
furi_assert(size == 1024);
|
||||
furi_assert(context);
|
||||
|
||||
RpcGuiSystem* rpc_gui = (RpcGuiSystem*)context;
|
||||
RpcSession* session = rpc_gui->session;
|
||||
uint8_t* buffer = rpc_gui->transmit_frame->content.gui_screen_frame.data->bytes;
|
||||
|
||||
PB_Main* frame = malloc(sizeof(PB_Main));
|
||||
furi_assert(size == rpc_gui->transmit_frame->content.gui_screen_frame.data->size);
|
||||
|
||||
frame->which_content = PB_Main_gui_screen_frame_tag;
|
||||
frame->command_status = PB_CommandStatus_OK;
|
||||
frame->content.gui_screen_frame.data = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(size));
|
||||
uint8_t* buffer = frame->content.gui_screen_frame.data->bytes;
|
||||
uint16_t* frame_size_msg = &frame->content.gui_screen_frame.data->size;
|
||||
*frame_size_msg = size;
|
||||
memcpy(buffer, data, size);
|
||||
|
||||
rpc_send_and_release(session, frame);
|
||||
osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit);
|
||||
}
|
||||
|
||||
free(frame);
|
||||
static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
RpcGuiSystem* rpc_gui = (RpcGuiSystem*)context;
|
||||
|
||||
while(true) {
|
||||
uint32_t flags = osThreadFlagsWait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever);
|
||||
if(flags & RpcGuiWorkerFlagTransmit) {
|
||||
rpc_send(rpc_gui->session, rpc_gui->transmit_frame);
|
||||
}
|
||||
if(flags & RpcGuiWorkerFlagExit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rpc_system_gui_start_screen_stream_process(const PB_Main* request, void* context) {
|
||||
@ -45,15 +69,30 @@ static void rpc_system_gui_start_screen_stream_process(const PB_Main* request, v
|
||||
|
||||
RpcSession* session = rpc_gui->session;
|
||||
furi_assert(session);
|
||||
furi_assert(!rpc_gui->is_streaming);
|
||||
|
||||
if(gui_get_framebuffer_callback(rpc_gui->gui) == NULL) {
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
rpc_gui->is_streaming = true;
|
||||
gui_set_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
} else {
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR_BUSY);
|
||||
}
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
|
||||
rpc_gui->is_streaming = true;
|
||||
size_t framebuffer_size = gui_get_framebuffer_size(rpc_gui->gui);
|
||||
// Reusable Frame
|
||||
rpc_gui->transmit_frame = malloc(sizeof(PB_Main));
|
||||
rpc_gui->transmit_frame->which_content = PB_Main_gui_screen_frame_tag;
|
||||
rpc_gui->transmit_frame->command_status = PB_CommandStatus_OK;
|
||||
rpc_gui->transmit_frame->content.gui_screen_frame.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(framebuffer_size));
|
||||
rpc_gui->transmit_frame->content.gui_screen_frame.data->size = framebuffer_size;
|
||||
// Transmission thread for async TX
|
||||
rpc_gui->transmit_thread = furi_thread_alloc();
|
||||
furi_thread_set_name(rpc_gui->transmit_thread, "GuiRpcWorker");
|
||||
furi_thread_set_callback(
|
||||
rpc_gui->transmit_thread, rpc_system_gui_screen_stream_frame_transmit_thread);
|
||||
furi_thread_set_context(rpc_gui->transmit_thread, rpc_gui);
|
||||
furi_thread_set_stack_size(rpc_gui->transmit_thread, 1024);
|
||||
furi_thread_start(rpc_gui->transmit_thread);
|
||||
// GUI framebuffer callback
|
||||
gui_add_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
}
|
||||
|
||||
static void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, void* context) {
|
||||
@ -66,7 +105,18 @@ static void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, vo
|
||||
|
||||
if(rpc_gui->is_streaming) {
|
||||
rpc_gui->is_streaming = false;
|
||||
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
||||
// Remove GUI framebuffer callback
|
||||
gui_remove_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
// Stop and release worker thread
|
||||
osThreadFlagsSet(
|
||||
furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit);
|
||||
furi_thread_join(rpc_gui->transmit_thread);
|
||||
furi_thread_free(rpc_gui->transmit_thread);
|
||||
// Release frame
|
||||
pb_release(&PB_Main_msg, rpc_gui->transmit_frame);
|
||||
free(rpc_gui->transmit_frame);
|
||||
rpc_gui->transmit_frame = NULL;
|
||||
}
|
||||
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
@ -296,7 +346,8 @@ void rpc_system_gui_free(void* context) {
|
||||
}
|
||||
|
||||
if(rpc_gui->is_streaming) {
|
||||
gui_set_framebuffer_callback(rpc_gui->gui, NULL, NULL);
|
||||
gui_remove_framebuffer_callback(
|
||||
rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context);
|
||||
}
|
||||
furi_record_close("gui");
|
||||
free(rpc_gui);
|
||||
|
@ -17,7 +17,10 @@ typedef struct {
|
||||
void* context;
|
||||
} RpcHandler;
|
||||
|
||||
void rpc_send(RpcSession* session, PB_Main* main_message);
|
||||
|
||||
void rpc_send_and_release(RpcSession* session, PB_Main* main_message);
|
||||
|
||||
void rpc_send_and_release_empty(RpcSession* session, uint32_t command_id, PB_CommandStatus status);
|
||||
|
||||
void rpc_add_handler(RpcSession* session, pb_size_t message_tag, RpcHandler* handler);
|
||||
|
@ -17,7 +17,8 @@ enum SubmenuIndex {
|
||||
SubmenuIndexNeroSketch,
|
||||
SubmenuIndexNeroRadio,
|
||||
SubmenuIndexGateTX,
|
||||
SubmenuIndexDoorHan,
|
||||
SubmenuIndexDoorHan_315_00,
|
||||
SubmenuIndexDoorHan_433_92,
|
||||
};
|
||||
|
||||
bool subghz_scene_set_type_submenu_gen_data_protocol(
|
||||
@ -122,10 +123,16 @@ void subghz_scene_set_type_on_enter(void* context) {
|
||||
SubmenuIndexGateTX,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"DoorHan_315",
|
||||
SubmenuIndexDoorHan_315_00,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"DoorHan_433",
|
||||
SubmenuIndexDoorHan,
|
||||
SubmenuIndexDoorHan_433_92,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
|
||||
@ -195,7 +202,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
||||
generated_protocol = true;
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexDoorHan:
|
||||
case SubmenuIndexDoorHan_433_92:
|
||||
subghz->txrx->transmitter =
|
||||
subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq");
|
||||
if(subghz->txrx->transmitter) {
|
||||
@ -219,6 +226,30 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexDoorHan_315_00:
|
||||
subghz->txrx->transmitter =
|
||||
subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq");
|
||||
if(subghz->txrx->transmitter) {
|
||||
subghz_protocol_keeloq_create_data(
|
||||
subghz->txrx->transmitter->protocol_instance,
|
||||
subghz->txrx->fff_data,
|
||||
key & 0x0FFFFFFF,
|
||||
0x2,
|
||||
0x0003,
|
||||
"DoorHan",
|
||||
subghz_frequencies[subghz_frequencies_315_00],
|
||||
FuriHalSubGhzPresetOok650Async);
|
||||
generated_protocol = true;
|
||||
} else {
|
||||
generated_protocol = false;
|
||||
}
|
||||
subghz_transmitter_free(subghz->txrx->transmitter);
|
||||
if(!generated_protocol) {
|
||||
string_set(
|
||||
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
|
@ -4,33 +4,57 @@
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
const char* const subghz_frequencies_text[] = {
|
||||
|
||||
"300.00",
|
||||
"303.88",
|
||||
"304.25",
|
||||
"315.00",
|
||||
"318.00",
|
||||
|
||||
"390.00",
|
||||
"418.00",
|
||||
"433.08",
|
||||
"433.42",
|
||||
"433.92",
|
||||
"434.42",
|
||||
"434.78",
|
||||
"438.90",
|
||||
|
||||
"868.35",
|
||||
"915.00",
|
||||
"925.00",
|
||||
};
|
||||
|
||||
const uint32_t subghz_frequencies[] = {
|
||||
|
||||
/* 300 - 348 */
|
||||
300000000,
|
||||
303875000,
|
||||
304250000,
|
||||
315000000,
|
||||
318000000,
|
||||
|
||||
/* 387 - 464 */
|
||||
|
||||
390000000,
|
||||
418000000,
|
||||
433075000, /* LPD433 first */
|
||||
433420000,
|
||||
433920000, /* LPD433 mid */
|
||||
434420000,
|
||||
/* 779 - 928 */
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
|
||||
/* 779 - 928 */
|
||||
868350000,
|
||||
915000000,
|
||||
925000000,
|
||||
|
||||
};
|
||||
|
||||
const uint32_t subghz_hopper_frequencies[] = {
|
||||
315000000,
|
||||
318000000,
|
||||
390000000,
|
||||
433920000,
|
||||
868350000,
|
||||
};
|
||||
@ -38,7 +62,8 @@ const uint32_t subghz_hopper_frequencies[] = {
|
||||
const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t);
|
||||
const uint32_t subghz_hopper_frequencies_count =
|
||||
sizeof(subghz_hopper_frequencies) / sizeof(uint32_t);
|
||||
const uint32_t subghz_frequencies_433_92 = 3;
|
||||
const uint32_t subghz_frequencies_433_92 = 9;
|
||||
const uint32_t subghz_frequencies_315_00 = 3;
|
||||
|
||||
bool subghz_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
|
@ -41,6 +41,7 @@ extern const uint32_t subghz_hopper_frequencies[];
|
||||
extern const uint32_t subghz_frequencies_count;
|
||||
extern const uint32_t subghz_hopper_frequencies_count;
|
||||
extern const uint32_t subghz_frequencies_433_92;
|
||||
extern const uint32_t subghz_frequencies_315_00;
|
||||
|
||||
/** SubGhzNotification state */
|
||||
typedef enum {
|
||||
|
Loading…
Reference in New Issue
Block a user