[FL-1756, FL-1769, FL-1776, FL-1759] Gui: input events complementary V3, refactoring. SubGhz: read/emulate fixes. Cleanup. (#684)

* Gui: move rotation logic to ViewPort, replace delayed View switch in ViewDispatcher with event filtering and redirection to previous view.
* SubGhz: add function description
* Gui, Input: add event id to input events.
* SubGhz: fix "crashing on ?"
* SubGhz: add icon scanning
* SubGhz: updated interface read scene,  updated interface config scene
* Assets: update subghz assets
* SubGhz:  replaced the picture in the read scene, changed the paths to additional files
* SubGhz: fix deadlock in timer callback
* SubGhz: fix icon read scene
* SubGhz: fix icon read scene
* SubGhz: fix duble text transmitter scene
* SubGhz: correct spelling. Gui: bigger queue for ViewDispatcher.
* SubGhz: fix creation and transmission of dynamic code without the presence of a manufactory key
* SubGhz: fix keelog, setting a name in the absence of a manufactory key
* SubGhz: fix load bad keelog key
* Format sources
* Furi: remove garbage from core. GpioTester: fix memory leak and cleanup
* Accessor: remove obsolete notification code
* MusicPlayer: remove input event injection
* Input: rename id to sequence

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Skorpionm 2021-09-02 01:05:00 +04:00 committed by GitHub
parent 3ed26e61eb
commit e17336498d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 763 additions and 476 deletions

View File

@ -35,7 +35,6 @@ AccessorApp::AccessorApp()
: onewire_master{&ibutton_gpio} { : onewire_master{&ibutton_gpio} {
furi_hal_power_insomnia_enter(); furi_hal_power_insomnia_enter();
notification = static_cast<NotificationApp*>(furi_record_open("notification")); notification = static_cast<NotificationApp*>(furi_record_open("notification"));
notify_init();
furi_hal_power_enable_otg(); furi_hal_power_enable_otg();
} }
@ -104,17 +103,6 @@ AccessorApp::Scene AccessorApp::get_previous_scene() {
/***************************** NOTIFY *******************************/ /***************************** NOTIFY *******************************/
void AccessorApp::notify_init() {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = PB3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(PB3_GPIO_Port, &GPIO_InitStruct);
}
void AccessorApp::notify_green_blink() { void AccessorApp::notify_green_blink() {
notification_message(notification, &sequence_blink_green_10); notification_message(notification, &sequence_blink_green_10);
} }

View File

@ -29,9 +29,7 @@ public:
bool switch_to_previous_scene(uint8_t count = 1); bool switch_to_previous_scene(uint8_t count = 1);
Scene get_previous_scene(); Scene get_previous_scene();
void notify_init();
void notify_green_blink(); void notify_green_blink();
void notify_success(); void notify_success();
char* get_text_store(); char* get_text_store();

View File

@ -2,143 +2,134 @@
#include <furi-hal.h> #include <furi-hal.h>
#include <gui/gui.h> #include <gui/gui.h>
#include <input/input.h>
#include <notification/notification-messages.h> #include <notification/notification-messages.h>
typedef struct { typedef struct {
const char* name; const char* name;
GpioPin pin; const GpioPin* pin;
} GpioItem; } GpioItem;
const GpioItem GPIO_PINS[] = { static const GpioItem GPIO_PINS[] = {
{"1.2: PA7", {GPIOA, GPIO_PIN_7}}, {"1.2: PA7", &gpio_ext_pa7},
{"1.3: PA6", {GPIOA, GPIO_PIN_6}}, {"1.3: PA6", &gpio_ext_pa6},
{"1.4: PA4", {GPIOA, GPIO_PIN_4}}, {"1.4: PA4", &gpio_ext_pa4},
{"1.5: PB3", {GPIOB, GPIO_PIN_3}}, {"1.5: PB3", &gpio_ext_pb3},
{"1.6: PB2", {GPIOB, GPIO_PIN_2}}, {"1.6: PB2", &gpio_ext_pb2},
{"1.7: PC3", {GPIOC, GPIO_PIN_3}}, {"1.7: PC3", &gpio_ext_pc3},
{"2.7: PC1", &gpio_ext_pc1},
{"2.7: PC1", {GPIOC, GPIO_PIN_1}}, {"2.8: PC0", &gpio_ext_pc0},
{"2.8: PC0", {GPIOC, GPIO_PIN_0}},
}; };
typedef enum { static const size_t GPIO_PINS_COUNT = sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]);
EventTypeTick,
EventTypeKey,
} EventType;
typedef struct {
union {
InputEvent input;
} value;
EventType type;
} AppEvent;
typedef struct { typedef struct {
osMessageQueueId_t input_queue;
uint8_t gpio_index; uint8_t gpio_index;
} State; ViewPort* view_port;
Gui* gui;
NotificationApp* notification;
} GpioTest;
static void render_callback(Canvas* canvas, void* ctx) { static void gpio_test_render_callback(Canvas* canvas, void* ctx) {
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); GpioTest* gpio_test = ctx;
canvas_clear(canvas); canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 2, 10, "GPIO Control"); canvas_draw_str(canvas, 2, 10, "GPIO Control");
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 2, 25, GPIO_PINS[state->gpio_index].name); canvas_draw_str(canvas, 2, 25, GPIO_PINS[gpio_test->gpio_index].name);
release_mutex((ValueMutex*)ctx, state);
} }
static void input_callback(InputEvent* input_event, void* ctx) { static void gpio_test_input_callback(InputEvent* input_event, void* ctx) {
osMessageQueueId_t event_queue = ctx; GpioTest* gpio_test = ctx;
AppEvent event; osMessageQueuePut(gpio_test->input_queue, input_event, 0, 0);
event.type = EventTypeKey; }
event.value.input = *input_event;
osMessageQueuePut(event_queue, &event, 0, 0); static void gpio_test_configure_pins(GpioMode mode) {
for(size_t i = 0; i < GPIO_PINS_COUNT; i++) {
hal_gpio_write(GPIO_PINS[i].pin, false);
hal_gpio_init(GPIO_PINS[i].pin, mode, GpioPullNo, GpioSpeedLow);
}
}
GpioTest* gpio_test_alloc() {
GpioTest* instance = furi_alloc(sizeof(GpioTest));
gpio_test_configure_pins(GpioModeOutputPushPull);
instance->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL);
furi_check(instance->input_queue);
instance->view_port = view_port_alloc();
view_port_draw_callback_set(instance->view_port, gpio_test_render_callback, instance);
view_port_input_callback_set(instance->view_port, gpio_test_input_callback, instance);
instance->gui = furi_record_open("gui");
gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
instance->notification = furi_record_open("notification");
return instance;
}
void gpio_test_free(GpioTest* instance) {
furi_assert(instance);
furi_record_close("notification");
view_port_enabled_set(instance->view_port, false);
gui_remove_view_port(instance->gui, instance->view_port);
furi_record_close("gui");
view_port_free(instance->view_port);
osMessageQueueDelete(instance->input_queue);
gpio_test_configure_pins(GpioModeAnalog);
free(instance);
} }
int32_t gpio_test_app(void* p) { int32_t gpio_test_app(void* p) {
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); GpioTest* gpio_test = gpio_test_alloc();
furi_check(event_queue);
State _state; InputEvent event;
_state.gpio_index = 0; while(osMessageQueueGet(gpio_test->input_queue, &event, NULL, osWaitForever) == osOK) {
if(event.type == InputTypeShort) {
if(event.key == InputKeyBack) {
notification_message(gpio_test->notification, &sequence_reset_green);
break;
}
ValueMutex state_mutex; if(event.key == InputKeyRight) {
if(!init_mutex(&state_mutex, &_state, sizeof(State))) { if(gpio_test->gpio_index < (GPIO_PINS_COUNT - 1)) {
printf("[gpio-tester] cannot create mutex\r\n"); gpio_test->gpio_index++;
return 255;
}
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
view_port_input_callback_set(view_port, input_callback, event_queue);
// Open GUI and register view_port
Gui* gui = furi_record_open("gui");
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
NotificationApp* notification = furi_record_open("notification");
// configure pin
for(uint8_t i = 0; i < sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); i++) {
hal_gpio_init(
(GpioPin*)&GPIO_PINS[i].pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
}
AppEvent event;
while(1) {
osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, osWaitForever);
State* state = (State*)acquire_mutex_block(&state_mutex);
if(event_status == osOK) {
if(event.type == EventTypeKey) {
if(event.value.input.type == InputTypeShort &&
event.value.input.key == InputKeyBack) {
printf("[gpio-tester] bye!\r\n");
notification_message(notification, &sequence_reset_green);
furi_record_close("notification");
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
return 0;
} }
}
if(event.value.input.type == InputTypeShort && if(event.key == InputKeyLeft) {
event.value.input.key == InputKeyRight) { if(gpio_test->gpio_index > 0) {
if(state->gpio_index < (sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]) - 1)) { gpio_test->gpio_index--;
state->gpio_index++;
}
} }
}
if(event.value.input.type == InputTypeShort && } else {
event.value.input.key == InputKeyLeft) { if(event.key == InputKeyOk) {
if(state->gpio_index > 0) { if(event.type == InputTypePress) {
state->gpio_index--; hal_gpio_write(GPIO_PINS[gpio_test->gpio_index].pin, true);
} notification_message(gpio_test->notification, &sequence_set_green_255);
} } else if(event.type == InputTypeRelease) {
hal_gpio_write(GPIO_PINS[gpio_test->gpio_index].pin, false);
if(event.value.input.key == InputKeyOk) { notification_message(gpio_test->notification, &sequence_reset_green);
if(event.value.input.type == InputTypePress) {
hal_gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, true);
notification_message(notification, &sequence_set_green_255);
} else if(event.value.input.type == InputTypeRelease) {
hal_gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, false);
notification_message(notification, &sequence_reset_green);
}
} }
} }
} }
release_mutex(&state_mutex, state); view_port_update(gpio_test->view_port);
view_port_update(view_port);
} }
gpio_test_free(gpio_test);
return 0; return 0;
} }

View File

@ -309,12 +309,15 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) {
furi_assert(canvas); furi_assert(canvas);
if(canvas->orientation != orientation) { if(canvas->orientation != orientation) {
canvas->orientation = orientation; canvas->orientation = orientation;
if(canvas->orientation == CanvasOrientationHorizontal) if(canvas->orientation == CanvasOrientationHorizontal) {
FURI_SWAP(canvas->width, canvas->height);
u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0); u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0);
else if(canvas->orientation == CanvasOrientationVertical) } else if(canvas->orientation == CanvasOrientationVertical) {
FURI_SWAP(canvas->width, canvas->height);
u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3); u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3);
else } else {
furi_assert(0); furi_assert(0);
}
} }
} }

View File

@ -1,40 +1,5 @@
#include "gui_i.h" #include "gui_i.h"
static void gui_rotate_buttons(InputEvent* event) {
switch(event->key) {
case InputKeyUp:
event->key = InputKeyRight;
break;
case InputKeyDown:
event->key = InputKeyLeft;
break;
case InputKeyRight:
event->key = InputKeyDown;
break;
case InputKeyLeft:
event->key = InputKeyUp;
break;
default:
break;
}
}
static void gui_setup_fs_orientation(const ViewPort* view_port, Canvas* canvas) {
ViewPortOrientation view_port_orientation = view_port_get_orientation(view_port);
CanvasOrientation canvas_orientation = canvas_get_orientation(canvas);
if(view_port_orientation == ViewPortOrientationHorizontal) {
canvas_frame_set(canvas, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
if(canvas_orientation != CanvasOrientationHorizontal) {
canvas_set_orientation(canvas, CanvasOrientationHorizontal);
}
} else if(view_port_orientation == ViewPortOrientationVertical) {
canvas_frame_set(canvas, 0, 0, GUI_DISPLAY_HEIGHT, GUI_DISPLAY_WIDTH);
if(canvas_orientation != CanvasOrientationVertical) {
canvas_set_orientation(canvas, CanvasOrientationVertical);
}
}
}
ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) {
// Iterating backward // Iterating backward
ViewPortArray_it_t it; ViewPortArray_it_t it;
@ -66,9 +31,10 @@ void gui_input_events_callback(const void* value, void* ctx) {
// Only Fullscreen supports vertical display for now // Only Fullscreen supports vertical display for now
bool gui_redraw_fs(Gui* gui) { bool gui_redraw_fs(Gui* gui) {
canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal);
canvas_frame_set(gui->canvas, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]); ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]);
if(view_port) { if(view_port) {
gui_setup_fs_orientation(view_port, gui->canvas);
view_port_draw(view_port, gui->canvas); view_port_draw(view_port, gui->canvas);
return true; return true;
} else { } else {
@ -225,9 +191,10 @@ void gui_input(Gui* gui, InputEvent* input_event) {
} else if(!(gui->ongoing_input & key_bit)) { } else if(!(gui->ongoing_input & key_bit)) {
FURI_LOG_W( FURI_LOG_W(
"Gui", "Gui",
"non-complementary input, discarding key %s type %s", "non-complementary input, discarding key: %s type: %s, sequence: %p",
input_get_key_name(input_event->key), input_get_key_name(input_event->key),
input_get_type_name(input_event->type)); input_get_type_name(input_event->type),
input_event->sequence);
return; return;
} }
@ -241,21 +208,27 @@ void gui_input(Gui* gui, InputEvent* input_event) {
gui->ongoing_input_view_port = view_port; gui->ongoing_input_view_port = view_port;
} }
if(view_port) { if(view_port && view_port == gui->ongoing_input_view_port) {
if(view_port == gui->ongoing_input_view_port) { view_port_input(view_port, input_event);
if(view_port_get_orientation(view_port) == ViewPortOrientationVertical) { } else if(gui->ongoing_input_view_port && input_event->type == InputTypeRelease) {
gui_rotate_buttons(input_event); FURI_LOG_W(
} "Gui",
view_port_input(view_port, input_event); "ViewPort changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
} else { gui->ongoing_input_view_port,
FURI_LOG_W( view_port,
"Gui", input_get_key_name(input_event->key),
"ViewPort change while key press %x -> %x. Discarding key: %s, type: %s", input_get_type_name(input_event->type),
gui->ongoing_input_view_port, input_event->sequence);
view_port, view_port_input(gui->ongoing_input_view_port, input_event);
input_get_key_name(input_event->key), } else {
input_get_type_name(input_event->type)); FURI_LOG_W(
} "Gui",
"ViewPort changed while key press %p -> %p. Discarding key: %s, type: %s, sequence: %p",
gui->ongoing_input_view_port,
view_port,
input_get_key_name(input_event->key),
input_get_type_name(input_event->type),
input_event->sequence);
} }
gui_unlock(gui); gui_unlock(gui);
@ -355,6 +328,10 @@ void gui_remove_view_port(Gui* gui, ViewPort* view_port) {
} }
} }
if(gui->ongoing_input_view_port == view_port) {
gui->ongoing_input_view_port = NULL;
}
gui_unlock(gui); gui_unlock(gui);
} }

View File

@ -37,7 +37,7 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) {
void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) { void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) {
furi_assert(view_dispatcher); furi_assert(view_dispatcher);
furi_assert(view_dispatcher->queue == NULL); furi_assert(view_dispatcher->queue == NULL);
view_dispatcher->queue = osMessageQueueNew(8, sizeof(ViewDispatcherMessage), NULL); view_dispatcher->queue = osMessageQueueNew(16, sizeof(ViewDispatcherMessage), NULL);
} }
void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context) { void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context) {
@ -149,6 +149,10 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_
if(view_dispatcher->current_view == view) { if(view_dispatcher->current_view == view) {
view_dispatcher_set_current_view(view_dispatcher, NULL); view_dispatcher_set_current_view(view_dispatcher, NULL);
} }
// Check if view is recieving input
if(view_dispatcher->ongoing_input_view == view) {
view_dispatcher->ongoing_input_view = NULL;
}
// Remove view // Remove view
ViewDict_erase(view_dispatcher->views, view_id); ViewDict_erase(view_dispatcher->views, view_id);
@ -169,12 +173,7 @@ void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t vi
} else { } else {
View** view_pp = ViewDict_get(view_dispatcher->views, view_id); View** view_pp = ViewDict_get(view_dispatcher->views, view_id);
furi_check(view_pp != NULL); furi_check(view_pp != NULL);
if(view_dispatcher->ongoing_input) { view_dispatcher_set_current_view(view_dispatcher, *view_pp);
view_dispatcher->delayed_next_view = *view_pp;
} else {
view_dispatcher->delayed_next_view = NULL;
view_dispatcher_set_current_view(view_dispatcher, *view_pp);
}
} }
} }
@ -227,39 +226,52 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e
} else if(!(view_dispatcher->ongoing_input & key_bit)) { } else if(!(view_dispatcher->ongoing_input & key_bit)) {
FURI_LOG_W( FURI_LOG_W(
"ViewDispatcher", "ViewDispatcher",
"non-complementary input, discarding key: %s, type: %s", "non-complementary input, discarding key: %s, type: %s, sequence: %p",
input_get_key_name(event->key), input_get_key_name(event->key),
input_get_type_name(event->type)); input_get_type_name(event->type),
event->sequence);
return; return;
} }
bool is_consumed = false; // Set ongoing input view if this is event is first press event
if(view_dispatcher->current_view) { if(!(view_dispatcher->ongoing_input & ~key_bit) && event->type == InputTypePress) {
is_consumed = view_input(view_dispatcher->current_view, event); view_dispatcher->ongoing_input_view = view_dispatcher->current_view;
}
if(!is_consumed && event->type == InputTypeShort) {
// TODO remove view navigation handlers
uint32_t view_id = VIEW_IGNORE;
if(event->key == InputKeyBack) {
view_id = view_previous(view_dispatcher->current_view);
if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) {
is_consumed =
view_dispatcher->navigation_event_callback(view_dispatcher->event_context);
if(!is_consumed) {
view_dispatcher_stop(view_dispatcher);
return;
}
}
}
if(!is_consumed) {
view_dispatcher_switch_to_view(view_dispatcher, view_id);
}
} }
// Delayed view switch // Deliver event
if(view_dispatcher->delayed_next_view && !(view_dispatcher->ongoing_input)) { if(view_dispatcher->ongoing_input_view == view_dispatcher->current_view) {
view_dispatcher_set_current_view(view_dispatcher, view_dispatcher->delayed_next_view); bool is_consumed = false;
view_dispatcher->delayed_next_view = NULL; if(view_dispatcher->current_view) {
is_consumed = view_input(view_dispatcher->current_view, event);
}
if(!is_consumed && event->type == InputTypeShort) {
// TODO remove view navigation handlers
uint32_t view_id = VIEW_IGNORE;
if(event->key == InputKeyBack) {
view_id = view_previous(view_dispatcher->current_view);
if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) {
is_consumed =
view_dispatcher->navigation_event_callback(view_dispatcher->event_context);
if(!is_consumed) {
view_dispatcher_stop(view_dispatcher);
return;
}
}
}
if(!is_consumed) {
view_dispatcher_switch_to_view(view_dispatcher, view_id);
}
}
} else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) {
FURI_LOG_W(
"ViewDispatcher",
"View changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port",
view_dispatcher->ongoing_input_view,
view_dispatcher->current_view,
input_get_key_name(event->key),
input_get_type_name(event->type),
event->sequence);
view_input(view_dispatcher->ongoing_input_view, event);
} }
} }

View File

@ -17,7 +17,7 @@ struct ViewDispatcher {
View* current_view; View* current_view;
View* delayed_next_view; View* ongoing_input_view;
uint8_t ongoing_input; uint8_t ongoing_input;
ViewDispatcherCustomEventCallback custom_event_callback; ViewDispatcherCustomEventCallback custom_event_callback;

View File

@ -7,6 +7,33 @@
// TODO add mutex to view_port ops // TODO add mutex to view_port ops
static void view_port_rotate_buttons(InputEvent* event) {
switch(event->key) {
case InputKeyUp:
event->key = InputKeyRight;
break;
case InputKeyDown:
event->key = InputKeyLeft;
break;
case InputKeyRight:
event->key = InputKeyDown;
break;
case InputKeyLeft:
event->key = InputKeyUp;
break;
default:
break;
}
}
static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) {
if(view_port->orientation == ViewPortOrientationHorizontal) {
canvas_set_orientation(canvas, CanvasOrientationHorizontal);
} else if(view_port->orientation == ViewPortOrientationVertical) {
canvas_set_orientation(canvas, CanvasOrientationVertical);
}
}
ViewPort* view_port_alloc() { ViewPort* view_port_alloc() {
ViewPort* view_port = furi_alloc(sizeof(ViewPort)); ViewPort* view_port = furi_alloc(sizeof(ViewPort));
view_port->orientation = ViewPortOrientationHorizontal; view_port->orientation = ViewPortOrientationHorizontal;
@ -84,6 +111,7 @@ void view_port_draw(ViewPort* view_port, Canvas* canvas) {
furi_check(view_port->gui); furi_check(view_port->gui);
if(view_port->draw_callback) { if(view_port->draw_callback) {
view_port_setup_canvas_orientation(view_port, canvas);
view_port->draw_callback(canvas, view_port->draw_callback_context); view_port->draw_callback(canvas, view_port->draw_callback_context);
} }
} }
@ -94,6 +122,9 @@ void view_port_input(ViewPort* view_port, InputEvent* event) {
furi_check(view_port->gui); furi_check(view_port->gui);
if(view_port->input_callback) { if(view_port->input_callback) {
if(view_port_get_orientation(view_port) == ViewPortOrientationVertical) {
view_port_rotate_buttons(event);
}
view_port->input_callback(event, view_port->input_callback_context); view_port->input_callback(event, view_port->input_callback_context);
} }
} }

