From b7046b21792995a5b7bc43c9ad8fd7b66dddc7d3 Mon Sep 17 00:00:00 2001 From: Liam Droog <61334243+LiamDroog@users.noreply.github.com> Date: Sun, 8 Jan 2023 23:03:51 -0700 Subject: [PATCH 01/24] Change broken BadUSB link to Hak5 duckyscript quick reference webpage (#2270) * Change broken link to Hak5 duckyscript quick reference webpage * Update BadUSB syntax link --- assets/resources/badusb/demo_macos.txt | 2 +- assets/resources/badusb/demo_windows.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/resources/badusb/demo_macos.txt b/assets/resources/badusb/demo_macos.txt index 3c21a4df8..82543b28f 100644 --- a/assets/resources/badusb/demo_macos.txt +++ b/assets/resources/badusb/demo_macos.txt @@ -79,7 +79,7 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo ENTER STRING More information about script syntax can be found here: ENTER -STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript +STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md ENTER STRING EOF diff --git a/assets/resources/badusb/demo_windows.txt b/assets/resources/badusb/demo_windows.txt index f304f5e8d..2ed33b3c0 100644 --- a/assets/resources/badusb/demo_windows.txt +++ b/assets/resources/badusb/demo_windows.txt @@ -80,5 +80,5 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo ENTER STRING More information about script syntax can be found here: ENTER -STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript +STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md ENTER From 8d2143add54641a256a02db775ee37ae6aff49c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 10 Jan 2023 03:15:03 +0900 Subject: [PATCH 02/24] Fix various issues reported on github (#2280) * Desktop: Fix use after free in slideshow view * Gui: long press toggles first letter case too * Desktop: remove debug logging --- .../services/desktop/views/desktop_view_slideshow.c | 2 +- applications/services/gui/modules/text_input.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/applications/services/desktop/views/desktop_view_slideshow.c b/applications/services/desktop/views/desktop_view_slideshow.c index 58a8f6d0c..09e155341 100644 --- a/applications/services/desktop/views/desktop_view_slideshow.c +++ b/applications/services/desktop/views/desktop_view_slideshow.c @@ -56,7 +56,7 @@ static bool desktop_view_slideshow_input(InputEvent* event, void* context) { instance->callback(DesktopSlideshowCompleted, instance->context); } update_view = true; - } else if(event->key == InputKeyOk) { + } else if(event->key == InputKeyOk && instance->timer) { if(event->type == InputTypePress) { furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_SHORT); } else if(event->type == InputTypeRelease) { diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index 7c419d96a..80680fe45 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -138,7 +138,7 @@ static bool char_is_lowercase(char letter) { static char char_to_uppercase(const char letter) { if(letter == '_') { return 0x20; - } else if(isalpha(letter)) { + } else if(islower(letter)) { return (letter - 0x20); } else { return letter; @@ -309,7 +309,9 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b char selected = get_selected_char(model); size_t text_length = strlen(model->text_buffer); - if(shift) { + bool toogle_case = text_length == 0; + if(shift) toogle_case = !toogle_case; + if(toogle_case) { selected = char_to_uppercase(selected); } @@ -329,9 +331,6 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b text_length = 0; } if(text_length < (model->text_buffer_size - 1)) { - if(text_length == 0 && char_is_lowercase(selected)) { - selected = char_to_uppercase(selected); - } model->text_buffer[text_length] = selected; model->text_buffer[text_length + 1] = 0; } From d2df35a35bfbffd167529dbd4b69dccf7833a225 Mon Sep 17 00:00:00 2001 From: Stephen Kent Date: Wed, 11 Jan 2023 02:13:07 -0800 Subject: [PATCH 03/24] fbt: add `fap_deploy` target to build and copy all .fap apps to flipper (#2146) * fbt: add `faps_copy` target to build and copy all .fap apps to flipper * fbt: restore default runfap.py invocation behavior, use -n for copy only * fbt: proper implementation of fap_deploy target Co-authored-by: hedger --- .vscode/example/tasks.json | 16 ++++++++++++++-- SConstruct | 8 ++++++++ scripts/fbt_tools/fbt_help.py | 2 ++ scripts/runfap.py | 20 +++++++++++++++----- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index c16c3ab4f..beedf8865 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -138,6 +138,18 @@ "Serial Console" ] }, + { + "label": "[Debug] Build and upload all FAPs to Flipper over USB", + "group": "build", + "type": "shell", + "command": "./fbt fap_deploy" + }, + { + "label": "[Release] Build and upload all FAPs to Flipper over USB", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 fap_deploy" + }, { // Press Ctrl+] to quit "label": "Serial Console", @@ -145,7 +157,7 @@ "command": "./fbt cli", "group": "none", "isBackground": true, - "options": { + "options": { "env": { "FBT_NO_SYNC": "0" } @@ -162,4 +174,4 @@ } } ] -} +} \ No newline at end of file diff --git a/SConstruct b/SConstruct index 138b52d93..b8c65044d 100644 --- a/SConstruct +++ b/SConstruct @@ -165,6 +165,14 @@ Alias("fap_dist", fap_dist) distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist) +# Copy all faps to device + +fap_deploy = distenv.PhonyTarget( + "fap_deploy", + "${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps", + source=Dir("#/assets/resources/apps"), +) + # Target for bundling core2 package for qFlipper copro_dist = distenv.CoproBuilder( diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index 0475f51bc..8cce9335b 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -11,6 +11,8 @@ Building: Build all FAP apps fap_{APPID}, launch_app APPSRC={APPID}: Build FAP app with appid={APPID}; upload & start it over USB + fap_deploy: + Build and upload all FAP apps over USB Flashing & debugging: flash, flash_blackmagic, jflash: diff --git a/scripts/runfap.py b/scripts/runfap.py index c2c0f78d5..410b3e7d2 100644 --- a/scripts/runfap.py +++ b/scripts/runfap.py @@ -15,6 +15,13 @@ import serial.tools.list_ports as list_ports class Main(App): def init(self): self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") + self.parser.add_argument( + "-n", + "--no-launch", + dest="launch_app", + action="store_false", + help="Don't launch app", + ) self.parser.add_argument("fap_src_path", help="App file to upload") self.parser.add_argument( @@ -84,11 +91,14 @@ class Main(App): self.logger.error(f"Error: upload failed: {storage.last_error}") return -3 - storage.send_and_wait_eol(f'loader open "Applications" {fap_dst_path}\r') - result = storage.read.until(storage.CLI_EOL) - if len(result): - self.logger.error(f"Unexpected response: {result.decode('ascii')}") - return -4 + if self.args.launch_app: + storage.send_and_wait_eol( + f'loader open "Applications" {fap_dst_path}\r' + ) + result = storage.read.until(storage.CLI_EOL) + if len(result): + self.logger.error(f"Unexpected response: {result.decode('ascii')}") + return -4 return 0 finally: From 20621da8ac013b1fc447e7f6f5a9e7e69c2bc913 Mon Sep 17 00:00:00 2001 From: Giacomo Ferretti Date: Wed, 11 Jan 2023 14:41:57 +0100 Subject: [PATCH 04/24] Fix typos in source code (#2285) * Fix typo in TextInput module * Fix typo in Widget comment * Fix typo in comment Co-authored-by: hedger --- applications/services/gui/modules/text_input.c | 14 +++++++------- applications/services/gui/modules/widget.h | 2 +- applications/services/input/input.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index 80680fe45..32607e884 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -29,7 +29,7 @@ typedef struct { TextInputValidatorCallback validator_callback; void* validator_callback_context; FuriString* validator_text; - bool valadator_message_visible; + bool validator_message_visible; } TextInputModel; static const uint8_t keyboard_origin_x = 1; @@ -254,7 +254,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { } } } - if(model->valadator_message_visible) { + if(model->validator_message_visible) { canvas_set_font(canvas, FontSecondary); canvas_set_color(canvas, ColorWhite); canvas_draw_box(canvas, 8, 10, 110, 48); @@ -319,7 +319,7 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b if(model->validator_callback && (!model->validator_callback( model->text_buffer, model->validator_text, model->validator_callback_context))) { - model->valadator_message_visible = true; + model->validator_message_visible = true; furi_timer_start(text_input->timer, furi_kernel_get_tick_frequency() * 4); } else if(model->callback != 0 && text_length > 0) { model->callback(model->callback_context); @@ -348,8 +348,8 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { TextInputModel* model = view_get_model(text_input->view); if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) && - model->valadator_message_visible) { - model->valadator_message_visible = false; + model->validator_message_visible) { + model->validator_message_visible = false; consumed = true; } else if(event->type == InputTypeShort) { consumed = true; @@ -435,7 +435,7 @@ void text_input_timer_callback(void* context) { with_view_model( text_input->view, TextInputModel * model, - { model->valadator_message_visible = false; }, + { model->validator_message_visible = false; }, true); } @@ -495,7 +495,7 @@ void text_input_reset(TextInput* text_input) { model->validator_callback = NULL; model->validator_callback_context = NULL; furi_string_reset(model->validator_text); - model->valadator_message_visible = false; + model->validator_message_visible = false; }, true); } diff --git a/applications/services/gui/modules/widget.h b/applications/services/gui/modules/widget.h index 50c261751..9076ce7f2 100644 --- a/applications/services/gui/modules/widget.h +++ b/applications/services/gui/modules/widget.h @@ -91,7 +91,7 @@ void widget_add_string_element( * @param[in] text Formatted text. The following formats are available: * "\e#Bold text\e#" - bold font is used * "\e*Monospaced text\e*" - monospaced font is used - * "\e#Inversed text\e#" - white text on black background + * "\e!Inversed text\e!" - white text on black background * @param strip_to_dots Strip text to ... if does not fit to width */ void widget_add_text_box_element( diff --git a/applications/services/input/input.h b/applications/services/input/input.h index ec3d09711..062dc0fa5 100644 --- a/applications/services/input/input.h +++ b/applications/services/input/input.h @@ -19,7 +19,7 @@ extern "C" { typedef enum { InputTypePress, /**< Press event, emitted after debounce */ InputTypeRelease, /**< Release event, emitted after debounce */ - InputTypeShort, /**< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ + InputTypeShort, /**< Short event, emitted after InputTypeRelease done within INPUT_LONG_PRESS interval */ InputTypeLong, /**< Long event, emitted after INPUT_LONG_PRESS_COUNTS interval, asynchronous to InputTypeRelease */ InputTypeRepeat, /**< Repeat event, emitted with INPUT_LONG_PRESS_COUNTS period after InputTypeLong event */ InputTypeMAX, /**< Special value for exceptional */ From ad9d746a279d7856780586304e4bafb92f2b6753 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Wed, 11 Jan 2023 16:58:51 +0300 Subject: [PATCH 05/24] BadUSB backspace/delete fix (#2288) Co-authored-by: hedger --- applications/main/bad_usb/bad_usb_script.c | 4 ++-- applications/main/gpio/scenes/gpio_scene_usb_uart_config.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index 92c7466f1..bbd721ed2 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -71,8 +71,8 @@ static const DuckyKey ducky_keys[] = { {"BREAK", HID_KEYBOARD_PAUSE}, {"PAUSE", HID_KEYBOARD_PAUSE}, {"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK}, - {"DELETE", HID_KEYBOARD_DELETE}, - {"BACKSPACE", HID_KEYPAD_BACKSPACE}, + {"DELETE", HID_KEYBOARD_DELETE_FORWARD}, + {"BACKSPACE", HID_KEYBOARD_DELETE}, {"END", HID_KEYBOARD_END}, {"ESC", HID_KEYBOARD_ESCAPE}, {"ESCAPE", HID_KEYBOARD_ESCAPE}, diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c index 55b04ed67..776343fb0 100644 --- a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c +++ b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c @@ -14,9 +14,12 @@ static const char* uart_ch[] = {"13,14", "15,16"}; static const char* flow_pins[] = {"None", "2,3", "6,7", "16,15"}; static const char* baudrate_mode[] = {"Host"}; static const uint32_t baudrate_list[] = { + 1200, 2400, + 4800, 9600, 19200, + 28800, 38400, 57600, 115200, From 75e9de12b065bd5e572b8b9232c8b9670c8e6f91 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:50:19 +0300 Subject: [PATCH 06/24] [FL-3078] Per protocol signal repeat count (#2293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Better Infrared protocol file structure * Rename InfraredProtocolSpec to InfraredProtocolVariant * Slightly better names * Add repeat count field to protocol variant description * Repeat the signal the appropriate number of times when brute-forcing * Repeat the signal the appropriate number of times when sending via worker * Better signal count logic in infrared_transmit * Better variable names * Convert some raw signals to messages in tv.ir Co-authored-by: あく --- assets/resources/infrared/assets/tv.ir | 814 +++++++++--------- firmware/targets/f7/api_symbols.csv | 3 +- .../common/infrared_common_decoder.c | 9 +- .../common/infrared_common_encoder.c | 11 +- .../common/infrared_common_protocol_defs.c | 140 --- lib/infrared/encoder_decoder/infrared.c | 63 +- lib/infrared/encoder_decoder/infrared.h | 10 + lib/infrared/encoder_decoder/infrared_i.h | 5 +- .../infrared_protocol_defs_i.h | 320 ------- .../kaseikyo/infrared_decoder_kaseikyo.c | 10 +- .../kaseikyo/infrared_encoder_kaseikyo.c | 8 +- .../kaseikyo/infrared_kaseikyo_spec.c | 17 - .../kaseikyo/infrared_protocol_kaseikyo.c | 40 + .../kaseikyo/infrared_protocol_kaseikyo.h | 31 + .../kaseikyo/infrared_protocol_kaseikyo_i.h | 30 + .../nec/infrared_decoder_nec.c | 11 +- .../nec/infrared_encoder_nec.c | 11 +- .../encoder_decoder/nec/infrared_nec_spec.c | 47 - .../nec/infrared_protocol_nec.c | 74 ++ .../nec/infrared_protocol_nec.h | 30 + .../nec/infrared_protocol_nec_i.h | 29 + .../rc5/infrared_decoder_rc5.c | 13 +- .../rc5/infrared_encoder_rc5.c | 12 +- .../rc5/infrared_protocol_rc5.c | 49 ++ .../rc5/infrared_protocol_rc5.h | 38 + .../rc5/infrared_protocol_rc5_i.h | 20 + .../encoder_decoder/rc5/infrared_rc5_spec.c | 27 - .../rc6/infrared_decoder_rc6.c | 13 +- .../rc6/infrared_encoder_rc6.c | 12 +- .../rc6/infrared_protocol_rc6.c | 39 + .../rc6/infrared_protocol_rc6.h | 37 + .../rc6/infrared_protocol_rc6_i.h | 28 + .../encoder_decoder/rc6/infrared_rc6_spec.c | 17 - .../samsung/infrared_decoder_samsung.c | 10 +- .../samsung/infrared_encoder_samsung.c | 10 +- .../samsung/infrared_protocol_samsung.c | 40 + .../samsung/infrared_protocol_samsung.h | 31 + .../samsung/infrared_protocol_samsung_i.h | 35 + .../samsung/infrared_samsung_spec.c | 17 - .../sirc/infrared_decoder_sirc.c | 11 +- .../sirc/infrared_encoder_sirc.c | 9 +- .../sirc/infrared_protocol_sirc.c | 64 ++ .../sirc/infrared_protocol_sirc.h | 37 + .../sirc/infrared_protocol_sirc_i.h | 26 + .../encoder_decoder/sirc/infrared_sirc_spec.c | 37 - lib/infrared/worker/infrared_transmit.c | 3 +- lib/infrared/worker/infrared_worker.c | 52 +- 47 files changed, 1220 insertions(+), 1180 deletions(-) mode change 100755 => 100644 assets/resources/infrared/assets/tv.ir delete mode 100644 lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c delete mode 100644 lib/infrared/encoder_decoder/infrared_protocol_defs_i.h delete mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h create mode 100644 lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h delete mode 100644 lib/infrared/encoder_decoder/nec/infrared_nec_spec.c create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h create mode 100644 lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h create mode 100644 lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h delete mode 100644 lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h create mode 100644 lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h delete mode 100644 lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h create mode 100644 lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h delete mode 100644 lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h create mode 100644 lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h delete mode 100644 lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir old mode 100755 new mode 100644 index cc5b0360e..b45171cb1 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -47,85 +47,85 @@ name: Mute type: parsed protocol: NEC address: 08 00 00 00 -command: 0b 00 00 00 +command: 0B 00 00 00 # name: Power type: parsed protocol: NECext -address: 00 df 00 00 -command: 1c 00 00 00 +address: 00 DF 00 00 +command: 1C 00 00 00 # name: Vol_up type: parsed protocol: NECext -address: 00 df 00 00 -command: 4b 00 00 00 +address: 00 DF 00 00 +command: 4B 00 00 00 # name: Vol_dn type: parsed protocol: NECext -address: 00 df 00 00 -command: 4f 00 00 00 +address: 00 DF 00 00 +command: 4F 00 00 00 # name: Ch_next type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 09 00 00 00 # name: Ch_prev type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 05 00 00 00 # name: Mute type: parsed protocol: NECext -address: 00 df 00 00 +address: 00 DF 00 00 command: 08 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0e 00 00 00 -command: 0c 00 00 00 +address: 0E 00 00 00 +command: 0C 00 00 00 # name: Mute type: parsed protocol: Samsung32 -address: 0e 00 00 00 -command: 0d 00 00 00 +address: 0E 00 00 00 +command: 0D 00 00 00 # name: Vol_up type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 14 00 00 00 # name: Vol_dn type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 15 00 00 00 # name: Ch_next type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 12 00 00 00 # name: Ch_prev type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 13 00 00 00 # name: Power type: parsed protocol: RC6 address: 00 00 00 00 -command: 0c 00 00 00 +command: 0C 00 00 00 # name: Power type: parsed @@ -190,19 +190,19 @@ command: 63 00 00 00 name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: 1c 00 00 00 +address: AA 00 00 00 +command: 1C 00 00 00 # name: Power type: parsed protocol: NEC address: 38 00 00 00 -command: 1c 00 00 00 +command: 1C 00 00 00 # name: Power type: parsed protocol: NECext -address: 83 7a 00 00 +address: 83 7A 00 00 command: 08 00 00 00 # name: Power @@ -215,7 +215,7 @@ name: Power type: parsed protocol: NECext address: 18 18 00 00 -command: c0 00 00 00 +command: C0 00 00 00 # name: Power type: parsed @@ -226,8 +226,8 @@ command: 10 00 00 00 name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: c5 00 00 00 +address: AA 00 00 00 +command: C5 00 00 00 # name: Power type: parsed @@ -250,8 +250,8 @@ command: 08 00 00 00 name: Power type: parsed protocol: NECext -address: 80 6f 00 00 -command: 0a 00 00 00 +address: 80 6F 00 00 +command: 0A 00 00 00 # name: Power type: parsed @@ -262,19 +262,19 @@ command: 00 00 00 00 name: Power type: parsed protocol: NECext -address: 80 7b 00 00 +address: 80 7B 00 00 command: 13 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0e 00 00 00 +address: 0E 00 00 00 command: 14 00 00 00 # name: Power type: parsed protocol: NECext -address: 80 7e 00 00 +address: 80 7E 00 00 command: 18 00 00 00 # name: Power @@ -287,25 +287,25 @@ name: Power type: parsed protocol: NECext address: 80 75 00 00 -command: 0a 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: NECext address: 80 57 00 00 -command: 0a 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: Samsung32 -address: 0b 00 00 00 -command: 0a 00 00 00 +address: 0B 00 00 00 +command: 0A 00 00 00 # name: Power type: parsed protocol: NEC -address: aa 00 00 00 -command: 1b 00 00 00 +address: AA 00 00 00 +command: 1B 00 00 00 # name: Power type: parsed @@ -323,7 +323,7 @@ name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -340,626 +340,626 @@ command: 01 00 00 00 name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 634 2571 505 519 479 519 479 518 480 518 480 518 480 518 480 517 481 547 481 517 481 20040 590 2555 501 1007 999 997 510 548 480 486 512 486 512 486 542 485 513 516 482 116758 593 2552 504 1004 992 1004 514 514 514 483 515 513 485 483 545 482 516 482 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 525 1955 449 1999 476 4545 446 4544 478 2032 443 2006 469 2011 444 4577 445 4545 447 4574 448 2002 473 4547 444 34913 447 2032 443 2007 478 4542 449 4541 471 2039 446 2004 471 2008 447 4574 448 4543 448 4572 450 2030 445 4545 446 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2445 582 1221 603 548 602 1191 609 572 602 1191 609 542 607 544 631 1172 603 568 606 545 605 566 608 543 26263 2414 611 1192 607 544 606 1197 602 569 606 1197 602 539 611 540 635 1168 606 565 610 541 608 563 587 564 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 15 00 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 3461 1802 439 452 444 1283 469 448 438 453 443 447 439 452 444 419 497 448 438 425 471 419 467 451 445 445 441 450 446 1281 471 420 466 425 471 446 440 424 472 445 461 456 440 451 445 445 441 450 446 1281 471 447 439 451 445 419 467 423 473 445 441 422 494 450 436 428 468 1259 493 425 471 1256 496 1259 472 1281 471 1285 467 423 473 417 469 1286 466 452 444 1283 469 1285 467 1261 491 1263 468 423 493 1260 471 74142 3578 1713 467 423 473 1281 471 420 466 452 444 419 467 424 472 418 488 429 467 451 445 445 441 450 446 444 442 449 437 1290 472 446 440 423 473 445 441 449 467 396 490 428 468 449 447 444 442 448 438 1289 473 445 441 450 446 444 442 449 437 426 470 421 495 422 464 426 470 1257 495 450 446 1254 488 1267 464 1290 472 1282 470 421 465 453 443 1284 468 450 446 1281 471 1283 469 1259 493 1261 470 448 468 1258 473 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 389 1737 280 796 253 744 295 754 274 775 274 776 273 1827 271 1828 270 805 254 1820 278 796 253 797 252 745 294 1806 302 773 245 48942 305 1821 277 798 251 746 303 747 271 778 271 1829 279 796 253 796 253 1821 277 798 251 1823 275 1824 274 1825 273 802 247 1827 271 42824 381 1745 272 804 245 752 297 753 275 773 276 774 275 1825 273 1826 272 803 246 1828 270 805 254 795 244 753 296 1804 294 781 247 48939 379 1746 271 804 245 779 270 753 275 774 275 1825 273 802 247 802 247 1827 271 804 245 1829 279 1820 278 1821 277 798 251 1823 275 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 562 1721 561 594 557 597 564 617 513 615 536 618 543 1715 566 1716 566 1692 559 594 567 588 563 618 543 611 540 615 536 618 543 1715 556 623 538 617 534 621 530 624 516 638 513 642 509 1722 560 620 541 1717 565 1692 559 1724 568 1715 556 1701 560 1723 559 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8436 4189 538 1563 566 1559 539 510 559 543 516 507 542 560 509 540 509 567 512 1586 512 1562 567 1559 539 536 533 1566 542 507 562 513 536 540 509 22102 647 1478 559 1568 540 508 541 535 534 515 534 568 511 538 511 539 540 1585 513 1560 559 1567 541 534 535 1564 534 515 534 568 511 538 511 22125 644 1482 565 1561 537 511 538 564 515 508 541 535 534 541 508 516 563 1588 510 1563 556 1570 538 510 559 1567 541 534 515 535 534 541 508 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 929 825 1711 934 797 930 791 909 822 932 789 938 793 934 797 930 791 1719 899 856 1711 907 824 90848 923 830 1706 912 819 908 823 931 790 910 822 933 788 912 819 935 796 1714 904 850 1707 939 792 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 448 2031 444 2005 480 4540 452 4539 473 2037 438 2011 474 2006 449 4571 451 4539 453 4568 444 2036 449 4541 451 34906 527 1953 451 1998 477 4543 449 4542 480 2030 445 2004 471 2009 446 4575 447 4543 449 4572 450 1999 476 4545 446 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 9021 4496 567 1664 567 1690 561 567 533 1698 563 1667 564 1693 568 1663 568 586 534 567 563 565 535 594 536 591 539 589 531 571 539 563 567 1690 541 560 560 594 536 592 538 564 536 1695 566 1664 567 1690 561 1670 561 1696 555 1675 566 562 558 596 514 562 568 559 561 594 536 565 535 593 537 591 539 1665 566 1692 559 1671 560 1697 564 1666 565 1666 565 1693 558 1672 569 23181 9013 4504 569 1689 542 1689 562 565 535 1697 564 1666 646 1610 560 1672 559 595 535 593 537 590 510 566 564 590 540 588 532 596 514 588 542 1689 542 560 560 594 536 592 538 590 510 1694 567 1664 567 1690 561 1669 562 1695 556 1675 566 561 559 596 514 588 542 585 535 593 537 591 509 593 537 591 539 1665 566 1692 559 1671 560 1697 564 1667 564 1667 564 1693 558 1672 569 +type: parsed +protocol: NEC42 +address: 7B 00 00 00 +command: 00 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8041 3979 513 536 482 515 513 1559 509 515 514 1560 508 515 514 509 509 514 484 4000 533 1566 512 537 481 1566 512 537 481 1566 512 537 481 516 513 537 481 24150 8044 3977 505 518 510 539 479 1567 511 512 506 1568 510 539 479 543 485 538 480 3977 536 1564 514 534 484 1563 515 508 510 1563 515 508 510 540 489 534 484 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 383 2027 295 2112 271 2138 266 890 271 887 294 926 235 2114 300 887 274 915 236 2145 269 887 274 884 297 923 238 920 241 917 264 895 266 26573 384 2026 296 2111 273 2136 268 889 272 886 295 924 237 2113 301 886 275 914 237 2144 270 886 275 914 267 921 240 919 242 916 265 924 237 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 8474 175 5510 174 8476 173 8477 177 8504 171 5515 175 8476 178 8472 177 8473 176 5541 174 8476 173 45583 171 8481 178 5507 177 8473 176 8474 175 8506 173 5512 172 8478 176 8475 174 8476 178 5538 177 8474 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8044 3976 506 517 511 1563 505 517 511 538 480 517 511 538 460 563 455 568 460 3993 530 545 483 1564 514 1559 509 1564 514 509 509 540 488 535 483 513 505 24150 8043 3978 514 509 509 1564 514 509 509 540 478 519 509 540 458 565 464 559 459 3994 529 546 482 1565 513 1560 508 1565 513 510 508 541 487 536 482 541 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 558 2942 450 10021 482 2989 484 10015 447 3024 449 10021 472 3100 485 2986 477 2994 500 2999 475 2996 477 2994 479 2992 482 3018 476 2995 479 6464 484 36270 477 3023 450 10020 473 2999 485 10014 448 3022 452 10019 474 3098 478 2994 480 2991 503 2996 477 2994 480 2992 482 2990 484 3015 479 2992 481 6462 485 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 587 2407 476 1062 965 547 482 547 451 577 452 546 452 22108 590 2404 479 1060 967 1028 510 519 509 548 480 487 511 120791 645 2411 472 1066 961 1065 483 515 514 514 504 493 515 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 7439 171 7441 169 7443 177 7434 176 7462 178 4887 176 4916 177 4914 169 7469 171 4920 174 4918 175 55174 176 7436 174 7437 173 7439 171 7440 175 7463 172 4894 174 4917 171 4921 172 7465 175 4916 178 4914 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 589 2556 500 524 474 554 454 544 454 543 455 543 455 543 455 543 445 583 446 552 446 20046 584 2561 505 1033 485 514 963 518 480 1032 516 512 476 522 506 491 507 522 476 116758 586 2560 506 1033 484 513 964 548 450 1031 507 522 476 521 507 490 508 521 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2407 476 1063 964 578 450 548 450 547 481 517 481 577 451 546 452 546 472 556 452 545 453 575 453 514 484 544 484 543 455 14954 510 2483 481 1058 480 548 959 552 446 1067 481 516 512 546 482 515 992 1003 535 493 515 543 486 513 475 522 506 552 446 111671 589 2405 478 1061 477 551 967 514 484 1059 479 549 479 548 480 517 990 1036 512 516 482 546 483 515 503 525 483 544 454 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8444 4180 537 1564 565 1560 538 1561 557 1568 540 1559 539 536 533 542 517 559 510 1563 535 1564 565 1561 537 512 567 1558 540 535 534 1566 542 1557 562 23122 564 1562 557 1569 539 1560 538 1587 542 1558 540 534 535 515 534 541 538 1587 511 1563 566 1560 538 536 533 1567 541 534 515 1585 533 1566 542 23166 561 1565 564 1561 537 1563 535 1590 539 1561 537 538 541 534 515 535 534 1564 534 1566 563 1563 535 540 539 1560 538 511 538 1588 541 1559 539 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 527 1923 481 1998 477 4543 449 4542 470 2040 445 2004 471 2009 446 4575 447 4543 449 4572 450 1999 476 2034 441 34899 524 1956 448 2001 474 4546 446 4545 477 2033 442 2007 478 2002 443 4578 444 4546 445 4575 447 2003 472 2037 448 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 533 1356 437 3474 427 3483 429 3455 436 1454 430 1459 405 28168 510 1379 434 3477 434 3476 425 3459 432 1457 427 1462 402 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 921 833 1714 932 789 938 793 934 797 903 818 909 822 905 816 938 793 1716 902 853 1714 905 816 90856 922 805 1742 931 790 937 794 933 788 939 792 935 796 930 791 937 794 1715 903 825 1742 904 817 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 7433 177 4915 178 7434 175 7436 174 7464 176 7435 175 4916 177 4915 173 4918 170 4922 171 4920 173 55174 175 7437 173 4919 174 7437 173 7439 171 7467 173 7438 172 4920 173 4919 174 4917 176 4915 178 4914 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 169 6731 176 6748 169 6730 177 6748 169 6755 172 4427 177 4447 178 6721 175 6749 178 4446 168 4456 169 54704 176 6723 174 6750 177 6723 173 6750 177 6747 170 4429 175 4449 176 6723 174 6751 176 4448 177 4447 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3506 3494 876 830 840 2576 847 2568 844 862 819 2570 842 864 816 863 818 2570 842 836 844 2572 840 866 815 865 815 2573 839 867 813 866 814 2573 850 857 813 2575 847 2568 844 834 847 2569 843 835 845 2571 872 2571 842 32654 3512 3488 872 834 847 2570 842 2573 839 867 814 2574 849 858 822 857 813 2575 848 859 821 2566 846 832 848 860 821 2567 845 833 848 860 820 2568 844 834 847 2569 843 2572 840 838 843 2574 849 829 841 2575 868 2575 837 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 560 2939 453 10018 475 2996 477 10022 450 3021 452 10018 475 3097 478 6464 483 6460 477 6466 502 6469 479 2993 480 2990 484 36274 564 2936 456 10015 478 2993 481 10020 534 2936 456 10014 479 3093 482 6461 476 6466 482 6461 476 6495 473 2999 485 2986 477 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 10726 41047 10727 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1617 4604 1559 1537 1560 1537 1560 4661 1533 33422 1613 4607 1566 1530 1556 1540 1536 4685 1539 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 4972 177 4910 173 4944 170 6988 174 6984 177 6951 175 6983 174 14269 177 4969 175 4912 176 4941 178 6979 172 6986 175 6953 178 6980 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7067 176 10544 1055 719 1053 739 1054 738 953 822 1052 2566 169 3435 171 3431 175 3446 170 3432 174 3446 170 3432 174 3428 178 3442 174 3429 177 3425 171 39320 2323 4900 178 10543 1056 719 1053 739 1054 738 953 821 1053 2566 169 3435 171 3431 175 3445 171 3432 174 3446 170 3432 174 3428 178 3442 174 3428 178 3425 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3506 3492 868 839 841 2575 848 858 822 2566 846 832 848 859 821 858 812 2576 847 860 820 2567 845 833 847 860 821 2568 844 862 818 2570 842 864 817 2571 841 2574 849 2567 845 861 820 2568 845 834 847 2570 873 2570 842 34395 3503 3496 874 833 847 2568 845 834 847 2570 842 864 816 835 846 862 819 2569 843 835 846 2571 841 865 816 864 816 2571 841 837 844 2573 850 857 813 2575 848 2567 845 2570 842 864 816 2572 840 838 842 2574 869 2574 838 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 8479 170 5516 178 8472 177 8474 175 8506 173 5513 171 8479 175 8476 178 8472 177 5540 175 8475 174 45584 177 8473 176 5509 175 8476 173 8477 176 8504 170 5516 178 8472 177 8474 175 8476 173 5543 172 8479 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 4969 170 6958 173 4944 175 6983 173 6956 174 6984 177 6980 171 16308 180 4966 173 6955 176 4941 172 6985 176 6982 169 6960 176 6982 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 585 2409 474 550 478 550 448 1033 994 1063 485 512 506 79916 585 2410 473 551 477 550 448 1034 993 1033 515 543 475 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1192 1012 6649 26844 1192 1013 6648 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3134 6105 6263 82963 3134 6105 6263 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 1511 567 1533 565 589 531 597 513 589 541 587 533 1565 533 569 541 1533 565 562 568 1531 537 1537 561 593 537 591 539 1507 561 1539 569 22152 586 1513 565 1535 563 590 540 562 538 564 566 588 542 1557 531 597 513 1534 564 590 540 1533 535 1539 559 568 562 592 538 1509 569 1531 567 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 923 831 1715 903 818 936 795 932 789 938 793 934 797 1713 1740 932 789 911 821 934 798 930 791 90853 928 799 1737 935 796 931 790 937 795 932 789 938 793 1717 1736 936 796 932 789 911 820 934 798 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 20 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 689 1461 566 1534 564 589 531 597 513 1534 564 564 566 1533 535 620 510 1537 561 592 538 1535 543 1531 567 587 533 595 535 1511 567 1533 565 22161 588 1512 566 1534 564 564 556 598 512 1535 563 565 565 1534 534 594 536 1538 560 593 537 1536 542 1532 566 587 543 585 535 1511 567 1534 564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 2558 498 526 482 515 483 546 452 545 453 545 453 545 453 545 453 544 474 554 444 20047 583 2562 504 519 479 519 479 1003 515 483 1024 548 450 1001 995 1001 506 116771 593 2552 504 520 478 551 447 1004 513 514 993 549 449 1002 994 1002 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 587 2559 507 517 481 517 481 547 451 516 482 546 452 546 452 546 452 545 473 525 483 20038 592 2553 503 521 477 552 446 521 477 1004 514 515 992 1034 483 514 484 513 485 116769 593 2552 504 520 478 550 448 520 478 1003 515 514 993 1032 486 513 475 522 476 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4558 4576 558 596 565 97881 4554 4579 565 589 562 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1039 7202 958 4713 981 4713 961 7255 956 4739 955 16077 1038 7204 956 4714 980 4715 959 7256 954 4741 954 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 506 2638 510 516 482 516 482 546 452 546 452 545 453 545 453 545 453 575 443 554 444 20048 592 2554 502 1036 481 517 481 517 511 516 482 516 961 1035 513 515 483 514 484 116757 594 2552 504 1034 484 514 484 514 504 524 484 513 964 1032 506 522 476 492 506 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 7441 169 4924 174 7437 193 7444 171 7441 174 4918 170 7441 174 4917 171 7440 195 7443 172 7439 171 55187 174 7437 173 4919 175 7437 173 7438 172 7466 175 4891 172 7439 171 4921 172 7439 171 7441 174 7464 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 4967 172 4915 178 6980 171 4945 169 4948 176 4912 176 4941 178 16307 176 4969 175 4912 176 6982 174 4942 171 4945 169 4919 174 4943 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1042 793 898 883 869 858 924 884 878 877 875 879 873 855 928 1717 901 854 1794 878 894 887 875 1716 902 89114 985 798 903 878 874 880 902 852 900 855 897 857 905 876 896 1722 906 849 1789 883 899 855 897 1721 897 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 8480 169 8481 178 8472 177 8474 175 8476 173 5513 176 8474 175 8476 173 8507 178 5509 175 8505 174 45558 175 8476 173 8476 173 8477 172 8478 171 8480 169 5517 177 8473 176 8474 175 8506 174 5512 172 8509 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 628 2577 499 528 480 545 453 544 454 544 454 544 454 544 454 543 455 543 475 553 445 20047 593 2553 503 521 477 551 447 1004 514 515 992 519 479 1003 515 513 485 543 455 116768 585 2561 505 519 479 519 479 1002 516 513 994 548 450 1001 506 522 476 521 477 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8987 4505 568 586 534 594 536 591 509 567 563 591 539 563 567 587 513 1692 559 1672 559 1698 563 590 510 592 538 590 540 1664 567 1690 561 593 507 1699 562 1668 563 1694 567 1663 568 586 534 568 562 592 508 595 535 1695 536 592 538 1693 558 595 515 1690 561 593 517 585 535 567 563 39551 8994 4497 566 589 541 560 560 594 516 586 534 594 536 592 538 590 510 1695 566 1664 567 1690 561 593 507 595 535 566 564 1667 564 1693 558 596 534 1670 561 1670 561 1696 565 1666 565 589 541 587 533 595 515 587 533 1697 534 568 562 1695 556 572 538 1693 568 559 541 588 542 585 535 +type: parsed +protocol: NECext +address: 80 63 00 00 +command: 0F 15 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 80 64 00 00 +command: 49 08 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8987 4504 569 559 561 593 537 565 535 567 563 591 539 588 532 597 513 1691 560 568 562 592 508 1697 564 589 511 565 565 1692 559 1672 559 569 561 1669 562 566 564 564 566 1665 566 588 542 586 534 1670 561 567 563 565 535 593 537 591 539 1692 539 589 541 586 534 594 536 592 508 40679 8987 4504 569 585 535 593 537 591 509 566 564 591 539 588 532 596 514 1691 560 594 536 592 508 1697 564 589 511 591 539 1692 559 1671 560 594 536 1669 562 592 538 590 540 1664 567 587 543 585 535 1670 561 593 537 565 535 593 537 591 539 1691 540 588 542 586 534 594 536 592 508 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 298 1828 270 804 245 1829 279 1820 278 797 252 771 278 1822 276 1824 274 800 249 1825 273 802 247 776 252 771 278 1822 276 799 250 48931 388 1737 280 796 253 1821 277 1822 276 798 251 1823 275 800 249 774 275 1825 273 776 273 1801 297 1828 270 1829 279 796 253 1821 277 42813 301 1825 273 801 248 1826 272 1827 271 804 245 805 244 1830 278 1821 277 798 251 1823 275 799 250 774 244 779 280 1820 278 796 253 48926 382 1744 354 696 271 1828 270 1829 279 796 253 1821 277 797 252 746 303 1823 275 774 275 1799 299 1826 272 1827 271 804 245 1829 279 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 5508 176 5539 176 8475 174 5542 173 8478 171 5545 170 8481 168 8482 177 8473 176 5541 174 8476 173 45573 169 5517 177 5538 177 8473 176 5541 174 8476 173 5544 171 8479 170 8481 178 8472 177 5540 175 8475 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8474 175 8475 174 8477 172 8478 171 8480 169 8481 178 5538 177 5510 174 5542 173 5543 172 5544 171 45575 177 8472 177 8474 175 8476 173 8477 172 8478 171 8481 178 5507 177 5539 176 5540 175 5542 173 5543 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8050 3971 511 1562 516 1558 510 539 490 1557 511 1563 515 533 485 538 490 533 485 3983 530 1569 509 1564 514 1559 509 1565 513 1560 508 515 513 536 482 541 488 24152 8042 3979 514 1560 508 1565 513 510 508 1565 513 1560 508 515 513 536 482 541 488 3980 533 1567 511 1562 516 1557 511 1563 515 1558 510 539 489 534 484 539 490 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8475 174 5512 177 8473 176 8475 174 8506 179 5508 176 8474 175 8475 174 8477 172 5544 171 8480 169 45587 176 8475 174 5511 173 8477 177 8473 176 8504 170 5516 178 8472 177 8473 176 8475 174 5542 173 8478 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7436 174 7438 172 7439 171 7441 174 7463 172 7440 170 4921 172 4919 174 4917 176 4916 177 4914 174 55176 175 7437 173 7439 191 7446 174 7438 177 7434 176 7435 175 4917 176 4915 179 4914 174 4917 171 4946 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7435 175 4917 177 7435 175 7436 189 7449 176 7435 175 7437 173 4918 175 7436 174 4918 175 4916 178 55171 175 7436 174 4918 170 7441 174 7438 177 7460 170 7441 174 7438 177 4914 174 7437 178 4914 169 4922 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8049 3973 509 1564 514 509 509 1564 514 535 483 1564 514 535 483 540 489 535 483 3980 533 1566 512 537 481 1566 512 511 507 1566 512 537 481 542 486 511 507 24149 8045 3976 516 1558 510 512 516 1557 511 512 516 1558 510 512 516 507 511 512 506 3984 539 1560 508 515 513 1560 508 541 488 1560 508 541 488 536 482 514 504 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 366 202 867 527 170 130516 343 227 863 529 168 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 5992 176 1372 176 1320 177 1345 172 1349 179 1370 178 1317 175 4444 176 1346 171 1351 177 1345 172 1349 179 1344 174 5963 175 65574 172 5995 178 1344 174 1348 175 1347 175 1347 170 1378 170 1325 172 4447 178 1344 173 1349 169 1353 175 1347 170 1351 177 5961 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 497 1478 488 511 467 1482 494 531 447 1477 499 501 466 533 445 530 468 507 471 529 438 12857 488 1485 491 509 469 1481 495 529 448 1476 490 510 468 532 445 529 469 480 498 502 465 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 982 6313 961 2662 903 2718 929 2719 907 6363 900 2722 904 6365 909 6361 903 6368 906 2742 905 46364 989 6307 906 2716 911 2712 925 2723 903 6367 907 2715 901 6369 905 6365 909 6361 903 2745 902 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 599 257 975 317 177 130649 308 228 974 319 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 4969 170 6958 173 6985 177 6981 171 6958 178 6980 177 6981 170 16308 180 4966 173 6955 176 6982 169 6988 174 6956 175 6983 173 6984 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 5990 173 1349 174 1348 175 1348 174 4444 176 1346 171 1351 177 4416 178 1344 173 1348 169 1353 175 1347 170 1351 177 9048 177 65573 173 5995 173 1348 175 1348 174 1347 176 4444 171 1351 177 1345 173 4421 173 1348 169 1352 176 1347 170 1351 177 1345 172 9053 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 4972 177 4910 173 6985 177 4940 174 6984 178 6951 175 6983 174 14269 177 4968 176 4912 176 6981 175 4941 173 6985 177 6953 178 6979 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1318 225 177 130305 1609 231 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 585 2410 473 1065 962 581 447 519 479 580 448 549 449 579 449 518 480 548 480 517 481 517 481 577 451 516 482 576 452 545 453 14955 510 2483 481 1058 480 549 969 543 445 1037 511 547 481 546 482 516 482 545 484 545 483 514 484 544 963 1063 485 543 445 111612 626 2427 557 954 513 512 995 547 451 1031 507 521 508 551 477 520 478 550 478 549 479 488 510 548 969 1057 481 517 481 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 203 272 1215 302 171 130229 1423 275 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7436 174 7438 192 7446 174 7437 178 7434 176 7435 175 4917 176 4915 178 4913 175 4917 197 7440 175 55130 286 7377 177 7435 175 7437 173 7438 172 7466 174 7411 178 4913 170 4921 172 4919 174 4918 175 7436 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 7437 173 4918 170 7441 174 7437 178 7460 170 7441 179 7433 177 4915 178 4913 170 4922 171 4920 173 55124 291 7372 172 4921 172 7439 171 7441 174 7463 172 7440 170 7442 178 4913 170 4922 171 4920 173 4918 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 8477 172 8478 171 8480 169 5516 179 8502 178 5509 175 8475 174 8476 173 8479 170 5545 170 8480 169 45588 176 8473 176 8474 175 8476 173 5513 177 8504 171 5515 174 8476 178 8472 177 8473 176 5541 174 8476 173 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 177 7436 174 4918 175 7436 174 4918 175 7462 178 4887 176 4916 177 4914 174 4917 171 4921 172 4919 175 55184 175 7435 175 4918 175 7436 174 4918 175 7462 178 4914 174 4917 171 4920 173 4919 174 4917 176 4915 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 508 2484 480 1060 967 544 485 544 454 574 454 543 455 573 445 553 445 522 506 552 446 552 446 551 477 551 447 581 447 520 478 550 478 15908 626 2427 476 1062 476 522 995 547 451 1061 477 520 508 550 478 519 479 519 999 1058 959 1037 990 582 446 1035 483 111666 590 2404 479 1059 479 549 968 543 455 1027 511 548 480 517 511 486 512 546 961 1065 962 1034 993 579 449 1032 486 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 8475 174 8475 174 8477 172 8478 171 8480 169 5517 178 8473 175 8475 179 8501 173 5513 176 8505 169 45562 179 8472 177 8473 176 8474 175 8476 173 8478 171 5515 174 8476 178 8473 176 8505 174 5512 172 8508 171 120769 178 93377 175 7437 173 4919 174 7437 173 7439 171 7467 173 7439 171 7441 174 4918 170 4921 172 7439 171 7467 173 55167 171 7440 170 4922 171 7440 195 7443 172 7439 171 7441 174 7438 177 4915 173 4918 195 7442 173 7439 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 295 1805 273 776 242 1808 270 754 244 1806 272 777 241 758 270 754 264 760 268 756 272 14149 297 1802 266 784 244 1805 263 762 246 1803 265 785 244 780 248 751 267 758 271 753 265 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 535 1723 569 585 566 615 536 619 542 586 565 616 535 1722 539 615 536 1721 561 620 541 587 564 617 534 621 540 588 563 618 543 1714 537 617 534 621 540 615 536 618 543 612 539 615 536 1722 560 594 567 1717 534 1723 569 1714 557 1700 643 1639 643 1641 559 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 502 2521 504 521 997 545 453 575 453 545 453 575 454 22097 591 2433 511 513 994 1062 476 552 476 522 476 552 476 120839 628 2455 509 515 992 1064 484 513 505 493 515 543 475 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 591 2404 479 1060 967 1029 509 519 509 549 479 518 480 79926 585 2408 556 956 989 1033 515 544 484 543 475 522 476 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2560 506 518 480 548 450 548 450 517 481 517 481 517 481 547 451 546 482 516 482 20040 590 2556 500 1038 480 518 969 543 455 543 475 1006 511 517 481 517 511 486 481 116778 584 2561 505 1033 485 513 964 548 450 548 480 1001 506 522 476 522 506 521 446 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 917 206 175 186 170 21561 170 2280 175 2274 502 1929 174 2276 169 5178 170 2261 173 3724 498 1932 171 2279 176 2273 172 3709 172 2277 178 3720 171 17223 177 7619 174 2275 170 2279 176 2256 168 2280 175 5172 176 2256 168 3729 173 2276 179 2253 171 2278 177 3703 178 2271 174 3724 177 17251 170 7627 177 2272 173 2276 169 2263 171 2277 178 5169 169 2262 172 3726 175 2256 168 2280 175 2274 171 3710 171 2278 177 3720 171 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 565 233 653 313 170 130328 752 235 233 107 229 398 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 586 2439 505 549 968 1027 511 517 511 517 481 547 481 21583 584 2439 505 520 997 1059 479 549 479 518 480 548 480 120894 593 2432 501 522 995 1061 477 521 507 520 478 550 478 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 558 8032 474 8115 503 8116 482 8108 480 8141 477 5239 476 8114 504 8115 483 8107 481 5236 509 8111 477 45290 554 8036 481 8108 510 8110 478 8112 476 8145 473 5243 482 8107 511 8109 479 8111 477 5240 505 8115 473 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7438 172 4920 173 7438 172 4920 173 7465 175 4890 173 7439 171 4920 173 4919 174 4917 176 4915 178 55179 170 7441 169 4924 174 7437 178 4913 175 7463 172 4893 170 7441 174 4918 170 4922 171 4920 173 4918 175 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 225 745 222 774 193 778 200 797 175 769 193 777 201 771 196 774 224 747 220 776 202 769 198 248 220 252 196 250 218 253 225 746 221 250 198 248 220 252 226 246 222 223 225 248 220 252 216 229 219 253 225 247 221 277 176 243 220 279 189 230 228 244 224 248 220 252 196 250 218 253 215 257 201 770 197 799 189 257 201 271 197 37716 222 749 218 778 200 771 196 801 172 772 200 771 196 774 193 777 221 750 217 780 197 773 194 251 217 255 193 279 199 273 195 749 218 254 194 252 226 245 223 275 178 242 221 277 201 245 193 253 225 247 221 250 218 254 194 252 226 272 196 223 225 248 220 251 217 255 193 253 225 247 221 251 197 773 194 803 174 297 176 244 219 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3503 2655 197 642 876 2568 844 834 846 833 848 860 821 831 839 2576 847 2569 843 2572 841 2574 849 858 823 857 813 866 815 865 815 2572 841 2575 848 2568 844 2570 842 836 844 863 818 834 847 861 820 2568 845 2571 872 2571 842 32651 3505 3495 875 2567 845 861 820 832 849 859 811 840 840 2576 847 2568 844 2571 842 2574 849 830 840 867 814 838 842 865 815 2572 840 2575 848 2568 845 2571 841 865 815 864 817 834 846 861 819 2569 843 2572 871 2572 840 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 347 677 219 252 196 276 202 742 225 798 174 770 192 778 200 771 196 775 223 748 219 777 200 770 197 249 219 253 195 251 227 271 197 747 220 252 216 229 219 253 225 273 195 277 176 244 219 253 215 230 228 244 224 248 220 252 196 250 218 280 198 247 201 245 223 249 219 253 195 251 227 245 223 248 200 797 175 795 198 248 200 246 222 37666 344 678 228 245 223 222 226 771 196 800 198 747 220 750 217 753 224 773 194 776 202 769 198 799 173 246 227 245 223 249 199 247 221 749 218 280 198 247 201 245 223 249 219 253 195 251 227 244 224 248 200 272 196 250 218 254 194 252 226 245 223 249 199 274 194 251 227 245 193 253 225 273 195 251 217 753 225 746 221 251 197 275 193 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7437 173 7440 174 7437 178 7433 177 7461 169 7442 178 4914 174 4917 171 4921 172 4919 174 7463 177 55163 177 7435 174 7437 173 7438 172 7440 175 7463 172 7413 176 4915 178 4913 175 4917 171 4920 174 7438 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8042 3979 513 510 508 541 487 1559 509 515 513 1560 508 515 513 510 508 541 477 3981 532 1568 510 1563 515 1558 510 1564 514 1559 509 514 514 535 483 540 488 24151 8042 3979 513 536 482 541 487 1560 508 541 488 1560 508 541 487 536 482 541 477 3980 533 1566 512 1561 507 1566 512 1562 516 1557 511 538 491 533 485 538 490 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8989 4501 562 1696 565 1665 566 562 568 586 514 588 542 586 534 594 536 1667 564 591 539 1692 539 563 567 1690 561 1669 562 1669 562 1696 565 562 538 564 566 588 542 586 534 1670 561 568 562 592 538 590 510 592 538 590 540 561 539 563 567 561 569 585 535 593 507 595 535 593 537 39547 8987 4504 569 1689 562 1668 563 591 539 589 511 591 539 589 541 561 559 1671 560 568 562 1695 536 592 538 1693 558 1673 568 1663 568 1689 562 592 508 594 536 592 538 590 540 1664 567 561 569 559 561 567 543 585 535 593 537 591 509 593 537 591 539 589 541 587 513 589 541 587 533 +type: parsed +protocol: NECext +address: 83 7A 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8988 4504 640 487 562 592 538 590 510 592 538 590 540 588 532 596 514 614 516 1689 562 1668 563 1695 536 1695 566 1664 567 1690 612 1618 643 1430 801 1613 648 481 558 570 540 589 541 587 533 595 535 592 508 594 536 592 538 1667 564 1693 558 1672 569 1688 563 1668 644 1586 563 1694 567 40630 8994 2265 557 96833 8987 2273 538 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7439 171 4922 172 7439 171 4921 172 7466 174 4917 176 4915 173 4918 170 7441 174 7438 192 7445 175 55181 174 7437 173 4918 175 7437 173 4919 175 7463 177 4888 175 4917 176 4915 178 7460 170 7440 175 7437 178 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1636 4610 1563 1533 1584 7760 1561 28769 1641 4606 1557 1539 1588 7757 1564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 590 2404 479 1059 968 575 454 544 454 574 454 543 455 543 475 522 476 552 476 552 446 551 447 581 448 520 478 581 447 519 479 549 479 15967 587 2407 476 1062 476 522 995 547 451 1030 508 520 509 550 478 519 479 519 998 1028 999 1057 481 547 960 1066 482 111641 587 2407 476 1063 485 513 994 547 451 1031 507 551 477 551 477 520 478 550 968 1059 968 1027 511 548 959 1036 512 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 588 2406 477 1061 966 577 451 516 482 545 483 545 453 575 443 524 484 514 504 554 454 543 455 543 475 553 445 583 445 521 477 582 446 15969 585 2409 474 1065 483 514 993 549 449 1033 515 543 475 553 475 522 476 552 965 1030 997 576 452 1029 998 1028 479 111668 587 2407 475 1063 485 543 964 517 481 1031 507 552 476 551 477 520 478 550 968 1028 999 574 454 1027 990 1036 481 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 7439 196 7441 174 7437 173 7439 171 7441 174 7438 177 7460 170 7442 178 7433 177 4915 173 4918 170 55186 174 7438 172 7440 170 7441 174 7438 177 7461 169 7416 173 7464 176 7435 175 7437 173 4918 175 4917 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 173 7438 172 7441 174 7438 177 7434 176 7462 168 7443 177 7435 175 4917 176 4915 173 7438 177 4941 173 55166 174 7438 197 7441 174 7437 173 7439 171 7441 174 7438 177 7460 170 4922 171 4893 195 7443 172 4920 173 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 175 7436 179 4913 175 4917 171 4920 173 4945 169 4896 177 7435 175 7436 174 7464 176 4916 177 4914 169 55180 170 7441 169 4924 169 4922 171 4920 173 4919 174 4917 176 7435 175 7463 177 7434 176 4916 177 4914 174 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 927 827 1709 936 796 932 789 938 793 1717 1736 936 795 932 789 1721 927 827 1709 909 822 90851 898 829 1738 934 798 930 791 936 796 1715 1738 934 797 930 791 1719 899 828 1739 934 797 +type: parsed +protocol: RC5 +address: 02 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 5991 177 1372 176 1320 177 1344 173 1349 174 1374 169 1327 170 4449 176 1346 171 1351 177 1345 172 1349 168 1353 175 5963 175 65573 173 5995 178 1344 174 1348 175 1348 174 1347 170 1378 170 1325 172 4447 178 1344 174 1349 169 1353 175 1347 170 1352 176 5961 177 # name: Power type: parsed protocol: NEC address: 71 00 00 00 -command: 4a 00 00 00 +command: 4A 00 00 00 # name: Power type: parsed @@ -982,26 +982,26 @@ command: 01 00 00 00 name: Power type: parsed protocol: NECext -address: 50 ad 00 00 +address: 50 AD 00 00 command: 00 00 00 00 # name: Power type: parsed protocol: NECext -address: 50 ad 00 00 +address: 50 AD 00 00 command: 02 00 00 00 # name: Power type: parsed protocol: NEC address: 50 00 00 00 -command: 3f 00 00 00 +command: 3F 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 06 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -1013,13 +1013,13 @@ name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 -command: 0b 00 00 00 +command: 0B 00 00 00 # name: Power type: parsed protocol: NECext address: 83 55 00 00 -command: c2 00 00 00 +command: C2 00 00 00 # name: Power type: parsed @@ -1030,20 +1030,20 @@ command: 51 00 00 00 name: Power type: parsed protocol: NECext -address: 00 bd 00 00 +address: 00 BD 00 00 command: 01 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 00 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed protocol: Samsung32 address: 16 00 00 00 -command: 0f 00 00 00 +command: 0F 00 00 00 # name: Power type: parsed @@ -1064,561 +1064,561 @@ address: 86 02 00 00 command: 49 00 00 00 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2383 609 1214 600 612 580 1213 608 614 583 1210 605 607 586 616 611 1192 599 613 608 614 579 613 615 607 26670 2387 601 1212 600 612 589 1214 603 609 586 1217 595 607 594 618 606 1187 602 610 609 613 588 614 610 612 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 15 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 7761 176 11308 546 957 540 1958 538 970 537 1955 541 962 545 1953 543 964 543 962 545 957 540 970 548 960 547 1945 541 1950 546 965 542 1953 543 962 545 1945 540 970 537 1958 538 7881 172 7744 172 11318 536 971 536 1956 540 963 534 1964 542 966 541 1951 535 968 539 971 536 971 536 969 538 964 533 1965 541 1954 542 963 534 1956 540 971 536 1959 537 968 539 1951 535 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 3444 1767 413 486 420 1343 419 478 418 485 411 490 416 479 417 489 417 482 414 485 421 482 414 483 413 490 416 485 411 1343 419 487 419 480 416 483 413 490 416 482 414 488 418 483 413 483 413 492 414 1345 417 482 414 489 417 480 416 487 419 482 414 481 415 491 415 484 412 1347 415 488 418 1338 414 1348 414 1347 415 1340 412 494 412 487 419 1340 412 491 415 1341 421 1341 421 1340 412 1343 419 487 419 1339 413 74311 3445 1753 437 461 445 1316 446 456 440 455 441 465 441 458 438 461 445 458 438 460 436 466 440 461 445 451 445 460 446 1313 439 460 446 457 439 459 437 465 441 460 446 450 436 469 437 462 444 456 440 1322 440 457 439 464 442 459 437 459 437 468 438 461 445 455 441 462 444 1312 440 463 443 1317 445 1310 442 1323 439 1320 442 457 439 464 442 1315 437 466 440 1320 442 1313 439 1326 446 1313 439 460 446 1317 445 +type: parsed +protocol: Kaseikyo +address: 80 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 278 1845 274 808 271 806 273 812 278 805 275 805 274 1840 279 1844 275 809 281 1836 272 806 274 812 278 805 274 1842 277 802 277 44956 279 1842 277 804 275 802 277 808 271 811 279 1838 281 798 271 814 276 1844 275 806 273 1841 278 1845 274 1846 273 808 271 1843 276 44959 275 1845 274 807 272 805 275 811 279 804 275 805 274 1839 280 1844 275 808 271 1845 274 805 274 811 279 804 275 1841 278 801 278 44955 280 1841 278 802 277 801 278 807 272 810 280 1837 271 807 272 813 277 1843 276 805 274 1839 280 1843 276 1845 274 807 272 1842 277 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 881 909 1750 928 875 927 876 921 872 929 874 927 876 918 875 930 873 1815 874 924 1745 937 876 88694 880 922 1747 933 880 914 879 926 877 922 871 927 876 927 876 920 873 1818 871 929 1740 934 879 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 509 1717 504 629 512 631 510 627 504 633 508 633 508 1713 508 1719 512 1713 508 625 505 637 504 633 508 629 512 629 512 623 508 1719 512 626 505 628 513 631 510 627 514 623 507 632 509 1713 508 632 509 1716 505 1715 506 1724 507 1716 505 1719 512 1715 506 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 506 493 505 4059 505 5051 501 506 502 4065 499 511 497 4063 501 5058 504 504 504 4060 504 5052 500 507 501 4066 498 5056 506 5042 500 515 503 119614 504 505 503 4065 499 5051 501 511 497 4069 505 499 499 4072 502 5050 502 506 502 4066 498 5053 499 512 506 4060 504 5044 498 5061 501 508 500 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8887 4470 532 1738 513 1708 533 1708 533 577 533 576 534 569 531 582 538 1705 536 571 539 1707 534 571 539 571 539 570 540 1699 532 581 539 568 532 575 535 576 534 571 539 571 539 569 541 1698 533 1717 534 1708 533 1710 531 1716 535 1706 535 1711 540 1705 536 567 533 580 540 567 533 39042 8915 2231 530 94849 8917 2256 535 +type: parsed +protocol: NECext +address: 87 22 00 00 +command: E0 1F 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8313 4161 515 1574 514 1571 507 569 510 562 507 563 506 562 507 568 511 562 507 1580 508 1577 511 1582 506 567 513 1575 513 554 505 571 509 564 505 22604 513 1573 505 1589 509 563 506 564 505 562 507 569 511 562 507 563 506 1579 509 1584 514 1576 512 558 511 1574 514 562 507 565 515 556 513 22593 514 1581 507 1583 505 564 505 563 506 570 510 563 506 564 505 562 507 1586 512 1578 510 1577 511 557 512 1581 507 566 514 556 513 555 514 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8735 4383 558 573 557 550 560 568 562 544 566 1722 560 540 560 1732 560 544 566 1719 563 1701 560 1723 559 1704 557 574 556 1699 562 574 556 1703 559 1727 565 1698 563 1721 561 546 564 1723 559 541 559 577 564 541 559 571 560 548 562 565 566 1697 565 567 564 1693 558 1733 559 1701 560 39926 8754 2247 565 92341 8758 2243 589 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3298 3336 821 2506 825 881 820 2505 826 2529 823 856 825 2524 817 866 825 2528 813 2513 818 888 813 862 819 887 814 865 826 2522 820 864 827 2526 815 861 820 887 814 2510 821 885 816 863 818 2531 821 2512 819 2559 793 32401 3298 3349 818 2507 824 882 819 2509 822 2527 814 868 823 2530 821 855 826 2531 821 2504 827 879 822 857 824 875 816 867 824 2529 823 854 827 2530 821 853 817 889 822 2506 825 873 818 866 825 2527 814 2513 818 2564 788 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8840 4439 532 566 534 566 534 1668 532 1674 536 1669 531 562 538 566 534 563 537 1667 533 567 533 563 537 563 537 562 538 1662 538 1671 529 568 532 565 535 566 534 1668 532 1674 536 1669 531 562 538 1672 528 1675 536 1668 532 1675 535 559 531 1676 534 565 535 558 532 1678 532 565 535 562 538 563 537 1665 535 565 535 1670 530 1669 531 572 538 1666 534 1669 531 1676 534 22777 8858 4447 535 92577 8858 4413 538 +type: parsed +protocol: NEC42 +address: 1C 01 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 289 2112 261 2109 295 2101 262 918 294 912 259 915 297 2098 265 916 296 909 262 2107 297 905 266 913 289 918 263 910 292 909 262 918 294 24789 263 2106 298 2098 265 2110 294 913 258 916 296 905 266 2108 296 911 260 914 288 2107 266 914 298 908 263 911 291 910 261 919 293 913 258 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8898 4453 569 578 573 577 574 571 570 1745 567 1747 565 1743 569 583 568 579 572 1740 572 1744 568 1742 570 579 572 576 575 568 573 1746 566 1746 566 580 571 1745 567 577 574 576 575 1739 573 569 572 581 570 577 574 1738 574 576 575 1735 567 1748 574 574 567 1742 570 1748 574 1737 575 41005 8876 2261 571 93850 8898 2264 568 +type: parsed +protocol: NEC +address: 38 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3215 1637 410 430 405 439 406 1242 408 435 410 1242 408 428 407 440 405 435 410 1240 410 1243 407 431 404 440 405 437 408 1238 402 1254 406 434 401 439 406 438 407 431 404 440 405 437 408 428 407 439 406 434 401 439 406 438 407 1241 409 434 401 441 404 432 403 444 401 1249 401 439 406 438 407 1241 409 434 401 441 404 433 402 444 401 1249 401 439 406 1248 402 436 409 434 401 441 404 433 402 444 401 439 406 45471 3239 1614 403 435 400 444 401 1250 400 437 408 1248 402 438 407 433 402 442 403 1245 405 1248 423 420 405 431 404 443 402 1248 402 1248 422 421 404 435 400 443 402 440 405 431 404 443 402 438 407 433 402 442 403 435 400 443 402 1250 400 436 399 447 408 432 403 438 407 1246 404 434 401 443 402 1250 400 436 399 447 408 432 403 437 408 1246 404 434 401 1253 407 434 401 436 399 447 408 432 403 437 408 436 399 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7928 3948 504 515 503 518 500 1583 505 516 502 1584 504 510 508 516 502 516 502 3952 510 1579 509 507 501 1587 501 519 510 1571 507 518 500 517 501 517 501 23073 7931 3943 509 514 504 515 503 1578 500 524 505 1580 508 510 508 514 504 511 507 3951 511 1576 502 513 505 1586 502 515 503 1582 506 515 503 513 505 516 502 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8837 4464 538 610 531 619 532 613 538 1748 534 1750 532 611 540 613 538 609 532 615 536 614 537 608 533 1753 539 1745 537 606 535 618 533 614 537 609 532 619 532 613 538 611 540 609 532 611 540 1748 534 1749 533 1750 532 1754 538 1743 539 1747 535 1750 532 1747 535 618 533 613 538 44105 8864 2224 537 93399 8912 2202 538 +type: parsed +protocol: NECext +address: 18 18 00 00 +command: C0 3F 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 492 4975 496 4993 498 498 500 4056 498 504 494 4055 499 4963 497 532 496 4031 492 4996 495 502 496 4060 494 4972 499 4990 491 506 492 4063 491 511 497 4052 492 4970 490 539 500 4027 496 103358 500 4961 500 4995 496 505 493 4056 498 499 499 4057 497 4969 491 533 496 4026 497 4997 494 508 490 4059 495 4967 494 5001 490 511 497 4053 491 505 493 4063 491 4975 496 528 490 4032 491 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 2357 610 1183 592 1191 614 1179 595 1188 618 584 613 1180 593 588 613 1190 612 590 605 587 613 589 605 587 25398 2355 623 1180 591 1181 627 1186 589 1183 618 584 616 1187 587 584 614 1189 615 587 605 587 615 587 609 593 +type: parsed +protocol: SIRC +address: 01 00 00 00 +command: 2F 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3425 3482 848 2607 846 2639 845 2608 846 2639 845 2612 852 2624 850 2613 851 911 851 885 847 919 843 891 851 915 847 890 852 907 845 897 845 917 845 891 851 915 847 887 845 2639 845 2612 852 2625 849 2613 851 2630 844 34282 3455 3478 852 2601 852 2633 851 2605 848 2629 845 2617 847 2633 851 2604 849 917 845 890 852 913 849 889 843 915 847 896 846 916 846 890 852 914 848 885 847 919 843 895 847 2630 844 2617 847 2634 850 2605 848 2636 848 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 500 500 498 4066 498 5058 504 502 506 4061 503 508 500 4060 504 5055 497 5055 497 511 497 4071 503 5047 505 507 501 4065 499 5049 503 512 496 124314 501 508 500 4067 507 5043 499 513 505 4060 504 501 497 4073 501 5052 500 5052 500 512 496 4066 498 5058 504 506 502 4058 506 5053 499 509 499 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7763 174 8817 169 10842 544 1955 541 967 540 1952 544 959 538 972 546 962 545 1947 538 1952 544 967 540 1955 541 964 543 1947 539 972 546 1949 547 7873 170 7746 170 10350 175 11811 543 960 537 1961 535 972 535 970 537 965 542 1956 540 1956 540 965 542 1947 539 973 534 1960 536 969 538 1952 534 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 2570 2682 1189 1208 1186 2665 1186 1217 1187 2668 1183 1215 1179 2671 1190 2695 1186 1187 1187 2692 1179 2671 1190 1213 1181 1193 1191 1207 1187 2663 1188 1215 1179 2676 1185 46941 2563 2685 1186 1191 1183 2698 1184 1188 1186 2691 1180 1197 1187 2694 1187 2666 1185 1210 1184 2674 1187 2695 1186 1185 1189 1206 1188 1189 1185 2696 1186 1186 1187 2689 1182 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 873 916 1773 906 877 925 878 919 874 928 875 925 878 1806 1770 914 879 1809 870 928 1772 88684 870 926 1774 908 875 926 877 917 876 929 874 925 878 1809 1777 905 877 1808 871 930 1770 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 26 00 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 874 906 877 912 1767 904 879 908 874 918 875 915 878 907 875 920 873 1795 874 914 1775 897 875 88704 879 914 868 922 1767 897 875 919 874 915 878 911 872 920 873 914 879 1792 877 914 1775 889 873 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3325 1560 406 444 401 453 402 1226 404 449 406 1226 404 443 402 454 401 449 406 1224 406 1228 402 446 409 444 401 451 404 1223 407 1230 410 440 405 445 410 443 402 446 409 444 401 451 404 442 403 453 402 448 407 443 402 451 404 1224 406 448 407 444 401 445 410 446 409 1221 409 442 403 1231 409 439 406 1227 403 450 405 441 404 452 403 1227 403 448 407 446 409 439 406 447 408 444 401 445 400 456 410 440 405 52348 3320 1553 403 445 400 454 401 1230 400 447 408 1228 402 449 406 444 401 452 403 1225 405 1229 431 421 404 442 403 454 401 1229 401 1229 431 423 402 446 399 455 400 451 404 442 403 453 402 448 407 443 402 451 404 444 401 452 403 1229 401 445 400 457 398 451 404 446 399 1235 405 443 402 1232 408 444 401 1225 405 452 403 447 398 452 403 1231 399 449 406 447 408 443 402 444 401 456 399 450 405 445 400 453 402 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 990 915 980 909 986 924 981 2829 981 934 981 2823 987 923 982 2828 982 933 982 906 989 33895 989 907 988 927 988 900 985 2841 979 915 980 2851 980 909 986 2840 980 914 981 934 981 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 821 5754 848 2490 841 2492 819 2524 817 5726 845 2492 839 5727 844 5757 845 5727 854 2483 848 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 5092 1621 406 2599 406 2598 407 2605 1653 1616 411 2619 1609 1606 1654 1618 409 2623 382 2600 405 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8879 4446 566 1747 565 584 567 1744 568 581 570 1744 568 574 567 586 565 582 569 578 563 1753 570 575 566 1749 563 585 566 1743 569 1749 563 1748 564 582 569 1747 565 580 571 578 573 1741 571 572 569 584 567 580 571 1741 571 578 573 1738 564 1751 572 577 564 1744 568 1750 572 1740 572 41007 8906 2257 565 93855 8872 2265 567 +type: parsed +protocol: NEC +address: 15 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1144 1010 6795 26754 1151 997 6798 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1144 1009 1120 1006 1143 1991 1116 26758 1146 1006 1123 1003 1146 1988 1119 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 46238 169 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8906 4165 572 1672 569 1678 563 640 572 637 565 643 569 633 569 643 569 1674 567 639 563 1684 567 637 565 1681 570 1675 566 1673 568 1681 570 636 566 640 572 637 565 639 563 1684 567 640 572 630 572 640 572 634 568 1675 566 1681 570 1670 571 638 564 1681 570 1669 572 1678 563 1680 571 40485 8898 2252 570 85621 8955 2194 567 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 446 1191 449 1194 446 1195 445 1204 446 1200 1316 459 447 1193 447 1202 448 1197 443 1201 449 1191 449 34491 443 1204 446 1197 443 1198 442 1207 443 1202 1314 436 440 1201 449 1199 441 1205 445 1198 442 1199 441 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4268 4327 522 1593 516 1603 516 1597 522 519 520 520 519 515 514 531 518 520 519 519 520 521 518 519 520 1597 522 1595 514 1597 522 1599 520 1595 514 524 515 1604 515 521 518 523 516 524 515 519 520 525 514 524 515 1599 520 522 517 1596 513 1605 514 1602 517 1595 514 1607 522 1592 516 40481 8748 2187 523 93986 8721 2189 521 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 247 3006 244 153 178 1007 251 117 637 597 381 678 218 156 175 529 382 679 217 157 174 24963 247 3038 252 117 219 994 249 119 217 483 250 117 173 531 278 779 173 167 169 569 383 679 217 156 175 126538 246 3039 251 118 218 995 247 120 195 504 249 118 172 532 277 780 172 168 178 560 382 680 216 157 174 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 579 572 578 573 572 569 581 570 1744 568 575 566 587 564 582 569 1743 569 1747 565 1745 567 1748 564 584 567 1741 571 1747 565 1747 565 1747 565 1751 571 1739 563 1752 570 578 563 1745 567 1751 572 1741 571 575 566 585 566 578 573 577 564 1750 573 571 570 583 568 579 572 41007 8905 2258 574 93846 8871 2266 566 +type: parsed +protocol: NEC +address: 10 00 00 00 +command: EF 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4278 4318 521 517 522 520 519 517 522 520 519 521 518 516 513 531 518 520 519 1595 514 1605 514 1599 520 1598 521 1595 513 1598 521 1600 519 1596 513 1602 517 1601 518 1595 514 1604 515 525 514 520 519 526 513 525 514 524 515 527 522 513 516 526 513 1603 516 1595 514 1607 522 1593 516 40481 8749 2186 524 93985 8722 2189 521 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 2746 8423 2744 19607 2746 19601 2742 8431 2745 8424 2742 19608 2745 8419 2747 19608 2745 19607 2746 8422 2744 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 170 6683 174 4889 175 10382 372 849 821 2498 176 10378 264 2479 842 2492 839 2475 846 2483 838 2481 840 2495 836 2477 844 845 846 37009 172 6681 176 4888 175 10381 373 848 924 2395 844 2490 174 10383 248 2492 172 10386 245 2495 169 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8898 4453 569 578 573 577 574 1737 565 584 567 582 569 574 567 1751 572 1741 571 1741 571 1744 568 576 575 1741 571 1743 569 1739 573 579 572 575 566 581 570 580 571 574 567 1748 575 1739 573 570 571 582 569 578 573 1739 573 1742 570 1740 572 577 574 575 566 1742 570 1749 574 1738 574 41006 8875 2262 570 93850 8907 2256 566 +type: parsed +protocol: NEC +address: C4 00 00 00 +command: 18 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 37 00 00 00 +command: 12 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 1745 567 1749 563 1746 566 584 567 1747 565 1743 569 583 568 579 572 575 566 584 567 578 563 1752 571 578 563 580 571 1747 565 1747 565 581 570 1746 566 578 573 577 564 1751 572 571 570 583 568 579 572 1740 572 578 563 1747 565 1750 573 576 565 1743 569 1749 563 1749 563 41017 8906 2257 565 93855 8872 2265 567 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 179 2644 178 8174 170 2646 176 8181 173 2648 174 8177 177 2640 172 5419 174 5413 170 2649 173 2644 178 2646 176 2646 176 5409 174 28831 174 2651 171 8183 171 2648 174 8174 170 2655 177 8177 177 2642 170 5412 171 5420 173 2649 173 2646 176 2640 172 2653 169 5419 174 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 174 2648 174 8178 176 2640 171 8185 169 2653 169 8182 172 2645 177 2647 557 2264 558 5027 174 5410 173 5418 175 5413 170 28837 168 2649 173 8184 170 2652 170 8181 173 2643 169 8188 176 2646 176 2643 168 2648 174 5417 176 5411 172 5413 170 5413 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 706 266 139 268 137 173 173 198 234 178 126768 175 299 169 86 275 130 267 138 172 230 177 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 554 1922 584 3809 582 3782 578 3821 580 1920 555 1941 544 1922 574 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 476 1470 465 3479 474 3469 474 3477 475 1467 468 1471 474 27473 472 1474 472 3475 467 3478 475 3468 474 1471 475 1468 467 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 301 2188 236 2169 235 2205 230 1009 234 1070 183 1064 179 2198 206 1046 207 1069 173 2207 207 1042 211 1062 201 1043 210 1032 231 1005 237 1039 234 1006 236 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4453 570 1744 568 582 569 1741 571 1744 568 580 571 1738 564 1754 569 578 563 584 567 1749 563 581 570 580 571 1743 569 573 568 585 566 1746 566 580 571 580 571 1739 563 586 565 1749 563 579 572 582 569 577 564 1748 564 1752 571 574 567 1748 564 584 567 1742 570 1748 564 1747 565 41015 8898 2265 567 93853 8875 2262 570 +type: parsed +protocol: NEC +address: 6D 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 20 00 00 00 +command: 11 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: A0 00 00 00 +command: 0B 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 28 00 00 00 +command: 0B 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: FF 00 00 00 +command: 3F 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8904 4446 576 572 569 581 570 575 566 584 567 582 569 1739 573 579 572 575 566 1746 566 1750 572 1738 574 1741 571 1742 570 573 568 1750 572 1740 572 1740 572 578 573 572 569 581 570 1744 568 574 567 586 575 572 569 578 573 1742 570 1740 572 1743 569 579 572 1737 565 1753 570 1743 569 41010 8881 2257 565 93855 8903 2259 573 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8878 4448 564 584 567 583 568 577 564 586 565 584 567 1741 571 582 569 1743 569 1743 569 1746 566 1744 568 1747 565 1749 563 579 572 1747 565 581 570 1743 569 1746 566 578 573 1743 569 579 572 571 570 583 568 579 572 575 566 584 567 1743 569 581 570 1744 568 1740 572 1746 566 1746 566 41013 8898 2264 568 93853 8872 2265 567 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8900 4450 572 575 566 585 566 578 573 1743 569 579 572 1736 566 587 574 572 569 1743 569 1747 565 1745 567 582 569 1745 567 575 566 1753 570 1742 570 1742 570 1746 566 578 573 1742 570 578 573 570 571 582 569 578 573 574 567 583 568 1742 570 579 572 1742 570 1738 574 1744 568 1744 568 41012 8871 2266 566 93855 8903 2258 574 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8872 4454 568 1745 567 1749 563 1747 565 1750 562 1752 571 1737 565 1754 568 1743 569 578 563 587 564 581 570 580 571 577 564 579 572 581 570 576 565 1748 564 1751 572 1739 563 1752 571 1743 569 1739 563 590 571 575 566 581 570 580 571 574 567 583 568 580 571 572 569 1750 562 1749 563 41017 8905 2257 575 93846 8871 2266 566 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 176 7764 173 11361 544 1951 545 1948 176 8815 171 2319 177 2322 174 2321 175 2318 178 2313 173 18281 170 7746 170 11369 536 1954 542 1957 539 969 538 1954 542 1949 536 1962 534 1960 174 2320 176 2315 170 2328 178 2317 168 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 172 23035 176 2267 178 2285 170 2270 175 2288 177 11602 222 2218 216 2246 173 183 173 935 221 218 174 864 221 1250 171 1310 223 2219 216 2247 218 1244 223 216 176 869 170 1296 217 2239 216 1254 223 216 176 866 219 9127 169 7642 173 2284 171 2273 172 2290 175 2263 171 10143 178 10623 222 1245 222 217 175 1843 220 2226 219 1264 223 1237 174 183 178 952 219 2222 223 216 176 866 219 1249 172 9190 173 7637 178 2266 169 2286 169 2280 175 2284 171 10125 175 10622 224 215 177 868 216 2228 217 2238 171 1299 224 215 177 865 174 183 173 934 222 216 176 1848 215 1247 220 1265 222 762 170 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7410 1482 382 2742 375 2747 380 2751 1630 1535 400 2724 1657 1529 1629 1538 407 2720 407 2716 401 2722 4125 1549 376 2751 376 2748 379 2744 1626 1541 405 2723 1658 1530 1628 1531 404 2726 401 2726 401 2723 4124 1542 383 2747 380 2747 380 2745 1626 1534 401 2729 1652 1539 1629 1532 403 2719 408 2722 405 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4277 4319 520 518 521 521 518 518 521 1597 522 1594 515 1597 522 1599 520 1594 515 1600 519 1600 519 1594 515 526 513 527 522 512 517 528 521 517 522 516 513 1605 514 522 517 525 514 525 514 521 518 526 513 525 514 1600 519 523 516 1597 522 1596 513 1603 516 1595 514 1607 522 1593 516 40481 8749 2186 524 93986 8721 2188 522 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 1325 431 445 1199 1317 455 441 1207 443 1202 1294 457 449 1190 440 1209 441 1205 445 1198 1318 454 442 93237 1320 434 442 1201 1325 448 448 1200 440 1205 1291 460 446 1193 447 1202 448 1198 442 1201 1325 447 449 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8876 4450 572 575 566 585 566 578 573 577 564 585 566 577 564 589 572 574 567 1745 567 1749 563 1747 565 1750 562 1751 571 1737 565 1754 569 1743 569 1743 569 1747 565 579 572 1743 569 579 572 571 570 583 568 579 572 575 566 584 567 1743 569 581 570 1744 568 1740 572 1746 566 1746 566 41013 8898 2265 567 93853 8873 2264 568 +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0B 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 300 1791 297 744 295 743 296 751 298 745 294 747 302 736 293 1837 271 745 294 747 302 1793 295 752 297 1802 296 1801 297 742 297 1806 302 31592 296 1801 297 742 297 749 300 744 295 745 294 745 294 752 297 1829 269 746 293 745 294 1809 300 744 295 1802 296 1799 299 748 301 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 2003 177 2899 177 1996 174 2908 168 2910 177 2000 170 2004 176 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8898 4173 564 642 570 1677 564 1677 564 645 567 640 572 631 571 641 571 635 567 639 563 1683 568 1673 568 641 571 636 566 637 565 647 565 641 571 634 568 642 570 1671 570 639 563 1682 569 632 570 643 569 636 566 1677 564 1683 568 636 566 1680 571 636 566 1674 567 1682 569 1674 567 40489 8904 2246 566 85626 8902 2248 564 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8897 4454 569 578 573 1743 569 576 565 1750 572 576 575 1733 569 584 567 1745 567 1745 567 583 568 1742 570 579 572 1742 570 573 568 1750 573 574 567 580 571 580 571 573 568 582 569 580 571 572 569 584 567 1744 568 1744 568 1748 575 1735 567 1749 574 1740 572 1736 566 1752 571 576 575 41005 8878 2259 563 93858 8901 2260 572 +type: parsed +protocol: NEC +address: AA 00 00 00 +command: 80 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 51 00 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8880 4446 566 1747 565 585 566 578 573 577 564 1750 573 571 570 1748 564 582 569 578 573 1743 569 1741 571 1744 568 580 571 1737 565 588 563 1749 563 583 568 582 569 576 565 1750 573 576 565 578 573 580 571 576 565 1747 565 1751 571 1738 564 586 565 1749 563 1745 567 1751 572 1741 571 41008 8905 2258 574 93846 8871 2266 566 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3892 3856 525 978 529 977 530 969 528 977 530 974 523 975 532 1924 531 971 526 1924 531 975 532 1916 529 976 531 1921 524 1947 508 1925 530 1920 525 1926 529 1925 530 970 527 1927 528 976 531 1915 530 978 529 1921 1033 9201 3871 3867 524 977 530 975 522 981 526 972 525 983 524 978 529 1921 524 982 525 1923 532 973 524 1928 527 971 526 1931 524 1950 505 1922 523 1931 524 1924 531 1923 532 972 525 1922 523 985 533 1918 527 975 532 1922 1032 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8900 4451 571 576 575 1742 570 1739 573 1742 570 578 573 1736 566 1752 570 576 575 1737 575 575 566 579 572 578 573 1741 571 571 570 583 568 1745 567 579 572 578 573 1738 574 575 566 1748 575 568 573 581 570 576 575 1737 565 1751 572 573 568 1747 576 573 568 1741 571 1747 565 1747 565 41014 8878 2260 562 93858 8901 2261 571 +type: parsed +protocol: NEC +address: 6E 00 00 00 +command: 14 00 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 07 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 875 904 1745 924 879 913 880 1786 873 919 874 917 1742 922 871 1802 877 912 1747 921 872 88714 880 907 1742 930 873 917 876 1788 871 924 879 910 1749 919 874 1798 871 916 1743 928 875 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4758 1543 403 2731 407 2726 402 2739 1601 1514 401 2760 1580 1530 1577 1540 406 2758 400 2708 1602 1535 400 2740 408 2729 409 2726 401 2731 1599 1520 405 2758 1572 1540 1578 1532 403 2737 431 2706 1604 1535 411 2722 405 2734 403 2734 404 2731 1599 1512 403 2764 1576 1539 1578 1533 402 2730 428 2712 1608 1534 402 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8873 4453 570 578 563 1753 570 575 566 1749 563 585 566 1742 570 583 568 1744 568 1744 568 582 569 1741 571 578 573 1741 571 572 569 1749 563 583 568 1745 567 1748 564 1746 566 583 568 581 570 1738 564 589 572 1740 572 574 567 584 567 577 564 1752 571 1743 569 573 568 1751 572 575 566 41014 8900 2263 569 93851 8878 2259 563 +type: parsed +protocol: NEC +address: AA 00 00 00 +command: A7 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 171 313 176 798 337 133 600 232 170 126777 176 65 169 496 176 200 609 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 500 527 491 4033 500 4986 495 510 498 4054 500 499 499 4048 496 4974 497 530 499 4026 497 4989 492 513 495 4057 497 4967 493 4992 499 506 492 4060 494 505 493 4054 500 98563 497 529 500 4025 498 4988 493 512 496 4056 498 501 497 4050 493 4976 495 532 497 4028 495 4991 500 505 493 4059 495 4969 491 4994 497 508 490 4062 492 507 491 4056 498 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 879 901 871 1796 1770 903 869 917 876 916 877 913 880 906 877 918 875 914 879 1788 1768 1784 875 87826 871 921 872 1797 1769 897 875 919 874 915 878 910 873 920 873 914 879 913 870 1800 1776 1767 871 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 874 905 1774 894 878 914 879 908 875 917 876 915 878 907 876 919 874 1793 876 913 1777 895 878 88703 872 920 1769 901 872 913 870 925 878 910 873 916 877 916 877 910 873 1798 871 919 1770 894 878 +type: parsed +protocol: RC5 +address: 00 00 00 00 +command: 0C 00 00 00 +# +name: Power +type: parsed +protocol: Kaseikyo +address: 90 02 20 00 +command: D0 03 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 3339 1714 415 445 420 1283 418 440 415 448 418 444 422 435 420 446 420 440 415 445 421 443 412 445 421 443 412 449 416 1279 412 455 421 439 416 443 412 452 414 444 411 452 414 1287 414 442 413 453 413 1287 414 446 419 444 422 437 418 445 421 441 414 442 413 452 414 447 419 1281 420 443 412 1285 416 1287 414 1287 414 1282 419 447 419 441 414 1286 415 448 418 1280 421 1282 419 443 412 1283 418 448 418 1283 418 73871 3336 1694 414 444 411 1291 410 452 414 442 413 453 413 448 418 442 413 450 416 443 412 450 416 447 419 437 418 448 418 1282 419 441 414 449 417 442 413 449 417 446 420 436 419 1287 414 446 420 440 415 1288 413 445 410 453 413 449 417 439 416 450 416 445 421 439 416 447 419 1279 412 451 415 1287 414 1282 419 1287 414 1285 416 444 411 453 413 1285 416 447 419 1283 418 1278 413 453 413 1287 414 446 419 1284 417 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4411 4332 558 1660 561 596 565 612 559 597 564 617 565 585 566 620 561 591 560 620 561 595 566 611 560 597 564 1653 558 592 559 627 565 589 562 617 564 1630 560 617 564 592 559 22591 4439 4322 558 1639 561 618 563 590 561 622 560 592 559 624 557 597 564 612 559 600 561 618 563 590 561 622 559 1628 562 621 561 594 567 609 562 597 564 1652 559 595 566 617 564 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3444 1767 413 487 419 1274 417 481 415 1277 414 488 418 1267 414 492 414 1276 415 484 412 1282 419 478 418 1275 416 1276 415 480 416 1280 421 479 417 1272 419 1275 416 1272 419 1274 417 484 412 484 412 493 413 1277 414 485 421 1273 418 479 417 486 420 1271 420 476 420 486 420 479 417 482 414 1280 411 1276 415 488 418 1273 418 478 418 488 418 481 415 1275 416 487 419 478 418 485 411 1280 421 475 421 1275 416 1273 418 69071 3439 1759 441 456 440 1253 438 463 443 1243 438 468 438 1251 440 460 446 1247 444 454 442 1251 440 461 445 1241 440 1256 445 455 441 1248 443 461 445 1242 439 1254 447 1245 446 1240 441 465 441 458 438 462 444 1249 442 456 440 1252 439 463 443 452 444 1252 439 461 445 454 442 461 445 452 444 1249 442 1250 441 454 442 1254 437 463 443 456 440 463 443 1245 446 456 440 462 444 451 445 1251 440 460 436 1253 438 1256 445 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 8705 4317 583 682 581 688 585 678 585 1721 581 1722 580 681 582 690 583 682 581 1721 581 1725 587 1713 579 689 584 683 580 1718 584 1724 588 1714 588 677 586 683 580 683 580 1726 586 680 583 678 585 687 586 679 584 1718 584 1721 581 1719 583 685 588 1716 586 1713 579 1729 583 1719 583 41145 8706 2217 585 94686 8705 2217 584 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8888 4470 532 576 534 576 534 571 539 572 538 1706 535 568 532 581 529 578 532 1711 530 581 529 1711 530 1717 534 574 536 1703 538 575 535 572 538 1705 536 1711 530 1711 530 1716 535 1709 532 571 529 585 535 571 529 579 531 579 531 574 536 574 536 573 537 1701 530 1720 531 1712 529 39045 8912 2261 540 94838 8911 2235 536 +type: parsed +protocol: NECext +address: 10 2D 00 00 +command: 1F E0 00 00 +# +name: Power +type: parsed +protocol: RC5 +address: 05 00 00 00 +command: 0C 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 874 915 1774 904 879 923 870 1816 1770 1800 1776 904 879 1805 874 931 1769 909 874 88698 876 927 1773 904 879 922 871 1819 1767 1796 1770 914 879 1809 870 928 1772 910 873 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 178 7753 174 2308 178 2284 171 2316 170 2298 177 10228 174 10724 223 1256 221 217 175 1868 169 2293 172 1327 216 1263 178 1316 217 2245 220 218 174 887 218 1261 170 10707 174 7752 175 2296 169 2314 171 2293 172 2307 179 10216 176 6265 174 10729 219 1258 219 1272 215 1268 173 2310 221 1255 222 217 175 877 172 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 532 1692 559 561 529 574 567 559 531 566 564 555 535 1694 557 568 532 1691 560 560 530 573 557 568 532 565 565 555 535 567 563 1688 533 564 567 554 536 567 563 562 538 558 562 558 532 1697 565 561 539 1683 558 1689 532 1697 564 1687 534 1689 562 1684 537 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 874 915 1774 904 879 923 870 927 876 1814 876 925 1775 900 872 1821 879 920 1769 909 874 88702 871 926 1774 907 876 925 878 917 876 1817 873 927 1773 905 878 1813 876 921 1769 912 871 +type: parsed +protocol: RC5 +address: 03 00 00 00 +command: 0C 00 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 12 FF 00 00 +command: 0E F1 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8884 4474 538 569 531 1716 535 570 530 580 530 1715 536 567 533 580 530 577 533 1710 531 1715 536 1705 536 1710 531 1714 537 1702 529 1720 531 1712 529 578 532 1715 536 1705 536 1710 531 577 533 570 530 584 536 571 529 1714 537 573 537 568 532 578 532 1713 538 1701 530 1719 532 1711 530 39044 8913 2260 531 94848 8907 2239 532 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 446 1694 455 1706 453 1705 424 628 452 597 452 622 458 1673 456 625 455 594 455 1706 454 590 459 621 459 591 458 616 453 591 458 622 539 22750 459 1675 454 1733 427 1712 427 622 458 588 451 622 458 1681 458 618 451 595 454 1705 455 598 451 625 454 592 457 616 453 598 451 626 535 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 3429 3445 875 2555 868 875 867 871 871 2560 873 868 874 2551 872 874 868 871 871 869 873 870 872 865 867 2565 868 873 869 2556 867 2567 866 874 868 2560 873 870 872 2555 868 2564 869 2586 847 2577 846 2589 844 870 872 32983 3470 3430 869 2559 874 868 874 867 875 2550 873 873 869 2559 874 865 867 877 875 862 870 873 869 872 870 2555 868 877 875 2554 869 2559 874 869 873 2554 869 873 869 2562 871 2553 870 2590 843 2586 847 2581 842 876 866 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8873 4452 571 1743 569 580 571 574 567 583 568 1746 566 1742 570 1748 564 582 569 578 563 1753 570 1740 572 1743 569 579 572 571 570 583 568 1744 568 579 572 578 573 572 569 1746 566 582 569 574 567 586 565 582 569 1743 569 1746 566 1744 568 581 570 1745 567 1741 571 1747 565 1746 566 41014 8898 2264 568 93853 8874 2263 569 +type: parsed +protocol: NEC +address: 71 00 00 00 +command: 08 00 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 83 00 00 00 +command: FF 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 -data: 8902 4448 574 1739 573 1742 570 575 566 584 567 581 570 573 568 585 566 1746 566 580 571 580 571 1739 573 1742 570 1743 569 1739 573 1745 567 579 572 1741 571 1744 568 1742 570 1745 567 1747 565 1743 569 1749 573 1739 573 573 568 583 568 576 575 575 566 583 568 575 566 587 574 572 569 41011 8871 2266 566 93854 8902 2260 572 -# -name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4275 4320 519 520 519 523 516 520 519 1599 520 520 519 515 524 521 518 520 519 1595 524 1595 524 1588 520 521 518 1599 520 1591 517 1603 516 1599 520 1595 524 1594 525 1588 521 1597 522 518 521 513 526 519 520 518 521 517 522 520 519 517 522 519 520 1597 522 1589 519 1601 518 1597 522 40475 8724 2186 514 93995 8752 2183 516 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 10380 4892 599 620 592 605 597 620 592 604 598 623 589 2081 598 627 595 2080 599 2101 598 2105 574 2099 590 2088 591 2111 599 591 590 2116 594 599 593 626 596 2082 597 619 593 2086 593 626 596 594 598 627 595 598 594 2106 593 604 598 2100 589 607 595 2107 593 2079 590 2116 594 2082 750 41149 8722 2109 590 94682 8727 2104 596 # name: Power -type: raw -frequency: 38000 -duty_cycle: 0.33 -data: 8879 4446 566 1747 565 1751 571 573 568 582 569 580 571 571 570 584 567 1744 568 579 572 578 573 1737 565 1751 572 1742 570 1738 564 1754 568 578 573 574 567 584 567 577 564 1752 571 577 564 580 571 582 569 577 564 1748 564 1752 571 1739 563 587 564 1750 572 1736 566 1752 571 1742 570 41009 8903 2260 572 93848 8880 2257 565 +type: parsed +protocol: NEC +address: 83 00 00 00 +command: 08 00 00 00 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 4271 4324 515 1600 519 1600 519 1594 515 1603 516 1601 518 1593 516 1605 514 1601 518 520 519 522 517 520 519 522 517 523 516 518 521 523 516 522 517 1598 521 1597 522 1591 518 1600 519 521 518 516 523 522 517 521 518 520 519 523 516 520 519 522 517 1599 520 1591 518 1603 516 1599 520 40477 8753 2183 516 93993 8724 2185 515 # name: Power type: raw frequency: 38000 -duty_cycle: 0.33 +duty_cycle: 0.330000 data: 7847 3931 470 1448 467 495 472 1443 472 490 467 1451 464 491 466 499 468 491 466 4413 467 1455 470 486 471 1449 466 495 472 1441 464 501 466 492 465 494 463 22093 7851 3934 467 1454 471 490 467 1446 469 496 471 1446 469 489 468 494 473 484 473 4410 470 1449 466 489 468 1455 470 489 468 1449 466 496 471 486 471 490 467 # name: Power @@ -1656,20 +1656,20 @@ type: parsed protocol: RC5 address: 01 00 00 00 command: 21 00 00 00 -# +# # Model: VIZIO name: Mute type: parsed protocol: NEC address: 04 00 00 00 command: 09 00 00 00 -# +# name: Vol_up type: parsed protocol: NEC address: 04 00 00 00 command: 02 00 00 00 -# +# name: Vol_dn type: parsed protocol: NEC diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index ac7d1a0c5..3d7bd7cd2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.6,, +Version,+,11.7,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1630,6 +1630,7 @@ Function,+,infrared_get_protocol_by_name,InfraredProtocol,const char* Function,+,infrared_get_protocol_command_length,uint8_t,InfraredProtocol Function,+,infrared_get_protocol_duty_cycle,float,InfraredProtocol Function,+,infrared_get_protocol_frequency,uint32_t,InfraredProtocol +Function,+,infrared_get_protocol_min_repeat_count,size_t,InfraredProtocol Function,+,infrared_get_protocol_name,const char*,InfraredProtocol Function,+,infrared_is_protocol_valid,_Bool,InfraredProtocol Function,+,infrared_reset_decoder,void,InfraredDecoderHandler* diff --git a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c index 8acb6751b..d67b204f5 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c @@ -1,11 +1,8 @@ +#include "infrared_common_i.h" + +#include #include #include -#include "infrared.h" -#include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder); diff --git a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c index 9c774617e..f145a585a 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c @@ -1,10 +1,9 @@ -#include -#include "infrared.h" #include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include + +#include +#include +#include +#include static InfraredStatus infrared_common_encode_bits(InfraredCommonEncoder* encoder, uint32_t* duration, bool* level) { diff --git a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c b/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c deleted file mode 100644 index 3dd26e9d8..000000000 --- a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "infrared_common_i.h" -#include "infrared_protocol_defs_i.h" - -const InfraredCommonProtocolSpec protocol_nec = { - .timings = - { - .preamble_mark = INFRARED_NEC_PREAMBLE_MARK, - .preamble_space = INFRARED_NEC_PREAMBLE_SPACE, - .bit1_mark = INFRARED_NEC_BIT1_MARK, - .bit1_space = INFRARED_NEC_BIT1_SPACE, - .bit0_mark = INFRARED_NEC_BIT0_MARK, - .bit0_space = INFRARED_NEC_BIT0_SPACE, - .preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_NEC_BIT_TOLERANCE, - .silence_time = INFRARED_NEC_SILENCE, - .min_split_time = INFRARED_NEC_MIN_SPLIT_TIME, - }, - .databit_len[0] = 42, - .databit_len[1] = 32, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_nec_interpret, - .decode_repeat = infrared_decoder_nec_decode_repeat, - .encode_repeat = infrared_encoder_nec_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_samsung32 = { - .timings = - { - .preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK, - .preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE, - .bit1_mark = INFRARED_SAMSUNG_BIT1_MARK, - .bit1_space = INFRARED_SAMSUNG_BIT1_SPACE, - .bit0_mark = INFRARED_SAMSUNG_BIT0_MARK, - .bit0_space = INFRARED_SAMSUNG_BIT0_SPACE, - .preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE, - .silence_time = INFRARED_SAMSUNG_SILENCE, - .min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME, - }, - .databit_len[0] = 32, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_samsung32_interpret, - .decode_repeat = infrared_decoder_samsung32_decode_repeat, - .encode_repeat = infrared_encoder_samsung32_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_rc6 = { - .timings = - { - .preamble_mark = INFRARED_RC6_PREAMBLE_MARK, - .preamble_space = INFRARED_RC6_PREAMBLE_SPACE, - .bit1_mark = INFRARED_RC6_BIT, - .preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_RC6_BIT_TOLERANCE, - .silence_time = INFRARED_RC6_SILENCE, - .min_split_time = INFRARED_RC6_MIN_SPLIT_TIME, - }, - .databit_len[0] = - 1 + 3 + 1 + 8 + - 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command - .manchester_start_from_space = false, - .decode = infrared_decoder_rc6_decode_manchester, - .encode = infrared_encoder_rc6_encode_manchester, - .interpret = infrared_decoder_rc6_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; - -const InfraredCommonProtocolSpec protocol_rc5 = { - .timings = - { - .preamble_mark = 0, - .preamble_space = 0, - .bit1_mark = INFRARED_RC5_BIT, - .preamble_tolerance = 0, - .bit_tolerance = INFRARED_RC5_BIT_TOLERANCE, - .silence_time = INFRARED_RC5_SILENCE, - .min_split_time = INFRARED_RC5_MIN_SPLIT_TIME, - }, - .databit_len[0] = 1 + 1 + 1 + 5 + - 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command - .manchester_start_from_space = true, - .decode = infrared_common_decode_manchester, - .encode = infrared_common_encode_manchester, - .interpret = infrared_decoder_rc5_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; - -const InfraredCommonProtocolSpec protocol_sirc = { - .timings = - { - .preamble_mark = INFRARED_SIRC_PREAMBLE_MARK, - .preamble_space = INFRARED_SIRC_PREAMBLE_SPACE, - .bit1_mark = INFRARED_SIRC_BIT1_MARK, - .bit1_space = INFRARED_SIRC_BIT1_SPACE, - .bit0_mark = INFRARED_SIRC_BIT0_MARK, - .bit0_space = INFRARED_SIRC_BIT0_SPACE, - .preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE, - .silence_time = INFRARED_SIRC_SILENCE, - .min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME, - }, - .databit_len[0] = 20, - .databit_len[1] = 15, - .databit_len[2] = 12, - .no_stop_bit = true, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_sirc_interpret, - .decode_repeat = NULL, - .encode_repeat = infrared_encoder_sirc_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_kaseikyo = { - .timings = - { - .preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK, - .preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE, - .bit1_mark = INFRARED_KASEIKYO_BIT1_MARK, - .bit1_space = INFRARED_KASEIKYO_BIT1_SPACE, - .bit0_mark = INFRARED_KASEIKYO_BIT0_MARK, - .bit0_space = INFRARED_KASEIKYO_BIT0_SPACE, - .preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE, - .silence_time = INFRARED_KASEIKYO_SILENCE, - .min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME, - }, - .databit_len[0] = 48, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_kaseikyo_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index 2c5ef0fff..fcfc5da2b 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -1,13 +1,16 @@ #include "infrared.h" -#include -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include + #include -#include -#include "infrared_i.h" -#include +#include +#include +#include + +#include "nec/infrared_protocol_nec.h" +#include "samsung/infrared_protocol_samsung.h" +#include "rc5/infrared_protocol_rc5.h" +#include "rc6/infrared_protocol_rc6.h" +#include "sirc/infrared_protocol_sirc.h" +#include "kaseikyo/infrared_protocol_kaseikyo.h" typedef struct { InfraredAlloc alloc; @@ -36,7 +39,7 @@ struct InfraredEncoderHandler { typedef struct { InfraredEncoders encoder; InfraredDecoders decoder; - InfraredGetProtocolSpec get_protocol_spec; + InfraredGetProtocolVariant get_protocol_variant; } InfraredEncoderDecoder; static const InfraredEncoderDecoder infrared_encoder_decoder[] = { @@ -52,7 +55,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_nec_encode, .reset = infrared_encoder_nec_reset, .free = infrared_encoder_nec_free}, - .get_protocol_spec = infrared_nec_get_spec, + .get_protocol_variant = infrared_protocol_nec_get_variant, }, { .decoder = @@ -66,7 +69,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_samsung32_encode, .reset = infrared_encoder_samsung32_reset, .free = infrared_encoder_samsung32_free}, - .get_protocol_spec = infrared_samsung32_get_spec, + .get_protocol_variant = infrared_protocol_samsung32_get_variant, }, { .decoder = @@ -80,7 +83,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_rc5_encode, .reset = infrared_encoder_rc5_reset, .free = infrared_encoder_rc5_free}, - .get_protocol_spec = infrared_rc5_get_spec, + .get_protocol_variant = infrared_protocol_rc5_get_variant, }, { .decoder = @@ -94,7 +97,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_rc6_encode, .reset = infrared_encoder_rc6_reset, .free = infrared_encoder_rc6_free}, - .get_protocol_spec = infrared_rc6_get_spec, + .get_protocol_variant = infrared_protocol_rc6_get_variant, }, { .decoder = @@ -108,7 +111,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_sirc_encode, .reset = infrared_encoder_sirc_reset, .free = infrared_encoder_sirc_free}, - .get_protocol_spec = infrared_sirc_get_spec, + .get_protocol_variant = infrared_protocol_sirc_get_variant, }, { .decoder = @@ -122,13 +125,12 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_kaseikyo_encode, .reset = infrared_encoder_kaseikyo_reset, .free = infrared_encoder_kaseikyo_free}, - .get_protocol_spec = infrared_kaseikyo_get_spec, + .get_protocol_variant = infrared_protocol_kaseikyo_get_variant, }, }; static int infrared_find_index_by_protocol(InfraredProtocol protocol); -static const InfraredProtocolSpecification* - infrared_get_spec_by_protocol(InfraredProtocol protocol); +static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol); const InfraredMessage* infrared_decode(InfraredDecoderHandler* handler, bool level, uint32_t duration) { @@ -224,7 +226,7 @@ void infrared_free_encoder(InfraredEncoderHandler* handler) { static int infrared_find_index_by_protocol(InfraredProtocol protocol) { for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { - if(infrared_encoder_decoder[i].get_protocol_spec(protocol)) { + if(infrared_encoder_decoder[i].get_protocol_variant(protocol)) { return i; } } @@ -282,34 +284,37 @@ InfraredProtocol infrared_get_protocol_by_name(const char* protocol_name) { return InfraredProtocolUnknown; } -static const InfraredProtocolSpecification* - infrared_get_spec_by_protocol(InfraredProtocol protocol) { +static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol) { int index = infrared_find_index_by_protocol(protocol); - const InfraredProtocolSpecification* spec = NULL; + const InfraredProtocolVariant* variant = NULL; if(index >= 0) { - spec = infrared_encoder_decoder[index].get_protocol_spec(protocol); + variant = infrared_encoder_decoder[index].get_protocol_variant(protocol); } - furi_assert(spec); - return spec; + furi_assert(variant); + return variant; } const char* infrared_get_protocol_name(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->name; + return infrared_get_variant_by_protocol(protocol)->name; } uint8_t infrared_get_protocol_address_length(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->address_length; + return infrared_get_variant_by_protocol(protocol)->address_length; } uint8_t infrared_get_protocol_command_length(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->command_length; + return infrared_get_variant_by_protocol(protocol)->command_length; } uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->frequency; + return infrared_get_variant_by_protocol(protocol)->frequency; } float infrared_get_protocol_duty_cycle(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->duty_cycle; + return infrared_get_variant_by_protocol(protocol)->duty_cycle; +} + +size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol) { + return infrared_get_variant_by_protocol(protocol)->repeat_count; } diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index 2c76645ff..3ab46cbbf 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #ifdef __cplusplus @@ -201,6 +202,15 @@ uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol); */ float infrared_get_protocol_duty_cycle(InfraredProtocol protocol); +/** + * Get the minimum count of signal repeats for the selected protocol + * + * \param[in] protocol - protocol to get the repeat count from + * + * \return repeat count + */ +size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol); + #ifdef __cplusplus } #endif diff --git a/lib/infrared/encoder_decoder/infrared_i.h b/lib/infrared/encoder_decoder/infrared_i.h index 3a645cede..3efc41cd6 100644 --- a/lib/infrared/encoder_decoder/infrared_i.h +++ b/lib/infrared/encoder_decoder/infrared_i.h @@ -22,9 +22,10 @@ typedef struct { uint8_t command_length; uint32_t frequency; float duty_cycle; -} InfraredProtocolSpecification; + size_t repeat_count; +} InfraredProtocolVariant; -typedef const InfraredProtocolSpecification* (*InfraredGetProtocolSpec)(InfraredProtocol protocol); +typedef const InfraredProtocolVariant* (*InfraredGetProtocolVariant)(InfraredProtocol protocol); typedef void* (*InfraredAlloc)(void); typedef void (*InfraredFree)(void*); diff --git a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h b/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h deleted file mode 100644 index 6146f7b4e..000000000 --- a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h +++ /dev/null @@ -1,320 +0,0 @@ -#pragma once - -#include -#include -#include -#include "infrared.h" -#include "common/infrared_common_i.h" - -/*************************************************************************************************** -* NEC protocol description -* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1 -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop -* mark space Modulation up to period repeat repeat bit -* mark space -* -* 9000 4500 32 bit + stop bit ...110000 9000 2250 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___ -* -***************************************************************************************************/ - -#define INFRARED_NEC_PREAMBLE_MARK 9000 -#define INFRARED_NEC_PREAMBLE_SPACE 4500 -#define INFRARED_NEC_BIT1_MARK 560 -#define INFRARED_NEC_BIT1_SPACE 1690 -#define INFRARED_NEC_BIT0_MARK 560 -#define INFRARED_NEC_BIT0_SPACE 560 -#define INFRARED_NEC_REPEAT_PERIOD 110000 -#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD -#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN -#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000 -#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000 -#define INFRARED_NEC_REPEAT_MARK 9000 -#define INFRARED_NEC_REPEAT_SPACE 2250 -#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_NEC_BIT_TOLERANCE 120 // us - -void* infrared_decoder_nec_alloc(void); -void infrared_decoder_nec_reset(void* decoder); -void infrared_decoder_nec_free(void* decoder); -InfraredMessage* infrared_decoder_nec_check_ready(void* decoder); -InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_nec_alloc(void); -InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_nec_free(void* encoder_ptr); -bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_nec_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_nec; - -/*************************************************************************************************** -* SAMSUNG32 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop -* mark space Modulation repeat repeat bit -* mark space -* -* 4500 4500 32 bit + stop bit 40000/100000 4500 4500 -* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _ -* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___ -* -***************************************************************************************************/ - -#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500 -#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500 -#define INFRARED_SAMSUNG_BIT1_MARK 550 -#define INFRARED_SAMSUNG_BIT1_SPACE 1650 -#define INFRARED_SAMSUNG_BIT0_MARK 550 -#define INFRARED_SAMSUNG_BIT0_SPACE 550 -#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000 -/* Samsung silence have to be greater than REPEAT MAX - * otherwise there can be problems during unit tests parsing - * of some data. Real tolerances we don't know, but in real life - * silence time should be greater than max repeat time. This is - * because of similar preambule timings for repeat and first messages. */ -#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000 -#define INFRARED_SAMSUNG_SILENCE 145000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000 -#define INFRARED_SAMSUNG_REPEAT_MARK 4500 -#define INFRARED_SAMSUNG_REPEAT_SPACE 4500 -#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us - -void* infrared_decoder_samsung32_alloc(void); -void infrared_decoder_samsung32_reset(void* decoder); -void infrared_decoder_samsung32_free(void* decoder); -InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx); -InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); -InfraredStatus - infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message); -void* infrared_encoder_samsung32_alloc(void); -void infrared_encoder_samsung32_free(void* encoder_ptr); -bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_samsung32_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_samsung32; - -/*************************************************************************************************** -* RC6 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A -**************************************************************************************************** -* Preamble Manchester/biphase Silence -* mark/space Modulation -* -* 2666 889 444/888 - bit (x2 for toggle bit) 2666 -* -* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __ -* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________ -* | 1 | 0 | 0 | 0 | 0 | ... | ... | | -* s m2 m1 m0 T address (MSB) command (MSB) -* -* s - start bit (always 1) -* m0-2 - mode (000 for RC6) -* T - toggle bit, twice longer -* address - 8 bit -* command - 8 bit -***************************************************************************************************/ - -#define INFRARED_RC6_CARRIER_FREQUENCY 36000 -#define INFRARED_RC6_DUTY_CYCLE 0.33 - -#define INFRARED_RC6_PREAMBLE_MARK 2666 -#define INFRARED_RC6_PREAMBLE_SPACE 889 -#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit -#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_RC6_BIT_TOLERANCE 120 // us -/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ -#define INFRARED_RC6_SILENCE (2700 * 10) -#define INFRARED_RC6_MIN_SPLIT_TIME 2700 - -void* infrared_decoder_rc6_alloc(void); -void infrared_decoder_rc6_reset(void* decoder); -void infrared_decoder_rc6_free(void* decoder); -InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx); -InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_rc6_alloc(void); -void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_rc6_free(void* decoder); -InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_rc6_decode_manchester( - InfraredCommonDecoder* decoder, - bool level, - uint32_t timing); -InfraredStatus infrared_encoder_rc6_encode_manchester( - InfraredCommonEncoder* encoder_ptr, - uint32_t* duration, - bool* polarity); -const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_rc6; - -/*************************************************************************************************** -* RC5 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X -**************************************************************************************************** -* Manchester/biphase -* Modulation -* -* 888/1776 - bit (x2 for toggle bit) -* -* __ ____ __ __ __ __ __ __ __ __ -* __ __ ____ __ __ __ __ __ __ __ _ -* | 1 | 1 | 0 | ... | ... | -* s si T address (MSB) command (MSB) -* -* Note: manchester starts from space timing, so it have to be handled properly -* s - start bit (always 1) -* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0) -* T - toggle bit, change it's value every button press -* address - 5 bit -* command - 6/7 bit -***************************************************************************************************/ - -#define INFRARED_RC5_CARRIER_FREQUENCY 36000 -#define INFRARED_RC5_DUTY_CYCLE 0.33 - -#define INFRARED_RC5_PREAMBLE_MARK 0 -#define INFRARED_RC5_PREAMBLE_SPACE 0 -#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit -#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_RC5_BIT_TOLERANCE 120 // us -/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ -#define INFRARED_RC5_SILENCE (2700 * 10) -#define INFRARED_RC5_MIN_SPLIT_TIME 2700 - -void* infrared_decoder_rc5_alloc(void); -void infrared_decoder_rc5_reset(void* decoder); -void infrared_decoder_rc5_free(void* decoder); -InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx); -InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_rc5_alloc(void); -void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_rc5_free(void* decoder); -InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder); -const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_rc5; - -/*************************************************************************************************** -* Sony SIRC protocol description -* https://www.sbprojects.net/knowledge/ir/sirc.php -* http://picprojects.org.uk/ -**************************************************************************************************** -* Preamble Preamble Pulse Width Modulation Pause Entirely repeat -* mark space up to period message.. -* -* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _ -* | command | address | -* SIRC | 7b LSB | 5b LSB | -* SIRC15 | 7b LSB | 8b LSB | -* SIRC20 | 7b LSB | 13b LSB | -* -* No way to determine either next message is repeat or not, -* so recognize only fact message received. Sony remotes always send at least 3 messages. -* Assume 8 last extended bits for SIRC20 are address bits. -***************************************************************************************************/ - -#define INFRARED_SIRC_CARRIER_FREQUENCY 40000 -#define INFRARED_SIRC_DUTY_CYCLE 0.33 -#define INFRARED_SIRC_PREAMBLE_MARK 2400 -#define INFRARED_SIRC_PREAMBLE_SPACE 600 -#define INFRARED_SIRC_BIT1_MARK 1200 -#define INFRARED_SIRC_BIT1_SPACE 600 -#define INFRARED_SIRC_BIT0_MARK 600 -#define INFRARED_SIRC_BIT0_SPACE 600 -#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_SIRC_BIT_TOLERANCE 120 // us -#define INFRARED_SIRC_SILENCE 10000 -#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000) -#define INFRARED_SIRC_REPEAT_PERIOD 45000 - -void* infrared_decoder_sirc_alloc(void); -void infrared_decoder_sirc_reset(void* decoder); -InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder); -uint32_t infrared_decoder_sirc_get_timeout(void* decoder); -void infrared_decoder_sirc_free(void* decoder); -InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_sirc_alloc(void); -void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_sirc_free(void* decoder); -InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder); -const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol); -InfraredStatus infrared_encoder_sirc_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); - -extern const InfraredCommonProtocolSpec protocol_sirc; - -/*************************************************************************************************** -* Kaseikyo protocol description -* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble -* mark space Modulation up to period repeat repeat -* mark space -* -* 3360 1665 48 bit ...130000 3456 1728 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ -* -***************************************************************************************************/ - -#define INFRARED_KASEIKYO_UNIT 432 -#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000 -#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD -#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN -#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000 -#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000 -#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK -#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000) -#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us - -void* infrared_decoder_kaseikyo_alloc(void); -void infrared_decoder_kaseikyo_reset(void* decoder); -void infrared_decoder_kaseikyo_free(void* decoder); -InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder); -InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_kaseikyo_alloc(void); -InfraredStatus - infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_kaseikyo_free(void* encoder_ptr); -bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_kaseikyo_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_kaseikyo; diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c index b8db81d7e..e85a89652 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_kaseikyo_i.h" +#include InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -38,7 +34,7 @@ bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder) { } void* infrared_decoder_kaseikyo_alloc(void) { - return infrared_common_decoder_alloc(&protocol_kaseikyo); + return infrared_common_decoder_alloc(&infrared_protocol_kaseikyo); } InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c index 5814c7255..618fc3bab 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c @@ -1,9 +1,5 @@ +#include "infrared_protocol_kaseikyo_i.h" #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message) { furi_assert(encoder_ptr); @@ -32,7 +28,7 @@ void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* m } void* infrared_encoder_kaseikyo_alloc(void) { - return infrared_common_encoder_alloc(&protocol_kaseikyo); + return infrared_common_encoder_alloc(&infrared_protocol_kaseikyo); } void infrared_encoder_kaseikyo_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c deleted file mode 100644 index 87c86c7b3..000000000 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_kaseikyo_protocol_specification = { - .name = "Kaseikyo", - .address_length = 26, - .command_length = 10, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolKaseikyo) - return &infrared_kaseikyo_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c new file mode 100644 index 000000000..0c61be3bf --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_kaseikyo_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_kaseikyo = { + .timings = + { + .preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK, + .preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE, + .bit1_mark = INFRARED_KASEIKYO_BIT1_MARK, + .bit1_space = INFRARED_KASEIKYO_BIT1_SPACE, + .bit0_mark = INFRARED_KASEIKYO_BIT0_MARK, + .bit0_space = INFRARED_KASEIKYO_BIT0_SPACE, + .preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE, + .silence_time = INFRARED_KASEIKYO_SILENCE, + .min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME, + }, + .databit_len[0] = 48, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_kaseikyo_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_kaseikyo = { + .name = "Kaseikyo", + .address_length = 26, + .command_length = 10, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_KASEIKYO_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolKaseikyo) + return &infrared_protocol_variant_kaseikyo; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h new file mode 100644 index 000000000..61ff0ca1c --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* Kaseikyo protocol description +* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble +* mark space Modulation up to period repeat repeat +* mark space +* +* 3360 1665 48 bit ...130000 3456 1728 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ +* +***************************************************************************************************/ + +void* infrared_decoder_kaseikyo_alloc(void); +void infrared_decoder_kaseikyo_reset(void* decoder); +void infrared_decoder_kaseikyo_free(void* decoder); +InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder); +InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_kaseikyo_alloc(void); +InfraredStatus + infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_kaseikyo_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h new file mode 100644 index 000000000..bee116c4d --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_KASEIKYO_UNIT 432 +#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000 +#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD +#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN +#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000 +#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000 +#define INFRARED_KASEIKYO_REPEAT_COUNT_MIN 1 +#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK +#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000) +#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_kaseikyo; + +bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_kaseikyo_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c index 3ad14a7ab..91384d702 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_nec_i.h" +#include InfraredMessage* infrared_decoder_nec_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -86,7 +81,7 @@ InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder } void* infrared_decoder_nec_alloc(void) { - return infrared_common_decoder_alloc(&protocol_nec); + return infrared_common_decoder_alloc(&infrared_protocol_nec); } InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c index d0039c330..87f815142 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c @@ -1,10 +1,7 @@ +#include "infrared_protocol_nec_i.h" + +#include #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include static const uint32_t repeat_timings[] = { INFRARED_NEC_REPEAT_PERIOD - INFRARED_NEC_REPEAT_MARK - INFRARED_NEC_REPEAT_SPACE - @@ -81,7 +78,7 @@ InfraredStatus infrared_encoder_nec_encode_repeat( } void* infrared_encoder_nec_alloc(void) { - return infrared_common_encoder_alloc(&protocol_nec); + return infrared_common_encoder_alloc(&infrared_protocol_nec); } void infrared_encoder_nec_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c b/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c deleted file mode 100644 index 16cab8b5f..000000000 --- a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_nec_protocol_specification = { - .name = "NEC", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_necext_protocol_specification = { - .name = "NECext", - .address_length = 16, - .command_length = 16, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_nec42_protocol_specification = { - .name = "NEC42", - .address_length = 13, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_nec42ext_protocol_specification = { - .name = "NEC42ext", - .address_length = 26, - .command_length = 16, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolNEC) - return &infrared_nec_protocol_specification; - else if(protocol == InfraredProtocolNECext) - return &infrared_necext_protocol_specification; - else if(protocol == InfraredProtocolNEC42) - return &infrared_nec42_protocol_specification; - else if(protocol == InfraredProtocolNEC42ext) - return &infrared_nec42ext_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c new file mode 100644 index 000000000..3444f78b6 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c @@ -0,0 +1,74 @@ +#include "infrared_protocol_nec_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_nec = { + .timings = + { + .preamble_mark = INFRARED_NEC_PREAMBLE_MARK, + .preamble_space = INFRARED_NEC_PREAMBLE_SPACE, + .bit1_mark = INFRARED_NEC_BIT1_MARK, + .bit1_space = INFRARED_NEC_BIT1_SPACE, + .bit0_mark = INFRARED_NEC_BIT0_MARK, + .bit0_space = INFRARED_NEC_BIT0_SPACE, + .preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_NEC_BIT_TOLERANCE, + .silence_time = INFRARED_NEC_SILENCE, + .min_split_time = INFRARED_NEC_MIN_SPLIT_TIME, + }, + .databit_len[0] = 42, + .databit_len[1] = 32, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_nec_interpret, + .decode_repeat = infrared_decoder_nec_decode_repeat, + .encode_repeat = infrared_encoder_nec_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec = { + .name = "NEC", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_necext = { + .name = "NECext", + .address_length = 16, + .command_length = 16, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec42 = { + .name = "NEC42", + .address_length = 13, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec42ext = { + .name = "NEC42ext", + .address_length = 26, + .command_length = 16, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolNEC) + return &infrared_protocol_variant_nec; + else if(protocol == InfraredProtocolNECext) + return &infrared_protocol_variant_necext; + else if(protocol == InfraredProtocolNEC42) + return &infrared_protocol_variant_nec42; + else if(protocol == InfraredProtocolNEC42ext) + return &infrared_protocol_variant_nec42ext; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h new file mode 100644 index 000000000..559e31fda --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* NEC protocol description +* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1 +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop +* mark space Modulation up to period repeat repeat bit +* mark space +* +* 9000 4500 32 bit + stop bit ...110000 9000 2250 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___ +* +***************************************************************************************************/ + +void* infrared_decoder_nec_alloc(void); +void infrared_decoder_nec_reset(void* decoder); +void infrared_decoder_nec_free(void* decoder); +InfraredMessage* infrared_decoder_nec_check_ready(void* decoder); +InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_nec_alloc(void); +InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_nec_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h new file mode 100644 index 000000000..05df1f474 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_NEC_PREAMBLE_MARK 9000 +#define INFRARED_NEC_PREAMBLE_SPACE 4500 +#define INFRARED_NEC_BIT1_MARK 560 +#define INFRARED_NEC_BIT1_SPACE 1690 +#define INFRARED_NEC_BIT0_MARK 560 +#define INFRARED_NEC_BIT0_SPACE 560 +#define INFRARED_NEC_REPEAT_PERIOD 110000 +#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD +#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN +#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000 +#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000 +#define INFRARED_NEC_REPEAT_COUNT_MIN 1 +#define INFRARED_NEC_REPEAT_MARK 9000 +#define INFRARED_NEC_REPEAT_SPACE 2250 +#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_NEC_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_nec; + +bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_nec_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c index 6b4a7c2e3..1b2f2f301 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include typedef struct { InfraredCommonDecoder* common_decoder; @@ -60,7 +57,7 @@ bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder) { void* infrared_decoder_rc5_alloc(void) { InfraredRc5Decoder* decoder = malloc(sizeof(InfraredRc5Decoder)); decoder->toggle = false; - decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc5); + decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc5); decoder->common_decoder->context = decoder; return decoder; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c index 7b55cdc44..df47fb7c4 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include typedef struct InfraredEncoderRC5 { InfraredCommonEncoder* common_encoder; @@ -41,7 +39,7 @@ InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration void* infrared_encoder_rc5_alloc(void) { InfraredEncoderRC5* encoder = malloc(sizeof(InfraredEncoderRC5)); - encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc5); + encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc5); encoder->toggle_bit = false; return encoder; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c new file mode 100644 index 000000000..bc7e299fd --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c @@ -0,0 +1,49 @@ +#include "infrared_protocol_rc5_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rc5 = { + .timings = + { + .preamble_mark = 0, + .preamble_space = 0, + .bit1_mark = INFRARED_RC5_BIT, + .preamble_tolerance = 0, + .bit_tolerance = INFRARED_RC5_BIT_TOLERANCE, + .silence_time = INFRARED_RC5_SILENCE, + .min_split_time = INFRARED_RC5_MIN_SPLIT_TIME, + }, + .databit_len[0] = 1 + 1 + 1 + 5 + + 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command + .manchester_start_from_space = true, + .decode = infrared_common_decode_manchester, + .encode = infrared_common_encode_manchester, + .interpret = infrared_decoder_rc5_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc5 = { + .name = "RC5", + .address_length = 5, + .command_length = 6, + .frequency = INFRARED_RC5_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC5_DUTY_CYCLE, + .repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc5x = { + .name = "RC5X", + .address_length = 5, + .command_length = 7, + .frequency = INFRARED_RC5_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC5_DUTY_CYCLE, + .repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRC5) + return &infrared_protocol_variant_rc5; + else if(protocol == InfraredProtocolRC5X) + return &infrared_protocol_variant_rc5x; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h new file mode 100644 index 000000000..9dd5802a9 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h @@ -0,0 +1,38 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RC5 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X +**************************************************************************************************** +* Manchester/biphase +* Modulation +* +* 888/1776 - bit (x2 for toggle bit) +* +* __ ____ __ __ __ __ __ __ __ __ +* __ __ ____ __ __ __ __ __ __ __ _ +* | 1 | 1 | 0 | ... | ... | +* s si T address (MSB) command (MSB) +* +* Note: manchester starts from space timing, so it have to be handled properly +* s - start bit (always 1) +* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0) +* T - toggle bit, change it's value every button press +* address - 5 bit +* command - 6/7 bit +***************************************************************************************************/ + +void* infrared_decoder_rc5_alloc(void); +void infrared_decoder_rc5_reset(void* decoder); +void infrared_decoder_rc5_free(void* decoder); +InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx); +InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rc5_alloc(void); +void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rc5_free(void* decoder); +InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h new file mode 100644 index 000000000..b906c369e --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RC5_CARRIER_FREQUENCY 36000 +#define INFRARED_RC5_DUTY_CYCLE 0.33 + +#define INFRARED_RC5_PREAMBLE_MARK 0 +#define INFRARED_RC5_PREAMBLE_SPACE 0 +#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit +#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RC5_BIT_TOLERANCE 120 // us +/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ +#define INFRARED_RC5_SILENCE (2700 * 10) +#define INFRARED_RC5_MIN_SPLIT_TIME 2700 +#define INFRARED_RC5_REPEAT_COUNT_MIN 1 + +extern const InfraredCommonProtocolSpec infrared_protocol_rc5; + +bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c b/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c deleted file mode 100644 index 25ea230ef..000000000 --- a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_rc5_protocol_specification = { - .name = "RC5", - .address_length = 5, - .command_length = 6, - .frequency = INFRARED_RC5_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC5_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_rc5x_protocol_specification = { - .name = "RC5X", - .address_length = 5, - .command_length = 7, - .frequency = INFRARED_RC5_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC5_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolRC5) - return &infrared_rc5_protocol_specification; - else if(protocol == InfraredProtocolRC5X) - return &infrared_rc5x_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c index 13d3e5364..b70f7ceb8 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include typedef struct { InfraredCommonDecoder* common_decoder; @@ -93,7 +90,7 @@ InfraredStatus infrared_decoder_rc6_decode_manchester( void* infrared_decoder_rc6_alloc(void) { InfraredRc6Decoder* decoder = malloc(sizeof(InfraredRc6Decoder)); decoder->toggle = false; - decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc6); + decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc6); decoder->common_decoder->context = decoder; return decoder; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c index f1240b17a..d13a204ea 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include typedef struct InfraredEncoderRC6 { InfraredCommonEncoder* common_encoder; @@ -35,7 +33,7 @@ InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration void* infrared_encoder_rc6_alloc(void) { InfraredEncoderRC6* encoder = malloc(sizeof(InfraredEncoderRC6)); - encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc6); + encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc6); encoder->toggle_bit = false; return encoder; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c new file mode 100644 index 000000000..40a187d85 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c @@ -0,0 +1,39 @@ +#include "infrared_protocol_rc6_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rc6 = { + .timings = + { + .preamble_mark = INFRARED_RC6_PREAMBLE_MARK, + .preamble_space = INFRARED_RC6_PREAMBLE_SPACE, + .bit1_mark = INFRARED_RC6_BIT, + .preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_RC6_BIT_TOLERANCE, + .silence_time = INFRARED_RC6_SILENCE, + .min_split_time = INFRARED_RC6_MIN_SPLIT_TIME, + }, + .databit_len[0] = + 1 + 3 + 1 + 8 + + 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command + .manchester_start_from_space = false, + .decode = infrared_decoder_rc6_decode_manchester, + .encode = infrared_encoder_rc6_encode_manchester, + .interpret = infrared_decoder_rc6_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc6 = { + .name = "RC6", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_RC6_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC6_DUTY_CYCLE, + .repeat_count = INFRARED_RC6_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRC6) + return &infrared_protocol_variant_rc6; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h new file mode 100644 index 000000000..f0b163411 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RC6 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A +**************************************************************************************************** +* Preamble Manchester/biphase Silence +* mark/space Modulation +* +* 2666 889 444/888 - bit (x2 for toggle bit) 2666 +* +* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __ +* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________ +* | 1 | 0 | 0 | 0 | 0 | ... | ... | | +* s m2 m1 m0 T address (MSB) command (MSB) +* +* s - start bit (always 1) +* m0-2 - mode (000 for RC6) +* T - toggle bit, twice longer +* address - 8 bit +* command - 8 bit +***************************************************************************************************/ + +void* infrared_decoder_rc6_alloc(void); +void infrared_decoder_rc6_reset(void* decoder); +void infrared_decoder_rc6_free(void* decoder); +InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx); +InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rc6_alloc(void); +void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rc6_free(void* decoder); +InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h new file mode 100644 index 000000000..06aa2a6a5 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RC6_CARRIER_FREQUENCY 36000 +#define INFRARED_RC6_DUTY_CYCLE 0.33 + +#define INFRARED_RC6_PREAMBLE_MARK 2666 +#define INFRARED_RC6_PREAMBLE_SPACE 889 +#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit +#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RC6_BIT_TOLERANCE 120 // us +/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ +#define INFRARED_RC6_SILENCE (2700 * 10) +#define INFRARED_RC6_MIN_SPLIT_TIME 2700 +#define INFRARED_RC6_REPEAT_COUNT_MIN 1 + +extern const InfraredCommonProtocolSpec infrared_protocol_rc6; + +bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_rc6_decode_manchester( + InfraredCommonDecoder* decoder, + bool level, + uint32_t timing); +InfraredStatus infrared_encoder_rc6_encode_manchester( + InfraredCommonEncoder* encoder_ptr, + uint32_t* duration, + bool* polarity); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c b/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c deleted file mode 100644 index 9e0ba7462..000000000 --- a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_rc6_protocol_specification = { - .name = "RC6", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_RC6_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC6_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolRC6) - return &infrared_rc6_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c index e8cd3b05c..32881d3c9 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_samsung_i.h" +#include InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -57,7 +53,7 @@ InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* d } void* infrared_decoder_samsung32_alloc(void) { - return infrared_common_decoder_alloc(&protocol_samsung32); + return infrared_common_decoder_alloc(&infrared_protocol_samsung32); } InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c index 75b037f00..3aed50656 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c @@ -1,9 +1,7 @@ +#include "infrared_protocol_samsung_i.h" + #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include +#include static const uint32_t repeat_timings[] = { INFRARED_SAMSUNG_REPEAT_PAUSE2, @@ -58,7 +56,7 @@ InfraredStatus infrared_encoder_samsung32_encode_repeat( } void* infrared_encoder_samsung32_alloc(void) { - return infrared_common_encoder_alloc(&protocol_samsung32); + return infrared_common_encoder_alloc(&infrared_protocol_samsung32); } void infrared_encoder_samsung32_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c new file mode 100644 index 000000000..ca78726ac --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_samsung_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_samsung32 = { + .timings = + { + .preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK, + .preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE, + .bit1_mark = INFRARED_SAMSUNG_BIT1_MARK, + .bit1_space = INFRARED_SAMSUNG_BIT1_SPACE, + .bit0_mark = INFRARED_SAMSUNG_BIT0_MARK, + .bit0_space = INFRARED_SAMSUNG_BIT0_SPACE, + .preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE, + .silence_time = INFRARED_SAMSUNG_SILENCE, + .min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME, + }, + .databit_len[0] = 32, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_samsung32_interpret, + .decode_repeat = infrared_decoder_samsung32_decode_repeat, + .encode_repeat = infrared_encoder_samsung32_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_samsung32 = { + .name = "Samsung32", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_SAMSUNG_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolSamsung32) + return &infrared_protocol_variant_samsung32; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h new file mode 100644 index 000000000..9abcb2e3e --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* SAMSUNG32 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop +* mark space Modulation repeat repeat bit +* mark space +* +* 4500 4500 32 bit + stop bit 40000/100000 4500 4500 +* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _ +* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___ +* +***************************************************************************************************/ + +void* infrared_decoder_samsung32_alloc(void); +void infrared_decoder_samsung32_reset(void* decoder); +void infrared_decoder_samsung32_free(void* decoder); +InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx); +InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); + +InfraredStatus + infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message); +void* infrared_encoder_samsung32_alloc(void); +void infrared_encoder_samsung32_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h new file mode 100644 index 000000000..b85384942 --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500 +#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500 +#define INFRARED_SAMSUNG_BIT1_MARK 550 +#define INFRARED_SAMSUNG_BIT1_SPACE 1650 +#define INFRARED_SAMSUNG_BIT0_MARK 550 +#define INFRARED_SAMSUNG_BIT0_SPACE 550 +#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000 +#define INFRARED_SAMSUNG_REPEAT_COUNT_MIN 1 +/* Samsung silence have to be greater than REPEAT MAX + * otherwise there can be problems during unit tests parsing + * of some data. Real tolerances we don't know, but in real life + * silence time should be greater than max repeat time. This is + * because of similar preambule timings for repeat and first messages. */ +#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000 +#define INFRARED_SAMSUNG_SILENCE 145000 +#define INFRARED_SAMSUNG_REPEAT_MARK 4500 +#define INFRARED_SAMSUNG_REPEAT_SPACE 4500 +#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us + +bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_samsung32_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); + +extern const InfraredCommonProtocolSpec infrared_protocol_samsung32; diff --git a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c b/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c deleted file mode 100644 index f4cbf699e..000000000 --- a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_samsung32_protocol_specification = { - .name = "Samsung32", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolSamsung32) - return &infrared_samsung32_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c index 45f06c942..fc18a183c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_sirc_i.h" +#include InfraredMessage* infrared_decoder_sirc_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -44,7 +39,7 @@ bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder) { } void* infrared_decoder_sirc_alloc(void) { - return infrared_common_decoder_alloc(&protocol_sirc); + return infrared_common_decoder_alloc(&infrared_protocol_sirc); } InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c index 2c2bda1af..6adf2235c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c @@ -1,10 +1,5 @@ +#include "infrared_protocol_sirc_i.h" #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message) { furi_assert(encoder_ptr); @@ -53,7 +48,7 @@ InfraredStatus infrared_encoder_sirc_encode_repeat( } void* infrared_encoder_sirc_alloc(void) { - return infrared_common_encoder_alloc(&protocol_sirc); + return infrared_common_encoder_alloc(&infrared_protocol_sirc); } void infrared_encoder_sirc_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c new file mode 100644 index 000000000..b527fba98 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c @@ -0,0 +1,64 @@ +#include "infrared_protocol_sirc_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_sirc = { + .timings = + { + .preamble_mark = INFRARED_SIRC_PREAMBLE_MARK, + .preamble_space = INFRARED_SIRC_PREAMBLE_SPACE, + .bit1_mark = INFRARED_SIRC_BIT1_MARK, + .bit1_space = INFRARED_SIRC_BIT1_SPACE, + .bit0_mark = INFRARED_SIRC_BIT0_MARK, + .bit0_space = INFRARED_SIRC_BIT0_SPACE, + .preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE, + .silence_time = INFRARED_SIRC_SILENCE, + .min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME, + }, + .databit_len[0] = 20, + .databit_len[1] = 15, + .databit_len[2] = 12, + .no_stop_bit = true, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_sirc_interpret, + .decode_repeat = NULL, + .encode_repeat = infrared_encoder_sirc_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc = { + .name = "SIRC", + .address_length = 5, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc15 = { + .name = "SIRC15", + .address_length = 8, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc20 = { + .name = "SIRC20", + .address_length = 13, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolSIRC) + return &infrared_protocol_variant_sirc; + else if(protocol == InfraredProtocolSIRC15) + return &infrared_protocol_variant_sirc15; + else if(protocol == InfraredProtocolSIRC20) + return &infrared_protocol_variant_sirc20; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h new file mode 100644 index 000000000..0c3bcd8a2 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* Sony SIRC protocol description +* https://www.sbprojects.net/knowledge/ir/sirc.php +* http://picprojects.org.uk/ +**************************************************************************************************** +* Preamble Preamble Pulse Width Modulation Pause Entirely repeat +* mark space up to period message.. +* +* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _ +* | command | address | +* SIRC | 7b LSB | 5b LSB | +* SIRC15 | 7b LSB | 8b LSB | +* SIRC20 | 7b LSB | 13b LSB | +* +* No way to determine either next message is repeat or not, +* so recognize only fact message received. Sony remotes always send at least 3 messages. +* Assume 8 last extended bits for SIRC20 are address bits. +***************************************************************************************************/ + +void* infrared_decoder_sirc_alloc(void); +void infrared_decoder_sirc_reset(void* decoder); +InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder); +void infrared_decoder_sirc_free(void* decoder); +InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_sirc_alloc(void); +void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_sirc_free(void* decoder); +InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h new file mode 100644 index 000000000..e38be9bc8 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_SIRC_CARRIER_FREQUENCY 40000 +#define INFRARED_SIRC_DUTY_CYCLE 0.33 +#define INFRARED_SIRC_PREAMBLE_MARK 2400 +#define INFRARED_SIRC_PREAMBLE_SPACE 600 +#define INFRARED_SIRC_BIT1_MARK 1200 +#define INFRARED_SIRC_BIT1_SPACE 600 +#define INFRARED_SIRC_BIT0_MARK 600 +#define INFRARED_SIRC_BIT0_SPACE 600 +#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_SIRC_BIT_TOLERANCE 120 // us +#define INFRARED_SIRC_SILENCE 10000 +#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000) +#define INFRARED_SIRC_REPEAT_PERIOD 45000 +#define INFRARED_SIRC_REPEAT_COUNT_MIN 3 + +extern const InfraredCommonProtocolSpec infrared_protocol_sirc; + +bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_sirc_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c b/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c deleted file mode 100644 index 9bf35908e..000000000 --- a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_sirc_protocol_specification = { - .name = "SIRC", - .address_length = 5, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_sirc15_protocol_specification = { - .name = "SIRC15", - .address_length = 8, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_sirc20_protocol_specification = { - .name = "SIRC20", - .address_length = 13, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolSIRC) - return &infrared_sirc_protocol_specification; - else if(protocol == InfraredProtocolSIRC15) - return &infrared_sirc15_protocol_specification; - else if(protocol == InfraredProtocolSIRC20) - return &infrared_sirc20_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/worker/infrared_transmit.c b/lib/infrared/worker/infrared_transmit.c index 1a5083019..113fb6324 100644 --- a/lib/infrared/worker/infrared_transmit.c +++ b/lib/infrared/worker/infrared_transmit.c @@ -101,7 +101,8 @@ void infrared_send(const InfraredMessage* message, int times) { InfraredEncoderHandler* handler = infrared_alloc_encoder(); infrared_reset_encoder(handler, message); - infrared_tx_number_of_transmissions = times; + infrared_tx_number_of_transmissions = + MAX((int)infrared_get_protocol_min_repeat_count(message->protocol), times); uint32_t frequency = infrared_get_protocol_frequency(message->protocol); float duty_cycle = infrared_get_protocol_duty_cycle(message->protocol); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 033dba525..5add1413e 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -1,13 +1,10 @@ +#include "infrared_worker.h" + +#include +#include + #include #include -#include "sys/_stdint.h" -#include "infrared_worker.h" -#include -#include -#include -#include -#include -#include #include @@ -471,18 +468,23 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { furi_assert(instance->state == InfraredWorkerStateStartTx); furi_assert(thread_context); + size_t repeats_left = + instance->signal.decoded ? + infrared_get_protocol_min_repeat_count(instance->signal.message.protocol) : + 1; uint32_t events = 0; - bool new_data_available = true; - bool exit = false; - exit = !infrared_get_new_signal(instance); - furi_assert(!exit); + bool exit_pending = false; - while(!exit) { + bool running = infrared_get_new_signal(instance); + furi_assert(running); + + while(running) { switch(instance->state) { case InfraredWorkerStateStartTx: + --repeats_left; /* The first message does not result in TX_MESSAGE_SENT event for some reason */ instance->tx.need_reinitialization = false; - new_data_available = infrared_worker_tx_fill_buffer(instance); + const bool new_data_available = infrared_worker_tx_fill_buffer(instance); furi_hal_infrared_async_tx_start(instance->tx.frequency, instance->tx.duty_cycle); if(!new_data_available) { @@ -496,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { break; case InfraredWorkerStateStopTx: furi_hal_infrared_async_tx_stop(); - exit = true; + running = false; break; case InfraredWorkerStateWaitTxEnd: furi_hal_infrared_async_tx_wait_termination(); @@ -504,18 +506,18 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { events = furi_thread_flags_get(); if(events & INFRARED_WORKER_EXIT) { - exit = true; + running = false; break; } break; case InfraredWorkerStateRunTx: - events = furi_thread_flags_wait(INFRARED_WORKER_ALL_TX_EVENTS, 0, FuriWaitForever); + events = furi_thread_flags_wait( + INFRARED_WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever); furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */ if(events & INFRARED_WORKER_EXIT) { - instance->state = InfraredWorkerStateStopTx; - break; + exit_pending = true; } if(events & INFRARED_WORKER_TX_FILL_BUFFER) { @@ -527,9 +529,19 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { } if(events & INFRARED_WORKER_TX_MESSAGE_SENT) { - if(instance->tx.message_sent_callback) + if(repeats_left > 0) { + --repeats_left; + } + + if(instance->tx.message_sent_callback) { instance->tx.message_sent_callback(instance->tx.message_sent_context); + } } + + if(exit_pending && repeats_left == 0) { + instance->state = InfraredWorkerStateStopTx; + } + break; default: furi_assert(0); From 073fb3861ac310c07bdbbb3fd12fc37fe8d9799c Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 13 Jan 2023 17:11:12 +0300 Subject: [PATCH 07/24] Add the ability to turn pages in infrared (#2271) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../services/gui/modules/button_menu.c | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/applications/services/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c index 60bd160c5..427a3e1ae 100644 --- a/applications/services/gui/modules/button_menu.c +++ b/applications/services/gui/modules/button_menu.c @@ -178,6 +178,47 @@ static void button_menu_process_down(ButtonMenu* button_menu) { true); } +static void button_menu_process_right(ButtonMenu* button_menu) { + furi_assert(button_menu); + + with_view_model( + button_menu->view, + ButtonMenuModel * model, + { + if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) { + size_t position_candidate = model->position + BUTTONS_PER_SCREEN; + position_candidate -= position_candidate % BUTTONS_PER_SCREEN; + if(position_candidate < (ButtonMenuItemArray_size(model->items))) { + model->position = position_candidate; + } else { + model->position = 0; + } + } + }, + true); +} + +static void button_menu_process_left(ButtonMenu* button_menu) { + furi_assert(button_menu); + + with_view_model( + button_menu->view, + ButtonMenuModel * model, + { + if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) { + size_t position_candidate; + if(model->position < BUTTONS_PER_SCREEN) { + position_candidate = (ButtonMenuItemArray_size(model->items) - 1); + } else { + position_candidate = model->position - BUTTONS_PER_SCREEN; + }; + position_candidate -= position_candidate % BUTTONS_PER_SCREEN; + model->position = position_candidate; + } + }, + true); +} + static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { furi_assert(button_menu); @@ -239,6 +280,14 @@ static bool button_menu_view_input_callback(InputEvent* event, void* context) { consumed = true; button_menu_process_down(button_menu); break; + case InputKeyRight: + consumed = true; + button_menu_process_right(button_menu); + break; + case InputKeyLeft: + consumed = true; + button_menu_process_left(button_menu); + break; default: break; } From 9e1a6a6d2ec4a340b2fc0dceda86116044044070 Mon Sep 17 00:00:00 2001 From: Eric Betts Date: Mon, 16 Jan 2023 01:36:59 -0800 Subject: [PATCH 08/24] relocate R_ARM_CALL (#2305) --- lib/flipper_application/elf/elf_file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index bf98650a2..64d5755ef 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -315,6 +315,7 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3 FURI_LOG_D(TAG, " R_ARM_ABS32 relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr)); break; case R_ARM_THM_PC22: + case R_ARM_CALL: case R_ARM_THM_JUMP24: elf_relocate_jmp_call(elf, relAddr, type, symAddr); FURI_LOG_D( From 341610b8a18fbff13521c3441ae30f4a3bb865fe Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 17 Jan 2023 15:55:49 +0300 Subject: [PATCH 09/24] [FL-3080] fbt: PVS support (#2286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt: added firmware_pvscheck & firmware_pvs targets for *nix * fbt: pvs support on Windows * fbt: additional fixes & docs for PVS support * fbt: fixes for updater env configuration * github: reworked pvs workflow * vscode: added PVS shortcut * pvs: added --ignore-ccache flag * fbt: pvs: opening web browser if there are warnings * fbt: pvs: added browser handler for mac * github: fixed report path for PVS * fbt: pvs: fixed report upload path * removed intentional PVS warning * fixed more PVS warnings * fixed secplus_v1 PVS warning * fbt: added PVSNOBROWSER flag * github: setting PVSNOBROWSER for pvs runs * fbt: less debug output Co-authored-by: あく --- .github/workflows/pvs_studio.yml | 27 +----- .pvsoptions | 2 +- .vscode/example/tasks.json | 6 ++ assets/SConscript | 6 +- documentation/fbt.md | 1 + firmware.scons | 21 +++++ furi/core/core_defines.h | 6 +- lib/lfrfid/protocols/protocol_fdx_b.c | 2 +- lib/subghz/blocks/math.h | 12 ++- lib/subghz/protocols/chamberlain_code.c | 4 +- lib/subghz/protocols/secplus_v1.c | 2 +- scripts/fbt_tools/fbt_extapps.py | 2 + scripts/fbt_tools/fbt_help.py | 2 + scripts/fbt_tools/pvsstudio.py | 106 ++++++++++++++++++++++++ site_scons/commandline.scons | 5 ++ site_scons/extapps.scons | 5 ++ 16 files changed, 174 insertions(+), 35 deletions(-) create mode 100644 scripts/fbt_tools/pvsstudio.py diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index 46ee8801d..50f8f0aa6 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -43,36 +43,15 @@ jobs: fi python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" - - name: 'Make reports directory' + - name: 'Supply PVS credentials' run: | - rm -rf reports/ - mkdir reports - - - name: 'Generate compile_comands.json' - run: | - ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons api_syms - - - name: 'Static code analysis' - run: | - source scripts/toolchain/fbtenv.sh pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} - pvs-studio-analyzer analyze \ - @.pvsoptions \ - -C gccarm \ - -j$(grep -c processor /proc/cpuinfo) \ - -f build/f7-firmware-DC/compile_commands.json \ - -o PVS-Studio.log - name: 'Convert PVS-Studio output to html and detect warnings' id: pvs-warn run: | WARNINGS=0 - plog-converter \ - -a GA:1,2,3 \ - -t fullhtml \ - --indicate-warnings \ - PVS-Studio.log \ - -o reports/${DEFAULT_TARGET}-${SUFFIX} || WARNINGS=1 + ./fbt COMPACT=1 PVSNOBROWSER=1 firmware_pvs || WARNINGS=1 echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT - name: 'Upload artifacts to update server' @@ -84,7 +63,7 @@ jobs: chmod 600 ./deploy_key; rsync -avrzP --mkpath \ -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ - reports/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/"; + build/f7-firmware-DC/pvsreport/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/"; rm ./deploy_key; - name: 'Find Previous Comment' diff --git a/.pvsoptions b/.pvsoptions index 31bc4b804..ca1b2b572 100644 --- a/.pvsoptions +++ b/.pvsoptions @@ -1 +1 @@ ---rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap +--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index beedf8865..28e67d456 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -105,6 +105,12 @@ "type": "shell", "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full" }, + { + "label": "[Debug] Create PVS-Studio report", + "group": "build", + "type": "shell", + "command": "./fbt firmware_pvs" + }, { "label": "[Debug] Build FAPs", "group": "build", diff --git a/assets/SConscript b/assets/SConscript index 63141829e..ef5d83c79 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -54,13 +54,14 @@ assetsenv.Alias("proto_ver", proto_ver) # Gather everything into a static lib assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver) +env.Replace(FW_ASSETS_HEADERS=assets_parts) assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts) assetsenv.Install("${LIB_DIST_DIR}", assetslib) # Resources for SD card - +env.SetDefault(FW_RESOURCES=None) if assetsenv["IS_BASE_FIRMWARE"]: # External dolphin animations dolphin_external = assetsenv.DolphinExtBuilder( @@ -92,8 +93,7 @@ if assetsenv["IS_BASE_FIRMWARE"]: ) # Exporting resources node to external environment - env["FW_ASSETS_HEADERS"] = assets_parts - env["FW_RESOURCES"] = resources + env.Replace(FW_RESOURCES=resources) assetsenv.Alias("resources", resources) Return("assetslib") diff --git a/documentation/fbt.md b/documentation/fbt.md index 7b1aa8b48..5166d0ab7 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -56,6 +56,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `OPENOCD_ADAPTER_SERIAL=...`. - `lint`, `format` - run clang-format on the C source code to check and reformat it according to the `.clang-format` specs. - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on the Python source code, build system files & application manifests. +- `firmware_pvs` - generate a PVS Studio report for the firmware. Requires PVS Studio to be availabe on your system's `PATH`. - `cli` - start a Flipper CLI session over USB. ### Firmware targets diff --git a/firmware.scons b/firmware.scons index d674bf160..8a52650c4 100644 --- a/firmware.scons +++ b/firmware.scons @@ -15,6 +15,7 @@ env = ENV.Clone( ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), "fwbin", "fbt_apps", + "pvsstudio", ], COMPILATIONDB_USE_ABSPATH=False, BUILD_DIR=fw_build_meta["build_dir"], @@ -69,6 +70,8 @@ env = ENV.Clone( ], }, }, + SDK_APISYMS=None, + _APP_ICONS=None, ) @@ -273,6 +276,24 @@ Precious(fwcdb) NoClean(fwcdb) Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) +pvscheck = fwenv.PVSCheck("pvsreport.log", fwcdb) +Depends( + pvscheck, + [ + fwenv["FW_VERSION_JSON"], + fwenv["FW_ASSETS_HEADERS"], + fwenv["SDK_APISYMS"], + fwenv["_APP_ICONS"], + ], +) +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvscheck", pvscheck) +AlwaysBuild(pvscheck) +Precious(pvscheck) + +pvsreport = fwenv.PVSReport(None, pvscheck, REPORT_DIR=Dir("pvsreport")) +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvs", pvsreport) +AlwaysBuild(pvsreport) + # If current configuration was explicitly requested, generate compilation database # and link its directory as build/latest if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS): diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index a0f50aff9..03a364abd 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -93,7 +93,11 @@ extern "C" { #endif #ifndef FURI_BIT_CLEAR -#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1UL << (n))) +#define FURI_BIT_CLEAR(x, n) \ + ({ \ + __typeof__(x) _x = (1); \ + (x) &= ~(_x << (n)); \ + }) #endif #define FURI_SW_MEMBARRIER() asm volatile("" : : : "memory") diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index 855356f2a..dd54cffb0 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -244,7 +244,7 @@ LevelDuration protocol_fdx_b_encoder_yield(ProtocolFDXB* protocol) { static uint64_t protocol_fdx_b_get_national_code(const uint8_t* data) { uint64_t national_code = bit_lib_get_bits_32(data, 0, 32); national_code = national_code << 32; - national_code |= bit_lib_get_bits_32(data, 32, 6) << (32 - 6); + national_code |= (uint64_t)bit_lib_get_bits_32(data, 32, 6) << (32 - 6); bit_lib_reverse_bits((uint8_t*)&national_code, 0, 64); return national_code; } diff --git a/lib/subghz/blocks/math.h b/lib/subghz/blocks/math.h index 87c209f71..dcea3da5f 100644 --- a/lib/subghz/blocks/math.h +++ b/lib/subghz/blocks/math.h @@ -5,8 +5,16 @@ #include #define bit_read(value, bit) (((value) >> (bit)) & 0x01) -#define bit_set(value, bit) ((value) |= (1UL << (bit))) -#define bit_clear(value, bit) ((value) &= ~(1UL << (bit))) +#define bit_set(value, bit) \ + ({ \ + __typeof__(value) _one = (1); \ + (value) |= (_one << (bit)); \ + }) +#define bit_clear(value, bit) \ + ({ \ + __typeof__(value) _one = (1); \ + (value) &= ~(_one << (bit)); \ + }) #define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit)) #define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 3650a9867..32f4e9520 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -280,9 +280,9 @@ 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) { + if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_0) { bit_write(data_res, i, 0); - } else if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_1) { + } else if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_1) { bit_write(data_res, i, 1); } else { return false; diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 75a44a26c..a11611011 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -224,7 +224,7 @@ static bool subghz_protocol_secplus_v1_encode(SubGhzProtocolEncoderSecPlus_v1* i instance->generic.data &= 0xFFFFFFFF00000000; instance->generic.data |= rolling; - if(rolling > 0xFFFFFFFF) { + if(rolling == 0xFFFFFFFF) { rolling = 0xE6000000; } if(fixed > 0xCFD41B90) { diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index f0015cf25..1199f5f82 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -32,6 +32,7 @@ def BuildAppElf(env, app): ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR") app_work_dir = os.path.join(ext_apps_work_dir, app.appid) + env.SetDefault(_APP_ICONS=[]) env.VariantDir(app_work_dir, app._appdir, duplicate=False) app_env = env.Clone(FAP_SRC_DIR=app._appdir, FAP_WORK_DIR=app_work_dir) @@ -63,6 +64,7 @@ def BuildAppElf(env, app): icon_bundle_name=f"{app.fap_icon_assets_symbol if app.fap_icon_assets_symbol else app.appid }_icons", ) app_env.Alias("_fap_icons", fap_icons) + env.Append(_APP_ICONS=[fap_icons]) private_libs = [] diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index 8cce9335b..afdb36665 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -31,6 +31,8 @@ Other: run linters format, format_py: run code formatters + firmware_pvs: + generate a PVS-Studio report For more targets & info, see documentation/fbt.md """ diff --git a/scripts/fbt_tools/pvsstudio.py b/scripts/fbt_tools/pvsstudio.py new file mode 100644 index 000000000..02014836a --- /dev/null +++ b/scripts/fbt_tools/pvsstudio.py @@ -0,0 +1,106 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Script import Delete, Mkdir, GetBuildFailures +import multiprocessing +import webbrowser +import atexit +import sys +import subprocess + +__no_browser = False + + +def _set_browser_action(target, source, env): + if env["PVSNOBROWSER"]: + global __no_browser + __no_browser = True + + +def emit_pvsreport(target, source, env): + target_dir = env["REPORT_DIR"] + if env["PLATFORM"] == "win32": + # Report generator on Windows emits to a subfolder of given output folder + target_dir = target_dir.Dir("fullhtml") + return [target_dir.File("index.html")], source + + +def atexist_handler(): + global __no_browser + if __no_browser: + return + + for bf in GetBuildFailures(): + if bf.node.exists and bf.node.name.endswith(".html"): + # macOS + if sys.platform == "darwin": + subprocess.run(["open", bf.node.abspath]) + else: + webbrowser.open(bf.node.abspath) + break + + +def generate(env): + env.SetDefault( + PVSNCORES=multiprocessing.cpu_count(), + PVSOPTIONS=[ + "@.pvsoptions", + "-j${PVSNCORES}", + # "--incremental", # kinda broken on PVS side + ], + PVSCONVOPTIONS=[ + "-a", + "GA:1,2,3", + "-t", + "fullhtml", + "--indicate-warnings", + ], + ) + + if env["PLATFORM"] == "win32": + env.SetDefault( + PVSCHECKBIN="CompilerCommandsAnalyzer.exe", + PVSCONVBIN="PlogConverter.exe", + ) + else: + env.SetDefault( + PVSCHECKBIN="pvs-studio-analyzer", + PVSCONVBIN="plog-converter", + ) + + if not env["VERBOSE"]: + env.SetDefault( + PVSCHECKCOMSTR="\tPVS\t${TARGET}", + PVSCONVCOMSTR="\tPVSREP\t${TARGET}", + ) + + env.Append( + BUILDERS={ + "PVSCheck": Builder( + action=Action( + '${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"', + "${PVSCHECKCOMSTR}", + ), + suffix=".log", + src_suffix=".json", + ), + "PVSReport": Builder( + action=Action( + [ + Delete("${TARGET.dir}"), + # PlogConverter.exe and plog-converter have different behavior + Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None, + Action(_set_browser_action, None), + '${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"', + ], + "${PVSCONVCOMSTR}", + ), + emitter=emit_pvsreport, + src_suffix=".log", + ), + } + ) + atexit.register(atexist_handler) + + +def exists(env): + return True diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index fc2534ed5..6d01eb8f6 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -235,6 +235,11 @@ vars.AddVariables( ("applications_user", False), ], ), + BoolVariable( + "PVSNOBROWSER", + help="Don't open browser after generating error repots", + default=False, + ), ) Return("vars") diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index b8f210563..4eff65cbf 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -143,6 +143,11 @@ sdk_apisyms = appenv.SDKSymGenerator( "${BUILD_DIR}/assets/compiled/symbols.h", appenv["SDK_DEFINITION"] ) Alias("api_syms", sdk_apisyms) +ENV.Replace( + SDK_APISYMS=sdk_apisyms, + _APP_ICONS=appenv["_APP_ICONS"], +) + if appenv["FORCE"]: appenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms) From a0814aab31d7f08eeffa5d424769ab1e303f4eb3 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 17 Jan 2023 18:07:47 +0300 Subject: [PATCH 10/24] [FL-3081] fbt: removed DEBUG_TOOLS & FAP_EXAMPLES flags (#2291) * fbt: deprecated DEBUG_TOOLS & FAP_EXAMPLES flags * fixes for PVS warnings * scripts: fbt: fixed leaking PYTHONHOME --- SConstruct | 9 ++++++--- applications/debug/accessor/accessor_app.cpp | 3 ++- applications/debug/accessor/helpers/wiegand.cpp | 3 --- applications/debug/bt_debug_app/views/bt_test.c | 11 +++++++---- .../debug/file_browser_test/file_browser_app.c | 2 +- applications/examples/application.fam | 4 ++-- firmware.scons | 3 --- scripts/fbt_tools/fbt_extapps.py | 17 ++++++++++++----- scripts/toolchain/fbtenv.sh | 10 +++++++--- site_scons/commandline.scons | 11 +---------- site_scons/extapps.scons | 3 +-- 11 files changed, 39 insertions(+), 37 deletions(-) diff --git a/SConstruct b/SConstruct index b8c65044d..62e37dfdc 100644 --- a/SConstruct +++ b/SConstruct @@ -148,9 +148,12 @@ fap_dist = [ for app_artifact in firmware_env["FW_EXTAPPS"].applications.values() ), ), - distenv.Install( - f"#/dist/{dist_dir}/apps", - "#/assets/resources/apps", + *( + distenv.Install( + f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}", + app_artifact.compact[0], + ) + for app_artifact in firmware_env["FW_EXTAPPS"].applications.values() ), ] Depends( diff --git a/applications/debug/accessor/accessor_app.cpp b/applications/debug/accessor/accessor_app.cpp index 2e3e27ec4..9d3708ebe 100644 --- a/applications/debug/accessor/accessor_app.cpp +++ b/applications/debug/accessor/accessor_app.cpp @@ -31,7 +31,8 @@ void AccessorApp::run(void) { onewire_host_stop(onewire_host); } -AccessorApp::AccessorApp() { +AccessorApp::AccessorApp() + : text_store{0} { notification = static_cast(furi_record_open(RECORD_NOTIFICATION)); onewire_host = onewire_host_alloc(); furi_hal_power_enable_otg(); diff --git a/applications/debug/accessor/helpers/wiegand.cpp b/applications/debug/accessor/helpers/wiegand.cpp index bb2885549..5cb3a85f5 100644 --- a/applications/debug/accessor/helpers/wiegand.cpp +++ b/applications/debug/accessor/helpers/wiegand.cpp @@ -171,9 +171,6 @@ bool WIEGAND::DoWiegandConversion() { return true; } else { _lastWiegand = sysTick; - _bitCount = 0; - _cardTemp = 0; - _cardTempHigh = 0; return false; } diff --git a/applications/debug/bt_debug_app/views/bt_test.c b/applications/debug/bt_debug_app/views/bt_test.c index 9588b667b..cd52b8650 100644 --- a/applications/debug/bt_debug_app/views/bt_test.c +++ b/applications/debug/bt_debug_app/views/bt_test.c @@ -2,8 +2,11 @@ #include #include + +#include #include #include +#include #include struct BtTestParam { @@ -98,16 +101,16 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) { elements_scrollbar(canvas, model->position, BtTestParamArray_size(model->params)); canvas_draw_str(canvas, 6, 60, model->message); if(model->state == BtTestStateStarted) { - if(model->rssi != 0.0f) { + if(!float_is_equal(model->rssi, 0.0f)) { snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi); canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); } } else if(model->state == BtTestStateStopped) { if(model->packets_num_rx) { - snprintf(info_str, sizeof(info_str), "%ld pack rcv", model->packets_num_rx); + snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack rcv", model->packets_num_rx); canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); } else if(model->packets_num_tx) { - snprintf(info_str, sizeof(info_str), "%ld pack sent", model->packets_num_tx); + snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack sent", model->packets_num_tx); canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str); } } @@ -153,7 +156,7 @@ static bool bt_test_input_callback(InputEvent* event, void* context) { } void bt_test_process_up(BtTest* bt_test) { - with_view_model( + with_view_model( // -V658 bt_test->view, BtTestModel * model, { diff --git a/applications/debug/file_browser_test/file_browser_app.c b/applications/debug/file_browser_test/file_browser_app.c index 996cb2bd2..bf423d34e 100644 --- a/applications/debug/file_browser_test/file_browser_app.c +++ b/applications/debug/file_browser_test/file_browser_app.c @@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) { app->file_path = furi_string_alloc(); app->file_browser = file_browser_alloc(app->file_path); - file_browser_configure(app->file_browser, "*", NULL, true, &I_badusb_10px, true); + file_browser_configure(app->file_browser, "*", NULL, true, false, &I_badusb_10px, true); view_dispatcher_add_view( app->view_dispatcher, FileBrowserAppViewStart, widget_get_view(app->widget)); diff --git a/applications/examples/application.fam b/applications/examples/application.fam index 16d240ccf..8556714c9 100644 --- a/applications/examples/application.fam +++ b/applications/examples/application.fam @@ -1,5 +1,5 @@ App( - appid="sample_apps", - name="Sample apps bundle", + appid="example_apps", + name="Example apps bundle", apptype=FlipperAppType.METAPACKAGE, ) diff --git a/firmware.scons b/firmware.scons index 8a52650c4..3922c136e 100644 --- a/firmware.scons +++ b/firmware.scons @@ -131,9 +131,6 @@ if extra_int_apps := GetOption("extra_int_apps"): fwenv.Append(APPS=extra_int_apps.split(",")) -if fwenv["FAP_EXAMPLES"]: - fwenv.Append(APPDIRS=[("applications/examples", False)]) - for app_dir, _ in env["APPDIRS"]: app_dir_node = env.Dir("#").Dir(app_dir) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 1199f5f82..214afd8af 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -7,7 +7,7 @@ from SCons.Node import NodeList import SCons.Warnings from fbt.elfmanifest import assemble_manifest_data -from fbt.appmanifest import FlipperApplication, FlipperManifestException +from fbt.appmanifest import FlipperApplication, FlipperManifestException, FlipperAppType from fbt.sdk.cache import SdkCache from fbt.util import extract_abs_dir_path @@ -234,11 +234,18 @@ def GetExtAppFromPath(env, app_dir): return app_artifacts -def fap_dist_emitter(target, source, env): +def resources_fap_dist_emitter(target, source, env): target_dir = target[0] target = [] for _, app_artifacts in env["EXT_APPS"].items(): + # We don't deploy example apps & debug tools with SD card resources + if ( + app_artifacts.app.apptype == FlipperAppType.DEBUG + or app_artifacts.app.fap_category == "Examples" + ): + continue + source.extend(app_artifacts.compact) target.append( target_dir.Dir(app_artifacts.app.fap_category).File( @@ -249,7 +256,7 @@ def fap_dist_emitter(target, source, env): return (target, source) -def fap_dist_action(target, source, env): +def resources_fap_dist_action(target, source, env): # FIXME target_dir = env.Dir("#/assets/resources/apps") @@ -282,10 +289,10 @@ def generate(env, **kw): BUILDERS={ "FapDist": Builder( action=Action( - fap_dist_action, + resources_fap_dist_action, "$FAPDISTCOMSTR", ), - emitter=fap_dist_emitter, + emitter=resources_fap_dist_emitter, ), "EmbedAppMetadata": Builder( action=[ diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index f3e4cb1fa..dd5484aa9 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -43,9 +43,11 @@ fbtenv_restore_env() PYTHONNOUSERSITE="$SAVED_PYTHONNOUSERSITE"; PYTHONPATH="$SAVED_PYTHONPATH"; + PYTHONHOME="$SAVED_PYTHONHOME"; unset SAVED_PYTHONNOUSERSITE; unset SAVED_PYTHONPATH; + unset SAVED_PYTHONHOME; unset SCRIPT_PATH; unset FBT_TOOLCHAIN_VERSION; @@ -69,7 +71,7 @@ fbtenv_check_sourced() return 1; } -fbtenv_chck_many_source() +fbtenv_check_if_sourced_multiple_times() { if ! echo "${PS1:-""}" | grep -qF "[fbt]"; then if ! echo "${PROMPT:-""}" | grep -qF "[fbt]"; then @@ -275,7 +277,7 @@ fbtenv_main() fbtenv_restore_env; return 0; fi - fbtenv_chck_many_source; # many source it's just a warning + fbtenv_check_if_sourced_multiple_times; # many source it's just a warning fbtenv_check_script_path || return 1; fbtenv_check_download_toolchain || return 1; fbtenv_set_shell_prompt; @@ -283,12 +285,14 @@ fbtenv_main() PATH="$TOOLCHAIN_ARCH_DIR/bin:$PATH"; PATH="$TOOLCHAIN_ARCH_DIR/protobuf/bin:$PATH"; PATH="$TOOLCHAIN_ARCH_DIR/openocd/bin:$PATH"; - + SAVED_PYTHONNOUSERSITE="${PYTHONNOUSERSITE:-""}"; SAVED_PYTHONPATH="${PYTHONPATH:-""}"; + SAVED_PYTHONHOME="${PYTHONHOME:-""}"; PYTHONNOUSERSITE=1; PYTHONPATH=; + PYTHONHOME=; } fbtenv_main "${1:-""}"; diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 6d01eb8f6..e01c8a39e 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -81,16 +81,6 @@ vars.AddVariables( "7", ], ), - BoolVariable( - "DEBUG_TOOLS", - help="Enable debug tools to be built", - default=False, - ), - BoolVariable( - "FAP_EXAMPLES", - help="Enable example applications to be built", - default=False, - ), ( "DIST_SUFFIX", "Suffix for binaries in build output for dist targets", @@ -232,6 +222,7 @@ vars.AddVariables( ("applications/system", False), ("applications/debug", False), ("applications/plugins", False), + ("applications/examples", False), ("applications_user", False), ], ), diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 4eff65cbf..bff9a8c30 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -65,9 +65,8 @@ class FlipperExtAppBuildArtifacts: apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, + FlipperAppType.DEBUG, ] -if appenv["DEBUG_TOOLS"]: - apps_to_build_as_faps.append(FlipperAppType.DEBUG) known_extapps = [ app From 709fa633ffdd50ea4cf5111681027944f566b775 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Wed, 25 Jan 2023 12:15:01 +0700 Subject: [PATCH 11/24] ELF-loader: wait for notification to complete on app exit (#2335) --- applications/plugins/snake_game/snake_game.c | 4 ++-- lib/flipper_application/flipper_application.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index f9b4d30af..2815e2f37 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -394,8 +394,8 @@ int32_t snake_game_app(void* p) { release_mutex(&state_mutex, snake_state); } - // Wait for all notifications to be played and return backlight to normal state - notification_message_block(notification, &sequence_display_backlight_enforce_auto); + // Return backlight to normal state + notification_message(notification, &sequence_display_backlight_enforce_auto); furi_timer_free(timer); view_port_enabled_set(view_port, false); diff --git a/lib/flipper_application/flipper_application.c b/lib/flipper_application/flipper_application.c index 618a36231..8b049a7d4 100644 --- a/lib/flipper_application/flipper_application.c +++ b/lib/flipper_application/flipper_application.c @@ -1,5 +1,6 @@ #include "flipper_application.h" #include "elf/elf_file.h" +#include #define TAG "fapp" @@ -95,6 +96,15 @@ static int32_t flipper_application_thread(void* context) { elf_file_pre_run(last_loaded_app->elf); int32_t result = elf_file_run(last_loaded_app->elf, context); elf_file_post_run(last_loaded_app->elf); + + // wait until all notifications from RAM are completed + NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); + const NotificationSequence sequence_empty = { + NULL, + }; + notification_message_block(notifications, &sequence_empty); + furi_record_close(RECORD_NOTIFICATION); + return result; } From 5134f44c09d39344a8747655c0d59864bb574b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Ha=C5=82adyn=20=28krzys=5Fh=29?= Date: Thu, 26 Jan 2023 09:28:36 +0100 Subject: [PATCH 12/24] nfc: Fix crash when using debug PCAP trace (#2338) --- lib/nfc/helpers/reader_analyzer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c index af4869ca9..9bf37a60d 100644 --- a/lib/nfc/helpers/reader_analyzer.c +++ b/lib/nfc/helpers/reader_analyzer.c @@ -159,6 +159,7 @@ void reader_analyzer_stop(ReaderAnalyzer* instance) { } if(instance->pcap) { nfc_debug_pcap_free(instance->pcap); + instance->pcap = NULL; } } From 8fc834090d289ad75de8261ad69ec310a39b5834 Mon Sep 17 00:00:00 2001 From: Krzysztof Zdulski Date: Fri, 27 Jan 2023 06:00:25 +0100 Subject: [PATCH 13/24] nfc: Fix sector reads when one block is unreadable for MIFARE Classic (#2296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix sector reads when one block is unreadable * Auth on the correct block instead of first * Fix in sector reader as well * Apply patch by @gornekich Co-authored-by: gornekich Co-authored-by: あく --- lib/nfc/protocols/mifare_classic.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index c91e9c605..d1aadf06f 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -595,6 +595,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; + } else if(i > start_block) { + // Try to re-auth to read block in case prevous block was protected from read + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) break; + if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { + mf_classic_set_block_read(data, i, &block_tmp); + blocks_read++; + } } } else { blocks_read++; @@ -607,13 +615,20 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u if(!key_b_found) break; FURI_LOG_D(TAG, "Try to read blocks with key B"); key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b)); - furi_hal_nfc_sleep(); if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break; for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; + } else if(i > start_block) { + // Try to re-auth to read block in case prevous block was protected from read + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) break; + if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { + mf_classic_set_block_read(data, i, &block_tmp); + blocks_read++; + } } } else { blocks_read++; @@ -665,6 +680,11 @@ static bool mf_classic_read_sector_with_reader( // Read blocks for(uint8_t i = 0; i < sector->total_blocks; i++) { + if(mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i])) continue; + if(i == 0) continue; + // Try to auth to read next block in case previous is locked + furi_hal_nfc_sleep(); + if(!mf_classic_auth(tx_rx, first_block + i, key, key_type, crypto, false, 0)) continue; mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i]); } // Save sector keys in last block From 4dc4d34d04c4d998ba5e05a2bca8a6d17aeefd01 Mon Sep 17 00:00:00 2001 From: Emily Trau Date: Fri, 27 Jan 2023 16:10:08 +1100 Subject: [PATCH 14/24] emv: parse track1&2 equivalent data (#2332) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * emv: parse track1&2 equivalent data * emv: alternate expiry parser * nfc: log EMV track1&2 data to trace output Co-authored-by: gornekich Co-authored-by: あく --- lib/nfc/protocols/emv.c | 35 +++++++++++++++++++++++++++++------ lib/nfc/protocols/emv.h | 3 ++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/nfc/protocols/emv.c b/lib/nfc/protocols/emv.c index e00d09e70..4c4ac856b 100644 --- a/lib/nfc/protocols/emv.c +++ b/lib/nfc/protocols/emv.c @@ -142,21 +142,44 @@ static bool emv_decode_response(uint8_t* buff, uint16_t len, EmvApplication* app success = true; FURI_LOG_T(TAG, "found EMV_TAG_AFL %x (len=%d)", tag, tlen); break; - case EMV_TAG_CARD_NUM: // Track 2 Equivalent Data. 0xD0 delimits PAN from expiry (YYMM) + case EMV_TAG_TRACK_1_EQUIV: { + char track_1_equiv[80]; + memcpy(track_1_equiv, &buff[i], tlen); + track_1_equiv[tlen] = '\0'; + success = true; + FURI_LOG_T(TAG, "found EMV_TAG_TRACK_1_EQUIV %x : %s", tag, track_1_equiv); + break; + } + case EMV_TAG_TRACK_2_EQUIV: { + // 0xD0 delimits PAN from expiry (YYMM) for(int x = 1; x < tlen; x++) { if(buff[i + x + 1] > 0xD0) { memcpy(app->card_number, &buff[i], x + 1); app->card_number_len = x + 1; + app->exp_year = (buff[i + x + 1] << 4) | (buff[i + x + 2] >> 4); + app->exp_month = (buff[i + x + 2] << 4) | (buff[i + x + 3] >> 4); break; } } + + // Convert 4-bit to ASCII representation + char track_2_equiv[41]; + uint8_t track_2_equiv_len = 0; + for(int x = 0; x < tlen; x++) { + char top = (buff[i + x] >> 4) + '0'; + char bottom = (buff[i + x] & 0x0F) + '0'; + track_2_equiv[x * 2] = top; + track_2_equiv_len++; + if(top == '?') break; + track_2_equiv[x * 2 + 1] = bottom; + track_2_equiv_len++; + if(bottom == '?') break; + } + track_2_equiv[track_2_equiv_len] = '\0'; success = true; - FURI_LOG_T( - TAG, - "found EMV_TAG_CARD_NUM %x (len=%d)", - EMV_TAG_CARD_NUM, - app->card_number_len); + FURI_LOG_T(TAG, "found EMV_TAG_TRACK_2_EQUIV %x : %s", tag, track_2_equiv); break; + } case EMV_TAG_PAN: memcpy(app->card_number, &buff[i], tlen); app->card_number_len = tlen; diff --git a/lib/nfc/protocols/emv.h b/lib/nfc/protocols/emv.h index 0ccf7c3e0..c5b089fdf 100644 --- a/lib/nfc/protocols/emv.h +++ b/lib/nfc/protocols/emv.h @@ -11,7 +11,8 @@ #define EMV_TAG_CARD_NAME 0x50 #define EMV_TAG_FCI 0xBF0C #define EMV_TAG_LOG_CTRL 0x9F4D -#define EMV_TAG_CARD_NUM 0x57 +#define EMV_TAG_TRACK_1_EQUIV 0x56 +#define EMV_TAG_TRACK_2_EQUIV 0x57 #define EMV_TAG_PAN 0x5A #define EMV_TAG_AFL 0x94 #define EMV_TAG_EXP_DATE 0x5F24 From eee5c3540060abb4c7e48dbdbbbc045f9cc1b1ed Mon Sep 17 00:00:00 2001 From: Giacomo Ferretti Date: Fri, 27 Jan 2023 06:51:47 +0100 Subject: [PATCH 15/24] NFC: add MIFARE MINI support (#2307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * NFC: add MIFARE MINI support * Move new value to end of enum * nfc: added missing unit test Co-authored-by: gornekich Co-authored-by: あく --- applications/debug/unit_tests/nfc/nfc_test.c | 5 +++++ lib/nfc/helpers/nfc_generators.c | 22 ++++++++++++++++++++ lib/nfc/nfc_device.c | 18 ++++++++++++---- lib/nfc/nfc_types.c | 4 +++- lib/nfc/protocols/mifare_classic.c | 20 +++++++++++++----- lib/nfc/protocols/mifare_classic.h | 2 ++ 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index e9e7b35f6..d613be2b9 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -466,6 +466,10 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) { nfc_device_free(nfc_keys); } +MU_TEST(mf_mini_file_test) { + mf_classic_generator_test(4, MfClassicTypeMini); +} + MU_TEST(mf_classic_1k_4b_file_test) { mf_classic_generator_test(4, MfClassicType1k); } @@ -486,6 +490,7 @@ MU_TEST_SUITE(nfc) { nfc_test_alloc(); MU_RUN_TEST(nfca_file_test); + MU_RUN_TEST(mf_mini_file_test); MU_RUN_TEST(mf_classic_1k_4b_file_test); MU_RUN_TEST(mf_classic_4k_4b_file_test); MU_RUN_TEST(mf_classic_1k_7b_file_test); diff --git a/lib/nfc/helpers/nfc_generators.c b/lib/nfc/helpers/nfc_generators.c index 769b9c7b6..590ff4d50 100644 --- a/lib/nfc/helpers/nfc_generators.c +++ b/lib/nfc/helpers/nfc_generators.c @@ -352,11 +352,27 @@ void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType } // Set SAK to 08 data->nfc_data.sak = 0x08; + } else if(type == MfClassicTypeMini) { + // Set every block to 0xFF + for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) { + if(mf_classic_is_sector_trailer(i)) { + nfc_generate_mf_classic_sector_trailer(mfc, i); + } else { + memset(&mfc->block[i].value, 0xFF, 16); + } + mf_classic_set_block_read(mfc, i, &mfc->block[i]); + } + // Set SAK to 09 + data->nfc_data.sak = 0x09; } mfc->type = type; } +static void nfc_generate_mf_mini(NfcDeviceData* data) { + nfc_generate_mf_classic(data, 4, MfClassicTypeMini); +} + static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { nfc_generate_mf_classic(data, 4, MfClassicType1k); } @@ -438,6 +454,11 @@ static const NfcGenerator ntag_i2c_plus_2k_generator = { .generator_func = nfc_generate_ntag_i2c_plus_2k, }; +static const NfcGenerator mifare_mini_generator = { + .name = "Mifare Mini", + .generator_func = nfc_generate_mf_mini, +}; + static const NfcGenerator mifare_classic_1k_4b_uid_generator = { .name = "Mifare Classic 1k 4byte UID", .generator_func = nfc_generate_mf_classic_1k_4b_uid, @@ -472,6 +493,7 @@ const NfcGenerator* const nfc_generators[] = { &ntag_i2c_2k_generator, &ntag_i2c_plus_1k_generator, &ntag_i2c_plus_2k_generator, + &mifare_mini_generator, &mifare_classic_1k_4b_uid_generator, &mifare_classic_1k_7b_uid_generator, &mifare_classic_4k_4b_uid_generator, diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index d10eaa0e5..517913070 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -745,7 +745,10 @@ static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* do { if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + blocks = 20; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; blocks = 64; } else if(data->type == MfClassicType4k) { @@ -843,7 +846,10 @@ static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* do { // Read Mifare Classic type if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + data_blocks = 20; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; data_blocks = 64; } else if(!furi_string_cmp(temp_str, "4K")) { @@ -918,7 +924,9 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) { if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; if(!flipper_format_write_header_cstr(file, nfc_keys_file_header, nfc_keys_file_version)) break; - if(data->type == MfClassicType1k) { + if(data->type == MfClassicTypeMini) { + if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "MINI")) break; + } else if(data->type == MfClassicType1k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; } else if(data->type == MfClassicType4k) { if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; @@ -968,7 +976,9 @@ bool nfc_device_load_key_cache(NfcDevice* dev) { if(furi_string_cmp_str(temp_str, nfc_keys_file_header)) break; if(version != nfc_keys_file_version) break; if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!furi_string_cmp(temp_str, "1K")) { + if(!furi_string_cmp(temp_str, "MINI")) { + data->type = MfClassicTypeMini; + } else if(!furi_string_cmp(temp_str, "1K")) { data->type = MfClassicType1k; } else if(!furi_string_cmp(temp_str, "4K")) { data->type = MfClassicType4k; diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c index 427628769..02ca85580 100644 --- a/lib/nfc/nfc_types.c +++ b/lib/nfc/nfc_types.c @@ -55,7 +55,9 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { } const char* nfc_mf_classic_type(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "Mifare Mini 0.3K"; + } else if(type == MfClassicType1k) { return "Mifare Classic 1K"; } else if(type == MfClassicType4k) { return "Mifare Classic 4K"; diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index d1aadf06f..2f340a5ce 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -13,7 +13,9 @@ #define MF_CLASSIC_WRITE_BLOCK_CMD (0xA0) const char* mf_classic_get_type_str(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return "MIFARE Mini 0.3K"; + } else if(type == MfClassicType1k) { return "MIFARE Classic 1K"; } else if(type == MfClassicType4k) { return "MIFARE Classic 4K"; @@ -73,7 +75,9 @@ MfClassicSectorTrailer* } uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return MF_MINI_TOTAL_SECTORS_NUM; + } else if(type == MfClassicType1k) { return MF_CLASSIC_1K_TOTAL_SECTORS_NUM; } else if(type == MfClassicType4k) { return MF_CLASSIC_4K_TOTAL_SECTORS_NUM; @@ -83,7 +87,9 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) { } uint16_t mf_classic_get_total_block_num(MfClassicType type) { - if(type == MfClassicType1k) { + if(type == MfClassicTypeMini) { + return 20; + } else if(type == MfClassicType1k) { return 64; } else if(type == MfClassicType4k) { return 256; @@ -363,8 +369,12 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { UNUSED(ATQA1); - if((ATQA0 == 0x44 || ATQA0 == 0x04) && (SAK == 0x08 || SAK == 0x88 || SAK == 0x09)) { - return MfClassicType1k; + if((ATQA0 == 0x44 || ATQA0 == 0x04)) { + if((SAK == 0x08 || SAK == 0x88)) { + return MfClassicType1k; + } else if(SAK == 0x09) { + return MfClassicTypeMini; + } } else if((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01)) { //skylanders support return MfClassicType1k; diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index 74beceb62..0346da0f7 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -6,6 +6,7 @@ #define MF_CLASSIC_BLOCK_SIZE (16) #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) +#define MF_MINI_TOTAL_SECTORS_NUM (5) #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) @@ -20,6 +21,7 @@ typedef enum { MfClassicType1k, MfClassicType4k, + MfClassicTypeMini, } MfClassicType; typedef enum { From 126a9efd091ea949cb9a26a01b0ee7f8c22a4a68 Mon Sep 17 00:00:00 2001 From: Giacomo Ferretti Date: Fri, 27 Jan 2023 09:21:52 +0100 Subject: [PATCH 16/24] NFC: change from int8_t to uint8_t (#2302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: gornekich Co-authored-by: あく --- firmware/targets/f7/api_symbols.csv | 2 +- lib/nfc/protocols/mifare_classic.c | 2 +- lib/nfc/protocols/mifare_classic.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3d7bd7cd2..0e4af3c1d 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1880,7 +1880,7 @@ Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*" -Function,-,mf_classic_get_classic_type,MfClassicType,"int8_t, uint8_t, uint8_t" +Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 2f340a5ce..5887ab4c1 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -367,7 +367,7 @@ bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { } } -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { UNUSED(ATQA1); if((ATQA0 == 0x44 || ATQA0 == 0x04)) { if((SAK == 0x08 || SAK == 0x88)) { diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index 0346da0f7..321ab5f03 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -96,7 +96,7 @@ const char* mf_classic_get_type_str(MfClassicType type); bool mf_classic_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); -MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t SAK); +MfClassicType mf_classic_get_classic_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); uint8_t mf_classic_get_total_sectors_num(MfClassicType type); From 24a23e5dc7b1719874f075abbf428bd5dd59e5e6 Mon Sep 17 00:00:00 2001 From: Emily Trau Date: Fri, 27 Jan 2023 20:41:55 +1100 Subject: [PATCH 17/24] debug apps: made runnable as .faps; sdk: resolved additional APIs in use by faps (#2333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sdk: resolve additional APIs in use by faps * debug tools: fixed battery_test, bt_debug, display_test, rpc_debug Co-authored-by: hedger Co-authored-by: hedger Co-authored-by: あく --- .../debug/battery_test_app/application.fam | 1 + .../battery_test_app/views/battery_info.c | 148 ++++++++++++++++++ .../battery_test_app/views/battery_info.h | 23 +++ .../debug/bt_debug_app/bt_debug_app.c | 7 +- .../debug/bt_debug_app/bt_debug_app.h | 5 +- .../debug/display_test/application.fam | 1 + .../debug/display_test/display_test.c | 1 - .../rpc_debug_app_scene_input_error_code.c | 6 +- applications/services/bt/bt_settings.h | 8 + firmware/targets/f7/api_symbols.csv | 8 +- lib/toolbox/SConscript | 1 + 11 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 applications/debug/battery_test_app/views/battery_info.c create mode 100644 applications/debug/battery_test_app/views/battery_info.h diff --git a/applications/debug/battery_test_app/application.fam b/applications/debug/battery_test_app/application.fam index b388445cc..f97d10279 100644 --- a/applications/debug/battery_test_app/application.fam +++ b/applications/debug/battery_test_app/application.fam @@ -11,4 +11,5 @@ App( stack_size=1 * 1024, order=130, fap_category="Debug", + fap_libs=["assets"], ) diff --git a/applications/debug/battery_test_app/views/battery_info.c b/applications/debug/battery_test_app/views/battery_info.c new file mode 100644 index 000000000..5353a2e2a --- /dev/null +++ b/applications/debug/battery_test_app/views/battery_info.c @@ -0,0 +1,148 @@ +#include "battery_info.h" +#include +#include +#include + +#define LOW_CHARGE_THRESHOLD 10 +#define HIGH_DRAIN_CURRENT_THRESHOLD 100 + +struct BatteryInfo { + View* view; +}; + +static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) { + canvas_draw_frame(canvas, x - 7, y + 7, 30, 13); + canvas_draw_icon(canvas, x, y, icon); + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, x - 4, y + 16, 24, 6); + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); +}; + +static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { + char emote[20] = {}; + char header[20] = {}; + char value[20] = {}; + + int32_t drain_current = data->gauge_current * (-1000); + uint32_t charge_current = data->gauge_current * 1000; + + // Draw battery + canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); + if(charge_current > 0) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); + } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); + } else if(data->charge < LOW_CHARGE_THRESHOLD) { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); + } else { + canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14); + } + + // Draw bubble + elements_bubble(canvas, 53, 0, 71, 39); + + // Set text + if(charge_current > 0) { + snprintf(emote, sizeof(emote), "%s", "Yummy!"); + snprintf(header, sizeof(header), "%s", "Charging at"); + snprintf( + value, + sizeof(value), + "%lu.%luV %lumA", + (uint32_t)(data->vbus_voltage), + (uint32_t)(data->vbus_voltage * 10) % 10, + charge_current); + } else if(drain_current > 0) { + snprintf( + emote, + sizeof(emote), + "%s", + drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); + snprintf(header, sizeof(header), "%s", "Consumption is"); + snprintf( + value, + sizeof(value), + "%ld %s", + drain_current, + drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); + } else if(drain_current != 0) { + snprintf(header, 20, "..."); + } else if(data->charging_voltage < 4.2) { + // Non-default battery charging limit, mention it + snprintf(emote, sizeof(emote), "Charged!"); + snprintf(header, sizeof(header), "Limited to"); + snprintf( + value, + sizeof(value), + "%lu.%luV", + (uint32_t)(data->charging_voltage), + (uint32_t)(data->charging_voltage * 10) % 10); + } else { + snprintf(header, sizeof(header), "Charged!"); + } + + canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); + canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header); + canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value); +}; + +static void battery_info_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + BatteryInfoModel* model = context; + + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + draw_battery(canvas, model, 0, 5); + + char batt_level[10]; + char temperature[10]; + char voltage[10]; + char health[10]; + + snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge); + snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature); + snprintf( + voltage, + sizeof(voltage), + "%lu.%01lu V", + (uint32_t)model->gauge_voltage, + (uint32_t)(model->gauge_voltage * 10) % 10UL); + snprintf(health, sizeof(health), "%d%%", model->health); + + draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level); + draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature); + draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage); + draw_stat(canvas, 104, 42, &I_Health_16x16, health); +} + +BatteryInfo* battery_info_alloc() { + BatteryInfo* battery_info = malloc(sizeof(BatteryInfo)); + battery_info->view = view_alloc(); + view_set_context(battery_info->view, battery_info); + view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel)); + view_set_draw_callback(battery_info->view, battery_info_draw_callback); + + return battery_info; +} + +void battery_info_free(BatteryInfo* battery_info) { + furi_assert(battery_info); + view_free(battery_info->view); + free(battery_info); +} + +View* battery_info_get_view(BatteryInfo* battery_info) { + furi_assert(battery_info); + return battery_info->view; +} + +void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) { + furi_assert(battery_info); + furi_assert(data); + with_view_model( + battery_info->view, + BatteryInfoModel * model, + { memcpy(model, data, sizeof(BatteryInfoModel)); }, + true); +} diff --git a/applications/debug/battery_test_app/views/battery_info.h b/applications/debug/battery_test_app/views/battery_info.h new file mode 100644 index 000000000..7bfacf69e --- /dev/null +++ b/applications/debug/battery_test_app/views/battery_info.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +typedef struct BatteryInfo BatteryInfo; + +typedef struct { + float vbus_voltage; + float gauge_voltage; + float gauge_current; + float gauge_temperature; + float charging_voltage; + uint8_t charge; + uint8_t health; +} BatteryInfoModel; + +BatteryInfo* battery_info_alloc(); + +void battery_info_free(BatteryInfo* battery_info); + +View* battery_info_get_view(BatteryInfo* battery_info); + +void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data); diff --git a/applications/debug/bt_debug_app/bt_debug_app.c b/applications/debug/bt_debug_app/bt_debug_app.c index 405051a4a..bf13f6570 100644 --- a/applications/debug/bt_debug_app/bt_debug_app.c +++ b/applications/debug/bt_debug_app/bt_debug_app.c @@ -31,9 +31,6 @@ uint32_t bt_debug_start_view(void* context) { BtDebugApp* bt_debug_app_alloc() { BtDebugApp* app = malloc(sizeof(BtDebugApp)); - // Load settings - bt_settings_load(&app->settings); - // Gui app->gui = furi_record_open(RECORD_GUI); @@ -105,13 +102,15 @@ int32_t bt_debug_app(void* p) { } BtDebugApp* app = bt_debug_app_alloc(); + // Was bt active? + const bool was_active = furi_hal_bt_is_active(); // Stop advertising furi_hal_bt_stop_advertising(); view_dispatcher_run(app->view_dispatcher); // Restart advertising - if(app->settings.enabled) { + if(was_active) { furi_hal_bt_start_advertising(); } bt_debug_app_free(app); diff --git a/applications/debug/bt_debug_app/bt_debug_app.h b/applications/debug/bt_debug_app/bt_debug_app.h index cd59e4d00..0ad94d7dd 100644 --- a/applications/debug/bt_debug_app/bt_debug_app.h +++ b/applications/debug/bt_debug_app/bt_debug_app.h @@ -4,15 +4,14 @@ #include #include #include +#include + #include -#include #include "views/bt_carrier_test.h" #include "views/bt_packet_test.h" -#include typedef struct { - BtSettings settings; Gui* gui; ViewDispatcher* view_dispatcher; Submenu* submenu; diff --git a/applications/debug/display_test/application.fam b/applications/debug/display_test/application.fam index 4b40322fb..e8a00d2ae 100644 --- a/applications/debug/display_test/application.fam +++ b/applications/debug/display_test/application.fam @@ -5,6 +5,7 @@ App( entry_point="display_test_app", cdefines=["APP_DISPLAY_TEST"], requires=["gui"], + fap_libs=["misc"], stack_size=1 * 1024, order=120, fap_category="Debug", diff --git a/applications/debug/display_test/display_test.c b/applications/debug/display_test/display_test.c index 5b46d2b41..8065a23a1 100644 --- a/applications/debug/display_test/display_test.c +++ b/applications/debug/display_test/display_test.c @@ -91,7 +91,6 @@ static void display_test_reload_config(DisplayTest* instance) { instance->config_contrast, instance->config_regulation_ratio, instance->config_bias); - gui_update(instance->gui); } static void display_config_set_bias(VariableItem* item) { diff --git a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c index eae12e6ee..367ca7a4f 100644 --- a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c +++ b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c @@ -44,7 +44,11 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv if(event.type == SceneManagerEventTypeCustom) { if(event.event == RpcDebugAppCustomEventInputErrorCode) { - rpc_system_app_set_error_code(app->rpc, (uint32_t)atol(app->text_store)); + char* end; + int error_code = strtol(app->text_store, &end, 10); + if(!*end) { + rpc_system_app_set_error_code(app->rpc, error_code); + } scene_manager_previous_scene(app->scene_manager); consumed = true; } diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h index 260d9c0e0..9ed8be89c 100644 --- a/applications/services/bt/bt_settings.h +++ b/applications/services/bt/bt_settings.h @@ -5,6 +5,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { bool enabled; } BtSettings; @@ -12,3 +16,7 @@ typedef struct { bool bt_settings_load(BtSettings* bt_settings); bool bt_settings_save(BtSettings* bt_settings); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 0e4af3c1d..0e027a6a2 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.7,, +Version,+,11.8,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -188,6 +188,7 @@ Header,+,lib/toolbox/stream/file_stream.h,, Header,+,lib/toolbox/stream/stream.h,, Header,+,lib/toolbox/stream/string_stream.h,, Header,+,lib/toolbox/tar/tar_archive.h,, +Header,+,lib/toolbox/value_index.h,, Header,+,lib/toolbox/version.h,, Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*" @@ -2066,7 +2067,7 @@ Function,-,posix_memalign,int,"void**, size_t, size_t" Function,-,pow,double,"double, double" Function,-,pow10,double,double Function,-,pow10f,float,float -Function,-,power_enable_low_battery_level_notification,void,"Power*, _Bool" +Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool" Function,+,power_get_info,void,"Power*, PowerInfo*" Function,+,power_get_pubsub,FuriPubSub*,Power* Function,+,power_is_battery_healthy,_Bool,Power* @@ -2804,6 +2805,9 @@ Function,-,vTimerSetTimerNumber,void,"TimerHandle_t, UBaseType_t" Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*" Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* +Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" +Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" +Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*" diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 724d25afa..8ce45d25f 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -20,6 +20,7 @@ env.Append( File("saved_struct.h"), File("version.h"), File("float_tools.h"), + File("value_index.h"), File("tar/tar_archive.h"), File("stream/stream.h"), File("stream/file_stream.h"), From d93ed003fec62ec8b9dc8a6b5ffbe93a25a0ef40 Mon Sep 17 00:00:00 2001 From: Krzysztof Zdulski Date: Sun, 29 Jan 2023 06:53:35 +0100 Subject: [PATCH 18/24] Change camelCase to PascalCase in code style (#2329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- CODING_STYLE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODING_STYLE.md b/CODING_STYLE.md index 6c7d6d792..c62009eff 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -52,7 +52,7 @@ Almost everything in flipper firmware is built around this concept. ## Naming -### Type names are CamelCase +### Type names are PascalCase Examples: From f5fe0ff694fd5c51472d3430565a156a66a05c15 Mon Sep 17 00:00:00 2001 From: Petr Portnov | PROgrm_JARvis Date: Sun, 29 Jan 2023 13:12:24 +0300 Subject: [PATCH 19/24] Furi: make `furi_is_irq_context` public (#2276) * Furi: make `furi_is_irq_context` public * Furi: proper name and documentation for furi_kernel_is_irq_or_masked. * Target: bump symbol table version * Furi: proper doxygen context for warnings Co-authored-by: Aleksandr Kutuzov --- firmware/targets/f7/api_symbols.csv | 1 + furi/core/common_defines.h | 24 ------------------- furi/core/kernel.c | 36 ++++++++++++++++++++++++----- furi/core/kernel.h | 29 ++++++++++++++++++++++- furi/core/message_queue.c | 16 ++++++------- furi/core/timer.c | 11 ++++----- furi/furi.c | 4 ++-- 7 files changed, 74 insertions(+), 47 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 0e027a6a2..a75e88bad 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1389,6 +1389,7 @@ Function,+,furi_hal_version_uid_size,size_t, Function,-,furi_hal_vibro_init,void, Function,+,furi_hal_vibro_on,void,_Bool Function,-,furi_init,void, +Function,+,furi_kernel_is_irq_or_masked,_Bool, Function,+,furi_kernel_get_tick_frequency,uint32_t, Function,+,furi_kernel_lock,int32_t, Function,+,furi_kernel_restore_lock,int32_t,int32_t diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index c7acf95b4..1ec847d45 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -52,30 +52,6 @@ extern "C" { } #endif -static inline bool furi_is_irq_context() { - bool irq = false; - BaseType_t state; - - if(FURI_IS_IRQ_MODE()) { - /* Called from interrupt context */ - irq = true; - } else { - /* Get FreeRTOS scheduler state */ - state = xTaskGetSchedulerState(); - - if(state != taskSCHEDULER_NOT_STARTED) { - /* Scheduler was started */ - if(FURI_IS_IRQ_MASKED()) { - /* Interrupts are masked */ - irq = true; - } - } - } - - /* Return context, 0: thread context, 1: IRQ context */ - return (irq); -} - #ifdef __cplusplus } #endif diff --git a/furi/core/kernel.c b/furi/core/kernel.c index 73d2012b4..7928ad11c 100644 --- a/furi/core/kernel.c +++ b/furi/core/kernel.c @@ -7,8 +7,32 @@ #include CMSIS_device_header +bool furi_kernel_is_irq_or_masked() { + bool irq = false; + BaseType_t state; + + if(FURI_IS_IRQ_MODE()) { + /* Called from interrupt context */ + irq = true; + } else { + /* Get FreeRTOS scheduler state */ + state = xTaskGetSchedulerState(); + + if(state != taskSCHEDULER_NOT_STARTED) { + /* Scheduler was started */ + if(FURI_IS_IRQ_MASKED()) { + /* Interrupts are masked */ + irq = true; + } + } + } + + /* Return context, 0: thread context, 1: IRQ context */ + return (irq); +} + int32_t furi_kernel_lock() { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); int32_t lock; @@ -33,7 +57,7 @@ int32_t furi_kernel_lock() { } int32_t furi_kernel_unlock() { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); int32_t lock; @@ -63,7 +87,7 @@ int32_t furi_kernel_unlock() { } int32_t furi_kernel_restore_lock(int32_t lock) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); switch(xTaskGetSchedulerState()) { case taskSCHEDULER_SUSPENDED: @@ -99,7 +123,7 @@ uint32_t furi_kernel_get_tick_frequency() { } void furi_delay_tick(uint32_t ticks) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); if(ticks == 0U) { taskYIELD(); } else { @@ -108,7 +132,7 @@ void furi_delay_tick(uint32_t ticks) { } FuriStatus furi_delay_until_tick(uint32_t tick) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); TickType_t tcnt, delay; FuriStatus stat; @@ -137,7 +161,7 @@ FuriStatus furi_delay_until_tick(uint32_t tick) { uint32_t furi_get_tick() { TickType_t ticks; - if(furi_is_irq_context() != 0U) { + if(furi_kernel_is_irq_or_masked() != 0U) { ticks = xTaskGetTickCountFromISR(); } else { ticks = xTaskGetTickCount(); diff --git a/furi/core/kernel.h b/furi/core/kernel.h index f30f109bb..371f76c1f 100644 --- a/furi/core/kernel.h +++ b/furi/core/kernel.h @@ -10,19 +10,42 @@ extern "C" { #endif +/** Check if CPU is in IRQ or kernel running and IRQ is masked + * + * Originally this primitive was born as a workaround for FreeRTOS kernel primitives shenanigans with PRIMASK. + * + * Meaningful use cases are: + * + * - When kernel is started and you want to ensure that you are not in IRQ or IRQ is not masked(like in critical section) + * - When kernel is not started and you want to make sure that you are not in IRQ mode, ignoring PRIMASK. + * + * As you can see there will be edge case when kernel is not started and PRIMASK is not 0 that may cause some funky behavior. + * Most likely it will happen after kernel primitives being used, but control not yet passed to kernel. + * It's up to you to figure out if it is safe for your code or not. + * + * @return true if CPU is in IRQ or kernel running and IRQ is masked + */ +bool furi_kernel_is_irq_or_masked(); + /** Lock kernel, pause process scheduling + * + * @warning This should never be called in interrupt request context. * * @return previous lock state(0 - unlocked, 1 - locked) */ int32_t furi_kernel_lock(); /** Unlock kernel, resume process scheduling + * + * @warning This should never be called in interrupt request context. * * @return previous lock state(0 - unlocked, 1 - locked) */ int32_t furi_kernel_unlock(); /** Restore kernel lock state + * + * @warning This should never be called in interrupt request context. * * @param[in] lock The lock state * @@ -37,7 +60,9 @@ int32_t furi_kernel_restore_lock(int32_t lock); uint32_t furi_kernel_get_tick_frequency(); /** Delay execution - * + * + * @warning This should never be called in interrupt request context. + * * Also keep in mind delay is aliased to scheduler timer intervals. * * @param[in] ticks The ticks count to pause @@ -45,6 +70,8 @@ uint32_t furi_kernel_get_tick_frequency(); void furi_delay_tick(uint32_t ticks); /** Delay until tick + * + * @warning This should never be called in interrupt request context. * * @param[in] ticks The tick until which kerel should delay task execution * diff --git a/furi/core/message_queue.c b/furi/core/message_queue.c index 9a41f8775..ddf56f006 100644 --- a/furi/core/message_queue.c +++ b/furi/core/message_queue.c @@ -1,11 +1,11 @@ +#include "kernel.h" #include "message_queue.h" -#include "core/common_defines.h" #include #include #include "check.h" FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size) { - furi_assert((furi_is_irq_context() == 0U) && (msg_count > 0U) && (msg_size > 0U)); + furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (msg_count > 0U) && (msg_size > 0U)); QueueHandle_t handle = xQueueCreate(msg_count, msg_size); furi_check(handle); @@ -14,7 +14,7 @@ FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size } void furi_message_queue_free(FuriMessageQueue* instance) { - furi_assert(furi_is_irq_context() == 0U); + furi_assert(furi_kernel_is_irq_or_masked() == 0U); furi_assert(instance); vQueueDelete((QueueHandle_t)instance); @@ -28,7 +28,7 @@ FuriStatus stat = FuriStatusOk; - if(furi_is_irq_context() != 0U) { + if(furi_kernel_is_irq_or_masked() != 0U) { if((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) { stat = FuriStatusErrorParameter; } else { @@ -65,7 +65,7 @@ FuriStatus furi_message_queue_get(FuriMessageQueue* instance, void* msg_ptr, uin stat = FuriStatusOk; - if(furi_is_irq_context() != 0U) { + if(furi_kernel_is_irq_or_masked() != 0U) { if((hQueue == NULL) || (msg_ptr == NULL) || (timeout != 0U)) { stat = FuriStatusErrorParameter; } else { @@ -131,7 +131,7 @@ uint32_t furi_message_queue_get_count(FuriMessageQueue* instance) { if(hQueue == NULL) { count = 0U; - } else if(furi_is_irq_context() != 0U) { + } else if(furi_kernel_is_irq_or_masked() != 0U) { count = uxQueueMessagesWaitingFromISR(hQueue); } else { count = uxQueueMessagesWaiting(hQueue); @@ -148,7 +148,7 @@ uint32_t furi_message_queue_get_space(FuriMessageQueue* instance) { if(mq == NULL) { space = 0U; - } else if(furi_is_irq_context() != 0U) { + } else if(furi_kernel_is_irq_or_masked() != 0U) { isrm = taskENTER_CRITICAL_FROM_ISR(); /* space = pxQueue->uxLength - pxQueue->uxMessagesWaiting; */ @@ -167,7 +167,7 @@ FuriStatus furi_message_queue_reset(FuriMessageQueue* instance) { QueueHandle_t hQueue = (QueueHandle_t)instance; FuriStatus stat; - if(furi_is_irq_context() != 0U) { + if(furi_kernel_is_irq_or_masked() != 0U) { stat = FuriStatusErrorISR; } else if(hQueue == NULL) { stat = FuriStatusErrorParameter; diff --git a/furi/core/timer.c b/furi/core/timer.c index be7efebe2..4b6ccecba 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -3,7 +3,6 @@ #include "memmgr.h" #include "kernel.h" -#include "core/common_defines.h" #include #include @@ -27,7 +26,7 @@ static void TimerCallback(TimerHandle_t hTimer) { } FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* context) { - furi_assert((furi_is_irq_context() == 0U) && (func != NULL)); + furi_assert((furi_kernel_is_irq_or_masked() == 0U) && (func != NULL)); TimerHandle_t hTimer; TimerCallback_t* callb; @@ -60,7 +59,7 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co } void furi_timer_free(FuriTimer* instance) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); TimerHandle_t hTimer = (TimerHandle_t)instance; @@ -82,7 +81,7 @@ void furi_timer_free(FuriTimer* instance) { } FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); TimerHandle_t hTimer = (TimerHandle_t)instance; @@ -99,7 +98,7 @@ FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) { } FuriStatus furi_timer_stop(FuriTimer* instance) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); TimerHandle_t hTimer = (TimerHandle_t)instance; @@ -117,7 +116,7 @@ FuriStatus furi_timer_stop(FuriTimer* instance) { } uint32_t furi_timer_is_running(FuriTimer* instance) { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(instance); TimerHandle_t hTimer = (TimerHandle_t)instance; diff --git a/furi/furi.c b/furi/furi.c index a616bce63..cc0e3f4f1 100644 --- a/furi/furi.c +++ b/furi/furi.c @@ -3,7 +3,7 @@ #include "queue.h" void furi_init() { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED); furi_log_init(); @@ -11,7 +11,7 @@ void furi_init() { } void furi_run() { - furi_assert(!furi_is_irq_context()); + furi_assert(!furi_kernel_is_irq_or_masked()); furi_assert(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED); #if(__ARM_ARCH_7A__ == 0U) From 55054fc1a7467aff87f7250178ecd8efd9e7a738 Mon Sep 17 00:00:00 2001 From: DEXV <89728480+DXVVAY@users.noreply.github.com> Date: Sun, 29 Jan 2023 11:55:04 +0100 Subject: [PATCH 20/24] Assets: correct MicroSD card pinout in service animations (#2323) * New Micro Sd-Card pinout: fixing the Micro Sd-Card pinout for the blocking an internal sd card animations * Updating the sd card pinout * Updating magnifying glass --- .../blocking/L0_NoDb_128x51/frame_0.png | Bin 1398 -> 1424 bytes .../blocking/L0_NoDb_128x51/frame_1.png | Bin 1403 -> 1425 bytes .../blocking/L0_NoDb_128x51/frame_2.png | Bin 1403 -> 1423 bytes .../blocking/L0_NoDb_128x51/frame_3.png | Bin 1401 -> 1420 bytes .../blocking/L0_SdBad_128x51/frame_0.png | Bin 1552 -> 1370 bytes .../blocking/L0_SdBad_128x51/frame_1.png | Bin 1586 -> 1387 bytes .../blocking/L0_SdOk_128x51/frame_0.png | Bin 1549 -> 1387 bytes .../blocking/L0_SdOk_128x51/frame_1.png | Bin 1559 -> 1395 bytes .../blocking/L0_SdOk_128x51/frame_2.png | Bin 1578 -> 1413 bytes .../blocking/L0_SdOk_128x51/frame_3.png | Bin 1567 -> 1403 bytes .../blocking/L0_Url_128x51/frame_0.png | Bin 1358 -> 1380 bytes .../blocking/L0_Url_128x51/frame_1.png | Bin 1964 -> 2046 bytes .../blocking/L0_Url_128x51/frame_2.png | Bin 1956 -> 2044 bytes .../blocking/L0_Url_128x51/frame_3.png | Bin 1955 -> 2045 bytes .../internal/L1_NoSd_128x49/frame_0.png | Bin 1382 -> 1411 bytes .../internal/L1_NoSd_128x49/frame_1.png | Bin 1376 -> 1410 bytes .../internal/L1_NoSd_128x49/frame_2.png | Bin 1381 -> 1416 bytes .../internal/L1_NoSd_128x49/frame_3.png | Bin 1378 -> 1415 bytes .../internal/L1_NoSd_128x49/frame_4.png | Bin 1372 -> 1401 bytes .../internal/L1_NoSd_128x49/frame_5.png | Bin 1377 -> 1412 bytes 20 files changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png b/assets/dolphin/blocking/L0_NoDb_128x51/frame_0.png index e82c6f2e9c6a2880b0b983e1a80497daac351704..759007623af4e16c1bbdd167750e2ee47152ff88 100644 GIT binary patch delta 602 zcmeyyHGzAAL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s00=W?UF+mzU|^m((aWESmuupzJZ4@lg~=R@POLy$ zL1D8O;{rx@FjGNc@++o=^$PlS5U!1WQA(PXOKNd)QD#9&W_})693mRz;s)f|=vP=( zD9qCSiJ- zyW#1BPdSXM*p9d|D~2C5xiCr9gyl|;y#gb9`nMI)?=+sNMr(WO`!U+tTj@JUKXd43 z{Gi!Y|7GU6jt?Hb4EH3G9nM+%8b4F2)?(by@44lvs=}@Yjs1)%+zm__#v8t`=4hJ9 zc9Zq>j%)|lW|jln)juy-^<5+&DE+5E13$y-z#EJSoEb6Uu?I`}&M{_8KU?Bjaj>zN z_m_3M_?=#n*I#lSJ}P{gZNT_o%Z7!FOEkC{b@}3-$_-7%~V00001JzVIRd000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oM;Hv@wJ z000J1OjJbx00960|E1ZV-2eaqd`Uz>RCwC#n28R9APk28zW+;aS)`X$px}`Ow|GRb z-+KKr(0{`l7Qkx&aJpR&06avX0Dc$o_ay-EIfH{^TdLtk0MHzOa;2wyclM-QZUa%U z*?=0=nS|IrRQv%)YIbt+Grk{?0pKUq05-pwu~PtAJs>|`oG}Yvp9554D$(WetC@Vy zl=hn%(E?Zi*4PYyQYWBlD+Vc3`Y-|@?Vzd!+JC+-=6(R|N}K^;+JzZp?UQEd1aMuB zyA)9*6ao<1x2G8Z69Ut}&j2tD03M+30TOeLpeqM#2&Aq=415ka08T-=sSkuczY~BF zJj!zbgl7PTt6&-cjRQ2wo7V!{{qg|y8K7e=P_KbWfR+id7AQ5evAGr?h>m+N$N=DA zS#E|JK=fvk0zmAGomvy>1UV0sr5x0X(X4fA078%qK`4Pm?pgpa2tXFVER5R#FcqLX z2QbtJ*n+H*(N_h70O>yP9{^oiFdu-LpNO{Mm#Ojkvw8v0M}PqUpUe`n6H&y000000 LNkvXXu0mjfS)JjK diff --git a/assets/dolphin/blocking/L0_NoDb_128x51/frame_1.png b/assets/dolphin/blocking/L0_NoDb_128x51/frame_1.png index 58dab74d4a618d0ccc4674be0754b2f11a28e111..c9810b61e34bfc61f4b62a26225afaab6a05490d 100644 GIT binary patch delta 603 zcmey(HIaLQL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s00=W?UF+mzU|^m((aWESmuupzJZ4@lg~=R@POLy$ zL1D8O;{rx@FjGNc@++o=^$PlS5U!1WQA(PXOKNd)QD#9&W_})693mRz;s)f|=vP=( zw#+_v4VT99ldTO;^Yd!VcHOU+&u6IPQh4!Rae=@sf5r)id;HRkUwNA| zYDhC^zKm_2#HKbe>{OA5@tck2OBoCgo|as@q*SYF^1Har;g*yxYf5 zObhI0*hDuhb6mKJQ9RhubiypFDNK2{dZ`~99 z7&mBk)t@k)DL7BLo%usHS4X9K+^-mw;-ie)W>v&TG1{gf=iXSmvmTNHLopF6}g0)F({~@jmx34pL>g6#1O7XGdSBqbDyZ&o% b*eUK(MH8nPTONl3(*uL2tDnm{r-UW|yvo^{ delta 578 zcmV-I0=@l_3;PO?7%~V00001JzVIRd000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oOC5CQ4{ z000J1OjJbx00960|E1ZV-2eaqfk{L`RCwC#m9uK7aBSSEh13Cm;RV)TJ2MmBnK-$s=sy^Qd zAP}f^+ze0@;x>TEDp&?U^8ikHE484a3ITxr4A7kxh!?>SfM-HW3xpa9S3V3-jgNXS zh;sm-u`EL$pnNk40if=SLahmXf|v)=QVwFpsMflD0JuY14M9}`lic|LFa&U>cv7h@-A}f&37T^=& z`v3obAT#vPO>_%)r2R0E8K{u61%UFfh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iOD7gEebrY#pM&; z)Nh_Vy+fg+g4D?$Q&(m^P|J;PVZPhH(v9(An@T*T|+p7|IW>`T;td(YD#u8JhAX$_#oi=Y^Iyb z6A#q}m3n*j?+rcHZ-qCW&{Jiw(@K8JDG=;%MW5kEf(=6fgB7ce*nP#sC(U!3eDBmc zwDU75JQKUu)x1cyaJej#)6sN>8m*Qgr1$WJiwROa&G5npZC0?L% zgzZ6%x$rZF5NYXk4CjxnIKxnL%Ao%W!+*IQi_;lye>xJe-Sd4dgTe~DWM4fw#Vk% delta 578 zcmV-I0=@l@3;PO?7%~V00001JzVIRd000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oMwV421M z000J1OjJbx00960|E1ZV-2eaqfk{L`RCwC#n2QdBAPhxs|Np1A7@#kdg2-ILw)lu> z4{hnS1AqPagAMQ+09<~a2LOIVAOMb&`tKzGusMU1eJs_m5CAj>AfL%wz8igzPt!nT z>|#KS>P$kUFJ*tgkg5$I9LD{C5rFcf7C`cw8ao9b>H(fSJ7X4r&jHFY<>;31i#y9T zwY1+|YxxTRy0lh_w0q7&Z07-ZfvS0hb Qf&c&j07*qoM6N<$f^|vo?*IS* diff --git a/assets/dolphin/blocking/L0_NoDb_128x51/frame_3.png b/assets/dolphin/blocking/L0_NoDb_128x51/frame_3.png index 789dc8822e8442ddd49ea503b9ac8d109475e1ef..b48aef97839e4766b73c9630ae25c4fc2abb3d3a 100644 GIT binary patch delta 598 zcmey#)x$kOB9Midfq`MIpR6*FVk{1FcVbv~PUa<$!;&U>cv7h@-A}f&37T^=& z`v3obAT#vPO>_%)r2R0E8K{u61%UFfh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iOD4`zo``_31b32qV@>rWQ9?@9NxS(A+JlrtPTc2?O zYs0iRdCiyD5=+-k`+6bm$K#AwOjktKhi}_-b>^F8cNaffU(&9?&yYJcV=v>a%#f-4 z43{6gi)0d!7m&9TDAJ$7za_0{SHtvg%zKzBPR+fl^U3JI|6qrS-W1%uJMFH1XI%QP7`_(^63JMb_Du4nvkZU$okLlmoyh3c1@3C8n+Z@cV{t0*s(kaZm5ZOoNS`1{exrSNu33E&5X58#IG@YS5MbV;d#e+ zYWqwB#s#--6fjnprBwozw^c4-`cWlNC&!p`TKK-&-_Wm86D}J`JKa<{xoH(^ON(Ly zlftJJ3My+De!OdTK2#%C)BdbXtgGd$#g0`!q!vu(KHXp@X}zDl+5YNN|G(PGznGtL WnK&{0-W3K+3JjjEelF{r5}E+=mf!XO delta 576 zcmV-G0>Ax?3;7C=7%~V00001JzVIRd000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oN5K?$w^ z000J1OjJbx00960|E1ZV-2eaqe@R3^RCwC#n2QdBAPhxs|Np1AEI=O=t@6+%xXnoh z_E1W%9e?QI0~_Eq060A60{{;Z2!LP1f4>9(HfGTHj)fW)0)WN<P3?TVU^&J8b^#D(voiPfajsePR%Bx$JUyLlj zsjdB{M6>}mz<7YXPe7-s7&HNZ)4{10X#1W^;(wF2Tf6{3r3=+b*-y3&LVVIP%atre zNJ}!Ebpog*Q2DzJK*BI}0>AJ3020R{j{A`-F)HA1og O0000U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iODOmSOyv4Q%M`>aOn5*dHIgX+W?QkAwwy`O3H@L=4^)oo@i zzKS~6l>_CIVl`i!?wmJiOC^P?u>qNI^UZB z_TvrHHgG$v%Vlz4ePO4tWOtCCvx9krSD@q};RpLxJ`q-W(!~5ma>3c%THX2ywIc{w;!)foz+D=s%LwzPi+6`4nyAd$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oMEGI*l^ z00JmUL_t(|+U#2Gj>I4cJR9Htm3y1poM}J-KWNnsKQ`Uex^+fiU=8Pa{=lBI0}y}! z5CD75Vt?sI2*K$mk#%$r@I&8w^4&tv`DX(!U<>2`?jmhYlb))5Jp3E^+V8u3hB)WG z_`GQHnEqu~IUo7y|>!DM4zFZj0QpJW%S`&z|Xm@w-`6)LFY#hn+m z91!%sUrXEYdY3;=23%*$a<39V-iJ@f{brdE^na{itqnLm?}E<;bG1f-Ask9JZNT@Wp1^M2ZR$(1-DI zOn>O`sBI$217y*rYG>oHr9+V2IYuU7l4s<8S^&>QfFSb+{#`Xy+2txdVy(au1ipM^VL9lB zuOf>~MK7qi*aP~)wmxdnm(ToM&m(=2zagi3NQd~FXriq;F=f!015yA LNkvXXu0mjfqA^8s diff --git a/assets/dolphin/blocking/L0_SdBad_128x51/frame_1.png b/assets/dolphin/blocking/L0_SdBad_128x51/frame_1.png index bd0f2b9338264ef39ffcf378f9e6017edc05286e..147561f0a40ab1c8ac7134844843d659783c2109 100644 GIT binary patch delta 565 zcmdnQ^O|ddL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iOD7K5f@kuUvl$d`dceBj?BVltoMHa~b5`YnL%L=JGReh8H(%VBLSrcGDk* zDh8IljMrOF)S5HQkYrL4lStTm?Zq_NE6?Wsy({qME`!`B%ibRQd*1h(UmW3g;5s-j zwBeYM8RI0z8O%!}WF4;8hz8XgvKKr3id86X=sUJw5tmEpqsDVK~`H#}*0;5XZpp|#)pPTYlQP6`fNS=RV0Viu5-JENbR%=aaL z{dmKy4crf&G9D1!z{{X*(B_oIb~;9&;^;f3d9JGO1rk`6@$@hR+3qf43~ZEQkJuQ) ze#5<1_E8QGV`Z@>qt+~Ap~V6_%oR3HTRMl)aN!pghG{0P=C&5In!jnSVc@D}yl|#< pYS$IHNJgvo^ZzgZ+bnj7-E@s%@+~b+J77#Rc)I$ztaD0e0sw!z%fSEu delta 763 zcmVAd$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oO0n2LV@ z00K%$L_t(|+U#1{j>8}fED`_z%h{^cqR2M33AhPl{IE(D!ZCx-b=vp+1-VW(KmYOA6dF+Fn_yp6!bpi7k6@Caxsq&{Mz!rl7BzSD_O;&bERA51j7THWi=qk+FW}Z9! zP3kc8qR=tx_6Mw+Gb$kQR&6Ecuz7t(kx?FH6VW%pRbX`vTTCtZVZ}0$5d|seLwGu- zRDXEPGLfbMdeCOZ&dy;|n;^e(jC8`p&*=5YRXG^WR&LckT~VCFmVwwT{+MMVT5x|( z3W`Jw!U#a`!tdo|G0yy79gvM8KxtMeuO56Bl`m^5&hSp zeSxJOMQCdMCEXA9jO)^RdCfIJB9Midfq`MIpR6*FVk{1FcVbv~PUa<$!;&U>cv7h@-A}f&37T^=& z`v3obAT#vPO>_%)r2R2!t6$HM|-a7?@{H^zvuo<(fDvkC~TCVKN7!6DyEb zP}uCnxPXxz%v4aA{EBH|y@I|SglnT;l#*uUl3JWxlvz-cnV$z1hlmEbxB+=K`W03c zxdpkYC5a%OeMLcHa&~HoLTX-$tx}Paz1{yC;&wpydwRM!hIkx*I<0%%VFix1pZ6K= z{ZBo9G%EM%#xl>%#UA3~UGq=4de^%stc|H>DEZvFp6SH=YzDTg&u=quY|L`_$ekEk zD0CpNmf^y2hOf>MXH8twQnj{D=5c7wI-OV@%eZcp+h>zD_T+{;tR{K;m@9Y^m>XOD z41f5k{h*gK?#Oig delta 726 zcmV;{0xA9L3XKeq7%~U~0002c0+&Ys000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oNTQ!`Ki z00JdRL_t(|+U#1}vV$NDEDrzw%bYXq)JcKF5Qr#lo={sZ*<4pcO6dieCmU1%0001F zo<#0J2!Fw8No1X45Af5z_vEXEp!Al31IU6oAbf>-Sk=!s=QBGcU5ielpD-?<{oS|d z_#Ek9?kQCeb&@}6t6LKi9u`&&?{P`p4J?11SSB_E36|c}Slt&w zC+%}O*_z^vzBNaNFeYK;M@}3JpGT`|zkm7>syud~A_OO0*zkpqP|Lue57)70LkJ*( zu9XU}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iODB1mW<1j6)WVvJ9oPPxyQ!48jGOlskvre!-&%m?l{BlNtq^k{E}{ z?x>7senJa+~jX3G0qkQoWZYdcR2>Cs}-xt=ljs?3_^!8hfzIzx&1YFU5FJ^T-N zN?o)M)q5-R__NnM>H7YwdzSvx_g7t9tG^uLXoygq#8Akh|3d75X}c!dM$5~b2N)lS zHdL?&^g3ELovr54IKJTZ!A%FQUo>Nw&0u%#lZb*egUi2**Brxl)t>(A^lDvxxt;8b zuTJN$pN`RbT4}zHVcB;_W(%oTOcA>#9(d~aAi=aDI!E1x;YV~eb3*gY+Vjn8C3rS( y;PLpx>abm0Z~d{C(_eiGOBN5?{>$F!3-e7Dv!zz0+0TJ7&fw|l=d#Wzp$P!L_tz)@ delta 736 zcmV<60w4YJ3YQF!7%~U~0002c0+&Ys000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aik!eo>Ad$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oNGb`Hz{ z00J*bL_t(|+U#1}vV$NDEDrzw%bYXq)JcKF5Qr#lo={sZ*<4pcO6dieCmU1%0001F zo<#0J2!Fw8No1X45Af5z_vEXEp!Al31IU6oAbf>-Sk=!s=QBGcU5ielpD-?<{oS|d z_#Ek9?kQCeb&cR(W=_7euOHIU8o4bNf$PJ;Um;C zFzCZ|?AZ_kh@fjF26!p&qJ6!M0)X*_ja>KxfRiwA&jC+Xbf(<$&7HoD004F_fzx&U>cv7h@-A}f&36W|l# z`v3obAoK6vzyJRI`{g134#?pw@Q5sCVBk9h!i=ICUJVQk%rhr?`7`lyO`Mg-%*&-P znS;@Z6-X;6Z1!SYz{n0}Dkw~T#k8Y^rpl>0b=AFvA)PXxA4=E<|EgDRR_$kXFpuBBrLg}RLqgW| z-HbXcTMdrtvt4QNWVln!zF<0|RJ+67lI}C7eO{>>Gx)C3J^rf z4qTtP9#|&q7Ic20$^L%jk@xHh_Iu23{9=sgyL!XtS)00bPLzqL9s3KnBK1xYhoApg z5@OG09p64Dmi+Y5p9;U(`@Eru??RgX)yDJP%WBvYHr``Yu+?Eava}&o zw;+%?o}q1*tJV^3hx$*S#143HFODdGAEY^dbs<~9Eq*Hp(JOog9#(x{Wi9gq*LHum0&Vv8-3GiKkC_`5ij}!PerbR8<iZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oM%Oi~C71l@rZ^CN`rWH(PVL%q>bkUycgPaP-qu>$(mxMhY~CNP0@yp6uo9o!5R!k$u$X4#%CD7S(J% z`hR87A$*qJ`BIl#-kgE;&9&sq$)Y z|G5W~8GX5!ph=A-a`6;g(D+Wcbar4mKmpbmnqCI_M|(h4$$^JBS^*{8K;O3ts`hB| z5%#SK2@jJ}HDXrmrZjxzp<@rr#D*Y&jejulQ1>-|C-gZ?3|x?@HAhNlOu~8wO6U(} zMZfwdRC(+|MF>thvEd7ULM;P>K3vD14IzLCSSxjaLwOhU^)?Cxj4y2D!XFAaNC)mY z;K@LjOmG&9^lbzb(9R`rh?|-?grJKxVi3O~yIL|K1hKLH7&dfiNZcO#xN@v_og_2h lG!Z!f3V=WXkCi_G1^|H}F1Di~quBre002ovPDHLkV1k$oN;v=k diff --git a/assets/dolphin/blocking/L0_SdOk_128x51/frame_3.png b/assets/dolphin/blocking/L0_SdOk_128x51/frame_3.png index 614ef9c5aeea94fc93a47ccf41b0ba8b4c8ee7ee..1e52f1513742e3b985d00385f5e153ccc3937edf 100644 GIT binary patch delta 581 zcmbQw^P6jeL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-Y=;hDE%QbOU9y2eO!ekCcCsrV> zps?ACaRDPcn5m#J`4!W`dIfzu2-ilxC?(CxCAB!YD6^m>Gd~Y34iOD9odm%?2E0G_Ydu}l%9{f|7{Pwvlh}5fR*!A_)YKG3&QVkQz_DVB|&SDFybIs7w zW0JVW-mr&fgT<7zH1{WA>x`^p86$%3%5J;PE3hif#QvDjL5T(BjGAZC8%{9(QCo1z zneSe3=YRPFe?H7Q@SJhs=e!&(^T*Be_O0O&ox}V_;o?>ot_APx858d9DSLE6u(lx~ zLLp2ruwLqD0l&h#oF6Op2Yuf9Y4NNjS=-}gFb0IJRCBoLBvQhkV10N>^P@SNm^Uz5 zFnX|Mlr(ISxuW~y_ld?QG8@7i#1C##V6dA~$o*jBJw^lD7^aLZOzXcfWtl(VOt`UK zM*LDi?fXjpge%;OBlzD3Y0fWy%=Mr|uB2h@LcWHjoh;W}W*#{7ib31BkXd2hEpvvz zl0PXd+lvfrTT>k-@iVmTE%;$F?_Y3inJItb)vND2PROSwnAsjIw2T7AJcFmJpUXO@ GgeCxpA=_&J delta 744 zcmVAd$LmlPdv2vvL8T0h1X6p?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oN1o5w={ z00K8jL_t(|+U#1{vV$NDEe`+x%icTflu3cautX3}p0HY$ll`bW&+`QtCkG&a0-ylM zIPu&K=YO2hlE^yO9$<&Q_2jFCpz|#q2apAGfcpydu&keP&R6Y}bS*lGenP(h`oXv8 z_#SCrZkH;Ex=7?Sk^M&g6j`*!&x93=J%C%ddN3rb2hRwo(aZla{e|9YcaG15>HO=2 zAQ}f|uCKVg`4?npw(y%Ao*H0uDLk3}P6ry34}VoS_pf}}VC~E33AU?(pa2LIFs0Nd z;UUQb3ixR;if#=jDk^IB^f-;>gQ^h=&0A5S7S&$Qb%iXsWJfpoj_4~VsW8UK5(V-= z?uxnDs>@|=QF?qiD){c`cho`F7&&A)?uC0MqHD6plofEfsAlti<}6B2RZX_E)ECOt zTYrMmQG~?}39x$I^DA9~p7md>xS+mOP?kT>+&rG&~IS@Ad#1WPttv1*C8TecLK1+gQoX(W40o3zN!*ci&ij zFKPJ7myRusJsW}q3Zba6dan5!q0eD*6n_yo`qmsNp)v_8KXT&K@VT`r`q__A<*^AB zAvo#6hA(`Cng#}axb`g@LI4r4R_XvRU}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O+BKL|5gum-CzFfg}F^zvuo<(fDvpP83SVKOJ96DyEb zP}uCvxPXxz%v4aA{FCzM>#8IXksPAvG_>R;ftI-tPJ7X{JE;hkLp>hIkx*JB>T9#em1f*nGy$ z|Eby5iuPu^8MQ*QUb|*Ap6Pz}&n8*Ht_WcUcAM?y#sVlDj4O{@87Xw70?z zOtDLMGhA>x_Tskp494r1en=$vMe+FDP5PkQ`o)_u;=vE53l?{UU9V1RXHZ@cx65m( zcr}B9!b0DUzz!>)Ejy10AK1XSV3E_}Ka%ASjxKn{;M60TAZ~VNS^|^4gZ<|J)5Tx$ zwM=`iTL0vyl!JCd7(;Kv6+hbp&(pQCUu=G`J)1|uu;I1NE?qX(h9A1G8caV0J6Scv zF|69lDzh$l*G_G5ML7ns$Q>L9|T#nOn<}vA5HgA*J2Fp};AT{lWY2k31Lj5}rDK`NEeV z%KS1?%#87D9b3V>)@+8J$ocs%KTm)4Eu{Wv&@ZO<4Ti?5S8OVQ@y_7s>gTe~DWM4f DD0JIS delta 554 zcmV+_0@eNG3eF0U7%~V00001JzVIRd000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000ANk!eo>Ad$LnlPm#3vvUEU0h1a7i+?XZAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oOw-4GW5 z000J1OjJbx00960|E1ZV-2eaqX-PyuRCwC#*nzHtAPhj!+yDRRB@Ss}1wldH+cZnm zMClQs#eX4-Hy*&B0Z`rM17MNB0JanV_XU8Y3GN4wgk1#KqG&8`9fa?Qgn04EZUxA1 z1Hv#ugWfy_{zoQ!0NsF28O;DsR36x&89oEhavFCgl--p9+btn3?(3n>E2o`FcbVTpnNNCEilzEeK&If&fCe>1s4IfYUG_? zSz8Vn!8JhkSwJg*Gb^teAnDu|fC`2H%$#opFcfg22V!MjGzJ)z2Tsm{ae%%&@NIyG sS}+qJ2QAX{WjL=IKYvy~0C@>806$X`4`zs|dH?_b07*qoM6N<$f+3vSUH||9 diff --git a/assets/dolphin/blocking/L0_Url_128x51/frame_1.png b/assets/dolphin/blocking/L0_Url_128x51/frame_1.png index 69f1fb365988f248aa238fa6a2d672fa7d8bcee1..9975ca3f042623b1cefdd5eb913a804dd185d734 100644 GIT binary patch delta 682 zcmZ3(|BruyL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O*?7=#%aX3dcRs#2KflA_ zpXF>ll4hVPeRO3u`q)f_sB=jzPAbocRnwN7ht`GX(lx-}lyu z|AzPDq#B&{BP!Dh5S#|Hi>aZs!4%{dD^NuZ+)Mju{Sg6x+O`tx~ zx3|>Li$7o$b4%R9xPOm~HzXx&Wju0&@r&cttE{FQn6?DIihsBwpP}$|Y{yrw24@C# zhHVWYZEOtIKK$~pbZ(UNHCFH>lu6wcYG!VbSohkY=*jMu5QaF0O*JfYqQ(0d=RY+# zB7C4!%#1ODIb?15v>z|`m>=P3SS5Tru47J)KjYc#lhPe|KJU(%Da=>CSWxU>!clcV zaH^$4?pnh~DeoE1%)iIUuq=#1%;Y|NnpK&G~mH28c7U-kg}}&!{kQSN>!j zMyJiij9-~1=d&!7(YI5usmLwx^|kWIEH23}ss!?jQqrt~Qw!}Td$69Z2Px2pi2#}C ziotR&sl~}fnFS@8`FSwqK`w3}W`z|{LvCtGB9LQWQIMFNom!%hnwMg$RHS5YckBCC zYX%0!bWaz@kch)?XWZV@tiamQiU zxS;ARdqX=1%Yie0YZx6;ntn5O+_7UxNb8<^RD8SI!$%XZ-nZKv&G=?J<24f{i@lcY z|J>DU7VDGYvW8teSGB_FhEI#%ayX={<85eeeZw?iRzCX!r-op`3(8l8Ef1L1J}425VZCsheING% sNA5JH8;!2B{MtTW`SEx2FV+qGb}NPXFA6B10HzKGPgg&ebxsLQ04xUSEdT%j diff --git a/assets/dolphin/blocking/L0_Url_128x51/frame_2.png b/assets/dolphin/blocking/L0_Url_128x51/frame_2.png index 855e7450e53b99c522d473e9e913271be4b36536..84241c3f16ab65f696964e17ab96c1deb8a7dc6c 100644 GIT binary patch delta 680 zcmZ3&|A&8qL?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O*?7=#%aX3dcRs#2KflA_ zpXF>ll4hVPeRO3u`q)f_sB=jzPARUho>;uzv_{Oz>tqQeS2EnCea?*892QNUkV$miC- zjMX12at_sT*cLpwe`t&Oz3a&gFEkrIycSS!*;|snPr9Fx=dC&eW9-u93>VUt-8>$> zgX!JUkI4;|nT7_X-3OL8TN_JU(V znKXk*Q~sk_toF&-JTsCQu1A(c^Dr&2I~FRt!R_Cq2}}SSw$=v*})r_JJ=3#c-)oHf6uV&>#>f> zdl?tqo!)+fwPA)WLs8r}hJUr8=NQ(?|99q}#BJS>Zm6L*CvD-bf(Z6z;rrY(svpWR nB%fIC{OjNRSKor_kGjaE>KGbtX4qr|Ok50}u6{1-oD!Mq=#1%;Y|NnpK&G~mH28c7U-kg}}&!{kQSN>!j zMyJiij9-~1=d&!7(YI5usmLwx^|kWIEH23}ss!?jQqrt~Qw!}Td$69Z2Px2pi2#}C ziotR&sl~}fnFS@8`FSwqK`w3}W`z|{LvCtGB9LQWQIMFNom!%hnwMg$RHS5YcjC&P zrwj~?@t!V@ArXh)&bZxoSb@jo{Gb2+-xXQTm~LRbRG%vx>ZP@HUbA5`$F84`7=K7G z%(`C1u%q(;gU8kL;tVc|H~1Y?s)ZYtD4$z+^qP{5NMTi7N;Kn_+YIY^I2O&$eo$}m zklBF8z~fjBL--9no}CP~@qcqA7!I!VF03&T7GPZRt1?LIT^Hj6lS&awJEI8|?i(1E zBz+5GRXEe=&02r#-J#+`3H47Hll~s4uw*TKBExWuF{P!H*Fo6f=yJ7&bD6!IS*r!4 zEw3>J{5+S!)e!l4FT<1e-+LuLu*}X@P`$B-tEg$Oox%5%FN_SbdlOU}^pq}@ j8bn|3oj?65e?#1h55oNRTYdxrQw4*ktDnm{r-UW|Ys2O5 diff --git a/assets/dolphin/blocking/L0_Url_128x51/frame_3.png b/assets/dolphin/blocking/L0_Url_128x51/frame_3.png index 9e9a79405817d4f1f3ec242de249beedac773c57..c44b171bfaae20b74657855c263a48cb0ca3ae85 100644 GIT binary patch delta 681 zcmZ3?|CfJ)L?8<@0|UcaKUrlU#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O*?7=#%aX3dcRs#2KflA_ zpXF>ll4hVPeRO3u`q)f_sB=jzPA_)(Vst@sWaSZV|{&re+(P0IimYdRR-qqiH)yR5d*})}m z`?vL|CtKh0ck=K$^}kE?@1tT{wuU!M9J|dJTTgh0y~!<>&a&}@i^PKDw=QKk_mO148k(ujE_RS<(PUJYUVI9Fmlau?r~Z&^K=30ixu^S z3`e!EoSy%WEsW<9Yrqn}X2u2lS?i($8bue>Zrb17`zlC$*TdPmE&JIfa5Cr}<8^Rz z$dtEjSanw5SMUbO*_I2QGc3FOW}A$~fjiBYtrF7yl_-b`Y;<1c{59BNB|}$^-&3t4 zyBU5imdKI;Vst04103%>V!Z delta 569 zcmey%znFi5gfs^;0|P_Gz7I-3iY>q=#1%;Y|NnpK&G~mH28c7U-kg}}&!{kQSN>!j zMyJiij9-~1=d&!7(YI5usmLwx^|kWIEH23}ss!?jQqrt~Qw!}Td$69Z2Px2pi2#}C ziotR&sl~}fnFS@8`FSwqK`w3}W`z|{LvCtGB9LQWQIMFNom!%hnwMg$RHS5YXE%4t z0R{%fI8PVHkch)?XLR!&Qs8m*|NnovubR_ouBJ`r>W_<^-FD=w+&eFBC3X2226<+O z?-p_leo6rhw|oEpWMmL-s$l4O!Okg=ld>|y*8Ty7=GqAOmP#r_(0}IpH~H= z53|ptjZzA#Wn72j8YbSZnZd6Md9nT+5Rr(SumCB;Q{Rp6TdSUa4UF4xG}t7>ZrcTD3IHzmT}gp z+Pcd zYZ-)h@jh7VGmT+|r9ImL?dU}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-b=;hDE%QbOU0W&X`!elN+CsrV> zps?A8aS0Gd~Y34iODy-7)iZ-yW^cKASs1s%!TYpTt@Q=^YUv z71E3s9z|MqZhqO+z!AgXaF0!9k{Cmc{DWD~b_;&8dr+eQS#MaGCx|y}NpR<3 zP(OIptDbd(nU`bt>72mw1I;@H7~7rAS!;IkH!NV>`*+nn;fhk{fOoRD7(tYR5DGNX3G}xo6A4`&apd}80Y#kUU=8jr}l|)!F2rx-0IKMfN{^@>FVdQ I&MBb@00G9?xc~qF delta 551 zcmV+?0@(e73+4)t7%~V00000bc2Ow+000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aok!eo>Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oL}eh47| z000J1OjJex|Nj6009C@%egFUgW=TXrRCwCtn2ip@AP9u--v6bSt<$Lkg{pKvW?7nQ zxvwaQ1%F~1i-z#lh(Yq%H(_gqvV83gECM*!&j&z5tqP0KouFdS##onB48q zUkUJZKc#Xg?L7HPf}Quk!5{z>)07x9@WLp_=6?kM;`x_H%>huPI_z};n3l!d6m$~- zbbw3tf*RmuU}6gB>aPF_FH}TJ&jZxYB~56a190kt3c=ZHlymlHutNY;m9%BapX#+?Pm2=7!0A+&c)!6Oo z=~z#K4?zC9GRm{d0Elv@P~)?H_fhPw02o6CH~_$P pEZ_$H6MOBI0I)7?qq&;^0|4Z21;)FNg7E+V002ovPDHLkV1nMUU}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-b=;hDE%QbOU0W&X`!elN+CsrV> zps?A8aS0Gd~Y34iOD+9 zf0HHJC8H14qjK5W)do3KJdj%!Q&RggW877sQGTozB4}j`kuj#_1p&zg}wr&gcZ{N zI0cwff@PQ{`26%}R1Mt4B*yqF^cl}(uSNN9`1h=F*dNUx)?qZ$bluU&0EPgD1}o_# zrX3v1>ZeIH*liYA@@m(jyaxSmPE0J#i5!0n`WjX=x<3!CR$JiX9Fiw&#bCm;hM|f< zV_n`&u>#$rKR9oS34CYL5I@1n7}MEU;Sjs>0_&B3D*m%iZfauEe7e|D){Q~qd7olu5+Z>X@>H4PuH#$#hsOG3V$Z7UH8dXogv*L zy5ZEmdd}Gldour*{FAycM_YoSO#emA?ef_SheRB{FcyUBXO=|lJ_n3?22WQ%mvv4F FO#pDe(sBR* delta 545 zcmV++0^a?C3*ZWn7%~V00000bc2Ow+000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aok!eo>Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oM(r97wr z000J1OjJex|Nj6009C@%egFUgU`a$lRCwCtn2QdBAPhx&|No~KryyWKN+0e)mcl00jdy=@o$z5*z`P!XBl2hhKlG@-c$Ak-&x2v)DMQvFLVtUGpu>T~_Fjeg%w z_5ZnUwbwz(JAsvkkPX|Ww%h>Rd2tyaJ>Vw9buIA(z~x9~)pAc^2tdF9fKvV_)osr} zl~Sn~0SuO!0r0PRF8-dWXe$7qvScywDJiIy0K7%>D40r=^X-HVz~FZLH~=jN!MMUW jzXCRNfP%mP;3dESp_c`?`EG1V00000NkvXXu0mjfVa42_ diff --git a/assets/dolphin/internal/L1_NoSd_128x49/frame_2.png b/assets/dolphin/internal/L1_NoSd_128x49/frame_2.png index 12dc13430908844d89e0c7a002030cdc4999124b..5b474fff262306ecccbdc2a0ace273bd26e55219 100644 GIT binary patch delta 588 zcmaFL)xkYMB9Midfq~&c+a3)d#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-b=;hDE%QbOU0W&X`!elN+CsrV> zps?A8aS0Gd~Y34iODv^(Izmxfoo%Z3S(t+2?qoBLQV~aLI#7j;5jElsuK4x{$WbkrF~__S?SyQ z4Xv$nD`T=F?l_n+eD*4}o3*)*;cTVZ&nds`8h%zWE%E-i*H6c~{A-oBtp0-CE~X9k zT!Gfn`<94*+8YqlaIVk2q0mO>u*F<$8OCPK^Y318J6LGRIdI6=gzKB#_`MI5Y#2OU L{an^LB{Ts5>L%C3 delta 550 zcmV+>0@?kD3*`!s7%~V00000bc2Ow+000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aok!eo>Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oML+;Z^% z000J1OjJex|Nj6009C@%egFUgWl2OqRCwC#n2Qd>AP7ad|Nqm=Qf+;Jq5|2LnPus! z<(>+HlYc0tp=cD|8qsJ5PA(8Zl4|Z_(9ZOAU4Rn-l$~!8@dGFQvfBv&>H$6gppOT* zhqwTMRsbAU0Tu>%0D!&%fPNQX?WsRN9Dral3g9x<+XRIHWDG3m+W}n0I-@gvOMt8n zaB+b&BwcZ^=QDub1(nK$_a1;7*fa>!TM`2RN`GHB#2Ekv>zzgb$YF8j0xV{s3=okC z(RSAWkAVXh%=IAw6thqf+317QXa2fAKehl=`VdM%wPg1IR`t7FSnt?j>3=o~N_}p> zY*mP*g;2dew_CNVgFCws1Av*0Wq=75xB_GefV#G_5teT2W^fZAUqCMVN(UYS5TvqO zI#(aIF`xlxHW_5P3Of53#NpHrI{^GK7k~U@z6y#o$sV@#2M-hlAlM^6fMGt;=h4j& om?U^|JQ>#kcpg9-0=xtm0DO@JvS@mv#Q*>R07*qoM6N<$g7Hz*umAu6 diff --git a/assets/dolphin/internal/L1_NoSd_128x49/frame_3.png b/assets/dolphin/internal/L1_NoSd_128x49/frame_3.png index f17f8713d34b7702ad58def6cf332b1770412808..952f968fb673a5de24fefb834e6c8655cc29a6d4 100644 GIT binary patch delta 587 zcmaFF)y_RZB9Midfq~&c+a3)d#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-b=;hDE%QbOU0W&X`!elN+CsrV> zps?A8aS0Gd~Y34iOD!g+4&{$9uXshIkymJ1uh3VFezSm(p9_ z)!&?WBpwptZfZ+(^0SUjtyk(cTKl47|Yk0XXAgSzR zb~yt#x3x!1_DR=AtTVz_eJ*`=GxU&o!?Qix-qkRC{>tFsCH3#o^V=Fv&fFDAmR(-$ zP~Q29^B{M^pDTYiU3-xXHjCsf*;S(Qsp`MB3A-}~ky{o^?wipBB OpTX1B&t;ucLK6VtnBzwP delta 547 zcmV+;0^I$F3*rip7%~V00000bc2Ow+000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aok!eo>Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oN4z+l$^ z000J1OjJex|Nj6009C@%egFUgVo5|nRCwC#m;nxhAPhzO?tkfJ5fr2dg+jJv#26>6 z|6xn1iht~BBu%!ro9J!^O>QGXP3m@^hc>6**9D6R=&0s#360Qp@2+rRz*`v58?cL5y6N}I?wfQW%X-w)t0Rv2yRdjdpt z(BgtHBwT5*^G|@%1)0i$_a49r>>7k&mZAV4;eT{O%mMJQ-sK5^7#4Fbz?g+1z>ZAF zy*mfE3{1G7txpXgc?ubkk3O2d^6Gm17y{_hr?M4fOLh#vs$b;7ykf`G|7sMZ`dYp0 zwGr1ALN7P^ lpO$=HP6xC7PXN3G7yx#e1*^`5DHH$z002ovPDHLkV1mgA;jjPz diff --git a/assets/dolphin/internal/L1_NoSd_128x49/frame_4.png b/assets/dolphin/internal/L1_NoSd_128x49/frame_4.png index 7a6992a2b04cdaf35abb8c23f269293e143a4ea0..2bb43b306f3bf9025ba68190fb4903cc5a132133 100644 GIT binary patch delta 573 zcmcb^^^;M1%fy~fDm+OEOXMsm#F#`kNArNL1)$nRyU|^m<(aWESmuupz0%l$=g~?ouPOLy$ zL1D8G;}S-8FjGNc@&~4c^$PlS5U!1WQA(PXOKNd)QD#9&W_})693mRz;s)f|=vP=( z3GX z?|;K45}z%!CFpnd%qu-752SNv`LMGECR^2S72>k&jo)(aQFL@wwWL&=wfvcc^9*_g zsw*$N=4}vt@1-87e^Vf!L7HL7dPcQO<^%5;S82w%EqTxQ?ZjdJTC;trFl$Ns3O1XL@Pk`6ubuwKq0WDbz=F?@ x#S-4|pEmM)FWT2|aB6k>7gmMbNR|ng_&I;+l{b0*l?BE)gQu&X%Q~loCIB#J)NKF& delta 541 zcmV+&0^Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oL=qvEvy z000J1OjJex|Nj6009C@%egFUgTuDShRCwC#n2Qd>AP7ad|Nqm=nrTr{QGx8`mZqyM z_e>C}M1L_2tWkKYM57rbxj=-TRCOJLcBZfE0-Ok-?0kxJzi`s$-A({d-{1oPdV7F; ziwgi~1;AkzVBsbY0MJJO(DwqYJ@p6pc>qu}KvkoKk3ea3rf&xTmiO8KNGnf1L+UaF z5dTzh1s4M7`n<-*&IR(I-UIMDWQa3>!5GjG0Dmbg&Rl@SB#;0iW&!H%65uv);DWh6 zdH_6Bu=^s1sW`^3uJ?~E0F^#EO98vI`zpJt-{iuwVu$TAAVdMzm+EC3{d)b8^&wTO zHaT#&7%%{s*;odcUs0ZWtOW?Q@QKv4i4d*lZ&%t!h>x)}nK1W%4T<2nG( f4QNAvhX4Zr1eOJu%LfM}00000NkvXXu0mjf9sAk! diff --git a/assets/dolphin/internal/L1_NoSd_128x49/frame_5.png b/assets/dolphin/internal/L1_NoSd_128x49/frame_5.png index 00d9843007e85a247de0c23257c310512b5f71f5..d7f8c6402a27c5a2eb565d12b595a3a438ed94ee 100644 GIT binary patch delta 584 zcmaFJ)xteNB9Midfq~&c+a3)d#aJBV?!>U}oXkrghb7(7*O7r?V?XzwL{=c5Ex;$l z_5c6>KxXKn%XL7Cv%n*=n1O-s5C}7hYIrp;Ffh-b=;hDE%QbOU0W&X`!elN+CsrV> zps?A8aS0Gd~Y34iODz$gZO)!`%nnn~{g8^b441&v9d6lX$2%~n|wpQUNDi>ERVTD;TVg~x&%=k2Q!AubA1(z zAx*2N)^jGDkLIu{+3kCmaeoB2xPqijTf^-4JSU_+l*FA)XNs2GRHXlcIYH=wbOQf^ zCpXvLW_lHJ#`(pzhCN~$sm(kb2Nc?FF`F<*{B>>aUYRR@`DFq7fs*hQn)CgqTQ^K^ zom)98JK~Om9K*b+vud`aS|uyuqh zX6oPe`*r@3B|}Ns9j2bgiIK-%#ysSZ@Yz}J9?y`n+Lb}cz9mQhq<7|ZMPTGJc)I$z JtaD0e0syY@+hza& delta 546 zcmV+-0^R+D3*ico7%~V00000bc2Ow+000?uMObuGZ)S9NVRB^vL1b@YWgtmyVP|Dh zWnpA_ami&o000Aok!eo>Ad$LolPv*4vvdKZ0h1pCp?@zvAUrQ}WM(=fFD zZ*D#yJTG!&W;#+tMm``sFL*k5ZE$U6bYVUqJU@7FVPk7$bRcDJWIZBsB0oNIez$f2 z000J1OjJex|Nj6009C@%egFUgVM#AP7ad|Nqm=)@jv(q5|E+G)*%N z_e=#5qJNl%qEUEjM57rvxj+O-s`(wAwx_S_0-Ok-?0kxd51jPNZYKb!2lxPhJ{}+s zaRC6$062I7CI)!`fW88Neir~8sT%=a?#7sm0yu0jHva_xCqR=8P%uCfUJ*D0NYg!` zZwc_8esJkfI(hOJ2fIH52Ll68EK_34z=mFs&3`ihp!X|}+5-Sfb=d0yAZ?4iCFlkM zk^ycx3u=JVz{V0_s=op#W}zZ7y$?XXmo%=q1~92l5C~SUva|Y^SXgK52-WBEWgC6j zPWAt}Y}GCkSV;&C07f>Z0R~u1nA=H-ne?eSTg8B{4dsgf=>y`iuU)`R0D>6s%VXYl z4^wCWnk0ivz2IUWoqaf5hZO+6%*B_V%)OuplWei=T6mx+0Kp#l0d(V$K8`MKfkA*L k$I7@4z_S2t2=EYK0A@u6zLP8OIRF3v07*qoM6N<$g6II$yZ`_I From e12958d408dfe0e1571b60451bf73b1d41914981 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Sun, 29 Jan 2023 15:08:26 +0400 Subject: [PATCH 21/24] [FL-3082] WS: add protocol LaCrosse-TX (TFA Dostmann) (#2292) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WS: add protocol LaCrosse-TX (TFA Dostmann) * WS: fix syntax * WS: fix MSG_TYPE * WS: fix PVS Co-authored-by: あく --- .../helpers/weather_station_types.h | 2 +- .../weather_station/protocols/lacrosse_tx.c | 329 ++++++++++++++++++ .../weather_station/protocols/lacrosse_tx.h | 79 +++++ .../protocols/protocol_items.c | 1 + .../protocols/protocol_items.h | 1 + 5 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 applications/plugins/weather_station/protocols/lacrosse_tx.c create mode 100644 applications/plugins/weather_station/protocols/lacrosse_tx.h diff --git a/applications/plugins/weather_station/helpers/weather_station_types.h b/applications/plugins/weather_station/helpers/weather_station_types.h index d512251f1..1f5612e2e 100644 --- a/applications/plugins/weather_station/helpers/weather_station_types.h +++ b/applications/plugins/weather_station/helpers/weather_station_types.h @@ -3,7 +3,7 @@ #include #include -#define WS_VERSION_APP "0.6.1" +#define WS_VERSION_APP "0.7" #define WS_DEVELOPED "SkorP" #define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx.c b/applications/plugins/weather_station/protocols/lacrosse_tx.c new file mode 100644 index 000000000..8d8a24e24 --- /dev/null +++ b/applications/plugins/weather_station/protocols/lacrosse_tx.c @@ -0,0 +1,329 @@ +#include "lacrosse_tx.h" + +#define TAG "WSProtocolLaCrosse_TX" + +/* + * Help + * https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse.c + * + * + * LaCrosse TX 433 Mhz Temperature and Humidity Sensors. + * - Tested: TX-7U and TX-6U (Temperature only) + * - Not Tested but should work: TX-3, TX-4 + * - also TFA Dostmann 30.3120.90 sensor (for e.g. 35.1018.06 (WS-9015) station) + * - also TFA Dostmann 30.3121 sensor + * Protocol Documentation: http://www.f6fbb.org/domo/sensors/tx3_th.php + * Message is 44 bits, 11 x 4 bit nybbles: + * [00] [cnt = 10] [type] [addr] [addr + parity] [v1] [v2] [v3] [iv1] [iv2] [check] + * Notes: + * - Zero Pulses are longer (1,400 uS High, 1,000 uS Low) = 2,400 uS + * - One Pulses are shorter ( 550 uS High, 1,000 uS Low) = 1,600 uS + * - Sensor id changes when the battery is changed + * - Primary Value are BCD with one decimal place: vvv = 12.3 + * - Secondary value is integer only intval = 12, seems to be a repeat of primary + * This may actually be an additional data check because the 4 bit checksum + * and parity bit is pretty week at detecting errors. + * - Temperature is in Celsius with 50.0 added (to handle negative values) + * - Humidity values appear to be integer precision, decimal always 0. + * - There is a 4 bit checksum and a parity bit covering the three digit value + * - Parity check for TX-3 and TX-4 might be different. + * - Msg sent with one repeat after 30 mS + * - Temperature and humidity are sent as separate messages + * - Frequency for each sensor may be could be off by as much as 50-75 khz + * - LaCrosse Sensors in other frequency ranges (915 Mhz) use FSK not OOK + * so they can't be decoded by rtl_433 currently. + * - Temperature and Humidity are sent in different messages bursts. +*/ + +#define LACROSSE_TX_GAP 1000 +#define LACROSSE_TX_BIT_SIZE 44 +#define LACROSSE_TX_SUNC_PATTERN 0x0A000000000 +#define LACROSSE_TX_SUNC_MASK 0x0F000000000 +#define LACROSSE_TX_MSG_TYPE_TEMP 0x00 +#define LACROSSE_TX_MSG_TYPE_HUM 0x0E + +static const SubGhzBlockConst ws_protocol_lacrosse_tx_const = { + .te_short = 550, + .te_long = 1300, + .te_delta = 120, + .min_count_bit_for_found = 40, +}; + +struct WSProtocolDecoderLaCrosse_TX { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + WSBlockGeneric generic; + + uint16_t header_count; +}; + +struct WSProtocolEncoderLaCrosse_TX { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + WSBlockGeneric generic; +}; + +typedef enum { + LaCrosse_TXDecoderStepReset = 0, + LaCrosse_TXDecoderStepCheckPreambule, + LaCrosse_TXDecoderStepSaveDuration, + LaCrosse_TXDecoderStepCheckDuration, +} LaCrosse_TXDecoderStep; + +const SubGhzProtocolDecoder ws_protocol_lacrosse_tx_decoder = { + .alloc = ws_protocol_decoder_lacrosse_tx_alloc, + .free = ws_protocol_decoder_lacrosse_tx_free, + + .feed = ws_protocol_decoder_lacrosse_tx_feed, + .reset = ws_protocol_decoder_lacrosse_tx_reset, + + .get_hash_data = ws_protocol_decoder_lacrosse_tx_get_hash_data, + .serialize = ws_protocol_decoder_lacrosse_tx_serialize, + .deserialize = ws_protocol_decoder_lacrosse_tx_deserialize, + .get_string = ws_protocol_decoder_lacrosse_tx_get_string, +}; + +const SubGhzProtocolEncoder ws_protocol_lacrosse_tx_encoder = { + .alloc = NULL, + .free = NULL, + + .deserialize = NULL, + .stop = NULL, + .yield = NULL, +}; + +const SubGhzProtocol ws_protocol_lacrosse_tx = { + .name = WS_PROTOCOL_LACROSSE_TX_NAME, + .type = SubGhzProtocolWeatherStation, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable, + + .decoder = &ws_protocol_lacrosse_tx_decoder, + .encoder = &ws_protocol_lacrosse_tx_encoder, +}; + +void* ws_protocol_decoder_lacrosse_tx_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + WSProtocolDecoderLaCrosse_TX* instance = malloc(sizeof(WSProtocolDecoderLaCrosse_TX)); + instance->base.protocol = &ws_protocol_lacrosse_tx; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void ws_protocol_decoder_lacrosse_tx_free(void* context) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + free(instance); +} + +void ws_protocol_decoder_lacrosse_tx_reset(void* context) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + instance->header_count = 0; + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; +} + +static bool ws_protocol_lacrosse_tx_check_crc(WSProtocolDecoderLaCrosse_TX* instance) { + if(!instance->decoder.decode_data) return false; + uint8_t msg[] = { + (instance->decoder.decode_data >> 36) & 0x0F, + (instance->decoder.decode_data >> 32) & 0x0F, + (instance->decoder.decode_data >> 28) & 0x0F, + (instance->decoder.decode_data >> 24) & 0x0F, + (instance->decoder.decode_data >> 20) & 0x0F, + (instance->decoder.decode_data >> 16) & 0x0F, + (instance->decoder.decode_data >> 12) & 0x0F, + (instance->decoder.decode_data >> 8) & 0x0F, + (instance->decoder.decode_data >> 4) & 0x0F}; + + uint8_t crc = subghz_protocol_blocks_add_bytes(msg, 9); + return ((crc & 0x0F) == ((instance->decoder.decode_data) & 0x0F)); +} + +/** + * Analysis of received data + * @param instance Pointer to a WSBlockGeneric* instance + */ +static void ws_protocol_lacrosse_tx_remote_controller(WSBlockGeneric* instance) { + uint8_t msg_type = (instance->data >> 32) & 0x0F; + instance->id = (((instance->data >> 28) & 0x0F) << 3) | (((instance->data >> 24) & 0x0F) >> 1); + + float msg_value = (float)((instance->data >> 20) & 0x0F) * 10.0f + + (float)((instance->data >> 16) & 0x0F) + + (float)((instance->data >> 12) & 0x0F) * 0.1f; + + if(msg_type == LACROSSE_TX_MSG_TYPE_TEMP) { //-V1051 + instance->temp = msg_value - 50.0f; + instance->humidity = WS_NO_HUMIDITY; + } else if(msg_type == LACROSSE_TX_MSG_TYPE_HUM) { + //ToDo for verification, records are needed with sensors maintaining temperature and temperature for this standard + instance->humidity = (uint8_t)msg_value; + } else { + furi_crash("WS: WSProtocolLaCrosse_TX incorrect msg_type."); + } + + instance->btn = WS_NO_BTN; + instance->battery_low = WS_NO_BATT; + instance->channel = WS_NO_CHANNEL; +} + +void ws_protocol_decoder_lacrosse_tx_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + + switch(instance->decoder.parser_step) { + case LaCrosse_TXDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, LACROSSE_TX_GAP) < + ws_protocol_lacrosse_tx_const.te_delta * 2)) { + instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckPreambule; + instance->header_count = 0; + } + break; + + case LaCrosse_TXDecoderStepCheckPreambule: + + if(level) { + if((DURATION_DIFF(duration, ws_protocol_lacrosse_tx_const.te_short) < + ws_protocol_lacrosse_tx_const.te_delta) && + (instance->header_count > 1)) { + instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.te_last = duration; + } else if(duration > (ws_protocol_lacrosse_tx_const.te_long * 2)) { + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + } + } else { + if(DURATION_DIFF(duration, LACROSSE_TX_GAP) < + ws_protocol_lacrosse_tx_const.te_delta * 2) { + instance->decoder.te_last = duration; + instance->header_count++; + } else { + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + } + } + + break; + + case LaCrosse_TXDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = LaCrosse_TXDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + } + break; + + case LaCrosse_TXDecoderStepCheckDuration: + + if(!level) { + if(duration > LACROSSE_TX_GAP * 3) { + if(DURATION_DIFF( + instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_short) < + ws_protocol_lacrosse_tx_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; + } else if( + DURATION_DIFF( + instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_long) < + ws_protocol_lacrosse_tx_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; + } + if((instance->decoder.decode_data & LACROSSE_TX_SUNC_MASK) == + LACROSSE_TX_SUNC_PATTERN) { + if(ws_protocol_lacrosse_tx_check_crc(instance)) { + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = LACROSSE_TX_BIT_SIZE; + ws_protocol_lacrosse_tx_remote_controller(&instance->generic); + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + } + + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->header_count = 0; + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + break; + } else if( + (DURATION_DIFF(instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_short) < + ws_protocol_lacrosse_tx_const.te_delta) && + (DURATION_DIFF(duration, LACROSSE_TX_GAP) < + ws_protocol_lacrosse_tx_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, ws_protocol_lacrosse_tx_const.te_long) < + ws_protocol_lacrosse_tx_const.te_delta) && + (DURATION_DIFF(duration, LACROSSE_TX_GAP) < + ws_protocol_lacrosse_tx_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = LaCrosse_TXDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + } + + } else { + instance->decoder.parser_step = LaCrosse_TXDecoderStepReset; + } + + break; + } +} + +uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool ws_protocol_decoder_lacrosse_tx_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + return ws_block_generic_serialize(&instance->generic, flipper_format, preset); +} + +bool ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + bool ret = false; + do { + if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + ws_protocol_lacrosse_tx_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + ret = true; + } while(false); + return ret; +} + +void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) { + furi_assert(context); + WSProtocolDecoderLaCrosse_TX* instance = context; + furi_string_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%lX Ch:%d Bat:%d\r\n" + "Temp:%3.1f C Hum:%d%%", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)(instance->generic.data), + instance->generic.id, + instance->generic.channel, + instance->generic.battery_low, + (double)instance->generic.temp, + instance->generic.humidity); +} diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx.h b/applications/plugins/weather_station/protocols/lacrosse_tx.h new file mode 100644 index 000000000..e88455689 --- /dev/null +++ b/applications/plugins/weather_station/protocols/lacrosse_tx.h @@ -0,0 +1,79 @@ +#pragma once + +#include + +#include +#include +#include +#include "ws_generic.h" +#include + +#define WS_PROTOCOL_LACROSSE_TX_NAME "LaCrosse_TX" + +typedef struct WSProtocolDecoderLaCrosse_TX WSProtocolDecoderLaCrosse_TX; +typedef struct WSProtocolEncoderLaCrosse_TX WSProtocolEncoderLaCrosse_TX; + +extern const SubGhzProtocolDecoder ws_protocol_lacrosse_tx_decoder; +extern const SubGhzProtocolEncoder ws_protocol_lacrosse_tx_encoder; +extern const SubGhzProtocol ws_protocol_lacrosse_tx; + +/** + * Allocate WSProtocolDecoderLaCrosse_TX. + * @param environment Pointer to a SubGhzEnvironment instance + * @return WSProtocolDecoderLaCrosse_TX* pointer to a WSProtocolDecoderLaCrosse_TX instance + */ +void* ws_protocol_decoder_lacrosse_tx_alloc(SubGhzEnvironment* environment); + +/** + * Free WSProtocolDecoderLaCrosse_TX. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + */ +void ws_protocol_decoder_lacrosse_tx_free(void* context); + +/** + * Reset decoder WSProtocolDecoderLaCrosse_TX. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + */ +void ws_protocol_decoder_lacrosse_tx_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void ws_protocol_decoder_lacrosse_tx_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + * @return hash Hash sum + */ +uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context); + +/** + * Serialize data WSProtocolDecoderLaCrosse_TX. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool ws_protocol_decoder_lacrosse_tx_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data WSProtocolDecoderLaCrosse_TX. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance + * @param output Resulting text + */ +void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output); diff --git a/applications/plugins/weather_station/protocols/protocol_items.c b/applications/plugins/weather_station/protocols/protocol_items.c index 99c8344f4..2c9d751c7 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.c +++ b/applications/plugins/weather_station/protocols/protocol_items.c @@ -8,6 +8,7 @@ const SubGhzProtocol* weather_station_protocol_registry_items[] = { &ws_protocol_gt_wt_03, &ws_protocol_acurite_606tx, &ws_protocol_acurite_609txc, + &ws_protocol_lacrosse_tx, &ws_protocol_lacrosse_tx141thbv2, &ws_protocol_oregon2, &ws_protocol_acurite_592txr, diff --git a/applications/plugins/weather_station/protocols/protocol_items.h b/applications/plugins/weather_station/protocols/protocol_items.h index 9d5d096f8..f9e443abc 100644 --- a/applications/plugins/weather_station/protocols/protocol_items.h +++ b/applications/plugins/weather_station/protocols/protocol_items.h @@ -8,6 +8,7 @@ #include "gt_wt_03.h" #include "acurite_606tx.h" #include "acurite_609txc.h" +#include "lacrosse_tx.h" #include "lacrosse_tx141thbv2.h" #include "oregon2.h" #include "acurite_592txr.h" From a8e5f2250026c4260bb13fddf696acb7f9322b77 Mon Sep 17 00:00:00 2001 From: Angel Date: Sun, 29 Jan 2023 06:23:45 -0500 Subject: [PATCH 22/24] LF-RFID: add CRC calculation to paradox protocol (#2299) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Angel Co-authored-by: あく --- lib/lfrfid/protocols/protocol_paradox.c | 45 ++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/lfrfid/protocols/protocol_paradox.c b/lib/lfrfid/protocols/protocol_paradox.c index 7e029f1de..26c9b55dc 100644 --- a/lib/lfrfid/protocols/protocol_paradox.c +++ b/lib/lfrfid/protocols/protocol_paradox.c @@ -136,17 +136,45 @@ LevelDuration protocol_paradox_encoder_yield(ProtocolParadox* protocol) { return level_duration_make(level, duration); }; +static uint8_t protocol_paradox_calculate_checksum(uint8_t fc, uint16_t card_id) { + uint8_t card_hi = (card_id >> 8) & 0xff; + uint8_t card_lo = card_id & 0xff; + + uint8_t arr[5] = {0, 0, fc, card_hi, card_lo}; + + uint8_t manchester[9]; + + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, false); + + for(uint8_t i = 6; i < 40; i += 1) { + if(bit_lib_get_bit(arr, i) == 0b1) { + bit_lib_push_bit(manchester, 9, true); + bit_lib_push_bit(manchester, 9, false); + } else { + bit_lib_push_bit(manchester, 9, false); + bit_lib_push_bit(manchester, 9, true); + } + } + + uint8_t output = bit_lib_crc8(manchester, 9, 0x31, 0x00, true, true, 0x06); + + return output; +} + void protocol_paradox_render_data(ProtocolParadox* protocol, FuriString* result) { uint8_t* decoded_data = protocol->data; uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); + uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8); + uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id); furi_string_cat_printf(result, "Facility: %u\r\n", fc); furi_string_cat_printf(result, "Card: %u\r\n", card_id); - furi_string_cat_printf(result, "Data: "); - for(size_t i = 0; i < PARADOX_DECODED_DATA_SIZE; i++) { - furi_string_cat_printf(result, "%02X", decoded_data[i]); - } + furi_string_cat_printf(result, "CRC: %u Calc CRC: %u\r\n", card_crc, calc_crc); + if(card_crc != calc_crc) furi_string_cat_printf(result, "CRC Mismatch, Invalid Card!\r\n"); }; void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* result) { @@ -154,8 +182,15 @@ void protocol_paradox_render_brief_data(ProtocolParadox* protocol, FuriString* r uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8); uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16); + uint8_t card_crc = bit_lib_get_bits_16(decoded_data, 34, 8); + uint8_t calc_crc = protocol_paradox_calculate_checksum(fc, card_id); - furi_string_cat_printf(result, "FC: %03u, Card: %05u", fc, card_id); + furi_string_cat_printf(result, "FC: %03u, Card: %05u\r\n", fc, card_id); + if(calc_crc == card_crc) { + furi_string_cat_printf(result, "CRC : %03u", card_crc); + } else { + furi_string_cat_printf(result, "Card is Invalid!"); + } }; bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) { From b1496ee9bd97ff8c34a67a49ec4ecdc6cfbd9436 Mon Sep 17 00:00:00 2001 From: Milk-Cool <43724263+Milk-Cool@users.noreply.github.com> Date: Mon, 30 Jan 2023 10:54:15 +0300 Subject: [PATCH 23/24] Furi: getter for current thread stdout write callback (#2344) --- firmware/targets/f7/api_symbols.csv | 5 +++-- furi/core/thread.c | 6 ++++++ furi/core/thread.h | 6 ++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a75e88bad..7b247daed 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.8,, +Version,+,11.9,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1389,8 +1389,8 @@ Function,+,furi_hal_version_uid_size,size_t, Function,-,furi_hal_vibro_init,void, Function,+,furi_hal_vibro_on,void,_Bool Function,-,furi_init,void, -Function,+,furi_kernel_is_irq_or_masked,_Bool, Function,+,furi_kernel_get_tick_frequency,uint32_t, +Function,+,furi_kernel_is_irq_or_masked,_Bool, Function,+,furi_kernel_lock,int32_t, Function,+,furi_kernel_restore_lock,int32_t,int32_t Function,+,furi_kernel_unlock,int32_t, @@ -1515,6 +1515,7 @@ Function,+,furi_thread_get_name,const char*,FuriThreadId Function,+,furi_thread_get_return_code,int32_t,FuriThread* Function,+,furi_thread_get_stack_space,uint32_t,FuriThreadId Function,+,furi_thread_get_state,FuriThreadState,FuriThread* +Function,+,furi_thread_get_stdout_callback,FuriThreadStdoutWriteCallback, Function,+,furi_thread_is_suspended,_Bool,FuriThreadId Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_mark_as_service,void,FuriThread* diff --git a/furi/core/thread.c b/furi/core/thread.c index c966dd572..ef9560b4a 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -530,6 +530,12 @@ bool furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback) { return true; } +FuriThreadStdoutWriteCallback furi_thread_get_stdout_callback() { + FuriThread* thread = furi_thread_get_current(); + + return thread->output.write_callback; +} + size_t furi_thread_stdout_write(const char* data, size_t size) { FuriThread* thread = furi_thread_get_current(); diff --git a/furi/core/thread.h b/furi/core/thread.h index c2f5a9130..1542d5bf0 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -227,6 +227,12 @@ const char* furi_thread_get_name(FuriThreadId thread_id); uint32_t furi_thread_get_stack_space(FuriThreadId thread_id); +/** Get STDOUT callback for thead + * + * @return STDOUT callback + */ +FuriThreadStdoutWriteCallback furi_thread_get_stdout_callback(); + /** Set STDOUT callback for thread * * @param callback callback or NULL to clear From 5db7fdf9852ec4a412765e265cd10d39c02305b7 Mon Sep 17 00:00:00 2001 From: Noam Drong Date: Mon, 30 Jan 2023 09:03:10 +0100 Subject: [PATCH 24/24] Add support for `GUI-CTRL` in bad_usb (#2315) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/main/bad_usb/bad_usb_script.c | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index bbd721ed2..e2281133f 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -50,6 +50,7 @@ static const DuckyKey ducky_keys[] = { {"ALT-SHIFT", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_SHIFT}, {"ALT-GUI", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_GUI}, {"GUI-SHIFT", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT}, + {"GUI-CTRL", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL}, {"CTRL", KEY_MOD_LEFT_CTRL}, {"CONTROL", KEY_MOD_LEFT_CTRL},