Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
		
						commit
						be4dec77da
					
				| @ -211,11 +211,12 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { | |||||||
|     bool result = false; |     bool result = false; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         // First remove key if it was saved (we rename the key)
 |         // Check if we has old key
 | ||||||
|         ibutton_delete_key(ibutton); |  | ||||||
| 
 |  | ||||||
|         // Set full file name, for new key
 |  | ||||||
|         if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { |         if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { | ||||||
|  |             // First remove old key
 | ||||||
|  |             ibutton_delete_key(ibutton); | ||||||
|  | 
 | ||||||
|  |             // Remove old key name from path
 | ||||||
|             size_t filename_start = string_search_rchar(ibutton->file_path, '/'); |             size_t filename_start = string_search_rchar(ibutton->file_path, '/'); | ||||||
|             string_left(ibutton->file_path, filename_start); |             string_left(ibutton->file_path, filename_start); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -81,7 +81,7 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */ | |||||||
|     case LfrfidKeyType::KeyIoProxXSF: |     case LfrfidKeyType::KeyIoProxXSF: | ||||||
|         line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary); |         line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary); | ||||||
|         line_2l_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary); |         line_2l_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary); | ||||||
|         line_2r_text->set_text("V:", 95, 35, 0, AlignRight, AlignBottom, FontSecondary); |         line_2r_text->set_text("VС:", 95, 35, 0, AlignRight, AlignBottom, FontSecondary); | ||||||
|         line_3_text->set_text("Card:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary); |         line_3_text->set_text("Card:", 65, 47, 0, AlignRight, AlignBottom, FontSecondary); | ||||||
| 
 | 
 | ||||||
|         for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { |         for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { | ||||||
|  | |||||||
| @ -1,23 +1,10 @@ | |||||||
| #include "lfrfid_app_scene_save_data.h" | #include "lfrfid_app_scene_save_data.h" | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
| static void print_buffer(const uint8_t* buffer) { |  | ||||||
|     for(uint8_t i = 0; i < LFRFID_KEY_SIZE; i++) { |  | ||||||
|         printf("%02X", buffer[i]); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) { | void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) { | ||||||
|     auto byte_input = app->view_controller.get<ByteInputVM>(); |     auto byte_input = app->view_controller.get<ByteInputVM>(); | ||||||
|     RfidKey& key = app->worker.key; |     RfidKey& key = app->worker.key; | ||||||
| 
 | 
 | ||||||
|     printf("k: "); |  | ||||||
|     print_buffer(key.get_data()); |  | ||||||
|     printf(" o: "); |  | ||||||
|     print_buffer(old_key_data); |  | ||||||
|     printf(" n: "); |  | ||||||
|     print_buffer(new_key_data); |  | ||||||
|     printf("\r\n"); |  | ||||||
|     if(need_restore) printf("restored\r\n"); |     if(need_restore) printf("restored\r\n"); | ||||||
| 
 | 
 | ||||||
|     if(need_restore) { |     if(need_restore) { | ||||||
|  | |||||||
| @ -5,6 +5,26 @@ typedef enum { | |||||||
|     SubGhzCustomEventManagerSet, |     SubGhzCustomEventManagerSet, | ||||||
|     SubGhzCustomEventManagerSetRAW, |     SubGhzCustomEventManagerSetRAW, | ||||||
| 
 | 
 | ||||||
|  |     //SubmenuIndex
 | ||||||
|  |     SubmenuIndexPricenton, | ||||||
|  |     SubmenuIndexNiceFlo12bit, | ||||||
|  |     SubmenuIndexNiceFlo24bit, | ||||||
|  |     SubmenuIndexCAME12bit, | ||||||
|  |     SubmenuIndexCAME24bit, | ||||||
|  |     SubmenuIndexCAMETwee, | ||||||
|  |     SubmenuIndexNeroSketch, | ||||||
|  |     SubmenuIndexNeroRadio, | ||||||
|  |     SubmenuIndexGateTX, | ||||||
|  |     SubmenuIndexDoorHan_315_00, | ||||||
|  |     SubmenuIndexDoorHan_433_92, | ||||||
|  |     SubmenuIndexLinear_300_00, | ||||||
|  |     SubmenuIndexLiftMaster_315_00, | ||||||
|  |     SubmenuIndexLiftMaster_390_00, | ||||||
|  |     SubmenuIndexSecPlus_v2_310_00, | ||||||
|  |     SubmenuIndexSecPlus_v2_315_00, | ||||||
|  |     SubmenuIndexSecPlus_v2_390_00, | ||||||
|  | 
 | ||||||
|  |     //SubGhzCustomEvent
 | ||||||
|     SubGhzCustomEventSceneDeleteSuccess = 100, |     SubGhzCustomEventSceneDeleteSuccess = 100, | ||||||
|     SubGhzCustomEventSceneDelete, |     SubGhzCustomEventSceneDelete, | ||||||
|     SubGhzCustomEventSceneDeleteRAW, |     SubGhzCustomEventSceneDeleteRAW, | ||||||
|  | |||||||
| @ -26,9 +26,15 @@ bool subghz_scene_delete_success_on_event(void* context, SceneManagerEvent event | |||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubGhzCustomEventSceneDeleteSuccess) { |         if(event.event == SubGhzCustomEventSceneDeleteSuccess) { | ||||||
|             if(!scene_manager_search_and_switch_to_previous_scene( |             if(scene_manager_search_and_switch_to_previous_scene( | ||||||
|                    subghz->scene_manager, SubGhzSceneSaved)) { |                    subghz->scene_manager, SubGhzSceneReadRAW)) { | ||||||
|  |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); | ||||||
|  |             } else if(scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                           subghz->scene_manager, SubGhzSceneSaved)) { | ||||||
|                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); | ||||||
|  |             } else { | ||||||
|  |                 scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                     subghz->scene_manager, SubGhzSceneStart); | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -167,11 +167,13 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { | |||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case SubGhzCustomEventViewReadRAWErase: |         case SubGhzCustomEventViewReadRAWErase: | ||||||
|             subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; |             if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) { | ||||||
|             if(subghz_scene_read_raw_update_filename(subghz)) { |                 if(subghz_scene_read_raw_update_filename(subghz)) { | ||||||
|                 string_set(subghz->file_path_tmp, subghz->file_path); |                     string_set(subghz->file_path_tmp, subghz->file_path); | ||||||
|                 subghz_delete_file(subghz); |                     subghz_delete_file(subghz); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |             subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; | ||||||
|             notification_message(subghz->notifications, &sequence_reset_rgb); |             notification_message(subghz->notifications, &sequence_reset_rgb); | ||||||
|             return true; |             return true; | ||||||
|             break; |             break; | ||||||
| @ -184,7 +186,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW); |                 scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW); | ||||||
|                 return true; |                 return true; | ||||||
|             } else { |             } else { | ||||||
|                 furi_crash("SugGhz: RAW file name update error."); |                 furi_crash("SubGhz: RAW file name update error."); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,26 +10,6 @@ | |||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzSetType" | #define TAG "SubGhzSetType" | ||||||
| 
 | 
 | ||||||
| enum SubmenuIndex { |  | ||||||
|     SubmenuIndexPricenton, |  | ||||||
|     SubmenuIndexNiceFlo12bit, |  | ||||||
|     SubmenuIndexNiceFlo24bit, |  | ||||||
|     SubmenuIndexCAME12bit, |  | ||||||
|     SubmenuIndexCAME24bit, |  | ||||||
|     SubmenuIndexCAMETwee, |  | ||||||
|     SubmenuIndexNeroSketch, |  | ||||||
|     SubmenuIndexNeroRadio, |  | ||||||
|     SubmenuIndexGateTX, |  | ||||||
|     SubmenuIndexDoorHan_315_00, |  | ||||||
|     SubmenuIndexDoorHan_433_92, |  | ||||||
|     SubmenuIndexFirefly_300_00, |  | ||||||
|     SubmenuIndexLiftMaster_315_00, |  | ||||||
|     SubmenuIndexLiftMaster_390_00, |  | ||||||
|     SubmenuIndexSecPlus_v2_310_00, |  | ||||||
|     SubmenuIndexSecPlus_v2_315_00, |  | ||||||
|     SubmenuIndexSecPlus_v2_390_00, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| bool subghz_scene_set_type_submenu_gen_data_protocol( | bool subghz_scene_set_type_submenu_gen_data_protocol( | ||||||
|     void* context, |     void* context, | ||||||
|     const char* protocol_name, |     const char* protocol_name, | ||||||
| @ -117,8 +97,8 @@ void subghz_scene_set_type_on_enter(void* context) { | |||||||
|         subghz); |         subghz); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         subghz->submenu, |         subghz->submenu, | ||||||
|         "Firefly_300", |         "Linear_300", | ||||||
|         SubmenuIndexFirefly_300_00, |         SubmenuIndexLinear_300_00, | ||||||
|         subghz_scene_set_type_submenu_callback, |         subghz_scene_set_type_submenu_callback, | ||||||
|         subghz); |         subghz); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
| @ -256,11 +236,11 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { | |||||||
|                 generated_protocol = true; |                 generated_protocol = true; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SubmenuIndexFirefly_300_00: |         case SubmenuIndexLinear_300_00: | ||||||
|             key = (key & 0x3FF); |             key = (key & 0x3FF); | ||||||
|             if(subghz_scene_set_type_submenu_gen_data_protocol( |             if(subghz_scene_set_type_submenu_gen_data_protocol( | ||||||
|                    subghz, |                    subghz, | ||||||
|                    SUBGHZ_PROTOCOL_FIREFLY_NAME, |                    SUBGHZ_PROTOCOL_LINEAR_NAME, | ||||||
|                    key, |                    key, | ||||||
|                    10, |                    10, | ||||||
|                    300000000, |                    300000000, | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_ | |||||||
|             subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { |             subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { | ||||||
|             string_set_str(modulation, "FM"); |             string_set_str(modulation, "FM"); | ||||||
|         } else { |         } else { | ||||||
|             furi_crash("SugGhz: Modulation is incorrect."); |             furi_crash("SubGhz: Modulation is incorrect."); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -71,7 +71,7 @@ void subghz_begin(SubGhz* subghz, FuriHalSubGhzPreset preset) { | |||||||
| uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { | uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { | ||||||
|     furi_assert(subghz); |     furi_assert(subghz); | ||||||
|     if(!furi_hal_subghz_is_frequency_valid(frequency)) { |     if(!furi_hal_subghz_is_frequency_valid(frequency)) { | ||||||
|         furi_crash("SugGhz: Incorrect RX frequency."); |         furi_crash("SubGhz: Incorrect RX frequency."); | ||||||
|     } |     } | ||||||
|     furi_assert( |     furi_assert( | ||||||
|         subghz->txrx->txrx_state != SubGhzTxRxStateRx && |         subghz->txrx->txrx_state != SubGhzTxRxStateRx && | ||||||
| @ -92,7 +92,7 @@ uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { | |||||||
| static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { | static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { | ||||||
|     furi_assert(subghz); |     furi_assert(subghz); | ||||||
|     if(!furi_hal_subghz_is_frequency_valid(frequency)) { |     if(!furi_hal_subghz_is_frequency_valid(frequency)) { | ||||||
|         furi_crash("SugGhz: Incorrect TX frequency."); |         furi_crash("SubGhz: Incorrect TX frequency."); | ||||||
|     } |     } | ||||||
|     furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); |     furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); | ||||||
|     furi_hal_subghz_idle(); |     furi_hal_subghz_idle(); | ||||||
|  | |||||||
| @ -328,10 +328,10 @@ MU_TEST(subghz_decoder_star_line_test) { | |||||||
|         "Test decoder " SUBGHZ_PROTOCOL_STAR_LINE_NAME " error\r\n"); |         "Test decoder " SUBGHZ_PROTOCOL_STAR_LINE_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(subghz_decoder_firefly_test) { | MU_TEST(subghz_decoder_linear_test) { | ||||||
|     mu_assert( |     mu_assert( | ||||||
|         subghz_decoder_test("/ext/unit_tests/subghz/firefly_raw.sub", SUBGHZ_PROTOCOL_FIREFLY_NAME), |         subghz_decoder_test("/ext/unit_tests/subghz/linear_raw.sub", SUBGHZ_PROTOCOL_LINEAR_NAME), | ||||||
|         "Test decoder " SUBGHZ_PROTOCOL_FIREFLY_NAME " error\r\n"); |         "Test decoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(subghz_decoder_megacode_test) { | MU_TEST(subghz_decoder_megacode_test) { | ||||||
| @ -398,10 +398,10 @@ MU_TEST(subghz_encoder_keelog_test) { | |||||||
|         "Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n"); |         "Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(subghz_encoder_firefly_test) { | MU_TEST(subghz_encoder_linear_test) { | ||||||
|     mu_assert( |     mu_assert( | ||||||
|         subghz_encoder_test("/ext/unit_tests/subghz/firely.sub"), |         subghz_encoder_test("/ext/unit_tests/subghz/linear.sub"), | ||||||
|         "Test encoder " SUBGHZ_PROTOCOL_FIREFLY_NAME " error\r\n"); |         "Test encoder " SUBGHZ_PROTOCOL_LINEAR_NAME " error\r\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(subghz_encoder_megacode_test) { | MU_TEST(subghz_encoder_megacode_test) { | ||||||
| @ -454,7 +454,7 @@ MU_TEST_SUITE(subghz) { | |||||||
|     MU_RUN_TEST(subghz_decoder_somfy_keytis_test); |     MU_RUN_TEST(subghz_decoder_somfy_keytis_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_somfy_telis_test); |     MU_RUN_TEST(subghz_decoder_somfy_telis_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_star_line_test); |     MU_RUN_TEST(subghz_decoder_star_line_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_firefly_test); |     MU_RUN_TEST(subghz_decoder_linear_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_megacode_test); |     MU_RUN_TEST(subghz_decoder_megacode_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_secplus_v1_test); |     MU_RUN_TEST(subghz_decoder_secplus_v1_test); | ||||||
|     MU_RUN_TEST(subghz_decoder_secplus_v2_test); |     MU_RUN_TEST(subghz_decoder_secplus_v2_test); | ||||||
| @ -466,7 +466,7 @@ MU_TEST_SUITE(subghz) { | |||||||
|     MU_RUN_TEST(subghz_encoder_gate_tx_test); |     MU_RUN_TEST(subghz_encoder_gate_tx_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_nice_flo_test); |     MU_RUN_TEST(subghz_encoder_nice_flo_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_keelog_test); |     MU_RUN_TEST(subghz_encoder_keelog_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_firefly_test); |     MU_RUN_TEST(subghz_encoder_linear_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_megacode_test); |     MU_RUN_TEST(subghz_encoder_megacode_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_holtek_test); |     MU_RUN_TEST(subghz_encoder_holtek_test); | ||||||
|     MU_RUN_TEST(subghz_encoder_secplus_v1_test); |     MU_RUN_TEST(subghz_encoder_secplus_v1_test); | ||||||
|  | |||||||
| @ -2,6 +2,6 @@ Filetype: Flipper SubGhz Key File | |||||||
| Version: 1 | Version: 1 | ||||||
| Frequency: 300000000 | Frequency: 300000000 | ||||||
| Preset: FuriHalSubGhzPresetOok650Async | Preset: FuriHalSubGhzPresetOok650Async | ||||||
| Protocol: Firefly | Protocol: Linear | ||||||
| Bit: 10 | Bit: 10 | ||||||
| Key: 00 00 00 00 00 00 01 E4 | Key: 00 00 00 00 00 00 01 E4 | ||||||
| @ -412,7 +412,7 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
|         furi_hal_subghz_load_registers(furi_hal_subghz_preset_gfsk_9_99kb_async_regs); |         furi_hal_subghz_load_registers(furi_hal_subghz_preset_gfsk_9_99kb_async_regs); | ||||||
|         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable); |         furi_hal_subghz_load_patable(furi_hal_subghz_preset_gfsk_async_patable); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash("SugGhz: Missing config."); |         furi_crash("SubGhz: Missing config."); | ||||||
|     } |     } | ||||||
|     furi_hal_subghz_preset = preset; |     furi_hal_subghz_preset = preset; | ||||||
| } | } | ||||||
| @ -564,7 +564,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | |||||||
|     } else if(value >= 778999847 && value <= 928000000) { |     } else if(value >= 778999847 && value <= 928000000) { | ||||||
|         furi_hal_subghz_set_path(FuriHalSubGhzPath868); |         furi_hal_subghz_set_path(FuriHalSubGhzPath868); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash("SugGhz: Incorrect frequency during set."); |         furi_crash("SubGhz: Incorrect frequency during set."); | ||||||
|     } |     } | ||||||
|     return value; |     return value; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,3 +1,45 @@ | |||||||
| #include "encoder.h" | #include "encoder.h" | ||||||
|  | #include "math.h" | ||||||
|  | #include <furi/check.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzBlockEncoder" | #define TAG "SubGhzBlockEncoder" | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_blocks_set_bit_array( | ||||||
|  |     bool bit_value, | ||||||
|  |     uint8_t data_array[], | ||||||
|  |     size_t set_index_bit, | ||||||
|  |     size_t max_size_array) { | ||||||
|  |     furi_assert(set_index_bit < max_size_array * 8); | ||||||
|  |     bit_write(data_array[set_index_bit >> 3], 7 - (set_index_bit & 0x7), bit_value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_index_bit) { | ||||||
|  |     return bit_read(data_array[read_index_bit >> 3], 7 - (read_index_bit & 0x7)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t subghz_protocol_blocks_get_upload( | ||||||
|  |     uint8_t data_array[], | ||||||
|  |     size_t count_bit_data_array, | ||||||
|  |     LevelDuration* upload, | ||||||
|  |     size_t max_size_upload, | ||||||
|  |     uint32_t duration_bit) { | ||||||
|  |     size_t index_bit = 0; | ||||||
|  |     size_t size_upload = 0; | ||||||
|  |     uint32_t duration = duration_bit; | ||||||
|  |     bool last_bit = subghz_protocol_blocks_get_bit_array(data_array, index_bit++); | ||||||
|  |     for(size_t i = 1; i < count_bit_data_array; i++) { | ||||||
|  |         if(last_bit == subghz_protocol_blocks_get_bit_array(data_array, index_bit)) { | ||||||
|  |             duration += duration_bit; | ||||||
|  |         } else { | ||||||
|  |             furi_assert(max_size_upload > size_upload); | ||||||
|  |             upload[size_upload++] = level_duration_make( | ||||||
|  |                 subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); | ||||||
|  |             last_bit = !last_bit; | ||||||
|  |             duration = duration_bit; | ||||||
|  |         } | ||||||
|  |         index_bit++; | ||||||
|  |     } | ||||||
|  |     upload[size_upload++] = level_duration_make( | ||||||
|  |         subghz_protocol_blocks_get_bit_array(data_array, index_bit - 1), duration); | ||||||
|  |     return size_upload; | ||||||
|  | } | ||||||
| @ -14,3 +14,39 @@ typedef struct { | |||||||
|     LevelDuration* upload; |     LevelDuration* upload; | ||||||
| 
 | 
 | ||||||
| } SubGhzProtocolBlockEncoder; | } SubGhzProtocolBlockEncoder; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Set data bit when encoding HEX array. | ||||||
|  |  * @param bit_value The value of the bit to be set | ||||||
|  |  * @param data_array Pointer to a HEX array | ||||||
|  |  * @param set_index_bit Number set a bit in the array starting from the left | ||||||
|  |  * @param max_size_array array size, check not to overflow | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_blocks_set_bit_array( | ||||||
|  |     bool bit_value, | ||||||
|  |     uint8_t data_array[], | ||||||
|  |     size_t set_index_bit, | ||||||
|  |     size_t max_size_array); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Get data bit when encoding HEX array. | ||||||
|  |  * @param data_array Pointer to a HEX array | ||||||
|  |  * @param read_index_bit Number get a bit in the array starting from the left | ||||||
|  |  * @return bool value bit | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_blocks_get_bit_array(uint8_t data_array[], size_t read_index_bit); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Generating an upload from data. | ||||||
|  |  * @param data_array Pointer to a HEX array | ||||||
|  |  * @param count_bit_data_array How many bits in the array are processed | ||||||
|  |  * @param upload Pointer to a LevelDuration | ||||||
|  |  * @param max_size_upload upload size, check not to overflow | ||||||
|  |  * @param duration_bit duration 1 bit | ||||||
|  |  */ | ||||||
|  | size_t subghz_protocol_blocks_get_upload( | ||||||
|  |     uint8_t data_array[], | ||||||
|  |     size_t count_bit_data_array, | ||||||
|  |     LevelDuration* upload, | ||||||
|  |     size_t max_size_upload, | ||||||
|  |     uint32_t duration_bit); | ||||||
|  | |||||||
| @ -145,7 +145,7 @@ static LevelDuration | |||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         furi_crash("SugGhz: ManchesterEncoderResult is incorrect."); |         furi_crash("SubGhz: ManchesterEncoderResult is incorrect."); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     return level_duration_make(data.level, data.duration); |     return level_duration_make(data.level, data.duration); | ||||||
|  | |||||||
							
								
								
									
										483
									
								
								lib/subghz/protocols/chamberlain_code.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										483
									
								
								lib/subghz/protocols/chamberlain_code.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,483 @@ | |||||||
|  | #include "chamberlain_code.h" | ||||||
|  | 
 | ||||||
|  | #include "../blocks/const.h" | ||||||
|  | #include "../blocks/decoder.h" | ||||||
|  | #include "../blocks/encoder.h" | ||||||
|  | #include "../blocks/generic.h" | ||||||
|  | #include "../blocks/math.h" | ||||||
|  | 
 | ||||||
|  | #define TAG "SubGhzProtocolChamb_Code" | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_CODE_BIT_STOP 0b0001 | ||||||
|  | #define CHAMBERLAIN_CODE_BIT_1 0b0011 | ||||||
|  | #define CHAMBERLAIN_CODE_BIT_0 0b0111 | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_7_CODE_MASK 0xF000000FF0F | ||||||
|  | #define CHAMBERLAIN_8_CODE_MASK 0xF00000F00F | ||||||
|  | #define CHAMBERLAIN_9_CODE_MASK 0xF000000000F | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_7_CODE_MASK_CHECK 0x10000001101 | ||||||
|  | #define CHAMBERLAIN_8_CODE_MASK_CHECK 0x1000001001 | ||||||
|  | #define CHAMBERLAIN_9_CODE_MASK_CHECK 0x10000000001 | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_7_CODE_DIP_PATTERN "%c%c%c%c%c%c%c" | ||||||
|  | #define CHAMBERLAIN_7_CODE_DATA_TO_DIP(dip)                                                 \ | ||||||
|  |     (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'),     \ | ||||||
|  |         (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \ | ||||||
|  |         (dip & 0x0001 ? '1' : '0') | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_8_CODE_DIP_PATTERN "%c%c%c%c%cx%c%c" | ||||||
|  | #define CHAMBERLAIN_8_CODE_DATA_TO_DIP(dip)                                                 \ | ||||||
|  |     (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'),     \ | ||||||
|  |         (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), (dip & 0x0001 ? '1' : '0'), \ | ||||||
|  |         (dip & 0x0002 ? '1' : '0') | ||||||
|  | 
 | ||||||
|  | #define CHAMBERLAIN_9_CODE_DIP_PATTERN "%c%c%c%c%c%c%c%c%c" | ||||||
|  | #define CHAMBERLAIN_9_CODE_DATA_TO_DIP(dip)                                                 \ | ||||||
|  |     (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), (dip & 0x0040 ? '1' : '0'),     \ | ||||||
|  |         (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), (dip & 0x0008 ? '1' : '0'), \ | ||||||
|  |         (dip & 0x0001 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), (dip & 0x0004 ? '1' : '0') | ||||||
|  | 
 | ||||||
|  | static const SubGhzBlockConst subghz_protocol_chamb_code_const = { | ||||||
|  |     .te_short = 1000, | ||||||
|  |     .te_long = 3000, | ||||||
|  |     .te_delta = 200, | ||||||
|  |     .min_count_bit_for_found = 10, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SubGhzProtocolDecoderChamb_Code { | ||||||
|  |     SubGhzProtocolDecoderBase base; | ||||||
|  | 
 | ||||||
|  |     SubGhzBlockDecoder decoder; | ||||||
|  |     SubGhzBlockGeneric generic; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct SubGhzProtocolEncoderChamb_Code { | ||||||
|  |     SubGhzProtocolEncoderBase base; | ||||||
|  | 
 | ||||||
|  |     SubGhzProtocolBlockEncoder encoder; | ||||||
|  |     SubGhzBlockGeneric generic; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     Chamb_CodeDecoderStepReset = 0, | ||||||
|  |     Chamb_CodeDecoderStepFoundStartBit, | ||||||
|  |     Chamb_CodeDecoderStepSaveDuration, | ||||||
|  |     Chamb_CodeDecoderStepCheckDuration, | ||||||
|  | } Chamb_CodeDecoderStep; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocolDecoder subghz_protocol_chamb_code_decoder = { | ||||||
|  |     .alloc = subghz_protocol_decoder_chamb_code_alloc, | ||||||
|  |     .free = subghz_protocol_decoder_chamb_code_free, | ||||||
|  | 
 | ||||||
|  |     .feed = subghz_protocol_decoder_chamb_code_feed, | ||||||
|  |     .reset = subghz_protocol_decoder_chamb_code_reset, | ||||||
|  | 
 | ||||||
|  |     .get_hash_data = subghz_protocol_decoder_chamb_code_get_hash_data, | ||||||
|  |     .serialize = subghz_protocol_decoder_chamb_code_serialize, | ||||||
|  |     .deserialize = subghz_protocol_decoder_chamb_code_deserialize, | ||||||
|  |     .get_string = subghz_protocol_decoder_chamb_code_get_string, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocolEncoder subghz_protocol_chamb_code_encoder = { | ||||||
|  |     .alloc = subghz_protocol_encoder_chamb_code_alloc, | ||||||
|  |     .free = subghz_protocol_encoder_chamb_code_free, | ||||||
|  | 
 | ||||||
|  |     .deserialize = subghz_protocol_encoder_chamb_code_deserialize, | ||||||
|  |     .stop = subghz_protocol_encoder_chamb_code_stop, | ||||||
|  |     .yield = subghz_protocol_encoder_chamb_code_yield, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const SubGhzProtocol subghz_protocol_chamb_code = { | ||||||
|  |     .name = SUBGHZ_PROTOCOL_CHAMB_CODE_NAME, | ||||||
|  |     .type = SubGhzProtocolTypeStatic, | ||||||
|  |     .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | | ||||||
|  |             SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, | ||||||
|  | 
 | ||||||
|  |     .decoder = &subghz_protocol_chamb_code_decoder, | ||||||
|  |     .encoder = &subghz_protocol_chamb_code_encoder, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void* subghz_protocol_encoder_chamb_code_alloc(SubGhzEnvironment* environment) { | ||||||
|  |     UNUSED(environment); | ||||||
|  |     SubGhzProtocolEncoderChamb_Code* instance = malloc(sizeof(SubGhzProtocolEncoderChamb_Code)); | ||||||
|  | 
 | ||||||
|  |     instance->base.protocol = &subghz_protocol_chamb_code; | ||||||
|  |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
|  | 
 | ||||||
|  |     instance->encoder.repeat = 10; | ||||||
|  |     instance->encoder.size_upload = 24; | ||||||
|  |     instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); | ||||||
|  |     instance->encoder.is_runing = false; | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_chamb_code_free(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolEncoderChamb_Code* instance = context; | ||||||
|  |     free(instance->encoder.upload); | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint64_t subghz_protocol_chamb_bit_to_code(uint64_t data, uint8_t size) { | ||||||
|  |     uint64_t data_res = 0; | ||||||
|  |     for(uint8_t i = 0; i < size; i++) { | ||||||
|  |         if(!(bit_read(data, size - i - 1))) { | ||||||
|  |             data_res = data_res << 4 | CHAMBERLAIN_CODE_BIT_0; | ||||||
|  |         } else { | ||||||
|  |             data_res = data_res << 4 | CHAMBERLAIN_CODE_BIT_1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return data_res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Generating an upload from data. | ||||||
|  |  * @param instance Pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | static bool | ||||||
|  |     subghz_protocol_encoder_chamb_code_get_upload(SubGhzProtocolEncoderChamb_Code* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  | 
 | ||||||
|  |     uint64_t data = subghz_protocol_chamb_bit_to_code( | ||||||
|  |         instance->generic.data, instance->generic.data_count_bit); | ||||||
|  | 
 | ||||||
|  |     switch(instance->generic.data_count_bit) { | ||||||
|  |     case 7: | ||||||
|  |         data = ((data >> 4) << 16) | (data & 0xF) << 4 | CHAMBERLAIN_7_CODE_MASK_CHECK; | ||||||
|  |         break; | ||||||
|  |     case 8: | ||||||
|  |         data = ((data >> 12) << 16) | (data & 0xFF) << 4 | CHAMBERLAIN_8_CODE_MASK_CHECK; | ||||||
|  |         break; | ||||||
|  |     case 9: | ||||||
|  |         data = (data << 4) | CHAMBERLAIN_9_CODE_MASK_CHECK; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         furi_crash(TAG " unknown protocol."); | ||||||
|  |         return false; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | #define UPLOAD_HEX_DATA_SIZE 10 | ||||||
|  |     uint8_t upload_hex_data[UPLOAD_HEX_DATA_SIZE] = {0}; | ||||||
|  |     size_t upload_hex_count_bit = 0; | ||||||
|  | 
 | ||||||
|  |     //insert guard time
 | ||||||
|  |     for(uint8_t i = 0; i < 36; i++) { | ||||||
|  |         subghz_protocol_blocks_set_bit_array( | ||||||
|  |             0, upload_hex_data, upload_hex_count_bit++, UPLOAD_HEX_DATA_SIZE); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //insert data
 | ||||||
|  |     switch(instance->generic.data_count_bit) { | ||||||
|  |     case 7: | ||||||
|  |     case 9: | ||||||
|  |         for(uint8_t i = 44; i > 0; i--) { | ||||||
|  |             if(!bit_read(data, i - 1)) { | ||||||
|  |                 subghz_protocol_blocks_set_bit_array( | ||||||
|  |                     0, upload_hex_data, upload_hex_count_bit++, UPLOAD_HEX_DATA_SIZE); | ||||||
|  |             } else { | ||||||
|  |                 subghz_protocol_blocks_set_bit_array( | ||||||
|  |                     1, upload_hex_data, upload_hex_count_bit++, UPLOAD_HEX_DATA_SIZE); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case 8: | ||||||
|  |         for(uint8_t i = 40; i > 0; i--) { | ||||||
|  |             if(!bit_read(data, i - 1)) { | ||||||
|  |                 subghz_protocol_blocks_set_bit_array( | ||||||
|  |                     0, upload_hex_data, upload_hex_count_bit++, UPLOAD_HEX_DATA_SIZE); | ||||||
|  |             } else { | ||||||
|  |                 subghz_protocol_blocks_set_bit_array( | ||||||
|  |                     1, upload_hex_data, upload_hex_count_bit++, UPLOAD_HEX_DATA_SIZE); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     instance->encoder.size_upload = subghz_protocol_blocks_get_upload( | ||||||
|  |         upload_hex_data, | ||||||
|  |         upload_hex_count_bit, | ||||||
|  |         instance->encoder.upload, | ||||||
|  |         instance->encoder.size_upload, | ||||||
|  |         subghz_protocol_chamb_code_const.te_short); | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolEncoderChamb_Code* instance = context; | ||||||
|  |     bool res = false; | ||||||
|  |     do { | ||||||
|  |         if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { | ||||||
|  |             FURI_LOG_E(TAG, "Deserialize error"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //optional parameter parameter
 | ||||||
|  |         flipper_format_read_uint32( | ||||||
|  |             flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); | ||||||
|  | 
 | ||||||
|  |         subghz_protocol_encoder_chamb_code_get_upload(instance); | ||||||
|  |         instance->encoder.is_runing = true; | ||||||
|  | 
 | ||||||
|  |         res = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_encoder_chamb_code_stop(void* context) { | ||||||
|  |     SubGhzProtocolEncoderChamb_Code* instance = context; | ||||||
|  |     instance->encoder.is_runing = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LevelDuration subghz_protocol_encoder_chamb_code_yield(void* context) { | ||||||
|  |     SubGhzProtocolEncoderChamb_Code* instance = context; | ||||||
|  | 
 | ||||||
|  |     if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { | ||||||
|  |         instance->encoder.is_runing = false; | ||||||
|  |         return level_duration_reset(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     LevelDuration ret = instance->encoder.upload[instance->encoder.front]; | ||||||
|  | 
 | ||||||
|  |     if(++instance->encoder.front == instance->encoder.size_upload) { | ||||||
|  |         instance->encoder.repeat--; | ||||||
|  |         instance->encoder.front = 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void* subghz_protocol_decoder_chamb_code_alloc(SubGhzEnvironment* environment) { | ||||||
|  |     UNUSED(environment); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = malloc(sizeof(SubGhzProtocolDecoderChamb_Code)); | ||||||
|  |     instance->base.protocol = &subghz_protocol_chamb_code; | ||||||
|  |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
|  |     return instance; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_chamb_code_free(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     free(instance); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_chamb_code_reset(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_protocol_chamb_code_to_bit(uint64_t* data, uint8_t size) { | ||||||
|  |     uint64_t data_tmp = data[0]; | ||||||
|  |     uint64_t data_res = 0; | ||||||
|  |     for(uint8_t i = 0; i < size; i++) { | ||||||
|  |         if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_0) { | ||||||
|  |             bit_write(data_res, i, 0); | ||||||
|  |         } else if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_1) { | ||||||
|  |             bit_write(data_res, i, 1); | ||||||
|  |         } else { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         data_tmp >>= 4; | ||||||
|  |     } | ||||||
|  |     data[0] = data_res; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_protocol_decoder_chamb_code_check_mask_and_parse( | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     if(instance->decoder.decode_count_bit > | ||||||
|  |        subghz_protocol_chamb_code_const.min_count_bit_for_found + 1) | ||||||
|  |         return false; | ||||||
|  | 
 | ||||||
|  |     if((instance->decoder.decode_data & CHAMBERLAIN_7_CODE_MASK) == | ||||||
|  |        CHAMBERLAIN_7_CODE_MASK_CHECK) { | ||||||
|  |         instance->decoder.decode_count_bit = 7; | ||||||
|  |         instance->decoder.decode_data &= ~CHAMBERLAIN_7_CODE_MASK; | ||||||
|  |         instance->decoder.decode_data = (instance->decoder.decode_data >> 12) | | ||||||
|  |                                         ((instance->decoder.decode_data >> 4) & 0xF); | ||||||
|  |     } else if( | ||||||
|  |         (instance->decoder.decode_data & CHAMBERLAIN_8_CODE_MASK) == | ||||||
|  |         CHAMBERLAIN_8_CODE_MASK_CHECK) { | ||||||
|  |         instance->decoder.decode_count_bit = 8; | ||||||
|  |         instance->decoder.decode_data &= ~CHAMBERLAIN_8_CODE_MASK; | ||||||
|  |         instance->decoder.decode_data = instance->decoder.decode_data >> 4 | | ||||||
|  |                                         CHAMBERLAIN_CODE_BIT_0 << 8; //DIP 6 no use
 | ||||||
|  |     } else if( | ||||||
|  |         (instance->decoder.decode_data & CHAMBERLAIN_9_CODE_MASK) == | ||||||
|  |         CHAMBERLAIN_9_CODE_MASK_CHECK) { | ||||||
|  |         instance->decoder.decode_count_bit = 9; | ||||||
|  |         instance->decoder.decode_data &= ~CHAMBERLAIN_9_CODE_MASK; | ||||||
|  |         instance->decoder.decode_data >>= 4; | ||||||
|  |     } else { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     return subghz_protocol_chamb_code_to_bit( | ||||||
|  |         &instance->decoder.decode_data, instance->decoder.decode_count_bit); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_chamb_code_feed(void* context, bool level, uint32_t duration) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     switch(instance->decoder.parser_step) { | ||||||
|  |     case Chamb_CodeDecoderStepReset: | ||||||
|  |         if((!level) && (DURATION_DIFF(duration, subghz_protocol_chamb_code_const.te_short * 39) < | ||||||
|  |                         subghz_protocol_chamb_code_const.te_delta * 20)) { | ||||||
|  |             //Found header Chamb_Code
 | ||||||
|  |             instance->decoder.parser_step = Chamb_CodeDecoderStepFoundStartBit; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case Chamb_CodeDecoderStepFoundStartBit: | ||||||
|  |         if((level) && (DURATION_DIFF(duration, subghz_protocol_chamb_code_const.te_short) < | ||||||
|  |                        subghz_protocol_chamb_code_const.te_delta)) { | ||||||
|  |             //Found start bit Chamb_Code
 | ||||||
|  |             instance->decoder.decode_data = 0; | ||||||
|  |             instance->decoder.decode_count_bit = 0; | ||||||
|  |             instance->decoder.decode_data = instance->decoder.decode_data << 4 | | ||||||
|  |                                             CHAMBERLAIN_CODE_BIT_STOP; | ||||||
|  |             instance->decoder.decode_count_bit++; | ||||||
|  |             instance->decoder.parser_step = Chamb_CodeDecoderStepSaveDuration; | ||||||
|  |         } else { | ||||||
|  |             instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case Chamb_CodeDecoderStepSaveDuration: | ||||||
|  |         if(!level) { //save interval
 | ||||||
|  |             if(duration > subghz_protocol_chamb_code_const.te_short * 5) { | ||||||
|  |                 if(instance->decoder.decode_count_bit >= | ||||||
|  |                    subghz_protocol_chamb_code_const.min_count_bit_for_found) { | ||||||
|  |                     instance->generic.serial = 0x0; | ||||||
|  |                     instance->generic.btn = 0x0; | ||||||
|  |                     if(subghz_protocol_decoder_chamb_code_check_mask_and_parse(instance)) { | ||||||
|  |                         instance->generic.data = instance->decoder.decode_data; | ||||||
|  |                         instance->generic.data_count_bit = instance->decoder.decode_count_bit; | ||||||
|  |                         if(instance->base.callback) | ||||||
|  |                             instance->base.callback(&instance->base, instance->base.context); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  |             } else { | ||||||
|  |                 instance->decoder.te_last = duration; | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepCheckDuration; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case Chamb_CodeDecoderStepCheckDuration: | ||||||
|  |         if(level) { | ||||||
|  |             if((DURATION_DIFF( //Found stop bit Chamb_Code
 | ||||||
|  |                     instance->decoder.te_last, | ||||||
|  |                     subghz_protocol_chamb_code_const.te_short * 3) < | ||||||
|  |                 subghz_protocol_chamb_code_const.te_delta) && | ||||||
|  |                (DURATION_DIFF(duration, subghz_protocol_chamb_code_const.te_short) < | ||||||
|  |                 subghz_protocol_chamb_code_const.te_delta)) { | ||||||
|  |                 instance->decoder.decode_data = instance->decoder.decode_data << 4 | | ||||||
|  |                                                 CHAMBERLAIN_CODE_BIT_STOP; | ||||||
|  |                 instance->decoder.decode_count_bit++; | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepSaveDuration; | ||||||
|  |             } else if( | ||||||
|  |                 (DURATION_DIFF( | ||||||
|  |                      instance->decoder.te_last, subghz_protocol_chamb_code_const.te_short * 2) < | ||||||
|  |                  subghz_protocol_chamb_code_const.te_delta) && | ||||||
|  |                 (DURATION_DIFF(duration, subghz_protocol_chamb_code_const.te_short * 2) < | ||||||
|  |                  subghz_protocol_chamb_code_const.te_delta)) { | ||||||
|  |                 instance->decoder.decode_data = instance->decoder.decode_data << 4 | | ||||||
|  |                                                 CHAMBERLAIN_CODE_BIT_1; | ||||||
|  |                 instance->decoder.decode_count_bit++; | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepSaveDuration; | ||||||
|  |             } else if( | ||||||
|  |                 (DURATION_DIFF( | ||||||
|  |                      instance->decoder.te_last, subghz_protocol_chamb_code_const.te_short) < | ||||||
|  |                  subghz_protocol_chamb_code_const.te_delta) && | ||||||
|  |                 (DURATION_DIFF(duration, subghz_protocol_chamb_code_const.te_short * 3) < | ||||||
|  |                  subghz_protocol_chamb_code_const.te_delta)) { | ||||||
|  |                 instance->decoder.decode_data = instance->decoder.decode_data << 4 | | ||||||
|  |                                                 CHAMBERLAIN_CODE_BIT_0; | ||||||
|  |                 instance->decoder.decode_count_bit++; | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepSaveDuration; | ||||||
|  |             } else { | ||||||
|  |                 instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } else { | ||||||
|  |             instance->decoder.parser_step = Chamb_CodeDecoderStepReset; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     return subghz_protocol_blocks_get_hash_data( | ||||||
|  |         &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_decoder_chamb_code_serialize( | ||||||
|  |     void* context, | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  |     return subghz_block_generic_deserialize(&instance->generic, flipper_format); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t output) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     SubGhzProtocolDecoderChamb_Code* instance = context; | ||||||
|  | 
 | ||||||
|  |     uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; | ||||||
|  | 
 | ||||||
|  |     uint64_t code_found_reverse = subghz_protocol_blocks_reverse_key( | ||||||
|  |         instance->generic.data, instance->generic.data_count_bit); | ||||||
|  | 
 | ||||||
|  |     uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; | ||||||
|  | 
 | ||||||
|  |     string_cat_printf( | ||||||
|  |         output, | ||||||
|  |         "%s %db\r\n" | ||||||
|  |         "Key:0x%03lX\r\n" | ||||||
|  |         "Yek:0x%03lX\r\n", | ||||||
|  |         instance->generic.protocol_name, | ||||||
|  |         instance->generic.data_count_bit, | ||||||
|  |         code_found_lo, | ||||||
|  |         code_found_reverse_lo); | ||||||
|  | 
 | ||||||
|  |     switch(instance->generic.data_count_bit) { | ||||||
|  |     case 7: | ||||||
|  |         string_cat_printf( | ||||||
|  |             output, | ||||||
|  |             "DIP:" CHAMBERLAIN_7_CODE_DIP_PATTERN "\r\n", | ||||||
|  |             CHAMBERLAIN_7_CODE_DATA_TO_DIP(code_found_lo)); | ||||||
|  |         break; | ||||||
|  |     case 8: | ||||||
|  |         string_cat_printf( | ||||||
|  |             output, | ||||||
|  |             "DIP:" CHAMBERLAIN_8_CODE_DIP_PATTERN "\r\n", | ||||||
|  |             CHAMBERLAIN_8_CODE_DATA_TO_DIP(code_found_lo)); | ||||||
|  |         break; | ||||||
|  |     case 9: | ||||||
|  |         string_cat_printf( | ||||||
|  |             output, | ||||||
|  |             "DIP:" CHAMBERLAIN_9_CODE_DIP_PATTERN "\r\n", | ||||||
|  |             CHAMBERLAIN_9_CODE_DATA_TO_DIP(code_found_lo)); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										109
									
								
								lib/subghz/protocols/chamberlain_code.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/subghz/protocols/chamberlain_code.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "base.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_PROTOCOL_CHAMB_CODE_NAME "Cham_Code" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzProtocolDecoderChamb_Code SubGhzProtocolDecoderChamb_Code; | ||||||
|  | typedef struct SubGhzProtocolEncoderChamb_Code SubGhzProtocolEncoderChamb_Code; | ||||||
|  | 
 | ||||||
|  | extern const SubGhzProtocolDecoder subghz_protocol_chamb_code_decoder; | ||||||
|  | extern const SubGhzProtocolEncoder subghz_protocol_chamb_code_encoder; | ||||||
|  | extern const SubGhzProtocol subghz_protocol_chamb_code; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolEncoderChamb_Code. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolEncoderChamb_Code* pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_encoder_chamb_code_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolEncoderChamb_Code. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_chamb_code_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize and generating an upload to send. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Forced transmission stop. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_chamb_code_stop(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the level and duration of the upload to be loaded into DMA. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderChamb_Code instance | ||||||
|  |  * @return LevelDuration  | ||||||
|  |  */ | ||||||
|  | LevelDuration subghz_protocol_encoder_chamb_code_yield(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolDecoderChamb_Code. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolDecoderChamb_Code* pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_decoder_chamb_code_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolDecoderChamb_Code. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_chamb_code_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Reset decoder SubGhzProtocolDecoderChamb_Code. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_chamb_code_reset(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Parse a raw sequence of levels and durations received from the air. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  * @param level Signal level true-high false-low | ||||||
|  |  * @param duration Duration of this level in, us | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_chamb_code_feed(void* context, bool level, uint32_t duration); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the hash sum of the last randomly received parcel. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  * @return hash Hash sum | ||||||
|  |  */ | ||||||
|  | uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Serialize data SubGhzProtocolDecoderChamb_Code. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @param frequency The frequency at which the signal was received, Hz | ||||||
|  |  * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_decoder_chamb_code_serialize( | ||||||
|  |     void* context, | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize data SubGhzProtocolDecoderChamb_Code. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting a textual representation of the received data. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance | ||||||
|  |  * @param output Resulting text | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_chamb_code_get_string(void* context, string_t output); | ||||||
| @ -1,109 +0,0 @@ | |||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "base.h" |  | ||||||
| 
 |  | ||||||
| #define SUBGHZ_PROTOCOL_FIREFLY_NAME "Firefly" |  | ||||||
| 
 |  | ||||||
| typedef struct SubGhzProtocolDecoderFirefly SubGhzProtocolDecoderFirefly; |  | ||||||
| typedef struct SubGhzProtocolEncoderFirefly SubGhzProtocolEncoderFirefly; |  | ||||||
| 
 |  | ||||||
| extern const SubGhzProtocolDecoder subghz_protocol_firefly_decoder; |  | ||||||
| extern const SubGhzProtocolEncoder subghz_protocol_firefly_encoder; |  | ||||||
| extern const SubGhzProtocol subghz_protocol_firefly; |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Allocate SubGhzProtocolEncoderFirefly. |  | ||||||
|  * @param environment Pointer to a SubGhzEnvironment instance |  | ||||||
|  * @return SubGhzProtocolEncoderFirefly* pointer to a SubGhzProtocolEncoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Free SubGhzProtocolEncoderFirefly. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolEncoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_encoder_firefly_free(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Deserialize and generating an upload to send. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolEncoderFirefly instance |  | ||||||
|  * @param flipper_format Pointer to a FlipperFormat instance |  | ||||||
|  * @return true On success |  | ||||||
|  */ |  | ||||||
| bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Forced transmission stop. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolEncoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_encoder_firefly_stop(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Getting the level and duration of the upload to be loaded into DMA. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolEncoderFirefly instance |  | ||||||
|  * @return LevelDuration  |  | ||||||
|  */ |  | ||||||
| LevelDuration subghz_protocol_encoder_firefly_yield(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Allocate SubGhzProtocolDecoderFirefly. |  | ||||||
|  * @param environment Pointer to a SubGhzEnvironment instance |  | ||||||
|  * @return SubGhzProtocolDecoderFirefly* pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Free SubGhzProtocolDecoderFirefly. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_decoder_firefly_free(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Reset decoder SubGhzProtocolDecoderFirefly. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_decoder_firefly_reset(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Parse a raw sequence of levels and durations received from the air. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  * @param level Signal level true-high false-low |  | ||||||
|  * @param duration Duration of this level in, us |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Getting the hash sum of the last randomly received parcel. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  * @return hash Hash sum |  | ||||||
|  */ |  | ||||||
| uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Serialize data SubGhzProtocolDecoderFirefly. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  * @param flipper_format Pointer to a FlipperFormat instance |  | ||||||
|  * @param frequency The frequency at which the signal was received, Hz |  | ||||||
|  * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset |  | ||||||
|  * @return true On success |  | ||||||
|  */ |  | ||||||
| bool subghz_protocol_decoder_firefly_serialize( |  | ||||||
|     void* context, |  | ||||||
|     FlipperFormat* flipper_format, |  | ||||||
|     uint32_t frequency, |  | ||||||
|     FuriHalSubGhzPreset preset); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Deserialize data SubGhzProtocolDecoderFirefly. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  * @param flipper_format Pointer to a FlipperFormat instance |  | ||||||
|  * @return true On success |  | ||||||
|  */ |  | ||||||
| bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * Getting a textual representation of the received data. |  | ||||||
|  * @param context Pointer to a SubGhzProtocolDecoderFirefly instance |  | ||||||
|  * @param output Resulting text |  | ||||||
|  */ |  | ||||||
| void subghz_protocol_decoder_firefly_get_string(void* context, string_t output); |  | ||||||
| @ -1,4 +1,4 @@ | |||||||
| #include "firefly.h" | #include "linear.h" | ||||||
| 
 | 
 | ||||||
| #include "../blocks/const.h" | #include "../blocks/const.h" | ||||||
| #include "../blocks/decoder.h" | #include "../blocks/decoder.h" | ||||||
| @ -6,7 +6,7 @@ | |||||||
| #include "../blocks/generic.h" | #include "../blocks/generic.h" | ||||||
| #include "../blocks/math.h" | #include "../blocks/math.h" | ||||||
| 
 | 
 | ||||||
| #define TAG "SubGhzProtocolFirefly" | #define TAG "SubGhzProtocolLinear" | ||||||
| 
 | 
 | ||||||
| #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c" | #define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c" | ||||||
| #define DATA_TO_DIP(dip)                                                                    \ | #define DATA_TO_DIP(dip)                                                                    \ | ||||||
| @ -15,21 +15,21 @@ | |||||||
|         (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \ |         (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \ | ||||||
|         (dip & 0x0001 ? '1' : '0') |         (dip & 0x0001 ? '1' : '0') | ||||||
| 
 | 
 | ||||||
| static const SubGhzBlockConst subghz_protocol_firefly_const = { | static const SubGhzBlockConst subghz_protocol_linear_const = { | ||||||
|     .te_short = 500, |     .te_short = 500, | ||||||
|     .te_long = 1500, |     .te_long = 1500, | ||||||
|     .te_delta = 150, |     .te_delta = 150, | ||||||
|     .min_count_bit_for_found = 10, |     .min_count_bit_for_found = 10, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SubGhzProtocolDecoderFirefly { | struct SubGhzProtocolDecoderLinear { | ||||||
|     SubGhzProtocolDecoderBase base; |     SubGhzProtocolDecoderBase base; | ||||||
| 
 | 
 | ||||||
|     SubGhzBlockDecoder decoder; |     SubGhzBlockDecoder decoder; | ||||||
|     SubGhzBlockGeneric generic; |     SubGhzBlockGeneric generic; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SubGhzProtocolEncoderFirefly { | struct SubGhzProtocolEncoderLinear { | ||||||
|     SubGhzProtocolEncoderBase base; |     SubGhzProtocolEncoderBase base; | ||||||
| 
 | 
 | ||||||
|     SubGhzProtocolBlockEncoder encoder; |     SubGhzProtocolBlockEncoder encoder; | ||||||
| @ -37,48 +37,48 @@ struct SubGhzProtocolEncoderFirefly { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     FireflyDecoderStepReset = 0, |     LinearDecoderStepReset = 0, | ||||||
|     FireflyDecoderStepSaveDuration, |     LinearDecoderStepSaveDuration, | ||||||
|     FireflyDecoderStepCheckDuration, |     LinearDecoderStepCheckDuration, | ||||||
| } FireflyDecoderStep; | } LinearDecoderStep; | ||||||
| 
 | 
 | ||||||
| const SubGhzProtocolDecoder subghz_protocol_firefly_decoder = { | const SubGhzProtocolDecoder subghz_protocol_linear_decoder = { | ||||||
|     .alloc = subghz_protocol_decoder_firefly_alloc, |     .alloc = subghz_protocol_decoder_linear_alloc, | ||||||
|     .free = subghz_protocol_decoder_firefly_free, |     .free = subghz_protocol_decoder_linear_free, | ||||||
| 
 | 
 | ||||||
|     .feed = subghz_protocol_decoder_firefly_feed, |     .feed = subghz_protocol_decoder_linear_feed, | ||||||
|     .reset = subghz_protocol_decoder_firefly_reset, |     .reset = subghz_protocol_decoder_linear_reset, | ||||||
| 
 | 
 | ||||||
|     .get_hash_data = subghz_protocol_decoder_firefly_get_hash_data, |     .get_hash_data = subghz_protocol_decoder_linear_get_hash_data, | ||||||
|     .serialize = subghz_protocol_decoder_firefly_serialize, |     .serialize = subghz_protocol_decoder_linear_serialize, | ||||||
|     .deserialize = subghz_protocol_decoder_firefly_deserialize, |     .deserialize = subghz_protocol_decoder_linear_deserialize, | ||||||
|     .get_string = subghz_protocol_decoder_firefly_get_string, |     .get_string = subghz_protocol_decoder_linear_get_string, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SubGhzProtocolEncoder subghz_protocol_firefly_encoder = { | const SubGhzProtocolEncoder subghz_protocol_linear_encoder = { | ||||||
|     .alloc = subghz_protocol_encoder_firefly_alloc, |     .alloc = subghz_protocol_encoder_linear_alloc, | ||||||
|     .free = subghz_protocol_encoder_firefly_free, |     .free = subghz_protocol_encoder_linear_free, | ||||||
| 
 | 
 | ||||||
|     .deserialize = subghz_protocol_encoder_firefly_deserialize, |     .deserialize = subghz_protocol_encoder_linear_deserialize, | ||||||
|     .stop = subghz_protocol_encoder_firefly_stop, |     .stop = subghz_protocol_encoder_linear_stop, | ||||||
|     .yield = subghz_protocol_encoder_firefly_yield, |     .yield = subghz_protocol_encoder_linear_yield, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SubGhzProtocol subghz_protocol_firefly = { | const SubGhzProtocol subghz_protocol_linear = { | ||||||
|     .name = SUBGHZ_PROTOCOL_FIREFLY_NAME, |     .name = SUBGHZ_PROTOCOL_LINEAR_NAME, | ||||||
|     .type = SubGhzProtocolTypeStatic, |     .type = SubGhzProtocolTypeStatic, | ||||||
|     .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | |     .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | | ||||||
|             SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, |             SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, | ||||||
| 
 | 
 | ||||||
|     .decoder = &subghz_protocol_firefly_decoder, |     .decoder = &subghz_protocol_linear_decoder, | ||||||
|     .encoder = &subghz_protocol_firefly_encoder, |     .encoder = &subghz_protocol_linear_encoder, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) { | void* subghz_protocol_encoder_linear_alloc(SubGhzEnvironment* environment) { | ||||||
|     UNUSED(environment); |     UNUSED(environment); | ||||||
|     SubGhzProtocolEncoderFirefly* instance = malloc(sizeof(SubGhzProtocolEncoderFirefly)); |     SubGhzProtocolEncoderLinear* instance = malloc(sizeof(SubGhzProtocolEncoderLinear)); | ||||||
| 
 | 
 | ||||||
|     instance->base.protocol = &subghz_protocol_firefly; |     instance->base.protocol = &subghz_protocol_linear; | ||||||
|     instance->generic.protocol_name = instance->base.protocol->name; |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
| 
 | 
 | ||||||
|     instance->encoder.repeat = 10; |     instance->encoder.repeat = 10; | ||||||
| @ -88,19 +88,19 @@ void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) { | |||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_encoder_firefly_free(void* context) { | void subghz_protocol_encoder_linear_free(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolEncoderFirefly* instance = context; |     SubGhzProtocolEncoderLinear* instance = context; | ||||||
|     free(instance->encoder.upload); |     free(instance->encoder.upload); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Generating an upload from data. |  * Generating an upload from data. | ||||||
|  * @param instance Pointer to a SubGhzProtocolEncoderFirefly instance |  * @param instance Pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  * @return true On success |  * @return true On success | ||||||
|  */ |  */ | ||||||
| static bool subghz_protocol_encoder_firefly_get_upload(SubGhzProtocolEncoderFirefly* instance) { | static bool subghz_protocol_encoder_linear_get_upload(SubGhzProtocolEncoderLinear* instance) { | ||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     size_t index = 0; |     size_t index = 0; | ||||||
|     size_t size_upload = (instance->generic.data_count_bit * 2); |     size_t size_upload = (instance->generic.data_count_bit * 2); | ||||||
| @ -116,40 +116,40 @@ static bool subghz_protocol_encoder_firefly_get_upload(SubGhzProtocolEncoderFire | |||||||
|         if(bit_read(instance->generic.data, i - 1)) { |         if(bit_read(instance->generic.data, i - 1)) { | ||||||
|             //send bit 1
 |             //send bit 1
 | ||||||
|             instance->encoder.upload[index++] = |             instance->encoder.upload[index++] = | ||||||
|                 level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); |                 level_duration_make(true, (uint32_t)subghz_protocol_linear_const.te_short * 3); | ||||||
|             instance->encoder.upload[index++] = |             instance->encoder.upload[index++] = | ||||||
|                 level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short); |                 level_duration_make(false, (uint32_t)subghz_protocol_linear_const.te_short); | ||||||
|         } else { |         } else { | ||||||
|             //send bit 0
 |             //send bit 0
 | ||||||
|             instance->encoder.upload[index++] = |             instance->encoder.upload[index++] = | ||||||
|                 level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); |                 level_duration_make(true, (uint32_t)subghz_protocol_linear_const.te_short); | ||||||
|             instance->encoder.upload[index++] = |             instance->encoder.upload[index++] = | ||||||
|                 level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 3); |                 level_duration_make(false, (uint32_t)subghz_protocol_linear_const.te_short * 3); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     //Send end bit
 |     //Send end bit
 | ||||||
|     if(bit_read(instance->generic.data, 0)) { |     if(bit_read(instance->generic.data, 0)) { | ||||||
|         //send bit 1
 |         //send bit 1
 | ||||||
|         instance->encoder.upload[index++] = |         instance->encoder.upload[index++] = | ||||||
|             level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); |             level_duration_make(true, (uint32_t)subghz_protocol_linear_const.te_short * 3); | ||||||
|         //Send PT_GUARD
 |         //Send PT_GUARD
 | ||||||
|         instance->encoder.upload[index++] = |         instance->encoder.upload[index++] = | ||||||
|             level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 42); |             level_duration_make(false, (uint32_t)subghz_protocol_linear_const.te_short * 42); | ||||||
|     } else { |     } else { | ||||||
|         //send bit 0
 |         //send bit 0
 | ||||||
|         instance->encoder.upload[index++] = |         instance->encoder.upload[index++] = | ||||||
|             level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); |             level_duration_make(true, (uint32_t)subghz_protocol_linear_const.te_short); | ||||||
|         //Send PT_GUARD
 |         //Send PT_GUARD
 | ||||||
|         instance->encoder.upload[index++] = |         instance->encoder.upload[index++] = | ||||||
|             level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 44); |             level_duration_make(false, (uint32_t)subghz_protocol_linear_const.te_short * 44); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { | bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolEncoderFirefly* instance = context; |     SubGhzProtocolEncoderLinear* instance = context; | ||||||
|     bool res = false; |     bool res = false; | ||||||
|     do { |     do { | ||||||
|         if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { |         if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { | ||||||
| @ -161,7 +161,7 @@ bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* f | |||||||
|         flipper_format_read_uint32( |         flipper_format_read_uint32( | ||||||
|             flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); |             flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); | ||||||
| 
 | 
 | ||||||
|         subghz_protocol_encoder_firefly_get_upload(instance); |         subghz_protocol_encoder_linear_get_upload(instance); | ||||||
|         instance->encoder.is_runing = true; |         instance->encoder.is_runing = true; | ||||||
| 
 | 
 | ||||||
|         res = true; |         res = true; | ||||||
| @ -170,13 +170,13 @@ bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* f | |||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_encoder_firefly_stop(void* context) { | void subghz_protocol_encoder_linear_stop(void* context) { | ||||||
|     SubGhzProtocolEncoderFirefly* instance = context; |     SubGhzProtocolEncoderLinear* instance = context; | ||||||
|     instance->encoder.is_runing = false; |     instance->encoder.is_runing = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LevelDuration subghz_protocol_encoder_firefly_yield(void* context) { | LevelDuration subghz_protocol_encoder_linear_yield(void* context) { | ||||||
|     SubGhzProtocolEncoderFirefly* instance = context; |     SubGhzProtocolEncoderLinear* instance = context; | ||||||
| 
 | 
 | ||||||
|     if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { |     if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { | ||||||
|         instance->encoder.is_runing = false; |         instance->encoder.is_runing = false; | ||||||
| @ -193,68 +193,66 @@ LevelDuration subghz_protocol_encoder_firefly_yield(void* context) { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment) { | void* subghz_protocol_decoder_linear_alloc(SubGhzEnvironment* environment) { | ||||||
|     UNUSED(environment); |     UNUSED(environment); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = malloc(sizeof(SubGhzProtocolDecoderFirefly)); |     SubGhzProtocolDecoderLinear* instance = malloc(sizeof(SubGhzProtocolDecoderLinear)); | ||||||
|     instance->base.protocol = &subghz_protocol_firefly; |     instance->base.protocol = &subghz_protocol_linear; | ||||||
|     instance->generic.protocol_name = instance->base.protocol->name; |     instance->generic.protocol_name = instance->base.protocol->name; | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_decoder_firefly_free(void* context) { | void subghz_protocol_decoder_linear_free(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_decoder_firefly_reset(void* context) { | void subghz_protocol_decoder_linear_reset(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     instance->decoder.parser_step = FireflyDecoderStepReset; |     instance->decoder.parser_step = LinearDecoderStepReset; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration) { | void subghz_protocol_decoder_linear_feed(void* context, bool level, uint32_t duration) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     switch(instance->decoder.parser_step) { |     switch(instance->decoder.parser_step) { | ||||||
|     case FireflyDecoderStepReset: |     case LinearDecoderStepReset: | ||||||
|         if((!level) && (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) < |         if((!level) && (DURATION_DIFF(duration, subghz_protocol_linear_const.te_short * 42) < | ||||||
|                         subghz_protocol_firefly_const.te_delta * 20)) { |                         subghz_protocol_linear_const.te_delta * 20)) { | ||||||
|             //Found header Firefly
 |             //Found header Linear
 | ||||||
|             instance->decoder.decode_data = 0; |             instance->decoder.decode_data = 0; | ||||||
|             instance->decoder.decode_count_bit = 0; |             instance->decoder.decode_count_bit = 0; | ||||||
|             instance->decoder.parser_step = FireflyDecoderStepSaveDuration; |             instance->decoder.parser_step = LinearDecoderStepSaveDuration; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FireflyDecoderStepSaveDuration: |     case LinearDecoderStepSaveDuration: | ||||||
|         if(level) { |         if(level) { | ||||||
|             instance->decoder.te_last = duration; |             instance->decoder.te_last = duration; | ||||||
|             instance->decoder.parser_step = FireflyDecoderStepCheckDuration; |             instance->decoder.parser_step = LinearDecoderStepCheckDuration; | ||||||
|         } else { |         } else { | ||||||
|             instance->decoder.parser_step = FireflyDecoderStepReset; |             instance->decoder.parser_step = LinearDecoderStepReset; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     case FireflyDecoderStepCheckDuration: |     case LinearDecoderStepCheckDuration: | ||||||
|         if(!level) { //save interval
 |         if(!level) { //save interval
 | ||||||
|             if(duration >= (subghz_protocol_firefly_const.te_short * 5)) { |             if(duration >= (subghz_protocol_linear_const.te_short * 5)) { | ||||||
|                 instance->decoder.parser_step = FireflyDecoderStepReset; |                 instance->decoder.parser_step = LinearDecoderStepReset; | ||||||
|                 //checking that the duration matches the guardtime
 |                 //checking that the duration matches the guardtime
 | ||||||
|                 if((DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) > |                 if((DURATION_DIFF(duration, subghz_protocol_linear_const.te_short * 42) > | ||||||
|                     subghz_protocol_firefly_const.te_delta * 20)) { |                     subghz_protocol_linear_const.te_delta * 20)) { | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 if(DURATION_DIFF( |                 if(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_linear_const.te_short) < | ||||||
|                        instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < |                    subghz_protocol_linear_const.te_delta) { | ||||||
|                    subghz_protocol_firefly_const.te_delta) { |  | ||||||
|                     subghz_protocol_blocks_add_bit(&instance->decoder, 0); |                     subghz_protocol_blocks_add_bit(&instance->decoder, 0); | ||||||
|                 } else if( |                 } else if( | ||||||
|                     DURATION_DIFF( |                     DURATION_DIFF(instance->decoder.te_last, subghz_protocol_linear_const.te_long) < | ||||||
|                         instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < |                     subghz_protocol_linear_const.te_delta) { | ||||||
|                     subghz_protocol_firefly_const.te_delta) { |  | ||||||
|                     subghz_protocol_blocks_add_bit(&instance->decoder, 1); |                     subghz_protocol_blocks_add_bit(&instance->decoder, 1); | ||||||
|                 } |                 } | ||||||
|                 if(instance->decoder.decode_count_bit == |                 if(instance->decoder.decode_count_bit == | ||||||
|                    subghz_protocol_firefly_const.min_count_bit_for_found) { |                    subghz_protocol_linear_const.min_count_bit_for_found) { | ||||||
|                     instance->generic.serial = 0x0; |                     instance->generic.serial = 0x0; | ||||||
|                     instance->generic.btn = 0x0; |                     instance->generic.btn = 0x0; | ||||||
| 
 | 
 | ||||||
| @ -267,56 +265,56 @@ void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t du | |||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < |             if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_linear_const.te_short) < | ||||||
|                 subghz_protocol_firefly_const.te_delta) && |                 subghz_protocol_linear_const.te_delta) && | ||||||
|                (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_long) < |                (DURATION_DIFF(duration, subghz_protocol_linear_const.te_long) < | ||||||
|                 subghz_protocol_firefly_const.te_delta)) { |                 subghz_protocol_linear_const.te_delta)) { | ||||||
|                 subghz_protocol_blocks_add_bit(&instance->decoder, 0); |                 subghz_protocol_blocks_add_bit(&instance->decoder, 0); | ||||||
|                 instance->decoder.parser_step = FireflyDecoderStepSaveDuration; |                 instance->decoder.parser_step = LinearDecoderStepSaveDuration; | ||||||
|             } else if( |             } else if( | ||||||
|                 (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < |                 (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_linear_const.te_long) < | ||||||
|                  subghz_protocol_firefly_const.te_delta) && |                  subghz_protocol_linear_const.te_delta) && | ||||||
|                 (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short) < |                 (DURATION_DIFF(duration, subghz_protocol_linear_const.te_short) < | ||||||
|                  subghz_protocol_firefly_const.te_delta)) { |                  subghz_protocol_linear_const.te_delta)) { | ||||||
|                 subghz_protocol_blocks_add_bit(&instance->decoder, 1); |                 subghz_protocol_blocks_add_bit(&instance->decoder, 1); | ||||||
|                 instance->decoder.parser_step = FireflyDecoderStepSaveDuration; |                 instance->decoder.parser_step = LinearDecoderStepSaveDuration; | ||||||
|             } else { |             } else { | ||||||
|                 instance->decoder.parser_step = FireflyDecoderStepReset; |                 instance->decoder.parser_step = LinearDecoderStepReset; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|         } else { |         } else { | ||||||
|             instance->decoder.parser_step = FireflyDecoderStepReset; |             instance->decoder.parser_step = LinearDecoderStepReset; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context) { | uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     return subghz_protocol_blocks_get_hash_data( |     return subghz_protocol_blocks_get_hash_data( | ||||||
|         &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); |         &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_protocol_decoder_firefly_serialize( | bool subghz_protocol_decoder_linear_serialize( | ||||||
|     void* context, |     void* context, | ||||||
|     FlipperFormat* flipper_format, |     FlipperFormat* flipper_format, | ||||||
|     uint32_t frequency, |     uint32_t frequency, | ||||||
|     FuriHalSubGhzPreset preset) { |     FuriHalSubGhzPreset preset) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); |     return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { | bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
|     return subghz_block_generic_deserialize(&instance->generic, flipper_format); |     return subghz_block_generic_deserialize(&instance->generic, flipper_format); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_protocol_decoder_firefly_get_string(void* context, string_t output) { | void subghz_protocol_decoder_linear_get_string(void* context, string_t output) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     SubGhzProtocolDecoderFirefly* instance = context; |     SubGhzProtocolDecoderLinear* instance = context; | ||||||
| 
 | 
 | ||||||
|     uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; |     uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; | ||||||
| 
 | 
 | ||||||
							
								
								
									
										109
									
								
								lib/subghz/protocols/linear.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/subghz/protocols/linear.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "base.h" | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_PROTOCOL_LINEAR_NAME "Linear" | ||||||
|  | 
 | ||||||
|  | typedef struct SubGhzProtocolDecoderLinear SubGhzProtocolDecoderLinear; | ||||||
|  | typedef struct SubGhzProtocolEncoderLinear SubGhzProtocolEncoderLinear; | ||||||
|  | 
 | ||||||
|  | extern const SubGhzProtocolDecoder subghz_protocol_linear_decoder; | ||||||
|  | extern const SubGhzProtocolEncoder subghz_protocol_linear_encoder; | ||||||
|  | extern const SubGhzProtocol subghz_protocol_linear; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolEncoderLinear. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolEncoderLinear* pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_encoder_linear_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolEncoderLinear. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_linear_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize and generating an upload to send. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Forced transmission stop. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_encoder_linear_stop(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the level and duration of the upload to be loaded into DMA. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolEncoderLinear instance | ||||||
|  |  * @return LevelDuration  | ||||||
|  |  */ | ||||||
|  | LevelDuration subghz_protocol_encoder_linear_yield(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Allocate SubGhzProtocolDecoderLinear. | ||||||
|  |  * @param environment Pointer to a SubGhzEnvironment instance | ||||||
|  |  * @return SubGhzProtocolDecoderLinear* pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  */ | ||||||
|  | void* subghz_protocol_decoder_linear_alloc(SubGhzEnvironment* environment); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Free SubGhzProtocolDecoderLinear. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_linear_free(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Reset decoder SubGhzProtocolDecoderLinear. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_linear_reset(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Parse a raw sequence of levels and durations received from the air. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  * @param level Signal level true-high false-low | ||||||
|  |  * @param duration Duration of this level in, us | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_linear_feed(void* context, bool level, uint32_t duration); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting the hash sum of the last randomly received parcel. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  * @return hash Hash sum | ||||||
|  |  */ | ||||||
|  | uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Serialize data SubGhzProtocolDecoderLinear. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @param frequency The frequency at which the signal was received, Hz | ||||||
|  |  * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_decoder_linear_serialize( | ||||||
|  |     void* context, | ||||||
|  |     FlipperFormat* flipper_format, | ||||||
|  |     uint32_t frequency, | ||||||
|  |     FuriHalSubGhzPreset preset); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Deserialize data SubGhzProtocolDecoderLinear. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  * @param flipper_format Pointer to a FlipperFormat instance | ||||||
|  |  * @return true On success | ||||||
|  |  */ | ||||||
|  | bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Getting a textual representation of the received data. | ||||||
|  |  * @param context Pointer to a SubGhzProtocolDecoderLinear instance | ||||||
|  |  * @param output Resulting text | ||||||
|  |  */ | ||||||
|  | void subghz_protocol_decoder_linear_get_string(void* context, string_t output); | ||||||
| @ -247,7 +247,7 @@ void subghz_protocol_decoder_megacode_feed(void* context, bool level, uint32_t d | |||||||
|     switch(instance->decoder.parser_step) { |     switch(instance->decoder.parser_step) { | ||||||
|     case MegaCodeDecoderStepReset: |     case MegaCodeDecoderStepReset: | ||||||
|         if((!level) && (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short * 13) < |         if((!level) && (DURATION_DIFF(duration, subghz_protocol_megacode_const.te_short * 13) < | ||||||
|                         subghz_protocol_megacode_const.te_delta * 15)) { //10..16ms
 |                         subghz_protocol_megacode_const.te_delta * 17)) { //10..16ms
 | ||||||
|             //Found header MegaCode
 |             //Found header MegaCode
 | ||||||
|             instance->decoder.parser_step = MegaCodeDecoderStepFoundStartBit; |             instance->decoder.parser_step = MegaCodeDecoderStepFoundStartBit; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -7,8 +7,9 @@ const SubGhzProtocol* subghz_protocol_registry[] = { | |||||||
|     &subghz_protocol_nero_sketch,  &subghz_protocol_ido,        &subghz_protocol_kia, |     &subghz_protocol_nero_sketch,  &subghz_protocol_ido,        &subghz_protocol_kia, | ||||||
|     &subghz_protocol_hormann,      &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, |     &subghz_protocol_hormann,      &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, | ||||||
|     &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, |     &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, | ||||||
|     &subghz_protocol_raw,          &subghz_protocol_firefly,    &subghz_protocol_secplus_v2, |     &subghz_protocol_raw,          &subghz_protocol_linear,     &subghz_protocol_secplus_v2, | ||||||
|     &subghz_protocol_secplus_v1,   &subghz_protocol_megacode,   &subghz_protocol_holtek, |     &subghz_protocol_secplus_v1,   &subghz_protocol_megacode,   &subghz_protocol_holtek, | ||||||
|  |     &subghz_protocol_chamb_code, | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,11 +21,12 @@ | |||||||
| #include "scher_khan.h" | #include "scher_khan.h" | ||||||
| #include "gate_tx.h" | #include "gate_tx.h" | ||||||
| #include "raw.h" | #include "raw.h" | ||||||
| #include "firefly.h" | #include "linear.h" | ||||||
| #include "secplus_v2.h" | #include "secplus_v2.h" | ||||||
| #include "secplus_v1.h" | #include "secplus_v1.h" | ||||||
| #include "megacode.h" | #include "megacode.h" | ||||||
| #include "holtek.h" | #include "holtek.h" | ||||||
|  | #include "chamberlain_code.h" | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Registration by name SubGhzProtocol. |  * Registration by name SubGhzProtocol. | ||||||
|  | |||||||
| @ -442,7 +442,7 @@ static LevelDuration | |||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     default: |     default: | ||||||
|         furi_crash("SugGhz: ManchesterEncoderResult is incorrect."); |         furi_crash("SubGhz: ManchesterEncoderResult is incorrect."); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     return level_duration_make(data.level, data.duration); |     return level_duration_make(data.level, data.duration); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov