[FL-1758, FL-1790] SubGhz refactoring part 2, fix generation of a new GateTX serial (#696)
* WidGet: fix name Multiline String Element * SubGhz: rename SubGhzProtocol to SubGhzParser and bring it up * SubGhz: a new way to navigate in receiver views * SubGhz: fix syntax * WedGet: add forwarding input type to wedget button callback, fix using a callback in an application * SubGhz: add assertions and status checks * SubGhz: fix syntax * [FL-1790] SubGhz: fix GateTX * SubGhz: add 434.42 MHz frequency support * SubGhz: rename type protocol, add decoder stage names * SubGhz: fix navigation through received signals when changing scenes * SubGhz: fix 2-fsk config Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
72ca76097a
commit
8fd411097e
@ -118,7 +118,7 @@ static void widget_add_element(Widget* widget, WidgetElement* element) {
|
||||
});
|
||||
}
|
||||
|
||||
void widget_add_string_multi_element(
|
||||
void widget_add_string_multiline_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
@ -127,9 +127,9 @@ void widget_add_string_multi_element(
|
||||
Font font,
|
||||
const char* text) {
|
||||
furi_assert(widget);
|
||||
WidgetElement* string_multi_element =
|
||||
widget_element_string_multi_create(x, y, horizontal, vertical, font, text);
|
||||
widget_add_element(widget, string_multi_element);
|
||||
WidgetElement* string_multiline_element =
|
||||
widget_element_string_multiline_create(x, y, horizontal, vertical, font, text);
|
||||
widget_add_element(widget, string_multiline_element);
|
||||
}
|
||||
|
||||
void widget_add_string_element(
|
||||
|
@ -34,7 +34,7 @@ View* widget_get_view(Widget* widget);
|
||||
* @param vertical - Align instance
|
||||
* @param font Font instance
|
||||
*/
|
||||
void widget_add_string_multi_element(
|
||||
void widget_add_string_multiline_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
|
@ -32,26 +32,15 @@ static bool gui_button_input(InputEvent* event, WidgetElement* element) {
|
||||
|
||||
if(model->callback == NULL) return consumed;
|
||||
|
||||
if(event->key == InputKeyOk && event->type == InputTypePress &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterPress, model->context);
|
||||
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
|
||||
model->callback(model->button_type, event->type, model->context);
|
||||
consumed = true;
|
||||
} else if(
|
||||
event->key == InputKeyOk && event->type == InputTypeRelease &&
|
||||
model->button_type == GuiButtonTypeCenter) {
|
||||
model->callback(GuiButtonTypeCenterRelease, model->context);
|
||||
} else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) {
|
||||
model->callback(model->button_type, event->type, model->context);
|
||||
consumed = true;
|
||||
} else if((model->button_type == GuiButtonTypeCenter) && (event->key == InputKeyOk)) {
|
||||
model->callback(model->button_type, event->type, model->context);
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
} else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
} else if((model->button_type == GuiButtonTypeCenter) && (event->key == InputKeyOk)) {
|
||||
model->callback(model->button_type, model->context);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
@ -1,16 +1,15 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <gui/view.h>
|
||||
#include <input/input.h>
|
||||
|
||||
typedef enum {
|
||||
GuiButtonTypeLeft,
|
||||
GuiButtonTypeCenter,
|
||||
GuiButtonTypeRight,
|
||||
GuiButtonTypeCenterPress,
|
||||
GuiButtonTypeCenterRelease,
|
||||
} GuiButtonType;
|
||||
|
||||
typedef void (*ButtonCallback)(GuiButtonType result, void* context);
|
||||
typedef void (*ButtonCallback)(GuiButtonType result, InputType type, void* context);
|
||||
|
||||
typedef struct WidgetElement WidgetElement;
|
||||
typedef struct Widget Widget;
|
||||
@ -31,7 +30,7 @@ struct WidgetElement {
|
||||
};
|
||||
|
||||
/* Create multi string element */
|
||||
WidgetElement* widget_element_string_multi_create(
|
||||
WidgetElement* widget_element_string_multiline_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
|
@ -9,12 +9,12 @@ typedef struct {
|
||||
Align vertical;
|
||||
Font font;
|
||||
string_t text;
|
||||
} GuiStringMultiModel;
|
||||
} GuiStringMultiLineModel;
|
||||
|
||||
static void gui_string_multi_draw(Canvas* canvas, WidgetElement* element) {
|
||||
static void gui_string_multiline_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiStringMultiModel* model = element->model;
|
||||
GuiStringMultiLineModel* model = element->model;
|
||||
|
||||
if(string_size(model->text)) {
|
||||
canvas_set_font(canvas, model->font);
|
||||
@ -28,16 +28,16 @@ static void gui_string_multi_draw(Canvas* canvas, WidgetElement* element) {
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_string_multi_free(WidgetElement* gui_string) {
|
||||
static void gui_string_multiline_free(WidgetElement* gui_string) {
|
||||
furi_assert(gui_string);
|
||||
|
||||
GuiStringMultiModel* model = gui_string->model;
|
||||
GuiStringMultiLineModel* model = gui_string->model;
|
||||
string_clear(model->text);
|
||||
free(gui_string->model);
|
||||
free(gui_string);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_string_multi_create(
|
||||
WidgetElement* widget_element_string_multiline_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
Align horizontal,
|
||||
@ -47,7 +47,7 @@ WidgetElement* widget_element_string_multi_create(
|
||||
furi_assert(text);
|
||||
|
||||
// Allocate and init model
|
||||
GuiStringMultiModel* model = furi_alloc(sizeof(GuiStringMultiModel));
|
||||
GuiStringMultiLineModel* model = furi_alloc(sizeof(GuiStringMultiLineModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->horizontal = horizontal;
|
||||
@ -59,8 +59,8 @@ WidgetElement* widget_element_string_multi_create(
|
||||
WidgetElement* gui_string = furi_alloc(sizeof(WidgetElement));
|
||||
gui_string->parent = NULL;
|
||||
gui_string->input = NULL;
|
||||
gui_string->draw = gui_string_multi_draw;
|
||||
gui_string->free = gui_string_multi_free;
|
||||
gui_string->draw = gui_string_multiline_draw;
|
||||
gui_string->free = gui_string_multiline_free;
|
||||
gui_string->model = model;
|
||||
|
||||
return gui_string;
|
@ -1,9 +1,10 @@
|
||||
#include "../nfc_i.h"
|
||||
|
||||
void nfc_scene_delete_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_delete_on_enter(void* context) {
|
||||
|
@ -7,9 +7,11 @@ enum {
|
||||
NfcSceneDeviceInfoData,
|
||||
};
|
||||
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) {
|
||||
@ -22,9 +24,11 @@ void nfc_scene_device_info_text_box_callback(void* context) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) {
|
||||
Nfc* nfc = context;
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_device_info_on_enter(void* context) {
|
||||
|
@ -1,10 +1,14 @@
|
||||
#include "../nfc_i.h"
|
||||
#include "../helpers/nfc_emv_parser.h"
|
||||
|
||||
void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* context) {
|
||||
void nfc_scene_read_emv_data_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
Nfc* nfc = (Nfc*)context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_scene_read_emv_data_success_on_enter(void* context) {
|
||||
|
@ -46,7 +46,7 @@ void subghz_scene_add_to_history_callback(SubGhzProtocolCommon* parser, void* co
|
||||
|
||||
if(subghz_history_add_to_history(
|
||||
subghz->txrx->history, parser, subghz->txrx->frequency, subghz->txrx->preset)) {
|
||||
subghz_protocol_reset(subghz->txrx->protocol);
|
||||
subghz_parser_reset(subghz->txrx->parser);
|
||||
string_clean(str_buff);
|
||||
subghz_history_get_text_item_menu(
|
||||
subghz->txrx->history, str_buff, subghz_history_get_item(subghz->txrx->history) - 1);
|
||||
@ -79,23 +79,18 @@ const void subghz_scene_receiver_on_enter(void* context) {
|
||||
string_clear(str_buff);
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
subghz_receiver_set_callback(subghz->subghz_receiver, subghz_scene_receiver_callback, subghz);
|
||||
subghz_protocol_enable_dump(
|
||||
subghz->txrx->protocol, subghz_scene_add_to_history_callback, subghz);
|
||||
subghz_parser_enable_dump(subghz->txrx->parser, subghz_scene_add_to_history_callback, subghz);
|
||||
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
//subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
};
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
subghz_rx(subghz->txrx->worker, subghz->txrx->frequency);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
}
|
||||
if(subghz->txrx->idx_menu_chosen != 0) {
|
||||
subghz_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIdle) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
subghz_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver);
|
||||
}
|
||||
@ -108,16 +103,15 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
case SubghzReceverEventBack:
|
||||
// Stop CC1101 Rx
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
};
|
||||
subghz_history_clean(subghz->txrx->history);
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz->txrx->idx_menu_chosen = 0;
|
||||
subghz_protocol_enable_dump(subghz->txrx->protocol, NULL, subghz);
|
||||
subghz_parser_enable_dump(subghz->txrx->parser, NULL, subghz);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
return true;
|
||||
@ -129,6 +123,7 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
break;
|
||||
case SubghzReceverEventConfig:
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig);
|
||||
return true;
|
||||
break;
|
||||
@ -137,7 +132,7 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz_hopper_update(subghz->txrx);
|
||||
subghz_hopper_update(subghz);
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,31 @@
|
||||
#include "../subghz_i.h"
|
||||
|
||||
void subghz_scene_receiver_info_callback(GuiButtonType result, void* context) {
|
||||
typedef enum {
|
||||
SubGhzSceneReceiverInfoCustomEventTxStart,
|
||||
SubGhzSceneReceiverInfoCustomEventTxStop,
|
||||
SubGhzSceneReceiverInfoCustomEventSave,
|
||||
} SubGhzSceneReceiverInfoCustomEvent;
|
||||
|
||||
void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, result);
|
||||
|
||||
if((result == GuiButtonTypeCenter) && (type == InputTypePress)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStart);
|
||||
} else if((result == GuiButtonTypeCenter) && (type == InputTypeRelease)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStop);
|
||||
} else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventSave);
|
||||
}
|
||||
}
|
||||
|
||||
static bool subghz_scene_receiver_info_update_parser(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
subghz->txrx->protocol_result = subghz_protocol_get_by_name(
|
||||
subghz->txrx->protocol,
|
||||
subghz->txrx->protocol_result = subghz_parser_get_by_name(
|
||||
subghz->txrx->parser,
|
||||
subghz_history_get_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
||||
|
||||
if(subghz->txrx->protocol_result->to_load_protocol != NULL) {
|
||||
@ -51,7 +67,7 @@ const void subghz_scene_receiver_info_on_enter(void* context) {
|
||||
string_t text;
|
||||
string_init(text);
|
||||
subghz->txrx->protocol_result->to_string(subghz->txrx->protocol_result, text);
|
||||
widget_add_string_multi_element(
|
||||
widget_add_string_multiline_element(
|
||||
subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, string_get_cstr(text));
|
||||
string_clear(text);
|
||||
|
||||
@ -83,52 +99,46 @@ const void subghz_scene_receiver_info_on_enter(void* context) {
|
||||
const bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeCenterPress) {
|
||||
if(event.event == SubGhzSceneReceiverInfoCustomEventTxStart) {
|
||||
//CC1101 Stop RX -> Start TX
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStatePause;
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
//subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
}
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_tx_start(subghz);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == GuiButtonTypeCenterRelease) {
|
||||
} else if(event.event == SubGhzSceneReceiverInfoCustomEventTxStop) {
|
||||
//CC1101 Stop Tx -> Start RX
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
subghz_rx(subghz->txrx->worker, subghz->txrx->frequency);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
if(subghz->txrx->hopper_state == SubGhzHopperStatePause) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
subghz->state_notifications = NOTIFICATION_RX_STATE;
|
||||
return true;
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
} else if(event.event == SubGhzSceneReceiverInfoCustomEventSave) {
|
||||
//CC1101 Stop RX -> Save
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
if(!subghz_scene_receiver_info_update_parser(subghz)) {
|
||||
return false;
|
||||
@ -141,7 +151,7 @@ const bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) {
|
||||
subghz_hopper_update(subghz->txrx);
|
||||
subghz_hopper_update(subghz);
|
||||
}
|
||||
switch(subghz->state_notifications) {
|
||||
case NOTIFICATION_TX_STATE:
|
||||
|
@ -15,8 +15,7 @@ enum SubmenuIndex {
|
||||
|
||||
bool subghz_scene_set_type_submenu_to_find_protocol(void* context, const char* protocol_name) {
|
||||
SubGhz* subghz = context;
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, protocol_name);
|
||||
subghz->txrx->protocol_result = subghz_parser_get_by_name(subghz->txrx->parser, protocol_name);
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
string_set(subghz->error_str, "Protocol not found");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
@ -142,7 +141,7 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event
|
||||
case SubmenuIndexGateTX:
|
||||
if(subghz_scene_set_type_submenu_to_find_protocol(subghz, "GateTX")) {
|
||||
subghz->txrx->protocol_result->code_last_count_bit = 24;
|
||||
key = (key & 0x00F0FFFF) | 0xF << 16; //btn 0xF, 0xC, 0xA, 0x6
|
||||
key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?)
|
||||
subghz->txrx->protocol_result->code_last_found =
|
||||
subghz_protocol_common_reverse_key(
|
||||
key, subghz->txrx->protocol_result->code_last_count_bit);
|
||||
|
@ -70,21 +70,19 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev
|
||||
if(event.event == SubghzTransmitterEventSendStart) {
|
||||
subghz->state_notifications = NOTIFICATION_TX_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz->txrx->worker);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_rx_end(subghz);
|
||||
}
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
if((subghz->txrx->txrx_state == SubGhzTxRxStateIdle) ||
|
||||
(subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) {
|
||||
subghz_tx_start(subghz);
|
||||
subghz_scene_transmitter_update_data_show(subghz);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventSendStop) {
|
||||
subghz->state_notifications = NOTIFICATION_IDLE_STATE;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||
subghz_tx_stop(subghz);
|
||||
subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz_sleep(subghz);
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubghzTransmitterEventBack) {
|
||||
|
@ -7,6 +7,7 @@ const char* const subghz_frequencies_text[] = {
|
||||
"387.00",
|
||||
"433.08",
|
||||
"433.92",
|
||||
"434.42",
|
||||
"434.78",
|
||||
"438.90",
|
||||
"464.00",
|
||||
@ -26,6 +27,7 @@ const uint32_t subghz_frequencies[] = {
|
||||
387000000,
|
||||
433075000, /* LPD433 first */
|
||||
433920000, /* LPD433 mid */
|
||||
434420000,
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
464000000,
|
||||
@ -156,24 +158,24 @@ SubGhz* subghz_alloc() {
|
||||
subghz->txrx = furi_alloc(sizeof(SubGhzTxRx));
|
||||
subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92];
|
||||
subghz->txrx->preset = FuriHalSubGhzPresetOok650Async;
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateOFF;
|
||||
subghz->txrx->history = subghz_history_alloc();
|
||||
subghz->txrx->worker = subghz_worker_alloc();
|
||||
subghz->txrx->protocol = subghz_protocol_alloc();
|
||||
subghz->txrx->parser = subghz_parser_alloc();
|
||||
subghz_worker_set_overrun_callback(
|
||||
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset);
|
||||
subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_parser_reset);
|
||||
subghz_worker_set_pair_callback(
|
||||
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse);
|
||||
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->protocol);
|
||||
subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_parser_parse);
|
||||
subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->parser);
|
||||
|
||||
//Init Error_str
|
||||
string_init(subghz->error_str);
|
||||
|
||||
subghz_protocol_load_keeloq_file(subghz->txrx->protocol, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_protocol_load_nice_flor_s_file(subghz->txrx->protocol, "/ext/subghz/nice_floor_s_rx");
|
||||
subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_parser_load_nice_flor_s_file(subghz->txrx->parser, "/ext/subghz/nice_floor_s_rx");
|
||||
|
||||
//subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
|
||||
//subghz_parser_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
|
||||
|
||||
return subghz;
|
||||
}
|
||||
@ -232,7 +234,7 @@ void subghz_free(SubGhz* subghz) {
|
||||
subghz->gui = NULL;
|
||||
|
||||
//Worker & Protocol & History
|
||||
subghz_protocol_free(subghz->txrx->protocol);
|
||||
subghz_parser_free(subghz->txrx->parser);
|
||||
subghz_worker_free(subghz->txrx->worker);
|
||||
subghz_history_free(subghz->txrx->history);
|
||||
free(subghz->txrx);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <furi.h>
|
||||
#include <furi-hal.h>
|
||||
#include <stream_buffer.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
||||
#include <lib/subghz/subghz_parser.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_princeton.h>
|
||||
|
||||
@ -205,10 +205,10 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
||||
furi_check(instance->stream);
|
||||
|
||||
SubGhzProtocol* protocol = subghz_protocol_alloc();
|
||||
subghz_protocol_load_keeloq_file(protocol, "/ext/subghz/keeloq_mfcodes");
|
||||
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);
|
||||
SubGhzParser* parser = subghz_parser_alloc();
|
||||
subghz_parser_load_keeloq_file(parser, "/ext/subghz/keeloq_mfcodes");
|
||||
subghz_parser_load_nice_flor_s_file(parser, "/ext/subghz/nice_floor_s_rx");
|
||||
subghz_parser_enable_dump_text(parser, subghz_cli_command_rx_text_callback, instance);
|
||||
|
||||
// Configure radio
|
||||
furi_hal_subghz_reset();
|
||||
@ -228,11 +228,11 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
if(ret == sizeof(LevelDuration)) {
|
||||
if(level_duration_is_reset(level_duration)) {
|
||||
printf(".");
|
||||
subghz_protocol_reset(protocol);
|
||||
subghz_parser_reset(parser);
|
||||
} else {
|
||||
bool level = level_duration_get_level(level_duration);
|
||||
uint32_t duration = level_duration_get_duration(level_duration);
|
||||
subghz_protocol_parse(protocol, level, duration);
|
||||
subghz_parser_parse(parser, level, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,7 +244,7 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
|
||||
printf("\r\nPackets recieved %u\r\n", instance->packet_count);
|
||||
|
||||
// Cleanup
|
||||
subghz_protocol_free(protocol);
|
||||
subghz_parser_free(parser);
|
||||
vStreamBufferDelete(instance->stream);
|
||||
free(instance);
|
||||
}
|
||||
|
@ -112,5 +112,3 @@ bool subghz_history_add_to_history(
|
||||
* @return SubGhzProtocolCommonLoad*
|
||||
*/
|
||||
SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx);
|
||||
|
||||
void subghz_hopper_update(void* context);
|
||||
|
@ -10,19 +10,23 @@
|
||||
#include "../notification/notification.h"
|
||||
#include "views/subghz_receiver.h"
|
||||
|
||||
void subghz_begin(FuriHalSubGhzPreset preset) {
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) {
|
||||
furi_assert(subghz);
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_preset(preset);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
furi_assert(context);
|
||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) {
|
||||
furi_assert(subghz);
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
SubGhzWorker* worker = context;
|
||||
furi_assert(
|
||||
subghz->txrx->txrx_state != SubGhzTxRxStateRx &&
|
||||
subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
@ -30,45 +34,54 @@ uint32_t subghz_rx(void* context, uint32_t frequency) {
|
||||
furi_hal_subghz_flush_rx();
|
||||
furi_hal_subghz_rx();
|
||||
|
||||
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, worker);
|
||||
subghz_worker_start(worker);
|
||||
furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->txrx->worker);
|
||||
subghz_worker_start(subghz->txrx->worker);
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t subghz_tx(uint32_t frequency) {
|
||||
uint32_t subghz_tx(SubGhz* subghz, uint32_t frequency) {
|
||||
furi_assert(subghz);
|
||||
if(!furi_hal_subghz_is_frequency_valid(frequency)) {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
furi_hal_subghz_idle();
|
||||
uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency);
|
||||
hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
hal_gpio_write(&gpio_cc1101_g0, true);
|
||||
furi_hal_subghz_tx();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateTx;
|
||||
return value;
|
||||
}
|
||||
|
||||
void subghz_idle(void) {
|
||||
void subghz_idle(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep);
|
||||
furi_hal_subghz_idle();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
void subghz_rx_end(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzWorker* worker = context;
|
||||
|
||||
if(subghz_worker_is_running(worker)) {
|
||||
subghz_worker_stop(worker);
|
||||
void subghz_rx_end(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateRx);
|
||||
if(subghz_worker_is_running(subghz->txrx->worker)) {
|
||||
subghz_worker_stop(subghz->txrx->worker);
|
||||
furi_hal_subghz_stop_async_rx();
|
||||
}
|
||||
furi_hal_subghz_idle();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
}
|
||||
|
||||
void subghz_sleep(void) {
|
||||
void subghz_sleep(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_hal_subghz_sleep();
|
||||
subghz->txrx->txrx_state = SubGhzTxRxStateSleep;
|
||||
}
|
||||
|
||||
void subghz_frequency_preset_to_str(void* context, string_t output) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
static void subghz_frequency_preset_to_str(SubGhz* subghz, string_t output) {
|
||||
furi_assert(subghz);
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Frequency: %d\n"
|
||||
@ -77,9 +90,9 @@ void subghz_frequency_preset_to_str(void* context, string_t output) {
|
||||
(int)subghz->txrx->preset);
|
||||
}
|
||||
|
||||
void subghz_tx_start(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
void subghz_tx_start(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
subghz->txrx->encoder = subghz_protocol_encoder_common_alloc();
|
||||
subghz->txrx->encoder->repeat = 200; //max repeat with the button held down
|
||||
//get upload
|
||||
@ -87,14 +100,14 @@ void subghz_tx_start(void* context) {
|
||||
if(subghz->txrx->protocol_result->get_upload_protocol(
|
||||
subghz->txrx->protocol_result, subghz->txrx->encoder)) {
|
||||
if(subghz->txrx->preset) {
|
||||
subghz_begin(subghz->txrx->preset);
|
||||
subghz_begin(subghz, subghz->txrx->preset);
|
||||
} else {
|
||||
subghz_begin(FuriHalSubGhzPresetOok270Async);
|
||||
subghz_begin(subghz, FuriHalSubGhzPresetOok270Async);
|
||||
}
|
||||
if(subghz->txrx->frequency) {
|
||||
subghz_tx(subghz->txrx->frequency);
|
||||
subghz_tx(subghz, subghz->txrx->frequency);
|
||||
} else {
|
||||
subghz_tx(433920000);
|
||||
subghz_tx(subghz, 433920000);
|
||||
}
|
||||
|
||||
//Start TX
|
||||
@ -104,15 +117,15 @@ void subghz_tx_start(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_tx_stop(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
void subghz_tx_stop(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateTx);
|
||||
//Stop TX
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
subghz_protocol_encoder_common_free(subghz->txrx->encoder);
|
||||
furi_hal_subghz_idle();
|
||||
subghz_idle(subghz);
|
||||
//if protocol dynamic then we save the last upload
|
||||
if(subghz->txrx->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) {
|
||||
if(subghz->txrx->protocol_result->type_protocol == SubGhzProtocolCommonTypeDynamic) {
|
||||
subghz_save_protocol_to_file(subghz, subghz->text_store);
|
||||
}
|
||||
notification_message(subghz->notifications, &sequence_reset_red);
|
||||
@ -164,7 +177,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
@ -186,10 +199,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name) {
|
||||
furi_assert(subghz);
|
||||
furi_assert(subghz->txrx->protocol_result);
|
||||
|
||||
FileWorker* file_worker = file_worker_alloc(false);
|
||||
string_t dev_file_name;
|
||||
string_init(dev_file_name);
|
||||
@ -308,7 +321,7 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) {
|
||||
// strlen("Protocol: ") = 10
|
||||
string_right(temp_str, 10);
|
||||
subghz->txrx->protocol_result =
|
||||
subghz_protocol_get_by_name(subghz->txrx->protocol, string_get_cstr(temp_str));
|
||||
subghz_parser_get_by_name(subghz->txrx->parser, string_get_cstr(temp_str));
|
||||
if(subghz->txrx->protocol_result == NULL) {
|
||||
break;
|
||||
}
|
||||
@ -342,11 +355,10 @@ uint32_t subghz_random_serial(void) {
|
||||
return (uint32_t)rand();
|
||||
}
|
||||
|
||||
void subghz_hopper_update(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzTxRx* txrx = context;
|
||||
void subghz_hopper_update(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
switch(txrx->hopper_state) {
|
||||
switch(subghz->txrx->hopper_state) {
|
||||
case SubGhzHopperStateOFF:
|
||||
return;
|
||||
break;
|
||||
@ -354,8 +366,8 @@ void subghz_hopper_update(void* context) {
|
||||
return;
|
||||
break;
|
||||
case SubGhzHopperStateRSSITimeOut:
|
||||
if(txrx->hopper_timeout != 0) {
|
||||
txrx->hopper_timeout--;
|
||||
if(subghz->txrx->hopper_timeout != 0) {
|
||||
subghz->txrx->hopper_timeout--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -363,35 +375,33 @@ void subghz_hopper_update(void* context) {
|
||||
break;
|
||||
}
|
||||
float rssi = -127.0f;
|
||||
if(txrx->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||
if(subghz->txrx->hopper_state != SubGhzHopperStateRSSITimeOut) {
|
||||
// See RSSI Calculation timings in CC1101 17.3 RSSI
|
||||
rssi = furi_hal_subghz_get_rssi();
|
||||
|
||||
// Stay if RSSI is high enough
|
||||
if(rssi > -90.0f) {
|
||||
txrx->hopper_timeout = 10;
|
||||
txrx->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||
subghz->txrx->hopper_timeout = 10;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRSSITimeOut;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
subghz->txrx->hopper_state = SubGhzHopperStateRunnig;
|
||||
}
|
||||
|
||||
// Select next frequency
|
||||
if(txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
|
||||
txrx->hopper_idx_frequency++;
|
||||
if(subghz->txrx->hopper_idx_frequency < subghz_hopper_frequencies_count - 1) {
|
||||
subghz->txrx->hopper_idx_frequency++;
|
||||
} else {
|
||||
txrx->hopper_idx_frequency = 0;
|
||||
subghz->txrx->hopper_idx_frequency = 0;
|
||||
}
|
||||
|
||||
if(txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(txrx->worker);
|
||||
txrx->txrx_state = SubGhzTxRxStateIdle;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) {
|
||||
subghz_rx_end(subghz);
|
||||
};
|
||||
if(txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_protocol_reset(txrx->protocol);
|
||||
txrx->frequency = subghz_hopper_frequencies[txrx->hopper_idx_frequency];
|
||||
subghz_rx(txrx->worker, txrx->frequency);
|
||||
txrx->txrx_state = SubGhzTxRxStateRx;
|
||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) {
|
||||
subghz_parser_reset(subghz->txrx->parser);
|
||||
subghz->txrx->frequency = subghz_hopper_frequencies[subghz->txrx->hopper_idx_frequency];
|
||||
subghz_rx(subghz, subghz->txrx->frequency);
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,8 @@
|
||||
#include <subghz/scenes/subghz_scene.h>
|
||||
|
||||
#include <lib/subghz/subghz_worker.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol.h>
|
||||
|
||||
#include <lib/subghz/subghz_parser.h>
|
||||
#include <lib/subghz/protocols/subghz_protocol_common.h>
|
||||
#include "subghz_history.h"
|
||||
|
||||
@ -47,6 +48,7 @@ typedef enum {
|
||||
SubGhzTxRxStateIdle,
|
||||
SubGhzTxRxStateRx,
|
||||
SubGhzTxRxStateTx,
|
||||
SubGhzTxRxStateSleep,
|
||||
} SubGhzTxRxState;
|
||||
|
||||
/** SubGhzHopperState state */
|
||||
@ -59,7 +61,7 @@ typedef enum {
|
||||
|
||||
struct SubGhzTxRx {
|
||||
SubGhzWorker* worker;
|
||||
SubGhzProtocol* protocol;
|
||||
SubGhzParser* parser;
|
||||
SubGhzProtocolCommon* protocol_result;
|
||||
SubGhzProtocolCommonEncoder* encoder;
|
||||
uint32_t frequency;
|
||||
@ -115,15 +117,14 @@ typedef enum {
|
||||
SubGhzViewTestPacket,
|
||||
} SubGhzView;
|
||||
|
||||
void subghz_begin(FuriHalSubGhzPreset preset);
|
||||
uint32_t subghz_rx(void* context, uint32_t frequency);
|
||||
uint32_t subghz_tx(uint32_t frequency);
|
||||
void subghz_idle(void);
|
||||
void subghz_rx_end(void* context);
|
||||
void subghz_sleep(void);
|
||||
void subghz_tx_start(void* context);
|
||||
void subghz_tx_stop(void* context);
|
||||
void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset);
|
||||
uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency);
|
||||
void subghz_rx_end(SubGhz* subghz);
|
||||
void subghz_sleep(SubGhz* subghz);
|
||||
void subghz_tx_start(SubGhz* subghz);
|
||||
void subghz_tx_stop(SubGhz* subghz);
|
||||
bool subghz_key_load(SubGhz* subghz, const char* file_path);
|
||||
bool subghz_save_protocol_to_file(void* context, const char* dev_name);
|
||||
bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name);
|
||||
bool subghz_load_protocol_from_file(SubGhz* subghz);
|
||||
uint32_t subghz_random_serial(void);
|
||||
void subghz_hopper_update(SubGhz* subghz);
|
||||
|
@ -29,9 +29,9 @@ struct SubGhzReceiverHistory {
|
||||
typedef struct SubGhzReceiverHistory SubGhzReceiverHistory;
|
||||
|
||||
static const Icon* ReceiverItemIcons[] = {
|
||||
[TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8,
|
||||
[TYPE_PROTOCOL_STATIC] = &I_Unlock_7x8,
|
||||
[TYPE_PROTOCOL_DYNAMIC] = &I_Lock_7x8,
|
||||
[SubGhzProtocolCommonTypeUnknown] = &I_Quest_7x8,
|
||||
[SubGhzProtocolCommonTypeStatic] = &I_Unlock_7x8,
|
||||
[SubGhzProtocolCommonTypeDynamic] = &I_Lock_7x8,
|
||||
};
|
||||
|
||||
struct SubghzReceiver {
|
||||
@ -90,7 +90,13 @@ void subghz_receiver_add_item_to_menu(
|
||||
SubGhzReceiverMenuItemArray_push_raw(model->history->data);
|
||||
string_init_set_str(item_menu->item_str, name);
|
||||
item_menu->type = type;
|
||||
model->history_item++;
|
||||
if((model->idx == model->history_item - 1)) {
|
||||
model->history_item++;
|
||||
model->idx++;
|
||||
} else {
|
||||
model->history_item++;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
subghz_receiver_update_offset(subghz_receiver);
|
||||
|
@ -15,166 +15,174 @@ static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
|
||||
{CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG1, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG2, 0x30 }, // Format ASK/OOK, No preamble/sync
|
||||
{ CC1101_MDMCFG3, 0x32 }, // Data rate is 3.79372 kBaud
|
||||
{ CC1101_MDMCFG4, 0x67 }, // Rx BW filter is 270.833333kHz
|
||||
{CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
|
||||
{CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
|
||||
{CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x11 }, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x07 }, // The only important bit is ADC_RETENTION
|
||||
{CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG1, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG2, 0x30 }, // Format ASK/OOK, No preamble/sync
|
||||
{ CC1101_MDMCFG3, 0x32 }, // Data rate is 3.79372 kBaud
|
||||
{ CC1101_MDMCFG4, 0x17 }, // Rx BW filter is 650.000kHz
|
||||
|
||||
{CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
|
||||
{CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
|
||||
{CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x11 }, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x88 },
|
||||
{ CC1101_TEST1, 0x31 },
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x88},
|
||||
{CC1101_TEST1, 0x31},
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION
|
||||
{CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0xF8 },
|
||||
{ CC1101_MDMCFG1, 0x00 }, // No preamble/sync
|
||||
{ CC1101_MDMCFG2, 0x80 }, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
|
||||
{ CC1101_MDMCFG3, 0x83 }, // Data rate is 9.59587 kBaud
|
||||
{ CC1101_MDMCFG4, 0x88 }, // Rx BW filter is 203.125000kHz
|
||||
{CC1101_MDMCFG0, 0x00},
|
||||
{CC1101_MDMCFG1, 0x02},
|
||||
{CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
|
||||
{CC1101_MDMCFG3, 0x8B}, // Data rate is 19.5885 kBaud
|
||||
{CC1101_MDMCFG4, 0x69}, // Rx BW filter is 270.833333 kHz
|
||||
|
||||
{ CC1101_DEVIATN, 0x14}, //Deviation 4.760742 khz
|
||||
{CC1101_DEVIATN, 0x47}, //Deviation 47.607422 khz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x10 }, // Adjusts current TX LO buffer
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x00,
|
||||
@ -184,8 +192,7 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
0x00};
|
||||
static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
|
||||
0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
|
||||
0x00,
|
||||
@ -195,6 +202,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
|
||||
};
|
||||
|
||||
void furi_hal_subghz_init() {
|
||||
@ -217,11 +225,13 @@ void furi_hal_subghz_init() {
|
||||
|
||||
// GD0 low
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != false);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != false)
|
||||
;
|
||||
|
||||
// GD0 high
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != true);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != true)
|
||||
;
|
||||
|
||||
// Reset GD0 to floating state
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||
@ -257,8 +267,7 @@ void furi_hal_subghz_dump_state() {
|
||||
printf(
|
||||
"[furi_hal_subghz] cc1101 chip %d, version %d\r\n",
|
||||
cc1101_get_partnumber(device),
|
||||
cc1101_get_version(device)
|
||||
);
|
||||
cc1101_get_version(device));
|
||||
furi_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
@ -266,10 +275,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
|
||||
if(preset == FuriHalSubGhzPresetOok650Async) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == FuriHalSubGhzPresetOok270Async){
|
||||
} else if(preset == FuriHalSubGhzPresetOok270Async) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == FuriHalSubGhzPreset2FSKAsync){
|
||||
} else if(preset == FuriHalSubGhzPreset2FSKAsync) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
|
||||
}else {
|
||||
@ -289,7 +298,7 @@ void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
|
||||
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
uint32_t i = 0;
|
||||
while (data[i][0]) {
|
||||
while(data[i][0]) {
|
||||
cc1101_write_reg(device, data[i][0], data[i][1]);
|
||||
i++;
|
||||
}
|
||||
@ -401,7 +410,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
||||
|
||||
while(true) {
|
||||
CC1101Status status = cc1101_get_status(device);
|
||||
if (status.STATE == CC1101StateIDLE) break;
|
||||
if(status.STATE == CC1101StateIDLE) break;
|
||||
}
|
||||
|
||||
furi_hal_spi_device_return(device);
|
||||
@ -411,16 +420,16 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
||||
|
||||
void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
|
||||
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
||||
if (path == FuriHalSubGhzPath433) {
|
||||
if(path == FuriHalSubGhzPath433) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 0);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
} else if (path == FuriHalSubGhzPath315) {
|
||||
} else if(path == FuriHalSubGhzPath315) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 1);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW);
|
||||
} else if (path == FuriHalSubGhzPath868) {
|
||||
} else if(path == FuriHalSubGhzPath868) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 1);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
} else if (path == FuriHalSubGhzPathIsolate) {
|
||||
} else if(path == FuriHalSubGhzPathIsolate) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 0);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW);
|
||||
} else {
|
||||
@ -438,24 +447,25 @@ static void furi_hal_subghz_capture_ISR() {
|
||||
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
|
||||
if (furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(true, furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context
|
||||
);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(
|
||||
true,
|
||||
furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
// Channel 2
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if (furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context
|
||||
);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(
|
||||
false,
|
||||
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) {
|
||||
furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
|
||||
furi_hal_subghz_state = SubGhzStateAsyncRx;
|
||||
@ -463,12 +473,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
furi_hal_subghz_capture_callback = callback;
|
||||
furi_hal_subghz_capture_callback_context = context;
|
||||
|
||||
hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
// Timer: base
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64-1;
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
@ -498,7 +509,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
|
||||
// ISR setup
|
||||
furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_capture_ISR);
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
// Interrupts and channels
|
||||
@ -508,7 +519,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
|
||||
// Enable NVIC
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
// Start timer
|
||||
@ -534,8 +545,8 @@ void furi_hal_subghz_stop_async_rx() {
|
||||
}
|
||||
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL (256)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL/2)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333
|
||||
|
||||
typedef struct {
|
||||
uint32_t* buffer;
|
||||
@ -547,12 +558,13 @@ typedef struct {
|
||||
static FuriHalSubGhzAsyncTx furi_hal_subghz_async_tx = {0};
|
||||
|
||||
static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
while (samples > 0) {
|
||||
while(samples > 0) {
|
||||
bool is_odd = samples % 2;
|
||||
LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context);
|
||||
if (level_duration_is_reset(ld)) {
|
||||
LevelDuration ld =
|
||||
furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context);
|
||||
if(level_duration_is_reset(ld)) {
|
||||
// One more even sample required to end at low level
|
||||
if (is_odd) {
|
||||
if(is_odd) {
|
||||
*buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME;
|
||||
buffer++;
|
||||
samples--;
|
||||
@ -560,7 +572,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
break;
|
||||
} else {
|
||||
// Inject guard time if level is incorrect
|
||||
if (is_odd == level_duration_get_level(ld)) {
|
||||
if(is_odd == level_duration_get_level(ld)) {
|
||||
*buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME;
|
||||
buffer++;
|
||||
samples--;
|
||||
@ -579,21 +591,24 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
|
||||
static void furi_hal_subghz_async_tx_dma_isr() {
|
||||
furi_assert(furi_hal_subghz_state == SubGhzStateAsyncTx);
|
||||
if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
LL_DMA_ClearFlag_HT1(DMA1);
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer+API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF,
|
||||
API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_subghz_async_tx_timer_isr() {
|
||||
if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) {
|
||||
LL_TIM_ClearFlag_UPDATE(TIM2);
|
||||
if (LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if (furi_hal_subghz_state == SubGhzStateAsyncTx) {
|
||||
if(LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if(furi_hal_subghz_state == SubGhzStateAsyncTx) {
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTxLast;
|
||||
} else {
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTxEnd;
|
||||
@ -612,15 +627,18 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTx;
|
||||
|
||||
furi_hal_subghz_async_tx.buffer = furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL);
|
||||
furi_hal_subghz_async_tx.buffer =
|
||||
furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL);
|
||||
|
||||
// Connect CC1101_GD0 to TIM2 as output
|
||||
hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
// Configure DMA
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->ARR);
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_async_tx.buffer;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
@ -632,7 +650,8 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config);
|
||||
furi_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr);
|
||||
furi_hal_interrupt_set_dma_channel_isr(
|
||||
DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr);
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
@ -640,7 +659,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
// Configure TIM2
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64-1;
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 1000;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
@ -672,7 +691,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
furi_hal_subghz_tx();
|
||||
|
||||
// Enable NVIC
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
@ -685,10 +704,9 @@ bool furi_hal_subghz_is_async_tx_complete() {
|
||||
|
||||
void furi_hal_subghz_stop_async_tx() {
|
||||
furi_assert(
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTx
|
||||
|| furi_hal_subghz_state == SubGhzStateAsyncTxLast
|
||||
|| furi_hal_subghz_state == SubGhzStateAsyncTxEnd
|
||||
);
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTx ||
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTxLast ||
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTxEnd);
|
||||
|
||||
// Shutdown radio
|
||||
furi_hal_subghz_idle();
|
||||
|
@ -15,166 +15,174 @@ static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
|
||||
{CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG1, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG2, 0x30 }, // Format ASK/OOK, No preamble/sync
|
||||
{ CC1101_MDMCFG3, 0x32 }, // Data rate is 3.79372 kBaud
|
||||
{ CC1101_MDMCFG4, 0x67 }, // Rx BW filter is 270.833333kHz
|
||||
{CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
|
||||
{CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
|
||||
{CC1101_MDMCFG4, 0x67}, // Rx BW filter is 270.833333kHz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x11 }, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x07 }, // The only important bit is ADC_RETENTION
|
||||
{CC1101_FIFOTHR, 0x07}, // The only important bit is ADC_RETENTION
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG1, 0x00 }, // Channel spacing is 25kHz
|
||||
{ CC1101_MDMCFG2, 0x30 }, // Format ASK/OOK, No preamble/sync
|
||||
{ CC1101_MDMCFG3, 0x32 }, // Data rate is 3.79372 kBaud
|
||||
{ CC1101_MDMCFG4, 0x17 }, // Rx BW filter is 650.000kHz
|
||||
|
||||
{CC1101_MDMCFG0, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG1, 0x00}, // Channel spacing is 25kHz
|
||||
{CC1101_MDMCFG2, 0x30}, // Format ASK/OOK, No preamble/sync
|
||||
{CC1101_MDMCFG3, 0x32}, // Data rate is 3.79372 kBaud
|
||||
{CC1101_MDMCFG4, 0x17}, // Rx BW filter is 650.000kHz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x18}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x11 }, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x11}, // Adjusts current TX LO buffer + high is PATABLE[1]
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x88 },
|
||||
{ CC1101_TEST1, 0x31 },
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x88},
|
||||
{CC1101_TEST1, 0x31},
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = {
|
||||
// https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration
|
||||
|
||||
/* GPIO GD0 */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
|
||||
|
||||
/* FIFO and internals */
|
||||
{ CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION
|
||||
{CC1101_FIFOTHR, 0x47}, // The only important bit is ADC_RETENTION
|
||||
|
||||
/* Packet engine */
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening
|
||||
{CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
|
||||
|
||||
/* Frequency Synthesizer Control */
|
||||
{ CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
{CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
|
||||
|
||||
// Modem Configuration
|
||||
{ CC1101_MDMCFG0, 0xF8 },
|
||||
{ CC1101_MDMCFG1, 0x00 }, // No preamble/sync
|
||||
{ CC1101_MDMCFG2, 0x80 }, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
|
||||
{ CC1101_MDMCFG3, 0x83 }, // Data rate is 9.59587 kBaud
|
||||
{ CC1101_MDMCFG4, 0x88 }, // Rx BW filter is 203.125000kHz
|
||||
{CC1101_MDMCFG0, 0x00},
|
||||
{CC1101_MDMCFG1, 0x02},
|
||||
{CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized)
|
||||
{CC1101_MDMCFG3, 0x8B}, // Data rate is 19.5885 kBaud
|
||||
{CC1101_MDMCFG4, 0x69}, // Rx BW filter is 270.833333 kHz
|
||||
|
||||
{ CC1101_DEVIATN, 0x14}, //Deviation 4.760742 khz
|
||||
{CC1101_DEVIATN, 0x47}, //Deviation 47.607422 khz
|
||||
|
||||
/* Main Radio Control State Machine */
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
{CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
|
||||
|
||||
/* Frequency Offset Compensation Configuration */
|
||||
{ CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
{CC1101_FOCCFG,
|
||||
0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
|
||||
|
||||
/* Automatic Gain Control */
|
||||
{ CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{ CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{ CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
{CC1101_AGCTRL0,
|
||||
0x40}, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary
|
||||
{CC1101_AGCTRL1,
|
||||
0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
|
||||
{CC1101_AGCTRL2, 0x03}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB
|
||||
|
||||
/* Wake on radio and timeouts control */
|
||||
{ CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
{CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
|
||||
|
||||
/* Frontend configuration */
|
||||
{ CC1101_FREND0, 0x10 }, // Adjusts current TX LO buffer
|
||||
{ CC1101_FREND1, 0xB6 }, //
|
||||
{CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
|
||||
{CC1101_FREND1, 0xB6}, //
|
||||
|
||||
/* Frequency Synthesizer Calibration, valid for 433.92 */
|
||||
{ CC1101_FSCAL3, 0xE9 },
|
||||
{ CC1101_FSCAL2, 0x2A },
|
||||
{ CC1101_FSCAL1, 0x00 },
|
||||
{ CC1101_FSCAL0, 0x1F },
|
||||
{CC1101_FSCAL3, 0xE9},
|
||||
{CC1101_FSCAL2, 0x2A},
|
||||
{CC1101_FSCAL1, 0x00},
|
||||
{CC1101_FSCAL0, 0x1F},
|
||||
|
||||
/* Magic f4ckery */
|
||||
{ CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{ CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled
|
||||
{CC1101_TEST2, 0x81}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST1, 0x35}, // FIFOTHR ADC_RETENTION=1 matched value
|
||||
{CC1101_TEST0, 0x09}, // VCO selection calibration stage is disabled
|
||||
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
{0, 0},
|
||||
};
|
||||
static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x00,
|
||||
@ -184,8 +192,7 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
0x00};
|
||||
static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
|
||||
0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12
|
||||
0x00,
|
||||
@ -194,8 +201,7 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00
|
||||
};
|
||||
0x00};
|
||||
|
||||
void furi_hal_subghz_init() {
|
||||
furi_assert(furi_hal_subghz_state == SubGhzStateInit);
|
||||
@ -217,11 +223,13 @@ void furi_hal_subghz_init() {
|
||||
|
||||
// GD0 low
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != false);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != false)
|
||||
;
|
||||
|
||||
// GD0 high
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != true);
|
||||
while(hal_gpio_read(&gpio_cc1101_g0) != true)
|
||||
;
|
||||
|
||||
// Reset GD0 to floating state
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||
@ -257,8 +265,7 @@ void furi_hal_subghz_dump_state() {
|
||||
printf(
|
||||
"[furi_hal_subghz] cc1101 chip %d, version %d\r\n",
|
||||
cc1101_get_partnumber(device),
|
||||
cc1101_get_version(device)
|
||||
);
|
||||
cc1101_get_version(device));
|
||||
furi_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
@ -266,10 +273,10 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
|
||||
if(preset == FuriHalSubGhzPresetOok650Async) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == FuriHalSubGhzPresetOok270Async){
|
||||
} else if(preset == FuriHalSubGhzPresetOok270Async) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == FuriHalSubGhzPreset2FSKAsync){
|
||||
} else if(preset == FuriHalSubGhzPreset2FSKAsync) {
|
||||
furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_async_regs);
|
||||
furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable);
|
||||
}else {
|
||||
@ -289,7 +296,7 @@ void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
|
||||
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
uint32_t i = 0;
|
||||
while (data[i][0]) {
|
||||
while(data[i][0]) {
|
||||
cc1101_write_reg(device, data[i][0], data[i][1]);
|
||||
i++;
|
||||
}
|
||||
@ -401,7 +408,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
||||
|
||||
while(true) {
|
||||
CC1101Status status = cc1101_get_status(device);
|
||||
if (status.STATE == CC1101StateIDLE) break;
|
||||
if(status.STATE == CC1101StateIDLE) break;
|
||||
}
|
||||
|
||||
furi_hal_spi_device_return(device);
|
||||
@ -411,16 +418,16 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
||||
|
||||
void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
|
||||
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz);
|
||||
if (path == FuriHalSubGhzPath433) {
|
||||
if(path == FuriHalSubGhzPath433) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 0);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
} else if (path == FuriHalSubGhzPath315) {
|
||||
} else if(path == FuriHalSubGhzPath315) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 1);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW);
|
||||
} else if (path == FuriHalSubGhzPath868) {
|
||||
} else if(path == FuriHalSubGhzPath868) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 1);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||
} else if (path == FuriHalSubGhzPathIsolate) {
|
||||
} else if(path == FuriHalSubGhzPathIsolate) {
|
||||
hal_gpio_write(&gpio_rf_sw_0, 0);
|
||||
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW);
|
||||
} else {
|
||||
@ -438,24 +445,25 @@ static void furi_hal_subghz_capture_ISR() {
|
||||
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC1(TIM2);
|
||||
furi_hal_subghz_capture_delta_duration = LL_TIM_IC_GetCaptureCH1(TIM2);
|
||||
if (furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(true, furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context
|
||||
);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(
|
||||
true,
|
||||
furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
// Channel 2
|
||||
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
|
||||
LL_TIM_ClearFlag_CC2(TIM2);
|
||||
if (furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(false, LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context
|
||||
);
|
||||
if(furi_hal_subghz_capture_callback) {
|
||||
furi_hal_subghz_capture_callback(
|
||||
false,
|
||||
LL_TIM_IC_GetCaptureCH2(TIM2) - furi_hal_subghz_capture_delta_duration,
|
||||
(void*)furi_hal_subghz_capture_callback_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* context) {
|
||||
furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
|
||||
furi_hal_subghz_state = SubGhzStateAsyncRx;
|
||||
@ -463,12 +471,13 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
furi_hal_subghz_capture_callback = callback;
|
||||
furi_hal_subghz_capture_callback_context = context;
|
||||
|
||||
hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
// Timer: base
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64-1;
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
@ -498,7 +507,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
|
||||
// ISR setup
|
||||
furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_capture_ISR);
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
// Interrupts and channels
|
||||
@ -508,7 +517,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
|
||||
// Enable NVIC
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
// Start timer
|
||||
@ -534,8 +543,8 @@ void furi_hal_subghz_stop_async_rx() {
|
||||
}
|
||||
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL (256)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL/2)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF (API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL / 2)
|
||||
#define API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME 333
|
||||
|
||||
typedef struct {
|
||||
uint32_t* buffer;
|
||||
@ -547,12 +556,13 @@ typedef struct {
|
||||
static FuriHalSubGhzAsyncTx furi_hal_subghz_async_tx = {0};
|
||||
|
||||
static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
while (samples > 0) {
|
||||
while(samples > 0) {
|
||||
bool is_odd = samples % 2;
|
||||
LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context);
|
||||
if (level_duration_is_reset(ld)) {
|
||||
LevelDuration ld =
|
||||
furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context);
|
||||
if(level_duration_is_reset(ld)) {
|
||||
// One more even sample required to end at low level
|
||||
if (is_odd) {
|
||||
if(is_odd) {
|
||||
*buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME;
|
||||
buffer++;
|
||||
samples--;
|
||||
@ -560,7 +570,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
break;
|
||||
} else {
|
||||
// Inject guard time if level is incorrect
|
||||
if (is_odd == level_duration_get_level(ld)) {
|
||||
if(is_odd == level_duration_get_level(ld)) {
|
||||
*buffer = API_HAL_SUBGHZ_ASYNC_TX_GUARD_TIME;
|
||||
buffer++;
|
||||
samples--;
|
||||
@ -579,21 +589,24 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
|
||||
static void furi_hal_subghz_async_tx_dma_isr() {
|
||||
furi_assert(furi_hal_subghz_state == SubGhzStateAsyncTx);
|
||||
if (LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
LL_DMA_ClearFlag_HT1(DMA1);
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
if (LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer+API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF,
|
||||
API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_subghz_async_tx_timer_isr() {
|
||||
if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) {
|
||||
LL_TIM_ClearFlag_UPDATE(TIM2);
|
||||
if (LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if (furi_hal_subghz_state == SubGhzStateAsyncTx) {
|
||||
if(LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if(furi_hal_subghz_state == SubGhzStateAsyncTx) {
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTxLast;
|
||||
} else {
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTxEnd;
|
||||
@ -612,15 +625,18 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
|
||||
furi_hal_subghz_state = SubGhzStateAsyncTx;
|
||||
|
||||
furi_hal_subghz_async_tx.buffer = furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||
furi_hal_subghz_async_tx_refill(furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL);
|
||||
furi_hal_subghz_async_tx.buffer =
|
||||
furi_alloc(API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL);
|
||||
|
||||
// Connect CC1101_GD0 to TIM2 as output
|
||||
hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
// Configure DMA
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->ARR);
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)furi_hal_subghz_async_tx.buffer;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_CIRCULAR;
|
||||
@ -632,7 +648,8 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config);
|
||||
furi_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr);
|
||||
furi_hal_interrupt_set_dma_channel_isr(
|
||||
DMA1, LL_DMA_CHANNEL_1, furi_hal_subghz_async_tx_dma_isr);
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
@ -640,7 +657,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
// Configure TIM2
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
TIM_InitStruct.Prescaler = 64-1;
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 1000;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
@ -672,7 +689,7 @@ void furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
furi_hal_subghz_tx();
|
||||
|
||||
// Enable NVIC
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0));
|
||||
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
@ -685,10 +702,9 @@ bool furi_hal_subghz_is_async_tx_complete() {
|
||||
|
||||
void furi_hal_subghz_stop_async_tx() {
|
||||
furi_assert(
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTx
|
||||
|| furi_hal_subghz_state == SubGhzStateAsyncTxLast
|
||||
|| furi_hal_subghz_state == SubGhzStateAsyncTxEnd
|
||||
);
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTx ||
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTxLast ||
|
||||
furi_hal_subghz_state == SubGhzStateAsyncTxEnd);
|
||||
|
||||
// Shutdown radio
|
||||
furi_hal_subghz_idle();
|
||||
|
@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz_protocol_common.h"
|
||||
|
||||
typedef void (*SubGhzProtocolTextCallback)(string_t text, void* context);
|
||||
typedef void (*SubGhzProtocolCommonCallbackDump)(SubGhzProtocolCommon *parser, void* context);
|
||||
|
||||
typedef struct SubGhzProtocol SubGhzProtocol;
|
||||
|
||||
/** Allocate SubGhzProtocol
|
||||
*
|
||||
* @return SubGhzProtocol*
|
||||
*/
|
||||
SubGhzProtocol* subghz_protocol_alloc();
|
||||
|
||||
/** Free SubGhzProtocol
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_protocol_free(SubGhzProtocol* instance);
|
||||
|
||||
/** Get protocol by name
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param name - name protocol
|
||||
* @param SubGhzProtocolCommon
|
||||
*/
|
||||
SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, const char* name);
|
||||
|
||||
/** Outputting data text from all parsers
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param callback - SubGhzProtocolTextCallback callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context);
|
||||
|
||||
/** Outputting data SubGhzProtocol from all parsers
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param callback - SubGhzProtocolTextCallback callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context);
|
||||
|
||||
/** File name rainbow table Nice Flor-S
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name);
|
||||
|
||||
/** File upload manufacture keys
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file_name);
|
||||
|
||||
/** Restarting all parsers
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
*/
|
||||
void subghz_protocol_reset(SubGhzProtocol* instance);
|
||||
|
||||
/** Loading data into all parsers
|
||||
*
|
||||
* @param instance - SubGhzProtocol instance
|
||||
* @param level - true is high, false if low
|
||||
* @param duration - level duration in microseconds
|
||||
*/
|
||||
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration);
|
@ -11,6 +11,13 @@ struct SubGhzProtocolCame {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CameDecoderStepReset = 0,
|
||||
CameDecoderStepFoundStartBit,
|
||||
CameDecoderStepSaveDuration,
|
||||
CameDecoderStepCheckDuration,
|
||||
} CameDecoderStep;
|
||||
|
||||
SubGhzProtocolCame* subghz_protocol_came_alloc() {
|
||||
SubGhzProtocolCame* instance = furi_alloc(sizeof(SubGhzProtocolCame));
|
||||
|
||||
@ -19,11 +26,11 @@ SubGhzProtocolCame* subghz_protocol_came_alloc() {
|
||||
instance->common.te_short = 320;
|
||||
instance->common.te_long = 640;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str;
|
||||
instance->common.to_load_protocol_from_file=
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_came_to_load_protocol;
|
||||
@ -38,97 +45,106 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_send_key(SubGhzProtocolCame* instance, SubGhzProtocolCommonEncoder* encoder){
|
||||
bool subghz_protocol_came_send_key(
|
||||
SubGhzProtocolCame* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload =(instance->common.code_last_count_bit * 2) + 2;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)){
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
}else{
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_reset(SubGhzProtocolCame* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short * 51)< instance->common.te_delta * 51)) { //Need protocol 36 te_short
|
||||
switch(instance->common.parser_step) {
|
||||
case CameDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 51) <
|
||||
instance->common.te_delta * 51)) { //Need protocol 36 te_short
|
||||
//Found header CAME
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!level) {
|
||||
case CameDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if (DURATION_DIFF(duration, instance->common.te_short)< instance->common.te_delta) {
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit CAME
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!level) { //save interval
|
||||
if (duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
|
||||
|
||||
case CameDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = CameDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if (instance->common.callback)
|
||||
instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = CameDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short) < instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
|
||||
case CameDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = CameDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = CameDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -150,8 +166,7 @@ void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output)
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo
|
||||
);
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output) {
|
||||
@ -165,7 +180,9 @@ void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t out
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolCame* instance){
|
||||
bool subghz_protocol_came_to_load_protocol_from_file(
|
||||
FileWorker* file_worker,
|
||||
SubGhzProtocolCame* instance) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
@ -202,9 +219,7 @@ bool subghz_protocol_came_to_load_protocol_from_file(FileWorker* file_worker, Su
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_came_to_load_protocol(
|
||||
SubGhzProtocolCame* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -19,12 +19,11 @@
|
||||
#define SUBGHZ_APP_EXTENSION ".sub"
|
||||
#define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 512
|
||||
|
||||
enum {
|
||||
TYPE_PROTOCOL_UNKNOWN,
|
||||
TYPE_PROTOCOL_STATIC,
|
||||
TYPE_PROTOCOL_DYNAMIC,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubGhzProtocolCommonTypeUnknown,
|
||||
SubGhzProtocolCommonTypeStatic,
|
||||
SubGhzProtocolCommonTypeDynamic,
|
||||
}SubGhzProtocolCommonType;
|
||||
|
||||
typedef struct SubGhzProtocolCommon SubGhzProtocolCommon;
|
||||
typedef struct SubGhzProtocolCommonEncoder SubGhzProtocolCommonEncoder;
|
||||
@ -38,7 +37,8 @@ typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string
|
||||
typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output);
|
||||
|
||||
//Load protocol from file
|
||||
typedef bool (*SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance);
|
||||
typedef bool (
|
||||
*SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance);
|
||||
//Load protocol
|
||||
typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context);
|
||||
//Get upload encoder protocol
|
||||
@ -56,13 +56,13 @@ struct SubGhzProtocolCommon {
|
||||
uint64_t code_found;
|
||||
uint64_t code_last_found;
|
||||
uint8_t code_min_count_bit_for_found;
|
||||
uint8_t parser_step;
|
||||
uint8_t type_protocol;
|
||||
uint32_t te_last;
|
||||
uint8_t header_count;
|
||||
uint16_t cnt;
|
||||
uint32_t serial;
|
||||
uint8_t btn;
|
||||
uint8_t header_count;
|
||||
SubGhzProtocolCommonType type_protocol;
|
||||
uint32_t te_last;
|
||||
uint32_t serial;
|
||||
uint32_t parser_step;
|
||||
uint16_t cnt;
|
||||
|
||||
/* Standard Callback for on rx complete event */
|
||||
SubGhzProtocolCommonCallback callback;
|
||||
@ -88,7 +88,7 @@ struct SubGhzProtocolCommonEncoder {
|
||||
LevelDuration* upload;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolCommonLoad{
|
||||
struct SubGhzProtocolCommonLoad {
|
||||
uint64_t code_found;
|
||||
uint8_t code_count_bit;
|
||||
uint32_t param1;
|
||||
|
@ -1,19 +1,25 @@
|
||||
#include "subghz_protocol_faac_slh.h"
|
||||
|
||||
|
||||
struct SubGhzProtocolFaacSLH {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FaacSLHDecoderStepReset = 0,
|
||||
FaacSLHDecoderStepFoundPreambula,
|
||||
FaacSLHDecoderStepSaveDuration,
|
||||
FaacSLHDecoderStepCheckDuration,
|
||||
} FaacSLHDecoderStep;
|
||||
|
||||
SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc(void) {
|
||||
SubGhzProtocolFaacSLH* instance = furi_alloc(sizeof(SubGhzProtocolFaacSLH));
|
||||
|
||||
instance->common.name = "Faac SLH";
|
||||
instance->common.name = "Faac SLH";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 255;
|
||||
instance->common.te_long = 595;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_faac_slh_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_faac_slh_to_load_protocol;
|
||||
@ -32,7 +38,7 @@ void subghz_protocol_faac_slh_free(SubGhzProtocolFaacSLH* instance) {
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_faac_slh_send_bit(SubGhzProtocolFaacSLH* instance, uint8_t bit) {
|
||||
if (bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
@ -47,22 +53,26 @@ void subghz_protocol_faac_slh_send_bit(SubGhzProtocolFaacSLH* instance, uint8_t
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_send_key(SubGhzProtocolFaacSLH* instance, uint64_t key, uint8_t bit,uint8_t repeat) {
|
||||
while (repeat--) {
|
||||
void subghz_protocol_faac_slh_send_key(
|
||||
SubGhzProtocolFaacSLH* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
//Send header
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
delay_us(instance->common.te_long * 2);
|
||||
//Send key data
|
||||
for (uint8_t i = bit; i > 0; i--) {
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_faac_slh_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
@ -70,7 +80,8 @@ void subghz_protocol_faac_slh_reset(SubGhzProtocolFaacSLH* instance) {
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* instance) {
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
//uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFF;
|
||||
|
||||
@ -79,62 +90,68 @@ void subghz_protocol_faac_slh_check_remote_controller(SubGhzProtocolFaacSLH* ins
|
||||
}
|
||||
|
||||
void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long * 2)< instance->common.te_delta * 3)) {
|
||||
instance->common.parser_step = 1;
|
||||
switch(instance->common.parser_step) {
|
||||
case FaacSLHDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long * 2)< instance->common.te_delta * 3)) {
|
||||
case FaacSLHDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (level) {
|
||||
if (duration >= (instance->common.te_short * 3 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
case FaacSLHDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 3 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepFoundPreambula;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = FaacSLHDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
}else{
|
||||
instance->common.parser_step = 0;
|
||||
} else {
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(!level){
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta)) {
|
||||
case FaacSLHDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long )< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = FaacSLHDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = FaacSLHDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -142,28 +159,29 @@ void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level,
|
||||
|
||||
void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output) {
|
||||
subghz_protocol_faac_slh_check_remote_controller(instance);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_fix = code_found_reverse & 0xFFFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >>32) & 0xFFFFFFFF;
|
||||
uint32_t code_hop = (code_found_reverse >> 32) & 0xFFFFFFFF;
|
||||
|
||||
string_cat_printf(output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%08lX \r\n"
|
||||
"Hop:%08lX \r\n"
|
||||
"Sn:%07lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix, code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Fix:%08lX \r\n"
|
||||
"Hop:%08lX \r\n"
|
||||
"Sn:%07lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found >> 32),
|
||||
(uint32_t)instance->common.code_last_found,
|
||||
code_fix,
|
||||
code_hop,
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_faac_slh_to_load_protocol(
|
||||
SubGhzProtocolFaacSLH* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -1,10 +1,16 @@
|
||||
#include "subghz_protocol_gate_tx.h"
|
||||
|
||||
|
||||
struct SubGhzProtocolGateTX {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GateTXDecoderStepReset = 0,
|
||||
GateTXDecoderStepFoundStartBit,
|
||||
GateTXDecoderStepSaveDuration,
|
||||
GateTXDecoderStepCheckDuration,
|
||||
} GateTXDecoderStep;
|
||||
|
||||
SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) {
|
||||
SubGhzProtocolGateTX* instance = furi_alloc(sizeof(SubGhzProtocolGateTX));
|
||||
|
||||
@ -13,11 +19,11 @@ SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) {
|
||||
instance->common.te_short = 350;
|
||||
instance->common.te_long = 700;
|
||||
instance->common.te_delta = 100;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str;
|
||||
instance->common.to_load_protocol_from_file=
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_gate_tx_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_gate_tx_to_load_protocol;
|
||||
@ -31,33 +37,40 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder){
|
||||
bool subghz_protocol_gate_tx_send_key(
|
||||
SubGhzProtocolGateTX* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload =(instance->common.code_last_count_bit * 2) + 2;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short * 49);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 49);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
//Send key data
|
||||
for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)){
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
}else{
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
@ -65,68 +78,78 @@ void subghz_protocol_gate_tx_reset(SubGhzProtocolGateTX* instance) {
|
||||
* @param instance SubGhzProtocolFaacSLH instance
|
||||
*/
|
||||
void subghz_protocol_gate_tx_check_remote_controller(SubGhzProtocolGateTX* instance) {
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
instance->common.serial = (code_found_reverse & 0xFF) << 12 | ((code_found_reverse >>8) & 0xFF) << 4 | ((code_found_reverse >>20) & 0x0F) ;
|
||||
instance->common.serial = (code_found_reverse & 0xFF) << 12 |
|
||||
((code_found_reverse >> 8) & 0xFF) << 4 |
|
||||
((code_found_reverse >> 20) & 0x0F);
|
||||
instance->common.btn = ((code_found_reverse >> 16) & 0x0F);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short * 47)< instance->common.te_delta * 47)) {
|
||||
switch(instance->common.parser_step) {
|
||||
case GateTXDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 47) <
|
||||
instance->common.te_delta * 47)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (level && ((DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3))){
|
||||
case GateTXDecoderStepFoundStartBit:
|
||||
if(level &&
|
||||
((DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta * 3))) {
|
||||
//Found start bit
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!level) {
|
||||
if (duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
|
||||
case GateTXDecoderStepSaveDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = GateTXDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = GateTXDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(level){
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3)) {
|
||||
break;
|
||||
case GateTXDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta*3)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = GateTXDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
}else{
|
||||
instance->common.parser_step = 0;
|
||||
} else {
|
||||
instance->common.parser_step = GateTXDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -134,16 +157,16 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u
|
||||
|
||||
void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
subghz_protocol_gate_tx_check_remote_controller(instance);
|
||||
string_cat_printf(output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%06lX\r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFF),
|
||||
instance->common.serial,
|
||||
instance->common.btn
|
||||
);
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:%06lX\r\n"
|
||||
"Sn:%05lX Btn:%lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
(uint32_t)(instance->common.code_last_found & 0xFFFFFF),
|
||||
instance->common.serial,
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output) {
|
||||
@ -157,7 +180,9 @@ void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
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) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
@ -195,9 +220,7 @@ bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker,
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_gate_tx_to_load_protocol(
|
||||
SubGhzProtocolGateTX* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -4,6 +4,13 @@ struct SubGhzProtocolIDo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
IDoDecoderStepReset = 0,
|
||||
IDoDecoderStepFoundPreambula,
|
||||
IDoDecoderStepSaveDuration,
|
||||
IDoDecoderStepCheckDuration,
|
||||
} IDoDecoderStep;
|
||||
|
||||
SubGhzProtocolIDo* subghz_protocol_ido_alloc(void) {
|
||||
SubGhzProtocolIDo* instance = furi_alloc(sizeof(SubGhzProtocolIDo));
|
||||
|
||||
@ -12,7 +19,7 @@ SubGhzProtocolIDo* subghz_protocol_ido_alloc(void) {
|
||||
instance->common.te_short = 450;
|
||||
instance->common.te_long = 1450;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_ido_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_ido_to_load_protocol;
|
||||
@ -65,7 +72,7 @@ void subghz_protocol_ido_send_key(
|
||||
}
|
||||
|
||||
void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
@ -83,29 +90,29 @@ void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance) {
|
||||
|
||||
void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
case IDoDecoderStepReset:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case IDoDecoderStepFoundPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 5)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case IDoDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 5 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = IDoDecoderStepFoundPreambula;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
@ -119,32 +126,32 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = IDoDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case IDoDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = IDoDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = IDoDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -174,9 +181,7 @@ void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output) {
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
void subghz_decoder_ido_to_load_protocol(
|
||||
SubGhzProtocolIDo* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -13,6 +13,13 @@ struct SubGhzProtocolKeeloq {
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
KeeloqDecoderStepReset = 0,
|
||||
KeeloqDecoderStepCheckPreambula,
|
||||
KeeloqDecoderStepSaveDuration,
|
||||
KeeloqDecoderStepCheckDuration,
|
||||
} KeeloqDecoderStep;
|
||||
|
||||
SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolKeeloq* instance = furi_alloc(sizeof(SubGhzProtocolKeeloq));
|
||||
|
||||
@ -23,7 +30,7 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) {
|
||||
instance->common.te_short = 400;
|
||||
instance->common.te_long = 800;
|
||||
instance->common.te_delta = 140;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str;
|
||||
@ -297,50 +304,50 @@ bool subghz_protocol_keeloq_send_key(
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_reset(SubGhzProtocolKeeloq* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
case KeeloqDecoderStepReset:
|
||||
if((level) &&
|
||||
DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
case KeeloqDecoderStepCheckPreambula:
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
break;
|
||||
}
|
||||
if((instance->common.header_count > 2) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 10) <
|
||||
instance->common.te_delta * 10)) {
|
||||
// Found header
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case KeeloqDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = KeeloqDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case KeeloqDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta)) {
|
||||
// Found end TX
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
@ -363,7 +370,7 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
}
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
@ -372,13 +379,13 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
}
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = KeeloqDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = KeeloqDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -4,6 +4,13 @@ struct SubGhzProtocolNeroRadio {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NeroRadioDecoderStepReset = 0,
|
||||
NeroRadioDecoderStepCheckPreambula,
|
||||
NeroRadioDecoderStepSaveDuration,
|
||||
NeroRadioDecoderStepCheckDuration,
|
||||
} NeroRadioDecoderStep;
|
||||
|
||||
SubGhzProtocolNeroRadio* subghz_protocol_nero_radio_alloc(void) {
|
||||
SubGhzProtocolNeroRadio* instance = furi_alloc(sizeof(SubGhzProtocolNeroRadio));
|
||||
|
||||
@ -12,7 +19,7 @@ SubGhzProtocolNeroRadio* subghz_protocol_nero_radio_alloc(void) {
|
||||
instance->common.te_short = 200;
|
||||
instance->common.te_long = 400;
|
||||
instance->common.te_delta = 80;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_radio_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_radio_to_save_str;
|
||||
@ -74,7 +81,7 @@ bool subghz_protocol_nero_radio_send_key(
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_radio_reset(SubGhzProtocolNeroRadio* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
@ -99,24 +106,24 @@ void subghz_protocol_nero_radio_parse(
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
case NeroRadioDecoderStepReset:
|
||||
if((level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = NeroRadioDecoderStepCheckPreambula;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.header_count = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case NeroRadioDecoderStepCheckPreambula:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) ||
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 4) <
|
||||
instance->common.te_delta)) {
|
||||
instance->common.te_last = duration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
if(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
@ -129,32 +136,32 @@ void subghz_protocol_nero_radio_parse(
|
||||
instance->common.te_delta) {
|
||||
// Found start bit
|
||||
if(instance->common.header_count > 40) {
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case NeroRadioDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NeroRadioDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case NeroRadioDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta * 2)) {
|
||||
//Found stop bit
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
@ -165,25 +172,25 @@ void subghz_protocol_nero_radio_parse(
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
break;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NeroRadioDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroRadioDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1,23 +1,29 @@
|
||||
#include "subghz_protocol_nero_sketch.h"
|
||||
|
||||
|
||||
struct SubGhzProtocolNeroSketch {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NeroSketchDecoderStepReset = 0,
|
||||
NeroSketchDecoderStepCheckPreambula,
|
||||
NeroSketchDecoderStepSaveDuration,
|
||||
NeroSketchDecoderStepCheckDuration,
|
||||
} NeroSketchDecoderStep;
|
||||
|
||||
SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) {
|
||||
SubGhzProtocolNeroSketch* instance = furi_alloc(sizeof(SubGhzProtocolNeroSketch));
|
||||
|
||||
instance->common.name = "Nero Sketch";
|
||||
instance->common.name = "Nero Sketch";
|
||||
instance->common.code_min_count_bit_for_found = 40;
|
||||
instance->common.te_short = 330;
|
||||
instance->common.te_long = 660;
|
||||
instance->common.te_delta = 150;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str;
|
||||
instance->common.to_load_protocol_from_file=
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_sketch_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nero_sketch_to_load_protocol;
|
||||
@ -32,45 +38,51 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder){
|
||||
bool subghz_protocol_nero_sketch_send_key(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload = 47*2+2+(instance->common.code_last_count_bit * 2) + 2;
|
||||
encoder->size_upload = 47 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
|
||||
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 47; i++){
|
||||
for(uint8_t i = 0; i < 47; i++) {
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}
|
||||
|
||||
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short*4);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 4);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
//Send key data
|
||||
for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)){
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
}else{
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
|
||||
//Send stop bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short*3);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short * 3);
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Analysis of received data
|
||||
@ -90,112 +102,123 @@ void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) {
|
||||
|
||||
// }
|
||||
|
||||
void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
void subghz_protocol_nero_sketch_parse(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NeroSketchDecoderStepReset:
|
||||
if((level) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckPreambula;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.header_count = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (level){
|
||||
if((DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta )
|
||||
|| (DURATION_DIFF(duration,instance->common.te_short*4)< instance->common.te_delta)) {
|
||||
case NeroSketchDecoderStepCheckPreambula:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) ||
|
||||
(DURATION_DIFF(duration, instance->common.te_short * 4) <
|
||||
instance->common.te_delta)) {
|
||||
instance->common.te_last = duration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else if(DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta){
|
||||
if(DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta){
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
if(DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) {
|
||||
// Found header
|
||||
instance->common.header_count++;
|
||||
break;
|
||||
}else if(DURATION_DIFF(instance->common.te_last,instance->common.te_short*4)< instance->common.te_delta){
|
||||
// Found start bit
|
||||
if(instance->common.header_count>40) {
|
||||
instance->common.parser_step = 2;
|
||||
} else if(
|
||||
DURATION_DIFF(instance->common.te_last, instance->common.te_short * 4) <
|
||||
instance->common.te_delta) {
|
||||
// Found start bit
|
||||
if(instance->common.header_count > 40) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
}else {
|
||||
instance->common.parser_step = 0;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (level) {
|
||||
if (duration >= (instance->common.te_short * 2 + instance->common.te_delta*2)) {
|
||||
case NeroSketchDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_short * 2 + instance->common.te_delta * 2)) {
|
||||
//Found stop bit
|
||||
instance->common.parser_step = 0;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NeroSketchDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
}else{
|
||||
instance->common.parser_step = 0;
|
||||
} else {
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(!level){
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta)) {
|
||||
case NeroSketchDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long )< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NeroSketchDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NeroSketchDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
|
||||
string_cat_printf(output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Yek:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo
|
||||
);
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%lX%08lX\r\n"
|
||||
"Yek:0x%lX%08lX\r\n",
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo,
|
||||
code_found_reverse_hi,
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output) {
|
||||
@ -210,11 +233,12 @@ void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance,
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_hi,
|
||||
code_found_lo
|
||||
);
|
||||
code_found_lo);
|
||||
}
|
||||
|
||||
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) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
@ -242,7 +266,7 @@ bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_wor
|
||||
if(res != 2) {
|
||||
break;
|
||||
}
|
||||
instance->common.code_last_found = (uint64_t)temp_key_hi<<32 | temp_key_lo;
|
||||
instance->common.code_last_found = (uint64_t)temp_key_hi << 32 | temp_key_lo;
|
||||
|
||||
loaded = true;
|
||||
} while(0);
|
||||
@ -252,9 +276,7 @@ bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_wor
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nero_sketch_to_load_protocol(
|
||||
SubGhzProtocolNeroSketch* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -10,6 +10,13 @@ struct SubGhzProtocolNiceFlo {
|
||||
SubGhzProtocolCommon common;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFloDecoderStepReset = 0,
|
||||
NiceFloDecoderStepFoundStartBit,
|
||||
NiceFloDecoderStepSaveDuration,
|
||||
NiceFloDecoderStepCheckDuration,
|
||||
} NiceFloDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() {
|
||||
SubGhzProtocolNiceFlo* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlo));
|
||||
|
||||
@ -18,11 +25,11 @@ SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() {
|
||||
instance->common.te_short = 700;
|
||||
instance->common.te_long = 1400;
|
||||
instance->common.te_delta = 200;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flo_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_protocol_nice_flo_to_save_str;
|
||||
instance->common.to_load_protocol_from_file=
|
||||
instance->common.to_load_protocol_from_file =
|
||||
(SubGhzProtocolCommonLoadFromFile)subghz_protocol_nice_flo_to_load_protocol_from_file;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flo_to_load_protocol;
|
||||
@ -36,94 +43,105 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder){
|
||||
bool subghz_protocol_nice_flo_send_key(
|
||||
SubGhzProtocolNiceFlo* instance,
|
||||
SubGhzProtocolCommonEncoder* encoder) {
|
||||
furi_assert(instance);
|
||||
furi_assert(encoder);
|
||||
size_t index = 0;
|
||||
encoder->size_upload =(instance->common.code_last_count_bit * 2) + 2;
|
||||
encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2;
|
||||
if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false;
|
||||
//Send header
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short * 36);
|
||||
//Send start bit
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
//Send key data
|
||||
for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)){
|
||||
for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) {
|
||||
if(bit_read(instance->common.code_last_found, i - 1)) {
|
||||
//send bit 1
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
}else{
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(false, (uint32_t)instance->common.te_short);
|
||||
encoder->upload[index++] =
|
||||
level_duration_make(true, (uint32_t)instance->common.te_long);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_reset(SubGhzProtocolNiceFlo* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short * 36)< instance->common.te_delta * 36)) {
|
||||
switch(instance->common.parser_step) {
|
||||
case NiceFloDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found header Nice Flo
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!level) {
|
||||
case NiceFloDecoderStepFoundStartBit:
|
||||
if(!level) {
|
||||
break;
|
||||
} else if (DURATION_DIFF(duration, instance->common.te_short)< instance->common.te_delta) {
|
||||
} else if(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta) {
|
||||
//Found start bit Nice Flo
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!level) { //save interval
|
||||
if (duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = 1;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
|
||||
case NiceFloDecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (instance->common.te_short * 4)) {
|
||||
instance->common.parser_step = NiceFloDecoderStepFoundStartBit;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.serial = 0x0;
|
||||
instance->common.btn = 0x0;
|
||||
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NiceFloDecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (level) {
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short) < instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_long)< instance->common.te_delta)) {
|
||||
case NiceFloDecoderStepCheckDuration:
|
||||
if(level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NiceFloDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFloDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -145,11 +163,9 @@ void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t o
|
||||
instance->common.name,
|
||||
instance->common.code_last_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo
|
||||
);
|
||||
code_found_reverse_lo);
|
||||
}
|
||||
|
||||
|
||||
void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output) {
|
||||
string_printf(
|
||||
output,
|
||||
@ -161,7 +177,9 @@ void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, strin
|
||||
(uint32_t)(instance->common.code_last_found & 0x00000000ffffffff));
|
||||
}
|
||||
|
||||
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) {
|
||||
bool loaded = false;
|
||||
string_t temp_str;
|
||||
string_init(temp_str);
|
||||
@ -198,9 +216,7 @@ bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_nice_flo_to_load_protocol(
|
||||
SubGhzProtocolNiceFlo* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -13,6 +13,14 @@ struct SubGhzProtocolNiceFlorS {
|
||||
const char* rainbow_table_file_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NiceFlorSDecoderStepReset = 0,
|
||||
NiceFlorSDecoderStepCheckHeader,
|
||||
NiceFlorSDecoderStepFoundHeader,
|
||||
NiceFlorSDecoderStepSaveDuration,
|
||||
NiceFlorSDecoderStepCheckDuration,
|
||||
} NiceFlorSDecoderStep;
|
||||
|
||||
SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc() {
|
||||
SubGhzProtocolNiceFlorS* instance = furi_alloc(sizeof(SubGhzProtocolNiceFlorS));
|
||||
|
||||
@ -21,7 +29,7 @@ SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc() {
|
||||
instance->common.te_short = 500;
|
||||
instance->common.te_long = 1000;
|
||||
instance->common.te_delta = 300;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flor_s_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flor_s_to_load_protocol;
|
||||
@ -93,16 +101,14 @@ void subghz_protocol_nice_flor_s_send_key(
|
||||
* @return byte data
|
||||
*/
|
||||
uint8_t subghz_nice_flor_s_get_byte_in_file(SubGhzProtocolNiceFlorS* instance, uint32_t address) {
|
||||
if(!instance->rainbow_table_file_name)
|
||||
return 0;
|
||||
if(!instance->rainbow_table_file_name) return 0;
|
||||
|
||||
uint8_t buffer = 0;
|
||||
FileWorker* file_worker = file_worker_alloc(true);
|
||||
if(file_worker_open(file_worker, instance->rainbow_table_file_name, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
if(file_worker_open(
|
||||
file_worker, instance->rainbow_table_file_name, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
file_worker_seek(file_worker, address, true);
|
||||
file_worker_read(file_worker, &buffer, 1);
|
||||
// bool res = file_worker_read(file_worker, &buffer, 1);
|
||||
// furi_assert(res== true);
|
||||
}
|
||||
file_worker_close(file_worker);
|
||||
file_worker_free(file_worker);
|
||||
@ -134,8 +140,11 @@ void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
|
||||
*/
|
||||
|
||||
uint16_t p3p4 = (uint16_t)(instance->common.code_last_found >> 24);
|
||||
instance->common.cnt = subghz_nice_flor_s_get_byte_in_file(instance,p3p4*2) << 8 | subghz_nice_flor_s_get_byte_in_file(instance,p3p4*2+1);
|
||||
uint8_t k =(uint8_t)(p3p4 & 0x00FF) ^subghz_nice_flor_s_get_byte_in_file(instance,(0x20000 |(instance->common.cnt &0x00ff)));
|
||||
instance->common.cnt = subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2) << 8 |
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, p3p4 * 2 + 1);
|
||||
uint8_t k =
|
||||
(uint8_t)(p3p4 & 0x00FF) ^
|
||||
subghz_nice_flor_s_get_byte_in_file(instance, (0x20000 | (instance->common.cnt & 0x00ff)));
|
||||
|
||||
uint8_t s3 = ((uint8_t)(instance->common.code_last_found >> 40) ^ k) & 0x0f;
|
||||
uint8_t s2 = ((uint8_t)(instance->common.code_last_found >> 16) ^ k);
|
||||
@ -147,73 +156,82 @@ void subghz_nice_flor_s_decoder_decrypt(SubGhzProtocolNiceFlorS* instance) {
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_reset(SubGhzProtocolNiceFlorS* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool level, uint32_t duration) {
|
||||
void subghz_protocol_nice_flor_s_parse(
|
||||
SubGhzProtocolNiceFlorS* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
if((!level)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short * 38) < instance->common.te_delta * 38)) {
|
||||
case NiceFlorSDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 38) <
|
||||
instance->common.te_delta * 38)) {
|
||||
//Found start header Nice Flor-S
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckHeader;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if((level)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short * 3) < instance->common.te_delta * 3)) {
|
||||
case NiceFlorSDecoderStepCheckHeader:
|
||||
if((level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found next header Nice Flor-S
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepFoundHeader;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if((!level)
|
||||
&& (DURATION_DIFF(duration, instance->common.te_short * 3) < instance->common.te_delta * 3)) {
|
||||
case NiceFlorSDecoderStepFoundHeader:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta * 3)) {
|
||||
//Found header Nice Flor-S
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case NiceFlorSDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_short * 3) < instance->common.te_delta) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_short * 3) <
|
||||
instance->common.te_delta) {
|
||||
//Found STOP bit
|
||||
instance->common.parser_step = 0;
|
||||
if(instance->common.code_count_bit >=instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if(instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
//save interval
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 4;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepCheckDuration;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case NiceFlorSDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) < instance->common.te_delta)
|
||||
&&(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) < instance->common.te_delta)
|
||||
&&(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepSaveDuration;
|
||||
} else
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = NiceFlorSDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -236,13 +254,10 @@ void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, strin
|
||||
code_found_lo,
|
||||
instance->common.serial,
|
||||
instance->common.cnt,
|
||||
instance->common.btn
|
||||
);
|
||||
instance->common.btn);
|
||||
}
|
||||
|
||||
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) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -16,6 +16,12 @@ struct SubGhzEncoderPrinceton {
|
||||
size_t front;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PrincetonDecoderStepReset = 0,
|
||||
PrincetonDecoderStepSaveDuration,
|
||||
PrincetonDecoderStepCheckDuration,
|
||||
} PrincetonDecoderStep;
|
||||
|
||||
SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc() {
|
||||
SubGhzEncoderPrinceton* instance = furi_alloc(sizeof(SubGhzEncoderPrinceton));
|
||||
return instance;
|
||||
@ -87,7 +93,7 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) {
|
||||
instance->common.te_short = SUBGHZ_PT_SHORT; //150;
|
||||
instance->common.te_long = SUBGHZ_PT_LONG; //450;
|
||||
instance->common.te_delta = 250; //50;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_STATIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeStatic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str;
|
||||
instance->common.to_save_string =
|
||||
(SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str;
|
||||
@ -142,7 +148,7 @@ bool subghz_protocol_princeton_send_key(
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_parse(
|
||||
@ -150,28 +156,28 @@ void subghz_decoder_princeton_parse(
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case 0:
|
||||
case PrincetonDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 36) <
|
||||
instance->common.te_delta * 36)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case PrincetonDecoderStepSaveDuration:
|
||||
//save duration
|
||||
if(level) {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = PrincetonDecoderStepCheckDuration;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case PrincetonDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if(duration >= (instance->common.te_short * 10 + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
if(instance->common.code_count_bit ==
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found == instance->common.code_found) {
|
||||
@ -201,18 +207,18 @@ void subghz_decoder_princeton_parse(
|
||||
(DURATION_DIFF(duration, instance->common.te_long) <
|
||||
instance->common.te_delta * 3)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta * 3) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 1;
|
||||
instance->common.parser_step = PrincetonDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = PrincetonDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -306,9 +312,7 @@ bool subghz_decoder_princeton_to_load_protocol_from_file(
|
||||
return loaded;
|
||||
}
|
||||
|
||||
void subghz_decoder_princeton_to_load_protocol(
|
||||
SubGhzDecoderPrinceton* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_princeton_to_load_protocol(SubGhzDecoderPrinceton* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -8,24 +8,30 @@
|
||||
#include <m-string.h>
|
||||
#include <m-array.h>
|
||||
|
||||
|
||||
struct SubGhzProtocolStarLine {
|
||||
SubGhzProtocolCommon common;
|
||||
SubGhzKeystore* keystore;
|
||||
const char* manufacture_name;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
StarLineDecoderStepReset = 0,
|
||||
StarLineDecoderStepCheckPreambula,
|
||||
StarLineDecoderStepSaveDuration,
|
||||
StarLineDecoderStepCheckDuration,
|
||||
} StarLineDecoderStep;
|
||||
|
||||
SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore) {
|
||||
SubGhzProtocolStarLine* instance = furi_alloc(sizeof(SubGhzProtocolStarLine));
|
||||
|
||||
instance->keystore = keystore;
|
||||
|
||||
instance->common.name = "Star Line";
|
||||
instance->common.name = "Star Line";
|
||||
instance->common.code_min_count_bit_for_found = 64;
|
||||
instance->common.te_short = 250;
|
||||
instance->common.te_long = 500;
|
||||
instance->common.te_delta = 120;
|
||||
instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC;
|
||||
instance->common.type_protocol = SubGhzProtocolCommonTypeDynamic;
|
||||
instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_star_line_to_str;
|
||||
instance->common.to_load_protocol =
|
||||
(SubGhzProtocolCommonLoadFromRAW)subghz_decoder_star_line_to_load_protocol;
|
||||
@ -38,13 +44,13 @@ void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name (void* context){
|
||||
const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
subghz_protocol_star_line_check_remote_controller(instance);
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
|
||||
const char* subghz_protocol_star_line_get_manufacture_name (void* context){
|
||||
const char* subghz_protocol_star_line_get_manufacture_name(void* context) {
|
||||
SubGhzProtocolStarLine* instance = context;
|
||||
return instance->manufacture_name;
|
||||
}
|
||||
@ -55,7 +61,7 @@ const char* subghz_protocol_star_line_get_manufacture_name (void* context){
|
||||
* @param bit - bit
|
||||
*/
|
||||
void subghz_protocol_star_line_send_bit(SubGhzProtocolStarLine* instance, uint8_t bit) {
|
||||
if (bit) {
|
||||
if(bit) {
|
||||
//send bit 1
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long);
|
||||
@ -70,18 +76,22 @@ void subghz_protocol_star_line_send_bit(SubGhzProtocolStarLine* instance, uint8_
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_send_key(SubGhzProtocolStarLine* instance, uint64_t key, uint8_t bit,uint8_t repeat) {
|
||||
while (repeat--) {
|
||||
void subghz_protocol_star_line_send_key(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint64_t key,
|
||||
uint8_t bit,
|
||||
uint8_t repeat) {
|
||||
while(repeat--) {
|
||||
//Send header
|
||||
for(uint8_t i = 0; i < 6; i++){
|
||||
for(uint8_t i = 0; i < 6; i++) {
|
||||
SUBGHZ_TX_PIN_HIGH();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
SUBGHZ_TX_PIN_LOW();
|
||||
delay_us(instance->common.te_long * 2);
|
||||
}
|
||||
delay_us(instance->common.te_long * 2);
|
||||
}
|
||||
//Send Start bit ??????????
|
||||
//Send key data
|
||||
for (uint8_t i = bit; i > 0; i--) {
|
||||
for(uint8_t i = bit; i > 0; i--) {
|
||||
subghz_protocol_star_line_send_bit(instance, bit_read(key, i - 1));
|
||||
}
|
||||
//Send Stop bit ??????????
|
||||
@ -89,7 +99,7 @@ void subghz_protocol_star_line_send_key(SubGhzProtocolStarLine* instance, uint64
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance) {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
|
||||
/** Checking the accepted code against the database manafacture key
|
||||
@ -99,86 +109,97 @@ void subghz_protocol_star_line_reset(SubGhzProtocolStarLine* instance) {
|
||||
* @param hop hop encrypted part of the parcel
|
||||
* @return true on successful search
|
||||
*/
|
||||
uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtocolStarLine* instance, uint32_t fix , uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix&0xFF);
|
||||
uint8_t btn = (uint8_t)(fix>>24);
|
||||
uint8_t subghz_protocol_star_line_check_remote_controller_selector(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
uint32_t fix,
|
||||
uint32_t hop) {
|
||||
uint16_t end_serial = (uint16_t)(fix & 0xFF);
|
||||
uint8_t btn = (uint8_t)(fix >> 24);
|
||||
uint32_t decrypt = 0;
|
||||
uint64_t man_normal_learning;
|
||||
|
||||
for
|
||||
M_EACH(manufacture_code, *subghz_keystore_get_data(instance->keystore), SubGhzKeyArray_t) {
|
||||
switch (manufacture_code->type){
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt>>24 == btn) && ((((uint16_t)(decrypt>>16)) & 0x00FF) == end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
switch(manufacture_code->type) {
|
||||
case KEELOQ_LEARNING_SIMPLE:
|
||||
//Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>24 ==btn)&& ((((uint16_t)(decrypt>>16))&0x00FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
case KEELOQ_LEARNING_NORMAL:
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if( (decrypt>>24 ==btn) && ((((uint16_t)(decrypt>>16))&0x00FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev=0;
|
||||
uint64_t man_rev_byte=0;
|
||||
for(uint8_t i=0; i<64; i+=8){
|
||||
man_rev_byte=(uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56-i);
|
||||
}
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if( (decrypt>>24 ==btn) && ((((uint16_t)(decrypt>>16))&0x00FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>24 ==btn)&& ((((uint16_t)(decrypt>>16))&0x00FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev=0;
|
||||
man_rev_byte=0;
|
||||
for(uint8_t i=0; i<64; i+=8){
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56-i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt=subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if( (decrypt>>24 ==btn) && ((((uint16_t)(decrypt>>16))&0x00FF)==end_serial)){
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt= decrypt&0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
case KEELOQ_LEARNING_UNKNOWN:
|
||||
// Simple Learning
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
uint64_t man_rev = 0;
|
||||
uint64_t man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
//###########################
|
||||
// Normal_Learning
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man_normal_learning =
|
||||
subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
// Check for mirrored man
|
||||
man_rev = 0;
|
||||
man_rev_byte = 0;
|
||||
for(uint8_t i = 0; i < 64; i += 8) {
|
||||
man_rev_byte = (uint8_t)(manufacture_code->key >> i);
|
||||
man_rev = man_rev | man_rev_byte << (56 - i);
|
||||
}
|
||||
man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning);
|
||||
if((decrypt >> 24 == btn) &&
|
||||
((((uint16_t)(decrypt >> 16)) & 0x00FF) == end_serial)) {
|
||||
instance->manufacture_name = string_get_cstr(manufacture_code->name);
|
||||
instance->common.cnt = decrypt & 0x0000FFFF;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
instance->manufacture_name = "Unknown";
|
||||
instance->common.cnt=0;
|
||||
instance->common.cnt = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -188,53 +209,61 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco
|
||||
* @param instance SubGhzProtocolStarLine instance
|
||||
*/
|
||||
void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* instance) {
|
||||
uint64_t key = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint64_t key = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint32_t key_fix = key >> 32;
|
||||
uint32_t key_hop = key & 0x00000000ffffffff;
|
||||
|
||||
subghz_protocol_star_line_check_remote_controller_selector(instance, key_fix, key_hop);
|
||||
|
||||
instance ->common.serial= key_fix&0x00FFFFFF;
|
||||
instance->common.serial = key_fix & 0x00FFFFFF;
|
||||
instance->common.btn = key_fix >> 24;
|
||||
}
|
||||
|
||||
void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool level, uint32_t duration) {
|
||||
switch (instance->common.parser_step) {
|
||||
case 0:
|
||||
if (level){
|
||||
if(DURATION_DIFF(duration,instance->common.te_long * 2)< instance->common.te_delta * 2) {
|
||||
instance->common.parser_step = 1;
|
||||
void subghz_protocol_star_line_parse(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
bool level,
|
||||
uint32_t duration) {
|
||||
switch(instance->common.parser_step) {
|
||||
case StarLineDecoderStepReset:
|
||||
if(level) {
|
||||
if(DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2) {
|
||||
instance->common.parser_step = StarLineDecoderStepCheckPreambula;
|
||||
instance->common.header_count++;
|
||||
} else if(instance->common.header_count>4){
|
||||
} else if(instance->common.header_count > 4) {
|
||||
instance->common.code_found = 0;
|
||||
instance->common.code_count_bit = 0;
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
}else{
|
||||
instance->common.parser_step = 0;
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
instance->common.header_count = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ((!level)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long * 2)< instance->common.te_delta * 2)) {
|
||||
case StarLineDecoderStepCheckPreambula:
|
||||
if((!level) && (DURATION_DIFF(duration, instance->common.te_long * 2) <
|
||||
instance->common.te_delta * 2)) {
|
||||
//Found Preambula
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
} else {
|
||||
instance->common.header_count = 0;
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (level) {
|
||||
if (duration >= (instance->common.te_long + instance->common.te_delta)) {
|
||||
instance->common.parser_step = 0;
|
||||
if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found){
|
||||
case StarLineDecoderStepSaveDuration:
|
||||
if(level) {
|
||||
if(duration >= (instance->common.te_long + instance->common.te_delta)) {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
if(instance->common.code_count_bit >=
|
||||
instance->common.code_min_count_bit_for_found) {
|
||||
if(instance->common.code_last_found != instance->common.code_found) {
|
||||
instance->common.code_last_found = instance->common.code_found;
|
||||
instance->common.code_last_count_bit = instance->common.code_count_bit;
|
||||
if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
if(instance->common.callback)
|
||||
instance->common.callback(
|
||||
(SubGhzProtocolCommon*)instance, instance->common.context);
|
||||
}
|
||||
}
|
||||
instance->common.code_found = 0;
|
||||
@ -243,28 +272,31 @@ void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool leve
|
||||
break;
|
||||
} else {
|
||||
instance->common.te_last = duration;
|
||||
instance->common.parser_step = 3;
|
||||
instance->common.parser_step = StarLineDecoderStepCheckDuration;
|
||||
}
|
||||
|
||||
}else{
|
||||
instance->common.parser_step = 0;
|
||||
} else {
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if(!level){
|
||||
if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) {
|
||||
case StarLineDecoderStepCheckDuration:
|
||||
if(!level) {
|
||||
if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 0);
|
||||
instance->common.parser_step = 2;
|
||||
} else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_long )< instance->common.te_delta)
|
||||
&& (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta)) {
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else if(
|
||||
(DURATION_DIFF(instance->common.te_last, instance->common.te_long) <
|
||||
instance->common.te_delta) &&
|
||||
(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta)) {
|
||||
subghz_protocol_common_add_bit(&instance->common, 1);
|
||||
instance->common.parser_step = 2;
|
||||
instance->common.parser_step = StarLineDecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
} else {
|
||||
instance->common.parser_step = 0;
|
||||
instance->common.parser_step = StarLineDecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -275,10 +307,11 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t
|
||||
uint32_t code_found_hi = instance->common.code_last_found >> 32;
|
||||
uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff;
|
||||
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
uint64_t code_found_reverse = subghz_protocol_common_reverse_key(
|
||||
instance->common.code_last_found, instance->common.code_last_count_bit);
|
||||
|
||||
uint32_t code_found_reverse_hi = code_found_reverse>>32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff;
|
||||
uint32_t code_found_reverse_hi = code_found_reverse >> 32;
|
||||
uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s %dbit\r\n"
|
||||
@ -296,13 +329,10 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t
|
||||
code_found_reverse_lo,
|
||||
instance->common.btn,
|
||||
instance->manufacture_name,
|
||||
instance->common.serial
|
||||
);
|
||||
instance->common.serial);
|
||||
}
|
||||
|
||||
void subghz_decoder_star_line_to_load_protocol(
|
||||
SubGhzProtocolStarLine* instance,
|
||||
void* context) {
|
||||
void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context) {
|
||||
furi_assert(context);
|
||||
furi_assert(instance);
|
||||
SubGhzProtocolCommonLoad* data = context;
|
||||
|
@ -1,18 +1,19 @@
|
||||
#include "subghz_protocol.h"
|
||||
#include "subghz_protocol_came.h"
|
||||
#include "subghz_protocol_cfm.h"
|
||||
#include "subghz_protocol_keeloq.h"
|
||||
#include "subghz_protocol_nice_flo.h"
|
||||
#include "subghz_protocol_nice_flor_s.h"
|
||||
#include "subghz_protocol_princeton.h"
|
||||
#include "subghz_protocol_gate_tx.h"
|
||||
#include "subghz_protocol_ido.h"
|
||||
#include "subghz_protocol_faac_slh.h"
|
||||
#include "subghz_protocol_nero_sketch.h"
|
||||
#include "subghz_protocol_star_line.h"
|
||||
#include "subghz_protocol_nero_radio.h"
|
||||
|
||||
#include "../subghz_keystore.h"
|
||||
#include "subghz_parser.h"
|
||||
#include "protocols/subghz_protocol_came.h"
|
||||
#include "protocols/subghz_protocol_cfm.h"
|
||||
#include "protocols/subghz_protocol_keeloq.h"
|
||||
#include "protocols/subghz_protocol_nice_flo.h"
|
||||
#include "protocols/subghz_protocol_nice_flor_s.h"
|
||||
#include "protocols/subghz_protocol_princeton.h"
|
||||
#include "protocols/subghz_protocol_gate_tx.h"
|
||||
#include "protocols/subghz_protocol_ido.h"
|
||||
#include "protocols/subghz_protocol_faac_slh.h"
|
||||
#include "protocols/subghz_protocol_nero_sketch.h"
|
||||
#include "protocols/subghz_protocol_star_line.h"
|
||||
#include "protocols/subghz_protocol_nero_radio.h"
|
||||
|
||||
#include "subghz_keystore.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <m-string.h>
|
||||
@ -33,7 +34,7 @@ typedef enum {
|
||||
SubGhzProtocolTypeMax,
|
||||
} SubGhzProtocolType;
|
||||
|
||||
struct SubGhzProtocol {
|
||||
struct SubGhzParser {
|
||||
SubGhzKeystore* keystore;
|
||||
|
||||
SubGhzProtocolCommon* protocols[SubGhzProtocolTypeMax];
|
||||
@ -44,8 +45,8 @@ struct SubGhzProtocol {
|
||||
void* parser_callback_context;
|
||||
};
|
||||
|
||||
static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
SubGhzProtocol* instance = context;
|
||||
static void subghz_parser_text_rx_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
SubGhzParser* instance = context;
|
||||
|
||||
string_t output;
|
||||
string_init(output);
|
||||
@ -58,15 +59,15 @@ static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void*
|
||||
string_clear(output);
|
||||
}
|
||||
|
||||
static void subghz_protocol_parser_rx_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
SubGhzProtocol* instance = context;
|
||||
static void subghz_parser_parser_rx_callback(SubGhzProtocolCommon* parser, void* context) {
|
||||
SubGhzParser* instance = context;
|
||||
if(instance->parser_callback) {
|
||||
instance->parser_callback(parser, instance->parser_callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
SubGhzProtocol* subghz_protocol_alloc() {
|
||||
SubGhzProtocol* instance = furi_alloc(sizeof(SubGhzProtocol));
|
||||
SubGhzParser* subghz_parser_alloc() {
|
||||
SubGhzParser* instance = furi_alloc(sizeof(SubGhzParser));
|
||||
|
||||
instance->keystore = subghz_keystore_alloc();
|
||||
|
||||
@ -96,7 +97,7 @@ SubGhzProtocol* subghz_protocol_alloc() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_free(SubGhzProtocol* instance) {
|
||||
void subghz_parser_free(SubGhzParser* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
subghz_protocol_came_free((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]);
|
||||
@ -125,7 +126,7 @@ void subghz_protocol_free(SubGhzProtocol* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, const char* name) {
|
||||
SubGhzProtocolCommon* subghz_parser_get_by_name(SubGhzParser* instance, const char* name) {
|
||||
SubGhzProtocolCommon* result = NULL;
|
||||
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
@ -138,46 +139,46 @@ SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, cons
|
||||
return result;
|
||||
}
|
||||
|
||||
void subghz_protocol_enable_dump_text(
|
||||
SubGhzProtocol* instance,
|
||||
void subghz_parser_enable_dump_text(
|
||||
SubGhzParser* instance,
|
||||
SubGhzProtocolTextCallback callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
subghz_protocol_common_set_callback(
|
||||
instance->protocols[i], subghz_protocol_text_rx_callback, instance);
|
||||
instance->protocols[i], subghz_parser_text_rx_callback, instance);
|
||||
}
|
||||
|
||||
instance->text_callback = callback;
|
||||
instance->text_callback_context = context;
|
||||
}
|
||||
|
||||
void subghz_protocol_enable_dump(
|
||||
SubGhzProtocol* instance,
|
||||
void subghz_parser_enable_dump(
|
||||
SubGhzParser* instance,
|
||||
SubGhzProtocolCommonCallbackDump callback,
|
||||
void* context) {
|
||||
furi_assert(instance);
|
||||
|
||||
for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) {
|
||||
subghz_protocol_common_set_callback(
|
||||
instance->protocols[i], subghz_protocol_parser_rx_callback, instance);
|
||||
instance->protocols[i], subghz_parser_parser_rx_callback, instance);
|
||||
}
|
||||
|
||||
instance->parser_callback = callback;
|
||||
instance->parser_callback_context = context;
|
||||
}
|
||||
|
||||
void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name) {
|
||||
void subghz_parser_load_nice_flor_s_file(SubGhzParser* instance, const char* file_name) {
|
||||
subghz_protocol_nice_flor_s_name_file(
|
||||
(SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name);
|
||||
}
|
||||
|
||||
void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file_name) {
|
||||
void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name) {
|
||||
subghz_keystore_load(instance->keystore, file_name);
|
||||
}
|
||||
|
||||
void subghz_protocol_reset(SubGhzProtocol* instance) {
|
||||
void subghz_parser_reset(SubGhzParser* instance) {
|
||||
subghz_protocol_came_reset((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]);
|
||||
subghz_protocol_keeloq_reset(
|
||||
(SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]);
|
||||
@ -200,7 +201,7 @@ void subghz_protocol_reset(SubGhzProtocol* instance) {
|
||||
(SubGhzProtocolNeroRadio*)instance->protocols[SubGhzProtocolTypeNeroRadio]);
|
||||
}
|
||||
|
||||
void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) {
|
||||
void subghz_parser_parse(SubGhzParser* instance, bool level, uint32_t duration) {
|
||||
subghz_protocol_came_parse(
|
||||
(SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame], level, duration);
|
||||
subghz_protocol_keeloq_parse(
|
72
lib/subghz/subghz_parser.h
Normal file
72
lib/subghz/subghz_parser.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "protocols/subghz_protocol_common.h"
|
||||
|
||||
typedef void (*SubGhzProtocolTextCallback)(string_t text, void* context);
|
||||
typedef void (*SubGhzProtocolCommonCallbackDump)(SubGhzProtocolCommon *parser, void* context);
|
||||
|
||||
typedef struct SubGhzParser SubGhzParser;
|
||||
|
||||
/** Allocate SubGhzParser
|
||||
*
|
||||
* @return SubGhzParser*
|
||||
*/
|
||||
SubGhzParser* subghz_parser_alloc();
|
||||
|
||||
/** Free SubGhzParser
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
void subghz_parser_free(SubGhzParser* instance);
|
||||
|
||||
/** Get protocol by name
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param name - name protocol
|
||||
* @param SubGhzProtocolCommon
|
||||
*/
|
||||
SubGhzProtocolCommon* subghz_parser_get_by_name(SubGhzParser* instance, const char* name);
|
||||
|
||||
/** Outputting data text from all parsers
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param callback - SubGhzProtocolTextCallback callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_parser_enable_dump_text(SubGhzParser* instance, SubGhzProtocolTextCallback callback, void* context);
|
||||
|
||||
/** Outputting data SubGhzParser from all parsers
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param callback - SubGhzProtocolTextCallback callback
|
||||
* @param context
|
||||
*/
|
||||
void subghz_parser_enable_dump(SubGhzParser* instance, SubGhzProtocolCommonCallbackDump callback, void* context);
|
||||
|
||||
/** File name rainbow table Nice Flor-S
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_parser_load_nice_flor_s_file(SubGhzParser* instance, const char* file_name);
|
||||
|
||||
/** File upload manufacture keys
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param file_name - "path/file_name"
|
||||
*/
|
||||
void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name);
|
||||
|
||||
/** Restarting all parsers
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
*/
|
||||
void subghz_parser_reset(SubGhzParser* instance);
|
||||
|
||||
/** Loading data into all parsers
|
||||
*
|
||||
* @param instance - SubGhzParser instance
|
||||
* @param level - true is high, false if low
|
||||
* @param duration - level duration in microseconds
|
||||
*/
|
||||
void subghz_parser_parse(SubGhzParser* instance, bool level, uint32_t duration);
|
Loading…
Reference in New Issue
Block a user