View File

@ -23,6 +23,7 @@ inline static void input_timer_stop(osTimerId_t timer_id) {
void input_press_timer_callback(void* arg) { void input_press_timer_callback(void* arg) {
InputPinState* input_pin = arg; InputPinState* input_pin = arg;
InputEvent event; InputEvent event;
event.sequence = input_pin->counter;
event.key = input_pin->pin->key; event.key = input_pin->pin->key;
input_pin->press_counter++; input_pin->press_counter++;
if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) { if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) {
@ -158,8 +159,12 @@ int32_t input_srv() {
// Short / Long / Repeat timer routine // Short / Long / Repeat timer routine
if(state) { if(state) {
input->counter++;
input->pin_states[i].counter = input->counter;
event.sequence = input->pin_states[i].counter;
input_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS); input_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS);
} else { } else {
event.sequence = input->pin_states[i].counter;
input_timer_stop(input->pin_states[i].press_timer); input_timer_stop(input->pin_states[i].press_timer);
if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) {
event.type = InputTypeShort; event.type = InputTypeShort;

View File

@ -15,6 +15,7 @@ typedef enum {
/* Input Event, dispatches with PubSub */ /* Input Event, dispatches with PubSub */
typedef struct { typedef struct {
uint32_t sequence;
InputKey key; InputKey key;
InputType type; InputType type;
} InputEvent; } InputEvent;

View File

@ -24,6 +24,7 @@ typedef struct {
volatile uint8_t debounce; volatile uint8_t debounce;
volatile osTimerId_t press_timer; volatile osTimerId_t press_timer;
volatile uint8_t press_counter; volatile uint8_t press_counter;
volatile uint32_t counter;
} InputPinState; } InputPinState;
/* Input state */ /* Input state */
@ -32,6 +33,7 @@ typedef struct {
PubSub event_pubsub; PubSub event_pubsub;
InputPinState* pin_states; InputPinState* pin_states;
Cli* cli; Cli* cli;
volatile uint32_t counter;
} Input; } Input;
/* Input press timer callback */ /* Input press timer callback */

View File

@ -383,11 +383,6 @@ int32_t music_player_app(void* p) {
Gui* gui = furi_record_open("gui"); Gui* gui = furi_record_open("gui");
gui_add_view_port(gui, view_port, GuiLayerFullscreen); gui_add_view_port(gui, view_port, GuiLayerFullscreen);
// open input record
PubSub* input_events_record = furi_record_open("input_events");
// prepare "do nothing" event
InputEvent input_event = {InputKeyRight, true};
// start player thread // start player thread
// TODO change to fuirac_start // TODO change to fuirac_start
osThreadAttr_t player_attr = {.name = "music_player_thread", .stack_size = 512}; osThreadAttr_t player_attr = {.name = "music_player_thread", .stack_size = 512};
@ -410,14 +405,8 @@ int32_t music_player_app(void* p) {
// press events // press events
if(event.value.input.type == InputTypeShort && if(event.value.input.type == InputTypeShort &&
event.value.input.key == InputKeyBack) { event.value.input.key == InputKeyBack) {
osThreadTerminate(player); release_mutex(&state_mutex, state);
hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH); break;
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
osMessageQueueDelete(event_queue);
return 0;
} }
if(event.value.input.type == InputTypePress && if(event.value.input.type == InputTypePress &&
@ -442,9 +431,6 @@ int32_t music_player_app(void* p) {
} }
} else if(event.type == EventTypeNote) { } else if(event.type == EventTypeNote) {
// send "do nothing" event to prevent display backlight off
notify_pubsub(input_events_record, &input_event);
state->note_record = event.value.note_record; state->note_record = event.value.note_record;
for(size_t i = note_stack_size - 1; i > 0; i--) { for(size_t i = note_stack_size - 1; i > 0; i--) {
@ -460,5 +446,14 @@ int32_t music_player_app(void* p) {
release_mutex(&state_mutex, state); release_mutex(&state_mutex, state);
} }
osThreadTerminate(player);
hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH);
view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
furi_record_close("gui");
view_port_free(view_port);
osMessageQueueDelete(event_queue);
delete_mutex(&state_mutex);
return 0; return 0;
} }

View File

@ -4,6 +4,7 @@ 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, no_man, NoMan)
ADD_SCENE(subghz, test, Test) ADD_SCENE(subghz, test, Test)
ADD_SCENE(subghz, test_static, TestStatic) ADD_SCENE(subghz, test_static, TestStatic)
ADD_SCENE(subghz, test_carrier, TestCarrier) ADD_SCENE(subghz, test_carrier, TestCarrier)

View File

@ -0,0 +1,48 @@
#include "../subghz_i.h"
#define SCENE_NO_MAN_CUSTOM_EVENT (11UL)
void subghz_scene_no_man_popup_callback(void* context) {
SubGhz* subghz = context;
view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT);
}
const void subghz_scene_no_man_on_enter(void* context) {
SubGhz* subghz = context;
// Setup view
Popup* popup = subghz->popup;
popup_set_icon(popup, 32, 12, &I_DolphinFirstStart7_61x51);
popup_set_header(popup, "No manufactory key", 13, 8, AlignLeft, AlignBottom);
popup_set_timeout(popup, 1500);
popup_set_context(popup, subghz);
popup_set_callback(popup, subghz_scene_no_man_popup_callback);
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewPopup);
}
const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event) {
SubGhz* subghz = context;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) {
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart);
return true;
}
}
return false;
}
const void subghz_scene_no_man_on_exit(void* context) {
SubGhz* subghz = context;
// Clear view
Popup* popup = subghz->popup;
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 0, NULL);
popup_set_callback(popup, NULL);
popup_set_context(popup, NULL);
popup_set_timeout(popup, 0);
popup_disable_timeout(popup);
}

View File

@ -57,6 +57,10 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
subghz->state_notifications = NOTIFICATION_IDLE_STATE; subghz->state_notifications = NOTIFICATION_IDLE_STATE;
return true; return true;
break; break;
case SubghzReceverEventSendHistoryFull:
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
return true;
break;
default: default:
break; break;
} }

View File

@ -146,11 +146,15 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event
subghz->protocol_result->serial = key & 0x0FFFFFFF; subghz->protocol_result->serial = key & 0x0FFFFFFF;
subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8 subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8
subghz->protocol_result->cnt = 0x0003; subghz->protocol_result->cnt = 0x0003;
subghz_protocol_keeloq_set_manufacture_name(subghz->protocol_result, "DoorHan"); if(subghz_protocol_keeloq_set_manufacture_name(
subghz->protocol_result->code_last_found = subghz->protocol_result, "DoorHan")) {
subghz_protocol_keeloq_gen_key(subghz->protocol_result); subghz->protocol_result->code_last_found =
subghz_protocol_keeloq_gen_key(subghz->protocol_result);
generated_protocol = true; generated_protocol = true;
} else {
generated_protocol = false;
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNoMan);
}
} }
break; break;

View File

@ -38,6 +38,11 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev
scene_manager_search_and_switch_to_previous_scene( scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneStart); subghz->scene_manager, SubGhzSceneStart);
return true; return true;
} else if(event.event == SubghzTransmitterEventNoMan) {
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
scene_manager_search_and_switch_to_previous_scene(
subghz->scene_manager, SubGhzSceneNoMan);
return true;
} }
} else if(event.type == SceneManagerEventTypeTick) { } else if(event.type == SceneManagerEventTypeTick) {
if(subghz->state_notifications == NOTIFICATION_TX_STATE) { if(subghz->state_notifications == NOTIFICATION_TX_STATE) {

View File

@ -129,8 +129,8 @@ SubGhz* subghz_alloc() {
subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
subghz_worker_set_context(subghz->worker, subghz->protocol); subghz_worker_set_context(subghz->worker, subghz->protocol);
subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/assets/subghz/keeloq_mfcodes"); subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/subghz/keeloq_mfcodes");
subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/assets/subghz/nice_floor_s_rx"); subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/subghz/nice_floor_s_rx");
//subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz); //subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);

View File

@ -206,8 +206,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
furi_check(instance->stream); furi_check(instance->stream);
SubGhzProtocol* protocol = subghz_protocol_alloc(); SubGhzProtocol* protocol = subghz_protocol_alloc();
subghz_protocol_load_keeloq_file(protocol, "/ext/assets/subghz/keeloq_mfcodes"); subghz_protocol_load_keeloq_file(protocol, "/ext/subghz/keeloq_mfcodes");
subghz_protocol_load_nice_flor_s_file(protocol, "/ext/assets/subghz/nice_floor_s_rx"); subghz_protocol_load_nice_flor_s_file(protocol, "/ext/subghz/nice_floor_s_rx");
subghz_protocol_enable_dump_text(protocol, subghz_cli_command_rx_text_callback, instance); subghz_protocol_enable_dump_text(protocol, subghz_cli_command_rx_text_callback, instance);
// Configure radio // Configure radio

View File

@ -88,9 +88,15 @@ SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, u
instance->data.param1 = instance->history[idx].te; instance->data.param1 = instance->history[idx].te;
return &instance->data; return &instance->data;
} }
void subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) {
furi_assert(instance); furi_assert(instance);
string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); if(instance->last_index_write == SUBGHZ_HISTORY_MAX) {
if(output != NULL) string_printf(output, "Memory is FULL");
return true;
}
if(output != NULL)
string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX);
return false;
} }
void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) { void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) {
if(instance->history[idx].code_count_bit < 33) { if(instance->history[idx].code_count_bit < 33) {
@ -144,10 +150,10 @@ void subghz_history_add_to_history(SubGhzHistory* instance, void* context) {
instance->history[instance->last_index_write].code_found = protocol->code_last_found; instance->history[instance->last_index_write].code_found = protocol->code_last_found;
if(strcmp(protocol->name, "KeeLoq") == 0) { if(strcmp(protocol->name, "KeeLoq") == 0) {
instance->history[instance->last_index_write].manufacture_name = instance->history[instance->last_index_write].manufacture_name =
subghz_protocol_keeloq_get_manufacture_name(protocol); subghz_protocol_keeloq_find_and_get_manufacture_name(protocol);
} else if(strcmp(protocol->name, "Star Line") == 0) { } else if(strcmp(protocol->name, "Star Line") == 0) {
instance->history[instance->last_index_write].manufacture_name = instance->history[instance->last_index_write].manufacture_name =
subghz_protocol_star_line_get_manufacture_name(protocol); subghz_protocol_star_line_find_and_get_manufacture_name(protocol);
} else if(strcmp(protocol->name, "Princeton") == 0) { } else if(strcmp(protocol->name, "Princeton") == 0) {
instance->history[instance->last_index_write].te = instance->history[instance->last_index_write].te =
subghz_protocol_princeton_get_te(protocol); subghz_protocol_princeton_get_te(protocol);

View File

@ -4,20 +4,103 @@
typedef struct SubGhzHistory SubGhzHistory; typedef struct SubGhzHistory SubGhzHistory;
/** Allocate SubGhzHistory
*
* @return SubGhzHistory*
*/
SubGhzHistory* subghz_history_alloc(void); SubGhzHistory* subghz_history_alloc(void);
/** Free SubGhzHistory
*
* @param instance - SubGhzHistory instance
*/
void subghz_history_free(SubGhzHistory* instance); void subghz_history_free(SubGhzHistory* instance);
/** Clear history
*
* @param instance - SubGhzHistory instance
*/
void subghz_history_clean(SubGhzHistory* instance); void subghz_history_clean(SubGhzHistory* instance);
/** Set frequency and preset to history[idx]
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @param frequency - frequency Hz
* @param preset - FuriHalSubGhzPreset preset
*/
void subghz_history_set_frequency_preset( void subghz_history_set_frequency_preset(
SubGhzHistory* instance, SubGhzHistory* instance,
uint16_t idx, uint16_t idx,
uint32_t frequency, uint32_t frequency,
FuriHalSubGhzPreset preset); FuriHalSubGhzPreset preset);
/** Get frequency to history[idx]
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @return frequency - frequency Hz
*/
uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx); uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx);
/** Get preset to history[idx]
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @return preset - FuriHalSubGhzPreset preset
*/
FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx); FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx);
/** Get history index write
*
* @param instance - SubGhzHistory instance
* @return idx - current record index
*/
uint16_t subghz_history_get_item(SubGhzHistory* instance); uint16_t subghz_history_get_item(SubGhzHistory* instance);
/** Get type protocol to history[idx]
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @return type - type protocol
*/
uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx); uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx);
/** Get name protocol to history[idx]
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @return name - const char* name protocol
*/
const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx); const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx);
/** Get string item menu to history[idx]
*
* @param instance - SubGhzHistory instance
* @param output - string_t output
* @param idx - record index
*/
void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, 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);
/** Get string the remaining number of records to history
*
* @param instance - SubGhzHistory instance
* @param output - string_t output
* @return bool - is FUUL
*/
bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output);
/** Add protocol to history
*
* @param instance - SubGhzHistory instance
* @param context - SubGhzProtocolCommon context
*/
void subghz_history_add_to_history(SubGhzHistory* instance, void* context); void subghz_history_add_to_history(SubGhzHistory* instance, void* context);
/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data
*
* @param instance - SubGhzHistory instance
* @param idx - record index
* @return SubGhzProtocolCommonLoad*
*/
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);

View File

@ -39,9 +39,9 @@ typedef enum {
} SubGhzHopperState; } 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,
[TYPE_PROTOCOL_DYNAMIC] = &I_lock_7x8, [TYPE_PROTOCOL_DYNAMIC] = &I_Lock_7x8,
}; };
struct SubghzReceiver { struct SubghzReceiver {
@ -53,6 +53,7 @@ struct SubghzReceiver {
osTimerId timer; osTimerId timer;
SubGhzHopperState hopper_state; SubGhzHopperState hopper_state;
uint8_t hopper_timeout; uint8_t hopper_timeout;
uint32_t event_key_sequence;
}; };
typedef struct { typedef struct {
@ -172,44 +173,40 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
string_clean(str_buff); string_clean(str_buff);
} }
if(scrollbar) { if(scrollbar) {
elements_scrollbar_pos(canvas, 126, 0, 49, model->idx, model->history_item); elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item);
} }
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
elements_button_left(canvas, "Conf"); elements_button_left(canvas, "Config");
if((model->real_frequency / 1000 % 10) > 4) { canvas_draw_line(canvas, 46, 51, 125, 51);
frequency = model->real_frequency + 10000; if(subghz_history_get_text_space_left(model->history, str_buff)) {
canvas_draw_str(canvas, 54, 62, string_get_cstr(str_buff));
} else { } else {
frequency = model->real_frequency; if((model->real_frequency / 1000 % 10) > 4) {
frequency = model->real_frequency + 10000;
} else {
frequency = model->real_frequency;
}
snprintf(
buffer,
sizeof(buffer),
"%03ld.%02ld",
frequency / 1000000 % 1000,
frequency / 10000 % 100);
canvas_draw_str(canvas, 44, 62, buffer);
canvas_draw_str(canvas, 79, 62, "AM");
canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff));
} }
snprintf(
buffer,
sizeof(buffer),
"%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; break;
case ReceiverSceneStart: case ReceiverSceneStart:
canvas_draw_icon(canvas, 0, 0, &I_RFIDDolphinReceive_97x61); canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
canvas_invert_color(canvas);
canvas_draw_box(canvas, 80, 2, 20, 20);
canvas_invert_color(canvas);
canvas_draw_icon(canvas, 75, 8, &I_sub1_10px);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 40, "Scanning..."); canvas_draw_str(canvas, 63, 46, "Scanning...");
canvas_set_color(canvas, ColorBlack); canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
elements_button_left(canvas, "Conf"); elements_button_left(canvas, "Config");
canvas_invert_color(canvas);
canvas_draw_box(canvas, 38, 52, 10, 10);
canvas_invert_color(canvas);
if((model->real_frequency / 1000 % 10) > 4) { if((model->real_frequency / 1000 % 10) > 4) {
frequency = model->real_frequency + 10000; frequency = model->real_frequency + 10000;
} else { } else {
@ -221,11 +218,11 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
"%03ld.%02ld", "%03ld.%02ld",
frequency / 1000000 % 1000, frequency / 1000000 % 1000,
frequency / 10000 % 100); frequency / 10000 % 100);
canvas_draw_str(canvas, 40, 62, buffer); canvas_draw_str(canvas, 44, 62, buffer);
canvas_draw_str(canvas, 75, 62, "AM"); canvas_draw_str(canvas, 79, 62, "AM");
subghz_history_get_text_space_left(model->history, str_buff); subghz_history_get_text_space_left(model->history, str_buff);
canvas_draw_str(canvas, 94, 62, string_get_cstr(str_buff)); canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff));
canvas_draw_line(canvas, 48, 51, 125, 51); canvas_draw_line(canvas, 46, 51, 125, 51);
break; break;
case ReceiverSceneConfig: case ReceiverSceneConfig:
@ -237,9 +234,12 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
model->real_frequency / 1000000 % 1000, model->real_frequency / 1000000 % 1000,
model->real_frequency / 1000 % 1000); model->real_frequency / 1000 % 1000);
canvas_draw_str(canvas, 0, 8, buffer); canvas_draw_str(canvas, 0, 8, buffer);
canvas_draw_str(canvas, 0, 18, "Frequency Hopping: <OFF>");
} else { } else {
canvas_draw_str(canvas, 0, 8, "Frequency: <auto>"); canvas_draw_str(canvas, 0, 8, "Frequency: < --- >");
canvas_draw_str(canvas, 0, 18, "Frequency Hopping: <ON>");
} }
canvas_draw_str(canvas, 0, 28, "Modulation: <AM>");
elements_button_center(canvas, "Save"); elements_button_center(canvas, "Save");
break; break;
@ -269,6 +269,13 @@ void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) {
string_clear(str_buff); string_clear(str_buff);
} }
void subghz_receiver_history_full(void* context) {
furi_assert(context);
SubghzReceiver* subghz_receiver = context;
subghz_receiver->callback(SubghzReceverEventSendHistoryFull, subghz_receiver->context);
subghz_receiver->hopper_state = SubGhzHopperStateOFF;
}
bool subghz_receiver_input(InputEvent* event, void* context) { bool subghz_receiver_input(InputEvent* event, void* context) {
furi_assert(context); furi_assert(context);
@ -280,13 +287,11 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
return false; return false;
}); });
if(scene != ReceiverSceneInfo && event->type != InputTypeShort) return false;
bool can_be_saved = false; bool can_be_saved = false;
switch(scene) { switch(scene) {
case ReceiverSceneMain: case ReceiverSceneMain:
if(event->key == InputKeyBack) { if(event->key == InputKeyBack && event->type == InputTypeShort) {
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
model->idx = 0; model->idx = 0;
@ -296,19 +301,23 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
return true; return true;
}); });
return false; return false;
} else if(event->key == InputKeyUp) { } else if(
event->key == InputKeyUp &&
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
if(model->idx != 0) model->idx--; if(model->idx != 0) model->idx--;
return true; return true;
}); });
} else if(event->key == InputKeyDown) { } else if(
event->key == InputKeyDown &&
(event->type == InputTypeShort || event->type == InputTypeRepeat)) {
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++; if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++;
return true; return true;
}); });
} else if(event->key == InputKeyLeft) { } else if(event->key == InputKeyLeft && event->type == InputTypeShort) {
subghz_receiver->hopper_state = SubGhzHopperStatePause; subghz_receiver->hopper_state = SubGhzHopperStatePause;
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
@ -317,7 +326,8 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
return true; return true;
}); });
subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context);
} else if(event->key == InputKeyOk) { } else if(event->key == InputKeyOk && event->type == InputTypeShort) {
subghz_receiver->event_key_sequence = event->sequence;
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
string_clean(model->text); string_clean(model->text);
@ -358,18 +368,23 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
} else if(can_be_saved && event->key == InputKeyRight) { } else if(can_be_saved && event->key == InputKeyRight) {
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->event_key_sequence != event->sequence) {
subghz_receiver->hopper_state = SubGhzHopperStatePause; 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;
} else if(can_be_saved && event->key == InputKeyOk && event->type == InputTypeRelease) { } else if(
can_be_saved && event->key == InputKeyOk && event->type == InputTypeRelease &&
subghz_receiver->event_key_sequence != event->sequence) {
subghz_receiver->callback(SubghzReceverEventSendStop, subghz_receiver->context); subghz_receiver->callback(SubghzReceverEventSendStop, subghz_receiver->context);
return true; return true;
} }
break; break;
case ReceiverSceneConfig: case ReceiverSceneConfig:
if(event->type != InputTypeShort) return false;
if(event->key == InputKeyBack) { if(event->key == InputKeyBack) {
with_view_model( with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) { subghz_receiver->view, (SubghzReceiverModel * model) {
@ -396,7 +411,6 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
osTimerStart(subghz_receiver->timer, 1024 / 10); osTimerStart(subghz_receiver->timer, 1024 / 10);
subghz_receiver->hopper_state = SubGhzHopperStateRunnig; 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 {
@ -426,6 +440,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
break; break;
case ReceiverSceneStart: case ReceiverSceneStart:
if(event->type != InputTypeShort) return false;
if(event->key == InputKeyBack) { if(event->key == InputKeyBack) {
return false; return false;
} else if(event->key == InputKeyLeft) { } else if(event->key == InputKeyLeft) {
@ -445,6 +460,16 @@ bool subghz_receiver_input(InputEvent* event, void* context) {
} }
subghz_receiver_update_offset(subghz_receiver); subghz_receiver_update_offset(subghz_receiver);
if(scene != ReceiverSceneInfo) {
with_view_model(
subghz_receiver->view, (SubghzReceiverModel * model) {
if(subghz_history_get_text_space_left(model->history, NULL)) {
subghz_receiver_history_full(subghz_receiver);
}
return false;
});
}
return true; return true;
} }
@ -476,6 +501,9 @@ void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* conte
model->history_item = subghz_history_get_item(model->history); model->history_item = subghz_history_get_item(model->history);
model->scene = ReceiverSceneMain; model->scene = ReceiverSceneMain;
if(subghz_history_get_text_space_left(model->history, NULL)) {
subghz_receiver_history_full(subghz_receiver);
}
return true; return true;
}); });
subghz_protocol_reset(subghz_receiver->protocol); subghz_protocol_reset(subghz_receiver->protocol);
@ -528,10 +556,11 @@ static void subghz_receiver_timer_callback(void* context) {
} }
// Restart radio // Restart radio
subghz_rx_end(subghz_receiver->worker); furi_hal_subghz_idle();
subghz_protocol_reset(subghz_receiver->protocol); subghz_protocol_reset(subghz_receiver->protocol);
model->real_frequency = model->real_frequency = furi_hal_subghz_set_frequency_and_path(
subghz_rx(subghz_receiver->worker, subghz_frequencies_hopper[model->frequency]); subghz_frequencies_hopper[model->frequency]);
furi_hal_subghz_rx();
return true; return true;
}); });

View File

@ -14,7 +14,8 @@ typedef enum {
SubghzReceverEventBack, SubghzReceverEventBack,
SubghzReceverEventMore, SubghzReceverEventMore,
SubghzReceverEventSendStart, SubghzReceverEventSendStart,
SubghzReceverEventSendStop SubghzReceverEventSendStop,
SubghzReceverEventSendHistoryFull,
} SubghzReceverEvent; } SubghzReceverEvent;
typedef struct SubghzReceiver SubghzReceiver; typedef struct SubghzReceiver SubghzReceiver;

View File

@ -7,6 +7,7 @@
#include <input/input.h> #include <input/input.h>
#include <gui/elements.h> #include <gui/elements.h>
#include <notification/notification-messages.h> #include <notification/notification-messages.h>
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
struct SubghzTransmitter { struct SubghzTransmitter {
View* view; View* view;
@ -100,6 +101,10 @@ void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) {
canvas_draw_str(canvas, 90, 8, buffer); canvas_draw_str(canvas, 90, 8, buffer);
if(model->protocol && model->protocol->get_upload_protocol) { if(model->protocol && model->protocol->get_upload_protocol) {
if((!strcmp(model->protocol->name, "KeeLoq")) &&
(!strcmp(subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
return;
}
subghz_transmitter_button_right(canvas, "Send"); subghz_transmitter_button_right(canvas, "Send");
} }
} }
@ -107,22 +112,33 @@ void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) {
bool subghz_transmitter_input(InputEvent* event, void* context) { bool subghz_transmitter_input(InputEvent* event, void* context) {
furi_assert(context); furi_assert(context);
SubghzTransmitter* subghz_transmitter = context; SubghzTransmitter* subghz_transmitter = context;
bool can_be_send = false; bool can_be_sent = false;
if(event->key == InputKeyBack) {
return false;
}
with_view_model( with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) { subghz_transmitter->view, (SubghzTransmitterModel * model) {
can_be_send = (model->protocol && model->protocol->get_upload_protocol); if(model->protocol && model->protocol->get_upload_protocol) {
if((!strcmp(model->protocol->name, "KeeLoq")) &&
(!strcmp(
subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
return false;
}
can_be_sent = true;
}
//can_be_sent = (model->protocol && model->protocol->get_upload_protocol);
string_clean(model->text); string_clean(model->text);
model->protocol->to_string(model->protocol, model->text); model->protocol->to_string(model->protocol, model->text);
return true; return true;
}); });
//if(event->type != InputTypeShort) return false; //if(event->type != InputTypeShort) return false;
if(event->key == InputKeyBack) { if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
return false;
} else if(can_be_send && event->key == InputKeyOk && event->type == InputTypePress) {
subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context); subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context);
return true; return true;
} else if(can_be_send && event->key == InputKeyOk && event->type == InputTypeRelease) { } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) {
subghz_transmitter->callback(SubghzTransmitterEventSendStop, subghz_transmitter->context); subghz_transmitter->callback(SubghzTransmitterEventSendStop, subghz_transmitter->context);
return true; return true;
} }
@ -147,6 +163,7 @@ void subghz_transmitter_enter(void* context) {
SubghzTransmitter* subghz_transmitter = context; SubghzTransmitter* subghz_transmitter = context;
with_view_model( with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) { subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_clean(model->text);
model->protocol->to_string(model->protocol, model->text); model->protocol->to_string(model->protocol, model->text);
return true; return true;
}); });

View File

@ -7,6 +7,7 @@ typedef enum {
SubghzTransmitterEventSendStart, SubghzTransmitterEventSendStart,
SubghzTransmitterEventSendStop, SubghzTransmitterEventSendStop,
SubghzTransmitterEventBack, SubghzTransmitterEventBack,
SubghzTransmitterEventNoMan,
} SubghzTransmitterEvent; } SubghzTransmitterEvent;
typedef struct SubghzTransmitter SubghzTransmitter; typedef struct SubghzTransmitter SubghzTransmitter;

View File

@ -98,23 +98,17 @@ const uint8_t *_I_Flipper_young_80x60[] = {_I_Flipper_young_80x60_0};
const uint8_t _I_DolphinFirstStart3_57x48_0[] = {0x00,0x00,0x00,0x80,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0xF8,0x03,0x01,0x00,0x00,0x08,0x00,0x00,0x04,0xBC,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0xC0,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x02,0x00,0x38,0x40,0x00,0x00,0x02,0x00,0x04,0x00,0x3E,0x40,0x00,0x00,0xF4,0x03,0x08,0x80,0x07,0x80,0x00,0x00,0x5C,0x0D,0x10,0xE0,0x01,0x80,0x00,0x00,0xA8,0x3A,0x20,0xE0,0x00,0x00,0x01,0x00,0x58,0x55,0x00,0xC0,0x01,0x00,0x01,0x00,0xB0,0xAA,0x00,0x80,0x07,0x00,0x01,0x00,0x60,0x55,0x01,0x00,0x1E,0x00,0x01,0x0E,0xC0,0xAA,0x02,0xE0,0x5C,0x00,0x01,0x11,0x80,0x55,0x05,0x00,0xA9,0x00,0x01,0x21,0x00,0xAB,0x0A,0x00,0x56,0x07,0x01,0x41,0x00,0x56,0x15,0x00,0xEC,0x08,0x01,0x81,0x00,0xBF,0x2A,0x00,0x34,0x08,0x01,0x01,0xF1,0xC0,0x57,0x00,0x0C,0x08,0x01,0x02,0x0A,0x00,0xBE,0x00,0x04,0x08,0x01,0x02,0x06,0x00,0x78,0x83,0x02,0x04,0x01,0x02,0x0C,0x00,0xF0,0x7F,0x01,0x04,0x01,0x02,0xF4,0x01,0xFE,0x81,0x00,0x04,0x01,0x04,0x08,0xFF,0x6B,0x40,0x00,0x02,0x01,0x04,0x88,0x55,0x1D,0x40,0x00,0x02,0x01,0x04,0x50,0xAA,0x06,0x20,0x00,0x02,0x01,0x04,0x30,0xD4,0x01,0x20,0x00,0x01,0x01,0x04,0x10,0x68,0x00,0x10,0x00,0x01,0x01,0x04,0x18,0x18,0x00,0x10,0x00,0x01,0x01,0x08,0x18,0x06,0x80,0x10,0x00,0x01,0x01,0x08,0xE8,0x01,0x60,0x08,0x80,0x00,0x01,0x08,0x08,0x00,0x18,0x08,0x80,0x00,0x00,0x08,0x10,0x00,0x06,0x08,0x80,0x00,0x00,0x08,0x60,0xE0,0x01,0x08,0x80,0x00,0x00,0x08,0x80,0x1F,0x00,0x08,0x80,0x00,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x06,0x00,}; const uint8_t _I_DolphinFirstStart3_57x48_0[] = {0x00,0x00,0x00,0x80,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0xF8,0x03,0x01,0x00,0x00,0x08,0x00,0x00,0x04,0xBC,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0xC0,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x02,0x00,0x38,0x40,0x00,0x00,0x02,0x00,0x04,0x00,0x3E,0x40,0x00,0x00,0xF4,0x03,0x08,0x80,0x07,0x80,0x00,0x00,0x5C,0x0D,0x10,0xE0,0x01,0x80,0x00,0x00,0xA8,0x3A,0x20,0xE0,0x00,0x00,0x01,0x00,0x58,0x55,0x00,0xC0,0x01,0x00,0x01,0x00,0xB0,0xAA,0x00,0x80,0x07,0x00,0x01,0x00,0x60,0x55,0x01,0x00,0x1E,0x00,0x01,0x0E,0xC0,0xAA,0x02,0xE0,0x5C,0x00,0x01,0x11,0x80,0x55,0x05,0x00,0xA9,0x00,0x01,0x21,0x00,0xAB,0x0A,0x00,0x56,0x07,0x01,0x41,0x00,0x56,0x15,0x00,0xEC,0x08,0x01,0x81,0x00,0xBF,0x2A,0x00,0x34,0x08,0x01,0x01,0xF1,0xC0,0x57,0x00,0x0C,0x08,0x01,0x02,0x0A,0x00,0xBE,0x00,0x04,0x08,0x01,0x02,0x06,0x00,0x78,0x83,0x02,0x04,0x01,0x02,0x0C,0x00,0xF0,0x7F,0x01,0x04,0x01,0x02,0xF4,0x01,0xFE,0x81,0x00,0x04,0x01,0x04,0x08,0xFF,0x6B,0x40,0x00,0x02,0x01,0x04,0x88,0x55,0x1D,0x40,0x00,0x02,0x01,0x04,0x50,0xAA,0x06,0x20,0x00,0x02,0x01,0x04,0x30,0xD4,0x01,0x20,0x00,0x01,0x01,0x04,0x10,0x68,0x00,0x10,0x00,0x01,0x01,0x04,0x18,0x18,0x00,0x10,0x00,0x01,0x01,0x08,0x18,0x06,0x80,0x10,0x00,0x01,0x01,0x08,0xE8,0x01,0x60,0x08,0x80,0x00,0x01,0x08,0x08,0x00,0x18,0x08,0x80,0x00,0x00,0x08,0x10,0x00,0x06,0x08,0x80,0x00,0x00,0x08,0x60,0xE0,0x01,0x08,0x80,0x00,0x00,0x08,0x80,0x1F,0x00,0x08,0x80,0x00,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x06,0x00,};
const uint8_t *_I_DolphinFirstStart3_57x48[] = {_I_DolphinFirstStart3_57x48_0}; const uint8_t *_I_DolphinFirstStart3_57x48[] = {_I_DolphinFirstStart3_57x48_0};
const uint8_t _I_quest_7x8_0[] = {0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,}; const uint8_t _I_Scanning_123x52_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x07,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x03,0x18,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x56,0x05,0x60,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x81,0x0A,0x80,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x80,0x00,0x15,0x00,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x38,0x00,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x20,0x00,0x74,0x00,0x04,0x00,0x00,0x40,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x20,0x00,0x68,0x00,0x04,0x00,0x00,0x20,0x82,0x02,0x06,0x00,0x00,0x21,0x00,0x00,0x10,0x00,0xD0,0xE0,0x0F,0x00,0x00,0x20,0x82,0x02,0x0A,0x0C,0x80,0x20,0x08,0x00,0x10,0x00,0xA0,0x1C,0x10,0x00,0x00,0x20,0x82,0x02,0x0A,0x14,0x80,0x10,0x04,0x00,0x08,0xE0,0xD3,0x03,0x10,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0x90,0xA7,0x40,0x24,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0xC8,0x7F,0x84,0x28,0x00,0x00,0x10,0x84,0x02,0x0A,0xFF,0x80,0x10,0x02,0x00,0x88,0x67,0x3E,0x88,0x28,0x00,0x00,0x10,0x84,0xFA,0xFF,0xFF,0x80,0x10,0x02,0x00,0x44,0x64,0x2E,0x88,0x28,0x00,0x00,0x10,0xFC,0xAF,0xFF,0x15,0x80,0x10,0x04,0x00,0x44,0xE4,0x2F,0x88,0x2A,0x00,0x00,0x18,0xD4,0xDF,0x1F,0x14,0x80,0x20,0x08,0x00,0x44,0xE4,0x2F,0x50,0xFF,0x00,0xFE,0x1F,0xEC,0x3F,0x0A,0x14,0x00,0x21,0x00,0x00,0x44,0xC4,0x2F,0xEA,0x00,0x01,0x01,0x1A,0xFC,0x02,0x0A,0x14,0x00,0x41,0x00,0x00,0x84,0x88,0x2F,0x1D,0x00,0x82,0x7D,0x1E,0x84,0x02,0x0A,0x18,0x00,0x82,0x00,0x00,0x86,0x1F,0xC6,0x06,0x00,0x84,0x7D,0x16,0x84,0x02,0x0A,0x00,0x00,0x02,0x00,0x00,0x46,0xF5,0xC3,0x01,0x00,0x44,0x01,0x22,0x84,0x02,0x0C,0x00,0x00,0x04,0x00,0x00,0x87,0x0A,0x7C,0x00,0x00,0x44,0x03,0x22,0x88,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x05,0x08,0x00,0x7E,0xA4,0x03,0x42,0x88,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x86,0x06,0x00,0xC0,0x81,0xA5,0x07,0x42,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x30,0x00,0xD2,0xFF,0x81,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0xD2,0x1F,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x80,0x00,0x03,0x00,0xD1,0x1F,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xE1,0x00,0x80,0xE9,0x0F,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x1E,0x00,0xC0,0xE8,0x0F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x70,0xEE,0x0F,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3C,0xF9,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xAA,0x9F,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x55,0xFD,0x5F,0xF0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0xEA,0xFF,0x3F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0xD5,0xFF,0x1F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0xAA,0xFF,0x0F,0xE0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0x55,0x03,0xF0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xAA,0xAA,0x00,0xB0,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x54,0x75,0x00,0x58,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xA8,0x0F,0x00,0xA8,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x7C,0x00,0x00,0x5C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0xAE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0xD7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x80,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
const uint8_t *_I_quest_7x8[] = {_I_quest_7x8_0}; const uint8_t *_I_Scanning_123x52[] = {_I_Scanning_123x52_0};
const uint8_t _I_unlock_7x8_0[] = {0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,}; const uint8_t _I_Quest_7x8_0[] = {0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,};
const uint8_t *_I_unlock_7x8[] = {_I_unlock_7x8_0}; const uint8_t *_I_Quest_7x8[] = {_I_Quest_7x8_0};
const uint8_t _I_Scanning_dolph_67_61_0[] = {0x00,0x00,0xFE,0x1F,0x00,0x00,0x20,0x00,0x00,0x00,0xC0,0x01,0xE0,0x01,0x00,0x10,0x00,0x00,0x00,0x30,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,0x0C,0x00,0x00,0x18,0x00,0x08,0x00,0x00,0x00,0x02,0x00,0x00,0x20,0x00,0x08,0x08,0x00,0x00,0x01,0x00,0x00,0x40,0x00,0x04,0x04,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x04,0x04,0x00,0x40,0x00,0x00,0x00,0x00,0x01,0x04,0x02,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x00,0x20,0x00,0x00,0x00,0x3C,0x04,0x02,0x81,0x00,0x10,0x00,0x00,0x00,0x42,0x04,0x02,0x41,0x00,0x10,0x00,0x00,0x00,0x81,0x08,0x02,0x41,0x00,0x08,0x06,0x00,0x80,0x18,0x09,0x02,0x41,0x00,0x08,0x09,0x08,0x80,0x24,0x09,0x02,0x41,0x00,0x84,0x10,0x08,0x80,0x24,0x11,0x02,0x41,0x00,0xC4,0x10,0x10,0x80,0x24,0x11,0x02,0x81,0x00,0x44,0x10,0x10,0x80,0x24,0x11,0x02,0x02,0x00,0x46,0x20,0x20,0x80,0x24,0x11,0x04,0x02,0x00,0x2A,0x20,0x20,0x80,0x24,0x11,0x04,0x04,0x00,0x36,0x20,0x40,0x80,0x18,0x11,0x04,0x04,0x00,0x1B,0xE0,0x80,0x00,0x81,0x10,0x08,0x08,0x00,0x0D,0xE0,0x00,0x01,0x42,0x10,0x08,0x00,0x00,0x07,0xE0,0x01,0x00,0x3C,0x18,0x10,0x00,0x00,0x03,0xF0,0x01,0x00,0x00,0x14,0x10,0x00,0x00,0x01,0xF0,0x03,0x00,0x00,0x0A,0x20,0x00,0x00,0x00,0xD0,0xFF,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0xD0,0xFF,0x01,0x00,0x0C,0x00,0x00,0x00,0x00,0x18,0xFF,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x08,0x3C,0x00,0x1F,0x0E,0x00,0x00,0x00,0x00,0x18,0x00,0x60,0x80,0x06,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x00,0x02,0x00,0x07,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x80,0x05,0x18,0x00,0x00,0x10,0x00,0x00,0x00,0xC0,0x02,0x20,0x00,0x00,0x10,0x00,0x00,0x00,0x40,0x05,0xC0,0x00,0x00,0x20,0x00,0x00,0x00,0xA0,0x02,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x50,0x01,0x00,0x06,0x00,0x40,0x00,0x00,0x00,0xB0,0x00,0x14,0x08,0x00,0x40,0x00,0x00,0x00,0x58,0x00,0x6A,0x30,0x00,0x40,0x00,0x00,0x00,0xAC,0x00,0xD4,0x41,0x00,0x40,0x00,0x00,0x00,0x54,0x00,0xA8,0x83,0x01,0x40,0x00,0x00,0x00,0x2A,0x00,0x50,0x0F,0x02,0x40,0x00,0x00,0x00,0x15,0x00,0xA0,0x1E,0xFC,0x5F,0x00,0x00,0x00,0x0B,0x00,0x40,0x7D,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0xA0,0xFA,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,}; const uint8_t _I_Unlock_7x8_0[] = {0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,};
const uint8_t *_I_Scanning_dolph_67_61[] = {_I_Scanning_dolph_67_61_0}; const uint8_t *_I_Unlock_7x8[] = {_I_Unlock_7x8_0};
const uint8_t _I_Broadcast_dolph_67_61_0[] = {0x00,0x00,0xFE,0x1F,0x00,0x00,0x00,0x40,0x00,0x00,0xC0,0x01,0xE0,0x01,0x00,0x00,0x80,0x00,0x00,0x30,0x00,0x00,0x06,0x00,0x00,0x80,0x00,0x00,0x0C,0x00,0x00,0x18,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x20,0x00,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x40,0x00,0x00,0x02,0x02,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x02,0x40,0x00,0x00,0x00,0x00,0x01,0x00,0x04,0x02,0x20,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x04,0x20,0x00,0x00,0x00,0x3C,0x04,0x10,0x08,0x04,0x10,0x00,0x00,0x00,0x42,0x04,0x20,0x08,0x04,0x10,0x00,0x00,0x00,0x81,0x08,0x20,0x08,0x04,0x08,0x06,0x00,0x80,0x18,0x09,0x20,0x08,0x04,0x08,0x09,0x08,0x80,0x24,0x09,0x20,0x08,0x04,0x84,0x10,0x08,0x80,0x24,0x11,0x20,0x08,0x04,0xC4,0x10,0x10,0x80,0x24,0x11,0x10,0x08,0x04,0x44,0x10,0x10,0x80,0x24,0x11,0x00,0x04,0x04,0x46,0x20,0x20,0x80,0x24,0x11,0x00,0x04,0x02,0x2A,0x20,0x20,0x80,0x24,0x11,0x00,0x02,0x02,0x36,0x20,0x40,0x80,0x18,0x11,0x00,0x02,0x02,0x1B,0xE0,0x80,0x00,0x81,0x10,0x00,0x01,0x01,0x0D,0xE0,0x00,0x01,0x42,0x10,0x00,0x00,0x01,0x07,0xE0,0x01,0x00,0x3C,0x18,0x00,0x80,0x00,0x03,0xF0,0x01,0x00,0x00,0x14,0x00,0x80,0x00,0x01,0xF0,0x03,0x00,0x00,0x0A,0x00,0x40,0x00,0x00,0xD0,0xFF,0x01,0x00,0x08,0x00,0x00,0x00,0x00,0xD0,0xFF,0x01,0x00,0x0C,0x00,0x00,0x00,0x00,0x18,0xFF,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x08,0x3C,0x00,0x1F,0x0E,0x00,0x00,0x00,0x00,0x18,0x00,0x60,0x80,0x06,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x00,0x02,0x00,0x07,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x0B,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x80,0x05,0x18,0x00,0x00,0x10,0x00,0x00,0x00,0xC0,0x02,0x20,0x00,0x00,0x10,0x00,0x00,0x00,0x40,0x05,0xC0,0x00,0x00,0x20,0x00,0x00,0x00,0xA0,0x02,0x00,0x01,0x00,0x20,0x00,0x00,0x00,0x50,0x01,0x00,0x06,0x00,0x40,0x00,0x00,0x00,0xB0,0x00,0x14,0x08,0x00,0x40,0x00,0x00,0x00,0x58,0x00,0x6A,0x30,0x00,0x40,0x00,0x00,0x00,0xAC,0x00,0xD4,0x41,0x00,0x40,0x00,0x00,0x00,0x54,0x00,0xA8,0x83,0x01,0x40,0x00,0x00,0x00,0x2A,0x00,0x50,0x0F,0x02,0x40,0x00,0x00,0x00,0x15,0x00,0xA0,0x1E,0xFC,0x5F,0x00,0x00,0x00,0x0B,0x00,0x40,0x7D,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0xA0,0xFA,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,}; const uint8_t _I_Lock_7x8_0[] = {0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,};
const uint8_t *_I_Broadcast_dolph_67_61[] = {_I_Broadcast_dolph_67_61_0}; const uint8_t *_I_Lock_7x8[] = {_I_Lock_7x8_0};
const uint8_t _I_lock_7x8_0[] = {0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,};
const uint8_t *_I_lock_7x8[] = {_I_lock_7x8_0};
const uint8_t _I_Top_frame_128_13_0[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,};
const uint8_t *_I_Top_frame_128_13[] = {_I_Top_frame_128_13_0};
const uint8_t _I_PassportBottom_128x17_0[] = {0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0xF9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x05,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x05,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x09,0x79,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xD5,0x80,0x55,0xD5,0x00,0xF3,0xCC,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x6A,0x00,0xAB,0x6A,0x00,0x06,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0xFE,0x3F,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; const uint8_t _I_PassportBottom_128x17_0[] = {0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0xF9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x05,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x05,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x09,0x79,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xD5,0x80,0x55,0xD5,0x00,0xF3,0xCC,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x6A,0x00,0xAB,0x6A,0x00,0x06,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0xFE,0x3F,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0}; const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0};
@ -478,12 +472,10 @@ const Icon I_DolphinFirstStart8_56x51 = {.width=56,.height=51,.frame_count=1,.fr
const Icon I_DolphinFirstStart7_61x51 = {.width=61,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart7_61x51}; const Icon I_DolphinFirstStart7_61x51 = {.width=61,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart7_61x51};
const Icon I_Flipper_young_80x60 = {.width=80,.height=60,.frame_count=1,.frame_rate=0,.frames=_I_Flipper_young_80x60}; const Icon I_Flipper_young_80x60 = {.width=80,.height=60,.frame_count=1,.frame_rate=0,.frames=_I_Flipper_young_80x60};
const Icon I_DolphinFirstStart3_57x48 = {.width=57,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart3_57x48}; const Icon I_DolphinFirstStart3_57x48 = {.width=57,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart3_57x48};
const Icon I_quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_quest_7x8}; const Icon I_Scanning_123x52 = {.width=123,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_123x52};
const Icon I_unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_unlock_7x8}; const Icon I_Quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Quest_7x8};
const Icon I_Scanning_dolph_67_61 = {.width=67,.height=61,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_dolph_67_61}; const Icon I_Unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Unlock_7x8};
const Icon I_Broadcast_dolph_67_61 = {.width=67,.height=61,.frame_count=1,.frame_rate=0,.frames=_I_Broadcast_dolph_67_61}; const Icon I_Lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_7x8};
const Icon I_lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_lock_7x8};
const Icon I_Top_frame_128_13 = {.width=128,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Top_frame_128_13};
const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17}; const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17};
const Icon I_DoorLeft_8x56 = {.width=8,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_8x56}; const Icon I_DoorLeft_8x56 = {.width=8,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_8x56};
const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56}; const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56};

View File

@ -29,12 +29,10 @@ extern const Icon I_DolphinFirstStart8_56x51;
extern const Icon I_DolphinFirstStart7_61x51; extern const Icon I_DolphinFirstStart7_61x51;
extern const Icon I_Flipper_young_80x60; extern const Icon I_Flipper_young_80x60;
extern const Icon I_DolphinFirstStart3_57x48; extern const Icon I_DolphinFirstStart3_57x48;
extern const Icon I_quest_7x8; extern const Icon I_Scanning_123x52;
extern const Icon I_unlock_7x8; extern const Icon I_Quest_7x8;
extern const Icon I_Scanning_dolph_67_61; extern const Icon I_Unlock_7x8;
extern const Icon I_Broadcast_dolph_67_61; extern const Icon I_Lock_7x8;
extern const Icon I_lock_7x8;
extern const Icon I_Top_frame_128_13;
extern const Icon I_PassportBottom_128x17; extern const Icon I_PassportBottom_128x17;
extern const Icon I_DoorLeft_8x56; extern const Icon I_DoorLeft_8x56;
extern const Icon I_DoorLocked_10x56; extern const Icon I_DoorLocked_10x56;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -1,144 +0,0 @@
#include <furi.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
struct used for handling SPI info.
*/
typedef struct {
SPI_HandleTypeDef* spi;
PubSubCallback cb;
void* ctx;
} SpiHandle;
/*
For transmit/receive data use `spi_xfer` function.
* `tx_data` and `rx_data` size must be equal (and equal `len`)
* `cb` called after spi operation is completed, `(NULL, ctx)` passed to callback.
*/
bool spi_xfer(
SPI_HandleTypeDef* spi,
uint8_t* tx_data,
uint8_t* rx_data,
size_t len,
PubSubCallback cb,
void* ctx);
/*
Blocking verison:
*/
static inline bool
spi_xfer_block(SPI_HandleTypeDef* spi, uint8_t* tx_data, uint8_t* rx_data, size_t len) {
semaphoreInfo s;
osSemaphore block = createSemaphoreStatic(s);
if(!spi_xfer(spi, tx_data, rx_data, len, RELEASE_SEMAPHORE, (void*)block)) {
osReleaseSemaphore(block);
return false;
}
osWaitSemaphore(block);
return false;
}
/*
Common implementation of SPI bus: serial interface + CS pin
*/
typedef struct {
GpioPin* cs; ///< CS pin
ValueMutex* spi; ///< <SpiHandle*>
} SpiBus;
/*
For dedicated work with one device there is `SpiDevice` entity.
It contains ValueMutex around SpiBus: after you acquire device
you can acquire spi to work with it (don't forget SPI bus is shared
around many device, release it after every transaction as quick as possible).
*/
typedef struct {
ValueMutex* bus; ///< <SpiBus*>
} SpiDevice;
##SPI IRQ device
/*
Many devices (like CC1101 and NFC) present as SPI bus and IRQ line.
For work with it there is special entity `SpiIrqDevice`.
Use `subscribe_pubsub` for subscribinq to irq events.
*/
typedef struct {
ValueMutex* bus; ///< <SpiBus*>
PubSub* irq;
} SpiIrqDevice;
/*
Special implementation of SPI bus: serial interface + CS, Res, D/I lines.
*/
typedef struct {
GpioPin* cs; ///< CS pin
GpioPin* res; ///< reset pin
GpioPin* di; ///< D/I pin
ValueMutex* spi; ///< <SPI_HandleTypeDef*>
} DisplayBus;
typedef struct {
ValueMutex* bus; ///< <DisplayBus*>
} DisplayDevice;
/*
# SPI devices (F2)
* `/dev/sdcard` - SD card SPI, `SpiDevice`
* `/dev/cc1101_bus` - Sub-GHz radio (CC1101), `SpiIrqDevice`
* `/dev/nfc` - NFC (ST25R3916), `SpiIrqDevice`
* `/dev/display` - `DisplayDevice`
* `/dev/spiext` - External SPI (warning! Lock PA4, PA5, PA6, PA7)
### Application example
```C
// Be careful, this function called from IRQ context
void handle_irq(void* _arg, void* _ctx) {
}
void cc1101_example() {
SpiIrqDevice* cc1101_device = open_input("/dev/cc1101_bus");
if(cc1101_device == NULL) return; // bus not available, critical error
subscribe_pubsub(cc1101_device->irq, handle_irq, NULL);
{
// acquire device as device bus
SpiBus* spi_bus = acquire_mutex(cc1101_device->bus, 0);
if(spi_bus == NULL) {
printf("Device busy\n");
// wait for device
spi_bus = acquire_mutex_block(cc1101_device->bus);
}
// make transaction
uint8_t request[4] = {0xDE, 0xAD, 0xBE, 0xEF};
uint8_t response[4];
{
SPI_HandleTypeDef* spi = acquire_mutex_block(spi_bus->spi);
gpio_write(spi_bus->cs, false);
spi_xfer_block(spi, request, response, 4);
gpio_write(spi_bus->cs, true);
release_mutex(cc1101_device->spi, spi);
}
// release device (device bus)
release_mutex(cc1101_device->bus, spi_bus);
}
}
```
*/
#ifdef __cplusplus
}
#endif

View File

@ -31,3 +31,12 @@
#ifndef COUNT_OF #ifndef COUNT_OF
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0])) #define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
#endif #endif
#ifndef FURI_SWAP
#define FURI_SWAP(x, y) \
do { \
typeof(x) SWAP = x; \
x = y; \
y = SWAP; \
} while(0)
#endif

View File

@ -22,7 +22,9 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance);
* @param encoder - SubGhzProtocolCommonEncoder encoder * @param encoder - SubGhzProtocolCommonEncoder encoder
* @return bool * @return bool
*/ */
bool subghz_protocol_came_send_key(SubGhzProtocolCame* instance, SubGhzProtocolCommonEncoder* encoder); bool subghz_protocol_came_send_key(
SubGhzProtocolCame* instance,
SubGhzProtocolCommonEncoder* encoder);
/** Reset internal state /** Reset internal state
* @param instance - SubGhzProtocolCame instance * @param instance - SubGhzProtocolCame instance
@ -43,6 +45,26 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32
*/ */
void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output); void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzProtocolCame instance
* @param output - the resulting string
*/
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output); void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output);
bool subghz_protocol_came_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolCame* instance);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzProtocolCame instance
* @return bool
*/
bool subghz_protocol_came_to_load_protocol_from_file(
FileWorker* file_worker,
SubGhzProtocolCame* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolCame instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context); void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context);

View File

@ -96,9 +96,30 @@ struct SubGhzProtocolCommonLoad{
uint32_t param3; uint32_t param3;
}; };
/** Allocate SubGhzProtocolCommonEncoder
*
* @return SubGhzProtocolCommonEncoder*
*/
SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc(); SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc();
/** Free SubGhzProtocolCommonEncoder
*
* @param instance
*/
void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance); void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance);
/** Get count repeat left
*
* @param instance - SubGhzProtocolCommonEncoder instance
* @return count repeat left
*/
size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance); size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance);
/** Get LevelDuration this encoder step
*
* @param context - SubGhzProtocolCommonEncoder context
* @return LevelDuration this step
*/
LevelDuration subghz_protocol_encoder_common_yield(void* context); LevelDuration subghz_protocol_encoder_common_yield(void* context);
/** Add data bit to code_found /** Add data bit to code_found
@ -146,4 +167,11 @@ void subghz_protocol_common_set_callback(
*/ */
void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output); void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output);
/** Converting a string to a HEX array
*
* @param str - string data
* @param buff - uint8_t* buff
* @param len - size buff
* @return bool
*/
bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len); bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len);

View File

@ -50,4 +50,9 @@ void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level,
*/ */
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output); void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolFaacSLH instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context); void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context);

View File

@ -43,6 +43,24 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u
*/ */
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output); void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzProtocolGateTX instance
* @param output - the resulting string
*/
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output); void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzProtocolGateTX instance
* @return bool
*/
bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance); bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolGateTX instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context); void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context);

View File

@ -49,4 +49,10 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t
* @param output - output string * @param output - output string
*/ */
void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output); void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolIDo instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context); void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context);

View File

@ -174,15 +174,31 @@ void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instan
instance->common.btn = key_fix >> 28; instance->common.btn = key_fix >> 28;
} }
const char* subghz_protocol_keeloq_get_manufacture_name(void* context) { const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context) {
SubGhzProtocolKeeloq* instance = context; SubGhzProtocolKeeloq* instance = context;
subghz_protocol_keeloq_check_remote_controller(instance); subghz_protocol_keeloq_check_remote_controller(instance);
return instance->manufacture_name; return instance->manufacture_name;
} }
void subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name) { const char* subghz_protocol_keeloq_get_manufacture_name(void* context) {
SubGhzProtocolKeeloq* instance = context;
return instance->manufacture_name;
}
bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name) {
SubGhzProtocolKeeloq* instance = context; SubGhzProtocolKeeloq* instance = context;
instance->manufacture_name = manufacture_name; instance->manufacture_name = manufacture_name;
int res = 0;
for
M_EACH(
manufacture_code,
*subghz_keystore_get_data(instance->keystore),
SubGhzKeyArray_t) {
res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name);
if(res == 0) return true;
}
instance->manufacture_name = "Unknown";
return false;
} }
uint64_t subghz_protocol_keeloq_gen_key(void* context) { uint64_t subghz_protocol_keeloq_gen_key(void* context) {
@ -232,6 +248,10 @@ bool subghz_protocol_keeloq_send_key(
if(instance->common.callback) if(instance->common.callback)
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
if(!strcmp(instance->manufacture_name, "Unknown")) {
return false;
}
size_t index = 0; size_t index = 0;
encoder->size_upload = 11 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 4; encoder->size_upload = 11 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 4;
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false; if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
@ -392,8 +412,7 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp
code_found_reverse_lo, code_found_reverse_lo,
instance->common.btn, instance->common.btn,
instance->manufacture_name, instance->manufacture_name,
instance->common.serial instance->common.serial);
);
} }
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) { void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) {
@ -450,9 +469,7 @@ bool subghz_protocol_keeloq_to_load_protocol_from_file(
return loaded; return loaded;
} }
void subghz_decoder_keeloq_to_load_protocol( void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context) {
SubGhzProtocolKeeloq* instance,
void* context) {
furi_assert(context); furi_assert(context);
furi_assert(instance); furi_assert(instance);
SubGhzProtocolCommonLoad* data = context; SubGhzProtocolCommonLoad* data = context;

View File

@ -18,14 +18,27 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore);
*/ */
void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance); void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance);
/** Find and get manufacture name
*
* @param context - SubGhzProtocolKeeloq context
* @return name - char* manufacture name
*/
const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context);
/** Get manufacture name
*
* @param context - SubGhzProtocolKeeloq context
* @return name - char* manufacture name
*/
const char* subghz_protocol_keeloq_get_manufacture_name(void* context); const char* subghz_protocol_keeloq_get_manufacture_name(void* context);
/** Set manufacture name /** Set manufacture name
* *
* @param manufacture_name - manufacture name * @param manufacture_name - manufacture name
* @param context - SubGhzProtocolKeeloq context * @param context - SubGhzProtocolKeeloq context
* @return bool
*/ */
void subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name); bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name);
/** Get key keeloq /** Get key keeloq
* *
@ -61,6 +74,24 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
*/ */
void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output); void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzProtocolKeeloq instance
* @param output - the resulting string
*/
void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output); void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzProtocolKeeloq instance
* @return bool
*/
bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance); bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolKeeloq instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context); void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context);

View File

@ -49,6 +49,24 @@ void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool
*/ */
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output); void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzProtocolNeroSketch instance
* @param output - the resulting string
*/
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output); void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzProtocolNeroSketch instance
* @return bool
*/
bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance); bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolNeroSketch instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context); void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context);

View File

@ -43,6 +43,24 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level,
*/ */
void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output); void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzProtocolNiceFlo instance
* @param output - the resulting string
*/
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output); void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzProtocolNiceFlo instance
* @return bool
*/
bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance); bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolNiceFlo instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context); void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context);

View File

@ -50,4 +50,10 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool l
* @param output - output string * @param output - output string
*/ */
void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output); void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output);
/** Loading protocol from bin data
*
* @param instance - SubGhzProtocolNiceFlorS instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context); void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context);

View File

@ -56,6 +56,11 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc();
*/ */
void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance); void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance);
/** Get Te interval protocol
*
* @param context - SubGhzDecoderPrinceton context
* @return Te interval (us)
*/
uint16_t subghz_protocol_princeton_get_te(void* context); uint16_t subghz_protocol_princeton_get_te(void* context);
/** Get upload protocol /** Get upload protocol
@ -90,11 +95,26 @@ void subghz_decoder_princeton_parse(
*/ */
void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output); void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output);
/** Get a string to save the protocol
*
* @param instance - SubGhzDecoderPrinceton instance
* @param output - the resulting string
*/
void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output); void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output);
bool subghz_decoder_princeton_to_load_protocol_from_file(
FileWorker* file_worker,
SubGhzDecoderPrinceton* instance);
/** Loading protocol from file
*
* @param file_worker - FileWorker file_worker
* @param instance - SubGhzDecoderPrinceton instance
* @return bool
*/
bool subghz_decoder_princeton_to_load_protocol_from_file(FileWorker* file_worker, SubGhzDecoderPrinceton* instance);
/** Loading protocol from bin data
*
* @param instance - SubGhzDecoderPrinceton instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_princeton_to_load_protocol( void subghz_decoder_princeton_to_load_protocol(
SubGhzDecoderPrinceton* instance, SubGhzDecoderPrinceton* instance,
void* context) ; void* context) ;

View File

@ -38,12 +38,17 @@ void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance) {
free(instance); free(instance);
} }
const char* subghz_protocol_star_line_get_manufacture_name (void* context){ const char* subghz_protocol_star_line_find_and_get_manufacture_name (void* context){
SubGhzProtocolStarLine* instance = context; SubGhzProtocolStarLine* instance = context;
subghz_protocol_star_line_check_remote_controller(instance); subghz_protocol_star_line_check_remote_controller(instance);
return instance->manufacture_name; return instance->manufacture_name;
} }
const char* subghz_protocol_star_line_get_manufacture_name (void* context){
SubGhzProtocolStarLine* instance = context;
return instance->manufacture_name;
}
/** Send bit /** Send bit
* *
* @param instance - SubGhzProtocolStarLine instance * @param instance - SubGhzProtocolStarLine instance

View File

@ -18,6 +18,18 @@ SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore
*/ */
void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance); void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance);
/** Find and get manufacture name
*
* @param context - SubGhzProtocolStarLine context
* @return name - char* manufacture name
*/
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context);
/** Get manufacture name
*
* @param context - SubGhzProtocolStarLine context
* @return name - char* manufacture name
*/
const char* subghz_protocol_star_line_get_manufacture_name(void* context); const char* subghz_protocol_star_line_get_manufacture_name(void* context);
/** Sends the key on the air /** Sends the key on the air
@ -53,4 +65,10 @@ void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool leve
* @param output - output string * @param output - output string
*/ */
void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output); void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output);
/** Loading protocol from bin data
*
* @param instance - SubGhzDecoderPrinceton instance
* @param context - SubGhzProtocolCommonLoad context
*/
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context); void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context);

View File

@ -16,10 +16,28 @@ ARRAY_DEF(SubGhzKeyArray, SubGhzKey, M_POD_OPLIST)
typedef struct SubGhzKeystore SubGhzKeystore; typedef struct SubGhzKeystore SubGhzKeystore;
/** Allocate SubGhzKeystore
*
* @return SubGhzKeystore*
*/
SubGhzKeystore* subghz_keystore_alloc(); SubGhzKeystore* subghz_keystore_alloc();
/** Free SubGhzKeystore
*
* @param instance
*/
void subghz_keystore_free(SubGhzKeystore* instance); void subghz_keystore_free(SubGhzKeystore* instance);
/** Loading manufacture key from file
*
* @param instance - SubGhzKeystore instance
* @param filename - const char* full path to the file
*/
void subghz_keystore_load(SubGhzKeystore* instance, const char* filename); void subghz_keystore_load(SubGhzKeystore* instance, const char* filename);
/** Get array of keys and names manufacture
*
* @param instance - SubGhzKeystore instance
* @return SubGhzKeyArray_t*
*/
SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance); SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance);