[FL-1913, FL-1963] SubGhz: save raw signal, add came atomo decoder (#783)
* File_Worker: getting the name of a new file with an index * SubGhz: add decoder RAW protocol * SubGhz: add view Save RAW * SubGhz: refactoring subghz custom event * SubGhz: fix syntax * SubGhz: fix error build * SubGhz: test build * SubGhz: refactoring subghz, add rename, delete, start and emulate RAW signal * SubGhz: fix triangle glitch in save raw view * SubGhz: fix receiver config scene * SubGhz: fix transfer after returning from save scene * Canvas: add font rotation * SubGhz: raw protocol encoder * SubGhz: fix error completion of transfer raw encoder * SubGhz: increased the speed of reading RAW data from a flash drive, displaying the name of the saved file in the Save RAW scene * Canvas: fix font rotation * SubGhz: fix navigation save RAW scene * SubGhz: add decode came atomo * Git: renormalize * Cleanup sources and enums * Gui: add font direction to canvas reset, canvas init sequence cleanup. * SubGhz: reorder menu. * Gui: correct canvas_set_font_direction signature Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									88cee4601a
								
							
						
					
					
						commit
						9d952ed855
					
				
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -1,2 +1 @@ | |||||||
| * text=auto | * text=auto | ||||||
| 
 |  | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								applications/gui/canvas.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										23
									
								
								applications/gui/canvas.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -11,17 +11,20 @@ Canvas* canvas_init() { | |||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_enter(); |     furi_hal_power_insomnia_enter(); | ||||||
| 
 | 
 | ||||||
|     canvas->orientation = CanvasOrientationHorizontal; |     // Setup u8g2
 | ||||||
|     u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); |     u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); | ||||||
| 
 |     canvas->orientation = CanvasOrientationHorizontal; | ||||||
|     // send init sequence to the display, display is in sleep mode after this
 |     // Initialize display
 | ||||||
|     u8g2_InitDisplay(&canvas->fb); |     u8g2_InitDisplay(&canvas->fb); | ||||||
|     // wake up display
 |     // Wake up display
 | ||||||
|     u8g2_ClearBuffer(&canvas->fb); |  | ||||||
|     u8g2_SetPowerSave(&canvas->fb, 0); |     u8g2_SetPowerSave(&canvas->fb, 0); | ||||||
|     u8g2_SendBuffer(&canvas->fb); | 
 | ||||||
|  |     // Clear buffer and send to device
 | ||||||
|  |     canvas_clear(canvas); | ||||||
|  |     canvas_commit(canvas); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_exit(); |     furi_hal_power_insomnia_exit(); | ||||||
|  | 
 | ||||||
|     return canvas; |     return canvas; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -32,9 +35,12 @@ void canvas_free(Canvas* canvas) { | |||||||
| 
 | 
 | ||||||
| void canvas_reset(Canvas* canvas) { | void canvas_reset(Canvas* canvas) { | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|  | 
 | ||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|  | 
 | ||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     canvas_set_font(canvas, FontSecondary); |     canvas_set_font(canvas, FontSecondary); | ||||||
|  |     canvas_set_font_direction(canvas, CanvasFontDirectionLeftToRight); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void canvas_commit(Canvas* canvas) { | void canvas_commit(Canvas* canvas) { | ||||||
| @ -96,6 +102,11 @@ void canvas_set_color(Canvas* canvas, Color color) { | |||||||
|     u8g2_SetDrawColor(&canvas->fb, color); |     u8g2_SetDrawColor(&canvas->fb, color); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void canvas_set_font_direction(Canvas* canvas, CanvasFontDirection dir) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     u8g2_SetFontDirection(&canvas->fb, dir); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void canvas_invert_color(Canvas* canvas) { | void canvas_invert_color(Canvas* canvas) { | ||||||
|     canvas->fb.draw_color = !canvas->fb.draw_color; |     canvas->fb.draw_color = !canvas->fb.draw_color; | ||||||
| } | } | ||||||
|  | |||||||
| @ -37,6 +37,14 @@ typedef enum { | |||||||
|     CanvasOrientationVertical, |     CanvasOrientationVertical, | ||||||
| } CanvasOrientation; | } CanvasOrientation; | ||||||
| 
 | 
 | ||||||
|  | /** Font Direction */ | ||||||
|  | typedef enum { | ||||||
|  |     CanvasFontDirectionLeftToRight, | ||||||
|  |     CanvasFontDirectionTopToDown, | ||||||
|  |     CanvasFontDirectionRightToLeft, | ||||||
|  |     CanvasFontDirectionDownToTop, | ||||||
|  | } CanvasFontDirection; | ||||||
|  | 
 | ||||||
| /** Canvas anonymouse structure */ | /** Canvas anonymouse structure */ | ||||||
| typedef struct Canvas Canvas; | typedef struct Canvas Canvas; | ||||||
| 
 | 
 | ||||||
| @ -77,6 +85,14 @@ void canvas_clear(Canvas* canvas); | |||||||
|  */ |  */ | ||||||
| void canvas_set_color(Canvas* canvas, Color color); | void canvas_set_color(Canvas* canvas, Color color); | ||||||
| 
 | 
 | ||||||
|  | /** Set font swap
 | ||||||
|  |  * Argument String Rotation Description | ||||||
|  |  * | ||||||
|  |  * @param      canvas  Canvas instance | ||||||
|  |  * @param      dir     Direction font | ||||||
|  |  */ | ||||||
|  | void canvas_set_font_direction(Canvas* canvas, CanvasFontDirection dir); | ||||||
|  | 
 | ||||||
| /** Invert drawing color
 | /** Invert drawing color
 | ||||||
|  * |  * | ||||||
|  * @param      canvas  Canvas instance |  * @param      canvas  Canvas instance | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								applications/subghz/helpers/subghz_custom_event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								applications/subghz/helpers/subghz_custom_event.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubghzCustomEventSceneDeleteSuccess = 100, | ||||||
|  |     SubghzCustomEventSceneDelete, | ||||||
|  |     SubghzCustomEventSceneReceiverInfoTxStart, | ||||||
|  |     SubghzCustomEventSceneReceiverInfoTxStop, | ||||||
|  |     SubghzCustomEventSceneReceiverInfoSave, | ||||||
|  |     SubghzCustomEventSceneSaveName, | ||||||
|  |     SubghzCustomEventSceneSaveSuccess, | ||||||
|  |     SubghzCustomEventSceneShowError, | ||||||
|  |     SubghzCustomEventSceneShowOnlyRX, | ||||||
|  | 
 | ||||||
|  |     SubghzCustomEventViewReceverOK, | ||||||
|  |     SubghzCustomEventViewReceverConfig, | ||||||
|  |     SubghzCustomEventViewReceverBack, | ||||||
|  | 
 | ||||||
|  |     SubghzCustomEventViewSaveRAWBack, | ||||||
|  |     SubghzCustomEventViewSaveRAWIDLE, | ||||||
|  |     SubghzCustomEventViewSaveRAWREC, | ||||||
|  |     SubghzCustomEventViewSaveRAWConfig, | ||||||
|  |     SubghzCustomEventViewSaveRAWMore, | ||||||
|  | 
 | ||||||
|  |     SubghzCustomEventViewTransmitterBack, | ||||||
|  |     SubghzCustomEventViewTransmitterSendStart, | ||||||
|  |     SubghzCustomEventViewTransmitterSendStop, | ||||||
|  |     SubghzCustomEventViewTransmitterError, | ||||||
|  | } SubghzCustomEvent; | ||||||
| @ -17,3 +17,4 @@ ADD_SCENE(subghz, test_carrier, TestCarrier) | |||||||
| ADD_SCENE(subghz, test_packet, TestPacket) | ADD_SCENE(subghz, test_packet, TestPacket) | ||||||
| ADD_SCENE(subghz, set_type, SetType) | ADD_SCENE(subghz, set_type, SetType) | ||||||
| ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) | ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) | ||||||
|  | ADD_SCENE(subghz, save_raw, SaveRAW) | ||||||
| @ -1,15 +1,11 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| typedef enum { |  | ||||||
|     SubGhzSceneDeleteInfoCustomEventDelete, |  | ||||||
| } SubGhzSceneDeleteInfoCustomEvent; |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* context) { | void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { |     if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { | ||||||
|         view_dispatcher_send_custom_event( |         view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneDelete); | ||||||
|             subghz->view_dispatcher, SubGhzSceneDeleteInfoCustomEventDelete); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -53,7 +49,7 @@ void subghz_scene_delete_on_enter(void* context) { | |||||||
| bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubGhzSceneDeleteInfoCustomEventDelete) { |         if(event.event == SubghzCustomEventSceneDelete) { | ||||||
|             memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name)); |             memcpy(subghz->file_name_tmp, subghz->file_name, strlen(subghz->file_name)); | ||||||
|             if(subghz_delete_file(subghz)) { |             if(subghz_delete_file(subghz)) { | ||||||
|                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| #define SCENE_DELETE_SUCCESS_CUSTOM_EVENT (0UL) |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_delete_success_popup_callback(void* context) { | void subghz_scene_delete_success_popup_callback(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_DELETE_SUCCESS_CUSTOM_EVENT); |     view_dispatcher_send_custom_event( | ||||||
|  |         subghz->view_dispatcher, SubghzCustomEventSceneDeleteSuccess); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_delete_success_on_enter(void* context) { | void subghz_scene_delete_success_on_enter(void* context) { | ||||||
| @ -25,7 +25,7 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event | |||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SCENE_DELETE_SUCCESS_CUSTOM_EVENT) { |         if(event.event == SubghzCustomEventSceneDeleteSuccess) { | ||||||
|             return scene_manager_search_and_switch_to_previous_scene( |             return scene_manager_search_and_switch_to_previous_scene( | ||||||
|                 subghz->scene_manager, SubGhzSceneStart); |                 subghz->scene_manager, SubGhzSceneStart); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include "../views/subghz_frequency_analyzer.h" | #include "../views/subghz_frequency_analyzer.h" | ||||||
| 
 | 
 | ||||||
| void subghz_scene_frequency_analyzer_callback(SubghzFrequencyAnalyzerEvent event, void* context) { | void subghz_scene_frequency_analyzer_callback(SubghzCustomEvent event, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); | ||||||
| @ -15,13 +15,7 @@ void subghz_scene_frequency_analyzer_on_enter(void* context) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     //SubGhz* subghz = context;
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |  | ||||||
|         if(event.event == SubghzFrequencyAnalyzerEventOnlyRx) { |  | ||||||
|             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -34,7 +34,7 @@ static void subghz_scene_receiver_update_statusbar(void* context) { | |||||||
|     string_clear(history_stat_str); |     string_clear(history_stat_str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_receiver_callback(SubghzReceverEvent event, void* context) { | void subghz_scene_receiver_callback(SubghzCustomEvent event, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); | ||||||
| @ -102,8 +102,9 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { | |||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         switch(event.event) { |         switch(event.event) { | ||||||
|         case SubghzReceverEventBack: |         case SubghzCustomEventViewReceverBack: | ||||||
|             // Stop CC1101 Rx
 |             // Stop CC1101 Rx
 | ||||||
|  |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { |             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { | ||||||
|                 subghz_rx_end(subghz); |                 subghz_rx_end(subghz); | ||||||
|                 subghz_sleep(subghz); |                 subghz_sleep(subghz); | ||||||
| @ -118,12 +119,12 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 subghz->scene_manager, SubGhzSceneStart); |                 subghz->scene_manager, SubGhzSceneStart); | ||||||
|             return true; |             return true; | ||||||
|             break; |             break; | ||||||
|         case SubghzReceverEventOK: |         case SubghzCustomEventViewReceverOK: | ||||||
|             subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); |             subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); | ||||||
|             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); | ||||||
|             return true; |             return true; | ||||||
|             break; |             break; | ||||||
|         case SubghzReceverEventConfig: |         case SubghzCustomEventViewReceverConfig: | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); |             subghz->txrx->idx_menu_chosen = subghz_receiver_get_idx_menu(subghz->subghz_receiver); | ||||||
|             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); | ||||||
|  | |||||||
| @ -66,6 +66,8 @@ static void subghz_scene_receiver_config_set_frequency(VariableItem* item) { | |||||||
|     if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { |     if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { | ||||||
|         variable_item_set_current_value_text(item, subghz_frequencies_text[index]); |         variable_item_set_current_value_text(item, subghz_frequencies_text[index]); | ||||||
|         subghz->txrx->frequency = subghz_frequencies[index]; |         subghz->txrx->frequency = subghz_frequencies[index]; | ||||||
|  |     } else { | ||||||
|  |         variable_item_set_current_value_index(item, subghz_frequencies_433_92); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -88,22 +90,24 @@ static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) | |||||||
|                 subghz->scene_manager, SubGhzSceneReceiverConfig), |                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||||
|             subghz_frequencies_text[subghz_frequencies_433_92]); |             subghz_frequencies_text[subghz_frequencies_433_92]); | ||||||
|         subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; |         subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||||
|  |         variable_item_set_current_value_index( | ||||||
|  |             (VariableItem*)scene_manager_get_scene_state( | ||||||
|  |                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||||
|  |             subghz_frequencies_433_92); | ||||||
|     } else { |     } else { | ||||||
|         variable_item_set_current_value_text( |         variable_item_set_current_value_text( | ||||||
|             (VariableItem*)scene_manager_get_scene_state( |             (VariableItem*)scene_manager_get_scene_state( | ||||||
|                 subghz->scene_manager, SubGhzSceneReceiverConfig), |                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||||
|             " -----"); |             " -----"); | ||||||
|  |         variable_item_set_current_value_index( | ||||||
|  |             (VariableItem*)scene_manager_get_scene_state( | ||||||
|  |                 subghz->scene_manager, SubGhzSceneReceiverConfig), | ||||||
|  |             subghz_frequencies_433_92); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     subghz->txrx->hopper_state = hopping_value[index]; |     subghz->txrx->hopper_state = hopping_value[index]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_receiver_config_callback(SubghzReceverEvent event, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     SubGhz* subghz = context; |  | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void subghz_scene_receiver_config_on_enter(void* context) { | void subghz_scene_receiver_config_on_enter(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     VariableItem* item; |     VariableItem* item; | ||||||
| @ -122,6 +126,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { | |||||||
|     variable_item_set_current_value_index(item, value_index); |     variable_item_set_current_value_index(item, value_index); | ||||||
|     variable_item_set_current_value_text(item, subghz_frequencies_text[value_index]); |     variable_item_set_current_value_text(item, subghz_frequencies_text[value_index]); | ||||||
| 
 | 
 | ||||||
|  |     if(!scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSaveRAW)) { | ||||||
|         item = variable_item_list_add( |         item = variable_item_list_add( | ||||||
|             subghz->variable_item_list, |             subghz->variable_item_list, | ||||||
|             "Hopping:", |             "Hopping:", | ||||||
| @ -132,6 +137,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { | |||||||
|             subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); |             subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); | ||||||
|         variable_item_set_current_value_index(item, value_index); |         variable_item_set_current_value_index(item, value_index); | ||||||
|         variable_item_set_current_value_text(item, hopping_text[value_index]); |         variable_item_set_current_value_text(item, hopping_text[value_index]); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     item = variable_item_list_add( |     item = variable_item_list_add( | ||||||
|         subghz->variable_item_list, |         subghz->variable_item_list, | ||||||
| @ -155,4 +161,5 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even | |||||||
| void subghz_scene_receiver_config_on_exit(void* context) { | void subghz_scene_receiver_config_on_exit(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     variable_item_list_clean(subghz->variable_item_list); |     variable_item_list_clean(subghz->variable_item_list); | ||||||
|  |     scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSaveRAW, 0); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,10 +1,5 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| typedef enum { |  | ||||||
|     SubGhzSceneReceiverInfoCustomEventTxStart, |  | ||||||
|     SubGhzSceneReceiverInfoCustomEventTxStop, |  | ||||||
|     SubGhzSceneReceiverInfoCustomEventSave, |  | ||||||
| } SubGhzSceneReceiverInfoCustomEvent; |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) { | void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
| @ -12,13 +7,13 @@ void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, v | |||||||
| 
 | 
 | ||||||
|     if((result == GuiButtonTypeCenter) && (type == InputTypePress)) { |     if((result == GuiButtonTypeCenter) && (type == InputTypePress)) { | ||||||
|         view_dispatcher_send_custom_event( |         view_dispatcher_send_custom_event( | ||||||
|             subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStart); |             subghz->view_dispatcher, SubghzCustomEventSceneReceiverInfoTxStart); | ||||||
|     } else if((result == GuiButtonTypeCenter) && (type == InputTypeRelease)) { |     } else if((result == GuiButtonTypeCenter) && (type == InputTypeRelease)) { | ||||||
|         view_dispatcher_send_custom_event( |         view_dispatcher_send_custom_event( | ||||||
|             subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventTxStop); |             subghz->view_dispatcher, SubghzCustomEventSceneReceiverInfoTxStop); | ||||||
|     } else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { |     } else if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { | ||||||
|         view_dispatcher_send_custom_event( |         view_dispatcher_send_custom_event( | ||||||
|             subghz->view_dispatcher, SubGhzSceneReceiverInfoCustomEventSave); |             subghz->view_dispatcher, SubghzCustomEventSceneReceiverInfoSave); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -101,7 +96,7 @@ void subghz_scene_receiver_info_on_enter(void* context) { | |||||||
| bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubGhzSceneReceiverInfoCustomEventTxStart) { |         if(event.event == SubghzCustomEventSceneReceiverInfoTxStart) { | ||||||
|             //CC1101 Stop RX -> Start TX
 |             //CC1101 Stop RX -> Start TX
 | ||||||
|             if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { |             if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { | ||||||
|                 subghz->txrx->hopper_state = SubGhzHopperStatePause; |                 subghz->txrx->hopper_state = SubGhzHopperStatePause; | ||||||
| @ -112,7 +107,8 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) | |||||||
|             if(!subghz_scene_receiver_info_update_parser(subghz)) { |             if(!subghz_scene_receiver_info_update_parser(subghz)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle) { |             if(subghz->txrx->txrx_state == SubGhzTxRxStateIdle || | ||||||
|  |                subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { | ||||||
|                 if(!subghz_tx_start(subghz)) { |                 if(!subghz_tx_start(subghz)) { | ||||||
|                     scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); |                     scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); | ||||||
|                 } else { |                 } else { | ||||||
| @ -120,7 +116,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } else if(event.event == SubGhzSceneReceiverInfoCustomEventTxStop) { |         } else if(event.event == SubghzCustomEventSceneReceiverInfoTxStop) { | ||||||
|             //CC1101 Stop Tx -> Start RX
 |             //CC1101 Stop Tx -> Start RX
 | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { |             if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { | ||||||
| @ -135,7 +131,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) | |||||||
|             } |             } | ||||||
|             subghz->state_notifications = NOTIFICATION_RX_STATE; |             subghz->state_notifications = NOTIFICATION_RX_STATE; | ||||||
|             return true; |             return true; | ||||||
|         } else if(event.event == SubGhzSceneReceiverInfoCustomEventSave) { |         } else if(event.event == SubghzCustomEventSceneReceiverInfoSave) { | ||||||
|             //CC1101 Stop RX -> Save
 |             //CC1101 Stop RX -> Save
 | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { |             if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { | ||||||
|  | |||||||
| @ -1,12 +1,11 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| #include <lib/toolbox/random_name.h> | #include <lib/toolbox/random_name.h> | ||||||
| #include "file-worker.h" | #include "file-worker.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| #define SCENE_SAVE_NAME_CUSTOM_EVENT (0UL) |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_save_name_text_input_callback(void* context) { | void subghz_scene_save_name_text_input_callback(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_SAVE_NAME_CUSTOM_EVENT); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneSaveName); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_save_name_on_enter(void* context) { | void subghz_scene_save_name_on_enter(void* context) { | ||||||
| @ -38,12 +37,14 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { | |||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SCENE_SAVE_NAME_CUSTOM_EVENT) { |         if(event.event == SubghzCustomEventSceneSaveName) { | ||||||
|             if(strcmp(subghz->file_name, "") && |             if(strcmp(subghz->file_name, "")) { | ||||||
|                subghz_save_protocol_to_file(subghz, subghz->file_name)) { |  | ||||||
|                 if(strcmp(subghz->file_name_tmp, "")) { |                 if(strcmp(subghz->file_name_tmp, "")) { | ||||||
|                     subghz_delete_file(subghz); |                     subghz_rename_file(subghz); | ||||||
|  |                 } else { | ||||||
|  |                     subghz_save_protocol_to_file(subghz, subghz->file_name); | ||||||
|                 } |                 } | ||||||
|  | 
 | ||||||
|                 subghz_file_name_clear(subghz); |                 subghz_file_name_clear(subghz); | ||||||
|                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); | ||||||
|                 return true; |                 return true; | ||||||
|  | |||||||
							
								
								
									
										169
									
								
								applications/subghz/scenes/subghz_scene_save_raw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								applications/subghz/scenes/subghz_scene_save_raw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | |||||||
|  | #include "../subghz_i.h" | ||||||
|  | #include "../views/subghz_save_raw.h" | ||||||
|  | #include <lib/subghz/protocols/subghz_protocol_raw.h> | ||||||
|  | #include <lib/subghz/subghz_parser.h> | ||||||
|  | 
 | ||||||
|  | static void subghz_scene_save_raw_update_statusbar(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     char frequency_str[20]; | ||||||
|  |     char preset_str[10]; | ||||||
|  | 
 | ||||||
|  |     snprintf( | ||||||
|  |         frequency_str, | ||||||
|  |         sizeof(frequency_str), | ||||||
|  |         "%03ld.%02ld", | ||||||
|  |         subghz->txrx->frequency / 1000000 % 1000, | ||||||
|  |         subghz->txrx->frequency / 10000 % 100); | ||||||
|  |     if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || | ||||||
|  |        subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { | ||||||
|  |         snprintf(preset_str, sizeof(preset_str), "AM"); | ||||||
|  |     } else if( | ||||||
|  |         subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || | ||||||
|  |         subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { | ||||||
|  |         snprintf(preset_str, sizeof(preset_str), "FM"); | ||||||
|  |     } else { | ||||||
|  |         furi_crash(NULL); | ||||||
|  |     } | ||||||
|  |     subghz_save_raw_add_data_statusbar(subghz->subghz_save_raw, frequency_str, preset_str); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_scene_save_raw_callback(SubghzCustomEvent event, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_scene_save_raw_on_enter(void* context) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     subghz_scene_save_raw_update_statusbar(subghz); | ||||||
|  |     subghz_save_raw_set_callback(subghz->subghz_save_raw, subghz_scene_save_raw_callback, subghz); | ||||||
|  | 
 | ||||||
|  |     subghz->txrx->protocol_result = subghz_parser_get_by_name(subghz->txrx->parser, "RAW"); | ||||||
|  |     furi_assert(subghz->txrx->protocol_result); | ||||||
|  | 
 | ||||||
|  |     subghz_worker_set_pair_callback( | ||||||
|  |         subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_parser_raw_parse); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewSaveRAW); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_scene_save_raw_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         switch(event.event) { | ||||||
|  |         case SubghzCustomEventViewSaveRAWBack: | ||||||
|  |             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { | ||||||
|  |                 subghz_rx_end(subghz); | ||||||
|  |                 subghz_sleep(subghz); | ||||||
|  |             }; | ||||||
|  |             subghz->txrx->frequency = subghz_frequencies[subghz_frequencies_433_92]; | ||||||
|  |             subghz->txrx->preset = FuriHalSubGhzPresetOok650Async; | ||||||
|  |             subghz_protocol_save_raw_to_file_stop( | ||||||
|  |                 (SubGhzProtocolRAW*)subghz->txrx->protocol_result); | ||||||
|  |             scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                 subghz->scene_manager, SubGhzSceneStart); | ||||||
|  |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|  |             return true; | ||||||
|  |             break; | ||||||
|  |         case SubghzCustomEventViewSaveRAWConfig: | ||||||
|  |             scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSaveRAW, 1); | ||||||
|  |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); | ||||||
|  |             return true; | ||||||
|  |             break; | ||||||
|  |         case SubghzCustomEventViewSaveRAWIDLE: | ||||||
|  |             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { | ||||||
|  |                 subghz_rx_end(subghz); | ||||||
|  |                 subghz_sleep(subghz); | ||||||
|  |             }; | ||||||
|  |             subghz_protocol_save_raw_to_file_stop( | ||||||
|  |                 (SubGhzProtocolRAW*)subghz->txrx->protocol_result); | ||||||
|  |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|  |             //send the name of the saved file to the account
 | ||||||
|  |             subghz_save_raw_set_file_name( | ||||||
|  |                 subghz->subghz_save_raw, | ||||||
|  |                 subghz_protocol_get_last_file_name( | ||||||
|  |                     (SubGhzProtocolRAW*)subghz->txrx->protocol_result)); | ||||||
|  |             return true; | ||||||
|  |             break; | ||||||
|  |         case SubghzCustomEventViewSaveRAWREC: | ||||||
|  |             if(subghz_protocol_save_raw_to_file_init( | ||||||
|  |                    (SubGhzProtocolRAW*)subghz->txrx->protocol_result, | ||||||
|  |                    "Raw", | ||||||
|  |                    subghz->txrx->frequency, | ||||||
|  |                    subghz->txrx->preset)) { | ||||||
|  |                 if((subghz->txrx->txrx_state == SubGhzTxRxStateIdle) || | ||||||
|  |                    (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { | ||||||
|  |                     subghz_begin(subghz, subghz->txrx->preset); | ||||||
|  |                     subghz_rx(subghz, subghz->txrx->frequency); | ||||||
|  |                 } | ||||||
|  |                 subghz->state_notifications = NOTIFICATION_RX_STATE; | ||||||
|  |             } else { | ||||||
|  |                 string_set(subghz->error_str, "No SD card"); | ||||||
|  |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |             break; | ||||||
|  |         case SubghzCustomEventViewSaveRAWMore: | ||||||
|  |             if(strcmp( | ||||||
|  |                    subghz_protocol_get_last_file_name( | ||||||
|  |                        (SubGhzProtocolRAW*)subghz->txrx->protocol_result), | ||||||
|  |                    "")) { | ||||||
|  |                 strlcpy( | ||||||
|  |                     subghz->file_name, | ||||||
|  |                     subghz_protocol_get_last_file_name( | ||||||
|  |                         (SubGhzProtocolRAW*)subghz->txrx->protocol_result), | ||||||
|  |                     strlen(subghz_protocol_get_last_file_name( | ||||||
|  |                         (SubGhzProtocolRAW*)subghz->txrx->protocol_result)) + | ||||||
|  |                         1); | ||||||
|  |                 //set the path to read the file
 | ||||||
|  |                 string_t temp_str; | ||||||
|  |                 string_init_printf( | ||||||
|  |                     temp_str, | ||||||
|  |                     "%s/%s%s", | ||||||
|  |                     SUBGHZ_APP_PATH_FOLDER, | ||||||
|  |                     subghz->file_name, | ||||||
|  |                     SUBGHZ_APP_EXTENSION); | ||||||
|  |                 subghz_protocol_set_last_file_name( | ||||||
|  |                     (SubGhzProtocolRAW*)subghz->txrx->protocol_result, string_get_cstr(temp_str)); | ||||||
|  |                 string_clear(temp_str); | ||||||
|  | 
 | ||||||
|  |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } else if(event.type == SceneManagerEventTypeTick) { | ||||||
|  |         switch(subghz->state_notifications) { | ||||||
|  |         case NOTIFICATION_RX_STATE: | ||||||
|  |             notification_message(subghz->notifications, &sequence_blink_blue_10); | ||||||
|  |             subghz_save_raw_update_sample_write( | ||||||
|  |                 subghz->subghz_save_raw, | ||||||
|  |                 subghz_save_protocol_raw_get_sample_write( | ||||||
|  |                     (SubGhzProtocolRAW*)subghz->txrx->protocol_result)); | ||||||
|  |             subghz_save_raw_add_data_rssi(subghz->subghz_save_raw, furi_hal_subghz_get_rssi()); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_scene_save_raw_on_exit(void* context) { | ||||||
|  |     SubGhz* subghz = context; | ||||||
|  | 
 | ||||||
|  |     //Stop CC1101
 | ||||||
|  |     if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { | ||||||
|  |         subghz_rx_end(subghz); | ||||||
|  |         subghz_sleep(subghz); | ||||||
|  |     }; | ||||||
|  |     subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|  | 
 | ||||||
|  |     //Сallback restoration
 | ||||||
|  |     subghz_worker_set_pair_callback( | ||||||
|  |         subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_parser_parse); | ||||||
|  | } | ||||||
| @ -1,10 +1,9 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| #define SCENE_SAVE_SUCCESS_CUSTOM_EVENT (0UL) |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_save_success_popup_callback(void* context) { | void subghz_scene_save_success_popup_callback(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_SAVE_SUCCESS_CUSTOM_EVENT); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneSaveSuccess); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_save_success_on_enter(void* context) { | void subghz_scene_save_success_on_enter(void* context) { | ||||||
| @ -24,7 +23,7 @@ void subghz_scene_save_success_on_enter(void* context) { | |||||||
| bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { |         if(event.event == SubghzCustomEventSceneSaveSuccess) { | ||||||
|             if(!scene_manager_search_and_switch_to_previous_scene( |             if(!scene_manager_search_and_switch_to_previous_scene( | ||||||
|                    subghz->scene_manager, SubGhzSceneReceiver)) { |                    subghz->scene_manager, SubGhzSceneReceiver)) { | ||||||
|                 scene_manager_search_and_switch_to_previous_scene( |                 scene_manager_search_and_switch_to_previous_scene( | ||||||
|  | |||||||
| @ -1,10 +1,9 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| #define SCENE_NO_MAN_CUSTOM_EVENT (11UL) |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_show_error_popup_callback(void* context) { | void subghz_scene_show_error_popup_callback(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneShowError); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_show_error_on_enter(void* context) { | void subghz_scene_show_error_on_enter(void* context) { | ||||||
| @ -24,7 +23,7 @@ void subghz_scene_show_error_on_enter(void* context) { | |||||||
| bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) { |         if(event.event == SubghzCustomEventSceneShowError) { | ||||||
|             scene_manager_search_and_switch_to_previous_scene( |             scene_manager_search_and_switch_to_previous_scene( | ||||||
|                 subghz->scene_manager, SubGhzSceneStart); |                 subghz->scene_manager, SubGhzSceneStart); | ||||||
|             return true; |             return true; | ||||||
|  | |||||||
| @ -1,10 +1,9 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| #define SCENE_NO_MAN_CUSTOM_EVENT (11UL) |  | ||||||
| 
 | 
 | ||||||
| void subghz_scene_show_only_rx_popup_callback(void* context) { | void subghz_scene_show_only_rx_popup_callback(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, SubghzCustomEventSceneShowOnlyRX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_show_only_rx_on_enter(void* context) { | void subghz_scene_show_only_rx_on_enter(void* context) { | ||||||
| @ -30,7 +29,7 @@ void subghz_scene_show_only_rx_on_enter(void* context) { | |||||||
| const bool subghz_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) { | const bool subghz_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) { |         if(event.event == SubghzCustomEventSceneShowOnlyRX) { | ||||||
|             scene_manager_previous_scene(subghz->scene_manager); |             scene_manager_previous_scene(subghz->scene_manager); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,11 +1,12 @@ | |||||||
| #include "../subghz_i.h" | #include "../subghz_i.h" | ||||||
| 
 | 
 | ||||||
| enum SubmenuIndex { | enum SubmenuIndex { | ||||||
|     SubmenuIndexRead, |     SubmenuIndexRead = 10, | ||||||
|     SubmenuIndexSaved, |     SubmenuIndexSaved, | ||||||
|     SubmenuIndexTest, |     SubmenuIndexTest, | ||||||
|     SubmenuIndexAddManualy, |     SubmenuIndexAddManualy, | ||||||
|     SubmenuIndexFrequencyAnalyzer, |     SubmenuIndexFrequencyAnalyzer, | ||||||
|  |     SubmenuIndexSaveRAW, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void subghz_scene_start_submenu_callback(void* context, uint32_t index) { | void subghz_scene_start_submenu_callback(void* context, uint32_t index) { | ||||||
| @ -20,6 +21,12 @@ void subghz_scene_start_on_enter(void* context) { | |||||||
|     } |     } | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); |         subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); | ||||||
|  |     submenu_add_item( | ||||||
|  |         subghz->submenu, | ||||||
|  |         "Read Raw", | ||||||
|  |         SubmenuIndexSaveRAW, | ||||||
|  |         subghz_scene_start_submenu_callback, | ||||||
|  |         subghz); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         subghz->submenu, "Saved", SubmenuIndexSaved, subghz_scene_start_submenu_callback, subghz); |         subghz->submenu, "Saved", SubmenuIndexSaved, subghz_scene_start_submenu_callback, subghz); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
| @ -47,7 +54,12 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { | |||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubmenuIndexRead) { |         if(event.event == SubmenuIndexSaveRAW) { | ||||||
|  |             scene_manager_set_scene_state( | ||||||
|  |                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexSaveRAW); | ||||||
|  |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveRAW); | ||||||
|  |             return true; | ||||||
|  |         } else if(event.event == SubmenuIndexRead) { | ||||||
|             scene_manager_set_scene_state( |             scene_manager_set_scene_state( | ||||||
|                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); |                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); | ||||||
|             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); | ||||||
|  | |||||||
| @ -2,13 +2,13 @@ | |||||||
| #include "../views/subghz_transmitter.h" | #include "../views/subghz_transmitter.h" | ||||||
| #include <lib/subghz/protocols/subghz_protocol_keeloq.h> | #include <lib/subghz/protocols/subghz_protocol_keeloq.h> | ||||||
| 
 | 
 | ||||||
| void subghz_scene_transmitter_callback(SubghzTransmitterEvent event, void* context) { | void subghz_scene_transmitter_callback(SubghzCustomEvent event, void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); |     view_dispatcher_send_custom_event(subghz->view_dispatcher, event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subghz_scene_transmitter_update_data_show(void* context) { | bool subghz_scene_transmitter_update_data_show(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
| 
 | 
 | ||||||
|     if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) { |     if(subghz->txrx->protocol_result && subghz->txrx->protocol_result->get_upload_protocol) { | ||||||
| @ -51,17 +51,22 @@ static void subghz_scene_transmitter_update_data_show(void* context) { | |||||||
|             preset_str, |             preset_str, | ||||||
|             show_button); |             show_button); | ||||||
|         string_clear(key_str); |         string_clear(key_str); | ||||||
|     } else { | 
 | ||||||
|         string_set(subghz->error_str, "Protocol not found"); |         return true; | ||||||
|         scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); |  | ||||||
|     } |     } | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_scene_transmitter_on_enter(void* context) { | void subghz_scene_transmitter_on_enter(void* context) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|  |     if(!subghz_scene_transmitter_update_data_show(subghz)) { | ||||||
|  |         view_dispatcher_send_custom_event( | ||||||
|  |             subghz->view_dispatcher, SubghzCustomEventViewTransmitterError); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     subghz_transmitter_set_callback( |     subghz_transmitter_set_callback( | ||||||
|         subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz); |         subghz->subghz_transmitter, subghz_scene_transmitter_callback, subghz); | ||||||
|     subghz_scene_transmitter_update_data_show(subghz); | 
 | ||||||
|     subghz->state_notifications = NOTIFICATION_IDLE_STATE; |     subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); |     view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); | ||||||
| } | } | ||||||
| @ -69,7 +74,7 @@ void subghz_scene_transmitter_on_enter(void* context) { | |||||||
| bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { | bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { | ||||||
|     SubGhz* subghz = context; |     SubGhz* subghz = context; | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubghzTransmitterEventSendStart) { |         if(event.event == SubghzCustomEventViewTransmitterSendStart) { | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { |             if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { | ||||||
|                 subghz_rx_end(subghz); |                 subghz_rx_end(subghz); | ||||||
| @ -84,18 +89,21 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } else if(event.event == SubghzTransmitterEventSendStop) { |         } else if(event.event == SubghzCustomEventViewTransmitterSendStop) { | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { |             if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { | ||||||
|                 subghz_tx_stop(subghz); |                 subghz_tx_stop(subghz); | ||||||
|                 subghz_sleep(subghz); |                 subghz_sleep(subghz); | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } else if(event.event == SubghzTransmitterEventBack) { |         } else if(event.event == SubghzCustomEventViewTransmitterBack) { | ||||||
|             subghz->state_notifications = NOTIFICATION_IDLE_STATE; |             subghz->state_notifications = NOTIFICATION_IDLE_STATE; | ||||||
|             scene_manager_search_and_switch_to_previous_scene( |             scene_manager_search_and_switch_to_previous_scene( | ||||||
|                 subghz->scene_manager, SubGhzSceneStart); |                 subghz->scene_manager, SubGhzSceneStart); | ||||||
|             return true; |             return true; | ||||||
|  |         } else if(event.event == SubghzCustomEventViewTransmitterError) { | ||||||
|  |             string_set(subghz->error_str, "Protocol not found"); | ||||||
|  |             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); | ||||||
|         } |         } | ||||||
|     } else if(event.type == SceneManagerEventTypeTick) { |     } else if(event.type == SceneManagerEventTypeTick) { | ||||||
|         if(subghz->state_notifications == NOTIFICATION_TX_STATE) { |         if(subghz->state_notifications == NOTIFICATION_TX_STATE) { | ||||||
|  | |||||||
| @ -140,6 +140,13 @@ SubGhz* subghz_alloc() { | |||||||
|         SubGhzViewFrequencyAnalyzer, |         SubGhzViewFrequencyAnalyzer, | ||||||
|         subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer)); |         subghz_frequency_analyzer_get_view(subghz->subghz_frequency_analyzer)); | ||||||
| 
 | 
 | ||||||
|  |     // Save RAW
 | ||||||
|  |     subghz->subghz_save_raw = subghz_save_raw_alloc(); | ||||||
|  |     view_dispatcher_add_view( | ||||||
|  |         subghz->view_dispatcher, | ||||||
|  |         SubGhzViewSaveRAW, | ||||||
|  |         subghz_save_raw_get_view(subghz->subghz_save_raw)); | ||||||
|  | 
 | ||||||
|     // Carrier Test Module
 |     // Carrier Test Module
 | ||||||
|     subghz->subghz_test_carrier = subghz_test_carrier_alloc(); |     subghz->subghz_test_carrier = subghz_test_carrier_alloc(); | ||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
| @ -181,6 +188,7 @@ SubGhz* subghz_alloc() { | |||||||
| 
 | 
 | ||||||
|     subghz_parser_load_keeloq_file(subghz->txrx->parser, "/ext/subghz/keeloq_mfcodes"); |     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_parser_load_nice_flor_s_file(subghz->txrx->parser, "/ext/subghz/nice_floor_s_rx"); | ||||||
|  |     subghz_parser_load_came_atomo_file(subghz->txrx->parser, "/ext/subghz/came_atomo"); | ||||||
| 
 | 
 | ||||||
|     //subghz_parser_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
 |     //subghz_parser_enable_dump_text(subghz->protocol, subghz_text_callback, subghz);
 | ||||||
| 
 | 
 | ||||||
| @ -226,6 +234,10 @@ void subghz_free(SubGhz* subghz) { | |||||||
|     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewFrequencyAnalyzer); |     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewFrequencyAnalyzer); | ||||||
|     subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer); |     subghz_frequency_analyzer_free(subghz->subghz_frequency_analyzer); | ||||||
| 
 | 
 | ||||||
|  |     // Save RAW
 | ||||||
|  |     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewSaveRAW); | ||||||
|  |     subghz_save_raw_free(subghz->subghz_save_raw); | ||||||
|  | 
 | ||||||
|     // Submenu
 |     // Submenu
 | ||||||
|     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu); |     view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu); | ||||||
|     submenu_free(subghz->submenu); |     submenu_free(subghz->submenu); | ||||||
|  | |||||||
| @ -191,7 +191,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         if(!subghz->txrx->protocol_result->to_load_protocol_from_file( |         if(!subghz->txrx->protocol_result->to_load_protocol_from_file( | ||||||
|                file_worker, subghz->txrx->protocol_result)) { |                file_worker, subghz->txrx->protocol_result, string_get_cstr(path))) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         loaded = true; |         loaded = true; | ||||||
| @ -334,8 +334,10 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { | |||||||
|         if(subghz->txrx->protocol_result == NULL) { |         if(subghz->txrx->protocol_result == NULL) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         if(!subghz->txrx->protocol_result->to_load_protocol_from_file( | 
 | ||||||
|                file_worker, subghz->txrx->protocol_result)) { |         if(subghz->txrx->protocol_result->to_load_protocol_from_file == NULL || | ||||||
|  |            !subghz->txrx->protocol_result->to_load_protocol_from_file( | ||||||
|  |                file_worker, subghz->txrx->protocol_result, string_get_cstr(protocol_file_name))) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         res = true; |         res = true; | ||||||
| @ -354,6 +356,28 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { | |||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool subghz_rename_file(SubGhz* subghz) { | ||||||
|  |     furi_assert(subghz); | ||||||
|  |     bool ret = false; | ||||||
|  |     string_t old_path; | ||||||
|  |     string_t new_path; | ||||||
|  | 
 | ||||||
|  |     FileWorker* file_worker = file_worker_alloc(false); | ||||||
|  | 
 | ||||||
|  |     string_init_printf( | ||||||
|  |         old_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); | ||||||
|  | 
 | ||||||
|  |     string_init_printf( | ||||||
|  |         new_path, "%s/%s%s", SUBGHZ_APP_PATH_FOLDER, subghz->file_name, SUBGHZ_APP_EXTENSION); | ||||||
|  | 
 | ||||||
|  |     ret = file_worker_rename(file_worker, string_get_cstr(old_path), string_get_cstr(new_path)); | ||||||
|  |     string_clear(old_path); | ||||||
|  |     string_clear(new_path); | ||||||
|  |     file_worker_close(file_worker); | ||||||
|  |     file_worker_free(file_worker); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool subghz_delete_file(SubGhz* subghz) { | bool subghz_delete_file(SubGhz* subghz) { | ||||||
|     furi_assert(subghz); |     furi_assert(subghz); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| #include "views/subghz_receiver.h" | #include "views/subghz_receiver.h" | ||||||
| #include "views/subghz_transmitter.h" | #include "views/subghz_transmitter.h" | ||||||
| #include "views/subghz_frequency_analyzer.h" | #include "views/subghz_frequency_analyzer.h" | ||||||
|  | #include "views/subghz_save_raw.h" | ||||||
| 
 | 
 | ||||||
| #include "views/subghz_test_static.h" | #include "views/subghz_test_static.h" | ||||||
| #include "views/subghz_test_carrier.h" | #include "views/subghz_test_carrier.h" | ||||||
| @ -64,6 +65,7 @@ struct SubGhzTxRx { | |||||||
|     SubGhzWorker* worker; |     SubGhzWorker* worker; | ||||||
|     SubGhzParser* parser; |     SubGhzParser* parser; | ||||||
|     SubGhzProtocolCommon* protocol_result; |     SubGhzProtocolCommon* protocol_result; | ||||||
|  |     //SubGhzProtocolCommon* protocol_save_raw;
 | ||||||
|     SubGhzProtocolCommonEncoder* encoder; |     SubGhzProtocolCommonEncoder* encoder; | ||||||
|     uint32_t frequency; |     uint32_t frequency; | ||||||
|     FuriHalSubGhzPreset preset; |     FuriHalSubGhzPreset preset; | ||||||
| @ -100,6 +102,7 @@ struct SubGhz { | |||||||
|     VariableItemList* variable_item_list; |     VariableItemList* variable_item_list; | ||||||
| 
 | 
 | ||||||
|     SubghzFrequencyAnalyzer* subghz_frequency_analyzer; |     SubghzFrequencyAnalyzer* subghz_frequency_analyzer; | ||||||
|  |     SubghzSaveRAW* subghz_save_raw; | ||||||
|     SubghzTestStatic* subghz_test_static; |     SubghzTestStatic* subghz_test_static; | ||||||
|     SubghzTestCarrier* subghz_test_carrier; |     SubghzTestCarrier* subghz_test_carrier; | ||||||
|     SubghzTestPacket* subghz_test_packet; |     SubghzTestPacket* subghz_test_packet; | ||||||
| @ -116,6 +119,7 @@ typedef enum { | |||||||
|     SubGhzViewTransmitter, |     SubGhzViewTransmitter, | ||||||
|     SubGhzViewVariableItemList, |     SubGhzViewVariableItemList, | ||||||
|     SubGhzViewFrequencyAnalyzer, |     SubGhzViewFrequencyAnalyzer, | ||||||
|  |     SubGhzViewSaveRAW, | ||||||
|     SubGhzViewStatic, |     SubGhzViewStatic, | ||||||
|     SubGhzViewTestCarrier, |     SubGhzViewTestCarrier, | ||||||
|     SubGhzViewTestPacket, |     SubGhzViewTestPacket, | ||||||
| @ -130,6 +134,7 @@ void subghz_tx_stop(SubGhz* subghz); | |||||||
| bool subghz_key_load(SubGhz* subghz, const char* file_path); | bool subghz_key_load(SubGhz* subghz, const char* file_path); | ||||||
| bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name); | bool subghz_save_protocol_to_file(SubGhz* subghz, const char* dev_name); | ||||||
| bool subghz_load_protocol_from_file(SubGhz* subghz); | bool subghz_load_protocol_from_file(SubGhz* subghz); | ||||||
|  | bool subghz_rename_file(SubGhz* subghz); | ||||||
| bool subghz_delete_file(SubGhz* subghz); | bool subghz_delete_file(SubGhz* subghz); | ||||||
| void subghz_file_name_clear(SubGhz* subghz); | void subghz_file_name_clear(SubGhz* subghz); | ||||||
| uint32_t subghz_random_serial(void); | uint32_t subghz_random_serial(void); | ||||||
|  | |||||||
| @ -1,14 +1,11 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| typedef enum { |  | ||||||
|     SubghzFrequencyAnalyzerEventOnlyRx, |  | ||||||
| } SubghzFrequencyAnalyzerEvent; |  | ||||||
| 
 | 
 | ||||||
| typedef struct SubghzFrequencyAnalyzer SubghzFrequencyAnalyzer; | typedef struct SubghzFrequencyAnalyzer SubghzFrequencyAnalyzer; | ||||||
| 
 | 
 | ||||||
| typedef void (*SubghzFrequencyAnalyzerCallback)(SubghzFrequencyAnalyzerEvent event, void* context); | typedef void (*SubghzFrequencyAnalyzerCallback)(SubghzCustomEvent event, void* context); | ||||||
| 
 | 
 | ||||||
| void subghz_frequency_analyzer_set_callback( | void subghz_frequency_analyzer_set_callback( | ||||||
|     SubghzFrequencyAnalyzer* subghz_frequency_analyzer, |     SubghzFrequencyAnalyzer* subghz_frequency_analyzer, | ||||||
|  | |||||||
| @ -181,7 +181,7 @@ bool subghz_receiver_input(InputEvent* event, void* context) { | |||||||
|     SubghzReceiver* subghz_receiver = context; |     SubghzReceiver* subghz_receiver = context; | ||||||
| 
 | 
 | ||||||
|     if(event->key == InputKeyBack && event->type == InputTypeShort) { |     if(event->key == InputKeyBack && event->type == InputTypeShort) { | ||||||
|         subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context); |         subghz_receiver->callback(SubghzCustomEventViewReceverBack, subghz_receiver->context); | ||||||
|     } else if( |     } else if( | ||||||
|         event->key == InputKeyUp && |         event->key == InputKeyUp && | ||||||
|         (event->type == InputTypeShort || event->type == InputTypeRepeat)) { |         (event->type == InputTypeShort || event->type == InputTypeRepeat)) { | ||||||
| @ -199,12 +199,13 @@ bool subghz_receiver_input(InputEvent* event, void* context) { | |||||||
|                 return true; |                 return true; | ||||||
|             }); |             }); | ||||||
|     } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { |     } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { | ||||||
|         subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); |         subghz_receiver->callback(SubghzCustomEventViewReceverConfig, subghz_receiver->context); | ||||||
|     } else if(event->key == InputKeyOk && event->type == InputTypeShort) { |     } else if(event->key == InputKeyOk && event->type == InputTypeShort) { | ||||||
|         with_view_model( |         with_view_model( | ||||||
|             subghz_receiver->view, (SubghzReceiverModel * model) { |             subghz_receiver->view, (SubghzReceiverModel * model) { | ||||||
|                 if(model->history_item != 0) { |                 if(model->history_item != 0) { | ||||||
|                     subghz_receiver->callback(SubghzReceverEventOK, subghz_receiver->context); |                     subghz_receiver->callback( | ||||||
|  |                         SubghzCustomEventViewReceverOK, subghz_receiver->context); | ||||||
|                 } |                 } | ||||||
|                 return false; |                 return false; | ||||||
|             }); |             }); | ||||||
|  | |||||||
| @ -1,16 +1,11 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| typedef enum { |  | ||||||
|     SubghzReceverEventOK, |  | ||||||
|     SubghzReceverEventConfig, |  | ||||||
|     SubghzReceverEventBack, |  | ||||||
| } SubghzReceverEvent; |  | ||||||
| 
 | 
 | ||||||
| typedef struct SubghzReceiver SubghzReceiver; | typedef struct SubghzReceiver SubghzReceiver; | ||||||
| 
 | 
 | ||||||
| typedef void (*SubghzReceiverCallback)(SubghzReceverEvent event, void* context); | typedef void (*SubghzReceiverCallback)(SubghzCustomEvent event, void* context); | ||||||
| 
 | 
 | ||||||
| void subghz_receiver_set_callback( | void subghz_receiver_set_callback( | ||||||
|     SubghzReceiver* subghz_receiver, |     SubghzReceiver* subghz_receiver, | ||||||
|  | |||||||
							
								
								
									
										313
									
								
								applications/subghz/views/subghz_save_raw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								applications/subghz/views/subghz_save_raw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,313 @@ | |||||||
|  | #include "subghz_save_raw.h" | ||||||
|  | #include "../subghz_i.h" | ||||||
|  | 
 | ||||||
|  | #include <math.h> | ||||||
|  | #include <furi.h> | ||||||
|  | #include <furi-hal.h> | ||||||
|  | #include <input/input.h> | ||||||
|  | #include <gui/elements.h> | ||||||
|  | #include <lib/subghz/protocols/subghz_protocol_princeton.h> | ||||||
|  | 
 | ||||||
|  | #include <assets_icons.h> | ||||||
|  | #define SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE 100 | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubghzSaveRAWStatusStart, | ||||||
|  |     SubghzSaveRAWStatusIDLE, | ||||||
|  |     SubghzSaveRAWStatusREC, | ||||||
|  |     SubghzSaveRAWStatusShowName, | ||||||
|  | } SubghzSaveRAWStatus; | ||||||
|  | 
 | ||||||
|  | struct SubghzSaveRAW { | ||||||
|  |     View* view; | ||||||
|  |     osTimerId timer; | ||||||
|  |     SubghzSaveRAWCallback callback; | ||||||
|  |     void* context; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     string_t frequency_str; | ||||||
|  |     string_t preset_str; | ||||||
|  |     string_t sample_write; | ||||||
|  |     string_t file_name; | ||||||
|  |     uint8_t* rssi_history; | ||||||
|  |     bool rssi_history_end; | ||||||
|  |     uint8_t ind_write; | ||||||
|  |     SubghzSaveRAWStatus satus; | ||||||
|  | } SubghzSaveRAWModel; | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_set_callback( | ||||||
|  |     SubghzSaveRAW* subghz_save_raw, | ||||||
|  |     SubghzSaveRAWCallback callback, | ||||||
|  |     void* context) { | ||||||
|  |     furi_assert(subghz_save_raw); | ||||||
|  |     furi_assert(callback); | ||||||
|  |     subghz_save_raw->callback = callback; | ||||||
|  |     subghz_save_raw->context = context; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_add_data_statusbar( | ||||||
|  |     SubghzSaveRAW* instance, | ||||||
|  |     const char* frequency_str, | ||||||
|  |     const char* preset_str) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             string_set(model->frequency_str, frequency_str); | ||||||
|  |             string_set(model->preset_str, preset_str); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_set_file_name(SubghzSaveRAW* instance, const char* file_name) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             string_set(model->file_name, file_name); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subghz_save_raw_timer_callback(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubghzSaveRAW* instance = context; | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             model->satus = SubghzSaveRAWStatusIDLE; | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_add_data_rssi(SubghzSaveRAW* instance, float rssi) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     uint8_t u_rssi = 0; | ||||||
|  | 
 | ||||||
|  |     if(rssi < -90) { | ||||||
|  |         u_rssi = 0; | ||||||
|  |     } else { | ||||||
|  |         u_rssi = (uint8_t)((rssi + 90) / 2.7); | ||||||
|  |     } | ||||||
|  |     //if(u_rssi > 34) u_rssi = 34;
 | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             model->rssi_history[model->ind_write++] = u_rssi; | ||||||
|  |             if(model->ind_write > SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE) { | ||||||
|  |                 model->rssi_history_end = true; | ||||||
|  |                 model->ind_write = 0; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_update_sample_write(SubghzSaveRAW* instance, size_t sample) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             string_printf(model->sample_write, "%d spl.", sample); | ||||||
|  |             return false; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_draw_rssi(Canvas* canvas, SubghzSaveRAWModel* model) { | ||||||
|  |     int ind = 0; | ||||||
|  |     int base = 0; | ||||||
|  |     if(model->rssi_history_end == false) { | ||||||
|  |         for(int i = model->ind_write; i >= 0; i--) { | ||||||
|  |             canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[i]); | ||||||
|  |         } | ||||||
|  |         if(model->ind_write > 3) { | ||||||
|  |             canvas_draw_line(canvas, model->ind_write, 47, model->ind_write, 13); | ||||||
|  |             canvas_draw_line(canvas, model->ind_write - 2, 12, model->ind_write + 2, 12); | ||||||
|  |             canvas_draw_line(canvas, model->ind_write - 1, 13, model->ind_write + 1, 13); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         base = SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE - model->ind_write; | ||||||
|  |         for(int i = SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE; i >= 0; i--) { | ||||||
|  |             ind = i - base; | ||||||
|  |             if(ind < 0) ind += SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE; | ||||||
|  |             canvas_draw_line(canvas, i, 47, i, 47 - model->rssi_history[ind]); | ||||||
|  |         } | ||||||
|  |         canvas_draw_line( | ||||||
|  |             canvas, SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE, 47, SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE, 13); | ||||||
|  |         canvas_draw_line( | ||||||
|  |             canvas, | ||||||
|  |             SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE - 2, | ||||||
|  |             12, | ||||||
|  |             SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE + 2, | ||||||
|  |             12); | ||||||
|  |         canvas_draw_line( | ||||||
|  |             canvas, | ||||||
|  |             SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE - 1, | ||||||
|  |             13, | ||||||
|  |             SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE + 1, | ||||||
|  |             13); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_draw(Canvas* canvas, SubghzSaveRAWModel* model) { | ||||||
|  |     canvas_set_color(canvas, ColorBlack); | ||||||
|  |     canvas_set_font(canvas, FontSecondary); | ||||||
|  |     if(model->satus != SubghzSaveRAWStatusShowName) { | ||||||
|  |         canvas_draw_str(canvas, 5, 8, string_get_cstr(model->frequency_str)); | ||||||
|  |         canvas_draw_str(canvas, 40, 8, string_get_cstr(model->preset_str)); | ||||||
|  |         canvas_draw_str_aligned( | ||||||
|  |             canvas, 126, 0, AlignRight, AlignTop, string_get_cstr(model->sample_write)); | ||||||
|  |     } else { | ||||||
|  |         canvas_draw_str_aligned( | ||||||
|  |             canvas, 61, 1, AlignRight, AlignTop, string_get_cstr(model->file_name)); | ||||||
|  |         canvas_draw_str(canvas, 65, 8, "Saved!"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     canvas_draw_line(canvas, 0, 14, 115, 14); | ||||||
|  |     subghz_save_raw_draw_rssi(canvas, model); | ||||||
|  |     canvas_draw_line(canvas, 0, 48, 115, 48); | ||||||
|  |     canvas_draw_line(canvas, 115, 14, 115, 48); | ||||||
|  | 
 | ||||||
|  |     if(model->satus == SubghzSaveRAWStatusIDLE) { | ||||||
|  |         elements_button_left(canvas, "Config"); | ||||||
|  |         elements_button_center(canvas, "REC"); | ||||||
|  |         elements_button_right(canvas, "More"); | ||||||
|  |     } else if(model->satus == SubghzSaveRAWStatusStart) { | ||||||
|  |         elements_button_left(canvas, "Config"); | ||||||
|  |         elements_button_center(canvas, "REC"); | ||||||
|  |     } else { | ||||||
|  |         elements_button_center(canvas, "Stop"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     canvas_set_font_direction(canvas, 3); | ||||||
|  |     canvas_draw_str(canvas, 126, 40, "RSSI"); | ||||||
|  |     canvas_set_font_direction(canvas, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_save_raw_input(InputEvent* event, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubghzSaveRAW* instance = context; | ||||||
|  | 
 | ||||||
|  |     if(event->key == InputKeyBack && event->type == InputTypeShort) { | ||||||
|  |         instance->callback(SubghzCustomEventViewSaveRAWBack, instance->context); | ||||||
|  |     } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { | ||||||
|  |         with_view_model( | ||||||
|  |             instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |                 if(model->satus == SubghzSaveRAWStatusIDLE || | ||||||
|  |                    model->satus == SubghzSaveRAWStatusStart) { | ||||||
|  |                     instance->callback(SubghzCustomEventViewSaveRAWConfig, instance->context); | ||||||
|  |                 } | ||||||
|  |                 return true; | ||||||
|  |             }); | ||||||
|  |     } else if(event->key == InputKeyRight && event->type == InputTypeShort) { | ||||||
|  |         with_view_model( | ||||||
|  |             instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |                 if(model->satus == SubghzSaveRAWStatusIDLE) { | ||||||
|  |                     instance->callback(SubghzCustomEventViewSaveRAWMore, instance->context); | ||||||
|  |                 } | ||||||
|  |                 return true; | ||||||
|  |             }); | ||||||
|  |     } else if(event->key == InputKeyOk && event->type == InputTypeShort) { | ||||||
|  |         with_view_model( | ||||||
|  |             instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |                 if(model->satus == SubghzSaveRAWStatusIDLE || | ||||||
|  |                    model->satus == SubghzSaveRAWStatusStart) { | ||||||
|  |                     instance->callback(SubghzCustomEventViewSaveRAWREC, instance->context); | ||||||
|  |                     model->satus = SubghzSaveRAWStatusREC; | ||||||
|  |                     model->ind_write = 0; | ||||||
|  |                     model->rssi_history_end = false; | ||||||
|  |                 } else { | ||||||
|  |                     instance->callback(SubghzCustomEventViewSaveRAWIDLE, instance->context); | ||||||
|  |                     model->satus = SubghzSaveRAWStatusShowName; | ||||||
|  |                     osTimerStart(instance->timer, 1024); | ||||||
|  |                 } | ||||||
|  |                 return true; | ||||||
|  |             }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(event->key == InputKeyBack) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_enter(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubghzSaveRAW* instance = context; | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             model->satus = SubghzSaveRAWStatusStart; | ||||||
|  |             model->rssi_history = furi_alloc(SUBGHZ_SAVE_RAW_RSSI_HISTORY_SIZE * sizeof(uint8_t)); | ||||||
|  |             model->rssi_history_end = false; | ||||||
|  |             model->ind_write = 0; | ||||||
|  |             string_set(model->sample_write, "0 spl."); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_exit(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubghzSaveRAW* instance = context; | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             if(model->satus != SubghzSaveRAWStatusIDLE && | ||||||
|  |                model->satus != SubghzSaveRAWStatusStart) { | ||||||
|  |                 instance->callback(SubghzCustomEventViewSaveRAWIDLE, instance->context); | ||||||
|  |                 model->satus = SubghzSaveRAWStatusStart; | ||||||
|  |             } | ||||||
|  |             string_clean(model->frequency_str); | ||||||
|  |             string_clean(model->preset_str); | ||||||
|  |             string_clean(model->sample_write); | ||||||
|  |             string_clean(model->file_name); | ||||||
|  |             free(model->rssi_history); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubghzSaveRAW* subghz_save_raw_alloc() { | ||||||
|  |     SubghzSaveRAW* instance = furi_alloc(sizeof(SubghzSaveRAW)); | ||||||
|  | 
 | ||||||
|  |     // View allocation and configuration
 | ||||||
|  |     instance->view = view_alloc(); | ||||||
|  |     view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzSaveRAWModel)); | ||||||
|  |     view_set_context(instance->view, instance); | ||||||
|  |     view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_save_raw_draw); | ||||||
|  |     view_set_input_callback(instance->view, subghz_save_raw_input); | ||||||
|  |     view_set_enter_callback(instance->view, subghz_save_raw_enter); | ||||||
|  |     view_set_exit_callback(instance->view, subghz_save_raw_exit); | ||||||
|  | 
 | ||||||
|  |     instance->timer = osTimerNew(subghz_save_raw_timer_callback, osTimerOnce, instance, NULL); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             string_init(model->frequency_str); | ||||||
|  |             string_init(model->preset_str); | ||||||
|  |             string_init(model->sample_write); | ||||||
|  |             string_init(model->file_name); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_free(SubghzSaveRAW* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     with_view_model( | ||||||
|  |         instance->view, (SubghzSaveRAWModel * model) { | ||||||
|  |             string_clear(model->frequency_str); | ||||||
|  |             string_clear(model->preset_str); | ||||||
|  |             string_clear(model->sample_write); | ||||||
|  |             string_clear(model->file_name); | ||||||
|  |             return true; | ||||||
|  |         }); | ||||||
|  |     osTimerDelete(instance->timer); | ||||||
|  |     view_free(instance->view); | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | View* subghz_save_raw_get_view(SubghzSaveRAW* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return instance->view; | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								applications/subghz/views/subghz_save_raw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								applications/subghz/views/subghz_save_raw.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <gui/view.h> | ||||||
|  | #include "../helpers/subghz_custom_event.h" | ||||||
|  | 
 | ||||||
|  | typedef struct SubghzSaveRAW SubghzSaveRAW; | ||||||
|  | 
 | ||||||
|  | typedef void (*SubghzSaveRAWCallback)(SubghzCustomEvent event, void* context); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_set_callback( | ||||||
|  |     SubghzSaveRAW* subghz_save_raw, | ||||||
|  |     SubghzSaveRAWCallback callback, | ||||||
|  |     void* context); | ||||||
|  | 
 | ||||||
|  | SubghzSaveRAW* subghz_save_raw_alloc(); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_free(SubghzSaveRAW* subghz_static); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_add_data_statusbar( | ||||||
|  |     SubghzSaveRAW* instance, | ||||||
|  |     const char* frequency_str, | ||||||
|  |     const char* preset_str); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_set_file_name(SubghzSaveRAW* instance, const char* file_name); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_update_sample_write(SubghzSaveRAW* instance, size_t sample); | ||||||
|  | 
 | ||||||
|  | void subghz_save_raw_add_data_rssi(SubghzSaveRAW* instance, float rssi); | ||||||
|  | 
 | ||||||
|  | View* subghz_save_raw_get_view(SubghzSaveRAW* subghz_static); | ||||||
| @ -111,10 +111,12 @@ bool subghz_transmitter_input(InputEvent* event, void* context) { | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|     if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { |     if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { | ||||||
|         subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context); |         subghz_transmitter->callback( | ||||||
|  |             SubghzCustomEventViewTransmitterSendStart, subghz_transmitter->context); | ||||||
|         return true; |         return true; | ||||||
|     } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) { |     } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) { | ||||||
|         subghz_transmitter->callback(SubghzTransmitterEventSendStop, subghz_transmitter->context); |         subghz_transmitter->callback( | ||||||
|  |             SubghzCustomEventViewTransmitterSendStop, subghz_transmitter->context); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,17 +1,11 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <gui/view.h> | #include <gui/view.h> | ||||||
| 
 | #include "../helpers/subghz_custom_event.h" | ||||||
| typedef enum { |  | ||||||
|     SubghzTransmitterEventSendStart, |  | ||||||
|     SubghzTransmitterEventSendStop, |  | ||||||
|     SubghzTransmitterEventBack, |  | ||||||
|     SubghzTransmitterEventNoMan, |  | ||||||
| } SubghzTransmitterEvent; |  | ||||||
| 
 | 
 | ||||||
| typedef struct SubghzTransmitter SubghzTransmitter; | typedef struct SubghzTransmitter SubghzTransmitter; | ||||||
| 
 | 
 | ||||||
| typedef void (*SubghzTransmitterCallback)(SubghzTransmitterEvent event, void* context); | typedef void (*SubghzTransmitterCallback)(SubghzCustomEvent event, void* context); | ||||||
| 
 | 
 | ||||||
| void subghz_transmitter_set_callback( | void subghz_transmitter_set_callback( | ||||||
|     SubghzTransmitter* subghz_transmitter, |     SubghzTransmitter* subghz_transmitter, | ||||||
|  | |||||||
| @ -658,6 +658,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { | |||||||
|         bool is_odd = samples % 2; |         bool is_odd = samples % 2; | ||||||
|         LevelDuration ld = |         LevelDuration ld = | ||||||
|             furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); |             furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); | ||||||
|  |         if(level_duration_is_wait(ld)) return; | ||||||
|         if(level_duration_is_reset(ld)) { |         if(level_duration_is_reset(ld)) { | ||||||
|             // One more even sample required to end at low level
 |             // One more even sample required to end at low level
 | ||||||
|             if(is_odd) { |             if(is_odd) { | ||||||
|  | |||||||
| @ -658,6 +658,7 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) { | |||||||
|         bool is_odd = samples % 2; |         bool is_odd = samples % 2; | ||||||
|         LevelDuration ld = |         LevelDuration ld = | ||||||
|             furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); |             furi_hal_subghz_async_tx.callback(furi_hal_subghz_async_tx.callback_context); | ||||||
|  |         if(level_duration_is_wait(ld)) return; | ||||||
|         if(level_duration_is_reset(ld)) { |         if(level_duration_is_reset(ld)) { | ||||||
|             // One more even sample required to end at low level
 |             // One more even sample required to end at low level
 | ||||||
|             if(is_odd) { |             if(is_odd) { | ||||||
|  | |||||||
| @ -79,6 +79,32 @@ bool file_worker_remove(FileWorker* file_worker, const char* filename) { | |||||||
|     return file_worker_check_common_errors(file_worker); |     return file_worker_check_common_errors(file_worker); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void file_worker_get_next_filename( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     const char* dirname, | ||||||
|  |     const char* filename, | ||||||
|  |     const char* fileextension, | ||||||
|  |     string_t nextfilename) { | ||||||
|  |     string_t temp_str; | ||||||
|  |     string_init(temp_str); | ||||||
|  |     uint16_t num = 0; | ||||||
|  | 
 | ||||||
|  |     string_printf(temp_str, "%s/%s%s", dirname, filename, fileextension); | ||||||
|  | 
 | ||||||
|  |     while(storage_common_stat(file_worker->api, string_get_cstr(temp_str), NULL) == FSE_OK) { | ||||||
|  |         num++; | ||||||
|  |         string_printf(temp_str, "%s/%s%d%s", dirname, filename, num, fileextension); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(num) { | ||||||
|  |         string_printf(nextfilename, "%s%d", filename, num); | ||||||
|  |     } else { | ||||||
|  |         string_printf(nextfilename, "%s", filename); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     string_clear(temp_str); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool file_worker_read(FileWorker* file_worker, void* buffer, uint16_t bytes_to_read) { | bool file_worker_read(FileWorker* file_worker, void* buffer, uint16_t bytes_to_read) { | ||||||
|     if(!file_worker_read_internal(file_worker, buffer, bytes_to_read)) { |     if(!file_worker_read_internal(file_worker, buffer, bytes_to_read)) { | ||||||
|         return false; |         return false; | ||||||
| @ -355,7 +381,11 @@ bool file_worker_read_until_buffered( | |||||||
|     return string_size(str_result) || *file_buf_cnt; |     return string_size(str_result) || *file_buf_cnt; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value) { | bool file_worker_get_value_from_key( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     string_t key, | ||||||
|  |     char delimiter, | ||||||
|  |     string_t value) { | ||||||
|     bool found = false; |     bool found = false; | ||||||
|     string_t next_line; |     string_t next_line; | ||||||
|     string_t next_key; |     string_t next_key; | ||||||
|  | |||||||
| @ -68,6 +68,22 @@ bool file_worker_mkdir(FileWorker* file_worker, const char* dirname); | |||||||
|  */ |  */ | ||||||
| bool file_worker_remove(FileWorker* file_worker, const char* filename); | bool file_worker_remove(FileWorker* file_worker, const char* filename); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * @brief Get next free filename. | ||||||
|  |  *  | ||||||
|  |  * @param file_worker FileWorker instance  | ||||||
|  |  * @param dirname  | ||||||
|  |  * @param filename  | ||||||
|  |  * @param fileextension  | ||||||
|  |  * @param nextfilename return name | ||||||
|  |  */ | ||||||
|  | void file_worker_get_next_filename( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     const char* dirname, | ||||||
|  |     const char* filename, | ||||||
|  |     const char* fileextension, | ||||||
|  |     string_t nextfilename); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Reads data from a file. |  * @brief Reads data from a file. | ||||||
|  *  |  *  | ||||||
| @ -194,7 +210,11 @@ bool file_worker_read_until_buffered( | |||||||
|  * @param value value for given key |  * @param value value for given key | ||||||
|  * @return true on success |  * @return true on success | ||||||
|  */ |  */ | ||||||
| bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value); | bool file_worker_get_value_from_key( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     string_t key, | ||||||
|  |     char delimiter, | ||||||
|  |     string_t value); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Check whether file exist or not |  * @brief Check whether file exist or not | ||||||
|  | |||||||
| @ -182,7 +182,8 @@ void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t out | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_came_to_load_protocol_from_file( | bool subghz_protocol_came_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolCame* instance) { |     SubGhzProtocolCame* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -56,11 +56,13 @@ void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t out | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolCame instance |  * @param instance - SubGhzProtocolCame instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_came_to_load_protocol_from_file( | bool subghz_protocol_came_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolCame* instance); |     SubGhzProtocolCame* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -2,9 +2,12 @@ | |||||||
| #include "subghz_protocol_common.h" | #include "subghz_protocol_common.h" | ||||||
| #include <lib/toolbox/manchester-decoder.h> | #include <lib/toolbox/manchester-decoder.h> | ||||||
| 
 | 
 | ||||||
|  | #define SUBGHZ_NO_CAME_ATOMO_RAINBOW_TABLE 0xFFFFFFFFFFFFFFFF | ||||||
|  | 
 | ||||||
| struct SubGhzProtocolCameAtomo { | struct SubGhzProtocolCameAtomo { | ||||||
|     SubGhzProtocolCommon common; |     SubGhzProtocolCommon common; | ||||||
|     ManchesterState manchester_saved_state; |     ManchesterState manchester_saved_state; | ||||||
|  |     const char* rainbow_table_file_name; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
| @ -39,11 +42,118 @@ void subghz_protocol_came_atomo_free(SubGhzProtocolCameAtomo* instance) { | |||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_protocol_came_atomo_name_file(SubGhzProtocolCameAtomo* instance, const char* name) { | ||||||
|  |     instance->rainbow_table_file_name = name; | ||||||
|  |     printf("Loading CAME Atomo rainbow table %s\r\n", name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Read bytes from rainbow table
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzProtocolCameAtomo* instance | ||||||
|  |  * @param number_atomo_magic_xor | ||||||
|  |  * @return atomo_magic_xor | ||||||
|  |  */ | ||||||
|  | uint64_t subghz_came_atomo_get_atomo_magic_xor_in_file( | ||||||
|  |     SubGhzProtocolCameAtomo* instance, | ||||||
|  |     uint8_t number_atomo_magic_xor) { | ||||||
|  |     if(!strcmp(instance->rainbow_table_file_name, "")) return SUBGHZ_NO_CAME_ATOMO_RAINBOW_TABLE; | ||||||
|  | 
 | ||||||
|  |     uint8_t buffer[sizeof(uint64_t)] = {0}; | ||||||
|  |     uint32_t address = number_atomo_magic_xor * sizeof(uint64_t); | ||||||
|  |     uint64_t atomo_magic_xor = 0; | ||||||
|  | 
 | ||||||
|  |     FileWorker* file_worker = file_worker_alloc(true); | ||||||
|  |     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, sizeof(uint64_t)); | ||||||
|  |         for(size_t i = 0; i < sizeof(uint64_t); i++) { | ||||||
|  |             atomo_magic_xor = (atomo_magic_xor << 8) | buffer[i]; | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         atomo_magic_xor = SUBGHZ_NO_CAME_ATOMO_RAINBOW_TABLE; | ||||||
|  |     } | ||||||
|  |     file_worker_close(file_worker); | ||||||
|  |     file_worker_free(file_worker); | ||||||
|  | 
 | ||||||
|  |     return atomo_magic_xor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** Analysis of received data
 | /** Analysis of received data
 | ||||||
|  *  |  *  | ||||||
|  * @param instance SubGhzProtocolCameAtomo instance |  * @param instance SubGhzProtocolCameAtomo instance | ||||||
|  */ |  */ | ||||||
| void subghz_protocol_came_atomo_remote_controller(SubGhzProtocolCameAtomo* instance) { | void subghz_protocol_came_atomo_remote_controller(SubGhzProtocolCameAtomo* instance) { | ||||||
|  |     /* 
 | ||||||
|  |     * 0x1fafef3ed0f7d9ef | ||||||
|  |     * 0x185fcc1531ee86e7 | ||||||
|  |     * 0x184fa96912c567ff | ||||||
|  |     * 0x187f8a42f3dc38f7 | ||||||
|  |     * 0x186f63915492a5cd | ||||||
|  |     * 0x181f40bab58bfac5 | ||||||
|  |     * 0x180f25c696a01bdd | ||||||
|  |     * 0x183f06ed77b944d5 | ||||||
|  |     * 0x182ef661d83d21a9 | ||||||
|  |     * 0x18ded54a39247ea1 | ||||||
|  |     * 0x18ceb0361a0f9fb9 | ||||||
|  |     * 0x18fe931dfb16c0b1 | ||||||
|  |     * 0x18ee7ace5c585d8b | ||||||
|  |     * ........  | ||||||
|  |     * transmission consists of 99 parcels with increasing counter while holding down the button | ||||||
|  |     * with each new press, the counter in the encrypted part increases | ||||||
|  |     *  | ||||||
|  |     * 0x1FAFF13ED0F7D9EF | ||||||
|  |     * 0x1FAFF11ED0F7D9EF | ||||||
|  |     * 0x1FAFF10ED0F7D9EF | ||||||
|  |     * 0x1FAFF0FED0F7D9EF | ||||||
|  |     * 0x1FAFF0EED0F7D9EF | ||||||
|  |     * 0x1FAFF0DED0F7D9EF | ||||||
|  |     * 0x1FAFF0CED0F7D9EF | ||||||
|  |     * 0x1FAFF0BED0F7D9EF | ||||||
|  |     * 0x1FAFF0AED0F7D9EF  | ||||||
|  |     *  | ||||||
|  |     *                   where     0x1FAF - parcel counter, 0хF0A - button press counter, | ||||||
|  |     *                           0xED0F7D9E - serial number, 0хF -  key | ||||||
|  |     * 0x1FAF parcel counter - 1 in the parcel queue ^ 0x185F =  0x07F0 | ||||||
|  |     * 0x185f ^ 0x185F = 0x0000 | ||||||
|  |     * 0x184f ^ 0x185F = 0x0010 | ||||||
|  |     * 0x187f ^ 0x185F = 0x0020 | ||||||
|  |     * ..... | ||||||
|  |     * 0x182e ^ 0x185F = 0x0071  | ||||||
|  |     * 0x18de ^ 0x185F = 0x0081 | ||||||
|  |     * ..... | ||||||
|  |     * 0x1e43 ^ 0x185F = 0x061C | ||||||
|  |     *                           where the last nibble is incremented every 8 samples | ||||||
|  |     *  | ||||||
|  |     * Decode | ||||||
|  |     *  | ||||||
|  |     * 0x1cf6931dfb16c0b1 => 0x1cf6 | ||||||
|  |     * 0x1cf6 ^ 0x185F = 0x04A9 | ||||||
|  |     * 0x04A9 => 0x04A = 74 (dec) | ||||||
|  |     * 74+1 % 32(atomo_magic_xor) = 11 | ||||||
|  |     * GET atomo_magic_xor[11] = 0xXXXXXXXXXXXXXXXX | ||||||
|  |     * 0x931dfb16c0b1 ^ 0xXXXXXXXXXXXXXXXX =  0xEF3ED0F7D9EF | ||||||
|  |     * 0xEF3 ED0F7D9E F  => 0xEF3 - CNT, 0xED0F7D9E - SN, 0xF - key | ||||||
|  |     *  | ||||||
|  |     * */ | ||||||
|  | 
 | ||||||
|  |     uint16_t parcel_counter = instance->common.code_last_found >> 48; | ||||||
|  |     parcel_counter = parcel_counter ^ 0x185F; | ||||||
|  |     parcel_counter >>= 4; | ||||||
|  |     uint8_t ind = (parcel_counter + 1) % 32; | ||||||
|  |     uint64_t temp_data = instance->common.code_last_found & 0x0000FFFFFFFFFFFF; | ||||||
|  |     uint64_t atomo_magic_xor = subghz_came_atomo_get_atomo_magic_xor_in_file(instance, ind); | ||||||
|  | 
 | ||||||
|  |     if(atomo_magic_xor != SUBGHZ_NO_CAME_ATOMO_RAINBOW_TABLE) { | ||||||
|  |         temp_data = temp_data ^ atomo_magic_xor; | ||||||
|  |         instance->common.cnt = temp_data >> 36; | ||||||
|  |         instance->common.serial = (temp_data >> 4) & 0x000FFFFFFFF; | ||||||
|  |         instance->common.btn = temp_data & 0xF; | ||||||
|  |     } else { | ||||||
|  |         instance->common.cnt = 0; | ||||||
|  |         instance->common.serial = 0; | ||||||
|  |         instance->common.btn = 0; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_came_atomo_reset(SubGhzProtocolCameAtomo* instance) { | void subghz_protocol_came_atomo_reset(SubGhzProtocolCameAtomo* instance) { | ||||||
| @ -89,26 +199,10 @@ void subghz_protocol_came_atomo_parse( | |||||||
|             } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) { |             } else if(DURATION_DIFF(duration, instance->common.te_long) < instance->common.te_delta) { | ||||||
|                 event = ManchesterEventLongLow; |                 event = ManchesterEventLongLow; | ||||||
|             } else if(duration >= (instance->common.te_long * 2 + instance->common.te_delta)) { |             } else if(duration >= (instance->common.te_long * 2 + instance->common.te_delta)) { | ||||||
|                 if(instance->common.code_count_bit >= |                 if(instance->common.code_count_bit == | ||||||
|                    instance->common.code_min_count_bit_for_found) { |                    instance->common.code_min_count_bit_for_found) { | ||||||
|                     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; |                     instance->common.code_last_count_bit = instance->common.code_count_bit; | ||||||
|                     // 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);
 |  | ||||||
| 
 |  | ||||||
|                     // uint32_t code_found_reverse_hi = code_found_reverse >> 32;
 |  | ||||||
|                     // uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff;
 |  | ||||||
|                     // FURI_LOG_I(
 |  | ||||||
|                     //     "ATOMO",
 |  | ||||||
|                     //     "%08lX%08lX  %08lX%08lX  %d",
 |  | ||||||
|                     //     code_found_hi,
 |  | ||||||
|                     //     code_found_lo,
 |  | ||||||
|                     //     code_found_reverse_hi,
 |  | ||||||
|                     //     code_found_reverse_lo,
 |  | ||||||
|                     //     instance->common.code_last_count_bit);
 |  | ||||||
|                     if(instance->common.callback) |                     if(instance->common.callback) | ||||||
|                         instance->common.callback( |                         instance->common.callback( | ||||||
|                             (SubGhzProtocolCommon*)instance, instance->common.context); |                             (SubGhzProtocolCommon*)instance, instance->common.context); | ||||||
| @ -151,17 +245,24 @@ void subghz_protocol_came_atomo_parse( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| void subghz_protocol_came_atomo_to_str(SubGhzProtocolCameAtomo* instance, string_t output) { | void subghz_protocol_came_atomo_to_str(SubGhzProtocolCameAtomo* instance, string_t output) { | ||||||
|  |     subghz_protocol_came_atomo_remote_controller(instance); | ||||||
|     uint32_t code_found_hi = instance->common.code_last_found >> 32; |     uint32_t code_found_hi = instance->common.code_last_found >> 32; | ||||||
|     uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; |     uint32_t code_found_lo = instance->common.code_last_found & 0x00000000ffffffff; | ||||||
| 
 | 
 | ||||||
|     string_cat_printf( |     string_cat_printf( | ||||||
|         output, |         output, | ||||||
|         "%s %dbit\r\n" |         "%s %db\r\n" | ||||||
|         "Key:0x%lX%08lX\r\n", |         "Key:0x%lX%08lX\r\n" | ||||||
|  |         "Sn:0x%08lX  Btn:0x%01X\r\n" | ||||||
|  |         "Cnt:0x%03X\r\n", | ||||||
|  | 
 | ||||||
|         instance->common.name, |         instance->common.name, | ||||||
|         instance->common.code_last_count_bit, |         instance->common.code_last_count_bit, | ||||||
|         code_found_hi, |         code_found_hi, | ||||||
|         code_found_lo); |         code_found_lo, | ||||||
|  |         instance->common.serial, | ||||||
|  |         instance->common.btn, | ||||||
|  |         instance->common.cnt); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // void subghz_protocol_came_atomo_to_save_str(SubGhzProtocolCameAtomo* instance, string_t output) {
 | // void subghz_protocol_came_atomo_to_save_str(SubGhzProtocolCameAtomo* instance, string_t output) {
 | ||||||
| @ -178,7 +279,8 @@ void subghz_protocol_came_atomo_to_str(SubGhzProtocolCameAtomo* instance, string | |||||||
| 
 | 
 | ||||||
| // bool subghz_protocol_came_atomo_to_load_protocol_from_file(
 | // bool subghz_protocol_came_atomo_to_load_protocol_from_file(
 | ||||||
| //     FileWorker* file_worker,
 | //     FileWorker* file_worker,
 | ||||||
| //     SubGhzProtocolCameAtomo* instance) {
 | //     SubGhzProtocolCameAtomo* instance,
 | ||||||
|  | //     const char* file_path) {
 | ||||||
| //     bool loaded = false;
 | //     bool loaded = false;
 | ||||||
| //     string_t temp_str;
 | //     string_t temp_str;
 | ||||||
| //     string_init(temp_str);
 | //     string_init(temp_str);
 | ||||||
|  | |||||||
| @ -16,6 +16,13 @@ SubGhzProtocolCameAtomo* subghz_protocol_came_atomo_alloc(); | |||||||
|  */ |  */ | ||||||
| void subghz_protocol_came_atomo_free(SubGhzProtocolCameAtomo* instance); | void subghz_protocol_came_atomo_free(SubGhzProtocolCameAtomo* instance); | ||||||
| 
 | 
 | ||||||
|  | /** File name rainbow table CAME Atomo
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzProtocolCameAtomo instance | ||||||
|  |  * @param file_name - "path/file_name" | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_came_atomo_name_file(SubGhzProtocolCameAtomo* instance, const char* name); | ||||||
|  | 
 | ||||||
| // /** Get upload protocol
 | // /** Get upload protocol
 | ||||||
| //  *
 | //  *
 | ||||||
| //  * @param instance - SubGhzProtocolCameAtomo instance
 | //  * @param instance - SubGhzProtocolCameAtomo instance
 | ||||||
| @ -59,11 +66,13 @@ void subghz_protocol_came_atomo_to_str(SubGhzProtocolCameAtomo* instance, string | |||||||
| //  *
 | //  *
 | ||||||
| //  * @param file_worker - FileWorker file_worker
 | //  * @param file_worker - FileWorker file_worker
 | ||||||
| //  * @param instance - SubGhzProtocolCameAtomo instance
 | //  * @param instance - SubGhzProtocolCameAtomo instance
 | ||||||
|  | //  * @param file_path - file path
 | ||||||
| //  * @return bool
 | //  * @return bool
 | ||||||
| //  */
 | //  */
 | ||||||
| // bool subghz_protocol_came_atomo_to_load_protocol_from_file(
 | // bool subghz_protocol_came_atomo_to_load_protocol_from_file(
 | ||||||
| //     FileWorker* file_worker,
 | //     FileWorker* file_worker,
 | ||||||
| //     SubGhzProtocolCameAtomo* instance);
 | //     SubGhzProtocolCameAtomo* instance,
 | ||||||
|  | //     const char* file_path);
 | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -341,7 +341,8 @@ void subghz_protocol_came_twee_to_save_str(SubGhzProtocolCameTwee* instance, str | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_came_twee_to_load_protocol_from_file( | bool subghz_protocol_came_twee_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolCameTwee* instance) { |     SubGhzProtocolCameTwee* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -59,11 +59,13 @@ void subghz_protocol_came_twee_to_save_str(SubGhzProtocolCameTwee* instance, str | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolCameTwee instance |  * @param instance - SubGhzProtocolCameTwee instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_came_twee_to_load_protocol_from_file( | bool subghz_protocol_came_twee_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolCameTwee* instance); |     SubGhzProtocolCameTwee* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <lib/toolbox/hex.h> | #include <lib/toolbox/hex.h> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() { | SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() { | ||||||
|     SubGhzProtocolCommonEncoder* instance = furi_alloc(sizeof(SubGhzProtocolCommonEncoder)); |     SubGhzProtocolCommonEncoder* instance = furi_alloc(sizeof(SubGhzProtocolCommonEncoder)); | ||||||
|     instance->upload = furi_alloc(SUBGHZ_ENCODER_UPLOAD_MAX_SIZE * sizeof(LevelDuration)); |     instance->upload = furi_alloc(SUBGHZ_ENCODER_UPLOAD_MAX_SIZE * sizeof(LevelDuration)); | ||||||
| @ -13,6 +12,9 @@ SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() { | |||||||
| 
 | 
 | ||||||
| void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance) { | void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|  |     if(instance->callback_end) { | ||||||
|  |         instance->callback_end((SubGhzProtocolCommon*)instance->context_end); | ||||||
|  |     } | ||||||
|     free(instance->upload); |     free(instance->upload); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| @ -22,9 +24,33 @@ size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instan | |||||||
|     return instance->repeat; |     return instance->repeat; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_protocol_encoder_common_set_callback( | ||||||
|  |     SubGhzProtocolCommonEncoder* instance, | ||||||
|  |     SubGhzProtocolCommonEncoderCallback callback, | ||||||
|  |     void* context) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(callback); | ||||||
|  |     instance->callback = callback; | ||||||
|  |     instance->context = context; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_common_set_callback_end( | ||||||
|  |     SubGhzProtocolCommonEncoder* instance, | ||||||
|  |     SubGhzProtocolCommonEncoderCallbackEnd callback_end, | ||||||
|  |     void* context_end) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(callback_end); | ||||||
|  |     instance->callback_end = callback_end; | ||||||
|  |     instance->context_end = context_end; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| LevelDuration subghz_protocol_encoder_common_yield(void* context) { | LevelDuration subghz_protocol_encoder_common_yield(void* context) { | ||||||
|     SubGhzProtocolCommonEncoder* instance = context; |     SubGhzProtocolCommonEncoder* instance = context; | ||||||
| 
 | 
 | ||||||
|  |     if(instance->callback) { | ||||||
|  |         return instance->callback((SubGhzProtocolCommon*)instance->context); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if(instance->repeat == 0) { |     if(instance->repeat == 0) { | ||||||
|         return level_duration_reset(); |         return level_duration_reset(); | ||||||
|     } |     } | ||||||
| @ -44,8 +70,12 @@ void subghz_protocol_common_add_bit(SubGhzProtocolCommon *common, uint8_t bit){ | |||||||
|     common->code_count_bit++; |     common->code_count_bit++; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_protocol_common_check_interval(SubGhzProtocolCommon *common, uint32_t duration, uint16_t duration_check) { | bool subghz_protocol_common_check_interval( | ||||||
|     if ((duration_check >= (duration - common->te_delta))&&(duration_check <= (duration + common->te_delta))){ |     SubGhzProtocolCommon* common, | ||||||
|  |     uint32_t duration, | ||||||
|  |     uint16_t duration_check) { | ||||||
|  |     if((duration_check >= (duration - common->te_delta)) && | ||||||
|  |        (duration_check <= (duration + common->te_delta))) { | ||||||
|         return true; |         return true; | ||||||
|     } else { |     } else { | ||||||
|         return false; |         return false; | ||||||
| @ -60,12 +90,14 @@ uint64_t subghz_protocol_common_reverse_key(uint64_t key, uint8_t count_bit){ | |||||||
|     return key_reverse; |     return key_reverse; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_common_set_callback(SubGhzProtocolCommon* common, SubGhzProtocolCommonCallback callback, void* context) { | void subghz_protocol_common_set_callback( | ||||||
|  |     SubGhzProtocolCommon* common, | ||||||
|  |     SubGhzProtocolCommonCallback callback, | ||||||
|  |     void* context) { | ||||||
|     common->callback = callback; |     common->callback = callback; | ||||||
|     common->context = context; |     common->context = context; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) { | void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output) { | ||||||
|     if(instance->to_string) { |     if(instance->to_string) { | ||||||
|         instance->to_string(instance, output); |         instance->to_string(instance, output); | ||||||
| @ -73,7 +105,8 @@ void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t outp | |||||||
|         uint32_t code_found_hi = instance->code_found >> 32; |         uint32_t code_found_hi = instance->code_found >> 32; | ||||||
|         uint32_t code_found_lo = instance->code_found & 0x00000000ffffffff; |         uint32_t code_found_lo = instance->code_found & 0x00000000ffffffff; | ||||||
| 
 | 
 | ||||||
|         uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->code_found, instance->code_count_bit); |         uint64_t code_found_reverse = | ||||||
|  |             subghz_protocol_common_reverse_key(instance->code_found, instance->code_count_bit); | ||||||
| 
 | 
 | ||||||
|         uint32_t code_found_reverse_hi = code_found_reverse >> 32; |         uint32_t code_found_reverse_hi = code_found_reverse >> 32; | ||||||
|         uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; |         uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; | ||||||
| @ -92,8 +125,7 @@ void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t outp | |||||||
|                 code_found_reverse_hi, |                 code_found_reverse_hi, | ||||||
|                 code_found_reverse_lo, |                 code_found_reverse_lo, | ||||||
|                 instance->serial, |                 instance->serial, | ||||||
|                 instance->btn |                 instance->btn); | ||||||
|             ); |  | ||||||
|         } else { |         } else { | ||||||
|             string_cat_printf( |             string_cat_printf( | ||||||
|                 output, |                 output, | ||||||
| @ -108,8 +140,7 @@ void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t outp | |||||||
|                 code_found_reverse_hi, |                 code_found_reverse_hi, | ||||||
|                 code_found_reverse_lo, |                 code_found_reverse_lo, | ||||||
|                 instance->serial, |                 instance->serial, | ||||||
|                 instance->btn |                 instance->btn); | ||||||
|             ); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -16,6 +16,8 @@ | |||||||
| 
 | 
 | ||||||
| #define SUBGHZ_APP_FOLDER "/any/subghz" | #define SUBGHZ_APP_FOLDER "/any/subghz" | ||||||
| #define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved" | #define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved" | ||||||
|  | #define SUBGHZ_RAW_FOLDER "/ext/subghz" | ||||||
|  | #define SUBGHZ_RAW_PATH_FOLDER "/ext/subghz/saved" | ||||||
| #define SUBGHZ_APP_EXTENSION ".sub" | #define SUBGHZ_APP_EXTENSION ".sub" | ||||||
| #define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048 | #define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 2048 | ||||||
| 
 | 
 | ||||||
| @ -23,6 +25,7 @@ typedef enum { | |||||||
|     SubGhzProtocolCommonTypeUnknown, |     SubGhzProtocolCommonTypeUnknown, | ||||||
|     SubGhzProtocolCommonTypeStatic, |     SubGhzProtocolCommonTypeStatic, | ||||||
|     SubGhzProtocolCommonTypeDynamic, |     SubGhzProtocolCommonTypeDynamic, | ||||||
|  |     SubGhzProtocolCommonTypeRAW, | ||||||
| } SubGhzProtocolCommonType; | } SubGhzProtocolCommonType; | ||||||
| 
 | 
 | ||||||
| typedef struct SubGhzProtocolCommon SubGhzProtocolCommon; | typedef struct SubGhzProtocolCommon SubGhzProtocolCommon; | ||||||
| @ -38,7 +41,7 @@ typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, s | |||||||
| 
 | 
 | ||||||
| //Load protocol from file
 | //Load protocol from file
 | ||||||
| typedef bool ( | typedef bool ( | ||||||
|     *SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance); |     *SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance, const char* file_path); | ||||||
| //Load protocol
 | //Load protocol
 | ||||||
| typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context); | typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context); | ||||||
| //Get upload encoder protocol
 | //Get upload encoder protocol
 | ||||||
| @ -46,6 +49,9 @@ typedef bool (*SubGhzProtocolCommonEncoderGetUpLoad)( | |||||||
|     SubGhzProtocolCommon* instance, |     SubGhzProtocolCommon* instance, | ||||||
|     SubGhzProtocolCommonEncoder* encoder); |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
|  | typedef LevelDuration (*SubGhzProtocolCommonEncoderCallback)(void* context); | ||||||
|  | typedef void (*SubGhzProtocolCommonEncoderCallbackEnd)(void* context); | ||||||
|  | 
 | ||||||
| struct SubGhzProtocolCommon { | struct SubGhzProtocolCommon { | ||||||
|     const char* name; |     const char* name; | ||||||
|     uint16_t te_long; |     uint16_t te_long; | ||||||
| @ -86,6 +92,11 @@ struct SubGhzProtocolCommonEncoder { | |||||||
|     size_t front; |     size_t front; | ||||||
|     size_t size_upload; |     size_t size_upload; | ||||||
|     LevelDuration* upload; |     LevelDuration* upload; | ||||||
|  | 
 | ||||||
|  |     SubGhzProtocolCommonEncoderCallback callback; | ||||||
|  |     SubGhzProtocolCommonEncoderCallbackEnd callback_end; | ||||||
|  |     void* context; | ||||||
|  |     void* context_end; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SubGhzProtocolCommonLoad { | struct SubGhzProtocolCommonLoad { | ||||||
| @ -108,6 +119,16 @@ SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc(); | |||||||
|  */ |  */ | ||||||
| void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance); | void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance); | ||||||
| 
 | 
 | ||||||
|  | void subghz_protocol_encoder_common_set_callback( | ||||||
|  |     SubGhzProtocolCommonEncoder* instance, | ||||||
|  |     SubGhzProtocolCommonEncoderCallback callback, | ||||||
|  |     void* context); | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_common_set_callback_end( | ||||||
|  |     SubGhzProtocolCommonEncoder* instance, | ||||||
|  |     SubGhzProtocolCommonEncoderCallbackEnd callback_end, | ||||||
|  |     void* context_end); | ||||||
|  | 
 | ||||||
| /** Get count repeat left
 | /** Get count repeat left
 | ||||||
|  *  |  *  | ||||||
|  * @param instance - SubGhzProtocolCommonEncoder instance |  * @param instance - SubGhzProtocolCommonEncoder instance | ||||||
|  | |||||||
| @ -182,7 +182,8 @@ void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_ | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_gate_tx_to_load_protocol_from_file( | bool subghz_protocol_gate_tx_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolGateTX* instance) { |     SubGhzProtocolGateTX* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -22,7 +22,9 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance); | |||||||
|  * @param encoder - SubGhzProtocolCommonEncoder encoder |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder); | bool subghz_protocol_gate_tx_send_key( | ||||||
|  |     SubGhzProtocolGateTX* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
| /** Reset internal state
 | /** Reset internal state
 | ||||||
|  * @param instance - SubGhzProtocolGateTX instance |  * @param instance - SubGhzProtocolGateTX instance | ||||||
| @ -54,9 +56,13 @@ void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_ | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolGateTX instance |  * @param instance - SubGhzProtocolGateTX instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance); | bool subghz_protocol_gate_tx_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolGateTX* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -436,7 +436,8 @@ void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_keeloq_to_load_protocol_from_file( | bool subghz_protocol_keeloq_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolKeeloq* instance) { |     SubGhzProtocolKeeloq* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -53,7 +53,9 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context); | |||||||
|  * @param encoder - SubGhzProtocolCommonEncoder encoder |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolCommonEncoder* encoder); | bool subghz_protocol_keeloq_send_key( | ||||||
|  |     SubGhzProtocolKeeloq* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
| /** Reset internal state
 | /** Reset internal state
 | ||||||
|  * @param instance - SubGhzProtocolKeeloq instance |  * @param instance - SubGhzProtocolKeeloq instance | ||||||
| @ -85,9 +87,13 @@ void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolKeeloq instance |  * @param instance - SubGhzProtocolKeeloq instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance); | bool subghz_protocol_keeloq_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolKeeloq* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -245,7 +245,8 @@ void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, s | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_nero_radio_to_load_protocol_from_file( | bool subghz_protocol_nero_radio_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolNeroRadio* instance) { |     SubGhzProtocolNeroRadio* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -22,7 +22,9 @@ void subghz_protocol_nero_radio_free(SubGhzProtocolNeroRadio* instance); | |||||||
|  * @param encoder - SubGhzProtocolCommonEncoder encoder |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nero_radio_send_key(SubGhzProtocolNeroRadio* instance, SubGhzProtocolCommonEncoder* encoder); | bool subghz_protocol_nero_radio_send_key( | ||||||
|  |     SubGhzProtocolNeroRadio* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
| /** Reset internal state
 | /** Reset internal state
 | ||||||
|  * @param instance - SubGhzProtocolNeroRadio instance |  * @param instance - SubGhzProtocolNeroRadio instance | ||||||
| @ -40,7 +42,10 @@ void subghz_protocol_nero_radio_check_remote_controller(SubGhzProtocolNeroRadio* | |||||||
|  * @param instance - SubGhzProtocolNeroRadio instance |  * @param instance - SubGhzProtocolNeroRadio instance | ||||||
|  * @param data - LevelDuration level_duration |  * @param data - LevelDuration level_duration | ||||||
|  */ |  */ | ||||||
| void subghz_protocol_nero_radio_parse(SubGhzProtocolNeroRadio* instance, bool level, uint32_t duration); | void subghz_protocol_nero_radio_parse( | ||||||
|  |     SubGhzProtocolNeroRadio* instance, | ||||||
|  |     bool level, | ||||||
|  |     uint32_t duration); | ||||||
| 
 | 
 | ||||||
| /** Outputting information from the parser
 | /** Outputting information from the parser
 | ||||||
|  *  |  *  | ||||||
| @ -60,9 +65,13 @@ void subghz_protocol_nero_radio_to_save_str(SubGhzProtocolNeroRadio* instance, s | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolNeroRadio instance |  * @param instance - SubGhzProtocolNeroRadio instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nero_radio_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroRadio* instance); | bool subghz_protocol_nero_radio_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolNeroRadio* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -238,7 +238,8 @@ void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_nero_sketch_to_load_protocol_from_file( | bool subghz_protocol_nero_sketch_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolNeroSketch* instance) { |     SubGhzProtocolNeroSketch* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -22,7 +22,9 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance); | |||||||
|  * @param encoder - SubGhzProtocolCommonEncoder encoder |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder); | bool subghz_protocol_nero_sketch_send_key( | ||||||
|  |     SubGhzProtocolNeroSketch* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
| /** Reset internal state
 | /** Reset internal state
 | ||||||
|  * @param instance - SubGhzProtocolNeroSketch instance |  * @param instance - SubGhzProtocolNeroSketch instance | ||||||
| @ -40,7 +42,10 @@ void subghz_protocol_nero_sketch_check_remote_controller(SubGhzProtocolNeroSketc | |||||||
|  * @param instance - SubGhzProtocolNeroSketch instance |  * @param instance - SubGhzProtocolNeroSketch instance | ||||||
|  * @param data - LevelDuration level_duration |  * @param data - LevelDuration level_duration | ||||||
|  */ |  */ | ||||||
| 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); | ||||||
| 
 | 
 | ||||||
| /** Outputting information from the parser
 | /** Outputting information from the parser
 | ||||||
|  *  |  *  | ||||||
| @ -60,9 +65,13 @@ void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolNeroSketch instance |  * @param instance - SubGhzProtocolNeroSketch instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance); | bool subghz_protocol_nero_sketch_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolNeroSketch* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -179,7 +179,8 @@ void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, strin | |||||||
| 
 | 
 | ||||||
| bool subghz_protocol_nice_flo_to_load_protocol_from_file( | bool subghz_protocol_nice_flo_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzProtocolNiceFlo* instance) { |     SubGhzProtocolNiceFlo* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -22,7 +22,9 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance); | |||||||
|  * @param encoder - SubGhzProtocolCommonEncoder encoder |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder); | bool subghz_protocol_nice_flo_send_key( | ||||||
|  |     SubGhzProtocolNiceFlo* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
| 
 | 
 | ||||||
| /** Reset internal state
 | /** Reset internal state
 | ||||||
|  * @param instance - SubGhzProtocolNiceFlo instance |  * @param instance - SubGhzProtocolNiceFlo instance | ||||||
| @ -54,9 +56,13 @@ void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, strin | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzProtocolNiceFlo instance |  * @param instance - SubGhzProtocolNiceFlo instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance); | bool subghz_protocol_nice_flo_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolNiceFlo* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -308,7 +308,8 @@ void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, stri | |||||||
| 
 | 
 | ||||||
| bool subghz_decoder_princeton_to_load_protocol_from_file( | bool subghz_decoder_princeton_to_load_protocol_from_file( | ||||||
|     FileWorker* file_worker, |     FileWorker* file_worker, | ||||||
|     SubGhzDecoderPrinceton* instance) { |     SubGhzDecoderPrinceton* instance, | ||||||
|  |     const char* file_path) { | ||||||
|     bool loaded = false; |     bool loaded = false; | ||||||
|     string_t temp_str; |     string_t temp_str; | ||||||
|     string_init(temp_str); |     string_init(temp_str); | ||||||
|  | |||||||
| @ -111,15 +111,17 @@ void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, stri | |||||||
|  *  |  *  | ||||||
|  * @param file_worker - FileWorker file_worker |  * @param file_worker - FileWorker file_worker | ||||||
|  * @param instance - SubGhzDecoderPrinceton instance |  * @param instance - SubGhzDecoderPrinceton instance | ||||||
|  |  * @param file_path - file path | ||||||
|  * @return bool |  * @return bool | ||||||
|  */ |  */ | ||||||
| bool subghz_decoder_princeton_to_load_protocol_from_file(FileWorker* file_worker, SubGhzDecoderPrinceton* instance); | bool subghz_decoder_princeton_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzDecoderPrinceton* instance, | ||||||
|  |     const char* file_path); | ||||||
| 
 | 
 | ||||||
| /** Loading protocol from bin data
 | /** Loading protocol from bin data
 | ||||||
|  *  |  *  | ||||||
|  * @param instance - SubGhzDecoderPrinceton instance |  * @param instance - SubGhzDecoderPrinceton instance | ||||||
|  * @param context - SubGhzProtocolCommonLoad context |  * @param context - SubGhzProtocolCommonLoad context | ||||||
|  */ |  */ | ||||||
| void subghz_decoder_princeton_to_load_protocol( | void subghz_decoder_princeton_to_load_protocol(SubGhzDecoderPrinceton* instance, void* context); | ||||||
|     SubGhzDecoderPrinceton* instance, |  | ||||||
|     void* context) ; |  | ||||||
|  | |||||||
							
								
								
									
										265
									
								
								lib/subghz/protocols/subghz_protocol_raw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								lib/subghz/protocols/subghz_protocol_raw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,265 @@ | |||||||
|  | #include "subghz_protocol_raw.h" | ||||||
|  | #include "file-worker.h" | ||||||
|  | #include "../subghz_file_encoder_worker.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_DOWNLOAD_MAX_SIZE 512 | ||||||
|  | 
 | ||||||
|  | struct SubGhzProtocolRAW { | ||||||
|  |     SubGhzProtocolCommon common; | ||||||
|  | 
 | ||||||
|  |     int16_t* upload_raw; | ||||||
|  |     uint16_t ind_write; | ||||||
|  |     FileWorker* file_worker; | ||||||
|  |     SubGhzFileEncoderWorker* file_worker_encoder; | ||||||
|  |     uint32_t file_is_open; | ||||||
|  |     string_t file_name; | ||||||
|  |     size_t sample_write; | ||||||
|  |     bool last_level; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     RAWFileIsOpenClose = 0, | ||||||
|  |     RAWFileIsOpenWrite, | ||||||
|  |     RAWFileIsOpenRead, | ||||||
|  | } RAWFilIsOpen; | ||||||
|  | 
 | ||||||
|  | SubGhzProtocolRAW* subghz_protocol_raw_alloc(void) { | ||||||
|  |     SubGhzProtocolRAW* instance = furi_alloc(sizeof(SubGhzProtocolRAW)); | ||||||
|  | 
 | ||||||
|  |     instance->upload_raw = NULL; | ||||||
|  |     instance->ind_write = 0; | ||||||
|  | 
 | ||||||
|  |     instance->last_level = false; | ||||||
|  | 
 | ||||||
|  |     instance->file_worker = file_worker_alloc(false); | ||||||
|  |     instance->file_is_open = RAWFileIsOpenClose; | ||||||
|  |     string_init(instance->file_name); | ||||||
|  | 
 | ||||||
|  |     instance->common.name = "RAW"; | ||||||
|  |     instance->common.code_min_count_bit_for_found = 0; | ||||||
|  |     instance->common.te_short = 80; | ||||||
|  |     instance->common.te_long = 32700; | ||||||
|  |     instance->common.te_delta = 0; | ||||||
|  |     instance->common.type_protocol = SubGhzProtocolCommonTypeRAW; | ||||||
|  |     instance->common.to_load_protocol_from_file = | ||||||
|  |         (SubGhzProtocolCommonLoadFromFile)subghz_protocol_raw_to_load_protocol_from_file; | ||||||
|  |     instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_raw_to_str; | ||||||
|  |     //instance->common.to_load_protocol =
 | ||||||
|  |     //    (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_raw_to_load_protocol;
 | ||||||
|  |     instance->common.get_upload_protocol = | ||||||
|  |         (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_raw_send_key; | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_raw_free(SubGhzProtocolRAW* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     string_clear(instance->file_name); | ||||||
|  |     file_worker_free(instance->file_worker); | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_raw_file_encoder_worker_stop(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolRAW* instance = context; | ||||||
|  |     if(subghz_file_encoder_worker_is_running(instance->file_worker_encoder)) { | ||||||
|  |         subghz_file_encoder_worker_stop(instance->file_worker_encoder); | ||||||
|  |         subghz_file_encoder_worker_free(instance->file_worker_encoder); | ||||||
|  |         instance->file_is_open = RAWFileIsOpenClose; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_raw_send_key( | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(encoder); | ||||||
|  | 
 | ||||||
|  |     bool loaded = false; | ||||||
|  | 
 | ||||||
|  |     instance->file_worker_encoder = subghz_file_encoder_worker_alloc(); | ||||||
|  | 
 | ||||||
|  |     if(subghz_file_encoder_worker_start( | ||||||
|  |            instance->file_worker_encoder, string_get_cstr(instance->file_name))) { | ||||||
|  |         //the worker needs a file in order to open and read part of the file
 | ||||||
|  |         osDelay(100); | ||||||
|  |         instance->file_is_open = RAWFileIsOpenRead; | ||||||
|  |         subghz_protocol_encoder_common_set_callback( | ||||||
|  |             encoder, subghz_file_encoder_worker_get_level_duration, instance->file_worker_encoder); | ||||||
|  |         subghz_protocol_encoder_common_set_callback_end( | ||||||
|  |             encoder, subghz_protocol_raw_file_encoder_worker_stop, instance); | ||||||
|  | 
 | ||||||
|  |         loaded = true; | ||||||
|  |     } else { | ||||||
|  |         subghz_protocol_raw_file_encoder_worker_stop(instance); | ||||||
|  |     } | ||||||
|  |     return loaded; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_raw_reset(SubGhzProtocolRAW* instance) { | ||||||
|  |     instance->ind_write = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_raw_parse(SubGhzProtocolRAW* instance, bool level, uint32_t duration) { | ||||||
|  |     if(instance->upload_raw != NULL) { | ||||||
|  |         if(duration > instance->common.te_short) { | ||||||
|  |             if(duration > instance->common.te_long) duration = instance->common.te_long; | ||||||
|  |             if(instance->last_level != level) { | ||||||
|  |                 instance->last_level = (level ? true : false); | ||||||
|  |                 instance->upload_raw[instance->ind_write++] = (level ? duration : -duration); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(instance->ind_write == SUBGHZ_DOWNLOAD_MAX_SIZE) { | ||||||
|  |             subghz_protocol_save_raw_to_file_write(instance); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_raw_to_str(SubGhzProtocolRAW* instance, string_t output) { | ||||||
|  |     string_cat_printf(output, "RAW Date"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const char* subghz_protocol_get_last_file_name(SubGhzProtocolRAW* instance) { | ||||||
|  |     return string_get_cstr(instance->file_name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_set_last_file_name(SubGhzProtocolRAW* instance, const char* name) { | ||||||
|  |     string_printf(instance->file_name, "%s", name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_save_raw_to_file_init( | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     const char* dev_name, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     string_t dev_file_name; | ||||||
|  |     string_init(dev_file_name); | ||||||
|  |     string_t temp_str; | ||||||
|  |     string_init(temp_str); | ||||||
|  |     bool init = false; | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         // Create subghz folder directory if necessary
 | ||||||
|  |         if(!file_worker_mkdir(instance->file_worker, SUBGHZ_RAW_FOLDER)) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         // Create saved directory if necessary
 | ||||||
|  |         if(!file_worker_mkdir(instance->file_worker, SUBGHZ_RAW_PATH_FOLDER)) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         //get the name of the next free file
 | ||||||
|  |         file_worker_get_next_filename( | ||||||
|  |             instance->file_worker, | ||||||
|  |             SUBGHZ_RAW_PATH_FOLDER, | ||||||
|  |             dev_name, | ||||||
|  |             SUBGHZ_APP_EXTENSION, | ||||||
|  |             temp_str); | ||||||
|  | 
 | ||||||
|  |         string_set(instance->file_name, temp_str); | ||||||
|  | 
 | ||||||
|  |         string_printf( | ||||||
|  |             dev_file_name, | ||||||
|  |             "%s/%s%s", | ||||||
|  |             SUBGHZ_RAW_PATH_FOLDER, | ||||||
|  |             string_get_cstr(temp_str), | ||||||
|  |             SUBGHZ_APP_EXTENSION); | ||||||
|  |         // Open file
 | ||||||
|  |         if(!file_worker_open( | ||||||
|  |                instance->file_worker, | ||||||
|  |                string_get_cstr(dev_file_name), | ||||||
|  |                FSAM_WRITE, | ||||||
|  |                FSOM_CREATE_ALWAYS)) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         //Get string frequency preset protocol
 | ||||||
|  |         string_printf( | ||||||
|  |             temp_str, | ||||||
|  |             "Frequency: %d\n" | ||||||
|  |             "Preset: %d\n" | ||||||
|  |             "Protocol: RAW\n", | ||||||
|  |             (int)frequency, | ||||||
|  |             (int)preset); | ||||||
|  | 
 | ||||||
|  |         if(!file_worker_write( | ||||||
|  |                instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         instance->upload_raw = furi_alloc(SUBGHZ_DOWNLOAD_MAX_SIZE * sizeof(uint16_t)); | ||||||
|  |         instance->file_is_open = RAWFileIsOpenWrite; | ||||||
|  |         instance->sample_write = 0; | ||||||
|  |         init = true; | ||||||
|  |     } while(0); | ||||||
|  | 
 | ||||||
|  |     string_clear(temp_str); | ||||||
|  |     string_clear(dev_file_name); | ||||||
|  | 
 | ||||||
|  |     return init; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_save_raw_to_file_stop(SubGhzProtocolRAW* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     if(instance->file_is_open == RAWFileIsOpenWrite && instance->ind_write) | ||||||
|  |         subghz_protocol_save_raw_to_file_write(instance); | ||||||
|  |     if(instance->file_is_open != RAWFileIsOpenClose) { | ||||||
|  |         free(instance->upload_raw); | ||||||
|  |         instance->upload_raw = NULL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     file_worker_close(instance->file_worker); | ||||||
|  |     instance->file_is_open = RAWFileIsOpenClose; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_save_raw_to_file_write(SubGhzProtocolRAW* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     string_t temp_str; | ||||||
|  |     string_init(temp_str); | ||||||
|  |     bool is_write = false; | ||||||
|  |     if(instance->file_is_open == RAWFileIsOpenWrite) { | ||||||
|  |         do { | ||||||
|  |             string_printf(temp_str, "RAW_Data: "); | ||||||
|  | 
 | ||||||
|  |             if(!file_worker_write( | ||||||
|  |                    instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             for(size_t i = 0; i < instance->ind_write - 1; i++) { | ||||||
|  |                 string_printf(temp_str, "%d, ", instance->upload_raw[i]); | ||||||
|  |                 if(!file_worker_write( | ||||||
|  |                        instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             string_printf(temp_str, "%d\n", instance->upload_raw[instance->ind_write - 1]); | ||||||
|  |             if(!file_worker_write( | ||||||
|  |                    instance->file_worker, string_get_cstr(temp_str), string_size(temp_str))) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             instance->sample_write += instance->ind_write; | ||||||
|  |             instance->ind_write = 0; | ||||||
|  |             is_write = true; | ||||||
|  |         } while(0); | ||||||
|  |         string_clear(temp_str); | ||||||
|  |     } | ||||||
|  |     return is_write; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t subghz_save_protocol_raw_get_sample_write(SubGhzProtocolRAW* instance) { | ||||||
|  |     return instance->sample_write + instance->ind_write; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_raw_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     const char* file_path) { | ||||||
|  |     subghz_protocol_set_last_file_name(instance, file_path); | ||||||
|  |     return true; | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								lib/subghz/protocols/subghz_protocol_raw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/subghz/protocols/subghz_protocol_raw.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "subghz_protocol_common.h" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzProtocolRAW SubGhzProtocolRAW; | ||||||
|  | 
 | ||||||
|  | /** Allocate SubGhzProtocolRAW
 | ||||||
|  |  *  | ||||||
|  |  * @return SubGhzProtocolRAW*  | ||||||
|  |  */ | ||||||
|  | SubGhzProtocolRAW* subghz_protocol_raw_alloc(); | ||||||
|  | 
 | ||||||
|  | /** Free SubGhzProtocolRAW
 | ||||||
|  |  *  | ||||||
|  |  * @param instance  | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_raw_free(SubGhzProtocolRAW* instance); | ||||||
|  | 
 | ||||||
|  | /** Reset internal state
 | ||||||
|  |  * @param instance - SubGhzProtocolRAW instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_raw_reset(SubGhzProtocolRAW* instance); | ||||||
|  | 
 | ||||||
|  | /** Get upload protocol
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzProtocolRAW instance | ||||||
|  |  * @param encoder - SubGhzProtocolCommonEncoder encoder | ||||||
|  |  * @return bool | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_raw_send_key( | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     SubGhzProtocolCommonEncoder* encoder); | ||||||
|  | 
 | ||||||
|  | /** Parse accepted duration
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzProtocolRAW instance | ||||||
|  |  * @param data - LevelDuration level_duration | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_raw_parse(SubGhzProtocolRAW* instance, bool level, uint32_t duration); | ||||||
|  | 
 | ||||||
|  | /** Outputting information from the parser
 | ||||||
|  |  * | ||||||
|  |  * @param instance - SubGhzProtocolRAW* instance | ||||||
|  |  * @param output   - output string | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_raw_to_str(SubGhzProtocolRAW* instance, string_t output); | ||||||
|  | 
 | ||||||
|  | const char* subghz_protocol_get_last_file_name(SubGhzProtocolRAW* instance); | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_set_last_file_name(SubGhzProtocolRAW* instance, const char* name); | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_save_raw_to_file_init( | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     const char* dev_name, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset); | ||||||
|  | void subghz_protocol_save_raw_to_file_stop(SubGhzProtocolRAW* instance); | ||||||
|  | bool subghz_protocol_save_raw_to_file_write(SubGhzProtocolRAW* instance); | ||||||
|  | size_t subghz_save_protocol_raw_get_sample_write(SubGhzProtocolRAW* instance); | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_raw_to_load_protocol_from_file( | ||||||
|  |     FileWorker* file_worker, | ||||||
|  |     SubGhzProtocolRAW* instance, | ||||||
|  |     const char* file_path); | ||||||
							
								
								
									
										210
									
								
								lib/subghz/subghz_file_encoder_worker.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								lib/subghz/subghz_file_encoder_worker.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,210 @@ | |||||||
|  | #include "subghz_file_encoder_worker.h" | ||||||
|  | #include <stream_buffer.h> | ||||||
|  | 
 | ||||||
|  | #include "file-worker.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_FILE_ENCODER_LOAD 512 | ||||||
|  | 
 | ||||||
|  | struct SubGhzFileEncoderWorker { | ||||||
|  |     FuriThread* thread; | ||||||
|  |     StreamBufferHandle_t stream; | ||||||
|  |     FileWorker* file_worker; | ||||||
|  | 
 | ||||||
|  |     volatile bool worker_running; | ||||||
|  |     bool level; | ||||||
|  |     int16_t duration; | ||||||
|  |     string_t str_data; | ||||||
|  |     string_t file_path; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void subghz_file_encoder_worker_add_livel_duration( | ||||||
|  |     SubGhzFileEncoderWorker* instance, | ||||||
|  |     int16_t duration) { | ||||||
|  |     bool res = true; | ||||||
|  |     if(duration < 0 && !instance->level) { | ||||||
|  |         instance->duration += duration; | ||||||
|  |         res = false; | ||||||
|  |     } else if(duration > 0 && instance->level) { | ||||||
|  |         instance->duration += duration; | ||||||
|  |         res = false; | ||||||
|  |     } else if(duration == 0) { | ||||||
|  |         instance->duration = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if(res) { | ||||||
|  |         instance->level = !instance->level; | ||||||
|  |         instance->duration += duration; | ||||||
|  |         xStreamBufferSend(instance->stream, &instance->duration, sizeof(int16_t), 10); | ||||||
|  |         instance->duration = 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_file_encoder_worker_data_parse( | ||||||
|  |     SubGhzFileEncoderWorker* instance, | ||||||
|  |     const char* strStart, | ||||||
|  |     size_t len) { | ||||||
|  |     char* str1; | ||||||
|  |     size_t ind_start = (size_t)strStart; //store the start address of the beginning of the line
 | ||||||
|  |     bool res = false; | ||||||
|  | 
 | ||||||
|  |     str1 = strstr( | ||||||
|  |         strStart, "RAW_Data: "); //looking for the beginning of the desired title in the line
 | ||||||
|  |     if(str1 != NULL) { | ||||||
|  |         str1 = strchr( | ||||||
|  |             str1, | ||||||
|  |             ' '); //if found, shift the pointer by 1 element per line "RAW_Data: -1, 2, -2..."
 | ||||||
|  |         subghz_file_encoder_worker_add_livel_duration(instance, atoi(str1)); | ||||||
|  |         while( | ||||||
|  |             strchr(str1, ',') != NULL && | ||||||
|  |             ((size_t)str1 < | ||||||
|  |              (len + | ||||||
|  |               ind_start))) { //check that there is still an element in the line and that it has not gone beyond the line
 | ||||||
|  |             str1 = strchr(str1, ','); | ||||||
|  |             str1 += 2; //if found, shift the pointer by next element per line
 | ||||||
|  |             subghz_file_encoder_worker_add_livel_duration(instance, atoi(str1)); | ||||||
|  |         } | ||||||
|  |         res = true; | ||||||
|  |     } | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzFileEncoderWorker* instance = context; | ||||||
|  |     int16_t duration; | ||||||
|  |     BaseType_t xHigherPriorityTaskWoken = pdFALSE; | ||||||
|  |     int ret = xStreamBufferReceiveFromISR( | ||||||
|  |         instance->stream, &duration, sizeof(int16_t), &xHigherPriorityTaskWoken); | ||||||
|  |     portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | ||||||
|  |     if(ret == sizeof(int16_t)) { | ||||||
|  |         LevelDuration level_duration = {.level = LEVEL_DURATION_RESET}; | ||||||
|  |         if(duration < 0) { | ||||||
|  |             level_duration = level_duration_make(false, duration * -1); | ||||||
|  |         } else if(duration > 0) { | ||||||
|  |             level_duration = level_duration_make(true, duration); | ||||||
|  |         } else if(duration == 0) { | ||||||
|  |             level_duration = level_duration_reset(); | ||||||
|  |             FURI_LOG_I("SubGhzFileEncoderWorker", "Stop transmission"); | ||||||
|  |         } | ||||||
|  |         return level_duration; | ||||||
|  |     } else { | ||||||
|  |         FURI_LOG_E("SubGhzFileEncoderWorker", "Slow flash read"); | ||||||
|  |         return level_duration_wait(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Worker thread
 | ||||||
|  |  *  | ||||||
|  |  * @param context  | ||||||
|  |  * @return exit code  | ||||||
|  |  */ | ||||||
|  | static int32_t subghz_file_encoder_worker_thread(void* context) { | ||||||
|  |     SubGhzFileEncoderWorker* instance = context; | ||||||
|  |     FURI_LOG_I("SubGhzFileEncoderWorker", "Worker start"); | ||||||
|  |     bool res = false; | ||||||
|  |     do { | ||||||
|  |         if(!file_worker_open( | ||||||
|  |                instance->file_worker, | ||||||
|  |                string_get_cstr(instance->file_path), | ||||||
|  |                FSAM_READ, | ||||||
|  |                FSOM_OPEN_EXISTING)) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         //todo skips 3 lines file header
 | ||||||
|  |         if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         res = true; | ||||||
|  |         FURI_LOG_I("SubGhzFileEncoderWorker", "Start transmission"); | ||||||
|  |     } while(0); | ||||||
|  | 
 | ||||||
|  |     while(res && instance->worker_running) { | ||||||
|  |         size_t stream_free_byte = xStreamBufferSpacesAvailable(instance->stream); | ||||||
|  |         if((stream_free_byte / sizeof(int16_t)) >= SUBGHZ_FILE_ENCODER_LOAD) { | ||||||
|  |             if(file_worker_read_until(instance->file_worker, instance->str_data, '\n')) { | ||||||
|  |                 if(!subghz_file_encoder_worker_data_parse( | ||||||
|  |                        instance, | ||||||
|  |                        string_get_cstr(instance->str_data), | ||||||
|  |                        strlen(string_get_cstr(instance->str_data)))) { | ||||||
|  |                     //to stop DMA correctly
 | ||||||
|  |                     subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); | ||||||
|  |                     subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); | ||||||
|  | 
 | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); | ||||||
|  |                 subghz_file_encoder_worker_add_livel_duration(instance, LEVEL_DURATION_RESET); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     //waiting for the end of the transfer
 | ||||||
|  |     while(instance->worker_running) { | ||||||
|  |         osDelay(50); | ||||||
|  |     } | ||||||
|  |     file_worker_close(instance->file_worker); | ||||||
|  |     FURI_LOG_I("SubGhzFileEncoderWorker", "Worker stop"); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() { | ||||||
|  |     SubGhzFileEncoderWorker* instance = furi_alloc(sizeof(SubGhzFileEncoderWorker)); | ||||||
|  | 
 | ||||||
|  |     instance->thread = furi_thread_alloc(); | ||||||
|  |     furi_thread_set_name(instance->thread, "subghz_file_encoder_worker"); | ||||||
|  |     furi_thread_set_stack_size(instance->thread, 2048); | ||||||
|  |     furi_thread_set_context(instance->thread, instance); | ||||||
|  |     furi_thread_set_callback(instance->thread, subghz_file_encoder_worker_thread); | ||||||
|  |     instance->stream = xStreamBufferCreate(sizeof(int16_t) * 4096, sizeof(int16_t)); | ||||||
|  | 
 | ||||||
|  |     instance->file_worker = file_worker_alloc(false); | ||||||
|  |     string_init(instance->str_data); | ||||||
|  |     string_init(instance->file_path); | ||||||
|  |     instance->level = false; | ||||||
|  | 
 | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     vStreamBufferDelete(instance->stream); | ||||||
|  |     furi_thread_free(instance->thread); | ||||||
|  | 
 | ||||||
|  |     string_clear(instance->str_data); | ||||||
|  |     string_clear(instance->file_path); | ||||||
|  |     file_worker_free(instance->file_worker); | ||||||
|  | 
 | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const char* file_path) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(!instance->worker_running); | ||||||
|  | 
 | ||||||
|  |     xStreamBufferReset(instance->stream); | ||||||
|  |     string_set(instance->file_path, file_path); | ||||||
|  |     instance->worker_running = true; | ||||||
|  |     furi_thread_start(instance->thread); | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     furi_assert(instance->worker_running); | ||||||
|  | 
 | ||||||
|  |     instance->worker_running = false; | ||||||
|  |     furi_thread_join(instance->thread); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_file_encoder_worker_is_running(SubGhzFileEncoderWorker* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     return instance->worker_running; | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								lib/subghz/subghz_file_encoder_worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/subghz/subghz_file_encoder_worker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <furi-hal.h> | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzFileEncoderWorker SubGhzFileEncoderWorker; | ||||||
|  | 
 | ||||||
|  | /** Allocate SubGhzFileEncoderWorker
 | ||||||
|  |  *  | ||||||
|  |  * @return SubGhzFileEncoderWorker*  | ||||||
|  |  */ | ||||||
|  | SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc(); | ||||||
|  | 
 | ||||||
|  | /** Free SubGhzFileEncoderWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzFileEncoderWorker instance | ||||||
|  |  */ | ||||||
|  | void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance); | ||||||
|  | 
 | ||||||
|  | LevelDuration subghz_file_encoder_worker_get_level_duration(void* context); | ||||||
|  | 
 | ||||||
|  | /** Start SubGhzFileEncoderWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzFileEncoderWorker instance | ||||||
|  |  * @return bool - true if ok | ||||||
|  |  */ | ||||||
|  | bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const char* file_path); | ||||||
|  | 
 | ||||||
|  | /** Stop SubGhzFileEncoderWorker
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzFileEncoderWorker instance | ||||||
|  |  */ | ||||||
|  | void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance); | ||||||
|  | 
 | ||||||
|  | /** Check if worker is running
 | ||||||
|  |  *  | ||||||
|  |  * @param instance SubGhzFileEncoderWorker instance | ||||||
|  |  * @return bool - true if running | ||||||
|  |  */ | ||||||
|  | bool subghz_file_encoder_worker_is_running(SubGhzFileEncoderWorker* instance); | ||||||
| @ -16,6 +16,7 @@ | |||||||
| #include "protocols/subghz_protocol_nero_radio.h" | #include "protocols/subghz_protocol_nero_radio.h" | ||||||
| #include "protocols/subghz_protocol_scher_khan.h" | #include "protocols/subghz_protocol_scher_khan.h" | ||||||
| #include "protocols/subghz_protocol_kia.h" | #include "protocols/subghz_protocol_kia.h" | ||||||
|  | #include "protocols/subghz_protocol_raw.h" | ||||||
| 
 | 
 | ||||||
| #include "subghz_keystore.h" | #include "subghz_keystore.h" | ||||||
| 
 | 
 | ||||||
| @ -38,6 +39,7 @@ typedef enum { | |||||||
|     SubGhzProtocolTypeNeroRadio, |     SubGhzProtocolTypeNeroRadio, | ||||||
|     SubGhzProtocolTypeScherKhan, |     SubGhzProtocolTypeScherKhan, | ||||||
|     SubGhzProtocolTypeKIA, |     SubGhzProtocolTypeKIA, | ||||||
|  |     SubGhzProtocolTypeRAW, | ||||||
| 
 | 
 | ||||||
|     SubGhzProtocolTypeMax, |     SubGhzProtocolTypeMax, | ||||||
| } SubGhzProtocolType; | } SubGhzProtocolType; | ||||||
| @ -109,6 +111,8 @@ SubGhzParser* subghz_parser_alloc() { | |||||||
|         (SubGhzProtocolCommon*)subghz_protocol_scher_khan_alloc(); |         (SubGhzProtocolCommon*)subghz_protocol_scher_khan_alloc(); | ||||||
|     instance->protocols[SubGhzProtocolTypeKIA] = |     instance->protocols[SubGhzProtocolTypeKIA] = | ||||||
|         (SubGhzProtocolCommon*)subghz_protocol_kia_alloc(); |         (SubGhzProtocolCommon*)subghz_protocol_kia_alloc(); | ||||||
|  |     instance->protocols[SubGhzProtocolTypeRAW] = | ||||||
|  |         (SubGhzProtocolCommon*)subghz_protocol_raw_alloc(); | ||||||
| 
 | 
 | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| @ -143,6 +147,7 @@ void subghz_parser_free(SubGhzParser* instance) { | |||||||
|     subghz_protocol_scher_khan_free( |     subghz_protocol_scher_khan_free( | ||||||
|         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]); |         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]); | ||||||
|     subghz_protocol_kia_free((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]); |     subghz_protocol_kia_free((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]); | ||||||
|  |     subghz_protocol_raw_free((SubGhzProtocolRAW*)instance->protocols[SubGhzProtocolTypeRAW]); | ||||||
| 
 | 
 | ||||||
|     subghz_keystore_free(instance->keystore); |     subghz_keystore_free(instance->keystore); | ||||||
| 
 | 
 | ||||||
| @ -197,6 +202,11 @@ void subghz_parser_load_nice_flor_s_file(SubGhzParser* instance, const char* fil | |||||||
|         (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name); |         (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void subghz_parser_load_came_atomo_file(SubGhzParser* instance, const char* file_name) { | ||||||
|  |     subghz_protocol_came_atomo_name_file( | ||||||
|  |         (SubGhzProtocolCameAtomo*)instance->protocols[SubGhzProtocolTypeCameAtomo], file_name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name) { | void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name) { | ||||||
|     subghz_keystore_load(instance->keystore, file_name); |     subghz_keystore_load(instance->keystore, file_name); | ||||||
| } | } | ||||||
| @ -229,6 +239,12 @@ void subghz_parser_reset(SubGhzParser* instance) { | |||||||
|     subghz_protocol_scher_khan_reset( |     subghz_protocol_scher_khan_reset( | ||||||
|         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]); |         (SubGhzProtocolScherKhan*)instance->protocols[SubGhzProtocolTypeScherKhan]); | ||||||
|     subghz_protocol_kia_reset((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]); |     subghz_protocol_kia_reset((SubGhzProtocolKIA*)instance->protocols[SubGhzProtocolTypeKIA]); | ||||||
|  |     subghz_protocol_raw_reset((SubGhzProtocolRAW*)instance->protocols[SubGhzProtocolTypeRAW]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_parser_raw_parse(SubGhzParser* instance, bool level, uint32_t duration) { | ||||||
|  |     subghz_protocol_raw_parse( | ||||||
|  |         (SubGhzProtocolRAW*)instance->protocols[SubGhzProtocolTypeRAW], level, duration); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_parser_parse(SubGhzParser* instance, bool level, uint32_t duration) { | void subghz_parser_parse(SubGhzParser* instance, bool level, uint32_t duration) { | ||||||
|  | |||||||
| @ -33,7 +33,10 @@ SubGhzProtocolCommon* subghz_parser_get_by_name(SubGhzParser* instance, const ch | |||||||
|  * @param callback - SubGhzProtocolTextCallback callback |  * @param callback - SubGhzProtocolTextCallback callback | ||||||
|  * @param context |  * @param context | ||||||
|  */ |  */ | ||||||
| void subghz_parser_enable_dump_text(SubGhzParser* instance, SubGhzProtocolTextCallback callback, void* context); | void subghz_parser_enable_dump_text( | ||||||
|  |     SubGhzParser* instance, | ||||||
|  |     SubGhzProtocolTextCallback callback, | ||||||
|  |     void* context); | ||||||
| 
 | 
 | ||||||
| /** Outputting data SubGhzParser from all parsers
 | /** Outputting data SubGhzParser from all parsers
 | ||||||
|  *  |  *  | ||||||
| @ -41,7 +44,10 @@ void subghz_parser_enable_dump_text(SubGhzParser* instance, SubGhzProtocolTextCa | |||||||
|  * @param callback - SubGhzProtocolTextCallback callback |  * @param callback - SubGhzProtocolTextCallback callback | ||||||
|  * @param context |  * @param context | ||||||
|  */ |  */ | ||||||
| void subghz_parser_enable_dump(SubGhzParser* instance, SubGhzProtocolCommonCallbackDump callback, void* context); | void subghz_parser_enable_dump( | ||||||
|  |     SubGhzParser* instance, | ||||||
|  |     SubGhzProtocolCommonCallbackDump callback, | ||||||
|  |     void* context); | ||||||
| 
 | 
 | ||||||
| /** File name rainbow table Nice Flor-S
 | /** File name rainbow table Nice Flor-S
 | ||||||
|  *  |  *  | ||||||
| @ -50,6 +56,13 @@ void subghz_parser_enable_dump(SubGhzParser* instance, SubGhzProtocolCommonCallb | |||||||
|  */ |  */ | ||||||
| void subghz_parser_load_nice_flor_s_file(SubGhzParser* instance, const char* file_name); | void subghz_parser_load_nice_flor_s_file(SubGhzParser* instance, const char* file_name); | ||||||
| 
 | 
 | ||||||
|  | /** File name rainbow table Came Atomo
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzParser instance | ||||||
|  |  * @param file_name - "path/file_name" | ||||||
|  |  */ | ||||||
|  | void subghz_parser_load_came_atomo_file(SubGhzParser* instance, const char* file_name); | ||||||
|  | 
 | ||||||
| /** File upload manufacture keys
 | /** File upload manufacture keys
 | ||||||
|  *  |  *  | ||||||
|  * @param instance - SubGhzParser instance |  * @param instance - SubGhzParser instance | ||||||
| @ -63,6 +76,8 @@ void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_nam | |||||||
|  */ |  */ | ||||||
| void subghz_parser_reset(SubGhzParser* instance); | void subghz_parser_reset(SubGhzParser* instance); | ||||||
| 
 | 
 | ||||||
|  | void subghz_parser_raw_parse(SubGhzParser* instance, bool level, uint32_t duration); | ||||||
|  | 
 | ||||||
| /** Loading data into all parsers
 | /** Loading data into all parsers
 | ||||||
|  *  |  *  | ||||||
|  * @param instance - SubGhzParser instance |  * @param instance - SubGhzParser instance | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| #define LEVEL_DURATION_RESET 0U | #define LEVEL_DURATION_RESET 0U | ||||||
| #define LEVEL_DURATION_LEVEL_LOW 1U | #define LEVEL_DURATION_LEVEL_LOW 1U | ||||||
| #define LEVEL_DURATION_LEVEL_HIGH 2U | #define LEVEL_DURATION_LEVEL_HIGH 2U | ||||||
|  | #define LEVEL_DURATION_WAIT 3U | ||||||
| #define LEVEL_DURATION_RESERVED 0x800000U | #define LEVEL_DURATION_RESERVED 0x800000U | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -29,10 +30,20 @@ static inline LevelDuration level_duration_reset() { | |||||||
|     return level_duration; |     return level_duration; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline LevelDuration level_duration_wait() { | ||||||
|  |     LevelDuration level_duration; | ||||||
|  |     level_duration.level = LEVEL_DURATION_WAIT; | ||||||
|  |     return level_duration; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline bool level_duration_is_reset(LevelDuration level_duration) { | static inline bool level_duration_is_reset(LevelDuration level_duration) { | ||||||
|     return level_duration.level == LEVEL_DURATION_RESET; |     return level_duration.level == LEVEL_DURATION_RESET; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline bool level_duration_is_wait(LevelDuration level_duration) { | ||||||
|  |     return level_duration.level == LEVEL_DURATION_WAIT; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline bool level_duration_get_level(LevelDuration level_duration) { | static inline bool level_duration_get_level(LevelDuration level_duration) { | ||||||
|     return level_duration.level == LEVEL_DURATION_LEVEL_HIGH; |     return level_duration.level == LEVEL_DURATION_LEVEL_HIGH; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Skorpionm
						Skorpionm