diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b9eb4d70..bd85858a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,7 +58,7 @@ jobs: - name: 'Bundle scripts' if: ${{ !github.event.pull_request.head.repo.fork }} run: | - tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts + tar czpf "artifacts/flipper-z-any-scripts-${SUFFIX}.tgz" scripts - name: 'Build the firmware' run: | @@ -73,6 +73,8 @@ jobs: ./fbt TARGET_HW=$TARGET_HW fap_dist tar czpf "artifacts/flipper-z-${TARGET}-debugapps-${SUFFIX}.tgz" \ -C dist/${TARGET}-*/apps/Debug . + tar czpf "artifacts/flipper-z-${TARGET}-appsymbols-${SUFFIX}.tgz" \ + -C dist/${TARGET}-*/debug_elf . done - name: "Check for uncommitted changes" diff --git a/.github/workflows/lint_and_submodule_check.yml b/.github/workflows/lint_and_submodule_check.yml index 22ca7d89..b85409ec 100644 --- a/.github/workflows/lint_and_submodule_check.yml +++ b/.github/workflows/lint_and_submodule_check.yml @@ -23,9 +23,8 @@ jobs: - name: 'Checkout code' uses: actions/checkout@v3 with: - fetch-depth: 1 - ref: ${{ github.event.pull_request.head.sha }} - + fetch-depth: 2 + ref: ${{ github.sha }} - name: 'Check protobuf branch' run: | @@ -48,8 +47,26 @@ jobs: exit 1; fi + - name: 'Check for new TODOs' + id: check_todos + if: github.event_name == 'pull_request' + run: | + set +e; + git diff --unified=0 --no-color ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep -E '^\+' | grep -i -E '(TODO|HACK|FIXME|XXX)[ :]' | grep -v -- '-nofl' > lines.log; + MISSING_TICKETS=$( grep -v -E '\[FL-[0-9]+\]' lines.log ); + if [ -n "$MISSING_TICKETS" ]; then + echo "Error: Missing ticket number in \`TODO\` comment(s)" >> $GITHUB_STEP_SUMMARY; + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY; + echo "$MISSING_TICKETS" >> $GITHUB_STEP_SUMMARY; + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY; + exit 1; + else + echo "No new TODOs without tickets found" >> $GITHUB_STEP_SUMMARY; + fi + - name: 'Check Python code formatting' id: syntax_check_py + if: always() run: | set +e; ./fbt -s lint_py 2>&1 | tee lint-py.log; diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 9c6c6b2d..794dce37 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -31,7 +31,7 @@ jobs: if: success() timeout-minutes: 10 run: | - ./fbt flash OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 + ./fbt flash SWD_TRANSPORT_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 - name: 'Wait for flipper and format ext' id: format_ext @@ -45,9 +45,10 @@ jobs: - name: 'Copy assets and unit data, reboot and wait for flipper' id: copy if: steps.format_ext.outcome == 'success' - timeout-minutes: 5 + timeout-minutes: 7 run: | source scripts/toolchain/fbtenv.sh + python3 scripts/testing/await_flipper.py ${{steps.device.outputs.flipper}} python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/resources /ext python3 scripts/storage.py -p ${{steps.device.outputs.flipper}} -f send assets/unit_tests /ext/unit_tests python3 scripts/power.py -p ${{steps.device.outputs.flipper}} reboot @@ -64,4 +65,4 @@ jobs: - name: 'Check GDB output' if: failure() run: | - ./fbt gdb_trace_all OPENOCD_ADAPTER_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 + ./fbt gdb_trace_all SWD_TRANSPORT_SERIAL=2A0906016415303030303032 FIRMWARE_APP_SET=unit_tests FORCE=1 diff --git a/.github/workflows/updater_test.yml b/.github/workflows/updater_test.yml index 27a181c4..f4064e1c 100644 --- a/.github/workflows/updater_test.yml +++ b/.github/workflows/updater_test.yml @@ -64,7 +64,7 @@ jobs: - name: 'Flash last release' if: failure() run: | - ./fbt flash OPENOCD_ADAPTER_SERIAL=${{steps.device.outputs.stlink}} FORCE=1 + ./fbt flash SWD_TRANSPORT_SERIAL=${{steps.device.outputs.stlink}} FORCE=1 - name: 'Wait for flipper and format ext' if: failure() diff --git a/.vscode/.gitignore b/.vscode/.gitignore index 670df7d4..481efcde 100644 --- a/.vscode/.gitignore +++ b/.vscode/.gitignore @@ -1,4 +1,5 @@ -./c_cpp_properties.json -./launch.json -./settings.json -./tasks.json +/c_cpp_properties.json +/extensions.json +/launch.json +/settings.json +/tasks.json diff --git a/.vscode/example/clangd/extensions.json b/.vscode/example/clangd/extensions.json new file mode 100644 index 00000000..daab417c --- /dev/null +++ b/.vscode/example/clangd/extensions.json @@ -0,0 +1,19 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "ms-python.black-formatter", + "llvm-vs-code-extensions.vscode-clangd", + "amiralizadeh9480.cpp-helper", + "marus25.cortex-debug", + "zxh404.vscode-proto3", + "augustocdias.tasks-shell-input" + ], + // List of extensions recommended by VS Code that should not be recommended for users of this workspace. + "unwantedRecommendations": [ + "twxs.cmake", + "ms-vscode.cpptools", + "ms-vscode.cmake-tools" + ] +} diff --git a/.vscode/example/c_cpp_properties.json b/.vscode/example/cpptools/c_cpp_properties.json similarity index 100% rename from .vscode/example/c_cpp_properties.json rename to .vscode/example/cpptools/c_cpp_properties.json diff --git a/.vscode/extensions.json b/.vscode/example/cpptools/extensions.json similarity index 93% rename from .vscode/extensions.json rename to .vscode/example/cpptools/extensions.json index ead935b0..a8babee1 100644 --- a/.vscode/extensions.json +++ b/.vscode/example/cpptools/extensions.json @@ -13,6 +13,7 @@ ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [ + "llvm-vs-code-extensions.vscode-clangd", "twxs.cmake", "ms-vscode.cmake-tools" ] diff --git a/.vscode/example/settings.json b/.vscode/example/settings.json index 19a03b69..efa08157 100644 --- a/.vscode/example/settings.json +++ b/.vscode/example/settings.json @@ -21,5 +21,10 @@ "SConscript": "python", "SConstruct": "python", "*.fam": "python", - } -} + }, + "clangd.arguments": [ + // We might be able to tighten this a bit more to only include the correct toolchain. + "--query-driver=**", + "--compile-commands-dir=${workspaceFolder}/build/latest" + ] +} \ No newline at end of file diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 3c01506a..e36a1fe4 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -16,29 +16,17 @@ "command": "./fbt" }, { - "label": "[Release] Flash (ST-Link)", + "label": "[Release] Flash (SWD)", "group": "build", "type": "shell", "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash" }, { - "label": "[Debug] Flash (ST-Link)", + "label": "[Debug] Flash (SWD)", "group": "build", "type": "shell", "command": "./fbt FORCE=1 flash" }, - { - "label": "[Release] Flash (blackmagic)", - "group": "build", - "type": "shell", - "command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic" - }, - { - "label": "[Debug] Flash (blackmagic)", - "group": "build", - "type": "shell", - "command": "./fbt FORCE=1 flash_blackmagic" - }, { "label": "[Release] Flash (JLink)", "group": "build", diff --git a/SConstruct b/SConstruct index d968254b..44ee7746 100644 --- a/SConstruct +++ b/SConstruct @@ -45,6 +45,7 @@ distenv = coreenv.Clone( ], ENV=os.environ, UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}", + VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"), ) firmware_env = distenv.AddFwProject( @@ -184,27 +185,15 @@ copro_dist = distenv.CoproBuilder( distenv.AlwaysBuild(copro_dist) distenv.Alias("copro_dist", copro_dist) -firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env) + +firmware_flash = distenv.AddFwFlashTarget(firmware_env) distenv.Alias("flash", firmware_flash) +# To be implemented in fwflash.py firmware_jflash = distenv.AddJFlashTarget(firmware_env) distenv.Alias("jflash", firmware_jflash) -firmware_bm_flash = distenv.PhonyTarget( - "flash_blackmagic", - "$GDB $GDBOPTS $SOURCES $GDBFLASH", - source=firmware_env["FW_ELF"], - GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", - GDBREMOTE="${BLACKMAGIC_ADDR}", - GDBFLASH=[ - "-ex", - "load", - "-ex", - "quit", - ], -) - -gdb_backtrace_all_threads = distenv.PhonyTarget( +distenv.PhonyTarget( "gdb_trace_all", "$GDB $GDBOPTS $SOURCES $GDBFLASH", source=firmware_env["FW_ELF"], @@ -348,7 +337,14 @@ distenv.PhonyTarget( ) # Prepare vscode environment -vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*")) +VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"] +vscode_dist = distenv.Install( + "#.vscode", + [ + distenv.Glob("#.vscode/example/*.json"), + distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"), + ], +) distenv.Precious(vscode_dist) distenv.NoClean(vscode_dist) distenv.Alias("vscode_dist", vscode_dist) diff --git a/applications/ReadMe.md b/applications/ReadMe.md index 91ef02bb..de465832 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -33,9 +33,6 @@ Applications for main Flipper menu. - `nfc` - NFC application, HF rfid, EMV and etc - `subghz` - SubGhz application, 433 fobs and etc - `u2f` - U2F Application -- `clock` - Clock application -- `music_player` - Music player app (demo) -- `snake_game` - Snake game application ## services diff --git a/applications/debug/accessor/helpers/wiegand.cpp b/applications/debug/accessor/helpers/wiegand.cpp index 5cb3a85f..10b284ea 100644 --- a/applications/debug/accessor/helpers/wiegand.cpp +++ b/applications/debug/accessor/helpers/wiegand.cpp @@ -174,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() { return false; } - // TODO: Handle validation failure case! + // TODO FL-3490: Handle validation failure case! } else if(4 == _bitCount) { // 4-bit Wiegand codes have no data integrity check so we just // read the LOW nibble. diff --git a/applications/debug/subghz_test/views/subghz_test_packet.c b/applications/debug/subghz_test/views/subghz_test_packet.c index bab83ab5..1f345829 100644 --- a/applications/debug/subghz_test/views/subghz_test_packet.c +++ b/applications/debug/subghz_test/views/subghz_test_packet.c @@ -56,7 +56,6 @@ static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void* subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration); } -//todo static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) { UNUSED(parser); furi_assert(context); diff --git a/applications/debug/unit_tests/application.fam b/applications/debug/unit_tests/application.fam index 949bb3fc..ad9a278f 100644 --- a/applications/debug/unit_tests/application.fam +++ b/applications/debug/unit_tests/application.fam @@ -3,6 +3,7 @@ App( apptype=FlipperAppType.STARTUP, entry_point="unit_tests_on_system_start", cdefines=["APP_UNIT_TESTS"], + requires=["system_settings"], provides=["delay_test"], order=100, ) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c index f7bc234a..05d967a9 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/furi/furi_memmgr_test.c @@ -26,7 +26,7 @@ void test_furi_memmgr() { mu_assert_int_eq(66, ((uint8_t*)ptr)[i]); } - // TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized + // TODO FL-3492: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized free(ptr); // allocate and zero-initialize array (calloc) diff --git a/applications/debug/unit_tests/furi/furi_string_test.c b/applications/debug/unit_tests/furi/furi_string_test.c index 3ea95b92..6cbcc0dc 100644 --- a/applications/debug/unit_tests/furi/furi_string_test.c +++ b/applications/debug/unit_tests/furi/furi_string_test.c @@ -69,7 +69,7 @@ MU_TEST(mu_test_furi_string_mem) { mu_check(string != NULL); mu_check(!furi_string_empty(string)); - // TODO: how to test furi_string_reserve? + // TODO FL-3493: how to test furi_string_reserve? // test furi_string_reset furi_string_reset(string); diff --git a/applications/debug/unit_tests/lfrfid/bit_lib_test.c b/applications/debug/unit_tests/lfrfid/bit_lib_test.c index 72661570..dcb69de7 100644 --- a/applications/debug/unit_tests/lfrfid/bit_lib_test.c +++ b/applications/debug/unit_tests/lfrfid/bit_lib_test.c @@ -311,7 +311,7 @@ MU_TEST(test_bit_lib_test_parity) { } MU_TEST(test_bit_lib_remove_bit_every_nth) { - // TODO: more tests + // TODO FL-3494: more tests uint8_t data_i[1] = {0b00001111}; uint8_t data_o[1] = {0b00011111}; size_t length; diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index 6bdaa641..e32a5748 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -330,7 +330,12 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { return false; } + FuriHalCortexTimer timer = furi_hal_cortex_timer_get(30000000); + while(!furi_hal_subghz_is_async_tx_complete()) { + if(furi_hal_cortex_timer_is_expired(timer)) { + return false; + } furi_delay_ms(10); } furi_hal_subghz_stop_async_tx(); diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index f7a53d7c..edaf950c 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -90,7 +90,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { Loader* loader = furi_record_open(RECORD_LOADER); NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - // TODO: lock device while test running + // TODO FL-3491: lock device while test running if(loader_is_locked(loader)) { printf("RPC: stop all applications to run tests\r\n"); notification_message(notification, &sequence_blink_magenta_100); diff --git a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c index e9560ce5..0a9599d0 100644 --- a/applications/drivers/subghz/cc1101_ext/cc1101_ext.c +++ b/applications/drivers/subghz/cc1101_ext/cc1101_ext.c @@ -333,8 +333,7 @@ bool subghz_device_cc1101_ext_rx_pipe_not_empty() { (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle); - // TODO: you can add a buffer overflow flag if needed - if(status->NUM_RXBYTES > 0) { + if((status->NUM_RXBYTES > 0) || (status->RXFIFO_OVERFLOW == 0)) { return true; } else { return false; diff --git a/applications/main/application.fam b/applications/main/application.fam index e3ceac34..0a90ee22 100644 --- a/applications/main/application.fam +++ b/applications/main/application.fam @@ -11,9 +11,6 @@ App( "subghz", "bad_usb", "u2f", - "clock", - "music_player", - "snake_game", "archive", "main_apps_on_start", ], diff --git a/applications/main/clock/application.fam b/applications/main/clock/application.fam deleted file mode 100644 index a6a2eff3..00000000 --- a/applications/main/clock/application.fam +++ /dev/null @@ -1,10 +0,0 @@ -App( - appid="clock", - name="Clock", - apptype=FlipperAppType.EXTERNAL, - entry_point="clock_app", - requires=["gui"], - stack_size=2 * 1024, - fap_icon="clock.png", - fap_category="Tools", -) diff --git a/applications/main/clock/clock.png b/applications/main/clock/clock.png deleted file mode 100644 index 0d96df10..00000000 Binary files a/applications/main/clock/clock.png and /dev/null differ diff --git a/applications/main/clock/clock_app.c b/applications/main/clock/clock_app.c deleted file mode 100644 index c938125b..00000000 --- a/applications/main/clock/clock_app.c +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include - -#include -#include - -typedef enum { - ClockEventTypeTick, - ClockEventTypeKey, -} ClockEventType; - -typedef struct { - ClockEventType type; - InputEvent input; -} ClockEvent; - -typedef struct { - FuriString* buffer; - FuriHalRtcDateTime datetime; - LocaleTimeFormat timeformat; - LocaleDateFormat dateformat; -} ClockData; - -typedef struct { - FuriMutex* mutex; - FuriMessageQueue* queue; - ClockData* data; -} Clock; - -static void clock_input_callback(InputEvent* input_event, FuriMessageQueue* queue) { - furi_assert(queue); - ClockEvent event = {.type = ClockEventTypeKey, .input = *input_event}; - furi_message_queue_put(queue, &event, FuriWaitForever); -} - -static void clock_render_callback(Canvas* canvas, void* ctx) { - Clock* clock = ctx; - if(furi_mutex_acquire(clock->mutex, 200) != FuriStatusOk) { - return; - } - - ClockData* data = clock->data; - - canvas_set_font(canvas, FontBigNumbers); - locale_format_time(data->buffer, &data->datetime, data->timeformat, true); - canvas_draw_str_aligned( - canvas, 64, 28, AlignCenter, AlignCenter, furi_string_get_cstr(data->buffer)); - - // Special case to cover missing glyphs in FontBigNumbers - if(data->timeformat == LocaleTimeFormat12h) { - size_t time_width = canvas_string_width(canvas, furi_string_get_cstr(data->buffer)); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - 64 + (time_width / 2) - 10, - 31, - AlignLeft, - AlignCenter, - (data->datetime.hour > 11) ? "PM" : "AM"); - } - - canvas_set_font(canvas, FontSecondary); - locale_format_date(data->buffer, &data->datetime, data->dateformat, "/"); - canvas_draw_str_aligned( - canvas, 64, 42, AlignCenter, AlignTop, furi_string_get_cstr(data->buffer)); - - furi_mutex_release(clock->mutex); -} - -static void clock_tick(void* ctx) { - furi_assert(ctx); - FuriMessageQueue* queue = ctx; - ClockEvent event = {.type = ClockEventTypeTick}; - // It's OK to loose this event if system overloaded - furi_message_queue_put(queue, &event, 0); -} - -int32_t clock_app(void* p) { - UNUSED(p); - Clock* clock = malloc(sizeof(Clock)); - clock->data = malloc(sizeof(ClockData)); - clock->data->buffer = furi_string_alloc(); - - clock->queue = furi_message_queue_alloc(8, sizeof(ClockEvent)); - clock->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - furi_hal_rtc_get_datetime(&clock->data->datetime); - clock->data->timeformat = locale_get_time_format(); - clock->data->dateformat = locale_get_date_format(); - - // Set ViewPort callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, clock_render_callback, clock); - view_port_input_callback_set(view_port, clock_input_callback, clock->queue); - - FuriTimer* timer = furi_timer_alloc(clock_tick, FuriTimerTypePeriodic, clock->queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - furi_timer_start(timer, 100); - - // Main loop - ClockEvent event; - for(bool processing = true; processing;) { - furi_check(furi_message_queue_get(clock->queue, &event, FuriWaitForever) == FuriStatusOk); - furi_mutex_acquire(clock->mutex, FuriWaitForever); - if(event.type == ClockEventTypeKey) { - if(event.input.type == InputTypeShort && event.input.key == InputKeyBack) { - processing = false; - } - } else if(event.type == ClockEventTypeTick) { - furi_hal_rtc_get_datetime(&clock->data->datetime); - } - - furi_mutex_release(clock->mutex); - view_port_update(view_port); - } - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - furi_record_close(RECORD_GUI); - - furi_message_queue_free(clock->queue); - furi_mutex_free(clock->mutex); - - furi_string_free(clock->data->buffer); - - free(clock->data); - free(clock); - - return 0; -} diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart.c b/applications/main/gpio/scenes/gpio_scene_usb_uart.c index aa41aaf9..c5e08519 100644 --- a/applications/main/gpio/scenes/gpio_scene_usb_uart.c +++ b/applications/main/gpio/scenes/gpio_scene_usb_uart.c @@ -19,7 +19,7 @@ void gpio_scene_usb_uart_on_enter(void* context) { uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart); if(prev_state == 0) { scene_usb_uart = malloc(sizeof(SceneUsbUartBridge)); - scene_usb_uart->cfg.vcp_ch = 0; // TODO: settings load + scene_usb_uart->cfg.vcp_ch = 0; scene_usb_uart->cfg.uart_ch = 0; scene_usb_uart->cfg.flow_pins = 0; scene_usb_uart->cfg.baudrate_mode = 0; diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index 3fa99cb0..54b5caba 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -85,7 +85,7 @@ static void infrared_cli_print_usage(void) { printf("\tir decode []\r\n"); printf("\tir universal \r\n"); printf("\tir universal list \r\n"); - // TODO: Do not hardcode universal remote names + // TODO FL-3496: Do not hardcode universal remote names printf("\tAvailable universal remotes: tv audio ac projector\r\n"); } @@ -211,7 +211,7 @@ static bool infrared_cli_decode_raw_signal( size_t i; for(i = 0; i < raw_signal->timings_size; ++i) { - // TODO: Any infrared_check_decoder_ready() magic? + // TODO FL-3523: Any infrared_check_decoder_ready() magic? const InfraredMessage* message = infrared_decode(decoder, level, raw_signal->timings[i]); if(message) { diff --git a/applications/main/infrared/scenes/infrared_scene_universal_ac.c b/applications/main/infrared/scenes/infrared_scene_universal_ac.c index 58f06773..cbb09a52 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_ac.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_ac.c @@ -1,6 +1,7 @@ #include "../infrared_i.h" #include "common/infrared_scene_universal_common.h" +#include void infrared_scene_universal_ac_on_enter(void* context) { infrared_scene_universal_common_on_enter(context); @@ -18,24 +19,26 @@ void infrared_scene_universal_ac_on_enter(void* context) { i, 0, 0, - 3, - 22, - &I_Off_25x27, - &I_Off_hvr_25x27, + 6, + 15, + &I_off_19x20, + &I_off_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 10, 37, &I_off_text_12x5); infrared_brute_force_add_record(brute_force, i++, "Off"); button_panel_add_item( button_panel, i, 1, 0, - 36, - 22, - &I_Dehumidify_25x27, - &I_Dehumidify_hvr_25x27, + 39, + 15, + &I_dry_19x20, + &I_dry_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 41, 37, &I_dry_text_15x5); infrared_brute_force_add_record(brute_force, i++, "Dh"); button_panel_add_item( button_panel, @@ -43,9 +46,9 @@ void infrared_scene_universal_ac_on_enter(void* context) { 0, 1, 3, - 59, - &I_CoolHi_25x27, - &I_CoolHi_hvr_25x27, + 49, + &I_max_24x23, + &I_max_hover_24x23, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Cool_hi"); @@ -54,39 +57,71 @@ void infrared_scene_universal_ac_on_enter(void* context) { i, 1, 1, - 36, - 59, - &I_HeatHi_25x27, - &I_HeatHi_hvr_25x27, + 37, + 49, + &I_max_24x23, + &I_max_hover_24x23, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Heat_hi"); - button_panel_add_item( - button_panel, - i, - 0, - 2, - 3, - 91, - &I_CoolLo_25x27, - &I_CoolLo_hvr_25x27, - infrared_scene_universal_common_item_callback, - context); + if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) { + button_panel_add_item( + button_panel, + i, + 0, + 2, + 3, + 100, + &I_celsius_24x23, + &I_celsius_hover_24x23, + infrared_scene_universal_common_item_callback, + context); + } else { + button_panel_add_item( + button_panel, + i, + 0, + 2, + 3, + 100, + &I_fahren_24x23, + &I_fahren_hover_24x23, + infrared_scene_universal_common_item_callback, + context); + } infrared_brute_force_add_record(brute_force, i++, "Cool_lo"); - button_panel_add_item( - button_panel, - i, - 1, - 2, - 36, - 91, - &I_HeatLo_25x27, - &I_HeatLo_hvr_25x27, - infrared_scene_universal_common_item_callback, - context); + + if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) { + button_panel_add_item( + button_panel, + i, + 1, + 2, + 37, + 100, + &I_celsius_24x23, + &I_celsius_hover_24x23, + infrared_scene_universal_common_item_callback, + context); + } else { + button_panel_add_item( + button_panel, + i, + 1, + 2, + 37, + 100, + &I_fahren_24x23, + &I_fahren_hover_24x23, + infrared_scene_universal_common_item_callback, + context); + } infrared_brute_force_add_record(brute_force, i++, "Heat_lo"); - button_panel_add_label(button_panel, 6, 10, FontPrimary, "AC remote"); + button_panel_add_icon(button_panel, 0, 60, &I_cool_30x51); + button_panel_add_icon(button_panel, 34, 60, &I_heat_30x51); + + button_panel_add_label(button_panel, 4, 10, FontPrimary, "AC remote"); view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); diff --git a/applications/main/infrared/scenes/infrared_scene_universal_audio.c b/applications/main/infrared/scenes/infrared_scene_universal_audio.c index 00c86fff..3938b608 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_audio.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_audio.c @@ -18,82 +18,88 @@ void infrared_scene_universal_audio_on_enter(void* context) { i, 0, 0, - 3, - 11, - &I_Power_25x27, - &I_Power_hvr_25x27, + 6, + 13, + &I_power_19x20, + &I_power_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 4, 35, &I_power_text_24x5); infrared_brute_force_add_record(brute_force, i++, "Power"); button_panel_add_item( button_panel, i, 1, 0, - 36, - 11, - &I_Mute_25x27, - &I_Mute_hvr_25x27, + 39, + 13, + &I_mute_19x20, + &I_mute_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 39, 35, &I_mute_text_19x5); infrared_brute_force_add_record(brute_force, i++, "Mute"); button_panel_add_item( button_panel, i, 0, 1, - 3, - 41, - &I_Play_25x27, - &I_Play_hvr_25x27, + 6, + 42, + &I_play_19x20, + &I_play_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 6, 64, &I_play_text_19x5); infrared_brute_force_add_record(brute_force, i++, "Play"); button_panel_add_item( button_panel, i, - 1, - 1, - 36, - 41, - &I_Pause_25x27, - &I_Pause_hvr_25x27, + 0, + 2, + 6, + 71, + &I_pause_19x20, + &I_pause_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 4, 93, &I_pause_text_23x5); infrared_brute_force_add_record(brute_force, i++, "Pause"); button_panel_add_item( button_panel, i, 0, - 2, 3, - 71, - &I_TrackPrev_25x27, - &I_TrackPrev_hvr_25x27, + 6, + 101, + &I_prev_19x20, + &I_prev_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 6, 123, &I_prev_text_19x5); infrared_brute_force_add_record(brute_force, i++, "Prev"); button_panel_add_item( button_panel, i, 1, - 2, - 36, - 71, - &I_TrackNext_25x27, - &I_TrackNext_hvr_25x27, + 3, + 39, + 101, + &I_next_19x20, + &I_next_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 39, 123, &I_next_text_19x6); infrared_brute_force_add_record(brute_force, i++, "Next"); button_panel_add_item( button_panel, i, - 0, - 3, - 3, - 101, - &I_Vol_down_25x27, - &I_Vol_down_hvr_25x27, + 1, + 2, + 37, + 77, + &I_voldown_24x21, + &I_voldown_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Vol_dn"); @@ -101,16 +107,17 @@ void infrared_scene_universal_audio_on_enter(void* context) { button_panel, i, 1, - 3, - 36, - 101, - &I_Vol_up_25x27, - &I_Vol_up_hvr_25x27, + 1, + 37, + 43, + &I_volup_24x21, + &I_volup_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Vol_up"); - button_panel_add_label(button_panel, 1, 8, FontPrimary, "Mus. remote"); + button_panel_add_label(button_panel, 1, 10, FontPrimary, "Mus. remote"); + button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30); view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); diff --git a/applications/main/infrared/scenes/infrared_scene_universal_projector.c b/applications/main/infrared/scenes/infrared_scene_universal_projector.c index c1df91c3..27ca46ea 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_projector.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_projector.c @@ -11,59 +11,62 @@ void infrared_scene_universal_projector_on_enter(void* context) { infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/projector.ir")); - button_panel_reserve(button_panel, 2, 2); + button_panel_reserve(button_panel, 2, 3); uint32_t i = 0; button_panel_add_item( button_panel, i, 0, 0, - 3, - 19, - &I_Power_25x27, - &I_Power_hvr_25x27, + 6, + 23, + &I_power_19x20, + &I_power_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 4, 45, &I_power_text_24x5); infrared_brute_force_add_record(brute_force, i++, "Power"); button_panel_add_item( button_panel, i, 1, 0, - 36, - 19, - &I_Mute_25x27, - &I_Mute_hvr_25x27, + 39, + 23, + &I_mute_19x20, + &I_mute_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 39, 45, &I_mute_text_19x5); infrared_brute_force_add_record(brute_force, i++, "Mute"); button_panel_add_item( button_panel, i, 0, 1, - 3, - 66, - &I_Vol_up_25x27, - &I_Vol_up_hvr_25x27, + 20, + 59, + &I_volup_24x21, + &I_volup_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Vol_up"); + button_panel_add_item( button_panel, i, - 1, - 1, - 36, - 66, - &I_Vol_down_25x27, - &I_Vol_down_hvr_25x27, + 0, + 2, + 20, + 93, + &I_voldown_24x21, + &I_voldown_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Vol_dn"); - button_panel_add_label(button_panel, 2, 11, FontPrimary, "Proj. remote"); - button_panel_add_label(button_panel, 17, 62, FontSecondary, "Volume"); + button_panel_add_label(button_panel, 3, 11, FontPrimary, "Proj. remote"); + button_panel_add_icon(button_panel, 17, 72, &I_vol_ac_text_30x30); view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); diff --git a/applications/main/infrared/scenes/infrared_scene_universal_tv.c b/applications/main/infrared/scenes/infrared_scene_universal_tv.c index e21bf8f9..f2958d88 100644 --- a/applications/main/infrared/scenes/infrared_scene_universal_tv.c +++ b/applications/main/infrared/scenes/infrared_scene_universal_tv.c @@ -18,77 +18,82 @@ void infrared_scene_universal_tv_on_enter(void* context) { i, 0, 0, - 3, - 19, - &I_Power_25x27, - &I_Power_hvr_25x27, + 6, + 16, + &I_power_19x20, + &I_power_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 4, 38, &I_power_text_24x5); infrared_brute_force_add_record(brute_force, i++, "Power"); button_panel_add_item( button_panel, i, 1, 0, - 36, - 19, - &I_Mute_25x27, - &I_Mute_hvr_25x27, + 39, + 16, + &I_mute_19x20, + &I_mute_hover_19x20, infrared_scene_universal_common_item_callback, context); + button_panel_add_icon(button_panel, 39, 38, &I_mute_text_19x5); + + button_panel_add_icon(button_panel, 0, 66, &I_ch_text_31x34); + button_panel_add_icon(button_panel, 35, 66, &I_vol_tv_text_29x34); + infrared_brute_force_add_record(brute_force, i++, "Mute"); + button_panel_add_item( + button_panel, + i, + 1, + 1, + 38, + 53, + &I_volup_24x21, + &I_volup_hover_24x21, + infrared_scene_universal_common_item_callback, + context); + + infrared_brute_force_add_record(brute_force, i++, "Vol_up"); button_panel_add_item( button_panel, i, 0, 1, 3, - 66, - &I_Vol_up_25x27, - &I_Vol_up_hvr_25x27, - infrared_scene_universal_common_item_callback, - context); - infrared_brute_force_add_record(brute_force, i++, "Vol_up"); - button_panel_add_item( - button_panel, - i, - 1, - 1, - 36, - 66, - &I_Up_25x27, - &I_Up_hvr_25x27, + 53, + &I_ch_up_24x21, + &I_ch_up_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Ch_next"); button_panel_add_item( button_panel, i, - 0, + 1, 2, - 3, - 98, - &I_Vol_down_25x27, - &I_Vol_down_hvr_25x27, + 38, + 91, + &I_voldown_24x21, + &I_voldown_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Vol_dn"); button_panel_add_item( button_panel, i, - 1, + 0, 2, - 36, - 98, - &I_Down_25x27, - &I_Down_hvr_25x27, + 3, + 91, + &I_ch_down_24x21, + &I_ch_down_hover_24x21, infrared_scene_universal_common_item_callback, context); infrared_brute_force_add_record(brute_force, i++, "Ch_prev"); - button_panel_add_label(button_panel, 6, 11, FontPrimary, "TV remote"); - button_panel_add_label(button_panel, 9, 64, FontSecondary, "Vol"); - button_panel_add_label(button_panel, 43, 64, FontSecondary, "Ch"); + button_panel_add_label(button_panel, 5, 10, FontPrimary, "TV remote"); view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index edde2380..aa7510a9 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -186,13 +186,15 @@ int32_t lfrfid_app(void* p) { dolphin_deed(DolphinDeedRfidEmulate); } else { furi_string_set(app->file_path, args); - lfrfid_load_key_data(app, app->file_path, true); - view_dispatcher_attach_to_gui( - app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); - dolphin_deed(DolphinDeedRfidEmulate); + if(lfrfid_load_key_data(app, app->file_path, true)) { + view_dispatcher_attach_to_gui( + app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate); + dolphin_deed(DolphinDeedRfidEmulate); + } else { + view_dispatcher_stop(app->view_dispatcher); + } } - } else { view_dispatcher_attach_to_gui( app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); diff --git a/applications/main/music_player/application.fam b/applications/main/music_player/application.fam deleted file mode 100644 index c9cd5e44..00000000 --- a/applications/main/music_player/application.fam +++ /dev/null @@ -1,16 +0,0 @@ -App( - appid="music_player", - name="Music Player", - apptype=FlipperAppType.EXTERNAL, - entry_point="music_player_app", - requires=[ - "gui", - "dialogs", - ], - stack_size=2 * 1024, - order=20, - fap_icon="icons/music_10px.png", - fap_category="Media", - fap_icon_assets="icons", - fap_libs=["music_worker"], -) diff --git a/applications/main/music_player/icons/music_10px.png b/applications/main/music_player/icons/music_10px.png deleted file mode 100644 index d41eb0db..00000000 Binary files a/applications/main/music_player/icons/music_10px.png and /dev/null differ diff --git a/applications/main/music_player/music_player.c b/applications/main/music_player/music_player.c deleted file mode 100644 index 8b0b758c..00000000 --- a/applications/main/music_player/music_player.c +++ /dev/null @@ -1,372 +0,0 @@ -#include - -#include -#include - -#include -#include -#include -#include - -#define TAG "MusicPlayer" - -#define MUSIC_PLAYER_APP_EXTENSION "*" - -#define MUSIC_PLAYER_SEMITONE_HISTORY_SIZE 4 - -typedef struct { - uint8_t semitone_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - uint8_t duration_history[MUSIC_PLAYER_SEMITONE_HISTORY_SIZE]; - - uint8_t volume; - uint8_t semitone; - uint8_t dots; - uint8_t duration; - float position; -} MusicPlayerModel; - -typedef struct { - MusicPlayerModel* model; - FuriMutex** model_mutex; - - FuriMessageQueue* input_queue; - - ViewPort* view_port; - Gui* gui; - - MusicWorker* worker; -} MusicPlayer; - -static const float MUSIC_PLAYER_VOLUMES[] = {0, .25, .5, .75, 1}; - -static const char* semitone_to_note(int8_t semitone) { - switch(semitone) { - case 0: - return "C"; - case 1: - return "C#"; - case 2: - return "D"; - case 3: - return "D#"; - case 4: - return "E"; - case 5: - return "F"; - case 6: - return "F#"; - case 7: - return "G"; - case 8: - return "G#"; - case 9: - return "A"; - case 10: - return "A#"; - case 11: - return "B"; - default: - return "--"; - } -} - -static bool is_white_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 0: - if(id == 0) return true; - break; - case 2: - if(id == 1) return true; - break; - case 4: - if(id == 2) return true; - break; - case 5: - if(id == 3) return true; - break; - case 7: - if(id == 4) return true; - break; - case 9: - if(id == 5) return true; - break; - case 11: - if(id == 6) return true; - break; - default: - break; - } - - return false; -} - -static bool is_black_note(uint8_t semitone, uint8_t id) { - switch(semitone) { - case 1: - if(id == 0) return true; - break; - case 3: - if(id == 1) return true; - break; - case 6: - if(id == 3) return true; - break; - case 8: - if(id == 4) return true; - break; - case 10: - if(id == 5) return true; - break; - default: - break; - } - - return false; -} - -static void render_callback(Canvas* canvas, void* ctx) { - MusicPlayer* music_player = ctx; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 0, 12, "MusicPlayer"); - - uint8_t x_pos = 0; - uint8_t y_pos = 24; - const uint8_t white_w = 10; - const uint8_t white_h = 40; - - const int8_t black_x = 6; - const int8_t black_y = -5; - const uint8_t black_w = 8; - const uint8_t black_h = 32; - - // white keys - for(size_t i = 0; i < 7; i++) { - if(is_white_note(music_player->model->semitone, i)) { - canvas_draw_box(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } else { - canvas_draw_frame(canvas, x_pos + white_w * i, y_pos, white_w + 1, white_h); - } - } - - // black keys - for(size_t i = 0; i < 7; i++) { - if(i != 2 && i != 6) { - canvas_set_color(canvas, ColorWhite); - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - canvas_set_color(canvas, ColorBlack); - if(is_black_note(music_player->model->semitone, i)) { - canvas_draw_box( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } else { - canvas_draw_frame( - canvas, x_pos + white_w * i + black_x, y_pos + black_y, black_w + 1, black_h); - } - } - } - - // volume view_port - x_pos = 124; - y_pos = 0; - const uint8_t volume_h = - (64 / (COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1)) * music_player->model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume_h), 4, volume_h); - - // note stack view_port - x_pos = 73; - y_pos = 0; //-V1048 - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - canvas_draw_frame(canvas, x_pos, y_pos, 49, 64); - canvas_draw_line(canvas, x_pos + 28, 0, x_pos + 28, 64); - - char duration_text[16]; - for(uint8_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE; i++) { - if(music_player->model->duration_history[i] == 0xFF) { - snprintf(duration_text, 15, "--"); - } else { - snprintf(duration_text, 15, "%d", music_player->model->duration_history[i]); - } - - if(i == 0) { - canvas_draw_box(canvas, x_pos, y_pos + 48, 49, 16); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_str( - canvas, - x_pos + 4, - 64 - 16 * i - 3, - semitone_to_note(music_player->model->semitone_history[i])); - canvas_draw_str(canvas, x_pos + 31, 64 - 16 * i - 3, duration_text); - canvas_draw_line(canvas, x_pos, 64 - 16 * i, x_pos + 48, 64 - 16 * i); - } - - furi_mutex_release(music_player->model_mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - MusicPlayer* music_player = ctx; - if(input_event->type == InputTypeShort) { - furi_message_queue_put(music_player->input_queue, input_event, 0); - } -} - -static void music_worker_callback( - uint8_t semitone, - uint8_t dots, - uint8_t duration, - float position, - void* context) { - MusicPlayer* music_player = context; - furi_check(furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - for(size_t i = 0; i < MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1; i++) { - size_t r = MUSIC_PLAYER_SEMITONE_HISTORY_SIZE - 1 - i; - music_player->model->duration_history[r] = music_player->model->duration_history[r - 1]; - music_player->model->semitone_history[r] = music_player->model->semitone_history[r - 1]; - } - - semitone = (semitone == 0xFF) ? 0xFF : semitone % 12; - - music_player->model->semitone = semitone; - music_player->model->dots = dots; - music_player->model->duration = duration; - music_player->model->position = position; - - music_player->model->semitone_history[0] = semitone; - music_player->model->duration_history[0] = duration; - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); -} - -void music_player_clear(MusicPlayer* instance) { - memset(instance->model->duration_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - memset(instance->model->semitone_history, 0xff, MUSIC_PLAYER_SEMITONE_HISTORY_SIZE); - music_worker_clear(instance->worker); -} - -MusicPlayer* music_player_alloc() { - MusicPlayer* instance = malloc(sizeof(MusicPlayer)); - - instance->model = malloc(sizeof(MusicPlayerModel)); - instance->model->volume = 3; - - instance->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - - instance->worker = music_worker_alloc(); - music_worker_set_volume(instance->worker, MUSIC_PLAYER_VOLUMES[instance->model->volume]); - music_worker_set_callback(instance->worker, music_worker_callback, instance); - - music_player_clear(instance); - - instance->view_port = view_port_alloc(); - view_port_draw_callback_set(instance->view_port, render_callback, instance); - view_port_input_callback_set(instance->view_port, input_callback, instance); - - // Open GUI and register view_port - instance->gui = furi_record_open(RECORD_GUI); - gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); - - return instance; -} - -void music_player_free(MusicPlayer* instance) { - gui_remove_view_port(instance->gui, instance->view_port); - furi_record_close(RECORD_GUI); - view_port_free(instance->view_port); - - music_worker_free(instance->worker); - - furi_message_queue_free(instance->input_queue); - - furi_mutex_free(instance->model_mutex); - - free(instance->model); - free(instance); -} - -int32_t music_player_app(void* p) { - MusicPlayer* music_player = music_player_alloc(); - - FuriString* file_path; - file_path = furi_string_alloc(); - - do { - if(p && strlen(p)) { - furi_string_set(file_path, (const char*)p); - } else { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_migrate( - storage, EXT_PATH("music_player"), STORAGE_APP_DATA_PATH_PREFIX); - furi_record_close(RECORD_STORAGE); - - furi_string_set(file_path, STORAGE_APP_DATA_PATH_PREFIX); - - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options( - &browser_options, MUSIC_PLAYER_APP_EXTENSION, &I_music_10px); - browser_options.hide_ext = false; - browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; - - DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); - bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options); - - furi_record_close(RECORD_DIALOGS); - - if(!res) { - FURI_LOG_E(TAG, "No file selected"); - break; - } - } - - if(!music_worker_load(music_player->worker, furi_string_get_cstr(file_path))) { - FURI_LOG_E(TAG, "Unable to load file"); - break; - } - - music_worker_start(music_player->worker); - - InputEvent input; - while(furi_message_queue_get(music_player->input_queue, &input, FuriWaitForever) == - FuriStatusOk) { - furi_check( - furi_mutex_acquire(music_player->model_mutex, FuriWaitForever) == FuriStatusOk); - - if(input.key == InputKeyBack) { - furi_mutex_release(music_player->model_mutex); - break; - } else if(input.key == InputKeyUp) { - if(music_player->model->volume < COUNT_OF(MUSIC_PLAYER_VOLUMES) - 1) - music_player->model->volume++; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } else if(input.key == InputKeyDown) { - if(music_player->model->volume > 0) music_player->model->volume--; - music_worker_set_volume( - music_player->worker, MUSIC_PLAYER_VOLUMES[music_player->model->volume]); - } - - furi_mutex_release(music_player->model_mutex); - view_port_update(music_player->view_port); - } - - music_worker_stop(music_player->worker); - if(p && strlen(p)) break; // Exit instead of going to browser if launched with arg - music_player_clear(music_player); - } while(1); - - furi_string_free(file_path); - music_player_free(music_player); - - return 0; -} diff --git a/applications/main/nfc/scenes/nfc_scene_file_select.c b/applications/main/nfc/scenes/nfc_scene_file_select.c index 374a933d..ce7ec92f 100644 --- a/applications/main/nfc/scenes/nfc_scene_file_select.c +++ b/applications/main/nfc/scenes/nfc_scene_file_select.c @@ -3,6 +3,8 @@ void nfc_scene_file_select_on_enter(void* context) { Nfc* nfc = context; + nfc_device_data_clear(&nfc->dev->dev_data); + // Process file_select return nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); if(!furi_string_size(nfc->dev->load_path)) { diff --git a/applications/main/snake_game/application.fam b/applications/main/snake_game/application.fam deleted file mode 100644 index c736a4dd..00000000 --- a/applications/main/snake_game/application.fam +++ /dev/null @@ -1,11 +0,0 @@ -App( - appid="snake_game", - name="Snake Game", - apptype=FlipperAppType.EXTERNAL, - entry_point="snake_game_app", - requires=["gui"], - stack_size=1 * 1024, - order=30, - fap_icon="snake_10px.png", - fap_category="Games", -) diff --git a/applications/main/snake_game/snake_10px.png b/applications/main/snake_game/snake_10px.png deleted file mode 100644 index 52d9fa7e..00000000 Binary files a/applications/main/snake_game/snake_10px.png and /dev/null differ diff --git a/applications/main/snake_game/snake_game.c b/applications/main/snake_game/snake_game.c deleted file mode 100644 index 6852cb21..00000000 --- a/applications/main/snake_game/snake_game.c +++ /dev/null @@ -1,434 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - // +-----x - // | - // | - // y - uint8_t x; - uint8_t y; -} Point; - -typedef enum { - GameStateLife, - - // https://melmagazine.com/en-us/story/snake-nokia-6110-oral-history-taneli-armanto - // Armanto: While testing the early versions of the game, I noticed it was hard - // to control the snake upon getting close to and edge but not crashing — especially - // in the highest speed levels. I wanted the highest level to be as fast as I could - // possibly make the device "run," but on the other hand, I wanted to be friendly - // and help the player manage that level. Otherwise it might not be fun to play. So - // I implemented a little delay. A few milliseconds of extra time right before - // the player crashes, during which she can still change the directions. And if - // she does, the game continues. - GameStateLastChance, - - GameStateGameOver, -} GameState; - -// Note: do not change without purpose. Current values are used in smart -// orthogonality calculation in `snake_game_get_turn_snake`. -typedef enum { - DirectionUp, - DirectionRight, - DirectionDown, - DirectionLeft, -} Direction; - -#define MAX_SNAKE_LEN 253 - -typedef struct { - Point points[MAX_SNAKE_LEN]; - uint16_t len; - Direction currentMovement; - Direction nextMovement; // if backward of currentMovement, ignore - Point fruit; - GameState state; - FuriMutex* mutex; -} SnakeState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} SnakeEvent; - -const NotificationSequence sequence_fail = { - &message_vibro_on, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_note_ds4, - &message_delay_10, - &message_sound_off, - &message_delay_10, - - &message_vibro_off, - NULL, -}; - -const NotificationSequence sequence_eat = { - &message_note_c7, - &message_delay_50, - &message_sound_off, - NULL, -}; - -static void snake_game_render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const SnakeState* snake_state = ctx; - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - // Frame - canvas_draw_frame(canvas, 0, 0, 128, 64); - - // Fruit - Point f = snake_state->fruit; - f.x = f.x * 4 + 1; - f.y = f.y * 4 + 1; - canvas_draw_rframe(canvas, f.x, f.y, 6, 6, 2); - - // Snake - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - p.x = p.x * 4 + 2; - p.y = p.y * 4 + 2; - canvas_draw_box(canvas, p.x, p.y, 4, 4); - } - - // Game Over banner - if(snake_state->state == GameStateGameOver) { - // Screen is 128x64 px - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 34, 20, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 34, 20, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 37, 31, "Game Over"); - - canvas_set_font(canvas, FontSecondary); - char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7U); - canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); - } - - furi_mutex_release(snake_state->mutex); -} - -static void snake_game_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void snake_game_update_timer_callback(FuriMessageQueue* event_queue) { - furi_assert(event_queue); - - SnakeEvent event = {.type = EventTypeTick}; - furi_message_queue_put(event_queue, &event, 0); -} - -static void snake_game_init_game(SnakeState* const snake_state) { - Point p[] = {{8, 6}, {7, 6}, {6, 6}, {5, 6}, {4, 6}, {3, 6}, {2, 6}}; - memcpy(snake_state->points, p, sizeof(p)); //-V1086 - - snake_state->len = 7; - - snake_state->currentMovement = DirectionRight; - - snake_state->nextMovement = DirectionRight; - - Point f = {18, 6}; - snake_state->fruit = f; - - snake_state->state = GameStateLife; -} - -static Point snake_game_get_new_fruit(SnakeState const* const snake_state) { - // 1 bit for each point on the playing field where the snake can turn - // and where the fruit can appear - uint16_t buffer[8]; - memset(buffer, 0, sizeof(buffer)); - uint8_t empty = 8 * 16; - - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - - if(p.x % 2 != 0 || p.y % 2 != 0) { - continue; - } - p.x /= 2; - p.y /= 2; - - buffer[p.y] |= 1 << p.x; - empty--; - } - // Bit set if snake use that playing field - - uint16_t newFruit = rand() % empty; - - // Skip random number of _empty_ fields - for(uint8_t y = 0; y < 8; y++) { - for(uint16_t x = 0, mask = 1; x < 16; x += 1, mask <<= 1) { - if((buffer[y] & mask) == 0) { - if(newFruit == 0) { - Point p = { - .x = x * 2, - .y = y * 2, - }; - return p; - } - newFruit--; - } - } - } - // We will never be here - Point p = {0, 0}; - return p; -} - -static bool snake_game_collision_with_frame(Point const next_step) { - // if x == 0 && currentMovement == left then x - 1 == 255 , - // so check only x > right border - return next_step.x > 30 || next_step.y > 14; -} - -static bool - snake_game_collision_with_tail(SnakeState const* const snake_state, Point const next_step) { - for(uint16_t i = 0; i < snake_state->len; i++) { - Point p = snake_state->points[i]; - if(p.x == next_step.x && p.y == next_step.y) { - return true; - } - } - - return false; -} - -static Direction snake_game_get_turn_snake(SnakeState const* const snake_state) { - // Sum of two `Direction` lies between 0 and 6, odd values indicate orthogonality. - bool is_orthogonal = (snake_state->currentMovement + snake_state->nextMovement) % 2 == 1; - return is_orthogonal ? snake_state->nextMovement : snake_state->currentMovement; -} - -static Point snake_game_get_next_step(SnakeState const* const snake_state) { - Point next_step = snake_state->points[0]; - switch(snake_state->currentMovement) { - // +-----x - // | - // | - // y - case DirectionUp: - next_step.y--; - break; - case DirectionRight: - next_step.x++; - break; - case DirectionDown: - next_step.y++; - break; - case DirectionLeft: - next_step.x--; - break; - } - return next_step; -} - -static void snake_game_move_snake(SnakeState* const snake_state, Point const next_step) { - memmove(snake_state->points + 1, snake_state->points, snake_state->len * sizeof(Point)); - snake_state->points[0] = next_step; -} - -static void - snake_game_process_game_step(SnakeState* const snake_state, NotificationApp* notification) { - if(snake_state->state == GameStateGameOver) { - return; - } - - bool can_turn = (snake_state->points[0].x % 2 == 0) && (snake_state->points[0].y % 2 == 0); - if(can_turn) { - snake_state->currentMovement = snake_game_get_turn_snake(snake_state); - } - - Point next_step = snake_game_get_next_step(snake_state); - - bool crush = snake_game_collision_with_frame(next_step); - if(crush) { - if(snake_state->state == GameStateLife) { - snake_state->state = GameStateLastChance; - return; - } else if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } else { - if(snake_state->state == GameStateLastChance) { - snake_state->state = GameStateLife; - } - } - - crush = snake_game_collision_with_tail(snake_state, next_step); - if(crush) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - - bool eatFruit = (next_step.x == snake_state->fruit.x) && (next_step.y == snake_state->fruit.y); - if(eatFruit) { - snake_state->len++; - if(snake_state->len >= MAX_SNAKE_LEN) { - snake_state->state = GameStateGameOver; - notification_message_block(notification, &sequence_fail); - return; - } - } - - snake_game_move_snake(snake_state, next_step); - - if(eatFruit) { - snake_state->fruit = snake_game_get_new_fruit(snake_state); - notification_message(notification, &sequence_eat); - } -} - -int32_t snake_game_app(void* p) { - UNUSED(p); - - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SnakeEvent)); - - SnakeState* snake_state = malloc(sizeof(SnakeState)); - snake_game_init_game(snake_state); - - snake_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - - if(!snake_state->mutex) { - FURI_LOG_E("SnakeGame", "cannot create mutex\r\n"); - free(snake_state); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, snake_game_render_callback, snake_state); - view_port_input_callback_set(view_port, snake_game_input_callback, event_queue); - - FuriTimer* timer = - furi_timer_alloc(snake_game_update_timer_callback, FuriTimerTypePeriodic, event_queue); - furi_timer_start(timer, furi_kernel_get_tick_frequency() / 4); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - - notification_message_block(notification, &sequence_display_backlight_enforce_on); - - dolphin_deed(DolphinDeedPluginGameStart); - - SnakeEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - - furi_mutex_acquire(snake_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress) { - switch(event.input.key) { - case InputKeyUp: - snake_state->nextMovement = DirectionUp; - break; - case InputKeyDown: - snake_state->nextMovement = DirectionDown; - break; - case InputKeyRight: - snake_state->nextMovement = DirectionRight; - break; - case InputKeyLeft: - snake_state->nextMovement = DirectionLeft; - break; - case InputKeyOk: - if(snake_state->state == GameStateGameOver) { - snake_game_init_game(snake_state); - } - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } else if(event.type == EventTypeTick) { - snake_game_process_game_step(snake_state, notification); - } - } else { - // event timeout - } - - view_port_update(view_port); - furi_mutex_release(snake_state->mutex); - } - - // Return backlight to normal state - notification_message(notification, &sequence_display_backlight_enforce_auto); - - furi_timer_free(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close(RECORD_GUI); - furi_record_close(RECORD_NOTIFICATION); - view_port_free(view_port); - furi_message_queue_free(event_queue); - furi_mutex_free(snake_state->mutex); - free(snake_state); - - return 0; -} - -// Screen is 128x64 px -// (4 + 4) * 16 - 4 + 2 + 2border == 128 -// (4 + 4) * 8 - 4 + 2 + 2border == 64 -// Game field from point{x: 0, y: 0} to point{x: 30, y: 14}. -// The snake turns only in even cells - intersections. -// ┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// ╎ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪ ╎ -// └╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┘ diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c index cbd47f5e..747ed732 100644 --- a/applications/main/subghz/helpers/subghz_txrx.c +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -334,7 +334,6 @@ static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { } subghz_txrx_idle(instance); subghz_txrx_speaker_off(instance); - //Todo: Show message } FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c index 06a855c2..0413173e 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c @@ -13,7 +13,7 @@ #define TAG "SubGhzCreateProtocolKey" -bool subghz_txrx_gen_data_protocol( +SubGhzProtocolStatus subghz_txrx_gen_data_protocol( void* context, const char* preset_name, uint32_t frequency, @@ -23,30 +23,29 @@ bool subghz_txrx_gen_data_protocol( furi_assert(context); SubGhzTxRx* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusOk; subghz_txrx_set_preset(instance, preset_name, frequency, NULL, 0); instance->decoder_result = subghz_receiver_search_decoder_base_by_name(instance->receiver, protocol_name); if(instance->decoder_result == NULL) { - //TODO: Error - // furi_string_set(error_str, "Protocol not\nfound!"); - // scene_manager_next_scene(scene_manager, SubGhzSceneShowErrorSub); FURI_LOG_E(TAG, "Protocol not found!"); - return false; + ret = SubGhzProtocolStatusErrorProtocolNotFound; + return ret; } do { Stream* fff_data_stream = flipper_format_get_raw_stream(instance->fff_data); stream_clean(fff_data_stream); - if(subghz_protocol_decoder_base_serialize( - instance->decoder_result, instance->fff_data, instance->preset) != - SubGhzProtocolStatusOk) { + ret = subghz_protocol_decoder_base_serialize( + instance->decoder_result, instance->fff_data, instance->preset); + if(ret != SubGhzProtocolStatusOk) { FURI_LOG_E(TAG, "Unable to serialize"); break; } if(!flipper_format_update_uint32(instance->fff_data, "Bit", &bit, 1)) { + ret = SubGhzProtocolStatusErrorParserOthers; FURI_LOG_E(TAG, "Unable to update Bit"); break; } @@ -56,15 +55,15 @@ bool subghz_txrx_gen_data_protocol( key_data[sizeof(uint64_t) - i - 1] = (key >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex(instance->fff_data, "Key", key_data, sizeof(uint64_t))) { + ret = SubGhzProtocolStatusErrorParserOthers; FURI_LOG_E(TAG, "Unable to update Key"); break; } - res = true; } while(false); - return res; + return ret; } -bool subghz_txrx_gen_data_protocol_and_te( +SubGhzProtocolStatus subghz_txrx_gen_data_protocol_and_te( SubGhzTxRx* instance, const char* preset_name, uint32_t frequency, @@ -73,18 +72,18 @@ bool subghz_txrx_gen_data_protocol_and_te( uint32_t bit, uint32_t te) { furi_assert(instance); - bool ret = false; - if(subghz_txrx_gen_data_protocol(instance, preset_name, frequency, protocol_name, key, bit)) { + SubGhzProtocolStatus ret = + subghz_txrx_gen_data_protocol(instance, preset_name, frequency, protocol_name, key, bit); + if(ret == SubGhzProtocolStatusOk) { if(!flipper_format_update_uint32(instance->fff_data, "TE", (uint32_t*)&te, 1)) { + ret = SubGhzProtocolStatusErrorParserOthers; FURI_LOG_E(TAG, "Unable to update Te"); - } else { - ret = true; } } return ret; } -bool subghz_txrx_gen_keeloq_protocol( +SubGhzProtocolStatus subghz_txrx_gen_keeloq_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency, @@ -94,7 +93,7 @@ bool subghz_txrx_gen_keeloq_protocol( uint16_t cnt) { furi_assert(instance); - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; serial &= 0x0FFFFFFF; instance->transmitter = subghz_transmitter_alloc_init(instance->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); @@ -108,13 +107,13 @@ bool subghz_txrx_gen_keeloq_protocol( cnt, name_sysmem, instance->preset); - ret = true; + ret = SubGhzProtocolStatusOk; } subghz_transmitter_free(instance->transmitter); return ret; } -bool subghz_txrx_gen_secplus_v2_protocol( +SubGhzProtocolStatus subghz_txrx_gen_secplus_v2_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency, @@ -123,10 +122,11 @@ bool subghz_txrx_gen_secplus_v2_protocol( uint32_t cnt) { furi_assert(instance); - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; instance->transmitter = subghz_transmitter_alloc_init(instance->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); subghz_txrx_set_preset(instance, name_preset, frequency, NULL, 0); + if(instance->transmitter) { subghz_protocol_secplus_v2_create_data( subghz_transmitter_get_protocol_instance(instance->transmitter), @@ -135,30 +135,27 @@ bool subghz_txrx_gen_secplus_v2_protocol( btn, cnt, instance->preset); - ret = true; + ret = SubGhzProtocolStatusOk; } return ret; } -bool subghz_txrx_gen_secplus_v1_protocol( +SubGhzProtocolStatus subghz_txrx_gen_secplus_v1_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency) { furi_assert(instance); - bool ret = false; uint32_t serial = (uint32_t)rand(); while(!subghz_protocol_secplus_v1_check_fixed(serial)) { serial = (uint32_t)rand(); } - if(subghz_txrx_gen_data_protocol( - instance, - name_preset, - frequency, - SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, - (uint64_t)serial << 32 | 0xE6000000, - 42)) { - ret = true; - } - return ret; -} \ No newline at end of file + + return subghz_txrx_gen_data_protocol( + instance, + name_preset, + frequency, + SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, + (uint64_t)serial << 32 | 0xE6000000, + 42); +} diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h index 514a5733..edc6e541 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h @@ -11,9 +11,9 @@ * @param protocol_name Name of protocol * @param key Key * @param bit Bit - * @return bool True if success + * @return SubGhzProtocolStatus */ -bool subghz_txrx_gen_data_protocol( +SubGhzProtocolStatus subghz_txrx_gen_data_protocol( void* context, const char* preset_name, uint32_t frequency, @@ -31,9 +31,9 @@ bool subghz_txrx_gen_data_protocol( * @param key Key * @param bit Bit * @param te Te - * @return bool True if success + * @return SubGhzProtocolStatus */ -bool subghz_txrx_gen_data_protocol_and_te( +SubGhzProtocolStatus subghz_txrx_gen_data_protocol_and_te( SubGhzTxRx* instance, const char* preset_name, uint32_t frequency, @@ -52,9 +52,9 @@ bool subghz_txrx_gen_data_protocol_and_te( * @param serial Serial number * @param btn Button * @param cnt Counter - * @return bool True if success + * @return SubGhzProtocolStatus */ -bool subghz_txrx_gen_keeloq_protocol( +SubGhzProtocolStatus subghz_txrx_gen_keeloq_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency, @@ -72,9 +72,9 @@ bool subghz_txrx_gen_keeloq_protocol( * @param serial Serial number * @param btn Button * @param cnt Counter - * @return bool True if success + * @return SubGhzProtocolStatus */ -bool subghz_txrx_gen_secplus_v2_protocol( +SubGhzProtocolStatus subghz_txrx_gen_secplus_v2_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency, @@ -88,9 +88,9 @@ bool subghz_txrx_gen_secplus_v2_protocol( * @param instance Pointer to a SubGhzTxRx * @param name_preset Name of preset * @param frequency Frequency in Hz - * @return bool True if success + * @return SubGhzProtocolStatus */ -bool subghz_txrx_gen_secplus_v1_protocol( +SubGhzProtocolStatus subghz_txrx_gen_secplus_v1_protocol( SubGhzTxRx* instance, const char* name_preset, uint32_t frequency); \ No newline at end of file diff --git a/applications/main/subghz/scenes/subghz_scene_radio_setting.c b/applications/main/subghz/scenes/subghz_scene_radio_setting.c index 0a47d5bf..1f8e4d83 100644 --- a/applications/main/subghz/scenes/subghz_scene_radio_setting.c +++ b/applications/main/subghz/scenes/subghz_scene_radio_setting.c @@ -1,6 +1,7 @@ #include "../subghz_i.h" #include #include +#include enum SubGhzRadioSettingIndex { SubGhzRadioSettingIndexDevice, @@ -17,16 +18,29 @@ const uint32_t radio_device_value[RADIO_DEVICE_COUNT] = { SubGhzRadioDeviceTypeExternalCC1101, }; +const char* const radio_device_name[RADIO_DEVICE_COUNT] = { + SUBGHZ_DEVICE_CC1101_INT_NAME, + SUBGHZ_DEVICE_CC1101_EXT_NAME, +}; + +static uint8_t subghz_scene_radio_settings_next_index_connect_ext_device( + SubGhz* subghz, + uint8_t current_index) { + uint8_t index = 0; + for(index = current_index; index < RADIO_DEVICE_COUNT; index++) { + if(subghz_txrx_radio_device_is_external_connected(subghz->txrx, radio_device_name[index])) { + break; + } + } + if(index == RADIO_DEVICE_COUNT) index = 0; + return index; +} + static void subghz_scene_radio_settings_set_device(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); - uint8_t index = variable_item_get_current_value_index(item); - - if(!subghz_txrx_radio_device_is_external_connected( - subghz->txrx, SUBGHZ_DEVICE_CC1101_EXT_NAME) && - radio_device_value[index] == SubGhzRadioDeviceTypeExternalCC1101) { - //ToDo correct if there is more than 1 module - index = 0; - } + uint8_t current_index = variable_item_get_current_value_index(item); + uint8_t index = + subghz_scene_radio_settings_next_index_connect_ext_device(subghz, current_index); variable_item_set_current_value_text(item, radio_device_text[index]); subghz_txrx_radio_device_set(subghz->txrx, radio_device_value[index]); } @@ -37,9 +51,11 @@ void subghz_scene_radio_settings_on_enter(void* context) { uint8_t value_index; uint8_t value_count_device = RADIO_DEVICE_COUNT; + if(subghz_txrx_radio_device_get(subghz->txrx) == SubGhzRadioDeviceTypeInternal && - !subghz_txrx_radio_device_is_external_connected(subghz->txrx, SUBGHZ_DEVICE_CC1101_EXT_NAME)) + !subghz_scene_radio_settings_next_index_connect_ext_device(subghz, 1)) value_count_device = 1; + item = variable_item_list_add( subghz->variable_item_list, "Module", diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 6ab44357..497938fe 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -123,7 +123,7 @@ void subghz_scene_receiver_on_enter(void* context) { subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } furi_string_free(str_buff); - subghz_scene_receiver_update_statusbar(subghz); + subghz_view_receiver_set_callback( subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); subghz_txrx_set_rx_calback(subghz->txrx, subghz_scene_add_to_history_callback, subghz); @@ -136,6 +136,8 @@ void subghz_scene_receiver_on_enter(void* context) { furi_check( subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_BIN_RAW_NAME)); + subghz_scene_receiver_update_statusbar(subghz); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 9b57165e..7180bb3a 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -23,7 +23,7 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { if(subghz_txrx_load_decoder_by_name_protocol( subghz->txrx, subghz_history_get_protocol_name(subghz->history, subghz->idx_menu_chosen))) { - //todo we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal + // we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal subghz_protocol_decoder_base_deserialize( subghz_txrx_get_decoder(subghz->txrx), subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen)); diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index d0571f1b..8c040cc9 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -118,7 +118,7 @@ void subghz_scene_set_type_on_enter(void* context) { bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; - bool generated_protocol = false; + SubGhzProtocolStatus generated_protocol = SubGhzProtocolStatusError; if(event.type == SceneManagerEventTypeCustom) { uint32_t key = (uint32_t)rand(); @@ -174,7 +174,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexDoorHan_433_92: generated_protocol = subghz_txrx_gen_keeloq_protocol( subghz->txrx, "AM650", 433920000, "DoorHan", key, 0x2, 0x0003); - if(!generated_protocol) { + if(generated_protocol != SubGhzProtocolStatusOk) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); @@ -183,7 +183,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexDoorHan_315_00: generated_protocol = subghz_txrx_gen_keeloq_protocol( subghz->txrx, "AM650", 315000000, "DoorHan", key, 0x2, 0x0003); - if(!generated_protocol) { + if(generated_protocol != SubGhzProtocolStatusOk) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); @@ -216,7 +216,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSetType, event.event); - if(generated_protocol) { + if(generated_protocol == SubGhzProtocolStatusOk) { subghz_file_name_clear(subghz); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); return true; diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 55036846..9ff61837 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -134,7 +134,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) { - //Todo add Custom_preset_module + //TODO FL-3551: add Custom_preset_module //delete preset if it already exists subghz_setting_delete_custom_preset(setting, furi_string_get_cstr(temp_str)); //load custom preset from file @@ -289,10 +289,13 @@ bool subghz_save_protocol_to_file( if(!storage_simply_remove(storage, dev_file_name)) { break; } - //ToDo check Write stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + if(storage_common_stat(storage, dev_file_name, NULL) != FSE_OK) { + break; + } + saved = true; } while(0); furi_string_free(file_dir); diff --git a/applications/services/applications.h b/applications/services/applications.h index 426d6d2d..7dbb7063 100644 --- a/applications/services/applications.h +++ b/applications/services/applications.h @@ -51,6 +51,12 @@ extern const size_t FLIPPER_ON_SYSTEM_START_COUNT; extern const FlipperInternalApplication FLIPPER_SYSTEM_APPS[]; extern const size_t FLIPPER_SYSTEM_APPS_COUNT; +/* Debug apps + * Can only be spawned by loader by name + */ +extern const FlipperInternalApplication FLIPPER_DEBUG_APPS[]; +extern const size_t FLIPPER_DEBUG_APPS_COUNT; + extern const FlipperInternalApplication FLIPPER_ARCHIVE; /* Settings list diff --git a/applications/services/desktop/animations/views/bubble_animation_view.c b/applications/services/desktop/animations/views/bubble_animation_view.c index 607862d1..30a16508 100644 --- a/applications/services/desktop/animations/views/bubble_animation_view.c +++ b/applications/services/desktop/animations/views/bubble_animation_view.c @@ -128,8 +128,8 @@ static bool bubble_animation_input_callback(InputEvent* event, void* context) { if(event->key == InputKeyRight) { /* Right button reserved for animation activation, so consume */ - consumed = true; if(event->type == InputTypeShort) { + consumed = true; if(animation_view->interact_callback) { animation_view->interact_callback(animation_view->interact_callback_context); } diff --git a/applications/services/desktop/animations/views/one_shot_animation_view.c b/applications/services/desktop/animations/views/one_shot_animation_view.c index 9a4dff06..077f82d0 100644 --- a/applications/services/desktop/animations/views/one_shot_animation_view.c +++ b/applications/services/desktop/animations/views/one_shot_animation_view.c @@ -65,8 +65,8 @@ static bool one_shot_view_input(InputEvent* event, void* context) { if(!consumed) { if(event->key == InputKeyRight) { /* Right button reserved for animation activation, so consume */ - consumed = true; if(event->type == InputTypeShort) { + consumed = true; if(view->interact_callback) { view->interact_callback(view->interact_callback_context); } diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 30e7253d..0627652a 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -101,7 +101,7 @@ static void desktop_clock_draw_callback(Canvas* canvas, void* context) { char buffer[20]; snprintf(buffer, sizeof(buffer), "%02u:%02u", hour, desktop->time_minute); - // ToDo: never do that, may cause visual glitches + // TODO FL-3515: never do that, may cause visual glitches view_port_set_width( desktop->clock_viewport, canvas_string_width(canvas, buffer) - 1 + (desktop->time_minute % 10 == 1)); @@ -126,7 +126,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { return true; case DesktopGlobalAfterAppFinished: animation_manager_load_and_continue_animation(desktop->animation_manager); - // TODO: Implement a message mechanism for loading settings and (optionally) + // TODO FL-3497: Implement a message mechanism for loading settings and (optionally) // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); @@ -223,7 +223,6 @@ void desktop_lock(Desktop* desktop) { scene_manager_set_scene_state( desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); - notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000); DesktopStatus status = {.locked = true}; furi_pubsub_publish(desktop->status_pubsub, &status); @@ -381,12 +380,7 @@ Desktop* desktop_alloc() { } gui_add_view_port(desktop->gui, desktop->stealth_mode_icon_viewport, GuiLayerStatusBarLeft); - // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); - if(loader_is_locked(desktop->loader) && - animation_manager_is_animation_loaded(desktop->animation_manager)) { - animation_manager_unload_and_stall_animation(desktop->animation_manager); - } desktop->notification = furi_record_open(RECORD_NOTIFICATION); desktop->app_start_stop_subscription = furi_pubsub_subscribe( @@ -477,6 +471,12 @@ int32_t desktop_srv(void* p) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneFault); } + // Special case: autostart application is already running + if(loader_is_locked(desktop->loader) && + animation_manager_is_animation_loaded(desktop->animation_manager)) { + animation_manager_unload_and_stall_animation(desktop->animation_manager); + } + view_dispatcher_run(desktop->view_dispatcher); furi_crash("That was unexpected"); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index a189f9f0..5cf9cc4c 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (9) +#define DESKTOP_SETTINGS_VER (10) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -36,6 +36,22 @@ #define MIN_PIN_SIZE 4 #define MAX_APP_LENGTH 128 +typedef enum { + FavoriteAppLeftShort = 0, + FavoriteAppLeftLong, + FavoriteAppRightShort, + FavoriteAppRightLong, + FavoriteAppNumber, +} FavoriteAppShortcut; + +typedef enum { + DummyAppLeft = 0, + DummyAppRight, + DummyAppDown, + DummyAppOk, + DummyAppNumber, +} DummyAppShortcut; + typedef struct { InputKey data[MAX_PIN_SIZE]; uint8_t length; @@ -46,10 +62,10 @@ typedef struct { } FavoriteApp; typedef struct { - FavoriteApp favorite_primary; - FavoriteApp favorite_secondary; PinCode pin_code; uint32_t auto_lock_delay_ms; uint8_t dummy_mode; uint8_t display_clock; + FavoriteApp favorite_apps[FavoriteAppNumber]; + FavoriteApp dummy_apps[DummyAppNumber]; } DesktopSettings; diff --git a/applications/services/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c index f64ef837..bbed5600 100644 --- a/applications/services/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -87,6 +87,10 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { desktop_unlock(desktop); consumed = true; break; + case DesktopLockedEventDoorsClosed: + notification_message(desktop->notification, &sequence_display_backlight_off); + consumed = true; + break; case DesktopLockedEventUpdate: if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) { notification_message(desktop->notification, &sequence_display_backlight_off); diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index ae39ec22..a659ff4e 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -12,10 +12,6 @@ #define TAG "DesktopSrv" -#define MUSIC_PLAYER_APP EXT_PATH("/apps/Media/music_player.fap") -#define SNAKE_GAME_APP EXT_PATH("/apps/Games/snake_game.fap") -#define CLOCK_APP EXT_PATH("/apps/Tools/clock.fap") - static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; @@ -65,8 +61,15 @@ static void } #endif -static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* path) { - if(loader_start_with_gui_error(desktop->loader, path, NULL) != LoaderStatusOk) { +static void desktop_scene_main_open_app_or_profile(Desktop* desktop, FavoriteApp* application) { + bool load_ok = false; + if(strlen(application->name_or_path) > 0) { + if(loader_start(desktop->loader, application->name_or_path, NULL, NULL) == + LoaderStatusOk) { + load_ok = true; + } + } + if(!load_ok) { loader_start(desktop->loader, "Passport", NULL, NULL); } } @@ -115,6 +118,11 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { consumed = true; } break; + case DesktopMainEventLock: + desktop_lock(desktop); + consumed = true; + break; + case DesktopMainEventOpenLockMenu: scene_manager_next_scene(desktop->scene_manager, DesktopSceneLockMenu); consumed = true; @@ -138,16 +146,31 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; } - case DesktopMainEventOpenFavoritePrimary: + case DesktopMainEventOpenFavoriteLeftShort: DESKTOP_SETTINGS_LOAD(&desktop->settings); - desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary); + desktop_scene_main_start_favorite( + desktop, &desktop->settings.favorite_apps[FavoriteAppLeftShort]); consumed = true; break; - case DesktopMainEventOpenFavoriteSecondary: + case DesktopMainEventOpenFavoriteLeftLong: DESKTOP_SETTINGS_LOAD(&desktop->settings); - desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary); + desktop_scene_main_start_favorite( + desktop, &desktop->settings.favorite_apps[FavoriteAppLeftLong]); consumed = true; break; + case DesktopMainEventOpenFavoriteRightShort: + DESKTOP_SETTINGS_LOAD(&desktop->settings); + desktop_scene_main_start_favorite( + desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]); + consumed = true; + break; + case DesktopMainEventOpenFavoriteRightLong: + DESKTOP_SETTINGS_LOAD(&desktop->settings); + desktop_scene_main_start_favorite( + desktop, &desktop->settings.favorite_apps[FavoriteAppRightLong]); + consumed = true; + break; + case DesktopAnimationEventCheckAnimation: animation_manager_check_blocking_process(desktop->animation_manager); consumed = true; @@ -158,26 +181,31 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; case DesktopAnimationEventInteractAnimation: if(!animation_manager_interact_process(desktop->animation_manager)) { - loader_start(desktop->loader, "Passport", NULL, NULL); + DESKTOP_SETTINGS_LOAD(&desktop->settings); + if(!desktop->settings.dummy_mode) { + desktop_scene_main_open_app_or_profile( + desktop, &desktop->settings.favorite_apps[FavoriteAppRightShort]); + } else { + desktop_scene_main_open_app_or_profile( + desktop, &desktop->settings.dummy_apps[DummyAppRight]); + } } consumed = true; break; - case DesktopMainEventOpenPassport: { - loader_start(desktop->loader, "Passport", NULL, NULL); + + case DesktopDummyEventOpenLeft: + desktop_scene_main_open_app_or_profile( + desktop, &desktop->settings.dummy_apps[DummyAppLeft]); break; - } - case DesktopMainEventOpenGame: { - desktop_scene_main_open_app_or_profile(desktop, SNAKE_GAME_APP); + case DesktopDummyEventOpenDown: + desktop_scene_main_open_app_or_profile( + desktop, &desktop->settings.dummy_apps[DummyAppDown]); break; - } - case DesktopMainEventOpenClock: { - desktop_scene_main_open_app_or_profile(desktop, CLOCK_APP); + case DesktopDummyEventOpenOk: + desktop_scene_main_open_app_or_profile( + desktop, &desktop->settings.dummy_apps[DummyAppOk]); break; - } - case DesktopMainEventOpenMusicPlayer: { - desktop_scene_main_open_app_or_profile(desktop, MUSIC_PLAYER_APP); - break; - } + case DesktopLockedEventUpdate: desktop_view_locked_update(desktop->locked_view); consumed = true; diff --git a/applications/services/desktop/views/desktop_events.h b/applications/services/desktop/views/desktop_events.h index e366885f..5dc51fd8 100644 --- a/applications/services/desktop/views/desktop_events.h +++ b/applications/services/desktop/views/desktop_events.h @@ -1,22 +1,25 @@ #pragma once typedef enum { + DesktopMainEventLock, DesktopMainEventOpenLockMenu, DesktopMainEventOpenArchive, - DesktopMainEventOpenFavoritePrimary, - DesktopMainEventOpenFavoriteSecondary, + DesktopMainEventOpenFavoriteLeftShort, + DesktopMainEventOpenFavoriteLeftLong, + DesktopMainEventOpenFavoriteRightShort, + DesktopMainEventOpenFavoriteRightLong, DesktopMainEventOpenMenu, DesktopMainEventOpenDebug, - DesktopMainEventOpenPassport, DesktopMainEventOpenPowerOff, - DesktopMainEventOpenGame, - DesktopMainEventOpenClock, - DesktopMainEventOpenMusicPlayer, + DesktopDummyEventOpenLeft, + DesktopDummyEventOpenDown, + DesktopDummyEventOpenOk, DesktopLockedEventUnlocked, DesktopLockedEventUpdate, DesktopLockedEventShowPinInput, + DesktopLockedEventDoorsClosed, DesktopPinInputEventResetWrongPinLabel, DesktopPinInputEventUnlocked, diff --git a/applications/services/desktop/views/desktop_view_locked.c b/applications/services/desktop/views/desktop_view_locked.c index 0bf75703..3cee2542 100644 --- a/applications/services/desktop/views/desktop_view_locked.c +++ b/applications/services/desktop/views/desktop_view_locked.c @@ -99,6 +99,7 @@ void desktop_view_locked_update(DesktopViewLocked* locked_view) { if(view_state == DesktopViewLockedStateDoorsClosing && !desktop_view_locked_doors_move(model)) { + locked_view->callback(DesktopLockedEventDoorsClosed, locked_view->context); model->view_state = DesktopViewLockedStateLocked; } else if(view_state == DesktopViewLockedStateLockedHintShown) { model->view_state = DesktopViewLockedStateLocked; diff --git a/applications/services/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c index 7d956489..d323567e 100644 --- a/applications/services/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -59,28 +59,32 @@ bool desktop_main_input_callback(InputEvent* event, void* context) { } else if(event->key == InputKeyDown) { main_view->callback(DesktopMainEventOpenArchive, main_view->context); } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context); + main_view->callback(DesktopMainEventOpenFavoriteLeftShort, main_view->context); } - // Right key is handled by animation manager + // Right key short is handled by animation manager } else if(event->type == InputTypeLong) { - if(event->key == InputKeyDown) { + if(event->key == InputKeyUp) { + main_view->callback(DesktopMainEventLock, main_view->context); + } else if(event->key == InputKeyDown) { main_view->callback(DesktopMainEventOpenDebug, main_view->context); } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); + main_view->callback(DesktopMainEventOpenFavoriteLeftLong, main_view->context); + } else if(event->key == InputKeyRight) { + main_view->callback(DesktopMainEventOpenFavoriteRightLong, main_view->context); } } } else { if(event->type == InputTypeShort) { if(event->key == InputKeyOk) { - main_view->callback(DesktopMainEventOpenGame, main_view->context); + main_view->callback(DesktopDummyEventOpenOk, main_view->context); } else if(event->key == InputKeyUp) { main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenMusicPlayer, main_view->context); + main_view->callback(DesktopDummyEventOpenDown, main_view->context); } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenClock, main_view->context); + main_view->callback(DesktopDummyEventOpenLeft, main_view->context); } - // Right key is handled by animation manager + // Right key short is handled by animation manager } } diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 9b7c84ec..37ecfde4 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -236,11 +236,11 @@ static size_t } if(len_px > px_left) { - uint8_t excess_symbols_approximately = - roundf((float)(len_px - px_left) / ((float)len_px / (float)text_size)); + size_t excess_symbols_approximately = + ceilf((float)(len_px - px_left) / ((float)len_px / (float)text_size)); // reduce to 5 to be sure dash fit, and next line will be at least 5 symbols long if(excess_symbols_approximately > 0) { - excess_symbols_approximately = MAX(excess_symbols_approximately, 5); + excess_symbols_approximately = MAX(excess_symbols_approximately, 5u); result = text_size - excess_symbols_approximately - 1; } else { result = text_size; diff --git a/applications/services/gui/modules/button_panel.c b/applications/services/gui/modules/button_panel.c index 9b816eed..ded7891e 100644 --- a/applications/services/gui/modules/button_panel.c +++ b/applications/services/gui/modules/button_panel.c @@ -29,6 +29,9 @@ typedef struct { const Icon* name_selected; } IconElement; +LIST_DEF(IconList, IconElement, M_POD_OPLIST) +#define M_OPL_IconList_t() LIST_OPLIST(IconList) + typedef struct ButtonItem { uint32_t index; ButtonItemCallback callback; @@ -47,6 +50,7 @@ struct ButtonPanel { typedef struct { ButtonMatrix_t button_matrix; + IconList_t icons; LabelList_t labels; uint16_t reserve_x; uint16_t reserve_y; @@ -103,7 +107,6 @@ void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t re ButtonArray_t* array = ButtonMatrix_get(model->button_matrix, i); ButtonArray_init(*array); ButtonArray_reserve(*array, reserve_x); - // TODO: do we need to clear allocated memory of ptr-s to ButtonItem ?? } LabelList_init(model->labels); }, @@ -147,6 +150,7 @@ void button_panel_reset(ButtonPanel* button_panel) { model->selected_item_x = 0; model->selected_item_y = 0; LabelList_reset(model->labels); + IconList_reset(model->icons); ButtonMatrix_reset(model->button_matrix); }, true); @@ -209,9 +213,17 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); + for + M_EACH(icon, model->icons, IconList_t) { + canvas_draw_icon(canvas, icon->x, icon->y, icon->name); + } + for(size_t x = 0; x < model->reserve_x; ++x) { for(size_t y = 0; y < model->reserve_y; ++y) { ButtonItem* button_item = *button_panel_get_item(model, x, y); + if(!button_item) { + continue; + } const Icon* icon_name = button_item->icon.name; if((model->selected_item_x == x) && (model->selected_item_y == y)) { icon_name = button_item->icon.name_selected; @@ -407,3 +419,24 @@ void button_panel_add_label( }, true); } + +// Draw an icon but don't make it a button. +void button_panel_add_icon( + ButtonPanel* button_panel, + uint16_t x, + uint16_t y, + const Icon* icon_name) { + furi_assert(button_panel); + + with_view_model( //-V773 + button_panel->view, + ButtonPanelModel * model, + { + IconElement* icon = IconList_push_raw(model->icons); + icon->x = x; + icon->y = y; + icon->name = icon_name; + icon->name_selected = icon_name; + }, + true); +} \ No newline at end of file diff --git a/applications/services/gui/modules/button_panel.h b/applications/services/gui/modules/button_panel.h index f3b0bae7..1218222b 100644 --- a/applications/services/gui/modules/button_panel.h +++ b/applications/services/gui/modules/button_panel.h @@ -100,6 +100,19 @@ void button_panel_add_label( Font font, const char* label_str); +/** Add a non-button icon to button_panel module. + * + * @param button_panel ButtonPanel instance + * @param x x-coordinate to place icon + * @param y y-coordinate to place icon + * @param icon_name name of the icon to draw + */ +void button_panel_add_icon( + ButtonPanel* button_panel, + uint16_t x, + uint16_t y, + const Icon* icon_name); + #ifdef __cplusplus } #endif diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 920b3c13..83f0edbe 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -272,7 +272,7 @@ void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* e } else if(view_dispatcher->navigation_event_callback) { // Dispatch navigation event if(!view_dispatcher->navigation_event_callback(view_dispatcher->event_context)) { - // TODO: should we allow view_dispatcher to stop without navigation_event_callback? + // TODO FL-3514: should we allow view_dispatcher to stop without navigation_event_callback? view_dispatcher_stop(view_dispatcher); return; } diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index 8c2ff6fe..57c0fddb 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -7,7 +7,7 @@ #include "gui.h" #include "gui_i.h" -// TODO add mutex to view_port ops +// TODO FL-3498: add mutex to view_port ops _Static_assert(ViewPortOrientationMAX == 4, "Incorrect ViewPortOrientation count"); _Static_assert( diff --git a/applications/services/loader/firmware_api/firmware_api.cpp b/applications/services/loader/firmware_api/firmware_api.cpp index 6651bf11..47554f62 100644 --- a/applications/services/loader/firmware_api/firmware_api.cpp +++ b/applications/services/loader/firmware_api/firmware_api.cpp @@ -10,6 +10,19 @@ static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!"); +#ifdef APP_UNIT_TESTS +constexpr HashtableApiInterface mock_elf_api_interface{ + { + .api_version_major = 0, + .api_version_minor = 0, + .resolver_callback = &elf_resolve_from_hashtable, + }, + .table_cbegin = nullptr, + .table_cend = nullptr, +}; + +const ElfApiInterface* const firmware_api_interface = &mock_elf_api_interface; +#else constexpr HashtableApiInterface elf_api_interface{ { .api_version_major = (elf_api_version >> 16), @@ -19,10 +32,10 @@ constexpr HashtableApiInterface elf_api_interface{ .table_cbegin = elf_api_table.cbegin(), .table_cend = elf_api_table.cend(), }; - const ElfApiInterface* const firmware_api_interface = &elf_api_interface; +#endif extern "C" void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor) { - *major = elf_api_interface.api_version_major; - *minor = elf_api_interface.api_version_minor; + *major = firmware_api_interface->api_version_major; + *minor = firmware_api_interface->api_version_minor; } \ No newline at end of file diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 41c0f95d..53f70a1e 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -1,4 +1,5 @@ #include "loader.h" +#include "core/core_defines.h" #include "loader_i.h" #include #include @@ -61,7 +62,7 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const dialog_message_free(message); furi_record_close(RECORD_DIALOGS); } else if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) { - // TODO: we have many places where we can emit a double start, ex: desktop, menu + // TODO FL-3522: we have many places where we can emit a double start, ex: desktop, menu // so i prefer to not show LoaderStatusErrorAppStarted error message for now DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); @@ -186,18 +187,24 @@ static FlipperInternalApplication const* loader_find_application_by_name_in_list } static const FlipperInternalApplication* loader_find_application_by_name(const char* name) { - const FlipperInternalApplication* application = NULL; - application = loader_find_application_by_name_in_list(name, FLIPPER_APPS, FLIPPER_APPS_COUNT); - if(!application) { - application = loader_find_application_by_name_in_list( - name, FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT); - } - if(!application) { - application = loader_find_application_by_name_in_list( - name, FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT); + const struct { + const FlipperInternalApplication* list; + const uint32_t count; + } lists[] = { + {FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT}, + {FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT}, + {FLIPPER_DEBUG_APPS, FLIPPER_DEBUG_APPS_COUNT}, + }; + + for(size_t i = 0; i < COUNT_OF(lists); i++) { + const FlipperInternalApplication* application = + loader_find_application_by_name_in_list(name, lists[i].list, lists[i].count); + if(application) { + return application; + } } - return application; + return NULL; } static void loader_start_app_thread(Loader* loader, FlipperInternalApplicationFlag flags) { @@ -253,9 +260,7 @@ static void loader_log_status_error( furi_string_vprintf(error_message, format, args); FURI_LOG_E(TAG, "Status [%d]: %s", status, furi_string_get_cstr(error_message)); } else { - FuriString* tmp = furi_string_alloc(); - FURI_LOG_E(TAG, "Status [%d]: %s", status, furi_string_get_cstr(tmp)); - furi_string_free(tmp); + FURI_LOG_E(TAG, "Status [%d]", status); } } @@ -490,7 +495,9 @@ int32_t loader_srv(void* p) { FLIPPER_ON_SYSTEM_START[i](); } - if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) { + if((furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) && FLIPPER_AUTORUN_APP_NAME && + strlen(FLIPPER_AUTORUN_APP_NAME)) { + FURI_LOG_I(TAG, "Starting autorun app: %s", FLIPPER_AUTORUN_APP_NAME); loader_do_start_by_name(loader, FLIPPER_AUTORUN_APP_NAME, NULL, NULL); } diff --git a/applications/services/loader/loader_cli.c b/applications/services/loader/loader_cli.c index cbec4adc..489a576e 100644 --- a/applications/services/loader/loader_cli.c +++ b/applications/services/loader/loader_cli.c @@ -28,7 +28,7 @@ static void loader_cli_info(Loader* loader) { if(!loader_is_locked(loader)) { printf("No application is running\r\n"); } else { - // TODO: print application name ??? + // TODO FL-3513: print application name ??? printf("Application is running\r\n"); } } diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index aadb5f46..e39a84ea 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -30,7 +30,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) { if(power->state == PowerStateCharging) { canvas_set_bitmap_mode(canvas, 1); canvas_set_color(canvas, ColorWhite); - // TODO: replace -1 magic for uint8_t with re-framing + // TODO FL-3510: replace -1 magic for uint8_t with re-framing canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_mask_9x10); canvas_set_color(canvas, ColorBlack); canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_9x10); diff --git a/applications/services/rpc/rpc_gui.c b/applications/services/rpc/rpc_gui.c index 9ba20a83..9eff4bca 100644 --- a/applications/services/rpc/rpc_gui.c +++ b/applications/services/rpc/rpc_gui.c @@ -279,7 +279,7 @@ static void rpc_system_gui_start_virtual_display_process(const PB_Main* request, return; } - // TODO: consider refactoring + // TODO FL-3511: consider refactoring // Using display framebuffer size as an XBM buffer size is like comparing apples and oranges // Glad they both are 1024 for now size_t buffer_size = canvas_get_buffer_size(rpc_gui->gui->canvas); diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index e6b42696..70cb7b92 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -399,7 +399,7 @@ static FS_Error storage_process_common_fs_info( } /****************** Raw SD API ******************/ -// TODO think about implementing a custom storage API to split that kind of api linkage +// TODO FL-3521: think about implementing a custom storage API to split that kind of api linkage #include "storages/storage_ext.h" static FS_Error storage_process_sd_format(Storage* app) { diff --git a/applications/services/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c index 15a355dc..35b3ee25 100644 --- a/applications/services/storage/storages/storage_ext.c +++ b/applications/services/storage/storages/storage_ext.c @@ -100,7 +100,7 @@ FS_Error sd_unmount_card(StorageData* storage) { storage->status = StorageStatusNotReady; error = FR_DISK_ERR; - // TODO do i need to close the files? + // TODO FL-3522: do i need to close the files? f_mount(0, sd_data->path, 0); return storage_ext_parse_error(error); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index e0b4c118..31826cae 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -1,17 +1,19 @@ #include "../desktop_settings_app.h" #include "applications.h" #include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" #include #include #include #define APPS_COUNT (FLIPPER_APPS_COUNT + FLIPPER_EXTERNAL_APPS_COUNT) -#define EXTERNAL_BROWSER_NAME ("Apps") -#define EXTERNAL_BROWSER_INDEX (APPS_COUNT + 1) +#define DEFAULT_INDEX (0) +#define EXTERNAL_BROWSER_NAME ("Apps Menu (Default)") +#define PASSPORT_NAME ("Passport (Default)") +#define EXTERNAL_APPLICATION_INDEX (1) #define EXTERNAL_APPLICATION_NAME ("[Select App]") -#define EXTERNAL_APPLICATION_INDEX (APPS_COUNT + 2) #define PRESELECTED_SPECIAL 0xffffffff @@ -55,28 +57,32 @@ void desktop_settings_scene_favorite_on_enter(void* context) { Submenu* submenu = app->submenu; submenu_reset(submenu); - uint32_t primary_favorite = + uint32_t favorite_id = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); uint32_t pre_select_item = PRESELECTED_SPECIAL; - FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary : - &app->settings.favorite_secondary; + FavoriteApp* curr_favorite_app = NULL; + bool is_dummy_app = false; + bool default_passport = false; - for(size_t i = 0; i < APPS_COUNT; i++) { - const char* name = favorite_fap_get_app_name(i); - - submenu_add_item(submenu, name, i, desktop_settings_scene_favorite_submenu_callback, app); - - // Select favorite item in submenu - if(!strcmp(name, curr_favorite_app->name_or_path)) { - pre_select_item = i; + if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) { + furi_assert(favorite_id < FavoriteAppNumber); + curr_favorite_app = &app->settings.favorite_apps[favorite_id]; + if(favorite_id == FavoriteAppRightShort) { + default_passport = true; } + } else { + favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP); + furi_assert(favorite_id < DummyAppNumber); + curr_favorite_app = &app->settings.dummy_apps[favorite_id]; + is_dummy_app = true; + default_passport = true; } // Special case: Application browser submenu_add_item( submenu, - EXTERNAL_BROWSER_NAME, - EXTERNAL_BROWSER_INDEX, + default_passport ? (PASSPORT_NAME) : (EXTERNAL_BROWSER_NAME), + DEFAULT_INDEX, desktop_settings_scene_favorite_submenu_callback, app); @@ -88,16 +94,29 @@ void desktop_settings_scene_favorite_on_enter(void* context) { desktop_settings_scene_favorite_submenu_callback, app); + if(!is_dummy_app) { + for(size_t i = 0; i < APPS_COUNT; i++) { + const char* name = favorite_fap_get_app_name(i); + + submenu_add_item( + submenu, name, i + 2, desktop_settings_scene_favorite_submenu_callback, app); + + // Select favorite item in submenu + if(!strcmp(name, curr_favorite_app->name_or_path)) { + pre_select_item = i + 2; + } + } + } + if(pre_select_item == PRESELECTED_SPECIAL) { if(curr_favorite_app->name_or_path[0] == '\0') { - pre_select_item = EXTERNAL_BROWSER_INDEX; + pre_select_item = DEFAULT_INDEX; } else { pre_select_item = EXTERNAL_APPLICATION_INDEX; } } - submenu_set_header( - submenu, primary_favorite ? "Primary favorite app:" : "Secondary favorite app:"); + submenu_set_header(submenu, is_dummy_app ? ("Dummy Mode app:") : ("Favorite app:")); submenu_set_selected_item(submenu, pre_select_item); // If set during loop, visual glitch. view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu); @@ -108,13 +127,20 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e bool consumed = false; FuriString* temp_path = furi_string_alloc_set_str(EXT_PATH("apps")); - uint32_t primary_favorite = + uint32_t favorite_id = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); - FavoriteApp* curr_favorite_app = primary_favorite ? &app->settings.favorite_primary : - &app->settings.favorite_secondary; + FavoriteApp* curr_favorite_app = NULL; + if((favorite_id & SCENE_STATE_SET_DUMMY_APP) == 0) { + furi_assert(favorite_id < FavoriteAppNumber); + curr_favorite_app = &app->settings.favorite_apps[favorite_id]; + } else { + favorite_id &= ~(SCENE_STATE_SET_DUMMY_APP); + furi_assert(favorite_id < DummyAppNumber); + curr_favorite_app = &app->settings.dummy_apps[favorite_id]; + } if(event.type == SceneManagerEventTypeCustom) { - if(event.event == EXTERNAL_BROWSER_INDEX) { + if(event.event == DEFAULT_INDEX) { curr_favorite_app->name_or_path[0] = '\0'; consumed = true; } else if(event.event == EXTERNAL_APPLICATION_INDEX) { @@ -142,7 +168,8 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e consumed = true; } } else { - const char* name = favorite_fap_get_app_name(event.event); + size_t app_index = event.event - 2; + const char* name = favorite_fap_get_app_name(app_index); if(name) strncpy(curr_favorite_app->name_or_path, name, MAX_APP_LENGTH); consumed = true; } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h b/applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h index 230fec87..657680bc 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_i.h @@ -5,3 +5,6 @@ #define SCENE_STATE_PIN_ERROR_MISMATCH (0) #define SCENE_STATE_PIN_ERROR_WRONG (1) + +#define SCENE_STATE_SET_FAVORITE_APP (0) +#define SCENE_STATE_SET_DUMMY_APP (1 << 8) diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 02acd51c..3e77bd8a 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -3,15 +3,24 @@ #include "../desktop_settings_app.h" #include "desktop_settings_scene.h" +#include "desktop_settings_scene_i.h" -#define SCENE_EVENT_SELECT_FAVORITE_PRIMARY 0 -#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1 -#define SCENE_EVENT_SELECT_PIN_SETUP 2 -#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 3 -#define SCENE_EVENT_SELECT_CLOCK_DISPLAY 4 +typedef enum { + DesktopSettingsPinSetup = 0, + DesktopSettingsAutoLockDelay, + DesktopSettingsClockDisplay, + DesktopSettingsFavoriteLeftShort, + DesktopSettingsFavoriteLeftLong, + DesktopSettingsFavoriteRightShort, + DesktopSettingsFavoriteRightLong, + DesktopSettingsDummyLeft, + DesktopSettingsDummyRight, + DesktopSettingsDummyDown, + DesktopSettingsDummyOk, +} DesktopSettingsEntry; #define AUTO_LOCK_DELAY_COUNT 6 -const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { +static const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { "OFF", "30s", "60s", @@ -19,8 +28,7 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { "5min", "10min", }; - -const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = +static const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 30000, 60000, 120000, 300000, 600000}; #define CLOCK_ENABLE_COUNT 2 @@ -59,10 +67,6 @@ void desktop_settings_scene_start_on_enter(void* context) { VariableItem* item; uint8_t value_index; - variable_item_list_add(variable_item_list, "Primary Favorite App", 1, NULL, NULL); - - variable_item_list_add(variable_item_list, "Secondary Favorite App", 1, NULL, NULL); - variable_item_list_add(variable_item_list, "PIN Setup", 1, NULL, NULL); item = variable_item_list_add( @@ -72,8 +76,6 @@ void desktop_settings_scene_start_on_enter(void* context) { desktop_settings_scene_start_auto_lock_delay_changed, app); - variable_item_list_set_enter_callback( - variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); value_index = value_index_uint32( app->settings.auto_lock_delay_ms, auto_lock_delay_value, AUTO_LOCK_DELAY_COUNT); variable_item_set_current_value_index(item, value_index); @@ -91,6 +93,19 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, clock_enable_text[value_index]); + variable_item_list_add(variable_item_list, "Favorite App - Left Short", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Favorite App - Left Long", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Favorite App - Right Short", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Favorite App - Right Long", 1, NULL, NULL); + + variable_item_list_add(variable_item_list, "Dummy Mode App - Left", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Dummy Mode App - Right", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Dummy Mode App - Down", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Dummy Mode App - Ok", 1, NULL, NULL); + + variable_item_list_set_enter_callback( + variable_item_list, desktop_settings_scene_start_var_list_enter_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList); } @@ -100,25 +115,72 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case SCENE_EVENT_SELECT_FAVORITE_PRIMARY: - scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 1); - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); - consumed = true; - break; - case SCENE_EVENT_SELECT_FAVORITE_SECONDARY: - scene_manager_set_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite, 0); - scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); - consumed = true; - break; - case SCENE_EVENT_SELECT_PIN_SETUP: + case DesktopSettingsPinSetup: scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinMenu); - consumed = true; break; - case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY: - case SCENE_EVENT_SELECT_CLOCK_DISPLAY: - consumed = true; + + case DesktopSettingsFavoriteLeftShort: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftShort); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsFavoriteLeftLong: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_FAVORITE_APP | FavoriteAppLeftLong); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsFavoriteRightShort: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightShort); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsFavoriteRightLong: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_FAVORITE_APP | FavoriteAppRightLong); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + + case DesktopSettingsDummyLeft: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_DUMMY_APP | DummyAppLeft); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsDummyRight: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_DUMMY_APP | DummyAppRight); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsDummyDown: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_DUMMY_APP | DummyAppDown); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + case DesktopSettingsDummyOk: + scene_manager_set_scene_state( + app->scene_manager, + DesktopSettingsAppSceneFavorite, + SCENE_STATE_SET_DUMMY_APP | DummyAppOk); + scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneFavorite); + break; + + default: break; } + consumed = true; } return consumed; } diff --git a/applications/system/updater/scenes/updater_scene_main.c b/applications/system/updater/scenes/updater_scene_main.c index 2ef0732c..9fd68161 100644 --- a/applications/system/updater/scenes/updater_scene_main.c +++ b/applications/system/updater/scenes/updater_scene_main.c @@ -80,7 +80,7 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) { break; case UpdaterCustomEventSdUnmounted: - // TODO: error out, stop worker (it's probably dead actually) + // TODO FL-3499: error out, stop worker (it's probably dead actually) break; default: break; diff --git a/assets/icons/Infrared/CoolHi_25x27.png b/assets/icons/Infrared/CoolHi_25x27.png deleted file mode 100644 index cea29a5b..00000000 Binary files a/assets/icons/Infrared/CoolHi_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/CoolHi_hvr_25x27.png b/assets/icons/Infrared/CoolHi_hvr_25x27.png deleted file mode 100644 index 692ac7b8..00000000 Binary files a/assets/icons/Infrared/CoolHi_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/CoolLo_25x27.png b/assets/icons/Infrared/CoolLo_25x27.png deleted file mode 100644 index 23288e44..00000000 Binary files a/assets/icons/Infrared/CoolLo_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/CoolLo_hvr_25x27.png b/assets/icons/Infrared/CoolLo_hvr_25x27.png deleted file mode 100644 index ae5316e4..00000000 Binary files a/assets/icons/Infrared/CoolLo_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Dehumidify_25x27.png b/assets/icons/Infrared/Dehumidify_25x27.png deleted file mode 100644 index dca77ae4..00000000 Binary files a/assets/icons/Infrared/Dehumidify_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Dehumidify_hvr_25x27.png b/assets/icons/Infrared/Dehumidify_hvr_25x27.png deleted file mode 100644 index 2c593ca8..00000000 Binary files a/assets/icons/Infrared/Dehumidify_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/HeatHi_25x27.png b/assets/icons/Infrared/HeatHi_25x27.png deleted file mode 100644 index a1724f99..00000000 Binary files a/assets/icons/Infrared/HeatHi_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/HeatHi_hvr_25x27.png b/assets/icons/Infrared/HeatHi_hvr_25x27.png deleted file mode 100644 index b92108d6..00000000 Binary files a/assets/icons/Infrared/HeatHi_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/HeatLo_25x27.png b/assets/icons/Infrared/HeatLo_25x27.png deleted file mode 100644 index af2e59d4..00000000 Binary files a/assets/icons/Infrared/HeatLo_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/HeatLo_hvr_25x27.png b/assets/icons/Infrared/HeatLo_hvr_25x27.png deleted file mode 100644 index 6708edb3..00000000 Binary files a/assets/icons/Infrared/HeatLo_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Mute_25x27.png b/assets/icons/Infrared/Mute_25x27.png deleted file mode 100644 index d8812dd4..00000000 Binary files a/assets/icons/Infrared/Mute_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Mute_hvr_25x27.png b/assets/icons/Infrared/Mute_hvr_25x27.png deleted file mode 100644 index 155bd900..00000000 Binary files a/assets/icons/Infrared/Mute_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Off_25x27.png b/assets/icons/Infrared/Off_25x27.png deleted file mode 100644 index c1510060..00000000 Binary files a/assets/icons/Infrared/Off_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Off_hvr_25x27.png b/assets/icons/Infrared/Off_hvr_25x27.png deleted file mode 100644 index d5e5e6f4..00000000 Binary files a/assets/icons/Infrared/Off_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Pause_25x27.png b/assets/icons/Infrared/Pause_25x27.png deleted file mode 100644 index a371ba81..00000000 Binary files a/assets/icons/Infrared/Pause_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Pause_hvr_25x27.png b/assets/icons/Infrared/Pause_hvr_25x27.png deleted file mode 100644 index 472d583d..00000000 Binary files a/assets/icons/Infrared/Pause_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Play_25x27.png b/assets/icons/Infrared/Play_25x27.png deleted file mode 100644 index fb793c5a..00000000 Binary files a/assets/icons/Infrared/Play_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Play_hvr_25x27.png b/assets/icons/Infrared/Play_hvr_25x27.png deleted file mode 100644 index 6708dcdb..00000000 Binary files a/assets/icons/Infrared/Play_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Power_25x27.png b/assets/icons/Infrared/Power_25x27.png deleted file mode 100644 index 5ae493fb..00000000 Binary files a/assets/icons/Infrared/Power_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Power_hvr_25x27.png b/assets/icons/Infrared/Power_hvr_25x27.png deleted file mode 100644 index 9425072c..00000000 Binary files a/assets/icons/Infrared/Power_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/TrackNext_25x27.png b/assets/icons/Infrared/TrackNext_25x27.png deleted file mode 100644 index 7b8f2839..00000000 Binary files a/assets/icons/Infrared/TrackNext_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/TrackNext_hvr_25x27.png b/assets/icons/Infrared/TrackNext_hvr_25x27.png deleted file mode 100644 index a4de4fc3..00000000 Binary files a/assets/icons/Infrared/TrackNext_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/TrackPrev_25x27.png b/assets/icons/Infrared/TrackPrev_25x27.png deleted file mode 100644 index 3cd2a8da..00000000 Binary files a/assets/icons/Infrared/TrackPrev_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/TrackPrev_hvr_25x27.png b/assets/icons/Infrared/TrackPrev_hvr_25x27.png deleted file mode 100644 index 83805534..00000000 Binary files a/assets/icons/Infrared/TrackPrev_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Up_25x27.png b/assets/icons/Infrared/Up_25x27.png deleted file mode 100644 index b81a02e8..00000000 Binary files a/assets/icons/Infrared/Up_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/Up_hvr_25x27.png b/assets/icons/Infrared/Up_hvr_25x27.png deleted file mode 100644 index cf71e596..00000000 Binary files a/assets/icons/Infrared/Up_hvr_25x27.png and /dev/null differ diff --git a/assets/icons/Infrared/back_btn_10x8.png b/assets/icons/Infrared/back_btn_10x8.png new file mode 100644 index 00000000..10d7beb3 Binary files /dev/null and b/assets/icons/Infrared/back_btn_10x8.png differ diff --git a/assets/icons/Infrared/celsius_24x23.png b/assets/icons/Infrared/celsius_24x23.png new file mode 100644 index 00000000..64d7a1db Binary files /dev/null and b/assets/icons/Infrared/celsius_24x23.png differ diff --git a/assets/icons/Infrared/celsius_hover_24x23.png b/assets/icons/Infrared/celsius_hover_24x23.png new file mode 100644 index 00000000..0488b40f Binary files /dev/null and b/assets/icons/Infrared/celsius_hover_24x23.png differ diff --git a/assets/icons/Infrared/Vol_up_hvr_25x27.png b/assets/icons/Infrared/ch_down_24x21.png similarity index 70% rename from assets/icons/Infrared/Vol_up_hvr_25x27.png rename to assets/icons/Infrared/ch_down_24x21.png index 90c2df47..8c3f81c3 100644 Binary files a/assets/icons/Infrared/Vol_up_hvr_25x27.png and b/assets/icons/Infrared/ch_down_24x21.png differ diff --git a/assets/icons/Infrared/Vol_down_25x27.png b/assets/icons/Infrared/ch_down_hover_24x21.png similarity index 70% rename from assets/icons/Infrared/Vol_down_25x27.png rename to assets/icons/Infrared/ch_down_hover_24x21.png index d7ae4455..9b840f9c 100644 Binary files a/assets/icons/Infrared/Vol_down_25x27.png and b/assets/icons/Infrared/ch_down_hover_24x21.png differ diff --git a/assets/icons/Infrared/Vol_up_25x27.png b/assets/icons/Infrared/ch_text_31x34.png similarity index 70% rename from assets/icons/Infrared/Vol_up_25x27.png rename to assets/icons/Infrared/ch_text_31x34.png index c4d9e87a..30e0f584 100644 Binary files a/assets/icons/Infrared/Vol_up_25x27.png and b/assets/icons/Infrared/ch_text_31x34.png differ diff --git a/assets/icons/Infrared/ch_up_24x21.png b/assets/icons/Infrared/ch_up_24x21.png new file mode 100644 index 00000000..fa4074d1 Binary files /dev/null and b/assets/icons/Infrared/ch_up_24x21.png differ diff --git a/assets/icons/Infrared/ch_up_hover_24x21.png b/assets/icons/Infrared/ch_up_hover_24x21.png new file mode 100644 index 00000000..944a973f Binary files /dev/null and b/assets/icons/Infrared/ch_up_hover_24x21.png differ diff --git a/assets/icons/Infrared/Down_25x27.png b/assets/icons/Infrared/cool_30x51.png similarity index 73% rename from assets/icons/Infrared/Down_25x27.png rename to assets/icons/Infrared/cool_30x51.png index c1309777..38a8014b 100644 Binary files a/assets/icons/Infrared/Down_25x27.png and b/assets/icons/Infrared/cool_30x51.png differ diff --git a/assets/icons/Infrared/dry_19x20.png b/assets/icons/Infrared/dry_19x20.png new file mode 100644 index 00000000..c689c067 Binary files /dev/null and b/assets/icons/Infrared/dry_19x20.png differ diff --git a/assets/icons/Infrared/dry_hover_19x20.png b/assets/icons/Infrared/dry_hover_19x20.png new file mode 100644 index 00000000..5b7196ae Binary files /dev/null and b/assets/icons/Infrared/dry_hover_19x20.png differ diff --git a/assets/icons/Infrared/dry_text_15x5.png b/assets/icons/Infrared/dry_text_15x5.png new file mode 100644 index 00000000..7696e1fc Binary files /dev/null and b/assets/icons/Infrared/dry_text_15x5.png differ diff --git a/assets/icons/Infrared/fahren_24x23.png b/assets/icons/Infrared/fahren_24x23.png new file mode 100644 index 00000000..d6f55e80 Binary files /dev/null and b/assets/icons/Infrared/fahren_24x23.png differ diff --git a/assets/icons/Infrared/fahren_hover_24x23.png b/assets/icons/Infrared/fahren_hover_24x23.png new file mode 100644 index 00000000..db922c55 Binary files /dev/null and b/assets/icons/Infrared/fahren_hover_24x23.png differ diff --git a/assets/icons/Infrared/Down_hvr_25x27.png b/assets/icons/Infrared/heat_30x51.png similarity index 73% rename from assets/icons/Infrared/Down_hvr_25x27.png rename to assets/icons/Infrared/heat_30x51.png index 76d18192..aca27c7c 100644 Binary files a/assets/icons/Infrared/Down_hvr_25x27.png and b/assets/icons/Infrared/heat_30x51.png differ diff --git a/assets/icons/Infrared/hourglass0_24x24.png b/assets/icons/Infrared/hourglass0_24x24.png new file mode 100644 index 00000000..a382d84e Binary files /dev/null and b/assets/icons/Infrared/hourglass0_24x24.png differ diff --git a/assets/icons/Infrared/hourglass1_24x24.png b/assets/icons/Infrared/hourglass1_24x24.png new file mode 100644 index 00000000..b4cc7b46 Binary files /dev/null and b/assets/icons/Infrared/hourglass1_24x24.png differ diff --git a/assets/icons/Infrared/hourglass2_24x24.png b/assets/icons/Infrared/hourglass2_24x24.png new file mode 100644 index 00000000..d2c3709f Binary files /dev/null and b/assets/icons/Infrared/hourglass2_24x24.png differ diff --git a/assets/icons/Infrared/hourglass3_24x24.png b/assets/icons/Infrared/hourglass3_24x24.png new file mode 100644 index 00000000..e7be1e99 Binary files /dev/null and b/assets/icons/Infrared/hourglass3_24x24.png differ diff --git a/assets/icons/Infrared/hourglass4_24x24.png b/assets/icons/Infrared/hourglass4_24x24.png new file mode 100644 index 00000000..49eee2f5 Binary files /dev/null and b/assets/icons/Infrared/hourglass4_24x24.png differ diff --git a/assets/icons/Infrared/hourglass5_24x24.png b/assets/icons/Infrared/hourglass5_24x24.png new file mode 100644 index 00000000..90e1d4b4 Binary files /dev/null and b/assets/icons/Infrared/hourglass5_24x24.png differ diff --git a/assets/icons/Infrared/hourglass6_24x24.png b/assets/icons/Infrared/hourglass6_24x24.png new file mode 100644 index 00000000..e68c744f Binary files /dev/null and b/assets/icons/Infrared/hourglass6_24x24.png differ diff --git a/assets/icons/Infrared/max_24x23.png b/assets/icons/Infrared/max_24x23.png new file mode 100644 index 00000000..d4163a65 Binary files /dev/null and b/assets/icons/Infrared/max_24x23.png differ diff --git a/assets/icons/Infrared/max_hover_24x23.png b/assets/icons/Infrared/max_hover_24x23.png new file mode 100644 index 00000000..65f97b0c Binary files /dev/null and b/assets/icons/Infrared/max_hover_24x23.png differ diff --git a/assets/icons/Infrared/mute_19x20.png b/assets/icons/Infrared/mute_19x20.png new file mode 100644 index 00000000..410e88ac Binary files /dev/null and b/assets/icons/Infrared/mute_19x20.png differ diff --git a/assets/icons/Infrared/mute_hover_19x20.png b/assets/icons/Infrared/mute_hover_19x20.png new file mode 100644 index 00000000..e9a5b351 Binary files /dev/null and b/assets/icons/Infrared/mute_hover_19x20.png differ diff --git a/assets/icons/Infrared/mute_text_19x5.png b/assets/icons/Infrared/mute_text_19x5.png new file mode 100644 index 00000000..fa2d042a Binary files /dev/null and b/assets/icons/Infrared/mute_text_19x5.png differ diff --git a/assets/icons/Infrared/next_19x20.png b/assets/icons/Infrared/next_19x20.png new file mode 100644 index 00000000..512b6874 Binary files /dev/null and b/assets/icons/Infrared/next_19x20.png differ diff --git a/assets/icons/Infrared/next_hover_19x20.png b/assets/icons/Infrared/next_hover_19x20.png new file mode 100644 index 00000000..c84bfdb9 Binary files /dev/null and b/assets/icons/Infrared/next_hover_19x20.png differ diff --git a/assets/icons/Infrared/next_text_19x6.png b/assets/icons/Infrared/next_text_19x6.png new file mode 100644 index 00000000..74d53171 Binary files /dev/null and b/assets/icons/Infrared/next_text_19x6.png differ diff --git a/assets/icons/Infrared/off_19x20.png b/assets/icons/Infrared/off_19x20.png new file mode 100644 index 00000000..6d68d7e6 Binary files /dev/null and b/assets/icons/Infrared/off_19x20.png differ diff --git a/assets/icons/Infrared/off_hover_19x20.png b/assets/icons/Infrared/off_hover_19x20.png new file mode 100644 index 00000000..fddd3f91 Binary files /dev/null and b/assets/icons/Infrared/off_hover_19x20.png differ diff --git a/assets/icons/Infrared/off_text_12x5.png b/assets/icons/Infrared/off_text_12x5.png new file mode 100644 index 00000000..500adbf2 Binary files /dev/null and b/assets/icons/Infrared/off_text_12x5.png differ diff --git a/assets/icons/Infrared/pause_19x20.png b/assets/icons/Infrared/pause_19x20.png new file mode 100644 index 00000000..99196d23 Binary files /dev/null and b/assets/icons/Infrared/pause_19x20.png differ diff --git a/assets/icons/Infrared/pause_hover_19x20.png b/assets/icons/Infrared/pause_hover_19x20.png new file mode 100644 index 00000000..33e7d8eb Binary files /dev/null and b/assets/icons/Infrared/pause_hover_19x20.png differ diff --git a/assets/icons/Infrared/pause_text_23x5.png b/assets/icons/Infrared/pause_text_23x5.png new file mode 100644 index 00000000..72c7b040 Binary files /dev/null and b/assets/icons/Infrared/pause_text_23x5.png differ diff --git a/assets/icons/Infrared/play_19x20.png b/assets/icons/Infrared/play_19x20.png new file mode 100644 index 00000000..880e977d Binary files /dev/null and b/assets/icons/Infrared/play_19x20.png differ diff --git a/assets/icons/Infrared/Vol_down_hvr_25x27.png b/assets/icons/Infrared/play_hover_19x20.png similarity index 70% rename from assets/icons/Infrared/Vol_down_hvr_25x27.png rename to assets/icons/Infrared/play_hover_19x20.png index c556a037..4c837a14 100644 Binary files a/assets/icons/Infrared/Vol_down_hvr_25x27.png and b/assets/icons/Infrared/play_hover_19x20.png differ diff --git a/assets/icons/Infrared/play_text_19x5.png b/assets/icons/Infrared/play_text_19x5.png new file mode 100644 index 00000000..c5f067bc Binary files /dev/null and b/assets/icons/Infrared/play_text_19x5.png differ diff --git a/assets/icons/Infrared/power_19x20.png b/assets/icons/Infrared/power_19x20.png new file mode 100644 index 00000000..12b92797 Binary files /dev/null and b/assets/icons/Infrared/power_19x20.png differ diff --git a/assets/icons/Infrared/power_hover_19x20.png b/assets/icons/Infrared/power_hover_19x20.png new file mode 100644 index 00000000..3a41249f Binary files /dev/null and b/assets/icons/Infrared/power_hover_19x20.png differ diff --git a/assets/icons/Infrared/power_text_24x5.png b/assets/icons/Infrared/power_text_24x5.png new file mode 100644 index 00000000..88fff8e3 Binary files /dev/null and b/assets/icons/Infrared/power_text_24x5.png differ diff --git a/assets/icons/Infrared/prev_19x20.png b/assets/icons/Infrared/prev_19x20.png new file mode 100644 index 00000000..8d17cec5 Binary files /dev/null and b/assets/icons/Infrared/prev_19x20.png differ diff --git a/assets/icons/Infrared/prev_hover_19x20.png b/assets/icons/Infrared/prev_hover_19x20.png new file mode 100644 index 00000000..be9dce70 Binary files /dev/null and b/assets/icons/Infrared/prev_hover_19x20.png differ diff --git a/assets/icons/Infrared/prev_text_19x5.png b/assets/icons/Infrared/prev_text_19x5.png new file mode 100644 index 00000000..473b8974 Binary files /dev/null and b/assets/icons/Infrared/prev_text_19x5.png differ diff --git a/assets/icons/Infrared/vol_ac_text_30x30.png b/assets/icons/Infrared/vol_ac_text_30x30.png new file mode 100644 index 00000000..068266d6 Binary files /dev/null and b/assets/icons/Infrared/vol_ac_text_30x30.png differ diff --git a/assets/icons/Infrared/vol_tv_text_29x34.png b/assets/icons/Infrared/vol_tv_text_29x34.png new file mode 100644 index 00000000..caef54c2 Binary files /dev/null and b/assets/icons/Infrared/vol_tv_text_29x34.png differ diff --git a/assets/icons/Infrared/voldown_24x21.png b/assets/icons/Infrared/voldown_24x21.png new file mode 100644 index 00000000..a80c5959 Binary files /dev/null and b/assets/icons/Infrared/voldown_24x21.png differ diff --git a/assets/icons/Infrared/voldown_hover_24x21.png b/assets/icons/Infrared/voldown_hover_24x21.png new file mode 100644 index 00000000..6bc57c70 Binary files /dev/null and b/assets/icons/Infrared/voldown_hover_24x21.png differ diff --git a/assets/icons/Infrared/volup_24x21.png b/assets/icons/Infrared/volup_24x21.png new file mode 100644 index 00000000..68855275 Binary files /dev/null and b/assets/icons/Infrared/volup_24x21.png differ diff --git a/assets/icons/Infrared/volup_hover_24x21.png b/assets/icons/Infrared/volup_hover_24x21.png new file mode 100644 index 00000000..5d790e79 Binary files /dev/null and b/assets/icons/Infrared/volup_hover_24x21.png differ diff --git a/assets/resources/apps_data/music_player/Marble_Machine.fmf b/assets/resources/apps_data/music_player/Marble_Machine.fmf deleted file mode 100644 index 7403c9a0..00000000 --- a/assets/resources/apps_data/music_player/Marble_Machine.fmf +++ /dev/null @@ -1,6 +0,0 @@ -Filetype: Flipper Music Format -Version: 0 -BPM: 130 -Duration: 8 -Octave: 5 -Notes: E6, P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6, 4P, E, B, 4P, E, A, G, A, E, B, P, G, A, D6, 4P, D, B, 4P, D, A, G, A, D, F#, P, G, A, D6, 4P, F#, B, 4P, F#, D6, C6, B, F#, A, P, G, F#, E, P, C, E, B, B4, C, D, D6, C6, B, F#, A, P, G, A, E6 diff --git a/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt b/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt deleted file mode 100644 index 908889ae..00000000 --- a/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt +++ /dev/null @@ -1,41 +0,0 @@ - -## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic - -# key1/Kc from PicoPass 2k documentation -7665544332211000 -# SAGEM -0123456789ABCDEF -# PicoPass Default Exchange Key -5CBCF1DA45D5FB4F -# From HID multiclassSE reader -31ad7ebd2f282168 -# From pastebin: https://pastebin.com/uHqpjiuU -6EFD46EFCBB3C875 -E033CA419AEE43F9 - -# default picopass KD / Page 0 / Book 1 -FDCB5A52EA8F3090 -237FF9079863DF44 -5ADC25FB27181D32 -83B881F2936B2E49 -43644E61EE866BA5 -897034143D016080 -82D17B44C0122963 -4895CA7DE65E2025 -DADAD4C57BE271B7 -E41E9EDEF5719ABF -293D275EC3AF9C7F -C3C169251B8A70FB -F41DAF58B20C8B91 -28877A609EC0DD2B -66584C91EE80D5E5 -C1B74D7478053AE2 - -# default iCLASS RFIDeas -6B65797374726B72 - -# CTF key -5C100DF7042EAE64 - -# iCopy-X DRM key (iCE product) -2020666666668888 diff --git a/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt b/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt deleted file mode 100644 index 46808ef6..00000000 --- a/assets/resources/apps_data/picopass/assets/iclass_standard_dict.txt +++ /dev/null @@ -1,47 +0,0 @@ - -## From https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/iclass_default_keys.dic - -# AA1 -AEA684A6DAB23278 -# key1/Kc from PicoPass 2k documentation -7665544332211000 -# SAGEM -0123456789ABCDEF -# from loclass demo file. -5b7c62c491c11b39 -# Kd from PicoPass 2k documentation -F0E1D2C3B4A59687 -# PicoPass Default Exchange Key -5CBCF1DA45D5FB4F -# From HID multiclassSE reader -31ad7ebd2f282168 -# From pastebin: https://pastebin.com/uHqpjiuU -6EFD46EFCBB3C875 -E033CA419AEE43F9 - -# iCopy-x DRM keys -# iCL tags -2020666666668888 -# iCS tags reversed from the SOs -6666202066668888 - -# default picopass KD / Page 0 / Book 1 -FDCB5A52EA8F3090 -237FF9079863DF44 -5ADC25FB27181D32 -83B881F2936B2E49 -43644E61EE866BA5 -897034143D016080 -82D17B44C0122963 -4895CA7DE65E2025 -DADAD4C57BE271B7 -E41E9EDEF5719ABF -293D275EC3AF9C7F -C3C169251B8A70FB -F41DAF58B20C8B91 -28877A609EC0DD2B -66584C91EE80D5E5 -C1B74D7478053AE2 - -# default iCLASS RFIDeas -6B65797374726B72 diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index a223c97c..a640b9a5 100644 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,1675 +1,1676 @@ Filetype: IR library file Version: 1 -# +# name: Power type: parsed protocol: SIRC address: 01 00 00 00 command: 15 00 00 00 -# +# name: Power type: parsed protocol: SIRC address: 10 00 00 00 command: 15 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 08 00 00 00 command: 05 00 00 00 -# +# name: Vol_up type: parsed protocol: NEC address: 08 00 00 00 command: 00 00 00 00 -# +# name: Vol_dn type: parsed protocol: NEC address: 08 00 00 00 command: 01 00 00 00 -# +# name: Ch_next type: parsed protocol: NEC address: 08 00 00 00 command: 02 00 00 00 -# +# name: Ch_prev type: parsed protocol: NEC address: 08 00 00 00 command: 03 00 00 00 -# +# name: Mute type: parsed protocol: NEC address: 08 00 00 00 command: 0B 00 00 00 -# +# name: Power type: parsed protocol: NECext 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 -# +# name: Vol_dn type: parsed protocol: NECext address: 00 DF 00 00 command: 4F 00 00 00 -# +# name: Ch_next type: parsed protocol: NECext address: 00 DF 00 00 command: 09 00 00 00 -# +# name: Ch_prev type: parsed protocol: NECext address: 00 DF 00 00 command: 05 00 00 00 -# +# name: Mute type: parsed protocol: NECext 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 -# +# name: Mute type: parsed protocol: Samsung32 address: 0E 00 00 00 command: 0D 00 00 00 -# +# name: Vol_up type: parsed protocol: Samsung32 address: 0E 00 00 00 command: 14 00 00 00 -# +# name: Vol_dn type: parsed protocol: Samsung32 address: 0E 00 00 00 command: 15 00 00 00 -# +# name: Ch_next type: parsed protocol: Samsung32 address: 0E 00 00 00 command: 12 00 00 00 -# +# name: Ch_prev type: parsed protocol: Samsung32 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 -# +# name: Power type: parsed protocol: Samsung32 address: 07 00 00 00 command: 02 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 address: 07 00 00 00 command: E6 00 00 00 -# +# name: Vol_up type: parsed protocol: Samsung32 address: 07 00 00 00 command: 07 00 00 00 -# +# name: Vol_dn type: parsed protocol: Samsung32 address: 07 00 00 00 command: 0B 00 00 00 -# +# name: Ch_next type: parsed protocol: Samsung32 address: 07 00 00 00 command: 12 00 00 00 -# +# name: Ch_prev type: parsed protocol: Samsung32 address: 07 00 00 00 command: 10 00 00 00 -# +# name: Mute type: parsed protocol: Samsung32 address: 07 00 00 00 command: 0F 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 50 00 00 00 command: 17 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 40 00 00 00 command: 12 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 31 49 00 00 command: 63 00 00 00 -# +# name: Power type: parsed protocol: NEC 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 -# +# name: Power type: parsed protocol: NECext address: 83 7A 00 00 command: 08 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 53 00 00 00 command: 17 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 18 18 00 00 command: C0 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 38 00 00 00 command: 10 00 00 00 -# +# name: Power type: parsed protocol: NEC address: AA 00 00 00 command: C5 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 04 00 00 00 command: 08 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 18 00 00 00 command: 08 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 71 00 00 00 command: 08 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 6F 00 00 command: 0A 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 48 00 00 00 command: 00 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 7B 00 00 command: 13 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 address: 0E 00 00 00 command: 14 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 7E 00 00 command: 18 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 50 00 00 00 command: 08 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 75 00 00 command: 0A 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 57 00 00 command: 0A 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 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 -# +# name: Power type: parsed protocol: NECext address: 85 46 00 00 command: 12 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 address: 05 00 00 00 command: 02 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 command: 0F 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 00 00 00 00 command: 01 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 00 00 00 00 command: 01 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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: 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.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.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.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: parsed protocol: RC5 address: 00 00 00 00 command: 0C 00 00 00 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: NEC42 address: 7B 00 00 00 command: 00 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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.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.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.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.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.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: parsed protocol: RC5 address: 00 00 00 00 command: 0C 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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.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.330000 data: 10726 41047 10727 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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.330000 data: 1192 1012 6649 26844 1192 1013 6648 -# +# name: Power type: raw frequency: 38000 duty_cycle: 0.330000 data: 3134 6105 6263 82963 3134 6105 6263 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: RC5 address: 00 00 00 00 command: 20 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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.330000 data: 4558 4576 558 596 565 97881 4554 4579 565 589 562 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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: 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.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.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.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.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.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.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.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.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.330000 data: 366 202 867 527 170 130516 343 227 863 529 168 -# +# name: Power type: raw frequency: 38000 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.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.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.330000 data: 599 257 975 317 177 130649 308 228 974 319 175 -# +# name: Power type: raw frequency: 38000 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.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.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.330000 data: 1318 225 177 130305 1609 231 171 -# +# name: Power type: raw frequency: 38000 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.330000 data: 203 272 1215 302 171 130229 1423 275 178 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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.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.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.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.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.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.330000 data: 565 233 653 313 170 130328 752 235 233 107 229 398 177 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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.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: parsed protocol: NECext address: 83 7A 00 00 command: 08 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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.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.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.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.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.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: parsed protocol: RC5 address: 02 00 00 00 command: 0C 00 00 00 -# +# name: Power type: raw frequency: 38000 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 -# +# name: Power type: parsed protocol: NEC address: 60 00 00 00 command: 03 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 60 00 00 00 command: 00 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 42 00 00 00 command: 01 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 50 AD 00 00 command: 00 00 00 00 -# +# name: Power type: parsed protocol: NECext 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 -# +# name: Power type: parsed protocol: Samsung32 address: 06 00 00 00 command: 0F 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 08 00 00 00 command: 12 00 00 00 -# +# name: Power type: parsed protocol: Samsung32 address: 08 00 00 00 command: 0B 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 83 55 00 00 command: C2 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 00 00 00 00 command: 51 00 00 00 -# +# name: Power type: parsed protocol: NECext 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 -# +# name: Power type: parsed protocol: Samsung32 address: 16 00 00 00 command: 0F 00 00 00 -# +# name: Power type: parsed protocol: NEC address: 01 00 00 00 command: 01 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 80 68 00 00 command: 49 00 00 00 -# +# name: Power type: parsed protocol: NECext address: 86 02 00 00 command: 49 00 00 00 -# +# name: Power type: parsed protocol: SIRC address: 01 00 00 00 command: 15 00 00 00 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: Kaseikyo address: 80 02 20 00 command: D0 03 00 00 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: RC5 address: 00 00 00 00 command: 0C 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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: parsed protocol: NECext address: 87 22 00 00 command: E0 1F 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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: parsed protocol: NEC42 address: 1C 01 00 00 command: 12 00 00 00 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: NEC address: 38 00 00 00 command: 12 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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: parsed protocol: NECext address: 18 18 00 00 command: C0 3F 00 00 -# +# name: Power type: raw frequency: 38000 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: parsed protocol: SIRC address: 01 00 00 00 command: 2F 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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.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: 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.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.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.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.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: parsed protocol: NEC address: 15 00 00 00 command: 12 00 00 00 -# +# name: Power type: raw frequency: 38000 duty_cycle: 0.330000 data: 1144 1010 6795 26754 1151 997 6798 -# +# name: Power type: raw frequency: 38000 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.330000 data: 170 46238 169 -# +# name: Power type: raw frequency: 38000 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.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.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.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: parsed protocol: NEC address: 10 00 00 00 command: EF 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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: 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.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.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.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.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.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.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: 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.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.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.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.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.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: parsed protocol: NEC address: 00 00 00 00 command: 0B 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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: 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.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: 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.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: parsed protocol: NEC address: AA 00 00 00 command: A7 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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.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: 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.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.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.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: 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.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.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: 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.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.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: 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.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.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: parsed protocol: NEC address: 83 00 00 00 command: 08 00 00 00 -# +# name: Power type: raw frequency: 38000 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.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 type: parsed protocol: RC5 address: 01 00 00 00 command: 0C 00 00 00 -# +# name: Mute type: parsed protocol: RC5 address: 01 00 00 00 command: 0D 00 00 00 -# +# name: Vol_up type: parsed protocol: RC5 address: 01 00 00 00 command: 10 00 00 00 -# +# name: Vol_dn type: parsed protocol: RC5 address: 01 00 00 00 command: 11 00 00 00 -# +# name: Ch_next type: parsed protocol: RC5 address: 01 00 00 00 command: 20 00 00 00 -# +# name: Ch_prev 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 @@ -1681,77 +1682,117 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3462 1592 490 332 513 1200 489 331 514 1201 489 355 490 1201 489 356 512 1178 489 356 512 1178 512 334 487 1202 488 1202 488 357 512 1178 512 334 486 1203 487 1202 488 1203 487 1204 486 383 461 1228 488 357 488 357 487 357 487 1203 486 1204 486 359 485 1205 485 360 485 361 484 360 485 360 485 361 484 361 484 361 484 1206 484 360 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 1206 484 361 484 71543 3434 1620 486 359 485 1205 485 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1205 485 1206 484 360 485 1206 484 360 485 1206 484 1206 484 1206 484 1206 484 361 484 1206 484 360 485 360 485 361 484 1206 484 1206 484 360 484 1206 484 360 485 361 484 361 484 360 485 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1207 483 361 484 1206 484 361 484 71543 3435 1619 486 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 484 1205 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 1205 485 1206 484 360 485 1205 485 360 485 360 485 360 485 1205 485 1206 484 360 485 1206 484 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1205 485 360 485 1206 484 360 485 71542 3436 1619 486 358 487 1204 486 359 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 1206 484 1206 484 1206 484 1206 484 360 485 1206 484 360 485 360 485 361 484 1206 484 1206 484 361 484 1206 484 361 484 361 484 361 484 361 484 361 484 361 484 360 485 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 360 485 1206 484 361 484 1206 484 361 484 71542 3437 1618 487 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1206 484 360 485 1205 485 360 485 1206 484 1205 485 1206 484 1205 485 360 485 1205 485 360 485 360 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 1205 485 360 485 -# Model: TCL +# +# TCL +# name: Power type: raw frequency: 38000 duty_cycle: 0.330000 data: 3977 3993 494 1994 495 1995 496 1997 494 1996 495 1004 496 1004 496 1995 496 1004 496 1997 494 1005 495 1995 495 1007 493 1006 494 1006 494 1005 495 1007 493 1997 494 1995 496 1004 496 1995 496 1005 495 1995 496 1003 497 1995 496 8467 3980 3993 494 1994 495 1996 495 1997 494 1995 496 1004 496 1006 494 1995 496 1004 496 1996 495 1004 496 1996 495 1005 495 1005 495 1004 496 1005 495 1005 495 1996 495 1995 496 1005 495 1996 495 1004 496 1995 496 1006 569 1920 571 8393 3980 3993 571 1918 572 1922 569 1920 571 1920 571 929 572 929 571 1920 571 929 571 1920 571 929 571 1921 570 930 570 929 571 929 571 929 571 928 572 1920 571 1921 570 930 571 1920 572 930 571 1921 571 929 571 1923 569 8396 3980 3994 570 1921 569 1923 569 1921 571 1920 572 929 572 930 571 1921 570 930 571 1922 570 930 571 1921 570 930 570 930 571 929 571 929 571 929 572 1922 570 1921 570 931 570 1922 570 930 571 1922 569 931 570 1921 570 -# +# name: Vol_up type: raw frequency: 38000 duty_cycle: 0.330000 data: 3979 3995 493 1994 496 1997 495 1999 492 1999 492 1006 495 1008 493 1998 493 1006 494 1997 495 1999 493 1997 494 1998 493 1006 495 1007 493 1005 495 1006 495 2025 467 1998 494 1006 494 1996 495 1006 494 1005 495 1006 494 1007 493 8468 3979 3995 492 1995 495 1999 492 1997 494 1997 494 1007 493 1006 494 1997 494 1006 494 1997 494 1996 571 1923 569 1921 570 930 570 929 571 931 569 931 575 1916 570 1920 571 930 570 1922 570 930 571 930 570 930 576 924 576 -# +# name: Vol_dn type: raw frequency: 38000 duty_cycle: 0.330000 data: 3951 3994 494 1997 493 1998 494 1998 493 1998 493 1005 496 1005 496 1996 495 1005 495 1997 495 1996 495 1996 495 1006 494 1005 495 1006 494 1005 495 1006 494 1996 495 1998 493 1005 495 1997 494 1008 492 1006 494 1006 494 1997 494 8471 3977 3996 493 1996 493 1997 494 1998 493 1997 494 1006 494 1007 493 1997 494 1009 492 1996 495 1996 495 1997 494 1006 494 1006 494 1006 494 1006 494 1006 494 1997 493 1997 494 1006 494 1996 494 1005 495 1004 495 1006 494 1996 494 -# +# name: Ch_next type: raw frequency: 38000 duty_cycle: 0.330000 data: 3978 3994 494 1995 495 1996 495 1996 495 1996 495 1006 494 1004 497 1997 494 1005 495 1997 520 1970 577 923 578 1914 577 924 576 924 576 925 575 924 576 1914 577 1915 576 924 576 1914 577 924 576 923 577 1915 576 926 574 8388 3978 3993 576 1913 576 1915 576 1915 576 1917 574 923 577 923 577 1943 548 925 575 1916 576 1915 575 924 576 1915 576 925 575 927 573 925 575 926 574 1916 574 1918 573 927 573 1918 573 928 572 927 573 1918 573 926 574 8389 4006 3966 572 1918 571 1919 572 1918 573 1920 570 929 571 929 571 1922 569 928 571 1920 571 1921 570 928 572 1919 572 929 571 929 571 929 571 929 571 1921 570 1921 521 980 569 1921 521 981 519 979 521 1971 520 979 521 -# +# name: Ch_prev type: raw frequency: 38000 duty_cycle: 0.330000 data: 3979 3994 494 1995 495 1997 494 1996 495 1998 493 1005 495 1006 494 1997 494 1005 495 1996 495 1995 496 1005 495 1005 495 1006 494 1005 495 1004 496 1005 495 1997 494 1997 494 1004 496 1996 495 1005 495 1005 495 1997 494 1996 495 8467 3976 3991 496 1995 495 1996 494 1994 496 1996 494 1005 495 1005 495 1996 495 1005 495 1995 495 1995 496 1006 494 1005 495 1006 494 1005 495 1004 496 1006 494 1994 496 1996 494 1005 495 1995 495 1004 496 1004 496 1995 495 1996 494 -# +# name: Mute type: raw frequency: 38000 duty_cycle: 0.330000 data: 3981 3992 495 1994 495 1995 496 1996 494 1996 495 1005 495 1006 494 1995 495 1997 494 1996 495 1996 494 1997 494 1996 495 1006 494 1005 495 1004 496 1005 495 1995 496 1994 496 1005 495 1004 496 1005 495 1006 494 1004 496 1006 494 8466 3978 3991 495 1994 495 1997 493 1994 496 1995 495 1004 496 1004 496 1996 494 1997 493 1996 494 1995 495 1995 495 1997 493 1004 495 1004 495 1006 494 1005 494 1998 491 1996 494 1006 494 1004 496 1006 494 1006 493 1005 495 1005 571 -# -# Thomson Remote -# Model RC3000E02 +# +# Thomson RC3000E02 +# name: Power type: parsed protocol: RCA address: 0F 00 00 00 command: 54 00 00 00 -# +# name: Vol_up type: parsed protocol: RCA address: 0F 00 00 00 command: F4 00 00 00 -# +# name: Vol_dn type: parsed protocol: RCA address: 0F 00 00 00 command: 74 00 00 00 -# +# name: Ch_next type: parsed protocol: RCA address: 0F 00 00 00 command: B4 00 00 00 -# +# name: Ch_prev type: parsed protocol: RCA address: 0F 00 00 00 command: 34 00 00 00 -# +# name: Mute type: parsed protocol: RCA address: 0F 00 00 00 command: FC 00 00 00 +# +# VOX Electronics 43ADS316B +# +name: Power +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 0B 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 13 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 12 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 17 00 00 00 +# +name: Ch_next +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 11 00 00 00 +# +name: Ch_prev +type: parsed +protocol: NEC +address: 40 00 00 00 +command: 10 00 00 00 diff --git a/documentation/fbt.md b/documentation/fbt.md index 1ab67b4e..02de2949 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -46,6 +46,8 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio `fbt` includes basic development environment configuration for VS Code. Run `./fbt vscode_dist` to deploy it. That will copy the initial environment configuration to the `.vscode` folder. After that, you can use that configuration by starting VS Code and choosing the firmware root folder in the "File > Open Folder" menu. +To use language servers other than the default VS Code C/C++ language server, use `./fbt vscode_dist LANG_SERVER=` instead. Currently `fbt` supports the default language server (`cpptools`) and `clangd`. + - On the first start, you'll be prompted to install recommended plugins. We highly recommend installing them for the best development experience. _You can find a list of them in `.vscode/extensions.json`._ - Basic build tasks are invoked in the Ctrl+Shift+B menu. - Debugging requires a supported probe. That includes: @@ -64,7 +66,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `fap_dist` - build external plugins & publish to the `dist` folder. - `updater_package`, `updater_minpackage` - build a self-update package. The minimal version only includes the firmware's DFU file; the full version also includes a radio stack & resources for the SD card. - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper. -- `flash` - flash the attached device with OpenOCD over ST-Link. +- `flash` - flash the attached device over SWD interface with supported probes. Probe is detected automatically; you can override it with `SWD_TRANSPORT=...` variable. If multiple probes are attached, you can specify the serial number of the probe to use with `SWD_TRANSPORT_SERIAL=...`. - `flash_usb`, `flash_usb_full` - build, upload and install the update package to the device over USB. See details on `updater_package` and `updater_minpackage`. - `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded. - `debug_other`, `debug_other_blackmagic` - attach GDB without loading any `.elf`. It will allow you to manually add external `.elf` files with `add-symbol-file` in GDB. @@ -73,7 +75,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board). - `openocd` - just start OpenOCD. - `get_blackmagic` - output the blackmagic address in the GDB remote format. Useful for IDE integration. -- `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `OPENOCD_ADAPTER_SERIAL=...`. +- `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `SWD_TRANSPORT_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 available on your system's `PATH`. @@ -86,9 +88,8 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `fap_snake_game`, etc. - build single app as `.fap` by its application ID. - Check out [`--extra-ext-apps`](#command-line-parameters) for force adding extra apps to external build. - `fap_snake_game_list`, etc - generate source + assembler listing for app's `.fap`. -- `flash`, `firmware_flash` - flash the current version to the attached device with OpenOCD over ST-Link. +- `flash`, `firmware_flash` - flash the current version to the attached device over SWD. - `jflash` - flash the current version to the attached device with JFlash using a J-Link probe. The JFlash executable must be on your `$PATH`. -- `flash_blackmagic` - flash the current version to the attached device with a Blackmagic probe. - `firmware_all`, `updater_all` - build a basic set of binaries. - `firmware_list`, `updater_list` - generate source + assembler listing. - `firmware_cdb`, `updater_cdb` - generate a `compilation_database.json` file for external tools and IDEs. It can be created without actually building the firmware. diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index eab140d5..a61679bc 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,35.0,, +Version,+,35.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -557,6 +557,7 @@ Function,+,button_menu_get_view,View*,ButtonMenu* Function,+,button_menu_reset,void,ButtonMenu* Function,+,button_menu_set_header,void,"ButtonMenu*, const char*" Function,+,button_menu_set_selected_item,void,"ButtonMenu*, uint32_t" +Function,+,button_panel_add_icon,void,"ButtonPanel*, uint16_t, uint16_t, const Icon*" Function,+,button_panel_add_item,void,"ButtonPanel*, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t, const Icon*, const Icon*, ButtonItemCallback, void*" Function,+,button_panel_add_label,void,"ButtonPanel*, uint16_t, uint16_t, Font, const char*" Function,+,button_panel_alloc,ButtonPanel*, @@ -1038,18 +1039,18 @@ Function,+,furi_hal_cortex_timer_is_expired,_Bool,FuriHalCortexTimer Function,+,furi_hal_cortex_timer_wait,void,FuriHalCortexTimer Function,+,furi_hal_crypto_ctr,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t +Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" +Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" +Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t +Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_gcm,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*, _Bool" Function,+,furi_hal_crypto_gcm_decrypt_and_verify,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, const uint8_t*" Function,+,furi_hal_crypto_gcm_encrypt_and_tag,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*" Function,-,furi_hal_crypto_init,void, Function,+,furi_hal_crypto_load_key,_Bool,"const uint8_t*, const uint8_t*" -Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" -Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" -Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t Function,+,furi_hal_crypto_unload_key,_Bool, -Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" -Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, Function,+,furi_hal_debug_is_gdb_session_active,_Bool, @@ -1471,7 +1472,6 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,-,gui_active_view_port_count,size_t,"Gui*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/firmware/targets/f18/furi_hal/furi_hal_resources.c index 32c9b619..63da03e0 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.c @@ -128,19 +128,22 @@ void furi_hal_resources_init_early() { furi_hal_resources_init_input_pins(GpioModeInput); + // Explicit, surviving reset, pulls + LL_PWR_EnablePUPDCfg(); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker + // SD Card stepdown control furi_hal_gpio_write(&gpio_periph_power, 1); furi_hal_gpio_init(&gpio_periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); // Display pins - furi_hal_gpio_write(&gpio_display_rst_n, 1); + furi_hal_gpio_write(&gpio_display_rst_n, 0); furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull); - furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - - // Pullup display reset pin for shutdown - SET_BIT(PWR->PUCRB, gpio_display_rst_n.pin); - CLEAR_BIT(PWR->PDCRB, gpio_display_rst_n.pin); - SET_BIT(PWR->CR3, PWR_CR3_APC); + LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_0); // gpio_display_rst_n + furi_hal_gpio_write(&gpio_display_di, 0); + furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_1); // gpio_display_di // Hard reset USB furi_hal_gpio_write(&gpio_usb_dm, 1); @@ -182,18 +185,6 @@ void furi_hal_resources_init() { // Button pins furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall); - // Explicit pulls pins - LL_PWR_EnablePUPDCfg(); - LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker - LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro - - // Display pins - furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_display_rst_n, 0); - - furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_display_di, 0); - // SD pins furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_sdcard_cd, 0); @@ -225,7 +216,7 @@ void furi_hal_resources_init() { } int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) { - // TODO: describe second ROW + // TODO FL-3500: describe second ROW if(gpio == &gpio_ext_pa7) return 2; else if(gpio == &gpio_ext_pa6) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 8efe980a..8baec5a8 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,+,35.0,, +Version,+,35.1,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -618,6 +618,7 @@ Function,+,button_menu_get_view,View*,ButtonMenu* Function,+,button_menu_reset,void,ButtonMenu* Function,+,button_menu_set_header,void,"ButtonMenu*, const char*" Function,+,button_menu_set_selected_item,void,"ButtonMenu*, uint32_t" +Function,+,button_panel_add_icon,void,"ButtonPanel*, uint16_t, uint16_t, const Icon*" Function,+,button_panel_add_item,void,"ButtonPanel*, uint32_t, uint16_t, uint16_t, uint16_t, uint16_t, const Icon*, const Icon*, ButtonItemCallback, void*" Function,+,button_panel_add_label,void,"ButtonPanel*, uint16_t, uint16_t, Font, const char*" Function,+,button_panel_alloc,ButtonPanel*, @@ -1109,18 +1110,18 @@ Function,+,furi_hal_cortex_timer_is_expired,_Bool,FuriHalCortexTimer Function,+,furi_hal_cortex_timer_wait,void,FuriHalCortexTimer Function,+,furi_hal_crypto_ctr,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t" +Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t +Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" +Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" +Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t +Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t" Function,+,furi_hal_crypto_gcm,_Bool,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*, _Bool" Function,+,furi_hal_crypto_gcm_decrypt_and_verify,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, const uint8_t*" Function,+,furi_hal_crypto_gcm_encrypt_and_tag,FuriHalCryptoGCMState,"const uint8_t*, const uint8_t*, const uint8_t*, size_t, const uint8_t*, uint8_t*, size_t, uint8_t*" Function,-,furi_hal_crypto_init,void, Function,+,furi_hal_crypto_load_key,_Bool,"const uint8_t*, const uint8_t*" -Function,+,furi_hal_crypto_enclave_store_key,_Bool,"FuriHalCryptoKey*, uint8_t*" -Function,+,furi_hal_crypto_enclave_load_key,_Bool,"uint8_t, const uint8_t*" -Function,+,furi_hal_crypto_enclave_unload_key,_Bool,uint8_t Function,+,furi_hal_crypto_unload_key,_Bool, -Function,+,furi_hal_crypto_enclave_verify,_Bool,"uint8_t*, uint8_t*" -Function,+,furi_hal_crypto_enclave_ensure_key,_Bool,uint8_t Function,+,furi_hal_debug_disable,void, Function,+,furi_hal_debug_enable,void, Function,+,furi_hal_debug_is_gdb_session_active,_Bool, @@ -1642,7 +1643,6 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* -Function,-,gui_active_view_port_count,size_t,"Gui*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 1cb5501d..746df71c 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -222,7 +222,7 @@ bool ble_glue_wait_for_c2_start(int32_t timeout) { bool started = false; do { - // TODO: use mutex? + // TODO FL-3505: use mutex? started = ble_glue->status == BleGlueStatusC2Started; if(!started) { timeout--; diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 9b6a44f6..e0539c34 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -14,7 +14,7 @@ void flipper_gatt_characteristic_init( furi_assert(char_instance); // Copy the descriptor to the instance, since it may point to stack memory - // TODO: only copy if really comes from stack + // TODO FL-3506: only copy if really comes from stack char_instance->characteristic = malloc(sizeof(FlipperGattCharacteristicParams)); memcpy( (void*)char_instance->characteristic, diff --git a/firmware/targets/f7/fatfs/sd_spi_io.c b/firmware/targets/f7/fatfs/sd_spi_io.c index e8e542b3..d420524d 100644 --- a/firmware/targets/f7/fatfs/sd_spi_io.c +++ b/firmware/targets/f7/fatfs/sd_spi_io.c @@ -283,7 +283,7 @@ static SdSpiCmdAnswer cmd_answer.r1 = sd_spi_wait_for_data_and_read(); break; case SdSpiCmdAnswerTypeR1B: - // TODO: can be wrong, at least for SD_CMD12_STOP_TRANSMISSION you need to purge one byte before reading R1 + // TODO FL-3507: can be wrong, at least for SD_CMD12_STOP_TRANSMISSION you need to purge one byte before reading R1 cmd_answer.r1 = sd_spi_wait_for_data_and_read(); // In general this shenenigans seems suspicious, please double check SD specs if you are using SdSpiCmdAnswerTypeR1B @@ -322,7 +322,7 @@ static SdSpiDataResponce sd_spi_get_data_response(uint32_t timeout_ms) { switch(responce & 0x1F) { case SdSpiDataResponceOK: - // TODO: check timings + // TODO FL-3508: check timings sd_spi_deselect_card(); sd_spi_select_card(); @@ -684,7 +684,7 @@ static SdSpiStatus sd_spi_cmd_write_blocks( } // Send dummy byte for NWR timing : one byte between CMD_WRITE and TOKEN - // TODO: check bytes count + // TODO FL-3509: check bytes count sd_spi_write_byte(SD_DUMMY_BYTE); sd_spi_write_byte(SD_DUMMY_BYTE); diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index b249c865..baffde1e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -701,7 +701,9 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { rfalNfcWorker(); state = rfalNfcGetState(); ret = rfalNfcDataExchangeGetStatus(); - if(ret == ERR_BUSY) { + if(ret == ERR_WRONG_STATE) { + return false; + } else if(ret == ERR_BUSY) { if(DWT->CYCCNT - start > timeout_ms * clocks_in_ms) { FURI_LOG_D(TAG, "Timeout during data exchange"); return false; diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.h b/firmware/targets/f7/furi_hal/furi_hal_nfc.h index c87f04a9..f4051926 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.h +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.h @@ -402,7 +402,6 @@ void furi_hal_nfc_ll_txrx_on(); void furi_hal_nfc_ll_txrx_off(); -// TODO rework all pollers with furi_hal_nfc_ll_txrx_bits FuriHalNfcReturn furi_hal_nfc_ll_txrx( uint8_t* txBuf, uint16_t txBufLen, diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 34b26b83..4d52960d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -117,19 +117,23 @@ void furi_hal_resources_init_early() { furi_hal_resources_init_input_pins(GpioModeInput); + // Explicit, surviving reset, pulls + LL_PWR_EnablePUPDCfg(); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_9); // gpio_infrared_tx + // SD Card stepdown control furi_hal_gpio_write(&gpio_periph_power, 1); furi_hal_gpio_init(&gpio_periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); // Display pins - furi_hal_gpio_write(&gpio_display_rst_n, 1); + furi_hal_gpio_write(&gpio_display_rst_n, 0); furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull); + LL_PWR_EnableGPIOPullUp(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_0); // gpio_display_rst_n + furi_hal_gpio_write(&gpio_display_di, 0); furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); - - // Alternative pull configuration for shutdown - SET_BIT(PWR->PUCRB, DISPLAY_RST_Pin); - CLEAR_BIT(PWR->PDCRB, DISPLAY_RST_Pin); - SET_BIT(PWR->CR3, PWR_CR3_APC); + LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_1); // gpio_display_di // Hard reset USB furi_hal_gpio_write(&gpio_usb_dm, 1); @@ -171,19 +175,6 @@ void furi_hal_resources_init() { // Button pins furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall); - // Explicit, surviving reset, pulls - LL_PWR_EnablePUPDCfg(); - LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_9); // gpio_infrared_tx - LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_B, LL_PWR_GPIO_BIT_8); // gpio_speaker - LL_PWR_EnableGPIOPullDown(LL_PWR_GPIO_A, LL_PWR_GPIO_BIT_8); // gpio_vibro - - // Display pins - furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_display_rst_n, 0); - - furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_display_di, 0); - // SD pins furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_sdcard_cd, 0); diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index ac5adefb..bd724f0b 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -207,8 +207,7 @@ bool furi_hal_subghz_rx_pipe_not_empty() { cc1101_read_reg( &furi_hal_spi_bus_handle_subghz, (CC1101_STATUS_RXBYTES) | CC1101_BURST, (uint8_t*)status); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); - // TODO: you can add a buffer overflow flag if needed - if(status->NUM_RXBYTES > 0) { + if((status->NUM_RXBYTES > 0) || (status->RXFIFO_OVERFLOW == 0)) { return true; } else { return false; diff --git a/firmware/targets/f7/src/update.c b/firmware/targets/f7/src/update.c index c6235a15..52030541 100644 --- a/firmware/targets/f7/src/update.c +++ b/firmware/targets/f7/src/update.c @@ -38,7 +38,7 @@ static bool flipper_update_mount_sd() { } static bool flipper_update_init() { - // TODO: Configure missing peripherals properly + // TODO FL-3504: Configure missing peripherals properly furi_hal_bus_enable(FuriHalBusHSEM); furi_hal_bus_enable(FuriHalBusIPCC); furi_hal_bus_enable(FuriHalBusRNG); diff --git a/lib/SConscript b/lib/SConscript index ab78c6ea..907a5a41 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -23,7 +23,7 @@ env.Append( env.Append( CPPPATH=[ "#/", - "#/lib", # TODO: remove! + "#/lib", # TODO FL-3553: remove! "#/lib/mlib", # Ugly hack Dir("../assets/compiled"), diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index 92dbfcd6..4a9feed9 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -69,7 +69,7 @@ static bool bq27220_parameter_check( uint8_t checksum = bq27220_get_checksum(buffer, size + 2); buffer[0] = checksum; - buffer[1] = 4 + size; // TODO: why 4? + buffer[1] = 4 + size; // TODO FL-3519: why 4? if(!furi_hal_i2c_write_mem( handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT)) { FURI_LOG_I(TAG, "CRC write failed"); diff --git a/lib/flipper_application/application_manifest.h b/lib/flipper_application/application_manifest.h index 25e4f8d0..d09ec900 100644 --- a/lib/flipper_application/application_manifest.h +++ b/lib/flipper_application/application_manifest.h @@ -16,7 +16,7 @@ extern "C" { #define FAP_MANIFEST_SUPPORTED_VERSION 1 #define FAP_MANIFEST_MAX_APP_NAME_LENGTH 32 -#define FAP_MANIFEST_MAX_ICON_SIZE 32 // TODO: reduce size? +#define FAP_MANIFEST_MAX_ICON_SIZE 32 // TODO FL-3524: reduce size? #pragma pack(push, 1) diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index 539a48c8..bea7c123 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -1,3 +1,4 @@ +#include "storage/storage.h" #include #include "elf_file.h" #include "elf_file_i.h" @@ -57,6 +58,13 @@ static void address_cache_put(AddressCache_t cache, int symEntry, Elf32_Addr sym /********************************************** ELF ***********************************************/ /**************************************************************************************************/ +static void elf_file_maybe_release_fd(ELFFile* elf) { + if(elf->fd) { + storage_file_free(elf->fd); + elf->fd = NULL; + } +} + static ELFSection* elf_file_get_section(ELFFile* elf, const char* name) { return ELFSectionDict_get(elf->sections, name); } @@ -507,7 +515,7 @@ static SectionType elf_preload_section( #endif // ignore .ARM and .rel.ARM sections - // TODO: how to do it not by name? + // TODO FL-3525: how to do it not by name? // .ARM: type 0x70000001, flags SHF_ALLOC | SHF_LINK_ORDER // .rel.ARM: type 0x9, flags SHT_REL if(str_prefix(name, ".ARM.") || str_prefix(name, ".rel.ARM.") || @@ -764,7 +772,7 @@ void elf_file_free(ELFFile* elf) { free(elf->debug_link_info.debug_link); } - storage_file_free(elf->fd); + elf_file_maybe_release_fd(elf); free(elf); } @@ -792,7 +800,7 @@ bool elf_file_load_section_table(ELFFile* elf) { FuriString* name = furi_string_alloc(); FURI_LOG_D(TAG, "Scan ELF indexs..."); - // TODO: why we start from 1? + // TODO FL-3526: why we start from 1? for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { Elf32_Shdr section_header; @@ -828,7 +836,7 @@ ElfProcessSectionResult elf_process_section( Elf32_Shdr section_header; // find section - // TODO: why we start from 1? + // TODO FL-3526: why we start from 1? for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) { furi_string_reset(section_name); if(!elf_read_section(elf, section_idx, §ion_header, section_name)) { @@ -855,6 +863,7 @@ ElfProcessSectionResult elf_process_section( } ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { + furi_check(elf->fd != NULL); ELFFileLoadStatus status = ELFFileLoadStatusSuccess; ELFSectionDict_it_t it; @@ -895,6 +904,7 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { FURI_LOG_I(TAG, "Total size of loaded sections: %zu", total_size); } + elf_file_maybe_release_fd(elf); return status; } diff --git a/lib/ibutton/ibutton_worker_modes.c b/lib/ibutton/ibutton_worker_modes.c index 1b8e0a3b..83e207de 100644 --- a/lib/ibutton/ibutton_worker_modes.c +++ b/lib/ibutton/ibutton_worker_modes.c @@ -127,7 +127,7 @@ void ibutton_worker_mode_write_blank_tick(iButtonWorker* worker) { furi_assert(worker->key); const bool success = ibutton_protocols_write_blank(worker->protocols, worker->key); - // TODO: pass a proper result to the callback + // TODO FL-3527: pass a proper result to the callback const iButtonWorkerWriteResult result = success ? iButtonWorkerWriteOK : iButtonWorkerWriteNoDetect; if(worker->write_cb != NULL) { @@ -139,7 +139,7 @@ void ibutton_worker_mode_write_copy_tick(iButtonWorker* worker) { furi_assert(worker->key); const bool success = ibutton_protocols_write_copy(worker->protocols, worker->key); - // TODO: pass a proper result to the callback + // TODO FL-3527: pass a proper result to the callback const iButtonWorkerWriteResult result = success ? iButtonWorkerWriteOK : iButtonWorkerWriteNoDetect; if(worker->write_cb != NULL) { diff --git a/lib/ibutton/protocols/blanks/rw1990.c b/lib/ibutton/protocols/blanks/rw1990.c index d3350fcf..f86e43d9 100644 --- a/lib/ibutton/protocols/blanks/rw1990.c +++ b/lib/ibutton/protocols/blanks/rw1990.c @@ -62,7 +62,7 @@ bool rw1990_write_v1(OneWireHost* host, const uint8_t* data, size_t data_size) { onewire_host_write_bit(host, true); furi_delay_us(10000); - // TODO: Better error handling + // TODO FL-3528: Better error handling return rw1990_read_and_compare(host, data, data_size); } @@ -90,6 +90,6 @@ bool rw1990_write_v2(OneWireHost* host, const uint8_t* data, size_t data_size) { onewire_host_write_bit(host, false); furi_delay_us(10000); - // TODO: Better error handling + // TODO Fl-3528: Better error handling return rw1990_read_and_compare(host, data, data_size); } diff --git a/lib/ibutton/protocols/blanks/tm2004.c b/lib/ibutton/protocols/blanks/tm2004.c index ef6f0619..b020a218 100644 --- a/lib/ibutton/protocols/blanks/tm2004.c +++ b/lib/ibutton/protocols/blanks/tm2004.c @@ -21,7 +21,7 @@ bool tm2004_write(OneWireHost* host, const uint8_t* data, size_t data_size) { onewire_host_write(host, data[i]); answer = onewire_host_read(host); - // TODO: check answer CRC + // TODO FL-3529: check answer CRC // pulse indicating that data is correct furi_delay_us(600); @@ -37,6 +37,6 @@ bool tm2004_write(OneWireHost* host, const uint8_t* data, size_t data_size) { } } - // TODO: Better error handling + // TODO FL-3529: Better error handling return i == data_size; } diff --git a/lib/ibutton/protocols/dallas/dallas_common.c b/lib/ibutton/protocols/dallas/dallas_common.c index ebf57e55..6e99a3be 100644 --- a/lib/ibutton/protocols/dallas/dallas_common.c +++ b/lib/ibutton/protocols/dallas/dallas_common.c @@ -149,7 +149,7 @@ bool dallas_common_emulate_search_rom(OneWireSlave* bus, const DallasCommonRomDa if(!onewire_slave_send_bit(bus, !bit)) return false; onewire_slave_receive_bit(bus); - // TODO: check for errors and return if any + // TODO FL-3530: check for errors and return if any } } diff --git a/lib/ibutton/protocols/dallas/protocol_ds1971.c b/lib/ibutton/protocols/dallas/protocol_ds1971.c index a806acb2..b65e6458 100644 --- a/lib/ibutton/protocols/dallas/protocol_ds1971.c +++ b/lib/ibutton/protocols/dallas/protocol_ds1971.c @@ -53,7 +53,7 @@ const iButtonProtocolDallasBase ibutton_protocol_ds1971 = { .name = DS1971_FAMILY_NAME, .read = dallas_ds1971_read, - .write_blank = NULL, // TODO: Implement writing to blank + .write_blank = NULL, // TODO FL-3531: Implement writing to blank .write_copy = dallas_ds1971_write_copy, .emulate = dallas_ds1971_emulate, .save = dallas_ds1971_save, diff --git a/lib/ibutton/protocols/dallas/protocol_ds1992.c b/lib/ibutton/protocols/dallas/protocol_ds1992.c index 0b4d4b34..7440882e 100644 --- a/lib/ibutton/protocols/dallas/protocol_ds1992.c +++ b/lib/ibutton/protocols/dallas/protocol_ds1992.c @@ -73,7 +73,7 @@ bool dallas_ds1992_read(OneWireHost* host, iButtonProtocolData* protocol_data) { bool dallas_ds1992_write_blank(OneWireHost* host, iButtonProtocolData* protocol_data) { DS1992ProtocolData* data = protocol_data; - // TODO: Make this work, currently broken + // TODO FL-3532: Make this work, currently broken return tm2004_write(host, (uint8_t*)data, sizeof(DallasCommonRomData) + DS1992_SRAM_DATA_SIZE); } diff --git a/lib/ibutton/protocols/dallas/protocol_ds1996.c b/lib/ibutton/protocols/dallas/protocol_ds1996.c index 5358b63e..5970a67b 100644 --- a/lib/ibutton/protocols/dallas/protocol_ds1996.c +++ b/lib/ibutton/protocols/dallas/protocol_ds1996.c @@ -159,7 +159,7 @@ static bool dallas_ds1996_command_callback(uint8_t command, void* context) { case DALLAS_COMMON_CMD_MATCH_ROM: case DALLAS_COMMON_CMD_OVERDRIVE_MATCH_ROM: - /* TODO: Match ROM command support */ + /* TODO FL-3533: Match ROM command support */ default: return false; } diff --git a/lib/lfrfid/lfrfid_dict_file.c b/lib/lfrfid/lfrfid_dict_file.c index 7ae84f8b..18bf505f 100644 --- a/lib/lfrfid/lfrfid_dict_file.c +++ b/lib/lfrfid/lfrfid_dict_file.c @@ -17,13 +17,13 @@ bool lfrfid_dict_file_save(ProtocolDict* dict, ProtocolId protocol, const char* if(!flipper_format_file_open_always(file, filename)) break; if(!flipper_format_write_header_cstr(file, LFRFID_DICT_FILETYPE, 1)) break; - // TODO: write comment about protocol types into file + // TODO FL-3517: write comment about protocol types into file if(!flipper_format_write_string_cstr( file, "Key type", protocol_dict_get_name(dict, protocol))) break; - // TODO: write comment about protocol sizes into file + // TODO FL-3517: write comment about protocol sizes into file protocol_dict_get_data(dict, protocol, data, data_size); diff --git a/lib/lfrfid/lfrfid_worker.h b/lib/lfrfid/lfrfid_worker.h index def9f89a..22135097 100644 --- a/lib/lfrfid/lfrfid_worker.h +++ b/lib/lfrfid/lfrfid_worker.h @@ -26,8 +26,8 @@ typedef enum { } LFRFIDWorkerReadType; typedef enum { - LFRFIDWorkerReadSenseStart, // TODO: not implemented - LFRFIDWorkerReadSenseEnd, // TODO: not implemented + LFRFIDWorkerReadSenseStart, // TODO FL-3516: not implemented + LFRFIDWorkerReadSenseEnd, // TODO FL-3516: not implemented LFRFIDWorkerReadSenseCardStart, LFRFIDWorkerReadSenseCardEnd, LFRFIDWorkerReadStartASK, diff --git a/lib/lfrfid/protocols/protocol_hid_ex_generic.c b/lib/lfrfid/protocols/protocol_hid_ex_generic.c index 240128cb..35500ab5 100644 --- a/lib/lfrfid/protocols/protocol_hid_ex_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_ex_generic.c @@ -193,7 +193,7 @@ bool protocol_hid_ex_generic_write_data(ProtocolHIDEx* protocol, void* data) { }; void protocol_hid_ex_generic_render_data(ProtocolHIDEx* protocol, FuriString* result) { - // TODO: parser and render functions + // TODO FL-3518: parser and render functions UNUSED(protocol); furi_string_printf(result, "Generic HID Extended\r\nData: Unknown"); }; diff --git a/lib/lfrfid/tools/bit_lib.c b/lib/lfrfid/tools/bit_lib.c index 54decb3e..e0d0ff40 100644 --- a/lib/lfrfid/tools/bit_lib.c +++ b/lib/lfrfid/tools/bit_lib.c @@ -38,7 +38,7 @@ uint8_t bit_lib_get_bits(const uint8_t* data, size_t position, uint8_t length) { if(shift == 0) { return data[position / 8] >> (8 - length); } else { - // TODO fix read out of bounds + // TODO FL-3534: fix read out of bounds uint8_t value = (data[position / 8] << (shift)); value |= data[position / 8 + 1] >> (8 - shift); value = value >> (8 - length); diff --git a/lib/littlefs b/lib/littlefs index 40dba4a5..611c9b20 160000 --- a/lib/littlefs +++ b/lib/littlefs @@ -1 +1 @@ -Subproject commit 40dba4a556e0d81dfbe64301a6aa4e18ceca896c +Subproject commit 611c9b20db2b99faee261daa7cc9bbe175d3eaca diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 8abf637d..2c92b5bf 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1625,6 +1625,9 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) { } else if(dev_data->protocol == NfcDeviceProtocolEMV) { memset(&dev_data->emv_data, 0, sizeof(EmvData)); } + + furi_string_reset(dev_data->parsed_data); + memset(&dev_data->nfc_data, 0, sizeof(FuriHalNfcDevData)); dev_data->protocol = NfcDeviceProtocolUnknown; furi_string_reset(dev_data->parsed_data); diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 017b06ca..28146328 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -29,7 +29,7 @@ ReturnCode nfcv_inventory(uint8_t* uid) { ReturnCode ret = ERR_NONE; for(int tries = 0; tries < NFCV_COMMAND_RETRIES; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ + /* TODO: needs proper abstraction via furi_hal(_ll)_* */ ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received); if(ret == ERR_NONE) { @@ -89,7 +89,7 @@ ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { FURI_LOG_D(TAG, "Read SYSTEM INFORMATION..."); for(int tries = 0; tries < NFCV_COMMAND_RETRIES; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ + /* TODO: needs proper abstraction via furi_hal(_ll)_* */ ret = rfalNfcvPollerGetSystemInformation( RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, rxBuf, sizeof(rxBuf), &received); diff --git a/lib/print/wrappers.c b/lib/print/wrappers.c index 5cfe1060..b248aeb3 100644 --- a/lib/print/wrappers.c +++ b/lib/print/wrappers.c @@ -59,7 +59,6 @@ int __wrap_fflush(FILE* stream) { __attribute__((__noreturn__)) void __wrap___assert(const char* file, int line, const char* e) { UNUSED(file); UNUSED(line); - // TODO: message file and line number furi_crash(e); } @@ -68,6 +67,5 @@ __attribute__((__noreturn__)) void UNUSED(file); UNUSED(line); UNUSED(func); - // TODO: message file and line number furi_crash(e); } \ No newline at end of file diff --git a/lib/subghz/devices/registry.c b/lib/subghz/devices/registry.c index c0d5bb29..779ba81d 100644 --- a/lib/subghz/devices/registry.c +++ b/lib/subghz/devices/registry.c @@ -22,7 +22,7 @@ void subghz_device_registry_init(void) { SUBGHZ_RADIO_DEVICE_PLUGIN_API_VERSION, firmware_api_interface); - //ToDo: fix path to plugins + //TODO FL-3556: fix path to plugins if(plugin_manager_load_all(subghz_device->manager, "/any/apps_data/subghz/plugins") != //if(plugin_manager_load_all(subghz_device->manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) { diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c index 123a4ba9..9509280c 100644 --- a/lib/subghz/protocols/bin_raw.c +++ b/lib/subghz/protocols/bin_raw.c @@ -744,7 +744,6 @@ static bool bin_raw_debug("\r\n\r\n"); #endif - //todo can be optimized BinRAW_Markup markup_temp[BIN_RAW_MAX_MARKUP_COUNT]; memcpy( markup_temp, @@ -770,7 +769,6 @@ static bool } } } - //todo can be optimized if(bin_raw_type == BinRAWTypeGap) { if(data_temp != 0) { //there are sequences with the same number of bits diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 80fecbbf..cfd83887 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -122,7 +122,7 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc uint32_t fix = (uint32_t)btn << 28 | instance->generic.serial; uint32_t decrypt = (uint32_t)btn << 28 | (instance->generic.serial & 0x3FF) - << 16 | //ToDo in some protocols the discriminator is 0 + << 16 | // In some protocols the discriminator is 0 instance->generic.cnt; uint32_t hop = 0; uint64_t man = 0; @@ -149,7 +149,8 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc hop = subghz_protocol_keeloq_common_encrypt(decrypt, man); break; case KEELOQ_LEARNING_UNKNOWN: - hop = 0; //todo + //Invalid or missing encoding type in keeloq_mfcodes + hop = 0; break; } break; @@ -199,9 +200,7 @@ static bool furi_assert(instance); //gen new key - if(subghz_protocol_keeloq_gen_data(instance, btn)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + if(!subghz_protocol_keeloq_gen_data(instance, btn)) { return false; } diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 1288c957..c9d2b301 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -265,7 +265,7 @@ SubGhzProtocolStatus furi_assert(context); UNUSED(context); UNUSED(flipper_format); - //ToDo stub, for backwards compatibility + // stub, for backwards compatibility return SubGhzProtocolStatusOk; } @@ -273,7 +273,6 @@ void subghz_protocol_decoder_raw_get_string(void* context, FuriString* output) { furi_assert(context); //SubGhzProtocolDecoderRAW* instance = context; UNUSED(context); - //ToDo no use furi_string_cat_printf(output, "RAW Date"); } diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index c8ecbea2..12d2fac7 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -380,7 +380,6 @@ static void subghz_protocol_secplus_v2_encode(SubGhzProtocolEncoderSecPlus_v2* i uint8_t roll_2[9] = {0}; instance->generic.cnt++; - //ToDo it is not known what value the counter starts if(instance->generic.cnt > 0xFFFFFFF) instance->generic.cnt = 0xE500000; uint32_t rolling = subghz_protocol_blocks_reverse_key(instance->generic.cnt, 28); diff --git a/lib/subghz/subghz_setting.c b/lib/subghz/subghz_setting.c index 9804f827..c0216913 100644 --- a/lib/subghz/subghz_setting.c +++ b/lib/subghz/subghz_setting.c @@ -344,7 +344,7 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { } while(flipper_format_read_uint32( fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { - //Todo: add a frequency support check depending on the selected radio device + //Todo FL-3535: add a frequency support check depending on the selected radio device if(furi_hal_subghz_is_frequency_valid(temp_data32)) { FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); FrequencyList_push_back(instance->frequencies, temp_data32); diff --git a/lib/subghz/subghz_tx_rx_worker.c b/lib/subghz/subghz_tx_rx_worker.c index 250e6666..daf046f4 100644 --- a/lib/subghz/subghz_tx_rx_worker.c +++ b/lib/subghz/subghz_tx_rx_worker.c @@ -165,7 +165,6 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE); } else { - //todo checking that he managed to write all the data to the TX buffer furi_stream_buffer_receive( instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF); subghz_tx_rx_worker_tx(instance, data, size_tx); @@ -178,7 +177,6 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { furi_stream_buffer_bytes_available(instance->stream_rx) == 0) { callback_rx = true; } - //todo checking that he managed to write all the data to the RX buffer furi_stream_buffer_send( instance->stream_rx, &data, @@ -189,7 +187,7 @@ static int32_t subghz_tx_rx_worker_thread(void* context) { callback_rx = false; } } else { - //todo RX buffer overflow + FURI_LOG_E(TAG, "Receive buffer overflow, over-the-air transmission too fast"); } } } diff --git a/lib/subghz/types.h b/lib/subghz/types.h index d87a0dc7..cccf70ba 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -57,6 +57,7 @@ typedef enum { // Encoder issue SubGhzProtocolStatusErrorEncoderGetUpload = (-12), ///< Payload encoder failure // Special Values + SubGhzProtocolStatusErrorProtocolNotFound = (-13), ///< Protocol not found SubGhzProtocolStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. } SubGhzProtocolStatus; diff --git a/lib/toolbox/crc32_calc.c b/lib/toolbox/crc32_calc.c index c8ae3524..c0cd169b 100644 --- a/lib/toolbox/crc32_calc.c +++ b/lib/toolbox/crc32_calc.c @@ -4,7 +4,7 @@ #define CRC_DATA_BUFFER_MAX_LEN 512 uint32_t crc32_calc_buffer(uint32_t crc, const void* buffer, size_t size) { - // TODO: consider removing dependency on LFS + // TODO FL-3547: consider removing dependency on LFS return ~lfs_crc(~crc, buffer, size); } diff --git a/lib/toolbox/stream/file_stream.c b/lib/toolbox/stream/file_stream.c index 06491216..095dce47 100644 --- a/lib/toolbox/stream/file_stream.c +++ b/lib/toolbox/stream/file_stream.c @@ -134,7 +134,7 @@ static size_t file_stream_size(FileStream* stream) { } static size_t file_stream_write(FileStream* stream, const uint8_t* data, size_t size) { - // TODO cache + // TODO FL-3545: cache size_t need_to_write = size; while(need_to_write > 0) { uint16_t was_written = @@ -148,7 +148,7 @@ static size_t file_stream_write(FileStream* stream, const uint8_t* data, size_t } static size_t file_stream_read(FileStream* stream, uint8_t* data, size_t size) { - // TODO cache + // TODO FL-3545: cache size_t need_to_read = size; while(need_to_read > 0) { uint16_t was_read = @@ -172,7 +172,7 @@ static bool file_stream_delete_and_insert( // open scratchpad Stream* scratch_stream = file_stream_alloc(_stream->storage); - // TODO: we need something like "storage_open_tmpfile and storage_close_tmpfile" + // TODO FL-3546: we need something like "storage_open_tmpfile and storage_close_tmpfile" FuriString* scratch_name; FuriString* tmp_name; tmp_name = furi_string_alloc(); diff --git a/lib/toolbox/stream/string_stream.c b/lib/toolbox/stream/string_stream.c index 075f0b26..f8a360c0 100644 --- a/lib/toolbox/stream/string_stream.c +++ b/lib/toolbox/stream/string_stream.c @@ -106,7 +106,7 @@ static size_t string_stream_size(StringStream* stream) { } static size_t string_stream_write(StringStream* stream, const char* data, size_t size) { - // TODO: can be optimized for edge cases + // TODO FL-3544: can be optimized for edge cases size_t i; for(i = 0; i < size; i++) { string_stream_write_char(stream, data[i]); diff --git a/lib/update_util/dfu_file.c b/lib/update_util/dfu_file.c index 62b139e8..eef9f064 100644 --- a/lib/update_util/dfu_file.c +++ b/lib/update_util/dfu_file.c @@ -55,7 +55,7 @@ uint8_t dfu_file_validate_headers(File* dfuf, const DfuValidationParams* referen if((dfu_suffix.bLength != sizeof(DfuSuffix)) || (dfu_suffix.bcdDFU != DFU_SUFFIX_VERSION)) { return 0; } - /* TODO: check DfuSignature?.. */ + /* TODO FL-3561: check DfuSignature?.. */ if((dfu_suffix.idVendor != reference_params->vendor) || (dfu_suffix.idProduct != reference_params->product) || @@ -137,7 +137,7 @@ bool dfu_file_process_targets(const DfuUpdateTask* task, File* dfuf, const uint8 return UpdateBlockResult_Failed; } - /* TODO: look into TargetPrefix and validate/filter?.. */ + /* TODO FL-3562: look into TargetPrefix and validate/filter?.. */ for(uint32_t i_element = 0; i_element < target_prefix.dwNbElements; ++i_element) { bytes_read = storage_file_read(dfuf, &image_element, sizeof(ImageElementHeader)); if(bytes_read != sizeof(ImageElementHeader)) { diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 795fdd5e..47b2cc0b 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -54,7 +54,7 @@ static bool FuriString* filetype; - // TODO: compare filetype? + // TODO FL-3543: compare filetype? filetype = furi_string_alloc(); update_manifest->valid = flipper_format_read_header(flipper_file, filetype, &update_manifest->manifest_version) && diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index a677d841..b8b8a8d6 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -2,9 +2,15 @@ import os import re from dataclasses import dataclass, field from enum import Enum -from fbt.util import resolve_real_dir_node from typing import Callable, ClassVar, List, Optional, Tuple, Union +try: + from fbt.util import resolve_real_dir_node +except ImportError: + # When running outside of SCons, we don't have access to SCons.Node + def resolve_real_dir_node(node): + return node + class FlipperManifestException(Exception): pass diff --git a/scripts/fbt/sdk/cache.py b/scripts/fbt/sdk/cache.py index b6f6edbe..074cac6b 100644 --- a/scripts/fbt/sdk/cache.py +++ b/scripts/fbt/sdk/cache.py @@ -237,6 +237,7 @@ class SdkCache: removed_entries = known_set - new_set if removed_entries: print(f"Removed: {removed_entries}") + self.loaded_dirty_version = True known_set -= removed_entries # If any of removed entries was a part of active API, that's a major bump if update_version and any( diff --git a/scripts/fbt_tools/compilation_db.py b/scripts/fbt_tools/compilation_db.py index 17ff6aaa..1f829ddb 100644 --- a/scripts/fbt_tools/compilation_db.py +++ b/scripts/fbt_tools/compilation_db.py @@ -38,7 +38,7 @@ from SCons.Tool.cxx import CXXSuffixes from SCons.Tool.cc import CSuffixes from SCons.Tool.asm import ASSuffixes, ASPPSuffixes -# TODO: Is there a better way to do this than this global? Right now this exists so that the +# TODO FL-3542: Is there a better way to do this than this global? Right now this exists so that the # emitter we add can record all of the things it emits, so that the scanner for the top level # compilation database can access the complete list, and also so that the writer has easy # access to write all of the files. But it seems clunky. How can the emitter and the scanner @@ -91,7 +91,7 @@ def make_emit_compilation_DB_entry(comstr): __COMPILATIONDB_ENV=env, ) - # TODO: Technically, these next two lines should not be required: it should be fine to + # TODO FL-3541: Technically, these next two lines should not be required: it should be fine to # cache the entries. However, they don't seem to update properly. Since they are quick # to re-generate disable caching and sidestep this problem. env.AlwaysBuild(entry) diff --git a/scripts/fbt_tools/crosscc.py b/scripts/fbt_tools/crosscc.py index d0631ca3..42fb4ce4 100644 --- a/scripts/fbt_tools/crosscc.py +++ b/scripts/fbt_tools/crosscc.py @@ -2,6 +2,8 @@ import subprocess import gdb import objdump +import shutil + import strip from SCons.Action import _subproc from SCons.Errors import StopError @@ -11,7 +13,7 @@ from SCons.Tool import ar, asm, gcc, gnulink, gxx def prefix_commands(env, command_prefix, cmd_list): for command in cmd_list: if command in env: - env[command] = command_prefix + env[command] + env[command] = shutil.which(command_prefix + env[command]) def _get_tool_version(env, tool): diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index d46ecd8f..392465a5 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -21,7 +21,7 @@ def generate(env, **kw): FBT_DEBUG_DIR="${FBT_SCRIPT_DIR}/debug", ) - if (adapter_serial := env.subst("$OPENOCD_ADAPTER_SERIAL")) != "auto": + if (adapter_serial := env.subst("$SWD_TRANSPORT_SERIAL")) != "auto": env.Append( OPENOCD_OPTS=[ "-c", diff --git a/scripts/fbt_tools/fbt_dist.py b/scripts/fbt_tools/fbt_dist.py index e47898bd..fdf66c0a 100644 --- a/scripts/fbt_tools/fbt_dist.py +++ b/scripts/fbt_tools/fbt_dist.py @@ -52,22 +52,16 @@ def AddFwProject(env, base_env, fw_type, fw_env_key): return project_env -def AddOpenOCDFlashTarget(env, targetenv, **kw): - openocd_target = env.OpenOCDFlash( - "#build/oocd-${BUILD_CFG}-flash.flag", - targetenv["FW_BIN"], - OPENOCD_COMMAND=[ - "-c", - "program ${SOURCE.posix} reset exit ${BASE_ADDRESS}", - ], - BUILD_CFG=targetenv.subst("$FIRMWARE_BUILD_CFG"), - BASE_ADDRESS=targetenv.subst("$IMAGE_BASE_ADDRESS"), +def AddFwFlashTarget(env, targetenv, **kw): + fwflash_target = env.FwFlash( + "#build/flash.flag", + targetenv["FW_ELF"], **kw, ) - env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), openocd_target) + env.Alias(targetenv.subst("${FIRMWARE_BUILD_CFG}_flash"), fwflash_target) if env["FORCE"]: - env.AlwaysBuild(openocd_target) - return openocd_target + env.AlwaysBuild(fwflash_target) + return fwflash_target def AddJFlashTarget(env, targetenv, **kw): @@ -115,7 +109,7 @@ def generate(env): env.SetDefault(COPROCOMSTR="\tCOPRO\t${TARGET}") env.AddMethod(AddFwProject) env.AddMethod(DistCommand) - env.AddMethod(AddOpenOCDFlashTarget) + env.AddMethod(AddFwFlashTarget) env.AddMethod(GetProjetDirName) env.AddMethod(AddJFlashTarget) env.AddMethod(AddUsbFlashTarget) @@ -125,30 +119,53 @@ def generate(env): SELFUPDATE_SCRIPT="${FBT_SCRIPT_DIR}/selfupdate.py", DIST_SCRIPT="${FBT_SCRIPT_DIR}/sconsdist.py", COPRO_ASSETS_SCRIPT="${FBT_SCRIPT_DIR}/assets.py", + FW_FLASH_SCRIPT="${FBT_SCRIPT_DIR}/fwflash.py", ) env.Append( BUILDERS={ + "FwFlash": Builder( + action=[ + [ + "${PYTHON3}", + "${FW_FLASH_SCRIPT}", + "-d" if env["VERBOSE"] else "", + "--interface=${SWD_TRANSPORT}", + "--serial=${SWD_TRANSPORT_SERIAL}", + "${SOURCE}", + ], + Touch("${TARGET}"), + ] + ), "UsbInstall": Builder( action=[ - Action( - '${PYTHON3} "${SELFUPDATE_SCRIPT}" -p ${FLIP_PORT} ${UPDATE_BUNDLE_DIR}/update.fuf' - ), + [ + "${PYTHON3}", + "${SELFUPDATE_SCRIPT}", + "-p", + "${FLIP_PORT}", + "${UPDATE_BUNDLE_DIR}/update.fuf", + ], Touch("${TARGET}"), ] ), "CoproBuilder": Builder( action=Action( [ - '${PYTHON3} "${COPRO_ASSETS_SCRIPT}" ' - "copro ${COPRO_CUBE_DIR} " - "${TARGET} ${COPRO_MCU_FAMILY} " - "--cube_ver=${COPRO_CUBE_VERSION} " - "--stack_type=${COPRO_STACK_TYPE} " - '--stack_file="${COPRO_STACK_BIN}" ' - "--stack_addr=${COPRO_STACK_ADDR} ", + [ + "${PYTHON3}", + "${COPRO_ASSETS_SCRIPT}", + "copro", + "${COPRO_CUBE_DIR}", + "${TARGET}", + "${COPRO_MCU_FAMILY}", + "--cube_ver=${COPRO_CUBE_VERSION}", + "--stack_type=${COPRO_STACK_TYPE}", + "--stack_file=${COPRO_STACK_BIN}", + "--stack_addr=${COPRO_STACK_ADDR}", + ] ], - "$COPROCOMSTR", + "${COPROCOMSTR}", ) ), } diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 642c1c98..6059628f 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -53,6 +53,11 @@ class AppBuilder: FAP_SRC_DIR=self.app._appdir, FAP_WORK_DIR=self.app_work_dir, ) + self.app_env.Append( + CPPDEFINES=[ + ("FAP_VERSION", f'"{".".join(map(str, self.app.fap_version))}"') + ], + ) self.app_env.VariantDir(self.app_work_dir, self.app._appdir, duplicate=False) def _build_external_files(self): diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index 68fc2aaf..dcdce934 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -16,8 +16,8 @@ Firmware & apps: Flashing & debugging: - flash, flash_blackmagic, jflash: - Flash firmware to target using debug probe + flash, jflash: + Flash firmware to target using SWD probe. See also SWD_TRANSPORT, SWD_TRANSPORT_SERIAL flash_usb, flash_usb_full: Install firmware using self-update package debug, debug_other, blackmagic: diff --git a/scripts/flipper/app.py b/scripts/flipper/app.py index 405c4c39..da43a1f1 100644 --- a/scripts/flipper/app.py +++ b/scripts/flipper/app.py @@ -15,10 +15,9 @@ class App: # Application specific initialization self.init() - def __call__(self, args=None, skip_logger_init=False): + def __call__(self, args=None): self.args, self.other_args = self.parser.parse_known_args(args=args) # configure log output - # if skip_logger_init: self.log_level = logging.DEBUG if self.args.debug else logging.INFO self.logger.setLevel(self.log_level) if not self.logger.hasHandlers(): diff --git a/scripts/flipper/storage.py b/scripts/flipper/storage.py index 2c9c043d..40af5ceb 100644 --- a/scripts/flipper/storage.py +++ b/scripts/flipper/storage.py @@ -150,7 +150,7 @@ class FlipperStorage: for line in lines: try: - # TODO: better decoding, considering non-ascii characters + # TODO FL-3539: better decoding, considering non-ascii characters line = line.decode("ascii") except Exception: continue @@ -193,7 +193,7 @@ class FlipperStorage: for line in lines: try: - # TODO: better decoding, considering non-ascii characters + # TODO FL-3539: better decoding, considering non-ascii characters line = line.decode("ascii") except Exception: continue diff --git a/scripts/flipper/utils/openocd.py b/scripts/flipper/utils/openocd.py index 1309055b..a4356809 100644 --- a/scripts/flipper/utils/openocd.py +++ b/scripts/flipper/utils/openocd.py @@ -78,7 +78,7 @@ class OpenOCD: def _wait_for_openocd_tcl(self): """Wait for OpenOCD to start""" - # TODO: timeout + # TODO Fl-3538: timeout while True: stderr = self.process.stderr if not stderr: @@ -128,7 +128,7 @@ class OpenOCD: def _recv(self): """Read from the stream until the token (\x1a) was received.""" - # TODO: timeout + # TODO FL-3538: timeout data = bytes() while True: chunk = self.socket.recv(4096) diff --git a/scripts/flipper/utils/stm32wb55.py b/scripts/flipper/utils/stm32wb55.py index 4a47b8be..9ea80322 100644 --- a/scripts/flipper/utils/stm32wb55.py +++ b/scripts/flipper/utils/stm32wb55.py @@ -247,7 +247,7 @@ class STM32WB55: def flash_wait_for_operation(self): # Wait for flash operation to complete - # TODO: timeout + # TODO FL-3537: timeout while True: self.FLASH_SR.load() if self.FLASH_SR.BSY == 0: diff --git a/scripts/program.py b/scripts/fwflash.py similarity index 54% rename from scripts/program.py rename to scripts/fwflash.py index f3e7e3e2..c119aaf8 100755 --- a/scripts/program.py +++ b/scripts/fwflash.py @@ -1,19 +1,24 @@ #!/usr/bin/env python3 import logging import os +import re import socket import subprocess import time import typing from abc import ABC, abstractmethod -from dataclasses import dataclass +from dataclasses import dataclass, field from flipper.app import App +# When adding an interface, also add it to SWD_TRANSPORT in fbt/ufbt options + class Programmer(ABC): + root_logger = logging.getLogger("Programmer") + @abstractmethod - def flash(self, bin: str) -> bool: + def flash(self, file_path: str, do_verify: bool) -> bool: pass @abstractmethod @@ -28,28 +33,46 @@ class Programmer(ABC): def set_serial(self, serial: str): pass + @classmethod + def _spawn_and_await(cls, process_params, show_progress: bool = False): + cls.root_logger.debug(f"Launching: {' '.join(process_params)}") + + process = subprocess.Popen( + process_params, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + + if show_progress: + while process.poll() is None: + time.sleep(0.25) + print(".", end="", flush=True) + print() + else: + process.wait() + + return process + @dataclass class OpenOCDInterface: name: str - file: str + config_file: str serial_cmd: str - additional_args: typing.Optional[list[str]] = None + additional_args: typing.Optional[list[str]] = field(default_factory=list) class OpenOCDProgrammer(Programmer): def __init__(self, interface: OpenOCDInterface): self.interface = interface - self.logger = logging.getLogger("OpenOCD") + self.logger = self.root_logger.getChild("OpenOCD") self.serial: typing.Optional[str] = None def _add_file(self, params: list[str], file: str): - params.append("-f") - params.append(file) + params += ["-f", file] def _add_command(self, params: list[str], command: str): - params.append("-c") - params.append(command) + params += ["-c", command] def _add_serial(self, params: list[str], serial: str): self._add_command(params, f"{self.interface.serial_cmd} {serial}") @@ -57,22 +80,27 @@ class OpenOCDProgrammer(Programmer): def set_serial(self, serial: str): self.serial = serial - def flash(self, bin: str) -> bool: - i = self.interface - + def flash(self, file_path: str, do_verify: bool) -> bool: if os.altsep: - bin = bin.replace(os.sep, os.altsep) + file_path = file_path.replace(os.sep, os.altsep) openocd_launch_params = ["openocd"] - self._add_file(openocd_launch_params, i.file) + self._add_file(openocd_launch_params, self.interface.config_file) if self.serial: self._add_serial(openocd_launch_params, self.serial) - if i.additional_args: - for a in i.additional_args: - self._add_command(openocd_launch_params, a) + for additional_arg in self.interface.additional_args: + self._add_command(openocd_launch_params, additional_arg) self._add_file(openocd_launch_params, "target/stm32wbx.cfg") self._add_command(openocd_launch_params, "init") - self._add_command(openocd_launch_params, f"program {bin} reset exit 0x8000000") + program_params = [ + "program", + f'"{file_path}"', + "verify" if do_verify else "", + "reset", + "exit", + "0x8000000" if file_path.endswith(".bin") else "", + ] + self._add_command(openocd_launch_params, " ".join(program_params)) # join the list of parameters into a string, but add quote if there are spaces openocd_launch_params_string = " ".join( @@ -81,17 +109,7 @@ class OpenOCDProgrammer(Programmer): self.logger.debug(f"Launching: {openocd_launch_params_string}") - process = subprocess.Popen( - openocd_launch_params, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - - while process.poll() is None: - time.sleep(0.25) - print(".", end="", flush=True) - print() - + process = self._spawn_and_await(openocd_launch_params, True) success = process.returncode == 0 if not success: @@ -102,35 +120,41 @@ class OpenOCDProgrammer(Programmer): return success def probe(self) -> bool: - i = self.interface - openocd_launch_params = ["openocd"] - self._add_file(openocd_launch_params, i.file) + self._add_file(openocd_launch_params, self.interface.config_file) if self.serial: self._add_serial(openocd_launch_params, self.serial) - if i.additional_args: - for a in i.additional_args: - self._add_command(openocd_launch_params, a) + for additional_arg in self.interface.additional_args: + self._add_command(openocd_launch_params, additional_arg) self._add_file(openocd_launch_params, "target/stm32wbx.cfg") self._add_command(openocd_launch_params, "init") self._add_command(openocd_launch_params, "exit") - self.logger.debug(f"Launching: {' '.join(openocd_launch_params)}") + process = self._spawn_and_await(openocd_launch_params) + success = process.returncode == 0 - process = subprocess.Popen( - openocd_launch_params, - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, - ) + output = process.stdout.read().decode("utf-8").strip() if process.stdout else "" + self.logger.debug(output) + # Find target voltage using regex + if match := re.search(r"Target voltage: (\d+\.\d+)", output): + voltage = float(match.group(1)) + if not success: + if voltage < 1: + self.logger.warning( + f"Found {self.get_name()}, but device is not connected" + ) + else: + self.logger.warning( + f"Device is connected, but {self.get_name()} failed to attach. Is System>Debug enabled?" + ) - # Wait for OpenOCD to end and get the return code - process.wait() - found = process.returncode == 0 + if "cannot read IDR" in output: + self.logger.warning( + f"Found {self.get_name()}, but failed to attach. Is device connected and is System>Debug enabled?" + ) + success = False - if process.stdout: - self.logger.debug(process.stdout.read().decode("utf-8").strip()) - - return found + return success def get_name(self) -> str: return self.interface.name @@ -187,7 +211,7 @@ def _resolve_hostname(hostname): def blackmagic_find_networked(serial: str): - if not serial: + if not serial or serial == "auto": serial = "blackmagic.local" # remove the tcp: prefix if it's there @@ -212,7 +236,7 @@ class BlackmagicProgrammer(Programmer): ): self.port_resolver = port_resolver self.name = name - self.logger = logging.getLogger("BlackmagicUSB") + self.logger = self.root_logger.getChild(f"Blackmagic{name}") self.port: typing.Optional[str] = None def _add_command(self, params: list[str], command: str): @@ -234,7 +258,15 @@ class BlackmagicProgrammer(Programmer): else: self.port = serial - def flash(self, bin: str) -> bool: + def _get_gdb_core_params(self) -> list[str]: + gdb_launch_params = ["arm-none-eabi-gdb"] + self._add_command(gdb_launch_params, f"target extended-remote {self.port}") + self._add_command(gdb_launch_params, "set pagination off") + self._add_command(gdb_launch_params, "set confirm off") + self._add_command(gdb_launch_params, "monitor swdp_scan") + return gdb_launch_params + + def flash(self, file_path: str, do_verify: bool) -> bool: if not self.port: if not self.probe(): return False @@ -242,12 +274,14 @@ class BlackmagicProgrammer(Programmer): # We can convert .bin to .elf with objcopy: # arm-none-eabi-objcopy -I binary -O elf32-littlearm --change-section-address=.data=0x8000000 -B arm -S app.bin app.elf # But I choose to use the .elf file directly because we are flashing our own firmware and it always has an elf predecessor. - elf = bin.replace(".bin", ".elf") - if not os.path.exists(elf): - self.logger.error( - f"Sorry, but Blackmagic can't flash .bin file, and {elf} doesn't exist" - ) - return False + + if file_path.endswith(".bin"): + file_path = file_path[:-4] + ".elf" + if not os.path.exists(file_path): + self.logger.error( + f"Sorry, but Blackmagic can't flash .bin file, and {file_path} doesn't exist" + ) + return False # arm-none-eabi-gdb build/f7-firmware-D/firmware.bin # -ex 'set pagination off' @@ -260,42 +294,25 @@ class BlackmagicProgrammer(Programmer): # -ex 'compare-sections' # -ex 'quit' - gdb_launch_params = ["arm-none-eabi-gdb", elf] - self._add_command(gdb_launch_params, f"target extended-remote {self.port}") - self._add_command(gdb_launch_params, "set pagination off") - self._add_command(gdb_launch_params, "set confirm off") - self._add_command(gdb_launch_params, "monitor swdp_scan") + gdb_launch_params = self._get_gdb_core_params() self._add_command(gdb_launch_params, "attach 1") self._add_command(gdb_launch_params, "set mem inaccessible-by-default off") self._add_command(gdb_launch_params, "load") - self._add_command(gdb_launch_params, "compare-sections") + if do_verify: + self._add_command(gdb_launch_params, "compare-sections") self._add_command(gdb_launch_params, "quit") + gdb_launch_params.append(file_path) - self.logger.debug(f"Launching: {' '.join(gdb_launch_params)}") - - process = subprocess.Popen( - gdb_launch_params, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - - while process.poll() is None: - time.sleep(0.5) - print(".", end="", flush=True) - print() - + process = self._spawn_and_await(gdb_launch_params, True) if not process.stdout: return False output = process.stdout.read().decode("utf-8").strip() - flashed = "Loading section .text," in output - - # Check flash verification - if "MIS-MATCHED!" in output: - flashed = False - - if "target image does not match the loaded file" in output: - flashed = False + flashed = ( + "Loading section .text," in output + and "MIS-MATCHED!" not in output + and "target image does not match the loaded file" not in output + ) if not flashed: self.logger.error("Blackmagic failed to flash") @@ -308,13 +325,29 @@ class BlackmagicProgrammer(Programmer): return False self.port = port + + gdb_launch_params = self._get_gdb_core_params() + self._add_command(gdb_launch_params, "quit") + + process = self._spawn_and_await(gdb_launch_params) + if not process.stdout or process.returncode != 0: + return False + + output = process.stdout.read().decode("utf-8").strip() + if "SW-DP scan failed!" in output: + self.logger.warning( + f"Found {self.get_name()} at {self.port}, but failed to attach. Is device connected and is System>Debug enabled?" + ) + return False return True def get_name(self) -> str: return self.name -programmers: list[Programmer] = [ +#################### + +local_flash_interfaces: list[Programmer] = [ OpenOCDProgrammer( OpenOCDInterface( "cmsis-dap", @@ -325,47 +358,66 @@ programmers: list[Programmer] = [ ), OpenOCDProgrammer( OpenOCDInterface( - "stlink", "interface/stlink.cfg", "hla_serial", ["transport select hla_swd"] + "stlink", + "interface/stlink.cfg", + "hla_serial", + ["transport select hla_swd"], ), ), BlackmagicProgrammer(blackmagic_find_serial, "blackmagic_usb"), ] -network_programmers = [ +network_flash_interfaces: list[Programmer] = [ BlackmagicProgrammer(blackmagic_find_networked, "blackmagic_wifi") ] +all_flash_interfaces = [*local_flash_interfaces, *network_flash_interfaces] + +#################### + class Main(App): + AUTO_INTERFACE = "auto" + def init(self): - self.subparsers = self.parser.add_subparsers(help="sub-command help") - self.parser_flash = self.subparsers.add_parser("flash", help="Flash a binary") - self.parser_flash.add_argument( - "bin", + Programmer.root_logger = self.logger + + self.parser.add_argument( + "filename", type=str, - help="Binary to flash", + help="File to flash", ) - interfaces = [i.get_name() for i in programmers] - interfaces.extend([i.get_name() for i in network_programmers]) - self.parser_flash.add_argument( + self.parser.add_argument( + "--verify", + "-v", + action="store_true", + help="Verify flash after programming", + default=False, + ) + self.parser.add_argument( "--interface", - choices=interfaces, + choices=( + self.AUTO_INTERFACE, + *[i.get_name() for i in all_flash_interfaces], + ), type=str, + default=self.AUTO_INTERFACE, help="Interface to use", ) - self.parser_flash.add_argument( + self.parser.add_argument( "--serial", type=str, + default=self.AUTO_INTERFACE, help="Serial number or port of the programmer", ) - self.parser_flash.set_defaults(func=self.flash) + self.parser.set_defaults(func=self.flash) - def _search_interface(self, serial: typing.Optional[str]) -> list[Programmer]: + def _search_interface(self, interface_list: list[Programmer]) -> list[Programmer]: found_programmers = [] - for p in programmers: + for p in interface_list: name = p.get_name() - if serial: + if (serial := self.args.serial) != self.AUTO_INTERFACE: p.set_serial(serial) self.logger.debug(f"Trying {name} with {serial}") else: @@ -373,29 +425,7 @@ class Main(App): if p.probe(): self.logger.debug(f"Found {name}") - found_programmers += [p] - else: - self.logger.debug(f"Failed to probe {name}") - - return found_programmers - - def _search_network_interface( - self, serial: typing.Optional[str] - ) -> list[Programmer]: - found_programmers = [] - - for p in network_programmers: - name = p.get_name() - - if serial: - p.set_serial(serial) - self.logger.debug(f"Trying {name} with {serial}") - else: - self.logger.debug(f"Trying {name}") - - if p.probe(): - self.logger.debug(f"Found {name}") - found_programmers += [p] + found_programmers.append(p) else: self.logger.debug(f"Failed to probe {name}") @@ -403,55 +433,59 @@ class Main(App): def flash(self): start_time = time.time() - bin_path = os.path.abspath(self.args.bin) + file_path = os.path.abspath(self.args.filename) - if not os.path.exists(bin_path): - self.logger.error(f"Binary file not found: {bin_path}") + if not os.path.exists(file_path): + self.logger.error(f"Binary file not found: {file_path}") return 1 - if self.args.interface: - i_name = self.args.interface - interfaces = [p for p in programmers if p.get_name() == i_name] - if len(interfaces) == 0: - interfaces = [p for p in network_programmers if p.get_name() == i_name] - else: - self.logger.info("Probing for interfaces...") - interfaces = self._search_interface(self.args.serial) + if self.args.interface != self.AUTO_INTERFACE: + available_interfaces = list( + filter( + lambda p: p.get_name() == self.args.interface, + all_flash_interfaces, + ) + ) - if len(interfaces) == 0: + else: + self.logger.info("Probing for local interfaces...") + available_interfaces = self._search_interface(local_flash_interfaces) + + if not available_interfaces: # Probe network blackmagic self.logger.info("Probing for network interfaces...") - interfaces = self._search_network_interface(self.args.serial) + available_interfaces = self._search_interface(network_flash_interfaces) - if len(interfaces) == 0: - self.logger.error("No interface found") + if not available_interfaces: + self.logger.error("No availiable interfaces") return 1 - - if len(interfaces) > 1: - self.logger.error("Multiple interfaces found: ") + elif len(available_interfaces) > 1: + self.logger.error("Multiple interfaces found:") self.logger.error( - f"Please specify '--interface={[i.get_name() for i in interfaces]}'" + f"Please specify '--interface={[i.get_name() for i in available_interfaces]}'" ) return 1 - interface = interfaces[0] + interface = available_interfaces.pop(0) - if self.args.serial: + if self.args.serial != self.AUTO_INTERFACE: interface.set_serial(self.args.serial) - self.logger.info( - f"Flashing {bin_path} via {interface.get_name()} with {self.args.serial}" - ) + self.logger.info(f"Using {interface.get_name()} with {self.args.serial}") else: - self.logger.info(f"Flashing {bin_path} via {interface.get_name()}") + self.logger.info(f"Using {interface.get_name()}") + self.logger.info(f"Flashing {file_path}") - if not interface.flash(bin_path): + if not interface.flash(file_path, self.args.verify): self.logger.error(f"Failed to flash via {interface.get_name()}") return 1 flash_time = time.time() - start_time - bin_size = os.path.getsize(bin_path) self.logger.info(f"Flashed successfully in {flash_time:.2f}s") - self.logger.info(f"Effective speed: {bin_size / flash_time / 1024:.2f} KiB/s") + if file_path.endswith(".bin"): + bin_size = os.path.getsize(file_path) + self.logger.info( + f"Effective speed: {bin_size / flash_time / 1024:.2f} KiB/s" + ) return 0 diff --git a/scripts/power.py b/scripts/power.py index 45a130c5..50bb2d4f 100755 --- a/scripts/power.py +++ b/scripts/power.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +import time +from typing import Optional + from flipper.app import App from flipper.storage import FlipperStorage from flipper.utils.cdc import resolve_port @@ -27,8 +30,20 @@ class Main(App): ) self.parser_reboot2dfu.set_defaults(func=self.reboot2dfu) - def _get_flipper(self): - if not (port := resolve_port(self.logger, self.args.port)): + def _get_flipper(self, retry_count: Optional[int] = 1): + port = None + self.logger.info(f"Attempting to find flipper with {retry_count} attempts.") + + for i in range(retry_count): + time.sleep(1) + self.logger.info(f"Attempting to find flipper #{i}.") + + if port := resolve_port(self.logger, self.args.port): + self.logger.info(f"Found flipper at {port}") + break + + if not port: + self.logger.info(f"Failed to find flipper") return None flipper = FlipperStorage(port) @@ -36,28 +51,28 @@ class Main(App): return flipper def power_off(self): - if not (flipper := self._get_flipper()): + if not (flipper := self._get_flipper(retry_count=10)): return 1 - self.logger.debug("Powering off") + self.logger.info("Powering off") flipper.send("power off" + "\r") flipper.stop() return 0 def reboot(self): - if not (flipper := self._get_flipper()): + if not (flipper := self._get_flipper(retry_count=10)): return 1 - self.logger.debug("Rebooting") + self.logger.info("Rebooting") flipper.send("power reboot" + "\r") flipper.stop() return 0 def reboot2dfu(self): - if not (flipper := self._get_flipper()): + if not (flipper := self._get_flipper(retry_count=10)): return 1 - self.logger.debug("Rebooting to DFU") + self.logger.info("Rebooting to DFU") flipper.send("power reboot2dfu" + "\r") flipper.stop() diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py index ea07d6be..f8dffeb6 100755 --- a/scripts/testing/await_flipper.py +++ b/scripts/testing/await_flipper.py @@ -22,14 +22,14 @@ def flp_serial_by_name(flp_name): if os.path.exists(flp_serial): return flp_serial else: - logging.info(f"Couldn't find {logging.info} on this attempt.") + logging.info(f"Couldn't find {flp_name} on this attempt.") if os.path.exists(flp_name): return flp_name else: return "" -UPDATE_TIMEOUT = 60 * 4 # 4 minutes +UPDATE_TIMEOUT = 30 * 4 # 4 minutes def main(): @@ -50,7 +50,7 @@ def main(): if flipper == "": logging.error("Flipper not found!") - sys.exit(1) + exit(1) logging.info(f"Found Flipper at {flipper}") diff --git a/scripts/testing/units.py b/scripts/testing/units.py index fd8e29a7..db302e9d 100755 --- a/scripts/testing/units.py +++ b/scripts/testing/units.py @@ -20,14 +20,12 @@ def main(): logging.error("Flipper not found!") sys.exit(1) - with serial.Serial(flp_serial, timeout=10) as flipper: + with serial.Serial(flp_serial, timeout=150) as flipper: logging.info(f"Found Flipper at {flp_serial}") flipper.baudrate = 230400 flipper.flushOutput() flipper.flushInput() - flipper.timeout = 300 - flipper.read_until(b">: ").decode("utf-8") flipper.write(b"unit_tests\r") data = flipper.read_until(b">: ").decode("utf-8") diff --git a/scripts/toolchain/windows-toolchain-download.ps1 b/scripts/toolchain/windows-toolchain-download.ps1 index 05ea4be2..f30b157d 100644 --- a/scripts/toolchain/windows-toolchain-download.ps1 +++ b/scripts/toolchain/windows-toolchain-download.ps1 @@ -1,7 +1,7 @@ Set-StrictMode -Version 2.0 $ErrorActionPreference = "Stop" [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" -# TODO: fix +# TODO FL-3536: fix path to download_dir $download_dir = (Get-Item "$PSScriptRoot\..\..").FullName $toolchain_version = $args[0] $toolchain_target_path = $args[1] diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 1c2f2bdf..1630135c 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -144,24 +144,20 @@ dist_env = env.Clone( ], ) -openocd_target = dist_env.OpenOCDFlash( +flash_target = dist_env.FwFlash( dist_env["UFBT_STATE_DIR"].File("flash"), - dist_env["FW_BIN"], - OPENOCD_COMMAND=[ - "-c", - "program ${SOURCE.posix} reset exit 0x08000000", - ], + dist_env["FW_ELF"], ) -dist_env.Alias("firmware_flash", openocd_target) -dist_env.Alias("flash", openocd_target) +dist_env.Alias("firmware_flash", flash_target) +dist_env.Alias("flash", flash_target) if env["FORCE"]: - env.AlwaysBuild(openocd_target) + env.AlwaysBuild(flash_target) firmware_jflash = dist_env.JFlash( dist_env["UFBT_STATE_DIR"].File("jflash"), dist_env["FW_BIN"], - JFLASHADDR="0x20000000", + JFLASHADDR="0x08000000", ) dist_env.Alias("firmware_jflash", firmware_jflash) dist_env.Alias("jflash", firmware_jflash) @@ -213,21 +209,6 @@ dist_env.PhonyTarget( GDBPYOPTS=debug_other_opts, ) - -dist_env.PhonyTarget( - "flash_blackmagic", - "$GDB $GDBOPTS $SOURCES $GDBFLASH", - source=dist_env["FW_ELF"], - GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", - GDBREMOTE="${BLACKMAGIC_ADDR}", - GDBFLASH=[ - "-ex", - "load", - "-ex", - "quit", - ], -) - flash_usb_full = dist_env.UsbInstall( dist_env["UFBT_STATE_DIR"].File("usbinstall"), [], diff --git a/scripts/ufbt/commandline.scons b/scripts/ufbt/commandline.scons index 349b4ef2..99c34c35 100644 --- a/scripts/ufbt/commandline.scons +++ b/scripts/ufbt/commandline.scons @@ -55,9 +55,21 @@ vars.AddVariables( "Blackmagic probe location", "auto", ), + EnumVariable( + "SWD_TRANSPORT", + help="SWD interface adapter type", + default="auto", + allowed_values=[ + "auto", + "cmsis-dap", + "stlink", + "blackmagic_usb", + "blackmagic_wifi", + ], + ), ( - "OPENOCD_ADAPTER_SERIAL", - "OpenOCD adapter serial number", + "SWD_TRANSPORT_SERIAL", + "SWD interface adapter serial number", "auto", ), ( diff --git a/scripts/ufbt/site_tools/ufbt_help.py b/scripts/ufbt/site_tools/ufbt_help.py index 3d7f6f00..1df6a059 100644 --- a/scripts/ufbt/site_tools/ufbt_help.py +++ b/scripts/ufbt/site_tools/ufbt_help.py @@ -20,8 +20,8 @@ Building: Build FAP app with appid={APPID}; upload & start it over USB Flashing & debugging: - flash, flash_blackmagic, *jflash: - Flash firmware to target using debug probe + flash, *jflash: + Flash firmware to target using SWD probe. See also SWD_TRANSPORT, SWD_TRANSPORT_SERIAL flash_usb, flash_usb_full: Install firmware using self-update package debug, debug_other, blackmagic: diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index 0d3b1f92..f75d5e0e 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -175,9 +175,21 @@ vars.AddVariables( "Blackmagic probe location", "auto", ), + EnumVariable( + "SWD_TRANSPORT", + help="SWD interface adapter type", + default="auto", + allowed_values=[ + "auto", + "cmsis-dap", + "stlink", + "blackmagic_usb", + "blackmagic_wifi", + ], + ), ( - "OPENOCD_ADAPTER_SERIAL", - "OpenOCD adapter serial number", + "SWD_TRANSPORT_SERIAL", + "SWD interface adapter serial number", "auto", ), ( @@ -248,6 +260,15 @@ vars.AddVariables( "Full port name of Flipper to use, if multiple Flippers are connected", "auto", ), + EnumVariable( + "LANG_SERVER", + help="Language server type for vscode_dist.", + default="cpptools", + allowed_values=[ + "cpptools", + "clangd", + ], + ), ) Return("vars") diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 5c6f18d6..97b7ac09 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -23,18 +23,14 @@ appenv.Replace( appenv.AppendUnique( CCFLAGS=[ - "-ggdb3", "-mword-relocations", "-mlong-calls", "-fno-common", "-nostdlib", - "-fvisibility=hidden", ], LINKFLAGS=[ "-Ur", "-Wl,-Ur", - # "-Wl,--orphan-handling=error", - "-Bsymbolic", "-nostartfiles", "-mlong-calls", "-fno-common",