From 2c95a7cba4b4ee32045e09354b8fb833af3939fe Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 28 Feb 2023 00:02:30 +0300 Subject: [PATCH] Somfy Telis - Custom buttons + Prog mode --- CHANGELOG.md | 3 +- ReadMe.md | 5 +- .../scenes/subghz_scene_receiver_info.c | 2 + .../main/subghz/scenes/subghz_scene_rpc.c | 2 + .../subghz/scenes/subghz_scene_transmitter.c | 3 + applications/main/subghz/views/transmitter.c | 16 +++ applications/main/unirfremix/unirfremix_app.c | 2 + firmware/targets/f7/api_symbols.csv | 4 + lib/subghz/protocols/somfy_telis.c | 121 ++++++++++++++++-- lib/subghz/protocols/somfy_telis.h | 8 ++ 10 files changed, 153 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc844c23..a50bfb1cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### New changes -* SubGHz: **Custom buttons for Nice Flor S** - now you can use arrow buttons to send signal with different button code +* SubGHz: **Custom buttons for Nice Flor S / Somfy Telis (+Programming mode)** - now you can use arrow buttons to send signal with different button code +* SubGHz: Somfy Telis -> Add manually (create new remote, now with programming button (Prog / 0x8) you can write it into receiver) * OFW: Drivers: remove excessive check in bq25896 and make PVS happy * OFW: FuriHal, Power, UnitTests: fix, rename battery charging voltage limit API -> **Breaking API change, api was changed from 14.x to 15.x** **(this will make your manually copied plugins not work, update them in same way you installed them, or delete `apps` folder and then install firmware, if you using extra pack builds (with `e` in version) all apps in _Extra will be updated automatically)** diff --git a/ReadMe.md b/ReadMe.md index 6f99a1993..2e9b0327e 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -72,7 +72,7 @@ Encoders/sending made by Eng1n33r & @xMasterX: - CAME Atomo - Nice Flor S - FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)] -- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)] +- Keeloq: BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)] - Security+ v1 & v2 - Star Line @@ -166,7 +166,8 @@ Games: - Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79) - Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107) * SubGHz -> **Hold right in received signal list to delete selected signal** -* SubGHz -> **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S** - now you can use arrow buttons to send signal with different button code +* SubGHz -> **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis** - now you can use arrow buttons to send signal with different button code +* SubGHz -> BFT Mitto / Somfy Telis manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis) * SubGHz -> Debug mode counter increase settings (+5, +10, default: +1) * SubGHz -> Debug PIN output settings for protocol development * Infrared -> Debug TX PIN output settings diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index c654ad0c5..fd28421a8 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -4,6 +4,7 @@ #include #include #include +#include void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, void* context) { furi_assert(context); @@ -238,6 +239,7 @@ void subghz_scene_receiver_info_on_exit(void* context) { keeloq_reset_original_btn(); alutech_reset_original_btn(); nice_flors_reset_original_btn(); + somfy_telis_reset_original_btn(); star_line_reset_mfname(); star_line_reset_kl_type(); } diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index b64f92de2..01804492e 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -3,6 +3,7 @@ #include #include #include +#include typedef enum { SubGhzRpcStateIdle, @@ -115,6 +116,7 @@ void subghz_scene_rpc_on_exit(void* context) { keeloq_reset_original_btn(); alutech_reset_original_btn(); nice_flors_reset_original_btn(); + somfy_telis_reset_original_btn(); star_line_reset_mfname(); star_line_reset_kl_type(); } diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index a10e10a37..00839170c 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -5,6 +5,7 @@ #include #include #include +#include void subghz_scene_transmitter_callback(SubGhzCustomEvent event, void* context) { furi_assert(context); @@ -95,6 +96,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { keeloq_set_btn(0); alutech_set_btn(0); nice_flors_set_btn(0); + somfy_telis_set_btn(0); uint8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); furi_hal_subghz_set_rolling_counter_mult(0); // Calling restore! @@ -138,6 +140,7 @@ void subghz_scene_transmitter_on_exit(void* context) { keeloq_reset_original_btn(); alutech_reset_original_btn(); nice_flors_reset_original_btn(); + somfy_telis_reset_original_btn(); star_line_reset_mfname(); star_line_reset_kl_type(); } diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index 5a64f27e2..e6ed16d81 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -7,6 +7,7 @@ #include #include #include +#include struct SubGhzViewTransmitter { View* view; @@ -161,6 +162,7 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { keeloq_set_btn(1); alutech_set_btn(1); nice_flors_set_btn(1); + somfy_telis_set_btn(1); with_view_model( subghz_transmitter->view, SubGhzViewTransmitterModel * model, @@ -176,6 +178,10 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { furi_string_printf( model->temp_button_id, "%01X", nice_flors_get_original_btn()); model->draw_temp_button = true; + } else if(somfy_telis_get_original_btn() != 0) { + furi_string_printf( + model->temp_button_id, "%01X", somfy_telis_get_original_btn()); + model->draw_temp_button = true; } }, true); @@ -192,6 +198,7 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { keeloq_set_btn(2); alutech_set_btn(2); nice_flors_set_btn(2); + somfy_telis_set_btn(2); with_view_model( subghz_transmitter->view, SubGhzViewTransmitterModel * model, @@ -207,6 +214,10 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { furi_string_printf( model->temp_button_id, "%01X", nice_flors_get_original_btn()); model->draw_temp_button = true; + } else if(somfy_telis_get_original_btn() != 0) { + furi_string_printf( + model->temp_button_id, "%01X", somfy_telis_get_original_btn()); + model->draw_temp_button = true; } }, true); @@ -223,6 +234,7 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { keeloq_set_btn(3); alutech_set_btn(3); nice_flors_set_btn(3); + somfy_telis_set_btn(3); with_view_model( subghz_transmitter->view, SubGhzViewTransmitterModel * model, @@ -238,6 +250,10 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { furi_string_printf( model->temp_button_id, "%01X", nice_flors_get_original_btn()); model->draw_temp_button = true; + } else if(somfy_telis_get_original_btn() != 0) { + furi_string_printf( + model->temp_button_id, "%01X", somfy_telis_get_original_btn()); + model->draw_temp_button = true; } }, true); diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index 4f8d5fa01..597870f94 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -21,6 +21,7 @@ #include #include #include +#include #define UNIRFMAP_FOLDER "/ext/unirf" #define UNIRFMAP_EXTENSION ".txt" @@ -486,6 +487,7 @@ void unirfremix_tx_stop(UniRFRemix* app) { keeloq_reset_original_btn(); alutech_reset_original_btn(); nice_flors_reset_original_btn(); + somfy_telis_reset_original_btn(); star_line_reset_mfname(); star_line_reset_kl_type(); } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 08c95fe1f..17df79bee 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2463,6 +2463,10 @@ Function,-,siprintf,int,"char*, const char*, ..." Function,-,siscanf,int,"const char*, const char*, ..." Function,-,sniprintf,int,"char*, size_t, const char*, ..." Function,+,snprintf,int,"char*, size_t, const char*, ..." +Function,-,somfy_telis_get_custom_btn,uint8_t, +Function,-,somfy_telis_get_original_btn,uint8_t, +Function,-,somfy_telis_reset_original_btn,void, +Function,-,somfy_telis_set_btn,void,uint8_t Function,-,sprintf,int,"char*, const char*, ..." Function,-,sqrt,double,double Function,-,sqrtf,float,float diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 143171a05..5d6b1c6f3 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -73,6 +73,25 @@ const SubGhzProtocol subghz_protocol_somfy_telis = { .encoder = &subghz_protocol_somfy_telis_encoder, }; +static uint8_t st_btn_temp_id; +static uint8_t st_btn_temp_id_original; + +void somfy_telis_set_btn(uint8_t b) { + st_btn_temp_id = b; +} + +uint8_t somfy_telis_get_original_btn() { + return st_btn_temp_id_original; +} + +uint8_t somfy_telis_get_custom_btn() { + return st_btn_temp_id; +} + +void somfy_telis_reset_original_btn() { + st_btn_temp_id_original = 0; +} + void* subghz_protocol_encoder_somfy_telis_alloc(SubGhzEnvironment* environment) { UNUSED(environment); SubGhzProtocolEncoderSomfyTelis* instance = malloc(sizeof(SubGhzProtocolEncoderSomfyTelis)); @@ -95,13 +114,86 @@ void subghz_protocol_encoder_somfy_telis_free(void* context) { free(instance); } -static bool - subghz_protocol_somfy_telis_gen_data(SubGhzProtocolEncoderSomfyTelis* instance, uint8_t btn) { - UNUSED(btn); +static bool subghz_protocol_somfy_telis_gen_data( + SubGhzProtocolEncoderSomfyTelis* instance, + uint8_t btn, + bool new_remote) { + // If we doing a clone we will use its data uint64_t data = instance->generic.data ^ (instance->generic.data >> 8); - instance->generic.btn = (data >> 44) & 0xF; // ctrl - instance->generic.cnt = (data >> 24) & 0xFFFF; // rolling code - instance->generic.serial = data & 0xFFFFFF; // address + if(!new_remote) { + instance->generic.btn = (data >> 44) & 0xF; // ctrl + btn = instance->generic.btn; + instance->generic.cnt = (data >> 24) & 0xFFFF; // rolling code + instance->generic.serial = data & 0xFFFFFF; // address + } + + // Save original button for later use + if(st_btn_temp_id_original == 0) { + st_btn_temp_id_original = btn; + } + + // Set custom button + if(st_btn_temp_id == 1) { + switch(st_btn_temp_id_original) { + case 0x1: + btn = 0x2; + break; + case 0x2: + btn = 0x1; + break; + case 0x4: + btn = 0x1; + break; + case 0x8: + btn = 0x1; + break; + + default: + break; + } + } + if(st_btn_temp_id == 2) { + switch(st_btn_temp_id_original) { + case 0x1: + btn = 0x4; + break; + case 0x2: + btn = 0x4; + break; + case 0x4: + btn = 0x2; + break; + case 0x8: + btn = 0x4; + break; + + default: + break; + } + } + if(st_btn_temp_id == 3) { + switch(st_btn_temp_id_original) { + case 0x1: + btn = 0x8; + break; + case 0x2: + btn = 0x8; + break; + case 0x4: + btn = 0x8; + break; + case 0x8: + btn = 0x2; + break; + + default: + break; + } + } + + if((st_btn_temp_id == 0) && (st_btn_temp_id_original != 0)) { + btn = st_btn_temp_id_original; + } if(instance->generic.cnt < 0xFFFF) { if((instance->generic.cnt + furi_hal_subghz_get_rolling_counter_mult()) >= 0xFFFF) { @@ -114,8 +206,12 @@ static bool } uint8_t frame[7]; - frame[0] = data >> 48; - frame[1] = instance->generic.btn << 4; + if(!new_remote) { + frame[0] = data >> 48; + } else { + frame[0] = 0xA7; + } + frame[1] = btn << 4; frame[2] = instance->generic.cnt >> 8; frame[3] = instance->generic.cnt; frame[4] = instance->generic.serial >> 16; @@ -154,7 +250,7 @@ bool subghz_protocol_somfy_telis_create_data( instance->generic.serial = serial; instance->generic.cnt = cnt; instance->generic.data_count_bit = 56; - bool res = subghz_protocol_somfy_telis_gen_data(instance, btn); + bool res = subghz_protocol_somfy_telis_gen_data(instance, btn, true); if(res) { res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } @@ -172,7 +268,7 @@ static bool subghz_protocol_encoder_somfy_telis_get_upload( furi_assert(instance); //gen new key - if(subghz_protocol_somfy_telis_gen_data(instance, btn)) { + if(subghz_protocol_somfy_telis_gen_data(instance, btn, false)) { //ToDo if you need to add a callback to automatically update the data on the display } else { return false; @@ -583,6 +679,11 @@ static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGener instance->btn = (data >> 44) & 0xF; // ctrl instance->cnt = (data >> 24) & 0xFFFF; // rolling code instance->serial = data & 0xFFFFFF; // address + + // Save original button for later use + if(st_btn_temp_id_original == 0) { + st_btn_temp_id_original = instance->btn; + } } /** diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index b5e989866..bca58b64b 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -11,6 +11,14 @@ extern const SubGhzProtocolDecoder subghz_protocol_somfy_telis_decoder; extern const SubGhzProtocolEncoder subghz_protocol_somfy_telis_encoder; extern const SubGhzProtocol subghz_protocol_somfy_telis; +// Custom buttons +void somfy_telis_set_btn(uint8_t b); + +uint8_t somfy_telis_get_original_btn(); +uint8_t somfy_telis_get_custom_btn(); + +void somfy_telis_reset_original_btn(); + /** * Allocate SubGhzProtocolEncoderSomfyTelis. * @param environment Pointer to a SubGhzEnvironment instance