[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,27 +32,16 @@ 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); | ||||
|         consumed = true; | ||||
|     } else if( | ||||
|         event->key == InputKeyOk && event->type == InputTypeRelease && | ||||
|         model->button_type == GuiButtonTypeCenter) { | ||||
|         model->callback(GuiButtonTypeCenterRelease, model->context); | ||||
|         consumed = true; | ||||
|     } else if(event->type == InputTypeShort) { | ||||
|     if((model->button_type == GuiButtonTypeLeft) && (event->key == InputKeyLeft)) { | ||||
|             model->callback(model->button_type, model->context); | ||||
|         model->callback(model->button_type, event->type, model->context); | ||||
|         consumed = true; | ||||
|     } else if((model->button_type == GuiButtonTypeRight) && (event->key == InputKeyRight)) { | ||||
|             model->callback(model->button_type, model->context); | ||||
|         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, model->context); | ||||
|         model->callback(model->button_type, event->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,10 +1,11 @@ | ||||
| #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; | ||||
| 
 | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_delete_on_enter(void* context) { | ||||
|     Nfc* nfc = (Nfc*)context; | ||||
|  | ||||
| @ -7,10 +7,12 @@ 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; | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) { | ||||
|     Nfc* nfc = context; | ||||
| @ -22,10 +24,12 @@ 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; | ||||
|     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) { | ||||
|     Nfc* nfc = context; | ||||
|  | ||||
| @ -1,11 +1,15 @@ | ||||
| #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; | ||||
| 
 | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_read_emv_data_success_on_enter(void* context) { | ||||
|     Nfc* nfc = (Nfc*)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->txrx_state == SubGhzTxRxStateIdle) || | ||||
|        (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { | ||||
|         subghz_begin(subghz, subghz->txrx->preset); | ||||
|         subghz_rx(subghz, subghz->txrx->frequency); | ||||
|     } | ||||
|     if(subghz->txrx->idx_menu_chosen != 0) { | ||||
|     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; | ||||
|             if((model->idx == model->history_item - 1)) { | ||||
|                 model->history_item++; | ||||
|                 model->idx++; | ||||
|             } else { | ||||
|                 model->history_item++; | ||||
|             } | ||||
| 
 | ||||
|             return true; | ||||
|         }); | ||||
|     subghz_receiver_update_offset(subghz_receiver); | ||||
|  | ||||
| @ -37,11 +37,14 @@ static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = { | ||||
|     {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_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 */ | ||||
| @ -92,11 +95,14 @@ static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { | ||||
|     {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_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 */ | ||||
| @ -121,7 +127,6 @@ static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { | ||||
|     {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
 | ||||
| @ -136,23 +141,26 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = { | ||||
|     {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)
 | ||||
| 
 | ||||
|     /* 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_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 */ | ||||
| @ -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); | ||||
| } | ||||
| 
 | ||||
| @ -439,23 +448,24 @@ static void furi_hal_subghz_capture_ISR() { | ||||
|         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 | ||||
|             ); | ||||
|             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 | ||||
|             ); | ||||
|             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,7 +473,8 @@ 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); | ||||
| @ -549,7 +560,8 @@ 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) { | ||||
|         bool is_odd = samples % 2; | ||||
|         LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); | ||||
|         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) { | ||||
| @ -581,11 +593,14 @@ static void furi_hal_subghz_async_tx_dma_isr() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateAsyncTx); | ||||
|     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)) { | ||||
|         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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -612,11 +627,14 @@ 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}; | ||||
| @ -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); | ||||
| @ -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(); | ||||
|  | ||||
| @ -37,11 +37,14 @@ static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = { | ||||
|     {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_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 */ | ||||
| @ -92,11 +95,14 @@ static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { | ||||
|     {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_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 */ | ||||
| @ -121,7 +127,6 @@ static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { | ||||
|     {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
 | ||||
| @ -136,23 +141,26 @@ static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = { | ||||
|     {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)
 | ||||
| 
 | ||||
|     /* 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_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 */ | ||||
| @ -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); | ||||
| } | ||||
| 
 | ||||
| @ -439,23 +446,24 @@ static void furi_hal_subghz_capture_ISR() { | ||||
|         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 | ||||
|             ); | ||||
|             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 | ||||
|             ); | ||||
|             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,7 +471,8 @@ 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); | ||||
| @ -549,7 +558,8 @@ 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) { | ||||
|         bool is_odd = samples % 2; | ||||
|         LevelDuration ld = furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); | ||||
|         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) { | ||||
| @ -581,11 +591,14 @@ static void furi_hal_subghz_async_tx_dma_isr() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateAsyncTx); | ||||
|     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)) { | ||||
|         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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -612,11 +625,14 @@ 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}; | ||||
| @ -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); | ||||
| @ -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,7 +26,7 @@ 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; | ||||
| @ -38,65 +45,71 @@ 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; | ||||
|     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)) { | ||||
|             //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); | ||||
|             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
 | ||||
|     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: | ||||
|     case CameDecoderStepFoundStartBit: | ||||
|         if(!level) { | ||||
|             break; | ||||
|         } 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: | ||||
|     case CameDecoderStepSaveDuration: | ||||
|         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) { | ||||
| 
 | ||||
| 
 | ||||
|                 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; | ||||
| 
 | ||||
| @ -104,31 +117,34 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32 | ||||
|                     instance->common.code_last_count_bit = instance->common.code_count_bit; | ||||
| 
 | ||||
|                     if(instance->common.callback) | ||||
|                         instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); | ||||
|                  | ||||
|                         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: | ||||
|     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)) { | ||||
|             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; | ||||
|  | ||||
| @ -1,10 +1,16 @@ | ||||
| #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)); | ||||
| 
 | ||||
| @ -13,7 +19,7 @@ SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc(void) { | ||||
|     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; | ||||
| @ -47,7 +53,11 @@ 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) { | ||||
| 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
 | ||||
| @ -62,7 +72,7 @@ void subghz_protocol_faac_slh_send_key(SubGhzProtocolFaacSLH* instance, uint64_t | ||||
| } | ||||
| 
 | ||||
| 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;
 | ||||
| 
 | ||||
| @ -80,61 +91,67 @@ 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; | ||||
|     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: | ||||
|     case FaacSLHDecoderStepSaveDuration: | ||||
|         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) { | ||||
|                 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; | ||||
|             instance->common.parser_step = FaacSLHDecoderStepReset; | ||||
|         } | ||||
|         break; | ||||
|     case 3: | ||||
|     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)) { | ||||
|             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,11 +159,13 @@ 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; | ||||
| 
 | ||||
|     string_cat_printf(output, | ||||
|     string_cat_printf( | ||||
|         output, | ||||
|         "%s %dbit\r\n" | ||||
|         "Key:0x%lX%08lX\r\n" | ||||
|         "Fix:%08lX \r\n" | ||||
| @ -156,14 +175,13 @@ void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t o | ||||
|         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,  | ||||
|         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,7 +19,7 @@ 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; | ||||
| @ -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; | ||||
|     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)) { | ||||
|             //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); | ||||
|             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)) { | ||||
|     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: | ||||
|     case GateTXDecoderStepSaveDuration: | ||||
|         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) { | ||||
|                      | ||||
|                 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: | ||||
|     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)) { | ||||
|             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; | ||||
|             instance->common.parser_step = GateTXDecoderStepReset; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| @ -134,7 +157,8 @@ 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, | ||||
|     string_cat_printf( | ||||
|         output, | ||||
|         "%s %dbit\r\n" | ||||
|         "Key:%06lX\r\n" | ||||
|         "Sn:%05lX  Btn:%lX\r\n", | ||||
| @ -142,8 +166,7 @@ void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t out | ||||
|         instance->common.code_last_count_bit, | ||||
|         (uint32_t)(instance->common.code_last_found & 0xFFFFFF), | ||||
|         instance->common.serial, | ||||
|                       instance->common.btn | ||||
|                       ); | ||||
|         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,10 +1,16 @@ | ||||
| #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)); | ||||
| 
 | ||||
| @ -13,7 +19,7 @@ SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) { | ||||
|     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; | ||||
| @ -32,7 +38,9 @@ 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; | ||||
| @ -53,12 +61,16 @@ bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, Su | ||||
|     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); | ||||
|             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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -70,7 +82,7 @@ bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, Su | ||||
| } | ||||
| 
 | ||||
| void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) { | ||||
|     instance->common.parser_step = 0; | ||||
|     instance->common.parser_step = NeroSketchDecoderStepReset; | ||||
| } | ||||
| 
 | ||||
| /** Analysis of received data
 | ||||
| @ -90,102 +102,114 @@ void subghz_protocol_nero_sketch_reset(SubGhzProtocolNeroSketch* instance) { | ||||
| 
 | ||||
| // }
 | ||||
| 
 | ||||
| void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool level, uint32_t duration) { | ||||
| 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; | ||||
|     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: | ||||
|     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)) { | ||||
|             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){ | ||||
|             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){ | ||||
|             } 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; | ||||
|                     instance->common.parser_step = NeroSketchDecoderStepSaveDuration; | ||||
|                     instance->common.code_found = 0; | ||||
|                     instance->common.code_count_bit = 0; | ||||
|                 } else { | ||||
|                     instance->common.parser_step = 0; | ||||
|                     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: | ||||
|     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; | ||||
|             instance->common.parser_step = NeroSketchDecoderStepReset; | ||||
|         } | ||||
|         break; | ||||
|     case 3: | ||||
|     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)) { | ||||
|             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; | ||||
| 
 | ||||
|     string_cat_printf(output, | ||||
|     string_cat_printf( | ||||
|         output, | ||||
|         "%s %dbit\r\n" | ||||
|         "Key:0x%lX%08lX\r\n" | ||||
|         "Yek:0x%lX%08lX\r\n", | ||||
| @ -194,8 +218,7 @@ void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, stri | ||||
|         code_found_hi, | ||||
|         code_found_lo, | ||||
|         code_found_reverse_hi, | ||||
|                       code_found_reverse_lo | ||||
|                       ); | ||||
|         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); | ||||
| @ -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,7 +25,7 @@ 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; | ||||
| @ -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; | ||||
|     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)) { | ||||
|             //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); | ||||
|             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)) { | ||||
|     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: | ||||
|     case NiceFloDecoderStepFoundStartBit: | ||||
|         if(!level) { | ||||
|             break; | ||||
|         } 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: | ||||
|     case NiceFloDecoderStepSaveDuration: | ||||
|         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) { | ||||
|                      | ||||
|                 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: | ||||
|     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)) { | ||||
|             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,13 +8,19 @@ | ||||
| #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)); | ||||
| 
 | ||||
| @ -25,7 +31,7 @@ SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore | ||||
|     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; | ||||
| @ -70,7 +76,11 @@ 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) { | ||||
| 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++) { | ||||
| @ -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,7 +109,10 @@ 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) { | ||||
| 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; | ||||
| @ -111,7 +124,8 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|             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)){ | ||||
|                 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; | ||||
| @ -120,9 +134,11 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|             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); | ||||
|                 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)){  | ||||
|                 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; | ||||
| @ -131,7 +147,8 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|             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)){ | ||||
|                 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; | ||||
| @ -144,7 +161,8 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|                     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)){ | ||||
|                 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; | ||||
| @ -152,9 +170,11 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|                 //###########################
 | ||||
|                 // 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); | ||||
|                 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)){ | ||||
|                 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; | ||||
| @ -168,7 +188,8 @@ uint8_t subghz_protocol_star_line_check_remote_controller_selector(SubGhzProtoco | ||||
|                 } | ||||
|                 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)){ | ||||
|                 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; | ||||
| @ -188,7 +209,8 @@ 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; | ||||
| 
 | ||||
| @ -198,43 +220,50 @@ void subghz_protocol_star_line_check_remote_controller(SubGhzProtocolStarLine* i | ||||
|     instance->common.btn = key_fix >> 24; | ||||
| } | ||||
| 
 | ||||
| void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool level, uint32_t duration) { | ||||
| void subghz_protocol_star_line_parse( | ||||
|     SubGhzProtocolStarLine* instance, | ||||
|     bool level, | ||||
|     uint32_t duration) { | ||||
|     switch(instance->common.parser_step) { | ||||
|     case 0: | ||||
|     case StarLineDecoderStepReset: | ||||
|         if(level) { | ||||
|             if(DURATION_DIFF(duration,instance->common.te_long * 2)< instance->common.te_delta * 2) { | ||||
|                 instance->common.parser_step = 1; | ||||
|             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) { | ||||
|                 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; | ||||
|             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: | ||||
|     case StarLineDecoderStepSaveDuration: | ||||
|         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) { | ||||
|                 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; | ||||
|             instance->common.parser_step = StarLineDecoderStepReset; | ||||
|         } | ||||
|         break; | ||||
|     case 3: | ||||
|     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)) { | ||||
|             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,7 +307,8 @@ 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; | ||||
| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm