diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45a97746..15b7f786 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,14 +71,6 @@ jobs: run: | tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts - - name: 'Rebuild Assets' - uses: ./.github/actions/docker - with: - run: | - set -e - make assets_rebuild assets_manifest - git diff --quiet || ( echo "Assets recompilation required."; exit 255 ) - - name: 'Build the firmware in docker' uses: ./.github/actions/docker with: @@ -86,7 +78,7 @@ jobs: set -e for TARGET in ${TARGETS} do - make updater_package TARGET=${TARGET} ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} done - name: 'Move upload files' @@ -97,7 +89,7 @@ jobs: set -e for TARGET in ${TARGETS} do - mv dist/${TARGET}/* artifacts/ + mv dist/${TARGET}-*/* artifacts/ done - name: 'Bundle self-update package' @@ -124,7 +116,7 @@ jobs: uses: ./.github/actions/docker with: run: | - make -C assets copro_bundle + ./fbt copro_dist tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware - name: 'Upload artifacts to update server' @@ -208,14 +200,6 @@ jobs: echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV - - name: 'Rebuild Assets' - uses: ./.github/actions/docker - with: - run: | - set -e - make assets_rebuild assets_manifest - git diff --quiet || ( echo "Assets recompilation required."; exit 255 ) - - name: 'Build the firmware in docker' uses: ./.github/actions/docker with: @@ -223,5 +207,5 @@ jobs: set -e for TARGET in ${TARGETS} do - make TARGET=${TARGET} DEBUG=0 COMPACT=1 + ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` --with-updater updater_package DEBUG=0 COMPACT=1 done diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index 97ef9fb9..f834586d 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -47,7 +47,7 @@ jobs: id: syntax_check uses: ./.github/actions/docker with: - run: SET_GH_OUTPUT=1 make lint + run: SET_GH_OUTPUT=1 ./fbt lint - name: Report code formatting errors if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request diff --git a/.gitignore b/.gitignore index 6577101d..2d66413b 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,11 @@ dist # kde .directory + +# SCons +.sconsign.dblite +# SCons build dir +build/ + +# Toolchain +toolchain*/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index c4649fdc..5846b705 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "lib/microtar"] path = lib/microtar url = https://github.com/amachronic/microtar.git +[submodule "lib/scons"] + path = lib/scons + url = https://github.com/SCons/scons.git diff --git a/Brewfile b/Brewfile index 963a687c..d9ba70e0 100644 --- a/Brewfile +++ b/Brewfile @@ -1,8 +1,6 @@ cask "gcc-arm-embedded" brew "protobuf" brew "gdb" -brew "heatshrink" brew "open-ocd" brew "clang-format" brew "dfu-util" -brew "imagemagick" diff --git a/CODING_STYLE.md b/CODING_STYLE.md index ccadbe8e..31426b94 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -48,7 +48,7 @@ Almost everything in flipper firmware is built around this concept. # C coding style - Tab is 4 spaces -- Use `make format` to reformat source code and check style guide before commit +- Use `fbt format` to reformat source code and check style guide before commit ## Naming diff --git a/Makefile b/Makefile index 8834cba6..ff701a42 100644 --- a/Makefile +++ b/Makefile @@ -1,155 +1,21 @@ -PROJECT_ROOT := $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))) - -include $(PROJECT_ROOT)/make/git.mk -include $(PROJECT_ROOT)/assets/copro.mk - -PROJECT_SOURCE_DIRECTORIES := \ - $(PROJECT_ROOT)/applications \ - $(PROJECT_ROOT)/core \ - $(PROJECT_ROOT)/firmware/targets \ - $(PROJECT_ROOT)/lib/app-template \ - $(PROJECT_ROOT)/lib/app-scened-template \ - $(PROJECT_ROOT)/lib/common-api \ - $(PROJECT_ROOT)/lib/drivers \ - $(PROJECT_ROOT)/lib/flipper_file \ - $(PROJECT_ROOT)/lib/infrared \ - $(PROJECT_ROOT)/lib/nfc_protocols \ - $(PROJECT_ROOT)/lib/ST25RFAL002 \ - $(PROJECT_ROOT)/lib/onewire \ - $(PROJECT_ROOT)/lib/qrcode \ - $(PROJECT_ROOT)/lib/subghz \ - $(PROJECT_ROOT)/lib/toolbox \ - $(PROJECT_ROOT)/lib/u8g2 - -NPROCS := 3 -OS := $(shell uname -s) - -ifeq ($(OS), Linux) -NPROCS := $(shell grep -c ^processor /proc/cpuinfo) -else ifeq ($(OS), Darwin) -NPROCS := $(shell sysctl -n hw.ncpu) -endif - -include $(PROJECT_ROOT)/make/defaults.mk - -.PHONY: all -all: firmware_all - @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware -s $(DIST_SUFFIX) - -.PHONY: whole -whole: flash_radio firmware_flash - -.PHONY: clean -clean: firmware_clean updater_clean - @rm -rf $(PROJECT_ROOT)/dist/$(TARGET) - -.PHONY: flash -flash: firmware_flash - -.PHONY: debug -debug: - @$(MAKE) -C firmware -j$(NPROCS) debug - -.PHONY: debug_other -debug_other: - @$(MAKE) -C firmware -j$(NPROCS) debug_other - -.PHONY: blackmagic -blackmagic: - @$(MAKE) -C firmware -j$(NPROCS) blackmagic - -.PHONY: wipe -wipe: - @$(PROJECT_ROOT)/scripts/flash.py wipe - @$(PROJECT_ROOT)/scripts/ob.py set - -.PHONY: firmware_all -firmware_all: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) all - -.PHONY: firmware_clean -firmware_clean: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) clean - -.PHONY: firmware_flash -firmware_flash: -ifeq ($(FORCE), 1) - @rm $(PROJECT_ROOT)/firmware/.obj/f*-firmware/flash || true -endif - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash - -.PHONY: updater -updater: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) RAM_EXEC=1 all - -.PHONY: updater_clean -updater_clean: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) RAM_EXEC=1 clean - -.PHONY: updater_debug -updater_debug: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) RAM_EXEC=1 debug - -.PHONY: updater_package_bin -updater_package_bin: firmware_all updater - @$(PROJECT_ROOT)/scripts/dist.py copy -t $(TARGET) -p firmware updater -s $(DIST_SUFFIX) --bundlever "$(VERSION_STRING)" - -.PHONY: updater_package -updater_package: firmware_all updater assets_manifest - @$(PROJECT_ROOT)/scripts/dist.py copy \ - -t $(TARGET) -p firmware updater \ - -s $(DIST_SUFFIX) -r $(PROJECT_ROOT)/assets/resources \ - --bundlever "$(VERSION_STRING)" \ - --radio $(COPRO_STACK_BIN_PATH) \ - --radiotype $(COPRO_STACK_TYPE) \ - $(COPRO_DISCLAIMER) \ - --obdata $(PROJECT_ROOT)/scripts/$(COPRO_OB_DATA) - -.PHONY: assets_manifest -assets_manifest: - @$(MAKE) -C $(PROJECT_ROOT)/assets manifest - -.PHONY: assets_rebuild -assets_rebuild: - @$(MAKE) -C $(PROJECT_ROOT)/assets clean all - -.PHONY: flash_radio -flash_radio: - @$(PROJECT_ROOT)/scripts/flash.py core2radio $(COPRO_STACK_BIN_PATH) --addr=$(COPRO_STACK_ADDR) - @$(PROJECT_ROOT)/scripts/ob.py set - -.PHONY: flash_radio_fus -flash_radio_fus: - @echo - @echo "================ DON'T DO IT ================" - @echo "= Flashing FUS is going to erase secure enclave =" - @echo "= You will lose ability to use encrypted assets =" - @echo "= type 'find / -exec rm -rf {} \;' =" - @echo "= In case if you still want to continue =" - @echo "================ JUST DON'T ================" - @echo - -.PHONY: flash_radio_fus_please_i_m_not_going_to_complain -flash_radio_fus_please_i_m_not_going_to_complain: - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_FIRMWARE_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin - @$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE $(COPRO_FIRMWARE_DIR)/stm32wb5x_FUS_fw.bin - @$(PROJECT_ROOT)/scripts/ob.py set - -.PHONY: lint -lint: - @echo "Checking source code formatting" - @$(PROJECT_ROOT)/scripts/lint.py check $(PROJECT_SOURCE_DIRECTORIES) - -.PHONY: format -format: - @echo "Reformating sources code" - @$(PROJECT_ROOT)/scripts/lint.py format $(PROJECT_SOURCE_DIRECTORIES) - -.PHONY: guruguru -guruguru: - @echo "ぐるぐる回る" - @$(PROJECT_ROOT)/scripts/guruguru.py $(PROJECT_ROOT) - -.PHONY: generate_compile_db -generate_compile_db: - @$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) generate_compile_db \ No newline at end of file +$(info +-------------------------------------------------+) +$(info | |) +$(info | Hello, this is Flipper team speaking! |) +$(info | |) +$(info | We've migrated to new build system |) +$(info | It's nice and based on scons |) +$(info | |) +$(info | Crash course: |) +$(info | |) +$(info | `./fbt` |) +$(info | `./fbt flash` |) +$(info | `./fbt debug` |) +$(info | |) +$(info | More details in documentation/fbt.md |) +$(info | |) +$(info | Also Please leave your feedback here: |) +$(info | https://flipp.dev/4RDu |) +$(info | or |) +$(info | https://flipp.dev/2XM8 |) +$(info | |) +$(info +-------------------------------------------------+) \ No newline at end of file diff --git a/ReadMe.md b/ReadMe.md index 9e34148f..6a3eed37 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -25,6 +25,12 @@ Flipper Zero's firmware consists of two components: They both must be flashed in order described. +## With offline update package + +`./fbt --with-updater updater_package` + +Copy the resulting directory to Flipper's SD card and navigate to `update.fuf` file in Archive app. + ## With STLink ### Core1 Firmware @@ -36,17 +42,7 @@ Prerequisites: - [arm-gcc-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) - openocd -One liner: `make flash` - -### Core2 flashing procedures - -Prerequisites: - -- Linux / macOS -- Terminal -- STM32_Programmer_CLI (v2.5.0) added to $PATH - -One liner: `make flash_radio` +One liner: `./fbt firmware_flash` ## With USB DFU @@ -56,7 +52,6 @@ One liner: `make flash_radio` - Press and hold `← Left` + `↩ Back` for reset - Release `↩ Back` and keep holding `← Left` until blue LED lights up - Release `← Left` - 3. Run `dfu-util -D full.dfu -a 0` @@ -74,7 +69,7 @@ One liner: `make flash_radio` ## Compile everything ```sh -docker-compose exec dev make +docker-compose exec dev ./fbt ``` Check `dist/` for build outputs. @@ -85,6 +80,8 @@ If compilation fails, make sure all submodules are all initialized. Either clone # Build on Linux/macOS +Check out `documentation/fbt.md` for details on building and flashing firmware. + ## macOS Prerequisites Make sure you have [brew](https://brew.sh) and install all the dependencies: @@ -127,7 +124,7 @@ heatshrink has to be compiled [from sources](https://github.com/atomicobject/hea ## Compile everything ```sh -make +./fbt ``` Check `dist/` for build outputs. @@ -138,7 +135,7 @@ Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. Connect your device via ST-Link and run: ```sh -make whole +./fbt firmware_flash ``` # Links @@ -158,7 +155,6 @@ make whole - `documentation` - Documentation generation system configs and input files - `firmware` - Firmware source code - `lib` - Our and 3rd party libraries, drivers and etc... -- `make` - Make helpers - `scripts` - Supplementary scripts and python libraries home Also pay attention to `ReadMe.md` files inside of those directories. diff --git a/SConstruct b/SConstruct new file mode 100644 index 00000000..312b23a6 --- /dev/null +++ b/SConstruct @@ -0,0 +1,161 @@ +# +# Main Fipper Build System entry point +# +# This file is evaluated by scons (the build system) every time fbt is invoked. +# Scons constructs all referenced environments & their targets' dependency +# trees on startup. So, to keep startup time as low as possible, we're hiding +# construction of certain targets behind command-line options. + +import os + +DefaultEnvironment(tools=[]) +# Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) + + +# This environment is created only for loading options & validating file/dir existance +fbt_variables = SConscript("site_scons/commandline.scons") +cmd_environment = Environment(tools=[], variables=fbt_variables) +Help(fbt_variables.GenerateHelpText(cmd_environment)) + + +# Building basic environment - tools, utility methods, cross-compilation +# settings, gcc flags for Cortex-M4, basic builders and more +coreenv = SConscript( + "site_scons/environ.scons", + exports={"VAR_ENV": cmd_environment}, +) +SConscript("site_scons/cc.scons", exports={"ENV": coreenv}) + +# Store root dir in environment for certain tools +coreenv["ROOT_DIR"] = Dir(".") + +# Create a separate "dist" environment and add construction envs to it +distenv = coreenv.Clone( + tools=["fbt_dist", "openocd"], + GDBOPTS="-ex 'target extended-remote | ${OPENOCD} -c \"gdb_port pipe\" ${OPENOCD_OPTS}' " + '-ex "set confirm off" ', + ENV=os.environ, +) + +firmware_out = distenv.AddFwProject( + base_env=coreenv, + fw_type="firmware", + fw_env_key="FW_ENV", +) + + +# If enabled, initialize updater-related targets +if GetOption("fullenv"): + updater_out = distenv.AddFwProject( + base_env=coreenv, + fw_type="updater", + fw_env_key="UPD_ENV", + ) + + # Target for self-update package + dist_arguments = [ + "-r", + '"${ROOT_DIR.abspath}/assets/resources"', + "--bundlever", + '"${UPDATE_VERSION_STRING}"', + "--radio", + '"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"', + "--radiotype", + "${COPRO_STACK_TYPE}", + "${COPRO_DISCLAIMER}", + "--obdata", + '"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"', + ] + if distenv["UPDATE_SPLASH"]: + dist_arguments += [ + "--splash", + distenv.subst("assets/slideshow/$UPDATE_SPLASH"), + ] + selfupdate_dist = distenv.DistBuilder( + "selfupdate.pseudo", + (distenv["DIST_DEPENDS"], firmware_out["FW_RESOURCES"]), + DIST_EXTRA=dist_arguments, + ) + distenv.Pseudo("selfupdate.pseudo") + AlwaysBuild(selfupdate_dist) + Alias("updater_package", selfupdate_dist) + + # Updater debug + debug_updater_elf = distenv.AddDebugTarget(updater_out, False) + Alias("updater_debug", debug_updater_elf) + + # Installation over USB & CLI + usb_update_package = distenv.UsbInstall( + "usbinstall.flag", + (distenv["DIST_DEPENDS"], firmware_out["FW_RESOURCES"], selfupdate_dist), + ) + if distenv["FORCE"]: + AlwaysBuild(usb_update_package) + Depends(usb_update_package, selfupdate_dist) + Alias("flash_usb", usb_update_package) + + +# Target for copying & renaming binaries to dist folder +basic_dist = distenv.DistBuilder("dist.pseudo", distenv["DIST_DEPENDS"]) +distenv.Pseudo("dist.pseudo") +AlwaysBuild(basic_dist) +Alias("fw_dist", basic_dist) +Default(basic_dist) + + +# Target for bundling core2 package for qFlipper +copro_dist = distenv.CoproBuilder( + Dir("assets/core2_firmware"), + [], +) +AlwaysBuild(copro_dist) +Alias("copro_dist", copro_dist) + + +# Debugging firmware + +debug_fw_elf = distenv.AddDebugTarget(firmware_out) +Alias("debug", debug_fw_elf) + + +# Debug alien elf +debug_other = distenv.GDBPy( + "debugother.pseudo", + None, + GDBPYOPTS= + # '-ex "source ${ROOT_DIR.abspath}/debug/FreeRTOS/FreeRTOS.py" ' + '-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ', +) +distenv.Pseudo("debugother.pseudo") +AlwaysBuild(debug_other) +Alias("debug_other", debug_other) + + +# Just start OpenOCD +openocd = distenv.OOCDCommand("openocd.pseudo", []) +distenv.Pseudo("openocd.pseudo") +AlwaysBuild(openocd) +Alias("openocd", openocd) + + +# Linter +lint_check = distenv.Command( + "lint.check.pseudo", + [], + "${PYTHON3} scripts/lint.py check $LINT_SOURCES", + LINT_SOURCES=firmware_out["LINT_SOURCES"], +) +distenv.Pseudo("lint.check.pseudo") +AlwaysBuild(lint_check) +Alias("lint", lint_check) + + +lint_format = distenv.Command( + "lint.format.pseudo", + [], + "${PYTHON3} scripts/lint.py format $LINT_SOURCES", + LINT_SOURCES=firmware_out["LINT_SOURCES"], +) +distenv.Pseudo("lint.format.pseudo") +AlwaysBuild(lint_format) +Alias("format", lint_format) diff --git a/applications/ReadMe.md b/applications/ReadMe.md index 2c78dfa2..cb2f5628 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -16,7 +16,6 @@ - `ibutton` - iButton application, onewire keys and more - `input` - Input service - `infrared` - Infrared application, controls your IR devices -- `infrared_monitor` - Infrared debug tool - `lfrfid` - LF RFID application - `lfrfid_debug` - LF RFID debug tool - `loader` - Application loader service @@ -36,6 +35,4 @@ - `u2f` - U2F Application - `updater` - Update service & application -- `application.c` - Firmware application list source - `application.h` - Firmware application list header -- `application.mk` - Makefile helper diff --git a/applications/about/about.c b/applications/about/about.c index 7c8a4c69..6f8ebdf3 100644 --- a/applications/about/about.c +++ b/applications/about/about.c @@ -5,6 +5,7 @@ #include #include #include +#include typedef DialogMessageButton (*AboutDialogScreen)(DialogsApp* dialogs, DialogMessage* message); @@ -57,7 +58,7 @@ static DialogMessageButton compliance_screen(DialogsApp* dialogs, DialogMessage* static DialogMessageButton icon1_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - dialog_message_set_icon(message, &I_Certification1_103x23, 12, 12); + dialog_message_set_icon(message, &I_Certification1_103x56, 13, 0); result = dialog_message_show(dialogs, message); dialog_message_set_icon(message, NULL, 0, 0); @@ -67,7 +68,7 @@ static DialogMessageButton icon1_screen(DialogsApp* dialogs, DialogMessage* mess static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - dialog_message_set_icon(message, &I_Certification2_119x30, 4, 9); + dialog_message_set_icon(message, &I_Certification2_98x33, 15, 10); result = dialog_message_show(dialogs, message); dialog_message_set_icon(message, NULL, 0, 0); @@ -111,18 +112,23 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* string_t buffer; string_init(buffer); const Version* ver = furi_hal_version_get_firmware_version(); + const BleGlueC2Info* c2_ver = NULL; +#ifdef SRV_BT + c2_ver = ble_glue_get_c2_info(); +#endif if(!ver) { string_cat_printf(buffer, "No info\n"); } else { string_cat_printf( buffer, - "%s [%s]\n%s%s [%s]\n[%d] %s", + "%s [%s]\n%s%s [%s] %s\n[%d] %s", version_get_version(ver), version_get_builddate(ver), version_get_dirty_flag(ver) ? "[!] " : "", version_get_githash(ver), version_get_gitbranchnum(ver), + c2_ver ? c2_ver->StackTypeString : "", version_get_target(ver), version_get_gitbranch(ver)); } diff --git a/applications/about/application.fam b/applications/about/application.fam new file mode 100644 index 00000000..d97817b4 --- /dev/null +++ b/applications/about/application.fam @@ -0,0 +1,13 @@ +App( + appid="about", + name="About", + apptype=FlipperAppType.SETTINGS, + entry_point="about_settings_app", + cdefines=["APP_ABOUT"], + requires=[ + "gui", + "dialogs", + ], + stack_size=1 * 1024, + order=1000, +) diff --git a/applications/accessor/application.fam b/applications/accessor/application.fam new file mode 100644 index 00000000..8a94049e --- /dev/null +++ b/applications/accessor/application.fam @@ -0,0 +1,10 @@ +App( + appid="accessor", + name="Accessor", + apptype=FlipperAppType.DEBUG, + entry_point="accessor_app", + cdefines=["APP_ACCESSOR"], + requires=["gui"], + stack_size=4 * 1024, + order=40, +) diff --git a/applications/applications.c b/applications/applications.c deleted file mode 100644 index dccab589..00000000 --- a/applications/applications.c +++ /dev/null @@ -1,558 +0,0 @@ -#include "applications.h" -#include - -// Services -extern int32_t rpc_srv(void* p); -extern int32_t bt_srv(void* p); -extern int32_t cli_srv(void* p); -extern int32_t dialogs_srv(void* p); -extern int32_t dolphin_srv(void* p); -extern int32_t gui_srv(void* p); -extern int32_t input_srv(void* p); -extern int32_t loader_srv(void* p); -extern int32_t notification_srv(void* p); -extern int32_t power_srv(void* p); -extern int32_t storage_srv(void* p); -extern int32_t desktop_srv(void* p); -extern int32_t updater_srv(void* p); - -// Apps -extern int32_t accessor_app(void* p); -extern int32_t archive_app(void* p); -extern int32_t bad_usb_app(void* p); -extern int32_t u2f_app(void* p); -extern int32_t uart_echo_app(void* p); -extern int32_t blink_test_app(void* p); -extern int32_t bt_debug_app(void* p); -extern int32_t delay_test_app(void* p); -extern int32_t display_test_app(void* p); -extern int32_t gpio_app(void* p); -extern int32_t ibutton_app(void* p); -extern int32_t infrared_app(void* p); -extern int32_t infrared_monitor_app(void* p); -extern int32_t keypad_test_app(void* p); -extern int32_t lfrfid_app(void* p); -extern int32_t lfrfid_debug_app(void* p); -extern int32_t nfc_app(void* p); -extern int32_t passport_app(void* p); -extern int32_t scened_app(void* p); -extern int32_t storage_test_app(void* p); -extern int32_t subghz_app(void* p); -extern int32_t usb_mouse_app(void* p); -extern int32_t usb_test_app(void* p); -extern int32_t vibro_test_app(void* p); -extern int32_t bt_hid_app(void* p); -extern int32_t battery_test_app(void* p); -extern int32_t text_box_test_app(void* p); -extern int32_t file_browser_app(void* p); - -// Plugins -extern int32_t music_player_app(void* p); -extern int32_t snake_game_app(void* p); - -// On system start hooks declaration -extern void bt_on_system_start(); -extern void crypto_on_system_start(); -extern void ibutton_on_system_start(); -extern void infrared_on_system_start(); -extern void lfrfid_on_system_start(); -extern void music_player_on_system_start(); -extern void nfc_on_system_start(); -extern void storage_on_system_start(); -extern void subghz_on_system_start(); -extern void power_on_system_start(); -extern void unit_tests_on_system_start(); -extern void updater_on_system_start(); - -// Settings -extern int32_t notification_settings_app(void* p); -extern int32_t storage_settings_app(void* p); -extern int32_t bt_settings_app(void* p); -extern int32_t desktop_settings_app(void* p); -extern int32_t about_settings_app(void* p); -extern int32_t power_settings_app(void* p); -extern int32_t system_settings_app(void* p); - -const FlipperApplication FLIPPER_SERVICES[] = { -/* Services */ -#ifdef SRV_RPC - {.app = rpc_srv, - .name = "RpcSrv", - .stack_size = 1024 * 4, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_BT - {.app = bt_srv, - .name = "BtSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_CLI - {.app = cli_srv, - .name = "CliSrv", - .stack_size = 4096, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_DIALOGS - {.app = dialogs_srv, - .name = "DialogsSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_DOLPHIN - {.app = dolphin_srv, - .name = "DolphinSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_DESKTOP -#ifdef SRV_UPDATER -#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! -#endif - {.app = desktop_srv, - .name = "DesktopSrv", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_GUI - {.app = gui_srv, - .name = "GuiSrv", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_INPUT - {.app = input_srv, - .name = "InputSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_LOADER - {.app = loader_srv, - .name = "LoaderSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_NOTIFICATION - {.app = notification_srv, - .name = "NotificationSrv", - .stack_size = 1536, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_POWER - {.app = power_srv, - .name = "PowerSrv", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_STORAGE - {.app = storage_srv, - .name = "StorageSrv", - .stack_size = 3072, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_UPDATER -#ifdef SRV_DESKTOP -#error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! -#endif - {.app = updater_srv, - .name = "UpdaterSrv", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif -}; - -const size_t FLIPPER_SERVICES_COUNT = COUNT_OF(FLIPPER_SERVICES); - -const FlipperApplication FLIPPER_SYSTEM_APPS[] = { -#ifdef APP_UPDATER -#ifdef SRV_UPDATER -#error APP_UPDATER and SRV_UPDATER are mutually exclusive! -#endif - {.app = updater_srv, - .name = "UpdaterApp", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif -}; - -const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS); - -// Main menu APP -const FlipperApplication FLIPPER_APPS[] = { - -#ifdef APP_SUBGHZ - {.app = subghz_app, - .name = "Sub-GHz", - .stack_size = 2048, - .icon = &A_Sub1ghz_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_LF_RFID - {.app = lfrfid_app, - .name = "125 kHz RFID", - .stack_size = 2048, - .icon = &A_125khz_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_NFC - {.app = nfc_app, - .name = "NFC", - .stack_size = 4096, - .icon = &A_NFC_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_INFRARED - {.app = infrared_app, - .name = "Infrared", - .stack_size = 1024 * 3, - .icon = &A_Infrared_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_GPIO - {.app = gpio_app, - .name = "GPIO", - .stack_size = 1024, - .icon = &A_GPIO_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_IBUTTON - {.app = ibutton_app, - .name = "iButton", - .stack_size = 2048, - .icon = &A_iButton_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_BAD_USB - {.app = bad_usb_app, - .name = "Bad USB", - .stack_size = 2048, - .icon = &A_BadUsb_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_U2F - {.app = u2f_app, - .name = "U2F", - .stack_size = 2048, - .icon = &A_U2F_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -}; - -const size_t FLIPPER_APPS_COUNT = COUNT_OF(FLIPPER_APPS); - -// On system start hooks -const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { - crypto_on_system_start, - -#ifdef APP_INFRARED - infrared_on_system_start, -#endif - -#ifdef APP_MUSIC_PLAYER - music_player_on_system_start, -#endif - -#ifdef APP_NFC - nfc_on_system_start, -#endif - -#ifdef APP_SUBGHZ - subghz_on_system_start, -#endif - -#ifdef APP_LF_RFID - lfrfid_on_system_start, -#endif - -#ifdef APP_IBUTTON - ibutton_on_system_start, -#endif - -#ifdef SRV_BT - bt_on_system_start, -#endif - -#ifdef SRV_POWER - power_on_system_start, -#endif - -#ifdef SRV_STORAGE - storage_on_system_start, -#endif - -#ifdef APP_UNIT_TESTS - unit_tests_on_system_start, -#endif - -#ifdef APP_UPDATER - updater_on_system_start, -#endif -}; - -const size_t FLIPPER_ON_SYSTEM_START_COUNT = COUNT_OF(FLIPPER_ON_SYSTEM_START); - -// Plugin menu -const FlipperApplication FLIPPER_PLUGINS[] = { -#ifdef APP_BLE_HID - {.app = bt_hid_app, - .name = "Bluetooth Remote", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_MUSIC_PLAYER - {.app = music_player_app, - .name = "Music Player", - .stack_size = 2048, - .icon = &A_Plugins_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_SNAKE_GAME - {.app = snake_game_app, - .name = "Snake Game", - .stack_size = 1024, - .icon = &A_Plugins_14, - .flags = FlipperApplicationFlagDefault}, -#endif -}; - -const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS); - -// Plugin menu -const FlipperApplication FLIPPER_DEBUG_APPS[] = { -#ifdef APP_BLINK - {.app = blink_test_app, - .name = "Blink Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_VIBRO_TEST - {.app = vibro_test_app, - .name = "Vibro Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_KEYPAD_TEST - {.app = keypad_test_app, - .name = "Keypad Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_ACCESSOR - {.app = accessor_app, - .name = "Accessor", - .stack_size = 4096, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_USB_TEST - {.app = usb_test_app, - .name = "USB Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_USB_MOUSE - {.app = usb_mouse_app, - .name = "USB Mouse Demo", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_UART_ECHO - {.app = uart_echo_app, - .name = "Uart Echo", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_INFRARED_MONITOR - {.app = infrared_monitor_app, - .name = "Infrared Monitor", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_LF_RFID - {.app = lfrfid_debug_app, - .name = "LF-RFID Debug", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_BT - {.app = bt_debug_app, - .name = "Bluetooth Debug", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_UNIT_TESTS - {.app = delay_test_app, - .name = "Delay Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_DISPLAY_TEST - {.app = display_test_app, - .name = "Display Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_FILE_BROWSER_TEST - {.app = file_browser_app, - .name = "File Browser test", - .stack_size = 2048, - .icon = &A_BadUsb_14, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_BATTERY_TEST - {.app = battery_test_app, - .name = "Battery Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_TEXT_BOX_TEST - {.app = text_box_test_app, - .name = "Text Box Test", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif -}; - -const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS); - -#ifdef APP_ARCHIVE -const FlipperApplication FLIPPER_ARCHIVE = { - .app = archive_app, - .name = "Archive", - .stack_size = 4096, - .icon = &A_FileManager_14, - .flags = FlipperApplicationFlagDefault}; -#endif - -// Settings menu -const FlipperApplication FLIPPER_SETTINGS_APPS[] = { -#ifdef SRV_BT - {.app = bt_settings_app, - .name = "Bluetooth", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_NOTIFICATION - {.app = notification_settings_app, - .name = "LCD and Notifications", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_STORAGE - {.app = storage_settings_app, - .name = "Storage", - .stack_size = 2048, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_POWER - {.app = power_settings_app, - .name = "Power", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagInsomniaSafe}, -#endif - -#ifdef SRV_DESKTOP - {.app = desktop_settings_app, - .name = "Desktop", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_PASSPORT - {.app = passport_app, - .name = "Passport", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef SRV_GUI - {.app = system_settings_app, - .name = "System", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - -#ifdef APP_ABOUT - {.app = about_settings_app, - .name = "About", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif -}; - -const size_t FLIPPER_SETTINGS_APPS_COUNT = COUNT_OF(FLIPPER_SETTINGS_APPS); diff --git a/applications/applications.mk b/applications/applications.mk deleted file mode 100644 index e7a9ebfc..00000000 --- a/applications/applications.mk +++ /dev/null @@ -1,362 +0,0 @@ -APP_DIR = $(PROJECT_ROOT)/applications -LIB_DIR = $(PROJECT_ROOT)/lib - -CFLAGS += -I$(APP_DIR) -C_SOURCES += $(shell find $(APP_DIR) -name "*.c") -CPP_SOURCES += $(shell find $(APP_DIR) -name "*.cpp") - -RAM_EXEC ?= 0 -ifeq ($(RAM_EXEC), 1) -APP_RELEASE = 0 -SRV_GUI = 1 -SRV_INPUT = 1 -SRV_NOTIFICATION = 1 -SRV_STORAGE = 1 -SRV_UPDATER = 1 -APP_UPDATER = 0 -endif - -APP_RELEASE ?= 1 -ifeq ($(APP_RELEASE), 1) -# Services -SRV_BT = 1 -SRV_CLI = 1 -SRV_DIALOGS = 1 -SRV_DOLPHIN = 1 -SRV_GUI = 1 -SRV_INPUT = 1 -SRV_LOADER = 1 -SRV_NOTIFICATION = 1 -SRV_POWER = 1 -SRV_RPC = 1 -SRV_STORAGE = 1 - -# Apps -SRV_DESKTOP = 1 -APP_ARCHIVE = 1 -APP_GPIO = 1 -APP_IBUTTON = 1 -APP_INFRARED = 1 -APP_LF_RFID = 1 -APP_NFC = 1 -APP_SUBGHZ = 1 -APP_ABOUT = 1 -APP_PASSPORT = 1 -APP_UPDATER = 1 - -# Plugins -APP_MUSIC_PLAYER = 1 -APP_SNAKE_GAME = 1 - -# Debug -APP_ACCESSOR = 1 -APP_BLINK = 1 -APP_INFRARED_MONITOR = 1 -APP_KEYPAD_TEST = 1 -APP_SD_TEST = 1 -APP_VIBRO_TEST = 1 -APP_USB_TEST = 1 -APP_DISPLAY_TEST = 1 -APP_BLE_HID = 1 -APP_USB_MOUSE = 1 -APP_BAD_USB = 1 -APP_U2F = 1 -APP_UART_ECHO = 1 -APP_FILE_BROWSER_TEST = 1 -endif - - -# Applications -# that will be shown in menu -# Prefix with APP_* - - -APP_INFRARED_MONITOR ?= 0 -ifeq ($(APP_INFRARED_MONITOR), 1) -CFLAGS += -DAPP_INFRARED_MONITOR -SRV_GUI = 1 -endif - - -APP_UNIT_TESTS ?= 0 -ifeq ($(APP_UNIT_TESTS), 1) -CFLAGS += -DAPP_UNIT_TESTS -endif - - -APP_ARCHIVE ?= 0 -ifeq ($(APP_ARCHIVE), 1) -CFLAGS += -DAPP_ARCHIVE -SRV_GUI = 1 -endif - - -APP_BLINK ?= 0 -ifeq ($(APP_BLINK), 1) -CFLAGS += -DAPP_BLINK -SRV_GUI = 1 -endif - - -APP_SUBGHZ ?= 0 -ifeq ($(APP_SUBGHZ), 1) -CFLAGS += -DAPP_SUBGHZ -SRV_GUI = 1 -SRV_CLI = 1 -endif - - -APP_ABOUT ?= 0 -ifeq ($(APP_ABOUT), 1) -CFLAGS += -DAPP_ABOUT -SRV_GUI = 1 -endif - - -APP_PASSPORT ?= 0 -ifeq ($(APP_PASSPORT), 1) -CFLAGS += -DAPP_PASSPORT -SRV_GUI = 1 -endif - - -APP_LF_RFID ?= 0 -ifeq ($(APP_LF_RFID), 1) -CFLAGS += -DAPP_LF_RFID -SRV_GUI = 1 -endif - - -APP_NFC ?= 0 -ifeq ($(APP_NFC), 1) -CFLAGS += -DAPP_NFC -SRV_GUI = 1 -endif - - -APP_INFRARED ?= 0 -ifeq ($(APP_INFRARED), 1) -CFLAGS += -DAPP_INFRARED -SRV_GUI = 1 -endif - - -APP_VIBRO_TEST ?= 0 -ifeq ($(APP_VIBRO_TEST), 1) -CFLAGS += -DAPP_VIBRO_TEST -SRV_GUI = 1 -endif - - -APP_USB_TEST ?= 0 -ifeq ($(APP_USB_TEST), 1) -CFLAGS += -DAPP_USB_TEST -SRV_GUI = 1 -endif - -APP_UART_ECHO ?= 0 -ifeq ($(APP_UART_ECHO), 1) -CFLAGS += -DAPP_UART_ECHO -SRV_GUI = 1 -endif - -APP_DISPLAY_TEST ?= 0 -ifeq ($(APP_DISPLAY_TEST), 1) -CFLAGS += -DAPP_DISPLAY_TEST -SRV_GUI = 1 -endif - -APP_TEXT_BOX_TEST ?= 0 -ifeq ($(APP_TEXT_BOX_TEST), 1) -CFLAGS += -DAPP_TEXT_BOX_TEST -SRV_GUI = 1 -endif - -APP_BATTERY_TEST ?= 0 -ifeq ($(APP_BATTERY_TEST), 1) -CFLAGS += -DAPP_BATTERY_TEST -SRV_GUI = 1 -endif - -APP_USB_MOUSE ?= 0 -ifeq ($(APP_USB_MOUSE), 1) -CFLAGS += -DAPP_USB_MOUSE -SRV_GUI = 1 -endif - -APP_BAD_USB ?= 0 -ifeq ($(APP_BAD_USB), 1) -CFLAGS += -DAPP_BAD_USB -SRV_GUI = 1 -endif - -APP_U2F ?= 0 -ifeq ($(APP_U2F), 1) -CFLAGS += -DAPP_U2F -SRV_GUI = 1 -endif - -APP_BLE_HID ?=0 -ifeq ($(APP_BLE_HID), 1) -CFLAGS += -DAPP_BLE_HID -SRV_GUI = 1 -endif - -APP_KEYPAD_TEST ?= 0 -ifeq ($(APP_KEYPAD_TEST), 1) -CFLAGS += -DAPP_KEYPAD_TEST -SRV_GUI = 1 -endif - -APP_FILE_BROWSER_TEST ?= 0 -ifeq ($(APP_FILE_BROWSER_TEST), 1) -CFLAGS += -DAPP_FILE_BROWSER_TEST -SRV_GUI = 1 -endif - -APP_ACCESSOR ?= 0 -ifeq ($(APP_ACCESSOR), 1) -CFLAGS += -DAPP_ACCESSOR -SRV_GUI = 1 -endif - - -APP_GPIO ?= 0 -ifeq ($(APP_GPIO), 1) -CFLAGS += -DAPP_GPIO -SRV_GUI = 1 -endif - - -APP_MUSIC_PLAYER ?= 0 -ifeq ($(APP_MUSIC_PLAYER), 1) -CFLAGS += -DAPP_MUSIC_PLAYER -SRV_GUI = 1 -endif - -APP_SNAKE_GAME ?= 0 -ifeq ($(APP_SNAKE_GAME), 1) -CFLAGS += -DAPP_SNAKE_GAME -SRV_GUI = 1 -endif - -APP_IBUTTON ?= 0 -ifeq ($(APP_IBUTTON), 1) -CFLAGS += -DAPP_IBUTTON -SRV_GUI = 1 -endif - -APP_UPDATER ?= 0 -ifeq ($(APP_UPDATER), 1) -CFLAGS += -DAPP_UPDATER -SRV_GUI = 1 -SRV_STORAGE = 1 -SRV_NOTIFICATION = 1 -SRV_INPUT = 1 -endif - -# Services -# that will start with OS -# Prefix with SRV_* - - -SRV_BT ?= 0 -ifeq ($(SRV_BT), 1) -CFLAGS += -DSRV_BT -SRV_CLI = 1 -endif - - -SRV_DESKTOP ?= 0 -ifeq ($(SRV_DESKTOP), 1) -CFLAGS += -DSRV_DESKTOP -SRV_DOLPHIN = 1 -SRV_STORAGE = 1 -SRV_GUI = 1 -endif - - -SRV_UPDATER ?= 0 -ifeq ($(SRV_UPDATER), 1) -CFLAGS += -DSRV_UPDATER -SRV_STORAGE = 1 -SRV_GUI = 1 -endif - - -SRV_DOLPHIN ?= 0 -ifeq ($(SRV_DOLPHIN), 1) -CFLAGS += -DSRV_DOLPHIN -SRV_DOLPHIN_STATE_DEBUG ?= 0 -ifeq ($(SRV_DOLPHIN_STATE_DEBUG), 1) -CFLAGS += -DSRV_DOLPHIN_STATE_DEBUG -endif -endif - - -SRV_POWER ?= 0 -ifeq ($(SRV_POWER), 1) -CFLAGS += -DSRV_POWER -SRV_GUI = 1 -SRV_CLI = 1 -endif - -SRV_RPC ?= 0 -ifeq ($(SRV_RPC), 1) -CFLAGS += -DSRV_RPC -ifeq ($(SRV_RPC_DEBUG), 1) -CFLAGS += -DSRV_RPC_DEBUG -endif -SRV_CLI = 1 -endif - -SRV_LOADER ?= 0 -ifeq ($(SRV_LOADER), 1) -CFLAGS += -DSRV_LOADER -SRV_GUI = 1 -# Loader autostart hook -LOADER_AUTOSTART ?= "" -ifneq ($(strip $(LOADER_AUTOSTART)), "") -CFLAGS += -DLOADER_AUTOSTART="\"$(LOADER_AUTOSTART)\"" -endif -# Loader autostart hook END -endif - - -SRV_DIALOGS ?= 0 -ifeq ($(SRV_DIALOGS), 1) -CFLAGS += -DSRV_DIALOGS -SRV_GUI = 1 -endif - - -SRV_GUI ?= 0 -ifeq ($(SRV_GUI), 1) -CFLAGS += -DSRV_GUI -SRV_INPUT = 1 -SRV_NOTIFICATION = 1 -endif - - -SRV_INPUT ?= 0 -ifeq ($(SRV_INPUT), 1) -CFLAGS += -DSRV_INPUT -endif - - -SRV_CLI ?= 0 -ifeq ($(SRV_CLI), 1) -CFLAGS += -DSRV_CLI -endif - - -SRV_NOTIFICATION ?= 0 -ifeq ($(SRV_NOTIFICATION), 1) -CFLAGS += -DSRV_NOTIFICATION -endif - - -SRV_STORAGE ?= 0 -ifeq ($(SRV_STORAGE), 1) -CFLAGS += -DSRV_STORAGE -endif diff --git a/applications/archive/application.fam b/applications/archive/application.fam new file mode 100644 index 00000000..f0a980ab --- /dev/null +++ b/applications/archive/application.fam @@ -0,0 +1,11 @@ +App( + appid="archive", + name="Archive", + apptype=FlipperAppType.ARCHIVE, + entry_point="archive_app", + cdefines=["APP_ARCHIVE"], + requires=["gui"], + stack_size=4 * 1024, + icon="A_FileManager_14", + order=0, +) diff --git a/applications/bad_usb/application.fam b/applications/bad_usb/application.fam new file mode 100644 index 00000000..4da34f0d --- /dev/null +++ b/applications/bad_usb/application.fam @@ -0,0 +1,14 @@ +App( + appid="bad_usb", + name="Bad USB", + apptype=FlipperAppType.APP, + entry_point="bad_usb_app", + cdefines=["APP_BAD_USB"], + requires=[ + "gui", + "dialogs", + ], + stack_size=2 * 1024, + icon="A_BadUsb_14", + order=70, +) diff --git a/applications/bad_usb/bad_usb_script.c b/applications/bad_usb/bad_usb_script.c index 685e5083..0266b51f 100644 --- a/applications/bad_usb/bad_usb_script.c +++ b/applications/bad_usb/bad_usb_script.c @@ -440,9 +440,9 @@ static void bad_usb_hid_state_callback(bool state, void* context) { BadUsbScript* bad_usb = context; if(state == true) - osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtConnect); + furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtConnect); else - osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtDisconnect); } static int32_t bad_usb_worker(void* context) { @@ -483,8 +483,8 @@ static int32_t bad_usb_worker(void* context) { bad_usb->st.state = worker_state; } else if(worker_state == BadUsbStateNotConnected) { // State: USB not connected - uint32_t flags = - osThreadFlagsWait(WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever); + uint32_t flags = furi_thread_flags_wait( + WorkerEvtEnd | WorkerEvtConnect, osFlagsWaitAny, osWaitForever); furi_check((flags & osFlagsError) == 0); if(flags & WorkerEvtEnd) { break; @@ -494,7 +494,7 @@ static int32_t bad_usb_worker(void* context) { bad_usb->st.state = worker_state; } else if(worker_state == BadUsbStateIdle) { // State: ready to start - uint32_t flags = osThreadFlagsWait( + uint32_t flags = furi_thread_flags_wait( WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, osFlagsWaitAny, osWaitForever); @@ -518,7 +518,7 @@ static int32_t bad_usb_worker(void* context) { } else if(worker_state == BadUsbStateRunning) { // State: running uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); - uint32_t flags = osThreadFlagsWait( + uint32_t flags = furi_thread_flags_wait( WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, osFlagsWaitAny, delay_cur); delay_val -= delay_cur; if(!(flags & osFlagsError)) { @@ -561,7 +561,7 @@ static int32_t bad_usb_worker(void* context) { } else if( (worker_state == BadUsbStateFileError) || (worker_state == BadUsbStateScriptError)) { // State: error - uint32_t flags = osThreadFlagsWait( + uint32_t flags = furi_thread_flags_wait( WorkerEvtEnd, osFlagsWaitAny, osWaitForever); // Waiting for exit command furi_check((flags & osFlagsError) == 0); if(flags & WorkerEvtEnd) { @@ -605,7 +605,7 @@ BadUsbScript* bad_usb_script_open(string_t file_path) { void bad_usb_script_close(BadUsbScript* bad_usb) { furi_assert(bad_usb); - osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtEnd); + furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtEnd); furi_thread_join(bad_usb->thread); furi_thread_free(bad_usb->thread); string_clear(bad_usb->file_path); @@ -614,7 +614,7 @@ void bad_usb_script_close(BadUsbScript* bad_usb) { void bad_usb_script_toggle(BadUsbScript* bad_usb) { furi_assert(bad_usb); - osThreadFlagsSet(furi_thread_get_thread_id(bad_usb->thread), WorkerEvtToggle); + furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtToggle); } BadUsbState* bad_usb_script_get_state(BadUsbScript* bad_usb) { diff --git a/applications/bt/application.fam b/applications/bt/application.fam new file mode 100644 index 00000000..248386ff --- /dev/null +++ b/applications/bt/application.fam @@ -0,0 +1,66 @@ +App( + appid="bt", + name="BtSrv", + apptype=FlipperAppType.SERVICE, + entry_point="bt_srv", + cdefines=["SRV_BT"], + requires=[ + "cli", + "dialogs", + ], + provides=[ + "bt_start", + "bt_settings", + "bt_debug", + ], + stack_size=1 * 1024, + order=20, +) + +App( + appid="bt_start", + apptype=FlipperAppType.STARTUP, + entry_point="bt_on_system_start", + order=70, +) + +App( + appid="bt_settings", + name="Bluetooth", + apptype=FlipperAppType.SETTINGS, + entry_point="bt_settings_app", + stack_size=1 * 1024, + requires=[ + "bt", + "gui", + ], + order=10, +) + +App( + appid="bt_debug", + name="Bluetooth Debug", + apptype=FlipperAppType.DEBUG, + entry_point="bt_debug_app", + stack_size=1 * 1024, + requires=[ + "bt", + "gui", + "dialogs", + ], + order=110, +) + +App( + appid="bt_hid", + name="Bluetooth Remote", + apptype=FlipperAppType.PLUGIN, + entry_point="bt_hid_app", + stack_size=1 * 1024, + cdefines=["APP_BLE_HID"], + requires=[ + "bt", + "gui", + ], + order=10, +) diff --git a/applications/cli/application.fam b/applications/cli/application.fam new file mode 100644 index 00000000..73c70aa4 --- /dev/null +++ b/applications/cli/application.fam @@ -0,0 +1,9 @@ +App( + appid="cli", + name="CliSrv", + apptype=FlipperAppType.SERVICE, + entry_point="cli_srv", + cdefines=["SRV_CLI"], + stack_size=4 * 1024, + order=30, +) diff --git a/applications/cli/cli.c b/applications/cli/cli.c index eefbb305..aa48e93b 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -149,7 +149,8 @@ void cli_reset(Cli* cli) { } static void cli_handle_backspace(Cli* cli) { - if(string_size(cli->line) > 0) { + if(cli->cursor_position > 0) { + furi_assert(string_size(cli->line) > 0); // Other side printf("\e[D\e[1P"); fflush(stdout); diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index 8271ab31..c99f4edc 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -255,19 +255,19 @@ void cli_command_ps(Cli* cli, string_t args, void* context) { UNUSED(context); const uint8_t threads_num_max = 32; - osThreadId_t threads_id[threads_num_max]; - uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max); + FuriThreadId threads_ids[threads_num_max]; + uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max); printf( "%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free"); for(uint8_t i = 0; i < thread_num; i++) { - TaskControlBlock* tcb = (TaskControlBlock*)threads_id[i]; + TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i]; printf( "%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n", - osThreadGetName(threads_id[i]), + furi_thread_get_name(threads_ids[i]), (uint32_t)tcb->pxStack, - memmgr_heap_get_thread_memory(threads_id[i]), + memmgr_heap_get_thread_memory(threads_ids[i]), (uint32_t)(tcb->pxEndOfStack - tcb->pxStack + 1) * sizeof(StackType_t), - osThreadGetStackSpace(threads_id[i])); + furi_thread_get_stack_space(threads_ids[i])); } printf("\r\nTotal: %d", thread_num); } diff --git a/applications/cli/cli_vcp.c b/applications/cli/cli_vcp.c index 84edca18..7e23e4b1 100644 --- a/applications/cli/cli_vcp.c +++ b/applications/cli/cli_vcp.c @@ -79,7 +79,7 @@ static void cli_vcp_init() { } static void cli_vcp_deinit() { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStop); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStop); furi_thread_join(vcp->thread); furi_thread_free(vcp->thread); vcp->thread = NULL; @@ -102,7 +102,8 @@ static int32_t vcp_worker(void* context) { vcp->running = true; while(1) { - uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + uint32_t flags = + furi_thread_flags_wait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); furi_assert((flags & osFlagsError) == 0); // VCP session opened @@ -232,7 +233,7 @@ static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) { FURI_LOG_D(TAG, "rx %u ", batch_size); #endif if(len == 0) break; - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamRx); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamRx); size -= len; buffer += len; rx_cnt += len; @@ -261,7 +262,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) { if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN; xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever); - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx); #ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "tx %u", batch_size); #endif @@ -283,7 +284,7 @@ static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { static void vcp_state_callback(void* context, uint8_t state) { UNUSED(context); if(state == 0) { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtDisconnect); } } @@ -293,21 +294,21 @@ static void vcp_on_cdc_control_line(void* context, uint8_t state) { bool dtr = state & (1 << 0); if(dtr == true) { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtConnect); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtConnect); } else { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtDisconnect); } } static void vcp_on_cdc_rx(void* context) { UNUSED(context); - uint32_t ret = osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtRx); + uint32_t ret = furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtRx); furi_check((ret & osFlagsError) == 0); } static void vcp_on_cdc_tx_complete(void* context) { UNUSED(context); - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); + furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtTx); } static bool cli_vcp_is_connected(void) { diff --git a/applications/crypto/application.fam b/applications/crypto/application.fam new file mode 100644 index 00000000..7771c5ed --- /dev/null +++ b/applications/crypto/application.fam @@ -0,0 +1,6 @@ +App( + appid="crypto_start", + apptype=FlipperAppType.STARTUP, + entry_point="crypto_on_system_start", + order=10, +) diff --git a/applications/debug_tools/application.fam b/applications/debug_tools/application.fam new file mode 100644 index 00000000..8cb495b0 --- /dev/null +++ b/applications/debug_tools/application.fam @@ -0,0 +1,115 @@ +App( + appid="debug_apps", + name="Basic debug apps bundle", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "blink_test", + "vibro_test", + "keypad_test", + "usb_test", + "usb_mouse", + "uart_echo", + "display_test", + "text_box_test", + "file_browser_test", + ], +) + +App( + appid="blink_test", + name="Blink Test", + apptype=FlipperAppType.DEBUG, + entry_point="blink_test_app", + cdefines=["APP_BLINK"], + requires=["gui"], + stack_size=1 * 1024, + order=10, +) + +App( + appid="vibro_test", + name="Vibro Test", + apptype=FlipperAppType.DEBUG, + entry_point="vibro_test_app", + cdefines=["APP_VIBRO_TEST"], + requires=["gui"], + stack_size=1 * 1024, + order=20, +) + +App( + appid="keypad_test", + name="Keypad Test", + apptype=FlipperAppType.DEBUG, + entry_point="keypad_test_app", + cdefines=["APP_KEYPAD_TEST"], + requires=["gui"], + stack_size=1 * 1024, + order=30, +) + +App( + appid="usb_test", + name="USB Test", + apptype=FlipperAppType.DEBUG, + entry_point="usb_test_app", + cdefines=["APP_USB_TEST"], + requires=["gui"], + stack_size=1 * 1024, + order=50, +) + +App( + appid="usb_mouse", + name="USB Mouse Demo", + apptype=FlipperAppType.DEBUG, + entry_point="usb_mouse_app", + cdefines=["APP_USB_MOUSE"], + requires=["gui"], + stack_size=1 * 1024, + order=60, +) + +App( + appid="uart_echo", + name="UART Echo", + apptype=FlipperAppType.DEBUG, + entry_point="uart_echo_app", + cdefines=["APP_UART_ECHO"], + requires=["gui"], + stack_size=2 * 1024, + order=70, +) + +App( + appid="display_test", + name="Display Test", + apptype=FlipperAppType.DEBUG, + entry_point="display_test_app", + cdefines=["APP_DISPLAY_TEST"], + requires=["gui"], + stack_size=1 * 1024, + order=120, +) + +App( + appid="text_box_test", + name="Text Box Test", + apptype=FlipperAppType.DEBUG, + entry_point="text_box_test_app", + cdefines=["APP_TEXT_BOX_TEST"], + requires=["gui"], + stack_size=1 * 1024, + order=140, +) + +App( + appid="file_browser_test", + name="File Browser Test", + apptype=FlipperAppType.DEBUG, + entry_point="file_browser_app", + cdefines=["APP_FILE_BROWSER_TEST"], + requires=["gui"], + stack_size=2 * 1024, + order=150, +) diff --git a/applications/debug_tools/uart_echo.c b/applications/debug_tools/uart_echo.c index 206c6c06..213769a5 100644 --- a/applications/debug_tools/uart_echo.c +++ b/applications/debug_tools/uart_echo.c @@ -97,7 +97,7 @@ static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { if(ev == UartIrqEventRXNE) { xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken); - osThreadFlagsSet(furi_thread_get_thread_id(app->worker_thread), WorkerEventRx); + furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } @@ -149,7 +149,8 @@ static int32_t uart_echo_worker(void* context) { UartEchoApp* app = context; while(1) { - uint32_t events = osThreadFlagsWait(WORKER_EVENTS_MASK, osFlagsWaitAny, osWaitForever); + uint32_t events = + furi_thread_flags_wait(WORKER_EVENTS_MASK, osFlagsWaitAny, osWaitForever); furi_check((events & osFlagsError) == 0); if(events & WorkerEventStop) break; @@ -234,7 +235,7 @@ static UartEchoApp* uart_echo_app_alloc() { static void uart_echo_app_free(UartEchoApp* app) { furi_assert(app); - osThreadFlagsSet(furi_thread_get_thread_id(app->worker_thread), WorkerEventStop); + furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop); furi_thread_join(app->worker_thread); furi_thread_free(app->worker_thread); diff --git a/applications/desktop/application.fam b/applications/desktop/application.fam new file mode 100644 index 00000000..5f3dcdfd --- /dev/null +++ b/applications/desktop/application.fam @@ -0,0 +1,30 @@ +App( + appid="desktop", + name="DesktopSrv", + apptype=FlipperAppType.SERVICE, + entry_point="desktop_srv", + cdefines=["SRV_DESKTOP"], + requires=[ + "gui", + "dolphin", + "storage", + "input", + ], + provides=["desktop_settings"], + conflicts=["updater"], + stack_size=2 * 1024, + order=60, +) + +App( + appid="desktop_settings", + name="Desktop", + apptype=FlipperAppType.SETTINGS, + entry_point="desktop_settings_app", + requires=[ + "desktop", + "gui", + ], + stack_size=1 * 1024, + order=50, +) diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index 34c169e0..52091753 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -158,11 +158,11 @@ Desktop* desktop_alloc() { desktop->lock_menu = desktop_lock_menu_alloc(); desktop->debug_view = desktop_debug_alloc(); - desktop->first_start_view = desktop_first_start_alloc(); desktop->hw_mismatch_popup = popup_alloc(); desktop->locked_view = desktop_view_locked_alloc(); desktop->pin_input_view = desktop_view_pin_input_alloc(); desktop->pin_timeout_view = desktop_view_pin_timeout_alloc(); + desktop->slideshow_view = desktop_view_slideshow_alloc(); desktop->main_view_stack = view_stack_alloc(); desktop->main_view = desktop_main_alloc(); @@ -193,10 +193,6 @@ Desktop* desktop_alloc() { desktop_lock_menu_get_view(desktop->lock_menu)); view_dispatcher_add_view( desktop->view_dispatcher, DesktopViewIdDebug, desktop_debug_get_view(desktop->debug_view)); - view_dispatcher_add_view( - desktop->view_dispatcher, - DesktopViewIdFirstStart, - desktop_first_start_get_view(desktop->first_start_view)); view_dispatcher_add_view( desktop->view_dispatcher, DesktopViewIdHwMismatch, @@ -209,6 +205,10 @@ Desktop* desktop_alloc() { desktop->view_dispatcher, DesktopViewIdPinInput, desktop_view_pin_input_get_view(desktop->pin_input_view)); + view_dispatcher_add_view( + desktop->view_dispatcher, + DesktopViewIdSlideshow, + desktop_view_slideshow_get_view(desktop->slideshow_view)); // Lock icon desktop->lock_viewport = view_port_alloc(); @@ -258,7 +258,6 @@ void desktop_free(Desktop* desktop) { view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdDebug); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdFirstStart); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdHwMismatch); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinInput); view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinTimeout); @@ -274,7 +273,6 @@ void desktop_free(Desktop* desktop) { desktop_lock_menu_free(desktop->lock_menu); desktop_view_locked_free(desktop->locked_view); desktop_debug_free(desktop->debug_view); - desktop_first_start_free(desktop->first_start_view); popup_free(desktop->hw_mismatch_popup); desktop_view_pin_timeout_free(desktop->pin_timeout_view); @@ -290,9 +288,9 @@ void desktop_free(Desktop* desktop) { free(desktop); } -static bool desktop_is_first_start() { +static bool desktop_check_file_flag(const char* flag_path) { Storage* storage = furi_record_open("storage"); - bool exists = storage_common_stat(storage, "/int/first_start", NULL) == FSE_OK; + bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK; furi_record_close("storage"); return exists; @@ -320,8 +318,8 @@ int32_t desktop_srv(void* p) { desktop_lock(desktop); } - if(desktop_is_first_start()) { - scene_manager_next_scene(desktop->scene_manager, DesktopSceneFirstStart); + if(desktop_check_file_flag("/int/slideshow")) { + scene_manager_next_scene(desktop->scene_manager, DesktopSceneSlideshow); } if(!furi_hal_version_do_i_belong_here()) { diff --git a/applications/desktop/desktop_i.h b/applications/desktop/desktop_i.h index 2888f099..8dc92e84 100644 --- a/applications/desktop/desktop_i.h +++ b/applications/desktop/desktop_i.h @@ -6,9 +6,9 @@ #include "views/desktop_view_pin_input.h" #include "views/desktop_view_locked.h" #include "views/desktop_view_main.h" -#include "views/desktop_view_first_start.h" #include "views/desktop_view_lock_menu.h" #include "views/desktop_view_debug.h" +#include "views/desktop_view_slideshow.h" #include "desktop/desktop_settings/desktop_settings.h" #include @@ -28,10 +28,10 @@ typedef enum { DesktopViewIdLockMenu, DesktopViewIdLocked, DesktopViewIdDebug, - DesktopViewIdFirstStart, DesktopViewIdHwMismatch, DesktopViewIdPinInput, DesktopViewIdPinTimeout, + DesktopViewIdSlideshow, DesktopViewIdTotal, } DesktopViewId; @@ -43,13 +43,13 @@ struct Desktop { ViewDispatcher* view_dispatcher; SceneManager* scene_manager; - DesktopFirstStartView* first_start_view; Popup* hw_mismatch_popup; DesktopLockMenuView* lock_menu; DesktopDebugView* debug_view; DesktopViewLocked* locked_view; DesktopMainView* main_view; DesktopViewPinTimeout* pin_timeout_view; + DesktopSlideshowView* slideshow_view; ViewStack* main_view_stack; ViewStack* locked_view_stack; diff --git a/applications/desktop/helpers/slideshow.c b/applications/desktop/helpers/slideshow.c new file mode 100644 index 00000000..37f66cf3 --- /dev/null +++ b/applications/desktop/helpers/slideshow.c @@ -0,0 +1,115 @@ +#include "slideshow.h" + +#include +#include +#include +#include +#include + +#define SLIDESHOW_MAGIC 0x72676468 +#define SLIDESHOW_MAX_SUPPORTED_VERSION 1 + +struct Slideshow { + Icon icon; + uint32_t current_frame; +}; + +#pragma pack(push, 1) + +typedef struct { + uint32_t magic; + uint8_t version; + uint8_t width; + uint8_t height; + uint8_t frame_count; +} SlideshowFileHeader; +_Static_assert(sizeof(SlideshowFileHeader) == 8, "Incorrect SlideshowFileHeader size"); + +typedef struct { + uint16_t size; +} SlideshowFrameHeader; +_Static_assert(sizeof(SlideshowFrameHeader) == 2, "Incorrect SlideshowFrameHeader size"); + +#pragma pack(pop) + +Slideshow* slideshow_alloc() { + Slideshow* ret = malloc(sizeof(Slideshow)); + return ret; +} + +void slideshow_free(Slideshow* slideshow) { + Icon* icon = &slideshow->icon; + if(icon) { + for(int frame_idx = 0; frame_idx < icon->frame_count; ++frame_idx) { + uint8_t* frame_data = (uint8_t*)icon->frames[frame_idx]; + free(frame_data); + } + free((uint8_t**)icon->frames); + } + free(slideshow); +} + +bool slideshow_load(Slideshow* slideshow, const char* fspath) { + Storage* storage = furi_record_open("storage"); + File* slideshow_file = storage_file_alloc(storage); + bool load_success = false; + do { + if(!storage_file_open(slideshow_file, fspath, FSAM_READ, FSOM_OPEN_EXISTING)) { + break; + } + SlideshowFileHeader header; + if((storage_file_read(slideshow_file, &header, sizeof(header)) != sizeof(header)) || + (header.magic != SLIDESHOW_MAGIC) || + (header.version > SLIDESHOW_MAX_SUPPORTED_VERSION)) { + break; + } + Icon* icon = &slideshow->icon; + FURI_CONST_ASSIGN(icon->frame_count, header.frame_count); + FURI_CONST_ASSIGN(icon->width, header.width); + FURI_CONST_ASSIGN(icon->height, header.height); + icon->frames = malloc(header.frame_count * sizeof(uint8_t*)); + for(int frame_idx = 0; frame_idx < header.frame_count; ++frame_idx) { + SlideshowFrameHeader frame_header; + if(storage_file_read(slideshow_file, &frame_header, sizeof(frame_header)) != + sizeof(frame_header)) { + break; + } + FURI_CONST_ASSIGN_PTR(icon->frames[frame_idx], malloc(frame_header.size)); + uint8_t* frame_data = (uint8_t*)icon->frames[frame_idx]; + if(storage_file_read(slideshow_file, frame_data, frame_header.size) != + frame_header.size) { + break; + } + load_success = (frame_idx + 1) == header.frame_count; + } + } while(false); + storage_file_free(slideshow_file); + furi_record_close("storage"); + return load_success; +} + +bool slideshow_advance(Slideshow* slideshow) { + uint8_t next_frame = slideshow->current_frame + 1; + if(next_frame < slideshow->icon.frame_count) { + slideshow->current_frame = next_frame; + return true; + } + return false; +} + +void slideshow_goback(Slideshow* slideshow) { + if(slideshow->current_frame > 0) { + slideshow->current_frame--; + } +} + +void slideshow_draw(Slideshow* slideshow, Canvas* canvas, uint8_t x, uint8_t y) { + furi_assert(slideshow->current_frame < slideshow->icon.frame_count); + canvas_draw_bitmap( + canvas, + x, + y, + slideshow->icon.width, + slideshow->icon.height, + slideshow->icon.frames[slideshow->current_frame]); +} \ No newline at end of file diff --git a/applications/desktop/helpers/slideshow.h b/applications/desktop/helpers/slideshow.h new file mode 100644 index 00000000..db19779a --- /dev/null +++ b/applications/desktop/helpers/slideshow.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +typedef struct Slideshow Slideshow; + +Slideshow* slideshow_alloc(); + +void slideshow_free(Slideshow* slideshow); +bool slideshow_load(Slideshow* slideshow, const char* fspath); +void slideshow_goback(Slideshow* slideshow); +bool slideshow_advance(Slideshow* slideshow); +void slideshow_draw(Slideshow* slideshow, Canvas* canvas, uint8_t x, uint8_t y); diff --git a/applications/desktop/scenes/desktop_scene_config.h b/applications/desktop/scenes/desktop_scene_config.h index c84d6ff8..c153972b 100644 --- a/applications/desktop/scenes/desktop_scene_config.h +++ b/applications/desktop/scenes/desktop_scene_config.h @@ -1,9 +1,9 @@ ADD_SCENE(desktop, main, Main) ADD_SCENE(desktop, lock_menu, LockMenu) ADD_SCENE(desktop, debug, Debug) -ADD_SCENE(desktop, first_start, FirstStart) ADD_SCENE(desktop, hw_mismatch, HwMismatch) ADD_SCENE(desktop, fault, Fault) ADD_SCENE(desktop, locked, Locked) ADD_SCENE(desktop, pin_input, PinInput) ADD_SCENE(desktop, pin_timeout, PinTimeout) +ADD_SCENE(desktop, slideshow, Slideshow) diff --git a/applications/desktop/scenes/desktop_scene_first_start.c b/applications/desktop/scenes/desktop_scene_first_start.c deleted file mode 100644 index dbdf8919..00000000 --- a/applications/desktop/scenes/desktop_scene_first_start.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -#include "../desktop_i.h" -#include "../views/desktop_view_first_start.h" -#include "../views/desktop_events.h" - -void desktop_scene_first_start_callback(DesktopEvent event, void* context) { - Desktop* desktop = (Desktop*)context; - view_dispatcher_send_custom_event(desktop->view_dispatcher, event); -} - -void desktop_scene_first_start_on_enter(void* context) { - Desktop* desktop = (Desktop*)context; - DesktopFirstStartView* first_start_view = desktop->first_start_view; - - desktop_first_start_set_callback( - first_start_view, desktop_scene_first_start_callback, desktop); - - view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdFirstStart); -} - -bool desktop_scene_first_start_on_event(void* context, SceneManagerEvent event) { - Desktop* desktop = (Desktop*)context; - bool consumed = false; - Storage* storage = NULL; - Power* power = NULL; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case DesktopFirstStartCompleted: - storage = furi_record_open("storage"); - storage_common_remove(storage, "/int/first_start"); - furi_record_close("storage"); - scene_manager_previous_scene(desktop->scene_manager); - consumed = true; - break; - case DesktopFirstStartPoweroff: - power = furi_record_open("power"); - power_off(power); - furi_record_close("power"); - consumed = true; - break; - - default: - break; - } - } - return consumed; -} - -void desktop_scene_first_start_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/desktop/scenes/desktop_scene_slideshow.c b/applications/desktop/scenes/desktop_scene_slideshow.c new file mode 100644 index 00000000..70080127 --- /dev/null +++ b/applications/desktop/scenes/desktop_scene_slideshow.c @@ -0,0 +1,45 @@ +#include + +#include "../desktop_i.h" +#include "../views/desktop_view_slideshow.h" +#include "../views/desktop_events.h" + +void desktop_scene_slideshow_callback(DesktopEvent event, void* context) { + Desktop* desktop = (Desktop*)context; + view_dispatcher_send_custom_event(desktop->view_dispatcher, event); +} + +void desktop_scene_slideshow_on_enter(void* context) { + Desktop* desktop = (Desktop*)context; + DesktopSlideshowView* slideshow_view = desktop->slideshow_view; + + desktop_view_slideshow_set_callback(slideshow_view, desktop_scene_slideshow_callback, desktop); + + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdSlideshow); +} + +bool desktop_scene_slideshow_on_event(void* context, SceneManagerEvent event) { + Desktop* desktop = (Desktop*)context; + bool consumed = false; + Storage* storage = NULL; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DesktopSlideshowCompleted: + storage = furi_record_open("storage"); + storage_common_remove(storage, "/int/slideshow"); + furi_record_close("storage"); + scene_manager_previous_scene(desktop->scene_manager); + consumed = true; + break; + + default: + break; + } + } + return consumed; +} + +void desktop_scene_slideshow_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/desktop/views/desktop_events.h b/applications/desktop/views/desktop_events.h index bbb6ff62..4ff5f795 100644 --- a/applications/desktop/views/desktop_events.h +++ b/applications/desktop/views/desktop_events.h @@ -26,9 +26,6 @@ typedef enum { DesktopDebugEventSaveState, DesktopDebugEventExit, - DesktopFirstStartCompleted, - DesktopFirstStartPoweroff, - DesktopLockMenuEventLock, DesktopLockMenuEventPinLock, DesktopLockMenuEventExit, @@ -37,6 +34,8 @@ typedef enum { DesktopAnimationEventNewIdleAnimation, DesktopAnimationEventInteractAnimation, + DesktopSlideshowCompleted, + // Global events DesktopGlobalBeforeAppStarted, DesktopGlobalAfterAppFinished, diff --git a/applications/desktop/views/desktop_view_debug.c b/applications/desktop/views/desktop_view_debug.c index 6ac62b49..3a6c87f1 100644 --- a/applications/desktop/views/desktop_view_debug.c +++ b/applications/desktop/views/desktop_view_debug.c @@ -46,7 +46,10 @@ void desktop_debug_render(Canvas* canvas, void* model) { canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); ver = furi_hal_version_get_firmware_version(); - + const BleGlueC2Info* c2_ver = NULL; +#ifdef SRV_BT + c2_ver = ble_glue_get_c2_info(); +#endif if(!ver) { canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, "No info"); return; @@ -63,10 +66,11 @@ void desktop_debug_render(Canvas* canvas, void* model) { snprintf( buffer, sizeof(buffer), - "%s%s [%s]", + "%s%s [%s] %s", version_get_dirty_flag(ver) ? "[!] " : "", version_get_githash(ver), - version_get_gitbranchnum(ver)); + version_get_gitbranchnum(ver), + c2_ver ? c2_ver->StackTypeString : ""); canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer); snprintf( diff --git a/applications/desktop/views/desktop_view_first_start.c b/applications/desktop/views/desktop_view_first_start.c deleted file mode 100644 index 87c07ad2..00000000 --- a/applications/desktop/views/desktop_view_first_start.c +++ /dev/null @@ -1,166 +0,0 @@ -#include -#include -#include - -#include "../desktop_i.h" -#include "desktop_view_first_start.h" - -#define DESKTOP_FIRST_START_POWEROFF_SHORT 5000 -#define DESKTOP_FIRST_START_POWEROFF_LONG (60 * 60 * 1000) - -struct DesktopFirstStartView { - View* view; - DesktopFirstStartViewCallback callback; - void* context; - osTimerId_t timer; -}; - -typedef struct { - uint8_t page; -} DesktopFirstStartViewModel; - -static void desktop_first_start_draw(Canvas* canvas, void* model) { - DesktopFirstStartViewModel* m = model; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - uint8_t width = canvas_width(canvas); - uint8_t height = canvas_height(canvas); - const char* my_name = furi_hal_version_get_name_ptr(); - if(m->page == 0) { - canvas_draw_icon(canvas, 0, height - 51, &I_DolphinFirstStart0_70x53); - elements_multiline_text_framed( - canvas, 75, 16 + STATUS_BAR_Y_SHIFT, "Hey m8,\npress > to\ncontinue"); - } else if(m->page == 1) { - canvas_draw_icon(canvas, 0, height - 51, &I_DolphinFirstStart1_59x53); - elements_multiline_text_framed( - canvas, 64, 16 + STATUS_BAR_Y_SHIFT, "First Of All,\n... >"); - } else if(m->page == 2) { - canvas_draw_icon(canvas, 0, height - 51, &I_DolphinFirstStart2_59x51); - elements_multiline_text_framed( - canvas, 64, 16 + STATUS_BAR_Y_SHIFT, "Thank you\nfor your\nsupport! >"); - } else if(m->page == 3) { - canvas_draw_icon(canvas, width - 57, height - 45, &I_DolphinFirstStart3_57x48); - elements_multiline_text_framed( - canvas, 0, 16 + STATUS_BAR_Y_SHIFT, "Kickstarter\ncampaign\nwas INSANE! >"); - } else if(m->page == 4) { - canvas_draw_icon(canvas, width - 67, height - 51, &I_DolphinFirstStart4_67x53); - elements_multiline_text_framed( - canvas, 0, 13 + STATUS_BAR_Y_SHIFT, "Now\nallow me\nto introduce\nmyself >"); - } else if(m->page == 5) { - char buf[64]; - snprintf( - buf, - 64, - "%s %s%s", - "I am", - my_name ? my_name : "Unknown", - ",\ncyberdolphin\nliving in your\npocket >"); - canvas_draw_icon(canvas, 0, height - 49, &I_DolphinFirstStart5_54x49); - elements_multiline_text_framed(canvas, 60, 13 + STATUS_BAR_Y_SHIFT, buf); - } else if(m->page == 6) { - canvas_draw_icon(canvas, 0, height - 51, &I_DolphinFirstStart6_58x54); - elements_multiline_text_framed( - canvas, - 63, - 13 + STATUS_BAR_Y_SHIFT, - "I can grow\nsmart'n'cool\nif you use me\noften >"); - } else if(m->page == 7) { - canvas_draw_icon(canvas, width - 61, height - 51, &I_DolphinFirstStart7_61x51); - elements_multiline_text_framed( - canvas, 0, 13 + STATUS_BAR_Y_SHIFT, "As long as\nyou read, write\nand emulate >"); - } else if(m->page == 8) { - canvas_draw_icon(canvas, width - 56, height - 51, &I_DolphinFirstStart8_56x51); - elements_multiline_text_framed( - canvas, - 0, - 13 + STATUS_BAR_Y_SHIFT, - "You can check\nmy level and\nmood in the\nPassport menu"); - } -} - -static bool desktop_first_start_input(InputEvent* event, void* context) { - furi_assert(event); - DesktopFirstStartView* instance = context; - - if(event->type == InputTypeShort) { - DesktopFirstStartViewModel* model = view_get_model(instance->view); - if(event->key == InputKeyLeft) { - if(model->page > 0) model->page--; - } else if(event->key == InputKeyRight) { - uint32_t page = ++model->page; - if(page > 8) { - instance->callback(DesktopFirstStartCompleted, instance->context); - } - } - view_commit_model(instance->view, true); - } - - if(event->key == InputKeyOk) { - if(event->type == InputTypePress) { - osTimerStart(instance->timer, DESKTOP_FIRST_START_POWEROFF_SHORT); - } else if(event->type == InputTypeRelease) { - osTimerStop(instance->timer); - } - } - - return true; -} - -static void desktop_first_start_timer_callback(void* context) { - DesktopFirstStartView* instance = context; - instance->callback(DesktopFirstStartPoweroff, instance->context); -} - -static void desktop_first_start_enter(void* context) { - DesktopFirstStartView* instance = context; - - furi_assert(instance->timer == NULL); - instance->timer = osTimerNew(desktop_first_start_timer_callback, osTimerOnce, instance, NULL); - - osTimerStart(instance->timer, DESKTOP_FIRST_START_POWEROFF_LONG); -} - -static void desktop_first_start_exit(void* context) { - DesktopFirstStartView* instance = context; - - osTimerStop(instance->timer); - osTimerDelete(instance->timer); - instance->timer = NULL; -} - -DesktopFirstStartView* desktop_first_start_alloc() { - DesktopFirstStartView* instance = malloc(sizeof(DesktopFirstStartView)); - instance->view = view_alloc(); - view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(DesktopFirstStartViewModel)); - view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)desktop_first_start_draw); - view_set_input_callback(instance->view, desktop_first_start_input); - view_set_enter_callback(instance->view, desktop_first_start_enter); - view_set_exit_callback(instance->view, desktop_first_start_exit); - - return instance; -} - -void desktop_first_start_free(DesktopFirstStartView* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* desktop_first_start_get_view(DesktopFirstStartView* instance) { - furi_assert(instance); - return instance->view; -} - -void desktop_first_start_set_callback( - DesktopFirstStartView* instance, - DesktopFirstStartViewCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} diff --git a/applications/desktop/views/desktop_view_first_start.h b/applications/desktop/views/desktop_view_first_start.h deleted file mode 100644 index 9b7b3c93..00000000 --- a/applications/desktop/views/desktop_view_first_start.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -#include "desktop_events.h" - -typedef struct DesktopFirstStartView DesktopFirstStartView; - -typedef void (*DesktopFirstStartViewCallback)(DesktopEvent event, void* context); - -DesktopFirstStartView* desktop_first_start_alloc(); - -void desktop_first_start_free(DesktopFirstStartView* main_view); - -View* desktop_first_start_get_view(DesktopFirstStartView* main_view); - -void desktop_first_start_set_callback( - DesktopFirstStartView* main_view, - DesktopFirstStartViewCallback callback, - void* context); diff --git a/applications/desktop/views/desktop_view_slideshow.c b/applications/desktop/views/desktop_view_slideshow.c new file mode 100644 index 00000000..97f779b5 --- /dev/null +++ b/applications/desktop/views/desktop_view_slideshow.c @@ -0,0 +1,108 @@ +#include +#include +#include + +#include "../desktop_i.h" +#include "desktop_view_slideshow.h" +#include "../helpers/slideshow.h" + +struct DesktopSlideshowView { + View* view; + DesktopSlideshowViewCallback callback; + void* context; +}; + +typedef struct { + uint8_t page; + Slideshow* slideshow; +} DesktopSlideshowViewModel; + +static void desktop_view_slideshow_draw(Canvas* canvas, void* model) { + DesktopSlideshowViewModel* m = model; + + canvas_clear(canvas); + slideshow_draw(m->slideshow, canvas, 0, 0); +} + +static bool desktop_view_slideshow_input(InputEvent* event, void* context) { + furi_assert(event); + DesktopSlideshowView* instance = context; + + if(event->type == InputTypeShort) { + DesktopSlideshowViewModel* model = view_get_model(instance->view); + bool end_slideshow = false; + switch(event->key) { + case InputKeyLeft: + slideshow_goback(model->slideshow); + break; + case InputKeyRight: + case InputKeyOk: + end_slideshow = !slideshow_advance(model->slideshow); + break; + case InputKeyBack: + end_slideshow = true; + default: + break; + } + if(end_slideshow) { + instance->callback(DesktopSlideshowCompleted, instance->context); + } + view_commit_model(instance->view, true); + } + + return true; +} + +static void desktop_view_slideshow_enter(void* context) { + DesktopSlideshowView* instance = context; + + DesktopSlideshowViewModel* model = view_get_model(instance->view); + model->slideshow = slideshow_alloc(); + if(!slideshow_load(model->slideshow, "/int/slideshow")) { + instance->callback(DesktopSlideshowCompleted, instance->context); + } + view_commit_model(instance->view, false); +} + +static void desktop_view_slideshow_exit(void* context) { + DesktopSlideshowView* instance = context; + + DesktopSlideshowViewModel* model = view_get_model(instance->view); + slideshow_free(model->slideshow); + view_commit_model(instance->view, false); +} + +DesktopSlideshowView* desktop_view_slideshow_alloc() { + DesktopSlideshowView* instance = malloc(sizeof(DesktopSlideshowView)); + instance->view = view_alloc(); + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(DesktopSlideshowViewModel)); + view_set_context(instance->view, instance); + view_set_draw_callback(instance->view, (ViewDrawCallback)desktop_view_slideshow_draw); + view_set_input_callback(instance->view, desktop_view_slideshow_input); + view_set_enter_callback(instance->view, desktop_view_slideshow_enter); + view_set_exit_callback(instance->view, desktop_view_slideshow_exit); + + return instance; +} + +void desktop_view_slideshow_free(DesktopSlideshowView* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* desktop_view_slideshow_get_view(DesktopSlideshowView* instance) { + furi_assert(instance); + return instance->view; +} + +void desktop_view_slideshow_set_callback( + DesktopSlideshowView* instance, + DesktopSlideshowViewCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + instance->callback = callback; + instance->context = context; +} \ No newline at end of file diff --git a/applications/desktop/views/desktop_view_slideshow.h b/applications/desktop/views/desktop_view_slideshow.h new file mode 100644 index 00000000..5b45a6b7 --- /dev/null +++ b/applications/desktop/views/desktop_view_slideshow.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "desktop_events.h" + +typedef struct DesktopSlideshowView DesktopSlideshowView; + +typedef void (*DesktopSlideshowViewCallback)(DesktopEvent event, void* context); + +DesktopSlideshowView* desktop_view_slideshow_alloc(); + +void desktop_view_slideshow_free(DesktopSlideshowView* main_view); + +View* desktop_view_slideshow_get_view(DesktopSlideshowView* main_view); + +void desktop_view_slideshow_set_callback( + DesktopSlideshowView* main_view, + DesktopSlideshowViewCallback callback, + void* context); diff --git a/applications/dialogs/application.fam b/applications/dialogs/application.fam new file mode 100644 index 00000000..0a18c79a --- /dev/null +++ b/applications/dialogs/application.fam @@ -0,0 +1,10 @@ +App( + appid="dialogs", + name="DialogsSrv", + apptype=FlipperAppType.SERVICE, + entry_point="dialogs_srv", + cdefines=["SRV_DIALOGS"], + requires=["gui"], + stack_size=1 * 1024, + order=40, +) diff --git a/applications/dolphin/application.fam b/applications/dolphin/application.fam new file mode 100644 index 00000000..1ee0e3cf --- /dev/null +++ b/applications/dolphin/application.fam @@ -0,0 +1,23 @@ +App( + appid="dolphin", + name="DolphinSrv", + apptype=FlipperAppType.SERVICE, + entry_point="dolphin_srv", + cdefines=["SRV_DOLPHIN"], + stack_size=1 * 1024, + order=50, +) + +App( + appid="passport", + name="Passport", + apptype=FlipperAppType.SETTINGS, + entry_point="passport_app", + cdefines=["APP_PASSPORT"], + requires=[ + "gui", + "dolphin", + ], + stack_size=1 * 1024, + order=60, +) diff --git a/applications/extapps.scons b/applications/extapps.scons new file mode 100644 index 00000000..7b1cae7d --- /dev/null +++ b/applications/extapps.scons @@ -0,0 +1,57 @@ +Import("ENV") + + +from fbt.appmanifest import FlipperAppType + + +appenv = ENV.Clone(tools=["fbt_extapps"]) + +appenv.Replace( + LINKER_SCRIPT="application-ext", + STRIPFLAGS=[ + "--strip-debug", + "--strip-unneeded", + "-d", + "-g", + "-S", + ], +) + +appenv.AppendUnique( + CCFLAGS=[ + "-Os", + "-ggdb3", + "-mword-relocations", + "-mlong-calls", + "-fno-common", + "-nostdlib", + "-fvisibility=hidden", + ], + LINKFLAGS=[ + "-r", + "-s", + # "-Bsymbolic", + "-nostartfiles", + "-mlong-calls", + "-fno-common", + "-nostdlib", + "-Wl,--gc-sections", + "-Wl,--no-export-dynamic", + "-fvisibility=hidden", + "-Wl,-e${APP_ENTRY}", + ], +) + + +extapps = [] +for apptype in (FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL): + for app in appenv["APPBUILD"].get_apps_of_type(apptype): + extapps.append(appenv.BuildAppElf(app)) + +# Ugly access to global option +if extra_app_list := GetOption("extra_ext_apps"): + for extra_app in extra_app_list.split(","): + extapps.append(appenv.BuildAppElf(appenv["APPMGR"].get(extra_app))) + +Alias(appenv["FIRMWARE_BUILD_CFG"] + "_extapps", extapps) +Return("extapps") diff --git a/applications/gpio/application.fam b/applications/gpio/application.fam new file mode 100644 index 00000000..64f8db5b --- /dev/null +++ b/applications/gpio/application.fam @@ -0,0 +1,11 @@ +App( + appid="gpio", + name="GPIO", + apptype=FlipperAppType.APP, + entry_point="gpio_app", + cdefines=["APP_GPIO"], + requires=["gui"], + stack_size=1 * 1024, + icon="A_GPIO_14", + order=50, +) diff --git a/applications/gpio/usb_uart_bridge.c b/applications/gpio/usb_uart_bridge.c index f70cf640..cf7e7687 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/gpio/usb_uart_bridge.c @@ -78,7 +78,7 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { if(ev == UartIrqEventRXNE) { xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken); - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtRxDone); + furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } @@ -181,12 +181,13 @@ static int32_t usb_uart_worker(void* context) { usb_uart_update_ctrl_lines(usb_uart); } - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtCdcRx); + furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtCdcRx); furi_thread_start(usb_uart->tx_thread); while(1) { - uint32_t events = osThreadFlagsWait(WORKER_ALL_RX_EVENTS, osFlagsWaitAny, osWaitForever); + uint32_t events = + furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, osFlagsWaitAny, osWaitForever); furi_check((events & osFlagsError) == 0); if(events & WorkerEvtStop) break; if(events & WorkerEvtRxDone) { @@ -205,7 +206,7 @@ static int32_t usb_uart_worker(void* context) { } if(events & WorkerEvtCfgChange) { if(usb_uart->cfg.vcp_ch != usb_uart->cfg_new.vcp_ch) { - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop); + furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop); furi_thread_join(usb_uart->tx_thread); usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); @@ -217,7 +218,7 @@ static int32_t usb_uart_worker(void* context) { events |= WorkerEvtLineCfgSet; } if(usb_uart->cfg.uart_ch != usb_uart->cfg_new.uart_ch) { - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop); + furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop); furi_thread_join(usb_uart->tx_thread); usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch); @@ -266,7 +267,7 @@ static int32_t usb_uart_worker(void* context) { furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); } - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtTxStop); + furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop); furi_thread_join(usb_uart->tx_thread); furi_thread_free(usb_uart->tx_thread); @@ -288,7 +289,8 @@ static int32_t usb_uart_tx_thread(void* context) { uint8_t data[USB_CDC_PKT_LEN]; while(1) { - uint32_t events = osThreadFlagsWait(WORKER_ALL_TX_EVENTS, osFlagsWaitAny, osWaitForever); + uint32_t events = + furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, osFlagsWaitAny, osWaitForever); furi_check((events & osFlagsError) == 0); if(events & WorkerEvtTxStop) break; if(events & WorkerEvtCdcRx) { @@ -314,7 +316,7 @@ static void vcp_on_cdc_tx_complete(void* context) { static void vcp_on_cdc_rx(void* context) { UsbUartBridge* usb_uart = (UsbUartBridge*)context; - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->tx_thread), WorkerEvtCdcRx); + furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtCdcRx); } static void vcp_state_callback(void* context, uint8_t state) { @@ -325,13 +327,13 @@ static void vcp_state_callback(void* context, uint8_t state) { static void vcp_on_cdc_control_line(void* context, uint8_t state) { UNUSED(state); UsbUartBridge* usb_uart = (UsbUartBridge*)context; - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCtrlLineSet); + furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCtrlLineSet); } static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config) { UNUSED(config); UsbUartBridge* usb_uart = (UsbUartBridge*)context; - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtLineCfgSet); + furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtLineCfgSet); } UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) { @@ -351,7 +353,7 @@ UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) { void usb_uart_disable(UsbUartBridge* usb_uart) { furi_assert(usb_uart); - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtStop); + furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtStop); furi_thread_join(usb_uart->thread); furi_thread_free(usb_uart->thread); free(usb_uart); @@ -361,7 +363,7 @@ void usb_uart_set_config(UsbUartBridge* usb_uart, UsbUartConfig* cfg) { furi_assert(usb_uart); furi_assert(cfg); memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig)); - osThreadFlagsSet(furi_thread_get_thread_id(usb_uart->thread), WorkerEvtCfgChange); + furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCfgChange); } void usb_uart_get_config(UsbUartBridge* usb_uart, UsbUartConfig* cfg) { diff --git a/applications/gui/application.fam b/applications/gui/application.fam new file mode 100644 index 00000000..0116f5b8 --- /dev/null +++ b/applications/gui/application.fam @@ -0,0 +1,13 @@ +App( + appid="gui", + name="GuiSrv", + apptype=FlipperAppType.SERVICE, + entry_point="gui_srv", + cdefines=["SRV_GUI"], + requires=[ + "input", + "notification", + ], + stack_size=2 * 1024, + order=70, +) diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 77ee4487..d9e32cdd 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -19,7 +19,7 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { void gui_update(Gui* gui) { furi_assert(gui); - osThreadFlagsSet(gui->thread, GUI_THREAD_FLAG_DRAW); + furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_DRAW); } void gui_input_events_callback(const void* value, void* ctx) { @@ -29,7 +29,7 @@ void gui_input_events_callback(const void* value, void* ctx) { Gui* gui = ctx; osMessageQueuePut(gui->input_queue, value, 0, osWaitForever); - osThreadFlagsSet(gui->thread, GUI_THREAD_FLAG_INPUT); + furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_INPUT); } // Only Fullscreen supports vertical display for now @@ -471,7 +471,7 @@ void gui_set_lockdown(Gui* gui, bool lockdown) { Gui* gui_alloc() { Gui* gui = malloc(sizeof(Gui)); // Thread ID - gui->thread = osThreadGetId(); + gui->thread_id = furi_thread_get_current_id(); // Allocate mutex gui->mutex = osMutexNew(NULL); furi_check(gui->mutex); @@ -500,7 +500,8 @@ int32_t gui_srv(void* p) { furi_record_create("gui", gui); while(1) { - uint32_t flags = osThreadFlagsWait(GUI_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + uint32_t flags = + furi_thread_flags_wait(GUI_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); // Process and dispatch input if(flags & GUI_THREAD_FLAG_INPUT) { // Process till queue become empty @@ -512,7 +513,7 @@ int32_t gui_srv(void* p) { // Process and dispatch draw call if(flags & GUI_THREAD_FLAG_DRAW) { // Clear flags that arrived on input step - osThreadFlagsClear(GUI_THREAD_FLAG_DRAW); + furi_thread_flags_clear(GUI_THREAD_FLAG_DRAW); gui_redraw(gui); } } diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index ea26339d..abe85615 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -57,7 +57,7 @@ ALGO_DEF(CanvasCallbackPairArray, CanvasCallbackPairArray_t); /** Gui structure */ struct Gui { // Thread and lock - osThreadId_t thread; + FuriThreadId thread_id; osMutexId_t mutex; // Layers and Canvas diff --git a/applications/gui/modules/file_browser_worker.c b/applications/gui/modules/file_browser_worker.c index 4931cb26..cd7b6cb7 100644 --- a/applications/gui/modules/file_browser_worker.c +++ b/applications/gui/modules/file_browser_worker.c @@ -259,10 +259,10 @@ static int32_t browser_worker(void* context) { string_t filename; string_init(filename); - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtConfigChange); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange); while(1) { - uint32_t flags = osThreadFlagsWait(WORKER_FLAGS_ALL, osFlagsWaitAny, osWaitForever); + uint32_t flags = furi_thread_flags_wait(WORKER_FLAGS_ALL, osFlagsWaitAny, osWaitForever); furi_assert((flags & osFlagsError) == 0); if(flags & WorkerEvtConfigChange) { @@ -272,7 +272,7 @@ static int32_t browser_worker(void* context) { } idx_last_array_reset(browser->idx_last); - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter); } if(flags & WorkerEvtFolderEnter) { @@ -369,7 +369,7 @@ BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, void file_browser_worker_free(BrowserWorker* browser) { furi_assert(browser); - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtStop); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtStop); furi_thread_join(browser->thread); furi_thread_free(browser->thread); @@ -423,30 +423,30 @@ void file_browser_worker_set_config( string_set(browser->path_next, path); string_set_str(browser->filter_extension, filter_ext); browser->skip_assets = skip_assets; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtConfigChange); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtConfigChange); } void file_browser_worker_folder_enter(BrowserWorker* browser, string_t path, int32_t item_idx) { furi_assert(browser); string_set(browser->path_next, path); browser->item_sel_idx = item_idx; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderEnter); } void file_browser_worker_folder_exit(BrowserWorker* browser) { furi_assert(browser); - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderExit); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderExit); } void file_browser_worker_folder_refresh(BrowserWorker* browser, int32_t item_idx) { furi_assert(browser); browser->item_sel_idx = item_idx; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderRefresh); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtFolderRefresh); } void file_browser_worker_load(BrowserWorker* browser, uint32_t offset, uint32_t count) { furi_assert(browser); browser->load_offset = offset; browser->load_count = count; - osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtLoad); + furi_thread_flags_set(furi_thread_get_id(browser->thread), WorkerEvtLoad); } diff --git a/applications/gui/modules/loading.c b/applications/gui/modules/loading.c index 60dc8338..57512697 100644 --- a/applications/gui/modules/loading.c +++ b/applications/gui/modules/loading.c @@ -20,10 +20,10 @@ typedef struct { static void loading_draw_callback(Canvas* canvas, void* _model) { LoadingModel* model = (LoadingModel*)_model; - uint8_t x = 7; - uint8_t y = 40; uint8_t width = 49; uint8_t height = 47; + uint8_t x = (canvas_width(canvas) - width) / 2; + uint8_t y = (canvas_height(canvas) - height) / 2; elements_bold_rounded_frame(canvas, x, y, width, height); diff --git a/applications/gui/scene_manager.c b/applications/gui/scene_manager.c index a8c40320..590145e1 100755 --- a/applications/gui/scene_manager.c +++ b/applications/gui/scene_manager.c @@ -165,6 +165,25 @@ bool scene_manager_search_and_switch_to_previous_scene( } } +bool scene_manager_search_and_switch_to_previous_scene_one_of( + SceneManager* scene_manager, + const uint32_t* scene_ids, + size_t scene_ids_size) { + furi_assert(scene_manager); + furi_assert(scene_ids); + bool scene_found = false; + + for(size_t i = 0; i < scene_ids_size; ++i) { + const uint32_t scene_id = scene_ids[i]; + if(scene_manager_has_previous_scene(scene_manager, scene_id)) { + scene_manager_search_and_switch_to_previous_scene(scene_manager, scene_id); + scene_found = true; + break; + } + } + return scene_found; +} + bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) { furi_assert(scene_manager); bool scene_found = false; diff --git a/applications/gui/scene_manager.h b/applications/gui/scene_manager.h index 69162853..5b833e5d 100755 --- a/applications/gui/scene_manager.h +++ b/applications/gui/scene_manager.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -146,6 +147,19 @@ bool scene_manager_search_and_switch_to_previous_scene( SceneManager* scene_manager, uint32_t scene_id); +/** Search and switch to previous Scene, multiple choice + * + * @param scene_manager SceneManager instance + * @param scene_ids Array of scene IDs + * @param scene_ids_size Array of scene IDs size + * + * @return true if one of previous scenes was found, false otherwise + */ +bool scene_manager_search_and_switch_to_previous_scene_one_of( + SceneManager* scene_manager, + const uint32_t* scene_ids, + size_t scene_ids_size); + /** Clear Scene stack and switch to another Scene * * @param scene_manager SceneManager instance diff --git a/applications/ibutton/application.fam b/applications/ibutton/application.fam new file mode 100644 index 00000000..0bc6f8a9 --- /dev/null +++ b/applications/ibutton/application.fam @@ -0,0 +1,23 @@ +App( + appid="ibutton", + name="iButton", + apptype=FlipperAppType.APP, + entry_point="ibutton_app", + cdefines=["APP_IBUTTON"], + requires=[ + "gui", + "dialogs", + ], + provides=["ibutton_start"], + icon="A_iButton_14", + stack_size=2 * 1024, + order=60, +) + +App( + appid="ibutton_start", + apptype=FlipperAppType.STARTUP, + entry_point="ibutton_on_system_start", + requires=["ibutton"], + order=60, +) diff --git a/applications/infrared/application.fam b/applications/infrared/application.fam new file mode 100644 index 00000000..6f76ed42 --- /dev/null +++ b/applications/infrared/application.fam @@ -0,0 +1,23 @@ +App( + appid="infrared", + name="Infrared", + apptype=FlipperAppType.APP, + entry_point="infrared_app", + cdefines=["APP_INFRARED"], + requires=[ + "gui", + "dialogs", + ], + provides=["infrared_start"], + icon="A_Infrared_14", + stack_size=3 * 1024, + order=40, +) + +App( + appid="infrared_start", + apptype=FlipperAppType.STARTUP, + entry_point="infrared_on_system_start", + requires=["infrared"], + order=20, +) diff --git a/applications/infrared/helpers/infrared_parser.cpp b/applications/infrared/helpers/infrared_parser.cpp deleted file mode 100644 index d85a7269..00000000 --- a/applications/infrared/helpers/infrared_parser.cpp +++ /dev/null @@ -1,157 +0,0 @@ - -#include "../infrared_app_signal.h" -#include "infrared.h" -#include "infrared/helpers/infrared_parser.h" -#include "infrared_worker.h" -#include "m-string.h" -#include -#include -#include -#include - -#define TAG "InfraredParser" - -bool infrared_parser_save_signal( - FlipperFormat* ff, - const InfraredAppSignal& signal, - const std::string& name) { - furi_assert(ff); - furi_assert(!name.empty()); - - bool result = false; - - do { - if(!flipper_format_write_comment_cstr(ff, "")) break; - if(!flipper_format_write_string_cstr(ff, "name", name.c_str())) break; - if(signal.is_raw()) { - furi_assert(signal.get_raw_signal().timings_cnt <= MAX_TIMINGS_AMOUNT); - auto raw_signal = signal.get_raw_signal(); - if(!flipper_format_write_string_cstr(ff, "type", "raw")) break; - if(!flipper_format_write_uint32(ff, "frequency", &raw_signal.frequency, 1)) break; - if(!flipper_format_write_float(ff, "duty_cycle", &raw_signal.duty_cycle, 1)) break; - if(!flipper_format_write_uint32(ff, "data", raw_signal.timings, raw_signal.timings_cnt)) - break; - } else { - auto parsed_signal = signal.get_message(); - const char* protocol_name = infrared_get_protocol_name(parsed_signal.protocol); - if(!flipper_format_write_string_cstr(ff, "type", "parsed")) break; - if(!flipper_format_write_string_cstr(ff, "protocol", protocol_name)) break; - if(!flipper_format_write_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4)) - break; - if(!flipper_format_write_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4)) - break; - } - result = true; - } while(0); - - return result; -} - -bool infrared_parser_read_signal(FlipperFormat* ff, InfraredAppSignal& signal, std::string& name) { - furi_assert(ff); - - bool result = false; - string_t read_string; - string_init(read_string); - - do { - if(!flipper_format_read_string(ff, "name", read_string)) break; - name = string_get_cstr(read_string); - if(!flipper_format_read_string(ff, "type", read_string)) break; - if(!string_cmp_str(read_string, "raw")) { - uint32_t* timings = nullptr; - uint32_t timings_cnt = 0; - uint32_t frequency = 0; - float duty_cycle = 0; - - if(!flipper_format_read_uint32(ff, "frequency", &frequency, 1)) break; - if(!flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1)) break; - if(!flipper_format_get_value_count(ff, "data", &timings_cnt)) break; - if(timings_cnt > MAX_TIMINGS_AMOUNT) break; - timings = (uint32_t*)malloc(sizeof(uint32_t) * timings_cnt); - if(flipper_format_read_uint32(ff, "data", timings, timings_cnt)) { - signal.set_raw_signal(timings, timings_cnt, frequency, duty_cycle); - result = true; - } - free(timings); - } else if(!string_cmp_str(read_string, "parsed")) { - InfraredMessage parsed_signal; - if(!flipper_format_read_string(ff, "protocol", read_string)) break; - parsed_signal.protocol = infrared_get_protocol_by_name(string_get_cstr(read_string)); - if(!flipper_format_read_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4)) break; - if(!flipper_format_read_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4)) break; - if(!infrared_parser_is_parsed_signal_valid(&parsed_signal)) break; - signal.set_message(&parsed_signal); - result = true; - } else { - FURI_LOG_E(TAG, "Unknown type of signal (allowed - raw/parsed) "); - } - } while(0); - - string_clear(read_string); - return result; -} - -bool infrared_parser_is_parsed_signal_valid(const InfraredMessage* signal) { - furi_assert(signal); - bool result = true; - - if(!infrared_is_protocol_valid(signal->protocol)) { - FURI_LOG_E(TAG, "Unknown protocol"); - result = false; - } - - if(result) { - uint32_t address_length = infrared_get_protocol_address_length(signal->protocol); - uint32_t address_mask = (1LU << address_length) - 1; - if(signal->address != (signal->address & address_mask)) { - FURI_LOG_E( - TAG, - "Address is out of range (mask 0x%08lX): 0x%lX\r\n", - address_mask, - signal->address); - result = false; - } - } - - if(result) { - uint32_t command_length = infrared_get_protocol_command_length(signal->protocol); - uint32_t command_mask = (1LU << command_length) - 1; - if(signal->command != (signal->command & command_mask)) { - FURI_LOG_E( - TAG, - "Command is out of range (mask 0x%08lX): 0x%lX\r\n", - command_mask, - signal->command); - result = false; - } - } - - return result; -} - -bool infrared_parser_is_raw_signal_valid( - uint32_t frequency, - float duty_cycle, - uint32_t timings_cnt) { - bool result = true; - - if((frequency > INFRARED_MAX_FREQUENCY) || (frequency < INFRARED_MIN_FREQUENCY)) { - FURI_LOG_E( - TAG, - "Frequency is out of range (%lX - %lX): %lX", - INFRARED_MIN_FREQUENCY, - INFRARED_MAX_FREQUENCY, - frequency); - result = false; - } else if((duty_cycle <= 0) || (duty_cycle > 1)) { - FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)duty_cycle); - result = false; - } else if((timings_cnt <= 0) || (timings_cnt > MAX_TIMINGS_AMOUNT)) { - FURI_LOG_E( - TAG, "Timings amount is out of range (0 - %lX): %lX", MAX_TIMINGS_AMOUNT, timings_cnt); - result = false; - } - - return result; -} diff --git a/applications/infrared/helpers/infrared_parser.h b/applications/infrared/helpers/infrared_parser.h deleted file mode 100644 index 2e790c38..00000000 --- a/applications/infrared/helpers/infrared_parser.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file infrared_parser.h - * Infrared: Helper file for conversion Flipper File Format - * to Infrared signal class, and backwards - */ -#pragma once - -#include "../infrared_app_signal.h" -#include -#include - -/** Save Infrared signal into file - * - * @param ff - Flipper File Format instance - * @param signal - Infrared signal to save - * @param name - name for saved signal. Every - * signal on disk has name. - */ -bool infrared_parser_save_signal( - FlipperFormat* ff, - const InfraredAppSignal& signal, - const std::string& name); - -/** Read Infrared signal from file - * - * @param ff - Flipper File Format instance - * @param signal - Infrared signal to read to - * @param name - name for saved signal. Every - * signal in file has name. - */ -bool infrared_parser_read_signal(FlipperFormat* ff, InfraredAppSignal& signal, std::string& name); - -/** Validate parsed signal - * - * @signal - signal to validate - * @retval true if valid, false otherwise - */ -bool infrared_parser_is_parsed_signal_valid(const InfraredMessage* signal); - -/** Validate raw signal - * - * @signal - signal to validate - * @retval true if valid, false otherwise - */ -bool infrared_parser_is_raw_signal_valid( - uint32_t frequency, - float duty_cycle, - uint32_t timings_cnt); diff --git a/applications/infrared/infrared.c b/applications/infrared/infrared.c new file mode 100644 index 00000000..e641302c --- /dev/null +++ b/applications/infrared/infrared.c @@ -0,0 +1,399 @@ +#include "infrared_i.h" + +#include +#include + +static const NotificationSequence* infrared_notification_sequences[] = { + &sequence_success, + &sequence_set_only_green_255, + &sequence_reset_green, + &sequence_blink_cyan_10, + &sequence_blink_magenta_10, + &sequence_solid_yellow, + &sequence_reset_rgb}; + +static void infrared_make_app_folder(Infrared* infrared) { + if(!storage_simply_mkdir(infrared->storage, INFRARED_APP_FOLDER)) { + dialog_message_show_storage_error(infrared->dialogs, "Cannot create\napp folder"); + } +} + +static bool infrared_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + Infrared* infrared = context; + return scene_manager_handle_custom_event(infrared->scene_manager, event); +} + +static bool infrared_back_event_callback(void* context) { + furi_assert(context); + Infrared* infrared = context; + return scene_manager_handle_back_event(infrared->scene_manager); +} + +static void infrared_tick_event_callback(void* context) { + furi_assert(context); + Infrared* infrared = context; + scene_manager_handle_tick_event(infrared->scene_manager); +} + +static void infrared_find_vacant_remote_name(string_t name, const char* path) { + Storage* storage = furi_record_open("storage"); + + string_t base_path; + string_init_set_str(base_path, path); + + if(string_end_with_str_p(base_path, INFRARED_APP_EXTENSION)) { + size_t filename_start = string_search_rchar(base_path, '/'); + string_left(base_path, filename_start); + } + + string_printf(base_path, "%s/%s%s", path, string_get_cstr(name), INFRARED_APP_EXTENSION); + + FS_Error status = storage_common_stat(storage, string_get_cstr(base_path), NULL); + + if(status == FSE_OK) { + /* If the suggested name is occupied, try another one (name2, name3, etc) */ + size_t dot = string_search_rchar(base_path, '.'); + string_left(base_path, dot); + + string_t path_temp; + string_init(path_temp); + + uint32_t i = 1; + do { + string_printf( + path_temp, "%s%u%s", string_get_cstr(base_path), ++i, INFRARED_APP_EXTENSION); + status = storage_common_stat(storage, string_get_cstr(path_temp), NULL); + } while(status == FSE_OK); + + string_clear(path_temp); + + if(status == FSE_NOT_EXIST) { + string_cat_printf(name, "%u", i); + } + } + + string_clear(base_path); + furi_record_close("storage"); +} + +static Infrared* infrared_alloc() { + Infrared* infrared = malloc(sizeof(Infrared)); + + string_init(infrared->file_path); + + InfraredAppState* app_state = &infrared->app_state; + app_state->is_learning_new_remote = false; + app_state->is_debug_enabled = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); + app_state->edit_target = InfraredEditTargetNone; + app_state->edit_mode = InfraredEditModeNone; + app_state->current_button_index = InfraredButtonIndexNone; + + infrared->scene_manager = scene_manager_alloc(&infrared_scene_handlers, infrared); + infrared->view_dispatcher = view_dispatcher_alloc(); + + infrared->gui = furi_record_open("gui"); + + ViewDispatcher* view_dispatcher = infrared->view_dispatcher; + view_dispatcher_attach_to_gui(view_dispatcher, infrared->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_enable_queue(view_dispatcher); + view_dispatcher_set_event_callback_context(view_dispatcher, infrared); + view_dispatcher_set_custom_event_callback(view_dispatcher, infrared_custom_event_callback); + view_dispatcher_set_navigation_event_callback(view_dispatcher, infrared_back_event_callback); + view_dispatcher_set_tick_event_callback(view_dispatcher, infrared_tick_event_callback, 100); + + infrared->storage = furi_record_open("storage"); + infrared->dialogs = furi_record_open("dialogs"); + infrared->notifications = furi_record_open("notification"); + + infrared->worker = infrared_worker_alloc(); + infrared->remote = infrared_remote_alloc(); + infrared->received_signal = infrared_signal_alloc(); + infrared->brute_force = infrared_brute_force_alloc(); + + infrared->submenu = submenu_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewSubmenu, submenu_get_view(infrared->submenu)); + + infrared->text_input = text_input_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewTextInput, text_input_get_view(infrared->text_input)); + + infrared->dialog_ex = dialog_ex_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewDialogEx, dialog_ex_get_view(infrared->dialog_ex)); + + infrared->button_menu = button_menu_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewButtonMenu, button_menu_get_view(infrared->button_menu)); + + infrared->popup = popup_alloc(); + view_dispatcher_add_view(view_dispatcher, InfraredViewPopup, popup_get_view(infrared->popup)); + + infrared->view_stack = view_stack_alloc(); + view_dispatcher_add_view( + view_dispatcher, InfraredViewStack, view_stack_get_view(infrared->view_stack)); + + if(app_state->is_debug_enabled) { + infrared->debug_view = infrared_debug_view_alloc(); + view_dispatcher_add_view( + view_dispatcher, + InfraredViewDebugView, + infrared_debug_view_get_view(infrared->debug_view)); + } + + infrared->button_panel = button_panel_alloc(); + infrared->loading = loading_alloc(); + infrared->progress = infrared_progress_view_alloc(); + + return infrared; +} + +static void infrared_free(Infrared* infrared) { + furi_assert(infrared); + ViewDispatcher* view_dispatcher = infrared->view_dispatcher; + InfraredAppState* app_state = &infrared->app_state; + + view_dispatcher_remove_view(view_dispatcher, InfraredViewSubmenu); + submenu_free(infrared->submenu); + + view_dispatcher_remove_view(view_dispatcher, InfraredViewTextInput); + text_input_free(infrared->text_input); + + view_dispatcher_remove_view(view_dispatcher, InfraredViewDialogEx); + dialog_ex_free(infrared->dialog_ex); + + view_dispatcher_remove_view(view_dispatcher, InfraredViewButtonMenu); + button_menu_free(infrared->button_menu); + + view_dispatcher_remove_view(view_dispatcher, InfraredViewPopup); + popup_free(infrared->popup); + + view_dispatcher_remove_view(view_dispatcher, InfraredViewStack); + view_stack_free(infrared->view_stack); + + if(app_state->is_debug_enabled) { + view_dispatcher_remove_view(view_dispatcher, InfraredViewDebugView); + infrared_debug_view_free(infrared->debug_view); + } + + button_panel_free(infrared->button_panel); + loading_free(infrared->loading); + infrared_progress_view_free(infrared->progress); + + view_dispatcher_free(view_dispatcher); + scene_manager_free(infrared->scene_manager); + + infrared_brute_force_free(infrared->brute_force); + infrared_signal_free(infrared->received_signal); + infrared_remote_free(infrared->remote); + infrared_worker_free(infrared->worker); + + furi_record_close("gui"); + infrared->gui = NULL; + + furi_record_close("notification"); + infrared->notifications = NULL; + + furi_record_close("dialogs"); + infrared->dialogs = NULL; + + furi_record_close("gui"); + infrared->gui = NULL; + + string_clear(infrared->file_path); + + free(infrared); +} + +bool infrared_add_remote_with_button( + Infrared* infrared, + const char* button_name, + InfraredSignal* signal) { + InfraredRemote* remote = infrared->remote; + + string_t new_name, new_path; + string_init_set_str(new_name, INFRARED_DEFAULT_REMOTE_NAME); + string_init_set_str(new_path, INFRARED_APP_FOLDER); + + infrared_find_vacant_remote_name(new_name, string_get_cstr(new_path)); + string_cat_printf(new_path, "/%s%s", string_get_cstr(new_name), INFRARED_APP_EXTENSION); + + infrared_remote_reset(remote); + infrared_remote_set_name(remote, string_get_cstr(new_name)); + infrared_remote_set_path(remote, string_get_cstr(new_path)); + + string_clear(new_name); + string_clear(new_path); + return infrared_remote_add_button(remote, button_name, signal); +} + +bool infrared_rename_current_remote(Infrared* infrared, const char* name) { + InfraredRemote* remote = infrared->remote; + const char* remote_path = infrared_remote_get_path(remote); + + if(!strcmp(infrared_remote_get_name(remote), name)) { + return true; + } + + string_t new_name; + string_init_set_str(new_name, name); + + infrared_find_vacant_remote_name(new_name, remote_path); + + string_t new_path; + string_init_set(new_path, infrared_remote_get_path(remote)); + if(string_end_with_str_p(new_path, INFRARED_APP_EXTENSION)) { + size_t filename_start = string_search_rchar(new_path, '/'); + string_left(new_path, filename_start); + } + string_cat_printf(new_path, "/%s%s", string_get_cstr(new_name), INFRARED_APP_EXTENSION); + + Storage* storage = furi_record_open("storage"); + + FS_Error status = storage_common_rename( + storage, infrared_remote_get_path(remote), string_get_cstr(new_path)); + infrared_remote_set_name(remote, string_get_cstr(new_name)); + + string_clear(new_name); + string_clear(new_path); + + furi_record_close("storage"); + return (status == FSE_OK || status == FSE_EXIST); +} + +void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { + if(infrared_signal_is_raw(signal)) { + InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size); + } else { + InfraredMessage* message = infrared_signal_get_message(signal); + infrared_worker_set_decoded_signal(infrared->worker, message); + } + + DOLPHIN_DEED(DolphinDeedIrSend); + infrared_worker_tx_start(infrared->worker); +} + +void infrared_tx_start_button_index(Infrared* infrared, size_t button_index) { + furi_assert(button_index < infrared_remote_get_button_count(infrared->remote)); + + InfraredRemoteButton* button = infrared_remote_get_button(infrared->remote, button_index); + InfraredSignal* signal = infrared_remote_button_get_signal(button); + + infrared_tx_start_signal(infrared, signal); +} + +void infrared_tx_start_received(Infrared* infrared) { + infrared_tx_start_signal(infrared, infrared->received_signal); +} + +void infrared_tx_stop(Infrared* infrared) { + infrared_worker_tx_stop(infrared->worker); +} + +void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...) { + va_list args; + va_start(args, text); + + vsnprintf(infrared->text_store[bank], INFRARED_TEXT_STORE_SIZE, text, args); + + va_end(args); +} + +void infrared_text_store_clear(Infrared* infrared, uint32_t bank) { + memset(infrared->text_store[bank], 0, INFRARED_TEXT_STORE_SIZE); +} + +void infrared_play_notification_message(Infrared* infrared, uint32_t message) { + furi_assert(message < sizeof(infrared_notification_sequences) / sizeof(NotificationSequence*)); + notification_message(infrared->notifications, infrared_notification_sequences[message]); +} + +void infrared_show_loading_popup(Infrared* infrared, bool show) { + TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); + ViewStack* view_stack = infrared->view_stack; + Loading* loading = infrared->loading; + + if(show) { + // Raise timer priority so that animations can play + vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + view_stack_add_view(view_stack, loading_get_view(loading)); + } else { + view_stack_remove_view(view_stack, loading_get_view(loading)); + // Restore default timer priority + vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + } +} + +void infrared_signal_sent_callback(void* context) { + furi_assert(context); + Infrared* infrared = context; + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend); +} + +void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { + furi_assert(context); + Infrared* infrared = context; + + if(infrared_worker_signal_is_decoded(received_signal)) { + infrared_signal_set_message( + infrared->received_signal, infrared_worker_get_decoded_signal(received_signal)); + } else { + const uint32_t* timings; + size_t timings_size; + infrared_worker_get_raw_signal(received_signal, &timings, &timings_size); + infrared_signal_set_raw_signal( + infrared->received_signal, + timings, + timings_size, + INFRARED_COMMON_CARRIER_FREQUENCY, + INFRARED_COMMON_DUTY_CYCLE); + } + + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeSignalReceived); +} + +void infrared_text_input_callback(void* context) { + furi_assert(context); + Infrared* infrared = context; + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypeTextEditDone); +} + +void infrared_popup_closed_callback(void* context) { + furi_assert(context); + Infrared* infrared = context; + view_dispatcher_send_custom_event( + infrared->view_dispatcher, InfraredCustomEventTypePopupClosed); +} + +int32_t infrared_app(void* p) { + Infrared* infrared = infrared_alloc(); + + infrared_make_app_folder(infrared); + + bool is_remote_loaded = false; + + if(p) { + string_set_str(infrared->file_path, (const char*)p); + is_remote_loaded = infrared_remote_load(infrared->remote, infrared->file_path); + if(!is_remote_loaded) { + dialog_message_show_storage_error( + infrared->dialogs, "Failed to load\nselected remote"); + return -1; + } + } + + if(is_remote_loaded) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); + } else { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneStart); + } + + view_dispatcher_run(infrared->view_dispatcher); + + infrared_free(infrared); + return 0; +} diff --git a/applications/infrared/infrared.h b/applications/infrared/infrared.h new file mode 100644 index 00000000..e5eeb117 --- /dev/null +++ b/applications/infrared/infrared.h @@ -0,0 +1,3 @@ +#pragma once + +typedef struct Infrared Infrared; diff --git a/applications/infrared/infrared_app.cpp b/applications/infrared/infrared_app.cpp deleted file mode 100644 index 1ac859d1..00000000 --- a/applications/infrared/infrared_app.cpp +++ /dev/null @@ -1,250 +0,0 @@ -#include "infrared_app.h" -#include "m-string.h" -#include -#include -#include -#include -#include -#include - -int32_t InfraredApp::run(void* args) { - InfraredAppEvent event; - bool consumed; - bool exit = false; - - if(args) { - string_t path; - string_init_set_str(path, (char*)args); - if(string_end_with_str_p(path, InfraredApp::infrared_extension)) { - bool result = remote_manager.load(path); - if(result) { - current_scene = InfraredApp::Scene::Remote; - } else { - printf("Failed to load remote \'%s\'\r\n", string_get_cstr(path)); - return -1; - } - } - string_clear(path); - } - - scenes[current_scene]->on_enter(this); - - while(!exit) { - view_manager.receive_event(&event); - - if(event.type == InfraredAppEvent::Type::Exit) break; - - consumed = scenes[current_scene]->on_event(this, &event); - - if(!consumed) { - if(event.type == InfraredAppEvent::Type::Back) { - exit = switch_to_previous_scene(); - } - } - }; - - scenes[current_scene]->on_exit(this); - - return 0; -}; - -InfraredApp::InfraredApp() { - furi_check(InfraredAppRemoteManager::max_button_name_length < get_text_store_size()); - string_init_set_str(file_path, InfraredApp::infrared_directory); - notification = static_cast(furi_record_open("notification")); - dialogs = static_cast(furi_record_open("dialogs")); - infrared_worker = infrared_worker_alloc(); -} - -InfraredApp::~InfraredApp() { - infrared_worker_free(infrared_worker); - furi_record_close("notification"); - furi_record_close("dialogs"); - string_clear(file_path); - for(auto& [key, scene] : scenes) delete scene; -} - -InfraredAppViewManager* InfraredApp::get_view_manager() { - return &view_manager; -} - -void InfraredApp::set_learn_new_remote(bool value) { - learn_new_remote = value; -} - -bool InfraredApp::get_learn_new_remote() { - return learn_new_remote; -} - -void InfraredApp::switch_to_next_scene(Scene next_scene) { - previous_scenes_list.push_front(current_scene); - switch_to_next_scene_without_saving(next_scene); -} - -void InfraredApp::switch_to_next_scene_without_saving(Scene next_scene) { - if(next_scene != Scene::Exit) { - scenes[current_scene]->on_exit(this); - current_scene = next_scene; - scenes[current_scene]->on_enter(this); - view_manager.clear_events(); - } -} - -void InfraredApp::search_and_switch_to_previous_scene( - const std::initializer_list& scenes_list) { - Scene previous_scene = Scene::Start; - bool scene_found = false; - - while(!scene_found) { - previous_scene = get_previous_scene(); - - if(previous_scene == Scene::Exit) break; - - for(Scene element : scenes_list) { - if(previous_scene == element) { - scene_found = true; - break; - } - } - } - - if(previous_scene == Scene::Exit) { - InfraredAppEvent event; - event.type = InfraredAppEvent::Type::Exit; - view_manager.send_event(&event); - } else { - scenes[current_scene]->on_exit(this); - current_scene = previous_scene; - scenes[current_scene]->on_enter(this); - view_manager.clear_events(); - } -} - -bool InfraredApp::switch_to_previous_scene(uint8_t count) { - Scene previous_scene = Scene::Start; - - for(uint8_t i = 0; i < count; i++) previous_scene = get_previous_scene(); - - if(previous_scene == Scene::Exit) return true; - - scenes[current_scene]->on_exit(this); - current_scene = previous_scene; - scenes[current_scene]->on_enter(this); - view_manager.clear_events(); - return false; -} - -InfraredApp::Scene InfraredApp::get_previous_scene() { - Scene scene = Scene::Exit; - - if(!previous_scenes_list.empty()) { - scene = previous_scenes_list.front(); - previous_scenes_list.pop_front(); - } - - return scene; -} - -InfraredAppRemoteManager* InfraredApp::get_remote_manager() { - return &remote_manager; -} - -void InfraredApp::set_text_store(uint8_t index, const char* text...) { - furi_check(index < text_store_max); - - va_list args; - va_start(args, text); - - vsnprintf(text_store[index], text_store_size, text, args); - - va_end(args); -} - -char* InfraredApp::get_text_store(uint8_t index) { - furi_check(index < text_store_max); - - return text_store[index]; -} - -uint8_t InfraredApp::get_text_store_size() { - return text_store_size; -} - -void InfraredApp::text_input_callback(void* context) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - event.type = InfraredAppEvent::Type::TextEditDone; - app->get_view_manager()->send_event(&event); -} - -void InfraredApp::popup_callback(void* context) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - event.type = InfraredAppEvent::Type::PopupTimer; - app->get_view_manager()->send_event(&event); -} - -void InfraredApp::set_edit_element(InfraredApp::EditElement value) { - element = value; -} - -InfraredApp::EditElement InfraredApp::get_edit_element(void) { - return element; -} - -void InfraredApp::set_edit_action(InfraredApp::EditAction value) { - action = value; -} - -InfraredApp::EditAction InfraredApp::get_edit_action(void) { - return action; -} - -void InfraredApp::set_current_button(int value) { - current_button = value; -} - -int InfraredApp::get_current_button() { - return current_button; -} - -void InfraredApp::notify_success() { - notification_message(notification, &sequence_success); -} - -void InfraredApp::notify_blink_read() { - notification_message(notification, &sequence_blink_cyan_10); -} - -void InfraredApp::notify_blink_send() { - notification_message(notification, &sequence_blink_magenta_10); -} - -DialogsApp* InfraredApp::get_dialogs() { - return dialogs; -} - -void InfraredApp::notify_green_on() { - notification_message(notification, &sequence_set_only_green_255); -} - -void InfraredApp::notify_green_off() { - notification_message(notification, &sequence_reset_green); -} - -InfraredWorker* InfraredApp::get_infrared_worker() { - return infrared_worker; -} - -const InfraredAppSignal& InfraredApp::get_received_signal() const { - return received_signal; -} - -void InfraredApp::set_received_signal(const InfraredAppSignal& signal) { - received_signal = signal; -} - -void InfraredApp::signal_sent_callback(void* context) { - InfraredApp* app = static_cast(context); - app->notify_blink_send(); -} diff --git a/applications/infrared/infrared_app.h b/applications/infrared/infrared_app.h deleted file mode 100644 index 1cb8b661..00000000 --- a/applications/infrared/infrared_app.h +++ /dev/null @@ -1,326 +0,0 @@ -/** - * @file infrared_app.h - * Infrared: Main infrared application class - */ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include "scene/infrared_app_scene.h" -#include "scene/infrared_app_scene.h" -#include "infrared_app_view_manager.h" -#include "infrared_app_remote_manager.h" -#include "infrared_app_view_manager.h" - -/** Main Infrared application class */ -class InfraredApp { -public: - /** Enum to save scene state: edit element */ - enum class EditElement : uint8_t { - Button, - Remote, - }; - /** Enum to save scene state: edit action */ - enum class EditAction : uint8_t { - Rename, - Delete, - }; - /** List of scenes for Infrared application */ - enum class Scene : uint8_t { - Exit, - Start, - Universal, - UniversalTV, - UniversalAudio, - UniversalAirConditioner, - Learn, - LearnSuccess, - LearnEnterName, - LearnDone, - AskBack, - Remote, - RemoteList, - Edit, - EditKeySelect, - EditRename, - EditDelete, - EditRenameDone, - EditDeleteDone, - }; - - /** Start application - * - * @param args - application arguments. - * Allowed argument is path to remote file. - * @retval 0 on success, error code otherwise - */ - int32_t run(void* args); - - /** Switch to next scene. Put current scene number on stack. - * Doesn't save scene state. - * - * @param index - next scene index - */ - void switch_to_next_scene(Scene index); - - /** Switch to next scene, but don't put current scene on - * stack. Thus calling switch_to_previous_scene() doesn't return - * to current scene. - * - * @param index - next scene index - */ - void switch_to_next_scene_without_saving(Scene index); - - /** Switch to previous scene. Pop scenes from stack and switch to last one. - * - * @param count - how many scenes should be popped - * @retval false on failed, true on success - */ - bool switch_to_previous_scene(uint8_t count = 1); - - /** Get previous scene in scene stack - * - * @retval previous scene - */ - Scene get_previous_scene(); - - /** Get view manager instance - * - * @retval view manager instance - */ - InfraredAppViewManager* get_view_manager(); - - /** Set one of text stores - * - * @param index - index of text store - * @param text - text to set - */ - void set_text_store(uint8_t index, const char* text...); - - /** Get value in text store - * - * @param index - index of text store - * @retval value in text_store - */ - char* get_text_store(uint8_t index); - - /** Get text store size - * - * @retval size of text store - */ - uint8_t get_text_store_size(); - - /** Get remote manager instance - * - * @retval remote manager instance - */ - InfraredAppRemoteManager* get_remote_manager(); - - /** Get infrared worker instance - * - * @retval infrared worker instance - */ - InfraredWorker* get_infrared_worker(); - - /** Get signal, previously got on Learn scene - * - * @retval received signal - */ - const InfraredAppSignal& get_received_signal() const; - - /** Set received signal - * - * @param signal - signal - */ - void set_received_signal(const InfraredAppSignal& signal); - - /** Switch to previous scene in one of provided in list. - * Pop scene stack, and find first scene from list. - * - * @param scenes_list - list of scenes - */ - void search_and_switch_to_previous_scene(const std::initializer_list& scenes_list); - - /** Set edit element value. It is used on edit scene to determine - * what should be deleted - remote or button. - * - * @param value - value to set - */ - void set_edit_element(EditElement value); - - /** Get edit element - * - * @retval edit element value - */ - EditElement get_edit_element(void); - - /** Set edit action value. It is used on edit scene to determine - * what action to perform - deletion or renaming. - * - * @param value - value to set - */ - void set_edit_action(EditAction value); - - /** Get edit action - * - * @retval edit action value - */ - EditAction get_edit_action(void); - - /** Get state of learning new signal. - * Adding new remote with 1 button from start scene and - * learning 1 additional button to remote have very similar - * flow, so they are joined. Difference in flow is handled - * by this boolean flag. - * - * @retval false if flow is in learning new remote, true if - * adding signal to created remote - * - */ - bool get_learn_new_remote(); - - /** Set state of learning new signal. - * Adding new remote with 1 button from start scene and - * learning 1 additional button to remote have very similar - * flow, so they are joined. Difference in flow is handled - * by this boolean flag. - * - * @param value - false if flow is in learning new remote, true if - * adding signal to created remote - */ - void set_learn_new_remote(bool value); - - /** Button is not assigned value - */ - enum : int { - ButtonNA = -1, - }; - - /** Get current button index - * - * @retval current button index - */ - int get_current_button(); - - /** Set current button index - * - * @param current button index - */ - void set_current_button(int value); - - /** Play success notification */ - void notify_success(); - /** Play red blink notification */ - void notify_blink_read(); - /** Light green */ - void notify_green_on(); - /** Disable green light */ - void notify_green_off(); - /** Blink on send */ - void notify_blink_send(); - - /** Get Dialogs instance */ - DialogsApp* get_dialogs(); - - /** Text input callback - * - * @param context - context to pass to callback - */ - static void text_input_callback(void* context); - - /** Popup callback - * - * @param context - context to pass to callback - */ - static void popup_callback(void* context); - - /** Signal sent callback - * - * @param context - context to pass to callback - */ - static void signal_sent_callback(void* context); - - /** Main class constructor, initializes all critical objects */ - InfraredApp(); - /** Main class destructor, deinitializes all critical objects */ - ~InfraredApp(); - - string_t file_path; - - /** Path to Infrared directory */ - static constexpr const char* infrared_directory = "/any/infrared"; - /** Infrared files extension (remote files and universal databases) */ - static constexpr const char* infrared_extension = ".ir"; - /** Max Raw timings in signal */ - static constexpr const uint32_t max_raw_timings_in_signal = 512; - /** Max line length in Infrared file */ - static constexpr const uint32_t max_line_length = - (9 + 1) * InfraredApp::max_raw_timings_in_signal + 100; - -private: - /** Text store size */ - static constexpr const uint8_t text_store_size = 128; - /** Amount of text stores */ - static constexpr const uint8_t text_store_max = 2; - /** Store text here, for some views, because they doesn't - * hold ownership of text */ - char text_store[text_store_max][text_store_size + 1]; - /** - * Flag to control adding new signal flow. - * Adding new remote with 1 button from start scene and - * learning 1 additional button to remote have very similar - * flow, so they are joined. Difference in flow is handled - * by this boolean flag. - */ - bool learn_new_remote; - /** Value to control edit scene */ - EditElement element; - /** Value to control edit scene */ - EditAction action; - /** Selected button index */ - uint32_t current_button; - - /** Notification instance */ - NotificationApp* notification; - /** Dialogs instance */ - DialogsApp* dialogs; - /** View manager instance */ - InfraredAppViewManager view_manager; - /** Remote manager instance */ - InfraredAppRemoteManager remote_manager; - /** Infrared worker instance */ - InfraredWorker* infrared_worker; - /** Signal received on Learn scene */ - InfraredAppSignal received_signal; - - /** Stack of previous scenes */ - std::forward_list previous_scenes_list; - /** Now acting scene */ - Scene current_scene = Scene::Start; - - /** Map of index/scene objects */ - std::map scenes = { - {Scene::Start, new InfraredAppSceneStart()}, - {Scene::Universal, new InfraredAppSceneUniversal()}, - {Scene::UniversalTV, new InfraredAppSceneUniversalTV()}, - {Scene::Learn, new InfraredAppSceneLearn()}, - {Scene::LearnSuccess, new InfraredAppSceneLearnSuccess()}, - {Scene::LearnEnterName, new InfraredAppSceneLearnEnterName()}, - {Scene::LearnDone, new InfraredAppSceneLearnDone()}, - {Scene::AskBack, new InfraredAppSceneAskBack()}, - {Scene::Remote, new InfraredAppSceneRemote()}, - {Scene::RemoteList, new InfraredAppSceneRemoteList()}, - {Scene::Edit, new InfraredAppSceneEdit()}, - {Scene::EditKeySelect, new InfraredAppSceneEditKeySelect()}, - {Scene::EditRename, new InfraredAppSceneEditRename()}, - {Scene::EditDelete, new InfraredAppSceneEditDelete()}, - {Scene::EditRenameDone, new InfraredAppSceneEditRenameDone()}, - {Scene::EditDeleteDone, new InfraredAppSceneEditDeleteDone()}, - }; -}; diff --git a/applications/infrared/infrared_app_brute_force.cpp b/applications/infrared/infrared_app_brute_force.cpp deleted file mode 100644 index 2910a399..00000000 --- a/applications/infrared/infrared_app_brute_force.cpp +++ /dev/null @@ -1,93 +0,0 @@ - -#include "helpers/infrared_parser.h" -#include "infrared_app_brute_force.h" -#include "infrared_app_signal.h" -#include -#include -#include - -void InfraredAppBruteForce::add_record(int index, const char* name) { - records[name].index = index; - records[name].amount = 0; -} - -bool InfraredAppBruteForce::calculate_messages() { - bool result = false; - - Storage* storage = static_cast(furi_record_open("storage")); - FlipperFormat* ff = flipper_format_file_alloc(storage); - result = flipper_format_file_open_existing(ff, universal_db_filename); - - if(result) { - InfraredAppSignal signal; - - string_t signal_name; - string_init(signal_name); - while(flipper_format_read_string(ff, "name", signal_name)) { - auto element = records.find(string_get_cstr(signal_name)); - if(element != records.cend()) { - ++element->second.amount; - } - } - string_clear(signal_name); - } - - flipper_format_free(ff); - furi_record_close("storage"); - return result; -} - -void InfraredAppBruteForce::stop_bruteforce() { - furi_assert((current_record.size())); - - if(current_record.size()) { - furi_assert(ff); - current_record.clear(); - flipper_format_free(ff); - furi_record_close("storage"); - } -} - -bool InfraredAppBruteForce::send_next_bruteforce(void) { - furi_assert(current_record.size()); - furi_assert(ff); - - InfraredAppSignal signal; - std::string signal_name; - bool result = false; - do { - result = infrared_parser_read_signal(ff, signal, signal_name); - } while(result && current_record.compare(signal_name)); - - if(result) { - signal.transmit(); - } - return result; -} - -bool InfraredAppBruteForce::start_bruteforce(int index, int& record_amount) { - bool result = false; - record_amount = 0; - - for(const auto& it : records) { - if(it.second.index == index) { - record_amount = it.second.amount; - if(record_amount) { - current_record = it.first; - } - break; - } - } - - if(record_amount) { - Storage* storage = static_cast(furi_record_open("storage")); - ff = flipper_format_file_alloc(storage); - result = flipper_format_file_open_existing(ff, universal_db_filename); - if(!result) { - flipper_format_free(ff); - furi_record_close("storage"); - } - } - - return result; -} diff --git a/applications/infrared/infrared_app_brute_force.h b/applications/infrared/infrared_app_brute_force.h deleted file mode 100644 index 2dd3ade9..00000000 --- a/applications/infrared/infrared_app_brute_force.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file infrared_app_brute_force.h - * Infrared: Brute Force class description - */ -#pragma once - -#include -#include -#include - -/** Class handles brute force mechanic */ -class InfraredAppBruteForce { - /** Universal database filename */ - const char* universal_db_filename; - - /** Current record name (POWER, MUTE, VOL+, etc). - * This is the name of signal to brute force. */ - std::string current_record; - - /** Flipper File Format instance */ - FlipperFormat* ff; - - /** Data about every record - index in button panel view - * and amount of signals, which is need for correct - * progress bar displaying. */ - typedef struct { - /** Index of record in button panel view model */ - int index; - /** Amount of signals of that type (POWER, MUTE, etc) */ - int amount; - } Record; - - /** Container to hold Record info. - * 'key' is record name, because we have to search by both, index and name, - * but index search has place once per button press, and should not be - * noticed, but name search should occur during entering universal menu, - * and will go through container for every record in file, that's why - * more critical to have faster search by record name. - */ - std::unordered_map records; - -public: - /** Calculate messages. Walk through the file ('universal_db_name') - * and calculate amount of records of certain type. */ - bool calculate_messages(); - - /** Start brute force */ - bool start_bruteforce(int index, int& record_amount); - - /** Stop brute force */ - void stop_bruteforce(); - - /** Send next signal during brute force */ - bool send_next_bruteforce(); - - /** Add record to container of records */ - void add_record(int index, const char* name); - - /** Initialize class, set db file */ - InfraredAppBruteForce(const char* filename) - : universal_db_filename(filename) { - } - - /** Deinitialize class */ - ~InfraredAppBruteForce() { - } -}; diff --git a/applications/infrared/infrared_app_event.h b/applications/infrared/infrared_app_event.h deleted file mode 100644 index 168ba0b1..00000000 --- a/applications/infrared/infrared_app_event.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file infrared_app_event.h - * Infrared: Scene events description - */ -#pragma once -#include -#include - -/** Infrared events class */ -class InfraredAppEvent { -public: - /** Type of event enum */ - enum class Type : uint8_t { - /** Tick event come after no other events came in 100 ms */ - Tick, - /** Exit application event */ - Exit, - /** Back event */ - Back, - /** Menu selected event type. Provided with payload value. */ - MenuSelected, - /** Button press event. Need for continuous signal sending. */ - MenuSelectedPress, - /** Button release event. Need for continuous signal sending. */ - MenuSelectedRelease, - /** Events from DialogEx view module */ - DialogExSelected, - /** Infrared signal received event */ - InfraredMessageReceived, - /** Text edit done event */ - TextEditDone, - /** Popup timer finished event */ - PopupTimer, - /** Button panel pressed event */ - ButtonPanelPressed, - }; - - union { - int32_t dummy; - /** Menu selected event type payload. Selected index. */ - int32_t menu_index; - /** DialogEx view module event type payload */ - DialogExResult dialog_ex_result; - } payload; - - /** Type of event */ - Type type; -}; diff --git a/applications/infrared/infrared_app_remote_manager.cpp b/applications/infrared/infrared_app_remote_manager.cpp deleted file mode 100644 index faeccb39..00000000 --- a/applications/infrared/infrared_app_remote_manager.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#include "m-string.h" -#include "storage/filesystem_api_defines.h" -#include -#include "infrared_app_remote_manager.h" -#include "infrared/helpers/infrared_parser.h" -#include "infrared/infrared_app_signal.h" - -#include - -#include -#include -#include -#include -#include -#include "infrared_app.h" -#include - -static const char* default_remote_name = "remote"; - -void InfraredAppRemoteManager::find_vacant_remote_name(string_t name, string_t path) { - Storage* storage = static_cast(furi_record_open("storage")); - - string_t base_path; - string_init_set(base_path, path); - - if(string_end_with_str_p(base_path, InfraredApp::infrared_extension)) { - size_t filename_start = string_search_rchar(base_path, '/'); - string_left(base_path, filename_start); - } - - string_printf( - base_path, - "%s/%s%s", - string_get_cstr(path), - string_get_cstr(name), - InfraredApp::infrared_extension); - - FS_Error error = storage_common_stat(storage, string_get_cstr(base_path), NULL); - - if(error == FSE_OK) { - /* if suggested name is occupied, try another one (name2, name3, etc) */ - size_t dot = string_search_rchar(base_path, '.'); - string_left(base_path, dot); - - string_t path_temp; - string_init(path_temp); - - uint32_t i = 1; - do { - string_printf( - path_temp, - "%s%u%s", - string_get_cstr(base_path), - ++i, - InfraredApp::infrared_extension); - error = storage_common_stat(storage, string_get_cstr(path_temp), NULL); - } while(error == FSE_OK); - - string_clear(path_temp); - - if(error == FSE_NOT_EXIST) { - string_cat_printf(name, "%u", i); - } - } - - string_clear(base_path); - furi_record_close("storage"); -} - -bool InfraredAppRemoteManager::add_button(const char* button_name, const InfraredAppSignal& signal) { - remote->buttons.emplace_back(button_name, signal); - return store(); -} - -bool InfraredAppRemoteManager::add_remote_with_button( - const char* button_name, - const InfraredAppSignal& signal) { - furi_check(button_name != nullptr); - - string_t new_name; - string_init_set_str(new_name, default_remote_name); - - string_t new_path; - string_init_set_str(new_path, InfraredApp::infrared_directory); - - find_vacant_remote_name(new_name, new_path); - - string_cat_printf( - new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension); - - remote = std::make_unique(new_path); - remote->name = std::string(string_get_cstr(new_name)); - - string_clear(new_path); - string_clear(new_name); - - return add_button(button_name, signal); -} - -std::vector InfraredAppRemoteManager::get_button_list(void) const { - std::vector name_vector; - name_vector.reserve(remote->buttons.size()); - - for(const auto& it : remote->buttons) { - name_vector.emplace_back(it.name); - } - - // copy elision - return name_vector; -} - -const InfraredAppSignal& InfraredAppRemoteManager::get_button_data(size_t index) const { - furi_check(remote.get() != nullptr); - auto& buttons = remote->buttons; - furi_check(index < buttons.size()); - - return buttons.at(index).signal; -} - -bool InfraredAppRemoteManager::delete_remote() { - Storage* storage = static_cast(furi_record_open("storage")); - - FS_Error error = storage_common_remove(storage, string_get_cstr(remote->path)); - reset_remote(); - - furi_record_close("storage"); - return (error == FSE_OK || error == FSE_NOT_EXIST); -} - -void InfraredAppRemoteManager::reset_remote() { - remote.reset(); -} - -bool InfraredAppRemoteManager::delete_button(uint32_t index) { - furi_check(remote.get() != nullptr); - auto& buttons = remote->buttons; - furi_check(index < buttons.size()); - - buttons.erase(buttons.begin() + index); - return store(); -} - -std::string InfraredAppRemoteManager::get_button_name(uint32_t index) { - furi_check(remote.get() != nullptr); - auto& buttons = remote->buttons; - furi_check(index < buttons.size()); - return buttons[index].name.c_str(); -} - -std::string InfraredAppRemoteManager::get_remote_name() { - return remote.get() ? remote->name : std::string(); -} - -bool InfraredAppRemoteManager::rename_remote(const char* str) { - furi_check(str != nullptr); - furi_check(remote.get() != nullptr); - furi_check(!string_empty_p(remote->path)); - - if(!remote->name.compare(str)) { - return true; - } - - string_t new_name; - string_init_set_str(new_name, str); - find_vacant_remote_name(new_name, remote->path); - - string_t new_path; - string_init_set(new_path, remote->path); - if(string_end_with_str_p(new_path, InfraredApp::infrared_extension)) { - size_t filename_start = string_search_rchar(new_path, '/'); - string_left(new_path, filename_start); - } - string_cat_printf( - new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension); - - Storage* storage = static_cast(furi_record_open("storage")); - - FS_Error error = - storage_common_rename(storage, string_get_cstr(remote->path), string_get_cstr(new_path)); - remote->name = std::string(string_get_cstr(new_name)); - - string_clear(new_name); - string_clear(new_path); - - furi_record_close("storage"); - return (error == FSE_OK || error == FSE_EXIST); -} - -bool InfraredAppRemoteManager::rename_button(uint32_t index, const char* str) { - furi_check(remote.get() != nullptr); - auto& buttons = remote->buttons; - furi_check(index < buttons.size()); - - buttons[index].name = str; - return store(); -} - -size_t InfraredAppRemoteManager::get_number_of_buttons() { - furi_check(remote.get() != nullptr); - return remote->buttons.size(); -} - -bool InfraredAppRemoteManager::store(void) { - bool result = false; - Storage* storage = static_cast(furi_record_open("storage")); - - if(!storage_simply_mkdir(storage, InfraredApp::infrared_directory)) return false; - - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FURI_LOG_I("RemoteManager", "store file: \'%s\'", string_get_cstr(remote->path)); - result = flipper_format_file_open_always(ff, string_get_cstr(remote->path)); - if(result) { - result = flipper_format_write_header_cstr(ff, "IR signals file", 1); - } - if(result) { - for(const auto& button : remote->buttons) { - result = infrared_parser_save_signal(ff, button.signal, button.name.c_str()); - if(!result) { - break; - } - } - } - - flipper_format_free(ff); - furi_record_close("storage"); - return result; -} - -bool InfraredAppRemoteManager::load(string_t path) { - bool result = false; - Storage* storage = static_cast(furi_record_open("storage")); - FlipperFormat* ff = flipper_format_file_alloc(storage); - - FURI_LOG_I("RemoteManager", "load file: \'%s\'", string_get_cstr(path)); - result = flipper_format_file_open_existing(ff, string_get_cstr(path)); - if(result) { - string_t header; - string_init(header); - uint32_t version; - result = flipper_format_read_header(ff, header, &version); - if(result) { - result = !string_cmp_str(header, "IR signals file") && (version == 1); - } - string_clear(header); - } - if(result) { - string_t new_name; - string_init(new_name); - - remote = std::make_unique(path); - path_extract_filename(path, new_name, true); - remote->name = std::string(string_get_cstr(new_name)); - - string_clear(new_name); - InfraredAppSignal signal; - std::string signal_name; - while(infrared_parser_read_signal(ff, signal, signal_name)) { - remote->buttons.emplace_back(signal_name.c_str(), std::move(signal)); - } - } - - flipper_format_free(ff); - furi_record_close("storage"); - return result; -} diff --git a/applications/infrared/infrared_app_remote_manager.h b/applications/infrared/infrared_app_remote_manager.h deleted file mode 100644 index b6f0b170..00000000 --- a/applications/infrared/infrared_app_remote_manager.h +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file infrared_app_remote_manager.h - * Infrared: Remote manager class. - * It holds remote, can load/save/rename remote, - * add/remove/rename buttons. - */ -#pragma once - -#include "infrared_app_signal.h" - -#include "m-string.h" -#include -#include - -#include -#include -#include -#include - -/** Class to handle remote button */ -class InfraredAppRemoteButton { - /** Allow field access */ - friend class InfraredAppRemoteManager; - /** Name of signal */ - std::string name; - /** Signal data */ - InfraredAppSignal signal; - -public: - /** Initialize remote button - * - * @param name - button name - * @param signal - signal to copy for remote button - */ - InfraredAppRemoteButton(const char* name, const InfraredAppSignal& signal) - : name(name) - , signal(signal) { - } - - /** Initialize remote button - * - * @param name - button name - * @param signal - signal to move for remote button - */ - InfraredAppRemoteButton(const char* name, InfraredAppSignal&& signal) - : name(name) - , signal(std::move(signal)) { - } - - /** Deinitialize remote button */ - ~InfraredAppRemoteButton() { - } -}; - -/** Class to handle remote */ -class InfraredAppRemote { - /** Allow field access */ - friend class InfraredAppRemoteManager; - /** Button container */ - std::vector buttons; - /** Name of remote */ - std::string name; - /** Path to remote file */ - string_t path; - -public: - /** Initialize new remote - * - * @param path - remote file path - */ - InfraredAppRemote(string_t file_path) { - string_init_set(path, file_path); - } - - ~InfraredAppRemote() { - string_clear(path); - } -}; - -/** Class to handle remote manager */ -class InfraredAppRemoteManager { - /** Remote instance. There can be 1 remote loaded at a time. */ - std::unique_ptr remote; - -public: - /** Restriction to button name length. Buttons larger are ignored. */ - static constexpr const uint32_t max_button_name_length = 22; - - /** Restriction to remote name length. Remotes larger are ignored. */ - static constexpr const uint32_t max_remote_name_length = 22; - - /** Construct button from signal, and create remote - * - * @param button_name - name of button to create - * @param signal - signal to create button from - * @retval true for success, false otherwise - * */ - bool add_remote_with_button(const char* button_name, const InfraredAppSignal& signal); - - /** Add button to current remote - * - * @param button_name - name of button to create - * @param signal - signal to create button from - * @retval true for success, false otherwise - * */ - bool add_button(const char* button_name, const InfraredAppSignal& signal); - - /** Rename button in current remote - * - * @param index - index of button to rename - * @param str - new button name - */ - bool rename_button(uint32_t index, const char* str); - - /** Rename current remote - * - * @param str - new remote name - */ - bool rename_remote(const char* str); - - /** Find vacant remote name. If suggested name is occupied, - * incremented digit(2,3,4,etc) added to name and check repeated. - * - * @param name - suggested remote name - * @param path - remote file path - */ - void find_vacant_remote_name(string_t name, string_t path); - - /** Get button list - * - * @retval container of button names - */ - std::vector get_button_list() const; - - /** Get button name by index - * - * @param index - index of button to get name from - * @retval button name - */ - std::string get_button_name(uint32_t index); - - /** Get remote name - * - * @retval remote name - */ - std::string get_remote_name(); - - /** Get number of buttons - * - * @retval number of buttons - */ - size_t get_number_of_buttons(); - - /** Get button's signal - * - * @param index - index of interested button - * @retval signal - */ - const InfraredAppSignal& get_button_data(size_t index) const; - - /** Delete button - * - * @param index - index of interested button - * @retval true if success, false otherwise - */ - bool delete_button(uint32_t index); - - /** Delete remote - * - * @retval true if success, false otherwise - */ - bool delete_remote(); - - /** Clean all loaded info in current remote */ - void reset_remote(); - - /** Store current remote data on disk - * - * @retval true if success, false otherwise - */ - bool store(); - - /** Load data from disk into current remote - * - * @param path - path to remote file - * @retval true if success, false otherwise - */ - bool load(string_t path); -}; diff --git a/applications/infrared/infrared_app_signal.cpp b/applications/infrared/infrared_app_signal.cpp deleted file mode 100644 index 3344b3ca..00000000 --- a/applications/infrared/infrared_app_signal.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "infrared_app_signal.h" -#include - -void InfraredAppSignal::copy_raw_signal( - const uint32_t* timings, - size_t size, - uint32_t frequency, - float duty_cycle) { - furi_assert(size); - furi_assert(timings); - - payload.raw.frequency = frequency; - payload.raw.duty_cycle = duty_cycle; - payload.raw.timings_cnt = size; - if(size) { - payload.raw.timings = new uint32_t[size]; - memcpy(payload.raw.timings, timings, size * sizeof(uint32_t)); - } -} - -void InfraredAppSignal::clear_timings() { - if(raw_signal) { - delete[] payload.raw.timings; - payload.raw.timings_cnt = 0; - payload.raw.timings = nullptr; - } -} - -InfraredAppSignal::InfraredAppSignal( - const uint32_t* timings, - size_t timings_cnt, - uint32_t frequency, - float duty_cycle) { - raw_signal = true; - copy_raw_signal(timings, timings_cnt, frequency, duty_cycle); -} - -InfraredAppSignal::InfraredAppSignal(const InfraredMessage* infrared_message) { - raw_signal = false; - payload.message = *infrared_message; -} - -InfraredAppSignal& InfraredAppSignal::operator=(const InfraredAppSignal& other) { - clear_timings(); - raw_signal = other.raw_signal; - if(!raw_signal) { - payload.message = other.payload.message; - } else { - copy_raw_signal( - other.payload.raw.timings, - other.payload.raw.timings_cnt, - other.payload.raw.frequency, - other.payload.raw.duty_cycle); - } - - return *this; -} - -InfraredAppSignal::InfraredAppSignal(const InfraredAppSignal& other) { - raw_signal = other.raw_signal; - if(!raw_signal) { - payload.message = other.payload.message; - } else { - copy_raw_signal( - other.payload.raw.timings, - other.payload.raw.timings_cnt, - other.payload.raw.frequency, - other.payload.raw.duty_cycle); - } -} - -InfraredAppSignal::InfraredAppSignal(InfraredAppSignal&& other) { - raw_signal = other.raw_signal; - if(!raw_signal) { - payload.message = other.payload.message; - } else { - furi_assert(other.payload.raw.timings_cnt > 0); - - payload.raw.timings = other.payload.raw.timings; - payload.raw.timings_cnt = other.payload.raw.timings_cnt; - payload.raw.frequency = other.payload.raw.frequency; - payload.raw.duty_cycle = other.payload.raw.duty_cycle; - other.payload.raw.timings = nullptr; - other.payload.raw.timings_cnt = 0; - other.raw_signal = false; - } -} - -void InfraredAppSignal::set_message(const InfraredMessage* infrared_message) { - clear_timings(); - raw_signal = false; - payload.message = *infrared_message; -} - -void InfraredAppSignal::set_raw_signal( - uint32_t* timings, - size_t timings_cnt, - uint32_t frequency, - float duty_cycle) { - clear_timings(); - raw_signal = true; - copy_raw_signal(timings, timings_cnt, frequency, duty_cycle); -} - -void InfraredAppSignal::transmit() const { - if(!raw_signal) { - infrared_send(&payload.message, 1); - } else { - infrared_send_raw_ext( - payload.raw.timings, - payload.raw.timings_cnt, - true, - payload.raw.frequency, - payload.raw.duty_cycle); - } -} diff --git a/applications/infrared/infrared_app_signal.h b/applications/infrared/infrared_app_signal.h deleted file mode 100644 index 7b0b491b..00000000 --- a/applications/infrared/infrared_app_signal.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @file infrared_app_signal.h - * Infrared: Signal class - */ -#pragma once -#include -#include -#include -#include - -/** Infrared application signal class */ -class InfraredAppSignal { -public: - /** Raw signal structure */ - typedef struct { - /** Timings amount */ - size_t timings_cnt; - /** Samples of raw signal in ms */ - uint32_t* timings; - /** PWM Frequency of raw signal */ - uint32_t frequency; - /** PWM Duty cycle of raw signal */ - float duty_cycle; - } RawSignal; - -private: - /** if true - signal is raw, if false - signal is parsed */ - bool raw_signal; - /** signal data, either raw or parsed */ - union { - /** signal data for parsed signal */ - InfraredMessage message; - /** raw signal data */ - RawSignal raw; - } payload; - - /** Copy raw signal into object - * - * @param timings - timings (samples) of raw signal - * @param size - number of timings - * @frequency - PWM frequency of raw signal - * @duty_cycle - PWM duty cycle - */ - void - copy_raw_signal(const uint32_t* timings, size_t size, uint32_t frequency, float duty_cycle); - /** Clear and free timings data */ - void clear_timings(); - -public: - /** Construct Infrared signal class */ - InfraredAppSignal() { - raw_signal = false; - payload.message.protocol = InfraredProtocolUnknown; - } - - /** Destruct signal class and free all allocated data */ - ~InfraredAppSignal() { - clear_timings(); - } - - /** Construct object with raw signal - * - * @param timings - timings (samples) of raw signal - * @param size - number of timings - * @frequency - PWM frequency of raw signal - * @duty_cycle - PWM duty cycle - */ - InfraredAppSignal( - const uint32_t* timings, - size_t timings_cnt, - uint32_t frequency, - float duty_cycle); - - /** Construct object with parsed signal - * - * @param infrared_message - parsed_signal to construct from - */ - InfraredAppSignal(const InfraredMessage* infrared_message); - - /** Copy constructor */ - InfraredAppSignal(const InfraredAppSignal& other); - /** Move constructor */ - InfraredAppSignal(InfraredAppSignal&& other); - - /** Assignment operator */ - InfraredAppSignal& operator=(const InfraredAppSignal& signal); - - /** Set object to parsed signal - * - * @param infrared_message - parsed_signal to construct from - */ - void set_message(const InfraredMessage* infrared_message); - - /** Set object to raw signal - * - * @param timings - timings (samples) of raw signal - * @param size - number of timings - * @frequency - PWM frequency of raw signal - * @duty_cycle - PWM duty cycle - */ - void - set_raw_signal(uint32_t* timings, size_t timings_cnt, uint32_t frequency, float duty_cycle); - - /** Transmit held signal (???) */ - void transmit() const; - - /** Show is held signal raw - * - * @retval true if signal is raw, false if signal is parsed - */ - bool is_raw(void) const { - return raw_signal; - } - - /** Get parsed signal. - * User must check is_raw() signal before calling this function. - * - * @retval parsed signal pointer - */ - const InfraredMessage& get_message(void) const { - furi_assert(!raw_signal); - return payload.message; - } - - /** Get raw signal. - * User must check is_raw() signal before calling this function. - * - * @retval raw signal - */ - const RawSignal& get_raw_signal(void) const { - furi_assert(raw_signal); - return payload.raw; - } -}; diff --git a/applications/infrared/infrared_app_view_manager.cpp b/applications/infrared/infrared_app_view_manager.cpp deleted file mode 100644 index f1e48ed4..00000000 --- a/applications/infrared/infrared_app_view_manager.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "infrared/infrared_app_view_manager.h" -#include "infrared/view/infrared_progress_view.h" -#include "infrared_app.h" -#include "infrared/infrared_app_event.h" - -InfraredAppViewManager::InfraredAppViewManager() { - event_queue = osMessageQueueNew(10, sizeof(InfraredAppEvent), NULL); - - view_dispatcher = view_dispatcher_alloc(); - auto callback = cbc::obtain_connector(this, &InfraredAppViewManager::previous_view_callback); - - gui = static_cast(furi_record_open("gui")); - view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); - - button_menu = button_menu_alloc(); - submenu = submenu_alloc(); - popup = popup_alloc(); - dialog_ex = dialog_ex_alloc(); - text_input = text_input_alloc(); - button_panel = button_panel_alloc(); - progress_view = infrared_progress_view_alloc(); - loading_view = loading_alloc(); - universal_view_stack = view_stack_alloc(); - view_stack_add_view(universal_view_stack, button_panel_get_view(button_panel)); - view_set_orientation(view_stack_get_view(universal_view_stack), ViewOrientationVertical); - - add_view(ViewId::UniversalRemote, view_stack_get_view(universal_view_stack)); - add_view(ViewId::ButtonMenu, button_menu_get_view(button_menu)); - add_view(ViewId::Submenu, submenu_get_view(submenu)); - add_view(ViewId::Popup, popup_get_view(popup)); - add_view(ViewId::DialogEx, dialog_ex_get_view(dialog_ex)); - add_view(ViewId::TextInput, text_input_get_view(text_input)); - - view_set_previous_callback(view_stack_get_view(universal_view_stack), callback); - view_set_previous_callback(button_menu_get_view(button_menu), callback); - view_set_previous_callback(submenu_get_view(submenu), callback); - view_set_previous_callback(popup_get_view(popup), callback); - view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback); - view_set_previous_callback(text_input_get_view(text_input), callback); -} - -InfraredAppViewManager::~InfraredAppViewManager() { - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::UniversalRemote)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::ButtonMenu)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::TextInput)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::DialogEx)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::Submenu)); - view_dispatcher_remove_view( - view_dispatcher, static_cast(InfraredAppViewManager::ViewId::Popup)); - - view_stack_remove_view(universal_view_stack, button_panel_get_view(button_panel)); - view_stack_free(universal_view_stack); - button_panel_free(button_panel); - submenu_free(submenu); - popup_free(popup); - button_menu_free(button_menu); - dialog_ex_free(dialog_ex); - text_input_free(text_input); - infrared_progress_view_free(progress_view); - loading_free(loading_view); - - view_dispatcher_free(view_dispatcher); - furi_record_close("gui"); - osMessageQueueDelete(event_queue); -} - -void InfraredAppViewManager::switch_to(ViewId type) { - view_dispatcher_switch_to_view(view_dispatcher, static_cast(type)); -} - -TextInput* InfraredAppViewManager::get_text_input() { - return text_input; -} - -DialogEx* InfraredAppViewManager::get_dialog_ex() { - return dialog_ex; -} - -Submenu* InfraredAppViewManager::get_submenu() { - return submenu; -} - -Popup* InfraredAppViewManager::get_popup() { - return popup; -} - -ButtonMenu* InfraredAppViewManager::get_button_menu() { - return button_menu; -} - -ButtonPanel* InfraredAppViewManager::get_button_panel() { - return button_panel; -} - -InfraredProgressView* InfraredAppViewManager::get_progress() { - return progress_view; -} - -Loading* InfraredAppViewManager::get_loading() { - return loading_view; -} - -ViewStack* InfraredAppViewManager::get_universal_view_stack() { - return universal_view_stack; -} - -osMessageQueueId_t InfraredAppViewManager::get_event_queue() { - return event_queue; -} - -void InfraredAppViewManager::clear_events() { - InfraredAppEvent event; - while(osMessageQueueGet(event_queue, &event, NULL, 0) == osOK) - ; -} - -void InfraredAppViewManager::receive_event(InfraredAppEvent* event) { - if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { - event->type = InfraredAppEvent::Type::Tick; - } -} - -void InfraredAppViewManager::send_event(InfraredAppEvent* event) { - uint32_t timeout = 0; - /* Rapid button hammering on signal send scenes causes queue overflow - ignore it, - * but try to keep button release event - it switches off INFRARED DMA sending. */ - if(event->type == InfraredAppEvent::Type::MenuSelectedRelease) { - timeout = 200; - } - if((event->type == InfraredAppEvent::Type::DialogExSelected) && - (event->payload.dialog_ex_result == DialogExReleaseCenter)) { - timeout = 200; - } - - osMessageQueuePut(event_queue, event, 0, timeout); -} - -uint32_t InfraredAppViewManager::previous_view_callback(void*) { - if(event_queue != NULL) { - InfraredAppEvent event; - event.type = InfraredAppEvent::Type::Back; - send_event(&event); - } - - return VIEW_IGNORE; -} - -void InfraredAppViewManager::add_view(ViewId view_type, View* view) { - view_dispatcher_add_view(view_dispatcher, static_cast(view_type), view); -} diff --git a/applications/infrared/infrared_app_view_manager.h b/applications/infrared/infrared_app_view_manager.h deleted file mode 100644 index 106d2660..00000000 --- a/applications/infrared/infrared_app_view_manager.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @file infrared_app_view_manager.h - * Infrared: Scene events description - */ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "infrared_app_event.h" -#include "view/infrared_progress_view.h" - -/** Infrared View manager class */ -class InfraredAppViewManager { -public: - /** Infrared View Id enum, it is used - * to identify added views */ - enum class ViewId : uint8_t { - DialogEx, - TextInput, - Submenu, - ButtonMenu, - UniversalRemote, - Popup, - }; - - /** Class constructor */ - InfraredAppViewManager(); - /** Class destructor */ - ~InfraredAppViewManager(); - - /** Switch to another view - * - * @param id - view id to switch to - */ - void switch_to(ViewId id); - - /** Receive event from queue - * - * @param event - received event - */ - void receive_event(InfraredAppEvent* event); - - /** Send event to queue - * - * @param event - event to send - */ - void send_event(InfraredAppEvent* event); - - /** Clear events that already in queue - * - * @param event - event to send - */ - void clear_events(); - - /** Get dialog_ex view module - * - * @retval dialog_ex view module - */ - DialogEx* get_dialog_ex(); - - /** Get submenu view module - * - * @retval submenu view module - */ - Submenu* get_submenu(); - - /** Get popup view module - * - * @retval popup view module - */ - Popup* get_popup(); - - /** Get text_input view module - * - * @retval text_input view module - */ - TextInput* get_text_input(); - - /** Get button_menu view module - * - * @retval button_menu view module - */ - ButtonMenu* get_button_menu(); - - /** Get button_panel view module - * - * @retval button_panel view module - */ - ButtonPanel* get_button_panel(); - - /** Get view_stack view module used in universal remote - * - * @retval view_stack view module - */ - ViewStack* get_universal_view_stack(); - - /** Get progress view module - * - * @retval progress view module - */ - InfraredProgressView* get_progress(); - - /** Get loading view module - * - * @retval loading view module - */ - Loading* get_loading(); - - /** Get event queue - * - * @retval event queue - */ - osMessageQueueId_t get_event_queue(); - - /** Callback to handle back button - * - * @param context - context to pass to callback - * @retval always returns VIEW_IGNORE - */ - uint32_t previous_view_callback(void* context); - -private: - /** View Dispatcher instance. - * It handles view switching */ - ViewDispatcher* view_dispatcher; - /** Gui instance */ - Gui* gui; - /** Text input view module instance */ - TextInput* text_input; - /** DialogEx view module instance */ - DialogEx* dialog_ex; - /** Submenu view module instance */ - Submenu* submenu; - /** Popup view module instance */ - Popup* popup; - /** ButtonMenu view module instance */ - ButtonMenu* button_menu; - /** ButtonPanel view module instance */ - ButtonPanel* button_panel; - /** ViewStack view module instance */ - ViewStack* universal_view_stack; - /** ProgressView view module instance */ - InfraredProgressView* progress_view; - /** Loading view module instance */ - Loading* loading_view; - - /** Queue to handle events, which are processed in scenes */ - osMessageQueueId_t event_queue; - - /** Add View to pull of views - * - * @param view_id - id to identify view - * @param view - view to add - */ - void add_view(ViewId view_id, View* view); -}; diff --git a/applications/infrared/infrared_brute_force.c b/applications/infrared/infrared_brute_force.c new file mode 100644 index 00000000..55bf5c7f --- /dev/null +++ b/applications/infrared/infrared_brute_force.c @@ -0,0 +1,154 @@ +#include "infrared_brute_force.h" + +#include +#include +#include +#include + +#include "infrared_signal.h" + +typedef struct { + uint32_t index; + uint32_t count; +} InfraredBruteForceRecord; + +DICT_DEF2( + InfraredBruteForceRecordDict, + string_t, + STRING_OPLIST, + InfraredBruteForceRecord, + M_POD_OPLIST); + +struct InfraredBruteForce { + FlipperFormat* ff; + const char* db_filename; + string_t current_record_name; + InfraredBruteForceRecordDict_t records; +}; + +InfraredBruteForce* infrared_brute_force_alloc() { + InfraredBruteForce* brute_force = malloc(sizeof(InfraredBruteForce)); + brute_force->ff = NULL; + brute_force->db_filename = NULL; + string_init(brute_force->current_record_name); + InfraredBruteForceRecordDict_init(brute_force->records); + return brute_force; +} + +void infrared_brute_force_free(InfraredBruteForce* brute_force) { + furi_assert(!brute_force->ff); + InfraredBruteForceRecordDict_clear(brute_force->records); + string_clear(brute_force->current_record_name); + free(brute_force); +} + +void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename) { + brute_force->db_filename = db_filename; +} + +bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) { + furi_assert(brute_force->db_filename); + bool success = false; + + Storage* storage = furi_record_open("storage"); + FlipperFormat* ff = flipper_format_file_alloc(storage); + + success = flipper_format_file_open_existing(ff, brute_force->db_filename); + if(success) { + string_t signal_name; + string_init(signal_name); + while(flipper_format_read_string(ff, "name", signal_name)) { + InfraredBruteForceRecord* record = + InfraredBruteForceRecordDict_get(brute_force->records, signal_name); + if(record) { + ++(record->count); + } + } + string_clear(signal_name); + } + + flipper_format_free(ff); + furi_record_close("storage"); + return success; +} + +bool infrared_brute_force_start( + InfraredBruteForce* brute_force, + uint32_t index, + uint32_t* record_count) { + bool success = false; + *record_count = 0; + + InfraredBruteForceRecordDict_it_t it; + for(InfraredBruteForceRecordDict_it(it, brute_force->records); + !InfraredBruteForceRecordDict_end_p(it); + InfraredBruteForceRecordDict_next(it)) { + const InfraredBruteForceRecordDict_itref_t* record = InfraredBruteForceRecordDict_cref(it); + if(record->value.index == index) { + *record_count = record->value.count; + if(*record_count) { + string_set(brute_force->current_record_name, record->key); + } + break; + } + } + + if(*record_count) { + Storage* storage = furi_record_open("storage"); + brute_force->ff = flipper_format_file_alloc(storage); + success = flipper_format_file_open_existing(brute_force->ff, brute_force->db_filename); + if(!success) { + flipper_format_free(brute_force->ff); + brute_force->ff = NULL; + furi_record_close("storage"); + } + } + return success; +} + +bool infrared_brute_force_is_started(InfraredBruteForce* brute_force) { + return brute_force->ff; +} + +void infrared_brute_force_stop(InfraredBruteForce* brute_force) { + furi_assert(string_size(brute_force->current_record_name)); + furi_assert(brute_force->ff); + + string_reset(brute_force->current_record_name); + flipper_format_free(brute_force->ff); + furi_record_close("storage"); + brute_force->ff = NULL; +} + +bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) { + furi_assert(string_size(brute_force->current_record_name)); + furi_assert(brute_force->ff); + bool success = false; + + string_t signal_name; + string_init(signal_name); + InfraredSignal* signal = infrared_signal_alloc(); + + do { + success = infrared_signal_read(signal, brute_force->ff, signal_name); + } while(success && !string_equal_p(brute_force->current_record_name, signal_name)); + + if(success) { + infrared_signal_transmit(signal); + } + + infrared_signal_free(signal); + string_clear(signal_name); + return success; +} + +void infrared_brute_force_add_record( + InfraredBruteForce* brute_force, + uint32_t index, + const char* name) { + InfraredBruteForceRecord value = {.index = index, .count = 0}; + string_t key; + string_init_set_str(key, name); + InfraredBruteForceRecordDict_set_at(brute_force->records, key, value); + string_clear(key); +} diff --git a/applications/infrared/infrared_brute_force.h b/applications/infrared/infrared_brute_force.h new file mode 100644 index 00000000..acf0d7b6 --- /dev/null +++ b/applications/infrared/infrared_brute_force.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +typedef struct InfraredBruteForce InfraredBruteForce; + +InfraredBruteForce* infrared_brute_force_alloc(); +void infrared_brute_force_free(InfraredBruteForce* brute_force); +void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename); +bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force); +bool infrared_brute_force_start( + InfraredBruteForce* brute_force, + uint32_t index, + uint32_t* record_count); +bool infrared_brute_force_is_started(InfraredBruteForce* brute_force); +void infrared_brute_force_stop(InfraredBruteForce* brute_force); +bool infrared_brute_force_send_next(InfraredBruteForce* brute_force); +void infrared_brute_force_add_record( + InfraredBruteForce* brute_force, + uint32_t index, + const char* name); diff --git a/applications/infrared/cli/infrared_cli.cpp b/applications/infrared/infrared_cli.c similarity index 72% rename from applications/infrared/cli/infrared_cli.cpp rename to applications/infrared/infrared_cli.c index 79ab987d..d88e7fff 100644 --- a/applications/infrared/cli/infrared_cli.cpp +++ b/applications/infrared/infrared_cli.c @@ -1,16 +1,12 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include "../helpers/infrared_parser.h" +#include +#include +#include +#include + +#include "infrared_signal.h" + +#define INFRARED_CLI_BUF_SIZE 10 static void infrared_cli_start_ir_rx(Cli* cli, string_t args); static void infrared_cli_start_ir_tx(Cli* cli, string_t args); @@ -92,79 +88,84 @@ static void infrared_cli_print_usage(void) { INFRARED_MAX_FREQUENCY); } -static bool parse_message(const char* str, InfraredMessage* message) { +static bool infrared_cli_parse_message(const char* str, InfraredSignal* signal) { char protocol_name[32]; - int parsed = sscanf(str, "%31s %lX %lX", protocol_name, &message->address, &message->command); + InfraredMessage message; + int parsed = sscanf(str, "%31s %lX %lX", protocol_name, &message.address, &message.command); if(parsed != 3) { return false; } - message->protocol = infrared_get_protocol_by_name(protocol_name); - message->repeat = false; - - return infrared_parser_is_parsed_signal_valid(message); + message.protocol = infrared_get_protocol_by_name(protocol_name); + message.repeat = false; + infrared_signal_set_message(signal, &message); + return infrared_signal_is_valid(signal); } -static bool parse_signal_raw( - const char* str, - uint32_t* timings, - uint32_t* timings_cnt, - float* duty_cycle, - uint32_t* frequency) { - char frequency_str[10]; - char duty_cycle_str[10]; +static bool infrared_cli_parse_raw(const char* str, InfraredSignal* signal) { + char frequency_str[INFRARED_CLI_BUF_SIZE]; + char duty_cycle_str[INFRARED_CLI_BUF_SIZE]; int parsed = sscanf(str, "RAW F:%9s DC:%9s", frequency_str, duty_cycle_str); - if(parsed != 2) return false; - *frequency = atoi(frequency_str); - *duty_cycle = (float)atoi(duty_cycle_str) / 100; - str += strlen(frequency_str) + strlen(duty_cycle_str) + 10; - - uint32_t timings_cnt_max = *timings_cnt; - *timings_cnt = 0; - - while(1) { - char timing_str[10]; - for(; *str == ' '; ++str) - ; - if(1 != sscanf(str, "%9s", timing_str)) break; - str += strlen(timing_str); - uint32_t timing = atoi(timing_str); - if(timing <= 0) break; - if(*timings_cnt >= timings_cnt_max) break; - timings[*timings_cnt] = timing; - ++*timings_cnt; + if(parsed != 2) { + return false; } - return infrared_parser_is_raw_signal_valid(*frequency, *duty_cycle, *timings_cnt); + uint32_t* timings = malloc(sizeof(uint32_t) * MAX_TIMINGS_AMOUNT); + uint32_t frequency = atoi(frequency_str); + float duty_cycle = (float)atoi(duty_cycle_str) / 100; + + str += strlen(frequency_str) + strlen(duty_cycle_str) + INFRARED_CLI_BUF_SIZE; + + size_t timings_size = 0; + while(1) { + while(*str == ' ') { + ++str; + } + + char timing_str[INFRARED_CLI_BUF_SIZE]; + if(sscanf(str, "%9s", timing_str) != 1) { + break; + } + + str += strlen(timing_str); + uint32_t timing = atoi(timing_str); + + if((timing <= 0) || (timings_size >= MAX_TIMINGS_AMOUNT)) { + break; + } + + timings[timings_size] = timing; + ++timings_size; + } + + infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle); + free(timings); + + return infrared_signal_is_valid(signal); } static void infrared_cli_start_ir_tx(Cli* cli, string_t args) { UNUSED(cli); - InfraredMessage message; const char* str = string_get_cstr(args); - uint32_t frequency; - float duty_cycle; - uint32_t timings_cnt = MAX_TIMINGS_AMOUNT; - uint32_t* timings = (uint32_t*)malloc(sizeof(uint32_t) * timings_cnt); + InfraredSignal* signal = infrared_signal_alloc(); - if(parse_message(str, &message)) { - infrared_send(&message, 1); - } else if(parse_signal_raw(str, timings, &timings_cnt, &duty_cycle, &frequency)) { - infrared_send_raw_ext(timings, timings_cnt, true, frequency, duty_cycle); + bool success = infrared_cli_parse_message(str, signal) || infrared_cli_parse_raw(str, signal); + if(success) { + infrared_signal_transmit(signal); } else { printf("Wrong arguments.\r\n"); infrared_cli_print_usage(); } - free(timings); + infrared_signal_free(signal); } static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { UNUSED(context); if(furi_hal_infrared_is_busy()) { - printf("INFRARED is busy. Exit."); + printf("INFRARED is busy. Exiting."); return; } @@ -189,8 +190,7 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { infrared_cli_print_usage(); } } - -extern "C" void infrared_on_system_start() { +void infrared_on_system_start() { #ifdef SRV_CLI Cli* cli = (Cli*)furi_record_open("cli"); cli_add_command(cli, "ir", CliCommandFlagDefault, infrared_cli_start_ir, NULL); diff --git a/applications/infrared/infrared_custom_event.h b/applications/infrared/infrared_custom_event.h new file mode 100644 index 00000000..46d75a9e --- /dev/null +++ b/applications/infrared/infrared_custom_event.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +enum InfraredCustomEventType { + // Reserve first 100 events for button types and indexes, starting from 0 + InfraredCustomEventTypeReserved = 100, + InfraredCustomEventTypeMenuSelected, + InfraredCustomEventTypeTransmitStarted, + InfraredCustomEventTypeTransmitStopped, + InfraredCustomEventTypeSignalReceived, + InfraredCustomEventTypeTextEditDone, + InfraredCustomEventTypePopupClosed, + InfraredCustomEventTypeButtonSelected, + InfraredCustomEventTypeBackPressed, +}; + +#pragma pack(push, 1) +typedef union { + uint32_t packed_value; + struct { + uint16_t type; + int16_t value; + } content; +} InfraredCustomEvent; +#pragma pack(pop) + +static inline uint32_t infrared_custom_event_pack(uint16_t type, int16_t value) { + InfraredCustomEvent event = {.content = {.type = type, .value = value}}; + return event.packed_value; +} + +static inline void + infrared_custom_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) { + InfraredCustomEvent event = {.packed_value = packed_value}; + if(type) *type = event.content.type; + if(value) *value = event.content.value; +} + +static inline uint16_t infrared_custom_event_get_type(uint32_t packed_value) { + uint16_t type; + infrared_custom_event_unpack(packed_value, &type, NULL); + return type; +} + +static inline int16_t infrared_custom_event_get_value(uint32_t packed_value) { + int16_t value; + infrared_custom_event_unpack(packed_value, NULL, &value); + return value; +} diff --git a/applications/infrared/infrared_i.h b/applications/infrared/infrared_i.h new file mode 100644 index 00000000..5c447adc --- /dev/null +++ b/applications/infrared/infrared_i.h @@ -0,0 +1,134 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "infrared.h" +#include "infrared_remote.h" +#include "infrared_brute_force.h" +#include "infrared_custom_event.h" + +#include "scenes/infrared_scene.h" +#include "views/infrared_progress_view.h" +#include "views/infrared_debug_view.h" + +#define INFRARED_FILE_NAME_SIZE 100 +#define INFRARED_TEXT_STORE_NUM 2 +#define INFRARED_TEXT_STORE_SIZE 128 + +#define INFRARED_MAX_BUTTON_NAME_LENGTH 22 +#define INFRARED_MAX_REMOTE_NAME_LENGTH 22 + +#define INFRARED_APP_FOLDER "/any/infrared" +#define INFRARED_APP_EXTENSION ".ir" + +#define INFRARED_DEFAULT_REMOTE_NAME "Remote" + +typedef enum { + InfraredButtonIndexNone = -1, +} InfraredButtonIndex; + +typedef enum { + InfraredEditTargetNone, + InfraredEditTargetRemote, + InfraredEditTargetButton, +} InfraredEditTarget; + +typedef enum { + InfraredEditModeNone, + InfraredEditModeRename, + InfraredEditModeDelete, +} InfraredEditMode; + +typedef struct { + bool is_learning_new_remote; + bool is_debug_enabled; + InfraredEditTarget edit_target : 8; + InfraredEditMode edit_mode : 8; + int32_t current_button_index; +} InfraredAppState; + +struct Infrared { + SceneManager* scene_manager; + ViewDispatcher* view_dispatcher; + + Gui* gui; + Storage* storage; + DialogsApp* dialogs; + NotificationApp* notifications; + InfraredWorker* worker; + InfraredRemote* remote; + InfraredSignal* received_signal; + InfraredBruteForce* brute_force; + + Submenu* submenu; + TextInput* text_input; + DialogEx* dialog_ex; + ButtonMenu* button_menu; + Popup* popup; + + ViewStack* view_stack; + InfraredDebugView* debug_view; + + ButtonPanel* button_panel; + Loading* loading; + InfraredProgressView* progress; + + string_t file_path; + char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; + InfraredAppState app_state; +}; + +typedef enum { + InfraredViewSubmenu, + InfraredViewTextInput, + InfraredViewDialogEx, + InfraredViewButtonMenu, + InfraredViewPopup, + InfraredViewStack, + InfraredViewDebugView, +} InfraredView; + +typedef enum { + InfraredNotificationMessageSuccess, + InfraredNotificationMessageGreenOn, + InfraredNotificationMessageGreenOff, + InfraredNotificationMessageBlinkRead, + InfraredNotificationMessageBlinkSend, + InfraredNotificationMessageYellowOn, + InfraredNotificationMessageYellowOff, +} InfraredNotificationMessage; + +bool infrared_add_remote_with_button(Infrared* infrared, const char* name, InfraredSignal* signal); +bool infrared_rename_current_remote(Infrared* infrared, const char* name); +void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal); +void infrared_tx_start_button_index(Infrared* infrared, size_t button_index); +void infrared_tx_start_received(Infrared* infrared); +void infrared_tx_stop(Infrared* infrared); +void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text, ...); +void infrared_text_store_clear(Infrared* infrared, uint32_t bank); +void infrared_play_notification_message(Infrared* infrared, uint32_t message); +void infrared_show_loading_popup(Infrared* infrared, bool show); + +void infrared_signal_sent_callback(void* context); +void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal); +void infrared_text_input_callback(void* context); +void infrared_popup_closed_callback(void* context); diff --git a/applications/infrared/infrared_remote.c b/applications/infrared/infrared_remote.c new file mode 100644 index 00000000..ad75efe7 --- /dev/null +++ b/applications/infrared/infrared_remote.c @@ -0,0 +1,176 @@ +#include "infrared_remote.h" + +#include +#include +#include +#include +#include +#include + +#define TAG "InfraredRemote" + +ARRAY_DEF(InfraredButtonArray, InfraredRemoteButton*, M_PTR_OPLIST); + +struct InfraredRemote { + InfraredButtonArray_t buttons; + string_t name; + string_t path; +}; + +static void infrared_remote_clear_buttons(InfraredRemote* remote) { + InfraredButtonArray_it_t it; + for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it); + InfraredButtonArray_next(it)) { + infrared_remote_button_free(*InfraredButtonArray_cref(it)); + } + InfraredButtonArray_reset(remote->buttons); +} + +InfraredRemote* infrared_remote_alloc() { + InfraredRemote* remote = malloc(sizeof(InfraredRemote)); + InfraredButtonArray_init(remote->buttons); + string_init(remote->name); + string_init(remote->path); + return remote; +} + +void infrared_remote_free(InfraredRemote* remote) { + infrared_remote_clear_buttons(remote); + InfraredButtonArray_clear(remote->buttons); + string_clear(remote->path); + string_clear(remote->name); + free(remote); +} + +void infrared_remote_reset(InfraredRemote* remote) { + infrared_remote_clear_buttons(remote); + string_reset(remote->name); + string_reset(remote->path); +} + +void infrared_remote_set_name(InfraredRemote* remote, const char* name) { + string_set_str(remote->name, name); +} + +const char* infrared_remote_get_name(InfraredRemote* remote) { + return string_get_cstr(remote->name); +} + +void infrared_remote_set_path(InfraredRemote* remote, const char* path) { + string_set_str(remote->path, path); +} + +const char* infrared_remote_get_path(InfraredRemote* remote) { + return string_get_cstr(remote->path); +} + +size_t infrared_remote_get_button_count(InfraredRemote* remote) { + return InfraredButtonArray_size(remote->buttons); +} + +InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index) { + furi_assert(index < InfraredButtonArray_size(remote->buttons)); + return *InfraredButtonArray_get(remote->buttons, index); +} + +bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal) { + InfraredRemoteButton* button = infrared_remote_button_alloc(); + infrared_remote_button_set_name(button, name); + infrared_remote_button_set_signal(button, signal); + InfraredButtonArray_push_back(remote->buttons, button); + return infrared_remote_store(remote); +} + +bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index) { + furi_assert(index < InfraredButtonArray_size(remote->buttons)); + InfraredRemoteButton* button = *InfraredButtonArray_get(remote->buttons, index); + infrared_remote_button_set_name(button, new_name); + return infrared_remote_store(remote); +} + +bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) { + furi_assert(index < InfraredButtonArray_size(remote->buttons)); + InfraredRemoteButton* button; + InfraredButtonArray_pop_at(&button, remote->buttons, index); + infrared_remote_button_free(button); + return infrared_remote_store(remote); +} + +bool infrared_remote_store(InfraredRemote* remote) { + Storage* storage = furi_record_open("storage"); + FlipperFormat* ff = flipper_format_file_alloc(storage); + const char* path = string_get_cstr(remote->path); + + FURI_LOG_I(TAG, "store file: \'%s\'", path); + + bool success = flipper_format_file_open_always(ff, path) && + flipper_format_write_header_cstr(ff, "IR signals file", 1); + if(success) { + InfraredButtonArray_it_t it; + for(InfraredButtonArray_it(it, remote->buttons); !InfraredButtonArray_end_p(it); + InfraredButtonArray_next(it)) { + InfraredRemoteButton* button = *InfraredButtonArray_cref(it); + success = infrared_signal_save( + infrared_remote_button_get_signal(button), + ff, + infrared_remote_button_get_name(button)); + if(!success) { + break; + } + } + } + + flipper_format_free(ff); + furi_record_close("storage"); + return success; +} + +bool infrared_remote_load(InfraredRemote* remote, string_t path) { + Storage* storage = furi_record_open("storage"); + FlipperFormat* ff = flipper_format_file_alloc(storage); + + string_t buf; + string_init(buf); + + FURI_LOG_I(TAG, "load file: \'%s\'", string_get_cstr(path)); + bool success = flipper_format_file_open_existing(ff, string_get_cstr(path)); + + if(success) { + uint32_t version; + success = flipper_format_read_header(ff, buf, &version) && + !string_cmp_str(buf, "IR signals file") && (version == 1); + } + + if(success) { + path_extract_filename(path, buf, true); + infrared_remote_clear_buttons(remote); + infrared_remote_set_name(remote, string_get_cstr(buf)); + infrared_remote_set_path(remote, string_get_cstr(path)); + + for(bool can_read = true; can_read;) { + InfraredRemoteButton* button = infrared_remote_button_alloc(); + can_read = infrared_signal_read(infrared_remote_button_get_signal(button), ff, buf); + if(can_read) { + infrared_remote_button_set_name(button, string_get_cstr(buf)); + InfraredButtonArray_push_back(remote->buttons, button); + } else { + infrared_remote_button_free(button); + } + } + } + + string_clear(buf); + flipper_format_free(ff); + furi_record_close("storage"); + return success; +} + +bool infrared_remote_remove(InfraredRemote* remote) { + Storage* storage = furi_record_open("storage"); + + FS_Error status = storage_common_remove(storage, string_get_cstr(remote->path)); + infrared_remote_reset(remote); + + furi_record_close("storage"); + return (status == FSE_OK || status == FSE_NOT_EXIST); +} diff --git a/applications/infrared/infrared_remote.h b/applications/infrared/infrared_remote.h new file mode 100644 index 00000000..1336383f --- /dev/null +++ b/applications/infrared/infrared_remote.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "infrared_remote_button.h" + +typedef struct InfraredRemote InfraredRemote; + +InfraredRemote* infrared_remote_alloc(); +void infrared_remote_free(InfraredRemote* remote); +void infrared_remote_reset(InfraredRemote* remote); + +void infrared_remote_set_name(InfraredRemote* remote, const char* name); +const char* infrared_remote_get_name(InfraredRemote* remote); + +void infrared_remote_set_path(InfraredRemote* remote, const char* path); +const char* infrared_remote_get_path(InfraredRemote* remote); + +size_t infrared_remote_get_button_count(InfraredRemote* remote); +InfraredRemoteButton* infrared_remote_get_button(InfraredRemote* remote, size_t index); + +bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal); +bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index); +bool infrared_remote_delete_button(InfraredRemote* remote, size_t index); + +bool infrared_remote_store(InfraredRemote* remote); +bool infrared_remote_load(InfraredRemote* remote, string_t path); +bool infrared_remote_remove(InfraredRemote* remote); diff --git a/applications/infrared/infrared_remote_button.c b/applications/infrared/infrared_remote_button.c new file mode 100644 index 00000000..7525ce48 --- /dev/null +++ b/applications/infrared/infrared_remote_button.c @@ -0,0 +1,38 @@ +#include "infrared_remote_button.h" + +#include +#include + +struct InfraredRemoteButton { + string_t name; + InfraredSignal* signal; +}; + +InfraredRemoteButton* infrared_remote_button_alloc() { + InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton)); + string_init(button->name); + button->signal = infrared_signal_alloc(); + return button; +} + +void infrared_remote_button_free(InfraredRemoteButton* button) { + string_clear(button->name); + infrared_signal_free(button->signal); + free(button); +} + +void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name) { + string_set_str(button->name, name); +} + +const char* infrared_remote_button_get_name(InfraredRemoteButton* button) { + return string_get_cstr(button->name); +} + +void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal) { + infrared_signal_set_signal(button->signal, signal); +} + +InfraredSignal* infrared_remote_button_get_signal(InfraredRemoteButton* button) { + return button->signal; +} diff --git a/applications/infrared/infrared_remote_button.h b/applications/infrared/infrared_remote_button.h new file mode 100644 index 00000000..f25b759b --- /dev/null +++ b/applications/infrared/infrared_remote_button.h @@ -0,0 +1,14 @@ +#pragma once + +#include "infrared_signal.h" + +typedef struct InfraredRemoteButton InfraredRemoteButton; + +InfraredRemoteButton* infrared_remote_button_alloc(); +void infrared_remote_button_free(InfraredRemoteButton* button); + +void infrared_remote_button_set_name(InfraredRemoteButton* button, const char* name); +const char* infrared_remote_button_get_name(InfraredRemoteButton* button); + +void infrared_remote_button_set_signal(InfraredRemoteButton* button, InfraredSignal* signal); +InfraredSignal* infrared_remote_button_get_signal(InfraredRemoteButton* button); diff --git a/applications/infrared/infrared_runner.cpp b/applications/infrared/infrared_runner.cpp deleted file mode 100644 index 650b0fcd..00000000 --- a/applications/infrared/infrared_runner.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "infrared_app.h" - -extern "C" int32_t infrared_app(void* p) { - InfraredApp* app = new InfraredApp(); - int32_t result = app->run(p); - delete app; - - return result; -} diff --git a/applications/infrared/infrared_signal.c b/applications/infrared/infrared_signal.c new file mode 100644 index 00000000..79eafb30 --- /dev/null +++ b/applications/infrared/infrared_signal.c @@ -0,0 +1,264 @@ +#include "infrared_signal.h" + +#include +#include +#include +#include +#include + +#define TAG "InfraredSignal" + +struct InfraredSignal { + bool is_raw; + union { + InfraredMessage message; + InfraredRawSignal raw; + } payload; +}; + +static void infrared_signal_clear_timings(InfraredSignal* signal) { + if(signal->is_raw) { + free(signal->payload.raw.timings); + signal->payload.raw.timings_size = 0; + signal->payload.raw.timings = NULL; + } +} + +static bool infrared_signal_is_message_valid(InfraredMessage* message) { + if(!infrared_is_protocol_valid(message->protocol)) { + FURI_LOG_E(TAG, "Unknown protocol"); + return false; + } + + uint32_t address_length = infrared_get_protocol_address_length(message->protocol); + uint32_t address_mask = (1UL << address_length) - 1; + + if(message->address != (message->address & address_mask)) { + FURI_LOG_E( + TAG, + "Address is out of range (mask 0x%08lX): 0x%lX\r\n", + address_mask, + message->address); + return false; + } + + uint32_t command_length = infrared_get_protocol_command_length(message->protocol); + uint32_t command_mask = (1UL << command_length) - 1; + + if(message->command != (message->command & command_mask)) { + FURI_LOG_E( + TAG, + "Command is out of range (mask 0x%08lX): 0x%lX\r\n", + command_mask, + message->command); + return false; + } + + return true; +} + +static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) { + if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) { + FURI_LOG_E( + TAG, + "Frequency is out of range (%lX - %lX): %lX", + INFRARED_MIN_FREQUENCY, + INFRARED_MAX_FREQUENCY, + raw->frequency); + return false; + + } else if((raw->duty_cycle <= 0) || (raw->duty_cycle > 1)) { + FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)raw->duty_cycle); + return false; + + } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) { + FURI_LOG_E( + TAG, + "Timings amount is out of range (0 - %lX): %lX", + MAX_TIMINGS_AMOUNT, + raw->timings_size); + return false; + } + + return true; +} + +static inline bool infrared_signal_save_message(InfraredMessage* message, FlipperFormat* ff) { + const char* protocol_name = infrared_get_protocol_name(message->protocol); + return flipper_format_write_string_cstr(ff, "type", "parsed") && + flipper_format_write_string_cstr(ff, "protocol", protocol_name) && + flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) && + flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4); +} + +static inline bool infrared_signal_save_raw(InfraredRawSignal* raw, FlipperFormat* ff) { + furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT); + return flipper_format_write_string_cstr(ff, "type", "raw") && + flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) && + flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) && + flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size); +} + +static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) { + string_t buf; + string_init(buf); + bool success = false; + + do { + if(!flipper_format_read_string(ff, "protocol", buf)) break; + + InfraredMessage message; + message.protocol = infrared_get_protocol_by_name(string_get_cstr(buf)); + + success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) && + flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) && + infrared_signal_is_message_valid(&message); + + if(!success) break; + + infrared_signal_set_message(signal, &message); + } while(0); + + string_clear(buf); + return success; +} + +static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) { + uint32_t timings_size, frequency; + float duty_cycle; + + bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) && + flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) && + flipper_format_get_value_count(ff, "data", &timings_size); + + if(!success || timings_size > MAX_TIMINGS_AMOUNT) { + return false; + } + + uint32_t* timings = malloc(sizeof(uint32_t) * timings_size); + success = flipper_format_read_uint32(ff, "data", timings, timings_size); + + if(success) { + infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle); + } + + free(timings); + return success; +} + +InfraredSignal* infrared_signal_alloc() { + InfraredSignal* signal = malloc(sizeof(InfraredSignal)); + + signal->is_raw = false; + signal->payload.message.protocol = InfraredProtocolUnknown; + + return signal; +} + +void infrared_signal_free(InfraredSignal* signal) { + infrared_signal_clear_timings(signal); + free(signal); +} + +bool infrared_signal_is_raw(InfraredSignal* signal) { + return signal->is_raw; +} + +bool infrared_signal_is_valid(InfraredSignal* signal) { + return signal->is_raw ? infrared_signal_is_raw_valid(&signal->payload.raw) : + infrared_signal_is_message_valid(&signal->payload.message); +} + +void infrared_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other) { + if(other->is_raw) { + const InfraredRawSignal* raw = &other->payload.raw; + infrared_signal_set_raw_signal( + signal, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle); + } else { + const InfraredMessage* message = &other->payload.message; + infrared_signal_set_message(signal, message); + } +} + +void infrared_signal_set_raw_signal( + InfraredSignal* signal, + const uint32_t* timings, + size_t timings_size, + uint32_t frequency, + float duty_cycle) { + infrared_signal_clear_timings(signal); + + signal->is_raw = true; + + signal->payload.raw.timings_size = timings_size; + signal->payload.raw.frequency = frequency; + signal->payload.raw.duty_cycle = duty_cycle; + + signal->payload.raw.timings = malloc(timings_size * sizeof(uint32_t)); + memcpy(signal->payload.raw.timings, timings, timings_size * sizeof(uint32_t)); +} + +InfraredRawSignal* infrared_signal_get_raw_signal(InfraredSignal* signal) { + furi_assert(signal->is_raw); + return &signal->payload.raw; +} + +void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* message) { + infrared_signal_clear_timings(signal); + + signal->is_raw = false; + signal->payload.message = *message; +} + +InfraredMessage* infrared_signal_get_message(InfraredSignal* signal) { + furi_assert(!signal->is_raw); + return &signal->payload.message; +} + +bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name) { + if(!flipper_format_write_comment_cstr(ff, "") || + !flipper_format_write_string_cstr(ff, "name", name)) { + return false; + } else if(signal->is_raw) { + return infrared_signal_save_raw(&signal->payload.raw, ff); + } else { + return infrared_signal_save_message(&signal->payload.message, ff); + } +} + +bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name) { + string_t buf; + string_init(buf); + bool success = false; + + do { + if(!flipper_format_read_string(ff, "name", buf)) break; + string_set(name, buf); + if(!flipper_format_read_string(ff, "type", buf)) break; + if(!string_cmp_str(buf, "raw")) { + success = infrared_signal_read_raw(signal, ff); + } else if(!string_cmp_str(buf, "parsed")) { + success = infrared_signal_read_message(signal, ff); + } else { + FURI_LOG_E(TAG, "Unknown type of signal (allowed - raw/parsed) "); + } + } while(0); + + string_clear(buf); + return success; +} + +void infrared_signal_transmit(InfraredSignal* signal) { + if(signal->is_raw) { + InfraredRawSignal* raw_signal = &signal->payload.raw; + infrared_send_raw_ext( + raw_signal->timings, + raw_signal->timings_size, + true, + raw_signal->frequency, + raw_signal->duty_cycle); + } else { + InfraredMessage* message = &signal->payload.message; + infrared_send(message, 1); + } +} diff --git a/applications/infrared/infrared_signal.h b/applications/infrared/infrared_signal.h new file mode 100644 index 00000000..2dbaa75f --- /dev/null +++ b/applications/infrared/infrared_signal.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +#include +#include + +typedef struct InfraredSignal InfraredSignal; + +typedef struct { + size_t timings_size; + uint32_t* timings; + uint32_t frequency; + float duty_cycle; +} InfraredRawSignal; + +InfraredSignal* infrared_signal_alloc(); +void infrared_signal_free(InfraredSignal* signal); + +bool infrared_signal_is_raw(InfraredSignal* signal); +bool infrared_signal_is_valid(InfraredSignal* signal); + +void infrared_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other); + +void infrared_signal_set_raw_signal( + InfraredSignal* signal, + const uint32_t* timings, + size_t timings_size, + uint32_t frequency, + float duty_cycle); +InfraredRawSignal* infrared_signal_get_raw_signal(InfraredSignal* signal); + +void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* message); +InfraredMessage* infrared_signal_get_message(InfraredSignal* signal); + +bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name); +bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, string_t name); + +void infrared_signal_transmit(InfraredSignal* signal); diff --git a/applications/infrared/scene/infrared_app_scene.h b/applications/infrared/scene/infrared_app_scene.h deleted file mode 100644 index 9c2e20e9..00000000 --- a/applications/infrared/scene/infrared_app_scene.h +++ /dev/null @@ -1,305 +0,0 @@ -/** - * @file infrared_app_scene.h - * Infrared: Application scenes - */ -#pragma once -#include "../infrared_app_event.h" -#include -#include "infrared.h" -#include -#include -#include "../infrared_app_brute_force.h" - -/** Anonymous class */ -class InfraredApp; - -/** Base Scene class */ -class InfraredAppScene { -public: - /** Called when enter scene */ - virtual void on_enter(InfraredApp* app) = 0; - /** Events handler callback */ - virtual bool on_event(InfraredApp* app, InfraredAppEvent* event) = 0; - /** Called when exit scene */ - virtual void on_exit(InfraredApp* app) = 0; - /** Virtual destructor of base class */ - virtual ~InfraredAppScene(){}; - -private: -}; - -/** Start scene - * Main Infrared application menu - */ -class InfraredAppSceneStart : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** Save previously selected submenu index - * to highlight it when get back */ - uint32_t submenu_item_selected = 0; -}; - -/** Universal menu scene - * Scene to select universal remote - */ -class InfraredAppSceneUniversal : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** Save previously selected submenu index - * to highlight it when get back */ - uint32_t submenu_item_selected = 0; -}; - -/** Learn new signal scene - * On this scene catching new IR signal performed. - */ -class InfraredAppSceneLearn : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -/** New signal learn succeeded scene - */ -class InfraredAppSceneLearnSuccess : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - bool button_pressed = false; -}; - -/** Scene to enter name for new button in remote - */ -class InfraredAppSceneLearnEnterName : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -/** Scene where signal is learnt - */ -class InfraredAppSceneLearnDone : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -/** Remote interface scene - * On this scene you can send IR signals from selected remote - */ -class InfraredAppSceneRemote : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** container of button names in current remote. */ - std::vector buttons_names; - /** Save previously selected index - * to highlight it when get back */ - uint32_t buttonmenu_item_selected = 0; - /** state flag to show button is pressed. - * As long as send-signal button pressed no other button - * events are handled. */ - bool button_pressed = false; -}; - -/** List of remotes scene - * Every remote is a file, located on internal/external storage. - * Every file has same format, and same extension. - * Files are parsed as you enter 'Remote scene' and showed - * as a buttons. - */ -class InfraredAppSceneRemoteList : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** Save previously selected index - * to highlight it when get back */ - uint32_t submenu_item_selected = 0; - /** Remote names to show them in submenu */ - std::vector remote_names; -}; - -class InfraredAppSceneAskBack : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -class InfraredAppSceneEdit : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** Save previously selected index - * to highlight it when get back */ - uint32_t submenu_item_selected = 0; -}; - -class InfraredAppSceneEditKeySelect : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - -private: - /** Button names to show them in submenu */ - std::vector buttons_names; -}; - -class InfraredAppSceneEditRename : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -class InfraredAppSceneEditDelete : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -class InfraredAppSceneEditRenameDone : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -class InfraredAppSceneEditDeleteDone : public InfraredAppScene { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; -}; - -class InfraredAppSceneUniversalCommon : public InfraredAppScene { - /** Brute force started flag */ - bool brute_force_started = false; - -protected: - /** Events handler callback */ - bool on_event(InfraredApp* app, InfraredAppEvent* event) final; - /** Called when exit scene */ - void on_exit(InfraredApp* app) final; - - /** Show popup window - * - * @param app - application instance - */ - void show_popup(InfraredApp* app, int record_amount); - - /** Hide popup window - * - * @param app - application instance - */ - void hide_popup(InfraredApp* app); - - /** Propagate progress in popup window - * - * @param app - application instance - */ - bool progress_popup(InfraredApp* app); - - /** Item selected callback - * - * @param context - context - * @param index - selected item index - */ - static void infrared_app_item_callback(void* context, uint32_t index); - - /** Brute Force instance */ - InfraredAppBruteForce brute_force; - - /** Constructor */ - InfraredAppSceneUniversalCommon(const char* filename) - : brute_force(filename) { - } - - /** Destructor */ - ~InfraredAppSceneUniversalCommon() { - } -}; - -class InfraredAppSceneUniversalTV : public InfraredAppSceneUniversalCommon { -public: - /** Called when enter scene */ - void on_enter(InfraredApp* app) final; - - /** Constructor - * Specifies path to brute force db library */ - InfraredAppSceneUniversalTV() - : InfraredAppSceneUniversalCommon("/ext/infrared/assets/tv.ir") { - } - - /** Destructor */ - ~InfraredAppSceneUniversalTV() { - } -}; diff --git a/applications/infrared/scene/infrared_app_scene_ask_back.cpp b/applications/infrared/scene/infrared_app_scene_ask_back.cpp deleted file mode 100644 index 65d7ca57..00000000 --- a/applications/infrared/scene/infrared_app_scene_ask_back.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "../infrared_app.h" -#include "gui/modules/dialog_ex.h" -#include "infrared.h" -#include "infrared/scene/infrared_app_scene.h" -#include - -static void dialog_result_callback(DialogExResult result, void* context) { - auto app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::DialogExSelected; - event.payload.dialog_ex_result = result; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneAskBack::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - if(app->get_learn_new_remote()) { - dialog_ex_set_header(dialog_ex, "Exit to Infrared menu?", 64, 0, AlignCenter, AlignTop); - } else { - dialog_ex_set_header(dialog_ex, "Exit to remote menu?", 64, 0, AlignCenter, AlignTop); - } - - dialog_ex_set_text( - dialog_ex, "All unsaved data\nwill be lost", 64, 31, AlignCenter, AlignCenter); - dialog_ex_set_icon(dialog_ex, 0, 0, NULL); - dialog_ex_set_left_button_text(dialog_ex, "Exit"); - dialog_ex_set_center_button_text(dialog_ex, nullptr); - dialog_ex_set_right_button_text(dialog_ex, "Stay"); - dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); - dialog_ex_set_context(dialog_ex, app); - - view_manager->switch_to(InfraredAppViewManager::ViewId::DialogEx); -} - -bool InfraredAppSceneAskBack::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::DialogExSelected) { - switch(event->payload.dialog_ex_result) { - case DialogExResultLeft: - consumed = true; - if(app->get_learn_new_remote()) { - app->search_and_switch_to_previous_scene({InfraredApp::Scene::Start}); - } else { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::Edit, InfraredApp::Scene::Remote}); - } - break; - case DialogExResultCenter: - furi_assert(0); - break; - case DialogExResultRight: - app->switch_to_previous_scene(); - consumed = true; - break; - default: - break; - } - } - - if(event->type == InfraredAppEvent::Type::Back) { - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneAskBack::on_exit(InfraredApp*) { -} diff --git a/applications/infrared/scene/infrared_app_scene_edit.cpp b/applications/infrared/scene/infrared_app_scene_edit.cpp deleted file mode 100644 index 5a2ae72f..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include "../infrared_app.h" -#include "gui/modules/submenu.h" - -typedef enum { - SubmenuIndexAddKey, - SubmenuIndexRenameKey, - SubmenuIndexDeleteKey, - SubmenuIndexRenameRemote, - SubmenuIndexDeleteRemote, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::MenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneEdit::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "Add Button", SubmenuIndexAddKey, submenu_callback, app); - submenu_add_item(submenu, "Rename Button", SubmenuIndexRenameKey, submenu_callback, app); - submenu_add_item(submenu, "Delete Button", SubmenuIndexDeleteKey, submenu_callback, app); - submenu_add_item(submenu, "Rename Remote", SubmenuIndexRenameRemote, submenu_callback, app); - submenu_add_item(submenu, "Delete Remote", SubmenuIndexDeleteRemote, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - submenu_item_selected = 0; - - view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu); -} - -bool InfraredAppSceneEdit::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::MenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexAddKey: - app->set_learn_new_remote(false); - app->switch_to_next_scene(InfraredApp::Scene::Learn); - break; - case SubmenuIndexRenameKey: - app->set_edit_action(InfraredApp::EditAction::Rename); - app->set_edit_element(InfraredApp::EditElement::Button); - app->switch_to_next_scene(InfraredApp::Scene::EditKeySelect); - break; - case SubmenuIndexDeleteKey: - app->set_edit_action(InfraredApp::EditAction::Delete); - app->set_edit_element(InfraredApp::EditElement::Button); - app->switch_to_next_scene(InfraredApp::Scene::EditKeySelect); - break; - case SubmenuIndexRenameRemote: - app->set_edit_action(InfraredApp::EditAction::Rename); - app->set_edit_element(InfraredApp::EditElement::Remote); - app->switch_to_next_scene(InfraredApp::Scene::EditRename); - break; - case SubmenuIndexDeleteRemote: - app->set_edit_action(InfraredApp::EditAction::Delete); - app->set_edit_element(InfraredApp::EditElement::Remote); - app->switch_to_next_scene(InfraredApp::Scene::EditDelete); - break; - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneEdit::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp b/applications/infrared/scene/infrared_app_scene_edit_delete.cpp deleted file mode 100644 index e17cfee0..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit_delete.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "../infrared_app.h" -#include "infrared.h" -#include "infrared/scene/infrared_app_scene.h" -#include - -static void dialog_result_callback(DialogExResult result, void* context) { - auto app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::DialogExSelected; - event.payload.dialog_ex_result = result; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneEditDelete::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - auto remote_manager = app->get_remote_manager(); - - if(app->get_edit_element() == InfraredApp::EditElement::Button) { - auto signal = remote_manager->get_button_data(app->get_current_button()); - dialog_ex_set_header(dialog_ex, "Delete button?", 64, 0, AlignCenter, AlignTop); - if(!signal.is_raw()) { - auto message = &signal.get_message(); - app->set_text_store( - 0, - "%s\n%s\nA=0x%0*lX C=0x%0*lX", - remote_manager->get_button_name(app->get_current_button()).c_str(), - infrared_get_protocol_name(message->protocol), - ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), - message->address, - ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), - message->command); - } else { - app->set_text_store( - 0, - "%s\nRAW\n%ld samples", - remote_manager->get_button_name(app->get_current_button()).c_str(), - signal.get_raw_signal().timings_cnt); - } - } else { - dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 0, AlignCenter, AlignTop); - app->set_text_store( - 0, - "%s\n with %lu buttons", - remote_manager->get_remote_name().c_str(), - remote_manager->get_number_of_buttons()); - } - - dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 31, AlignCenter, AlignCenter); - dialog_ex_set_icon(dialog_ex, 0, 0, NULL); - dialog_ex_set_left_button_text(dialog_ex, "Cancel"); - dialog_ex_set_right_button_text(dialog_ex, "Delete"); - dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); - dialog_ex_set_context(dialog_ex, app); - - view_manager->switch_to(InfraredAppViewManager::ViewId::DialogEx); -} - -bool InfraredAppSceneEditDelete::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::DialogExSelected) { - switch(event->payload.dialog_ex_result) { - case DialogExResultLeft: - app->switch_to_previous_scene(); - break; - case DialogExResultCenter: - furi_assert(0); - break; - case DialogExResultRight: { - auto remote_manager = app->get_remote_manager(); - bool result = false; - if(app->get_edit_element() == InfraredApp::EditElement::Remote) { - result = remote_manager->delete_remote(); - } else { - result = remote_manager->delete_button(app->get_current_button()); - app->set_current_button(InfraredApp::ButtonNA); - } - - if(!result) { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::RemoteList, InfraredApp::Scene::Start}); - } else { - app->switch_to_next_scene(InfraredApp::Scene::EditDeleteDone); - } - break; - } - default: - break; - } - } - - return consumed; -} - -void InfraredAppSceneEditDelete::on_exit(InfraredApp*) { -} diff --git a/applications/infrared/scene/infrared_app_scene_edit_delete_done.cpp b/applications/infrared/scene/infrared_app_scene_edit_delete_done.cpp deleted file mode 100644 index 3f9800e1..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit_delete_done.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "../infrared_app.h" - -void InfraredAppSceneEditDeleteDone::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); - popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); - - popup_set_callback(popup, InfraredApp::popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(InfraredAppViewManager::ViewId::Popup); -} - -bool InfraredAppSceneEditDeleteDone::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::PopupTimer) { - if(app->get_edit_element() == InfraredApp::EditElement::Remote) { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::Start, InfraredApp::Scene::RemoteList}); - } else { - app->search_and_switch_to_previous_scene({InfraredApp::Scene::Remote}); - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneEditDeleteDone::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - popup_set_header(popup, nullptr, 0, 0, AlignLeft, AlignTop); -} diff --git a/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp b/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp deleted file mode 100644 index 49142c21..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit_key_select.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "../infrared_app.h" -#include "gui/modules/submenu.h" - -static void submenu_callback(void* context, uint32_t index) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::MenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneEditKeySelect::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - int item_number = 0; - - const char* header = app->get_edit_action() == InfraredApp::EditAction::Rename ? - "Rename Button:" : - "Delete Button:"; - submenu_set_header(submenu, header); - - auto remote_manager = app->get_remote_manager(); - buttons_names = remote_manager->get_button_list(); - for(const auto& it : buttons_names) { - submenu_add_item(submenu, it.c_str(), item_number++, submenu_callback, app); - } - if((item_number > 0) && (app->get_current_button() != InfraredApp::ButtonNA)) { - submenu_set_selected_item(submenu, app->get_current_button()); - app->set_current_button(InfraredApp::ButtonNA); - } - - view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu); -} - -bool InfraredAppSceneEditKeySelect::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::MenuSelected) { - app->set_current_button(event->payload.menu_index); - consumed = true; - if(app->get_edit_action() == InfraredApp::EditAction::Rename) { - app->switch_to_next_scene(InfraredApp::Scene::EditRename); - } else { - app->switch_to_next_scene(InfraredApp::Scene::EditDelete); - } - } - - return consumed; -} - -void InfraredAppSceneEditKeySelect::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp b/applications/infrared/scene/infrared_app_scene_edit_rename.cpp deleted file mode 100644 index 761da49f..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "../infrared_app.h" -#include "m-string.h" -#include "toolbox/path.h" - -void InfraredAppSceneEditRename::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - TextInput* text_input = view_manager->get_text_input(); - size_t enter_name_length = 0; - - auto remote_manager = app->get_remote_manager(); - if(app->get_edit_element() == InfraredApp::EditElement::Button) { - furi_assert(app->get_current_button() != InfraredApp::ButtonNA); - auto button_name = remote_manager->get_button_name(app->get_current_button()); - char* buffer_str = app->get_text_store(0); - size_t max_len = InfraredAppRemoteManager::max_button_name_length; - strncpy(buffer_str, button_name.c_str(), max_len); - buffer_str[max_len + 1] = 0; - enter_name_length = max_len; - text_input_set_header_text(text_input, "Name the button"); - } else { - auto remote_name = remote_manager->get_remote_name(); - strncpy(app->get_text_store(0), remote_name.c_str(), app->get_text_store_size()); - enter_name_length = InfraredAppRemoteManager::max_remote_name_length; - text_input_set_header_text(text_input, "Name the remote"); - - string_t folder_path; - string_init(folder_path); - - if(string_end_with_str_p(app->file_path, InfraredApp::infrared_extension)) { - path_extract_dirname(string_get_cstr(app->file_path), folder_path); - } - - ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - string_get_cstr(folder_path), app->infrared_extension, remote_name.c_str()); - text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); - - string_clear(folder_path); - } - - text_input_set_result_callback( - text_input, - InfraredApp::text_input_callback, - app, - app->get_text_store(0), - enter_name_length, - false); - - view_manager->switch_to(InfraredAppViewManager::ViewId::TextInput); -} - -bool InfraredAppSceneEditRename::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::TextEditDone) { - auto remote_manager = app->get_remote_manager(); - bool result = false; - if(app->get_edit_element() == InfraredApp::EditElement::Button) { - result = - remote_manager->rename_button(app->get_current_button(), app->get_text_store(0)); - app->set_current_button(InfraredApp::ButtonNA); - } else { - result = remote_manager->rename_remote(app->get_text_store(0)); - } - if(!result) { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::Start, InfraredApp::Scene::RemoteList}); - } else { - app->switch_to_next_scene_without_saving(InfraredApp::Scene::EditRenameDone); - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneEditRename::on_exit(InfraredApp* app) { - TextInput* text_input = app->get_view_manager()->get_text_input(); - - void* validator_context = text_input_get_validator_callback_context(text_input); - text_input_set_validator(text_input, NULL, NULL); - - if(validator_context != NULL) validator_is_file_free((ValidatorIsFile*)validator_context); -} diff --git a/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp b/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp deleted file mode 100644 index 803481f6..00000000 --- a/applications/infrared/scene/infrared_app_scene_edit_rename_done.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "../infrared_app.h" - -void InfraredAppSceneEditRenameDone::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); - - popup_set_callback(popup, InfraredApp::popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(InfraredAppViewManager::ViewId::Popup); -} - -bool InfraredAppSceneEditRenameDone::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::PopupTimer) { - app->switch_to_next_scene(InfraredApp::Scene::Remote); - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneEditRenameDone::on_exit(InfraredApp*) { -} diff --git a/applications/infrared/scene/infrared_app_scene_learn.cpp b/applications/infrared/scene/infrared_app_scene_learn.cpp deleted file mode 100644 index 3ad152cf..00000000 --- a/applications/infrared/scene/infrared_app_scene_learn.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "../infrared_app.h" -#include "../infrared_app_event.h" -#include "infrared.h" -#include - -static void signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { - furi_assert(context); - furi_assert(received_signal); - - InfraredApp* app = static_cast(context); - - if(infrared_worker_signal_is_decoded(received_signal)) { - InfraredAppSignal signal(infrared_worker_get_decoded_signal(received_signal)); - app->set_received_signal(signal); - } else { - const uint32_t* timings; - size_t timings_cnt; - infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt); - InfraredAppSignal signal( - timings, timings_cnt, INFRARED_COMMON_CARRIER_FREQUENCY, INFRARED_COMMON_DUTY_CYCLE); - app->set_received_signal(signal); - } - - infrared_worker_rx_set_received_signal_callback(app->get_infrared_worker(), NULL, NULL); - InfraredAppEvent event; - event.type = InfraredAppEvent::Type::InfraredMessageReceived; - auto view_manager = app->get_view_manager(); - view_manager->send_event(&event); -} - -void InfraredAppSceneLearn::on_enter(InfraredApp* app) { - auto view_manager = app->get_view_manager(); - auto popup = view_manager->get_popup(); - - auto worker = app->get_infrared_worker(); - infrared_worker_rx_set_received_signal_callback(worker, signal_received_callback, app); - infrared_worker_rx_start(worker); - - popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31); - popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter); - popup_set_text( - popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter); - popup_set_callback(popup, NULL); - - view_manager->switch_to(InfraredAppViewManager::ViewId::Popup); -} - -bool InfraredAppSceneLearn::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - switch(event->type) { - case InfraredAppEvent::Type::Tick: - consumed = true; - app->notify_blink_read(); - break; - case InfraredAppEvent::Type::InfraredMessageReceived: - app->notify_success(); - app->switch_to_next_scene_without_saving(InfraredApp::Scene::LearnSuccess); - break; - case InfraredAppEvent::Type::Back: - consumed = true; - app->switch_to_previous_scene(); - break; - default: - furi_assert(0); - } - - return consumed; -} - -void InfraredAppSceneLearn::on_exit(InfraredApp* app) { - infrared_worker_rx_stop(app->get_infrared_worker()); - auto view_manager = app->get_view_manager(); - auto popup = view_manager->get_popup(); - popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignCenter); -} diff --git a/applications/infrared/scene/infrared_app_scene_learn_done.cpp b/applications/infrared/scene/infrared_app_scene_learn_done.cpp deleted file mode 100644 index 6ee13b43..00000000 --- a/applications/infrared/scene/infrared_app_scene_learn_done.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "../infrared_app.h" -#include - -void InfraredAppSceneLearnDone::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - DOLPHIN_DEED(DolphinDeedIrSave); - - if(app->get_learn_new_remote()) { - popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop); - } else { - popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); - } - - popup_set_callback(popup, InfraredApp::popup_callback); - popup_set_context(popup, app); - popup_set_timeout(popup, 1500); - popup_enable_timeout(popup); - - view_manager->switch_to(InfraredAppViewManager::ViewId::Popup); -} - -bool InfraredAppSceneLearnDone::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::PopupTimer) { - app->switch_to_next_scene(InfraredApp::Scene::Remote); - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneLearnDone::on_exit(InfraredApp* app) { - app->set_learn_new_remote(false); - InfraredAppViewManager* view_manager = app->get_view_manager(); - Popup* popup = view_manager->get_popup(); - popup_set_header(popup, nullptr, 0, 0, AlignLeft, AlignTop); -} diff --git a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp b/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp deleted file mode 100644 index 7d15a7c5..00000000 --- a/applications/infrared/scene/infrared_app_scene_learn_enter_name.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "../infrared_app.h" -#include "gui/modules/text_input.h" - -void InfraredAppSceneLearnEnterName::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - TextInput* text_input = view_manager->get_text_input(); - - auto signal = app->get_received_signal(); - - if(!signal.is_raw()) { - auto message = &signal.get_message(); - app->set_text_store( - 0, - "%.4s_%0*lX", - infrared_get_protocol_name(message->protocol), - ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), - message->command); - } else { - auto raw_signal = signal.get_raw_signal(); - app->set_text_store(0, "RAW_%d", raw_signal.timings_cnt); - } - - text_input_set_header_text(text_input, "Name the button"); - text_input_set_result_callback( - text_input, - InfraredApp::text_input_callback, - app, - app->get_text_store(0), - InfraredAppRemoteManager::max_button_name_length, - true); - - view_manager->switch_to(InfraredAppViewManager::ViewId::TextInput); -} - -bool InfraredAppSceneLearnEnterName::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::TextEditDone) { - auto remote_manager = app->get_remote_manager(); - bool result = false; - if(app->get_learn_new_remote()) { - result = remote_manager->add_remote_with_button( - app->get_text_store(0), app->get_received_signal()); - } else { - result = - remote_manager->add_button(app->get_text_store(0), app->get_received_signal()); - } - - if(!result) { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::Start, InfraredApp::Scene::RemoteList}); - } else { - app->switch_to_next_scene_without_saving(InfraredApp::Scene::LearnDone); - } - } - return consumed; -} - -void InfraredAppSceneLearnEnterName::on_exit(InfraredApp*) { -} diff --git a/applications/infrared/scene/infrared_app_scene_learn_success.cpp b/applications/infrared/scene/infrared_app_scene_learn_success.cpp deleted file mode 100644 index a7f7c4cd..00000000 --- a/applications/infrared/scene/infrared_app_scene_learn_success.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include -#include -#include - -#include "../infrared_app.h" -#include "infrared.h" - -static void dialog_result_callback(DialogExResult result, void* context) { - auto app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::DialogExSelected; - event.payload.dialog_ex_result = result; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneLearnSuccess::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - - DOLPHIN_DEED(DolphinDeedIrLearnSuccess); - app->notify_green_on(); - - infrared_worker_tx_set_get_signal_callback( - app->get_infrared_worker(), infrared_worker_tx_get_signal_steady_callback, app); - infrared_worker_tx_set_signal_sent_callback( - app->get_infrared_worker(), InfraredApp::signal_sent_callback, app); - - auto signal = app->get_received_signal(); - - if(!signal.is_raw()) { - auto message = &signal.get_message(); - uint8_t adr_digits = - ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4); - uint8_t cmd_digits = - ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4); - uint8_t max_digits = MAX(adr_digits, cmd_digits); - max_digits = MIN(max_digits, 7); - size_t label_x_offset = 63 + (7 - max_digits) * 3; - - app->set_text_store(0, "%s", infrared_get_protocol_name(message->protocol)); - app->set_text_store( - 1, - "A: 0x%0*lX\nC: 0x%0*lX\n", - adr_digits, - message->address, - cmd_digits, - message->command); - - dialog_ex_set_header(dialog_ex, app->get_text_store(0), 95, 7, AlignCenter, AlignCenter); - dialog_ex_set_text( - dialog_ex, app->get_text_store(1), label_x_offset, 34, AlignLeft, AlignCenter); - } else { - dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter); - app->set_text_store(0, "%d samples", signal.get_raw_signal().timings_cnt); - dialog_ex_set_text(dialog_ex, app->get_text_store(0), 75, 23, AlignLeft, AlignTop); - } - - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "Save"); - dialog_ex_set_center_button_text(dialog_ex, "Send"); - dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); - dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); - dialog_ex_set_context(dialog_ex, app); - dialog_ex_enable_extended_events(dialog_ex); - - view_manager->switch_to(InfraredAppViewManager::ViewId::DialogEx); -} - -bool InfraredAppSceneLearnSuccess::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - if(event->type == InfraredAppEvent::Type::Tick) { - /* Send event every tick to suppress any switching off green light */ - if(!button_pressed) { - app->notify_green_on(); - } - } - - if(event->type == InfraredAppEvent::Type::DialogExSelected) { - switch(event->payload.dialog_ex_result) { - case DialogExResultLeft: - consumed = true; - if(!button_pressed) { - app->switch_to_next_scene_without_saving(InfraredApp::Scene::Learn); - } - break; - case DialogExResultRight: { - consumed = true; - if(!button_pressed) { - app->switch_to_next_scene(InfraredApp::Scene::LearnEnterName); - } - break; - } - case DialogExPressCenter: - if(!button_pressed) { - button_pressed = true; - - auto signal = app->get_received_signal(); - if(signal.is_raw()) { - infrared_worker_set_raw_signal( - app->get_infrared_worker(), - signal.get_raw_signal().timings, - signal.get_raw_signal().timings_cnt); - } else { - infrared_worker_set_decoded_signal( - app->get_infrared_worker(), &signal.get_message()); - } - - infrared_worker_tx_start(app->get_infrared_worker()); - } - break; - case DialogExReleaseCenter: - if(button_pressed) { - button_pressed = false; - infrared_worker_tx_stop(app->get_infrared_worker()); - app->notify_green_off(); - } - break; - default: - break; - } - } - - if(event->type == InfraredAppEvent::Type::Back) { - if(!button_pressed) { - app->switch_to_next_scene(InfraredApp::Scene::AskBack); - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneLearnSuccess::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - DialogEx* dialog_ex = view_manager->get_dialog_ex(); - dialog_ex_reset(dialog_ex); - app->notify_green_off(); - infrared_worker_tx_set_get_signal_callback(app->get_infrared_worker(), nullptr, nullptr); - infrared_worker_tx_set_signal_sent_callback(app->get_infrared_worker(), nullptr, nullptr); -} diff --git a/applications/infrared/scene/infrared_app_scene_remote.cpp b/applications/infrared/scene/infrared_app_scene_remote.cpp deleted file mode 100644 index ac87b581..00000000 --- a/applications/infrared/scene/infrared_app_scene_remote.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include "../infrared_app.h" -#include "../infrared_app_view_manager.h" - -typedef enum { - ButtonIndexPlus = -2, - ButtonIndexEdit = -1, - ButtonIndexNA = 0, -} ButtonIndex; - -static void button_menu_callback(void* context, int32_t index, InputType type) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - if(type == InputTypePress) { - event.type = InfraredAppEvent::Type::MenuSelectedPress; - } else if(type == InputTypeRelease) { - event.type = InfraredAppEvent::Type::MenuSelectedRelease; - } else if(type == InputTypeShort) { - event.type = InfraredAppEvent::Type::MenuSelected; - } else { - furi_assert(0); - } - - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneRemote::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - ButtonMenu* button_menu = view_manager->get_button_menu(); - auto remote_manager = app->get_remote_manager(); - int i = 0; - button_pressed = false; - - infrared_worker_tx_set_get_signal_callback( - app->get_infrared_worker(), infrared_worker_tx_get_signal_steady_callback, app); - infrared_worker_tx_set_signal_sent_callback( - app->get_infrared_worker(), InfraredApp::signal_sent_callback, app); - buttons_names = remote_manager->get_button_list(); - - i = 0; - for(auto& name : buttons_names) { - button_menu_add_item( - button_menu, name.c_str(), i++, button_menu_callback, ButtonMenuItemTypeCommon, app); - } - - button_menu_add_item( - button_menu, "+", ButtonIndexPlus, button_menu_callback, ButtonMenuItemTypeControl, app); - button_menu_add_item( - button_menu, "Edit", ButtonIndexEdit, button_menu_callback, ButtonMenuItemTypeControl, app); - - app->set_text_store(0, "%s", remote_manager->get_remote_name().c_str()); - button_menu_set_header(button_menu, app->get_text_store(0)); - if(buttonmenu_item_selected != ButtonIndexNA) { - button_menu_set_selected_item(button_menu, buttonmenu_item_selected); - buttonmenu_item_selected = ButtonIndexNA; - } - view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu); -} - -bool InfraredAppSceneRemote::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = true; - - if((event->type == InfraredAppEvent::Type::MenuSelected) || - (event->type == InfraredAppEvent::Type::MenuSelectedPress) || - (event->type == InfraredAppEvent::Type::MenuSelectedRelease)) { - switch(event->payload.menu_index) { - case ButtonIndexPlus: - furi_assert(event->type == InfraredAppEvent::Type::MenuSelected); - buttonmenu_item_selected = event->payload.menu_index; - app->set_learn_new_remote(false); - app->switch_to_next_scene(InfraredApp::Scene::Learn); - break; - case ButtonIndexEdit: - furi_assert(event->type == InfraredAppEvent::Type::MenuSelected); - buttonmenu_item_selected = event->payload.menu_index; - app->switch_to_next_scene(InfraredApp::Scene::Edit); - break; - default: - furi_assert(event->type != InfraredAppEvent::Type::MenuSelected); - bool pressed = (event->type == InfraredAppEvent::Type::MenuSelectedPress); - - if(pressed && !button_pressed) { - button_pressed = true; - - auto button_signal = - app->get_remote_manager()->get_button_data(event->payload.menu_index); - if(button_signal.is_raw()) { - infrared_worker_set_raw_signal( - app->get_infrared_worker(), - button_signal.get_raw_signal().timings, - button_signal.get_raw_signal().timings_cnt); - } else { - infrared_worker_set_decoded_signal( - app->get_infrared_worker(), &button_signal.get_message()); - } - - DOLPHIN_DEED(DolphinDeedIrSend); - infrared_worker_tx_start(app->get_infrared_worker()); - } else if(!pressed && button_pressed) { - button_pressed = false; - infrared_worker_tx_stop(app->get_infrared_worker()); - app->notify_green_off(); - } - break; - } - } else if(event->type == InfraredAppEvent::Type::Back) { - if(!button_pressed) { - app->search_and_switch_to_previous_scene( - {InfraredApp::Scene::Start, InfraredApp::Scene::RemoteList}); - } - } else { - consumed = false; - } - - return consumed; -} - -void InfraredAppSceneRemote::on_exit(InfraredApp* app) { - infrared_worker_tx_set_get_signal_callback(app->get_infrared_worker(), nullptr, nullptr); - infrared_worker_tx_set_signal_sent_callback(app->get_infrared_worker(), nullptr, nullptr); - InfraredAppViewManager* view_manager = app->get_view_manager(); - ButtonMenu* button_menu = view_manager->get_button_menu(); - - button_menu_reset(button_menu); -} diff --git a/applications/infrared/scene/infrared_app_scene_remote_list.cpp b/applications/infrared/scene/infrared_app_scene_remote_list.cpp deleted file mode 100644 index c72acb6e..00000000 --- a/applications/infrared/scene/infrared_app_scene_remote_list.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "../infrared_app.h" -#include "assets_icons.h" -#include "infrared/infrared_app_event.h" -#include - -void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) { - furi_assert(app); - - bool result = false; - bool file_select_result; - auto remote_manager = app->get_remote_manager(); - DialogsApp* dialogs = app->get_dialogs(); - - InfraredAppViewManager* view_manager = app->get_view_manager(); - ButtonMenu* button_menu = view_manager->get_button_menu(); - button_menu_reset(button_menu); - view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu); - - file_select_result = dialog_file_browser_show( - dialogs, - app->file_path, - app->file_path, - InfraredApp::infrared_extension, - true, - &I_ir_10px, - true); - - if(file_select_result) { - if(remote_manager->load(app->file_path)) { - app->switch_to_next_scene(InfraredApp::Scene::Remote); - result = true; - } - } - - if(!result) { - app->switch_to_previous_scene(); - } -} - -bool InfraredAppSceneRemoteList::on_event(InfraredApp*, InfraredAppEvent*) { - return false; -} - -void InfraredAppSceneRemoteList::on_exit(InfraredApp*) { -} diff --git a/applications/infrared/scene/infrared_app_scene_start.cpp b/applications/infrared/scene/infrared_app_scene_start.cpp deleted file mode 100644 index 5efdce7a..00000000 --- a/applications/infrared/scene/infrared_app_scene_start.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "../infrared_app.h" - -typedef enum { - SubmenuIndexUniversalLibrary, - SubmenuIndexLearnNewRemote, - SubmenuIndexSavedRemotes, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::MenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneStart::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item( - submenu, "Universal Library", SubmenuIndexUniversalLibrary, submenu_callback, app); - submenu_add_item( - submenu, "Learn New Remote", SubmenuIndexLearnNewRemote, submenu_callback, app); - submenu_add_item(submenu, "Saved Remotes", SubmenuIndexSavedRemotes, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - - string_set_str(app->file_path, InfraredApp::infrared_directory); - submenu_item_selected = 0; - - view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu); -} - -bool InfraredAppSceneStart::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::MenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexUniversalLibrary: - app->switch_to_next_scene(InfraredApp::Scene::Universal); - break; - case SubmenuIndexLearnNewRemote: - app->set_learn_new_remote(true); - app->switch_to_next_scene(InfraredApp::Scene::Learn); - break; - case SubmenuIndexSavedRemotes: - app->switch_to_next_scene(InfraredApp::Scene::RemoteList); - break; - default: - furi_assert(0); - break; - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneStart::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - app->get_remote_manager()->reset_remote(); - submenu_reset(submenu); -} diff --git a/applications/infrared/scene/infrared_app_scene_universal.cpp b/applications/infrared/scene/infrared_app_scene_universal.cpp deleted file mode 100644 index 57b5653a..00000000 --- a/applications/infrared/scene/infrared_app_scene_universal.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "../infrared_app.h" - -typedef enum { - SubmenuIndexUniversalTV, - SubmenuIndexUniversalAudio, - SubmenuIndexUniversalAirConditioner, -} SubmenuIndex; - -static void submenu_callback(void* context, uint32_t index) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::MenuSelected; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -void InfraredAppSceneUniversal::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_add_item(submenu, "TVs", SubmenuIndexUniversalTV, submenu_callback, app); - submenu_set_selected_item(submenu, submenu_item_selected); - submenu_item_selected = 0; - - view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu); -} - -bool InfraredAppSceneUniversal::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(event->type == InfraredAppEvent::Type::MenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuIndexUniversalTV: - app->switch_to_next_scene(InfraredApp::Scene::UniversalTV); - break; - case SubmenuIndexUniversalAudio: - // app->switch_to_next_scene(InfraredApp::Scene::UniversalAudio); - break; - case SubmenuIndexUniversalAirConditioner: - // app->switch_to_next_scene(InfraredApp::Scene::UniversalAirConditioner); - break; - } - consumed = true; - } - - return consumed; -} - -void InfraredAppSceneUniversal::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - Submenu* submenu = view_manager->get_submenu(); - - submenu_reset(submenu); -} diff --git a/applications/infrared/scene/infrared_app_scene_universal_common.cpp b/applications/infrared/scene/infrared_app_scene_universal_common.cpp deleted file mode 100644 index 9e7a18f4..00000000 --- a/applications/infrared/scene/infrared_app_scene_universal_common.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include -#include -#include -#include - -#include "../infrared_app.h" -#include "infrared/infrared_app_event.h" -#include "infrared/infrared_app_view_manager.h" -#include "infrared/scene/infrared_app_scene.h" -#include "../view/infrared_progress_view.h" - -void InfraredAppSceneUniversalCommon::infrared_app_item_callback(void* context, uint32_t index) { - InfraredApp* app = static_cast(context); - InfraredAppEvent event; - - event.type = InfraredAppEvent::Type::ButtonPanelPressed; - event.payload.menu_index = index; - - app->get_view_manager()->send_event(&event); -} - -static void infrared_progress_back_callback(void* context) { - furi_assert(context); - auto app = static_cast(context); - - InfraredAppEvent infrared_event = { - .payload = {.dummy = 0}, - .type = InfraredAppEvent::Type::Back, - }; - app->get_view_manager()->clear_events(); - app->get_view_manager()->send_event(&infrared_event); -} - -void InfraredAppSceneUniversalCommon::hide_popup(InfraredApp* app) { - auto stack_view = app->get_view_manager()->get_universal_view_stack(); - auto progress_view = app->get_view_manager()->get_progress(); - view_stack_remove_view(stack_view, infrared_progress_view_get_view(progress_view)); -} - -void InfraredAppSceneUniversalCommon::show_popup(InfraredApp* app, int record_amount) { - auto stack_view = app->get_view_manager()->get_universal_view_stack(); - auto progress_view = app->get_view_manager()->get_progress(); - infrared_progress_view_set_progress_total(progress_view, record_amount); - infrared_progress_view_set_back_callback(progress_view, infrared_progress_back_callback, app); - view_stack_add_view(stack_view, infrared_progress_view_get_view(progress_view)); -} - -bool InfraredAppSceneUniversalCommon::progress_popup(InfraredApp* app) { - auto progress_view = app->get_view_manager()->get_progress(); - return infrared_progress_view_increase_progress(progress_view); -} - -bool InfraredAppSceneUniversalCommon::on_event(InfraredApp* app, InfraredAppEvent* event) { - bool consumed = false; - - if(brute_force_started) { - if(event->type == InfraredAppEvent::Type::Tick) { - auto view_manager = app->get_view_manager(); - app->notify_blink_send(); - InfraredAppEvent tick_event = { - .payload = {.dummy = 0}, - .type = InfraredAppEvent::Type::Tick, - }; - view_manager->send_event(&tick_event); - bool result = brute_force.send_next_bruteforce(); - if(result) { - result = progress_popup(app); - } - if(!result) { - brute_force.stop_bruteforce(); - brute_force_started = false; - hide_popup(app); - } - consumed = true; - } else if(event->type == InfraredAppEvent::Type::Back) { - brute_force_started = false; - brute_force.stop_bruteforce(); - hide_popup(app); - consumed = true; - } - } else { - if(event->type == InfraredAppEvent::Type::ButtonPanelPressed) { - int record_amount = 0; - if(brute_force.start_bruteforce(event->payload.menu_index, record_amount)) { - DOLPHIN_DEED(DolphinDeedIrBruteForce); - brute_force_started = true; - show_popup(app, record_amount); - app->notify_blink_send(); - } else { - app->switch_to_previous_scene(); - } - consumed = true; - } else if(event->type == InfraredAppEvent::Type::Back) { - app->switch_to_previous_scene(); - consumed = true; - } - } - - return consumed; -} - -void InfraredAppSceneUniversalCommon::on_exit(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - ButtonPanel* button_panel = view_manager->get_button_panel(); - button_panel_reset(button_panel); -} diff --git a/applications/infrared/scene/infrared_app_scene_universal_tv.cpp b/applications/infrared/scene/infrared_app_scene_universal_tv.cpp deleted file mode 100644 index a12481ec..00000000 --- a/applications/infrared/scene/infrared_app_scene_universal_tv.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include "infrared/scene/infrared_app_scene.h" -#include "infrared/infrared_app.h" - -void InfraredAppSceneUniversalTV::on_enter(InfraredApp* app) { - InfraredAppViewManager* view_manager = app->get_view_manager(); - ButtonPanel* button_panel = view_manager->get_button_panel(); - button_panel_reserve(button_panel, 2, 3); - - int i = 0; - button_panel_add_item( - button_panel, - i, - 0, - 0, - 3, - 19, - &I_Power_25x27, - &I_Power_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "POWER"); - ++i; - button_panel_add_item( - button_panel, - i, - 1, - 0, - 36, - 19, - &I_Mute_25x27, - &I_Mute_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "MUTE"); - ++i; - button_panel_add_item( - button_panel, - i, - 0, - 1, - 3, - 66, - &I_Vol_up_25x27, - &I_Vol_up_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "VOL+"); - ++i; - button_panel_add_item( - button_panel, - i, - 1, - 1, - 36, - 66, - &I_Up_25x27, - &I_Up_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "CH+"); - ++i; - button_panel_add_item( - button_panel, - i, - 0, - 2, - 3, - 98, - &I_Vol_down_25x27, - &I_Vol_down_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "VOL-"); - ++i; - button_panel_add_item( - button_panel, - i, - 1, - 2, - 36, - 98, - &I_Down_25x27, - &I_Down_hvr_25x27, - infrared_app_item_callback, - app); - brute_force.add_record(i, "CH-"); - - 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"); - - view_manager->switch_to(InfraredAppViewManager::ViewId::UniversalRemote); - - auto stack_view = app->get_view_manager()->get_universal_view_stack(); - auto loading_view = app->get_view_manager()->get_loading(); - view_stack_add_view(stack_view, loading_get_view(loading_view)); - - /** - * Problem: Update events are not handled in Loading View, because: - * 1) Timer task has least prio - * 2) Storage service uses drivers that capture whole CPU time - * to handle SD communication - * - * Ugly workaround, but it works for current situation: - * raise timer task prio for DB scanning period. - */ - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - TaskHandle_t storage_task = xTaskGetHandle("StorageSrv"); - uint32_t timer_prio = uxTaskPriorityGet(timer_task); - uint32_t storage_prio = uxTaskPriorityGet(storage_task); - vTaskPrioritySet(timer_task, storage_prio + 1); - bool result = brute_force.calculate_messages(); - vTaskPrioritySet(timer_task, timer_prio); - - view_stack_remove_view(stack_view, loading_get_view(loading_view)); - - if(!result) { - app->switch_to_previous_scene(); - } -} diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.c b/applications/infrared/scenes/common/infrared_scene_universal_common.c new file mode 100644 index 00000000..7eff81ee --- /dev/null +++ b/applications/infrared/scenes/common/infrared_scene_universal_common.c @@ -0,0 +1,92 @@ +#include "../../infrared_i.h" + +#include + +void infrared_scene_universal_common_item_callback(void* context, uint32_t index) { + Infrared* infrared = context; + uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeButtonSelected, index); + view_dispatcher_send_custom_event(infrared->view_dispatcher, event); +} + +static void infrared_scene_universal_common_progress_back_callback(void* context) { + Infrared* infrared = context; + uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeBackPressed, -1); + view_dispatcher_send_custom_event(infrared->view_dispatcher, event); +} + +static void infrared_scene_universal_common_show_popup(Infrared* infrared, uint32_t record_count) { + ViewStack* view_stack = infrared->view_stack; + InfraredProgressView* progress = infrared->progress; + infrared_progress_view_set_progress_total(progress, record_count); + infrared_progress_view_set_back_callback( + progress, infrared_scene_universal_common_progress_back_callback, infrared); + view_stack_add_view(view_stack, infrared_progress_view_get_view(progress)); +} + +static void infrared_scene_universal_common_hide_popup(Infrared* infrared) { + ViewStack* view_stack = infrared->view_stack; + InfraredProgressView* progress = infrared->progress; + view_stack_remove_view(view_stack, infrared_progress_view_get_view(progress)); +} + +void infrared_scene_universal_common_on_enter(void* context) { + Infrared* infrared = context; + view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel)); +} + +bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + InfraredBruteForce* brute_force = infrared->brute_force; + bool consumed = false; + + if(infrared_brute_force_is_started(brute_force)) { + if(event.type == SceneManagerEventTypeTick) { + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkSend); + bool success = infrared_brute_force_send_next(brute_force); + if(success) { + success = infrared_progress_view_increase_progress(infrared->progress); + } + if(!success) { + infrared_brute_force_stop(brute_force); + infrared_scene_universal_common_hide_popup(infrared); + } + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(infrared_custom_event_get_type(event.event) == InfraredCustomEventTypeBackPressed) { + infrared_brute_force_stop(brute_force); + infrared_scene_universal_common_hide_popup(infrared); + consumed = true; + } + } + } else { + if(event.type == SceneManagerEventTypeBack) { + scene_manager_previous_scene(scene_manager); + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(infrared_custom_event_get_type(event.event) == + InfraredCustomEventTypeButtonSelected) { + uint32_t record_count; + if(infrared_brute_force_start( + brute_force, infrared_custom_event_get_value(event.event), &record_count)) { + DOLPHIN_DEED(DolphinDeedIrBruteForce); + infrared_scene_universal_common_show_popup(infrared, record_count); + infrared_play_notification_message( + infrared, InfraredNotificationMessageBlinkSend); + } else { + scene_manager_next_scene(scene_manager, InfraredSceneErrorDatabases); + } + consumed = true; + } + } + } + + return consumed; +} + +void infrared_scene_universal_common_on_exit(void* context) { + Infrared* infrared = context; + ButtonPanel* button_panel = infrared->button_panel; + view_stack_remove_view(infrared->view_stack, button_panel_get_view(button_panel)); + button_panel_reset(button_panel); +} diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.h b/applications/infrared/scenes/common/infrared_scene_universal_common.h new file mode 100644 index 00000000..a6c697d7 --- /dev/null +++ b/applications/infrared/scenes/common/infrared_scene_universal_common.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +void infrared_scene_universal_common_on_enter(void* context); +bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event); +void infrared_scene_universal_common_on_exit(void* context); +void infrared_scene_universal_common_item_callback(void* context, uint32_t index); diff --git a/applications/infrared/scenes/infrared_scene.c b/applications/infrared/scenes/infrared_scene.c new file mode 100644 index 00000000..b0f298e6 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene.c @@ -0,0 +1,30 @@ +#include "infrared_scene.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const infrared_on_enter_handlers[])(void*) = { +#include "infrared_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const infrared_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "infrared_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const infrared_on_exit_handlers[])(void* context) = { +#include "infrared_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers infrared_scene_handlers = { + .on_enter_handlers = infrared_on_enter_handlers, + .on_event_handlers = infrared_on_event_handlers, + .on_exit_handlers = infrared_on_exit_handlers, + .scene_num = InfraredSceneNum, +}; diff --git a/applications/infrared/scenes/infrared_scene.h b/applications/infrared/scenes/infrared_scene.h new file mode 100644 index 00000000..e9d499a7 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) InfraredScene##id, +typedef enum { +#include "infrared_scene_config.h" + InfraredSceneNum, +} InfraredScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers infrared_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "infrared_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "infrared_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "infrared_scene_config.h" +#undef ADD_SCENE diff --git a/applications/infrared/scenes/infrared_scene_ask_back.c b/applications/infrared/scenes/infrared_scene_ask_back.c new file mode 100644 index 00000000..11cfcb04 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_ask_back.c @@ -0,0 +1,59 @@ +#include "../infrared_i.h" + +static void infrared_scene_dialog_result_callback(DialogExResult result, void* context) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, result); +} + +void infrared_scene_ask_back_on_enter(void* context) { + Infrared* infrared = context; + DialogEx* dialog_ex = infrared->dialog_ex; + + if(infrared->app_state.is_learning_new_remote) { + dialog_ex_set_header(dialog_ex, "Exit to Infrared menu?", 64, 0, AlignCenter, AlignTop); + } else { + dialog_ex_set_header(dialog_ex, "Exit to remote menu?", 64, 0, AlignCenter, AlignTop); + } + + dialog_ex_set_text( + dialog_ex, "All unsaved data\nwill be lost", 64, 31, AlignCenter, AlignCenter); + dialog_ex_set_icon(dialog_ex, 0, 0, NULL); + dialog_ex_set_left_button_text(dialog_ex, "Exit"); + dialog_ex_set_center_button_text(dialog_ex, NULL); + dialog_ex_set_right_button_text(dialog_ex, "Stay"); + dialog_ex_set_result_callback(dialog_ex, infrared_scene_dialog_result_callback); + dialog_ex_set_context(dialog_ex, context); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); +} + +bool infrared_scene_ask_back_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + if(infrared->app_state.is_learning_new_remote) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneStart); + } else { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneRemote); + } + consumed = true; + } else if(event.event == DialogExResultRight) { + scene_manager_previous_scene(scene_manager); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_ask_back_on_exit(void* context) { + Infrared* infrared = context; + dialog_ex_reset(infrared->dialog_ex); +} diff --git a/applications/infrared/scenes/infrared_scene_config.h b/applications/infrared/scenes/infrared_scene_config.h new file mode 100644 index 00000000..c4e083c1 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_config.h @@ -0,0 +1,18 @@ +ADD_SCENE(infrared, start, Start) +ADD_SCENE(infrared, ask_back, AskBack) +ADD_SCENE(infrared, edit, Edit) +ADD_SCENE(infrared, edit_delete, EditDelete) +ADD_SCENE(infrared, edit_delete_done, EditDeleteDone) +ADD_SCENE(infrared, edit_button_select, EditButtonSelect) +ADD_SCENE(infrared, edit_rename, EditRename) +ADD_SCENE(infrared, edit_rename_done, EditRenameDone) +ADD_SCENE(infrared, learn, Learn) +ADD_SCENE(infrared, learn_done, LearnDone) +ADD_SCENE(infrared, learn_enter_name, LearnEnterName) +ADD_SCENE(infrared, learn_success, LearnSuccess) +ADD_SCENE(infrared, remote, Remote) +ADD_SCENE(infrared, remote_list, RemoteList) +ADD_SCENE(infrared, universal, Universal) +ADD_SCENE(infrared, universal_tv, UniversalTV) +ADD_SCENE(infrared, debug, Debug) +ADD_SCENE(infrared, error_databases, ErrorDatabases) diff --git a/applications/infrared/scenes/infrared_scene_debug.c b/applications/infrared/scenes/infrared_scene_debug.c new file mode 100644 index 00000000..ddb85644 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_debug.c @@ -0,0 +1,68 @@ +#include "../infrared_i.h" + +void infrared_scene_debug_on_enter(void* context) { + Infrared* infrared = context; + InfraredWorker* worker = infrared->worker; + + infrared_worker_rx_set_received_signal_callback( + worker, infrared_signal_received_callback, context); + infrared_worker_rx_enable_blink_on_receiving(worker, true); + infrared_worker_rx_start(worker); + + infrared_debug_view_set_text(infrared->debug_view, "Received signals\nwill appear here"); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDebugView); +} + +bool infrared_scene_debug_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeSignalReceived) { + InfraredDebugView* debug_view = infrared->debug_view; + InfraredSignal* signal = infrared->received_signal; + + if(infrared_signal_is_raw(signal)) { + InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_debug_view_set_text(debug_view, "RAW\n%d samples\n", raw->timings_size); + + printf("RAW, %d samples:\r\n", raw->timings_size); + for(size_t i = 0; i < raw->timings_size; ++i) { + printf("%lu ", raw->timings[i]); + } + printf("\r\n"); + + } else { + InfraredMessage* message = infrared_signal_get_message(signal); + infrared_debug_view_set_text( + debug_view, + "%s\nA:0x%0*lX\nC:0x%0*lX\n%s\n", + infrared_get_protocol_name(message->protocol), + ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), + message->address, + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), + message->command, + message->repeat ? " R" : ""); + + printf( + "== %s, A:0x%0*lX, C:0x%0*lX%s ==\r\n", + infrared_get_protocol_name(message->protocol), + ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), + message->address, + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), + message->command, + message->repeat ? " R" : ""); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_debug_on_exit(void* context) { + Infrared* infrared = context; + InfraredWorker* worker = infrared->worker; + infrared_worker_rx_stop(worker); + infrared_worker_rx_enable_blink_on_receiving(worker, false); +} diff --git a/applications/infrared/scenes/infrared_scene_edit.c b/applications/infrared/scenes/infrared_scene_edit.c new file mode 100644 index 00000000..360ed49b --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit.c @@ -0,0 +1,101 @@ +#include "../infrared_i.h" + +typedef enum { + SubmenuIndexAddButton, + SubmenuIndexRenameButton, + SubmenuIndexDeleteButton, + SubmenuIndexRenameRemote, + SubmenuIndexDeleteRemote, +} SubmenuIndex; + +static void infrared_scene_edit_submenu_callback(void* context, uint32_t index) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, index); +} + +void infrared_scene_edit_on_enter(void* context) { + Infrared* infrared = context; + Submenu* submenu = infrared->submenu; + SceneManager* scene_manager = infrared->scene_manager; + + submenu_add_item( + submenu, + "Add Button", + SubmenuIndexAddButton, + infrared_scene_edit_submenu_callback, + context); + submenu_add_item( + submenu, + "Rename Button", + SubmenuIndexRenameButton, + infrared_scene_edit_submenu_callback, + context); + submenu_add_item( + submenu, + "Delete Button", + SubmenuIndexDeleteButton, + infrared_scene_edit_submenu_callback, + context); + submenu_add_item( + submenu, + "Rename Remote", + SubmenuIndexRenameRemote, + infrared_scene_edit_submenu_callback, + context); + submenu_add_item( + submenu, + "Delete Remote", + SubmenuIndexDeleteRemote, + infrared_scene_edit_submenu_callback, + context); + + const uint32_t submenu_index = scene_manager_get_scene_state(scene_manager, InfraredSceneEdit); + submenu_set_selected_item(submenu, submenu_index); + scene_manager_set_scene_state(scene_manager, InfraredSceneEdit, SubmenuIndexAddButton); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); +} + +bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + const uint32_t submenu_index = event.event; + scene_manager_set_scene_state(scene_manager, InfraredSceneEdit, submenu_index); + + if(submenu_index == SubmenuIndexAddButton) { + infrared->app_state.is_learning_new_remote = false; + scene_manager_next_scene(scene_manager, InfraredSceneLearn); + consumed = true; + } else if(submenu_index == SubmenuIndexRenameButton) { + infrared->app_state.edit_target = InfraredEditTargetButton; + infrared->app_state.edit_mode = InfraredEditModeRename; + scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect); + consumed = true; + } else if(submenu_index == SubmenuIndexDeleteButton) { + infrared->app_state.edit_target = InfraredEditTargetButton; + infrared->app_state.edit_mode = InfraredEditModeDelete; + scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect); + consumed = true; + } else if(submenu_index == SubmenuIndexRenameRemote) { + infrared->app_state.edit_target = InfraredEditTargetRemote; + infrared->app_state.edit_mode = InfraredEditModeRename; + scene_manager_next_scene(scene_manager, InfraredSceneEditRename); + consumed = true; + } else if(submenu_index == SubmenuIndexDeleteRemote) { + infrared->app_state.edit_target = InfraredEditTargetRemote; + infrared->app_state.edit_mode = InfraredEditModeDelete; + scene_manager_next_scene(scene_manager, InfraredSceneEditDelete); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_on_exit(void* context) { + Infrared* infrared = context; + submenu_reset(infrared->submenu); +} diff --git a/applications/infrared/scenes/infrared_scene_edit_button_select.c b/applications/infrared/scenes/infrared_scene_edit_button_select.c new file mode 100644 index 00000000..a7f8a2bf --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit_button_select.c @@ -0,0 +1,63 @@ +#include "../infrared_i.h" + +static void infrared_scene_edit_button_select_submenu_callback(void* context, uint32_t index) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, index); +} + +void infrared_scene_edit_button_select_on_enter(void* context) { + Infrared* infrared = context; + Submenu* submenu = infrared->submenu; + InfraredRemote* remote = infrared->remote; + InfraredAppState* app_state = &infrared->app_state; + + const char* header = infrared->app_state.edit_mode == InfraredEditModeRename ? + "Rename Button:" : + "Delete Button:"; + submenu_set_header(submenu, header); + + const size_t button_count = infrared_remote_get_button_count(remote); + for(size_t i = 0; i < button_count; ++i) { + InfraredRemoteButton* button = infrared_remote_get_button(remote, i); + submenu_add_item( + submenu, + infrared_remote_button_get_name(button), + i, + infrared_scene_edit_button_select_submenu_callback, + context); + } + + if(button_count && app_state->current_button_index != InfraredButtonIndexNone) { + submenu_set_selected_item(submenu, app_state->current_button_index); + app_state->current_button_index = InfraredButtonIndexNone; + } + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); +} + +bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + InfraredAppState* app_state = &infrared->app_state; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + app_state->current_button_index = event.event; + const InfraredEditMode edit_mode = app_state->edit_mode; + if(edit_mode == InfraredEditModeRename) { + scene_manager_next_scene(scene_manager, InfraredSceneEditRename); + } else if(edit_mode == InfraredEditModeDelete) { + scene_manager_next_scene(scene_manager, InfraredSceneEditDelete); + } else { + furi_assert(0); + } + consumed = true; + } + + return consumed; +} + +void infrared_scene_edit_button_select_on_exit(void* context) { + Infrared* infrared = context; + submenu_reset(infrared->submenu); +} diff --git a/applications/infrared/scenes/infrared_scene_edit_delete.c b/applications/infrared/scenes/infrared_scene_edit_delete.c new file mode 100644 index 00000000..0842cd61 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit_delete.c @@ -0,0 +1,112 @@ +#include "../infrared_i.h" + +static void + infrared_scene_edit_delete_dialog_result_callback(DialogExResult result, void* context) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, result); +} + +void infrared_scene_edit_delete_on_enter(void* context) { + Infrared* infrared = context; + DialogEx* dialog_ex = infrared->dialog_ex; + InfraredRemote* remote = infrared->remote; + + const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { + int32_t current_button_index = infrared->app_state.current_button_index; + furi_assert(current_button_index != InfraredButtonIndexNone); + + dialog_ex_set_header(dialog_ex, "Delete button?", 64, 0, AlignCenter, AlignTop); + InfraredRemoteButton* current_button = + infrared_remote_get_button(remote, current_button_index); + InfraredSignal* signal = infrared_remote_button_get_signal(current_button); + + if(infrared_signal_is_raw(signal)) { + const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_text_store_set( + infrared, + 0, + "%s\nRAW\n%ld samples", + infrared_remote_button_get_name(current_button), + raw->timings_size); + + } else { + const InfraredMessage* message = infrared_signal_get_message(signal); + infrared_text_store_set( + infrared, + 0, + "%s\n%s\nA=0x%0*lX C=0x%0*lX", + infrared_remote_button_get_name(current_button), + infrared_get_protocol_name(message->protocol), + ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), + message->address, + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), + message->command); + } + + } else if(edit_target == InfraredEditTargetRemote) { + dialog_ex_set_header(dialog_ex, "Delete remote?", 64, 0, AlignCenter, AlignTop); + infrared_text_store_set( + infrared, + 0, + "%s\n with %lu buttons", + infrared_remote_get_name(remote), + infrared_remote_get_button_count(remote)); + } else { + furi_assert(0); + } + + dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter); + dialog_ex_set_icon(dialog_ex, 0, 0, NULL); + dialog_ex_set_left_button_text(dialog_ex, "Cancel"); + dialog_ex_set_right_button_text(dialog_ex, "Delete"); + dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_delete_dialog_result_callback); + dialog_ex_set_context(dialog_ex, context); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); +} + +bool infrared_scene_edit_delete_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + scene_manager_previous_scene(scene_manager); + consumed = true; + } else if(event.event == DialogExResultRight) { + bool success = false; + InfraredRemote* remote = infrared->remote; + InfraredAppState* app_state = &infrared->app_state; + const InfraredEditTarget edit_target = app_state->edit_target; + + if(edit_target == InfraredEditTargetButton) { + furi_assert(app_state->current_button_index != InfraredButtonIndexNone); + success = infrared_remote_delete_button(remote, app_state->current_button_index); + app_state->current_button_index = InfraredButtonIndexNone; + } else if(edit_target == InfraredEditTargetRemote) { + success = infrared_remote_remove(remote); + app_state->current_button_index = InfraredButtonIndexNone; + } else { + furi_assert(0); + } + + if(success) { + scene_manager_next_scene(scene_manager, InfraredSceneEditDeleteDone); + } else { + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_delete_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} diff --git a/applications/infrared/scenes/infrared_scene_edit_delete_done.c b/applications/infrared/scenes/infrared_scene_edit_delete_done.c new file mode 100644 index 00000000..4502abbd --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit_delete_done.c @@ -0,0 +1,46 @@ +#include "../infrared_i.h" + +void infrared_scene_edit_delete_done_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); + popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); + + popup_set_callback(popup, infrared_popup_closed_callback); + popup_set_context(popup, context); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_edit_delete_done_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypePopupClosed) { + const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneRemote); + } else if(edit_target == InfraredEditTargetRemote) { + const uint32_t possible_scenes[] = {InfraredSceneStart, InfraredSceneRemoteList}; + scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } else { + furi_assert(0); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_delete_done_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} diff --git a/applications/infrared/scenes/infrared_scene_edit_rename.c b/applications/infrared/scenes/infrared_scene_edit_rename.c new file mode 100644 index 00000000..ebe7c2a9 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit_rename.c @@ -0,0 +1,107 @@ +#include "../infrared_i.h" + +#include +#include + +void infrared_scene_edit_rename_on_enter(void* context) { + Infrared* infrared = context; + InfraredRemote* remote = infrared->remote; + TextInput* text_input = infrared->text_input; + size_t enter_name_length = 0; + + const InfraredEditTarget edit_target = infrared->app_state.edit_target; + if(edit_target == InfraredEditTargetButton) { + text_input_set_header_text(text_input, "Name the button"); + + const int32_t current_button_index = infrared->app_state.current_button_index; + furi_assert(current_button_index != InfraredButtonIndexNone); + + InfraredRemoteButton* current_button = + infrared_remote_get_button(remote, current_button_index); + enter_name_length = INFRARED_MAX_BUTTON_NAME_LENGTH; + strncpy( + infrared->text_store[0], + infrared_remote_button_get_name(current_button), + enter_name_length); + + } else if(edit_target == InfraredEditTargetRemote) { + text_input_set_header_text(text_input, "Name the remote"); + enter_name_length = INFRARED_MAX_REMOTE_NAME_LENGTH; + strncpy(infrared->text_store[0], infrared_remote_get_name(remote), enter_name_length); + + string_t folder_path; + string_init(folder_path); + + if(string_end_with_str_p(infrared->file_path, INFRARED_APP_EXTENSION)) { + path_extract_dirname(string_get_cstr(infrared->file_path), folder_path); + } + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + string_get_cstr(folder_path), + INFRARED_APP_EXTENSION, + infrared_remote_get_name(remote)); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + string_clear(folder_path); + } else { + furi_assert(0); + } + + text_input_set_result_callback( + text_input, + infrared_text_input_callback, + context, + infrared->text_store[0], + enter_name_length, + false); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewTextInput); +} + +bool infrared_scene_edit_rename_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + InfraredRemote* remote = infrared->remote; + SceneManager* scene_manager = infrared->scene_manager; + InfraredAppState* app_state = &infrared->app_state; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeTextEditDone) { + bool success = false; + const InfraredEditTarget edit_target = app_state->edit_target; + if(edit_target == InfraredEditTargetButton) { + const int32_t current_button_index = app_state->current_button_index; + furi_assert(current_button_index != InfraredButtonIndexNone); + success = infrared_remote_rename_button( + remote, infrared->text_store[0], current_button_index); + app_state->current_button_index = InfraredButtonIndexNone; + } else if(edit_target == InfraredEditTargetRemote) { + success = infrared_rename_current_remote(infrared, infrared->text_store[0]); + } else { + furi_assert(0); + } + + if(success) { + scene_manager_next_scene(scene_manager, InfraredSceneEditRenameDone); + } else { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneRemoteList); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_rename_on_exit(void* context) { + Infrared* infrared = context; + TextInput* text_input = infrared->text_input; + + void* validator_context = text_input_get_validator_callback_context(text_input); + text_input_set_validator(text_input, NULL, NULL); + + if(validator_context) { + validator_is_file_free((ValidatorIsFile*)validator_context); + } +} diff --git a/applications/infrared/scenes/infrared_scene_edit_rename_done.c b/applications/infrared/scenes/infrared_scene_edit_rename_done.c new file mode 100644 index 00000000..54b18ab6 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_edit_rename_done.c @@ -0,0 +1,35 @@ +#include "../infrared_i.h" + +void infrared_scene_edit_rename_done_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); + + popup_set_callback(popup, infrared_popup_closed_callback); + popup_set_context(popup, context); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_edit_rename_done_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypePopupClosed) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_edit_rename_done_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} diff --git a/applications/infrared/scenes/infrared_scene_error_databases.c b/applications/infrared/scenes/infrared_scene_error_databases.c new file mode 100644 index 00000000..4ed4dee5 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_error_databases.c @@ -0,0 +1,37 @@ +#include "../infrared_i.h" + +void infrared_scene_error_databases_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + + popup_set_icon(popup, 5, 11, &I_SDQuestion_35x43); + popup_set_text( + popup, "Function requires\nSD card with fresh\ndatabases.", 47, 17, AlignLeft, AlignTop); + + popup_set_context(popup, context); + popup_set_callback(popup, infrared_popup_closed_callback); + + infrared_play_notification_message(infrared, InfraredNotificationMessageYellowOn); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_error_databases_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypePopupClosed) { + scene_manager_search_and_switch_to_previous_scene( + infrared->scene_manager, InfraredSceneUniversal); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_error_databases_on_exit(void* context) { + Infrared* infrared = context; + popup_reset(infrared->popup); + infrared_play_notification_message(infrared, InfraredNotificationMessageYellowOff); +} diff --git a/applications/infrared/scenes/infrared_scene_learn.c b/applications/infrared/scenes/infrared_scene_learn.c new file mode 100644 index 00000000..d91b8676 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_learn.c @@ -0,0 +1,46 @@ +#include "../infrared_i.h" + +void infrared_scene_learn_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + InfraredWorker* worker = infrared->worker; + + infrared_worker_rx_set_received_signal_callback( + worker, infrared_signal_received_callback, context); + infrared_worker_rx_start(worker); + + popup_set_icon(popup, 0, 32, &I_InfraredLearnShort_128x31); + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignCenter); + popup_set_text( + popup, "Point the remote at IR port\nand push the button", 5, 10, AlignLeft, AlignCenter); + popup_set_callback(popup, NULL); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkRead); + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeSignalReceived) { + infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL); + infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess); + scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_learn_on_exit(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + infrared_worker_rx_stop(infrared->worker); + popup_set_icon(popup, 0, 0, NULL); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignCenter); +} diff --git a/applications/infrared/scenes/infrared_scene_learn_done.c b/applications/infrared/scenes/infrared_scene_learn_done.c new file mode 100644 index 00000000..eb6cced8 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_learn_done.c @@ -0,0 +1,44 @@ +#include "../infrared_i.h" + +#include + +void infrared_scene_learn_done_on_enter(void* context) { + Infrared* infrared = context; + Popup* popup = infrared->popup; + + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + DOLPHIN_DEED(DolphinDeedIrSave); + + if(infrared->app_state.is_learning_new_remote) { + popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop); + } else { + popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop); + } + + popup_set_callback(popup, infrared_popup_closed_callback); + popup_set_context(popup, context); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup); +} + +bool infrared_scene_learn_done_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypePopupClosed) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_learn_done_on_exit(void* context) { + Infrared* infrared = context; + infrared->app_state.is_learning_new_remote = false; + popup_set_header(infrared->popup, NULL, 0, 0, AlignLeft, AlignTop); +} diff --git a/applications/infrared/scenes/infrared_scene_learn_enter_name.c b/applications/infrared/scenes/infrared_scene_learn_enter_name.c new file mode 100644 index 00000000..b7f4179e --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_learn_enter_name.c @@ -0,0 +1,66 @@ +#include "../infrared_i.h" + +void infrared_scene_learn_enter_name_on_enter(void* context) { + Infrared* infrared = context; + TextInput* text_input = infrared->text_input; + InfraredSignal* signal = infrared->received_signal; + + if(infrared_signal_is_raw(signal)) { + InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + infrared_text_store_set(infrared, 0, "RAW_%d", raw->timings_size); + } else { + InfraredMessage* message = infrared_signal_get_message(signal); + infrared_text_store_set( + infrared, + 0, + "%.4s_%0*lX", + infrared_get_protocol_name(message->protocol), + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), + message->command); + } + + text_input_set_header_text(text_input, "Name the button"); + text_input_set_result_callback( + text_input, + infrared_text_input_callback, + context, + infrared->text_store[0], + INFRARED_MAX_BUTTON_NAME_LENGTH, + true); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewTextInput); +} + +bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + InfraredSignal* signal = infrared->received_signal; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == InfraredCustomEventTypeTextEditDone) { + bool success = false; + if(infrared->app_state.is_learning_new_remote) { + success = + infrared_add_remote_with_button(infrared, infrared->text_store[0], signal); + } else { + success = + infrared_remote_add_button(infrared->remote, infrared->text_store[0], signal); + } + + if(success) { + scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); + } else { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneRemoteList); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_learn_enter_name_on_exit(void* context) { + Infrared* infrared = context; + UNUSED(infrared); +} diff --git a/applications/infrared/scenes/infrared_scene_learn_success.c b/applications/infrared/scenes/infrared_scene_learn_success.c new file mode 100644 index 00000000..ec950ca7 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_learn_success.c @@ -0,0 +1,131 @@ +#include "../infrared_i.h" + +#include + +typedef enum { + InfraredSceneLearnSuccessStateIdle = 0, + InfraredSceneLearnSuccessStateSending = 1, +} InfraredSceneLearnSuccessState; + +static void + infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, result); +} + +void infrared_scene_learn_success_on_enter(void* context) { + Infrared* infrared = context; + DialogEx* dialog_ex = infrared->dialog_ex; + InfraredSignal* signal = infrared->received_signal; + + DOLPHIN_DEED(DolphinDeedIrLearnSuccess); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); + + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, context); + infrared_worker_tx_set_signal_sent_callback( + infrared->worker, infrared_signal_sent_callback, context); + + if(infrared_signal_is_raw(signal)) { + InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); + dialog_ex_set_header(dialog_ex, "Unknown", 95, 10, AlignCenter, AlignCenter); + infrared_text_store_set(infrared, 0, "%d samples", raw->timings_size); + dialog_ex_set_text(dialog_ex, infrared->text_store[0], 75, 23, AlignLeft, AlignTop); + + } else { + InfraredMessage* message = infrared_signal_get_message(signal); + uint8_t addr_digits = + ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4); + uint8_t cmd_digits = + ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4); + uint8_t max_digits = MAX(addr_digits, cmd_digits); + max_digits = MIN(max_digits, 7); + size_t label_x_offset = 63 + (7 - max_digits) * 3; + + infrared_text_store_set(infrared, 0, "%s", infrared_get_protocol_name(message->protocol)); + infrared_text_store_set( + infrared, + 1, + "A: 0x%0*lX\nC: 0x%0*lX\n", + addr_digits, + message->address, + cmd_digits, + message->command); + + dialog_ex_set_header(dialog_ex, infrared->text_store[0], 95, 7, AlignCenter, AlignCenter); + dialog_ex_set_text( + dialog_ex, infrared->text_store[1], label_x_offset, 34, AlignLeft, AlignCenter); + } + + dialog_ex_set_left_button_text(dialog_ex, "Retry"); + dialog_ex_set_right_button_text(dialog_ex, "Save"); + dialog_ex_set_center_button_text(dialog_ex, "Send"); + dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); + dialog_ex_set_result_callback(dialog_ex, infrared_scene_learn_success_dialog_result_callback); + dialog_ex_set_context(dialog_ex, context); + dialog_ex_enable_extended_events(dialog_ex); + + scene_manager_set_scene_state( + infrared->scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx); +} + +bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + uint32_t scene_state = scene_manager_get_scene_state(scene_manager, InfraredSceneLearnSuccess); + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + if(scene_state == InfraredSceneLearnSuccessStateIdle) { + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn); + } + consumed = true; + } else if(event.type == SceneManagerEventTypeBack) { + if(scene_state == InfraredSceneLearnSuccessStateIdle) { + scene_manager_next_scene(scene_manager, InfraredSceneAskBack); + } + consumed = true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == DialogExResultLeft) { + if(scene_state == InfraredSceneLearnSuccessStateIdle) { + scene_manager_search_and_switch_to_previous_scene( + scene_manager, InfraredSceneLearn); + } + consumed = true; + } else if(event.event == DialogExResultRight) { + if(scene_state == InfraredSceneLearnSuccessStateIdle) { + scene_manager_next_scene(scene_manager, InfraredSceneLearnEnterName); + } + consumed = true; + } else if(event.event == DialogExPressCenter) { + if(scene_state == InfraredSceneLearnSuccessStateIdle) { + scene_manager_set_scene_state( + scene_manager, + InfraredSceneLearnSuccess, + InfraredSceneLearnSuccessStateSending); + infrared_tx_start_received(infrared); + } + consumed = true; + } else if(event.event == DialogExReleaseCenter) { + if(scene_state == InfraredSceneLearnSuccessStateSending) { + scene_manager_set_scene_state( + scene_manager, InfraredSceneLearnSuccess, InfraredSceneLearnSuccessStateIdle); + infrared_tx_stop(infrared); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); + } + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_learn_success_on_exit(void* context) { + Infrared* infrared = context; + InfraredWorker* worker = infrared->worker; + dialog_ex_reset(infrared->dialog_ex); + infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOff); + infrared_worker_tx_set_get_signal_callback(worker, NULL, NULL); + infrared_worker_tx_set_signal_sent_callback(worker, NULL, NULL); +} diff --git a/applications/infrared/scenes/infrared_scene_remote.c b/applications/infrared/scenes/infrared_scene_remote.c new file mode 100644 index 00000000..50f71488 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_remote.c @@ -0,0 +1,118 @@ +#include "../infrared_i.h" + +typedef enum { + ButtonIndexPlus = -2, + ButtonIndexEdit = -1, + ButtonIndexNA = 0, +} ButtonIndex; + +static void + infrared_scene_remote_button_menu_callback(void* context, int32_t index, InputType type) { + Infrared* infrared = context; + + uint16_t custom_type; + if(type == InputTypePress) { + custom_type = InfraredCustomEventTypeTransmitStarted; + } else if(type == InputTypeRelease) { + custom_type = InfraredCustomEventTypeTransmitStopped; + } else if(type == InputTypeShort) { + custom_type = InfraredCustomEventTypeMenuSelected; + } else { + furi_crash("Unexpected input type"); + } + + view_dispatcher_send_custom_event( + infrared->view_dispatcher, infrared_custom_event_pack(custom_type, index)); +} + +void infrared_scene_remote_on_enter(void* context) { + Infrared* infrared = context; + InfraredRemote* remote = infrared->remote; + ButtonMenu* button_menu = infrared->button_menu; + SceneManager* scene_manager = infrared->scene_manager; + + infrared_worker_tx_set_get_signal_callback( + infrared->worker, infrared_worker_tx_get_signal_steady_callback, infrared); + infrared_worker_tx_set_signal_sent_callback( + infrared->worker, infrared_signal_sent_callback, infrared); + + size_t button_count = infrared_remote_get_button_count(remote); + for(size_t i = 0; i < button_count; ++i) { + InfraredRemoteButton* button = infrared_remote_get_button(remote, i); + button_menu_add_item( + button_menu, + infrared_remote_button_get_name(button), + i, + infrared_scene_remote_button_menu_callback, + ButtonMenuItemTypeCommon, + context); + } + + button_menu_add_item( + button_menu, + "+", + ButtonIndexPlus, + infrared_scene_remote_button_menu_callback, + ButtonMenuItemTypeControl, + context); + button_menu_add_item( + button_menu, + "Edit", + ButtonIndexEdit, + infrared_scene_remote_button_menu_callback, + ButtonMenuItemTypeControl, + context); + + button_menu_set_header(button_menu, infrared_remote_get_name(remote)); + const int16_t button_index = + (signed)scene_manager_get_scene_state(scene_manager, InfraredSceneRemote); + button_menu_set_selected_item(button_menu, button_index); + scene_manager_set_scene_state(scene_manager, InfraredSceneRemote, ButtonIndexNA); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewButtonMenu); +} + +bool infrared_scene_remote_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + consumed = scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t)); + } else if(event.type == SceneManagerEventTypeCustom) { + const uint16_t custom_type = infrared_custom_event_get_type(event.event); + const int16_t button_index = infrared_custom_event_get_value(event.event); + + if(custom_type == InfraredCustomEventTypeTransmitStarted) { + furi_assert(button_index >= 0); + infrared_tx_start_button_index(infrared, button_index); + consumed = true; + } else if(custom_type == InfraredCustomEventTypeTransmitStopped) { + infrared_tx_stop(infrared); + consumed = true; + } else if(custom_type == InfraredCustomEventTypeMenuSelected) { + furi_assert(button_index < 0); + scene_manager_set_scene_state( + scene_manager, InfraredSceneRemote, (unsigned)button_index); + if(button_index == ButtonIndexPlus) { + infrared->app_state.is_learning_new_remote = false; + scene_manager_next_scene(scene_manager, InfraredSceneLearn); + consumed = true; + } else if(button_index == ButtonIndexEdit) { + scene_manager_next_scene(scene_manager, InfraredSceneEdit); + consumed = true; + } + } + } + + return consumed; +} + +void infrared_scene_remote_on_exit(void* context) { + Infrared* infrared = context; + infrared_worker_tx_set_get_signal_callback(infrared->worker, NULL, NULL); + infrared_worker_tx_set_signal_sent_callback(infrared->worker, NULL, NULL); + button_menu_reset(infrared->button_menu); +} diff --git a/applications/infrared/scenes/infrared_scene_remote_list.c b/applications/infrared/scenes/infrared_scene_remote_list.c new file mode 100644 index 00000000..25b37759 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_remote_list.c @@ -0,0 +1,44 @@ +#include "../infrared_i.h" + +void infrared_scene_remote_list_on_enter(void* context) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + ViewDispatcher* view_dispatcher = infrared->view_dispatcher; + + string_set_str(infrared->file_path, INFRARED_APP_FOLDER); + bool success = dialog_file_browser_show( + infrared->dialogs, + infrared->file_path, + infrared->file_path, + INFRARED_APP_EXTENSION, + true, + &I_ir_10px, + true); + + if(success) { + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationHorizontal); + view_dispatcher_switch_to_view(view_dispatcher, InfraredViewStack); + + infrared_show_loading_popup(infrared, true); + success = infrared_remote_load(infrared->remote, infrared->file_path); + infrared_show_loading_popup(infrared, false); + } + + if(success) { + scene_manager_next_scene(scene_manager, InfraredSceneRemote); + } else { + scene_manager_previous_scene(scene_manager); + } +} + +bool infrared_scene_remote_list_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + bool consumed = false; + + return consumed; +} + +void infrared_scene_remote_list_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/infrared/scenes/infrared_scene_start.c b/applications/infrared/scenes/infrared_scene_start.c new file mode 100644 index 00000000..6b874a3a --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_start.c @@ -0,0 +1,83 @@ +#include "../infrared_i.h" + +enum SubmenuIndex { + SubmenuIndexUniversalRemotes, + SubmenuIndexLearnNewRemote, + SubmenuIndexSavedRemotes, + SubmenuIndexDebug +}; + +static void infrared_scene_start_submenu_callback(void* context, uint32_t index) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, index); +} + +void infrared_scene_start_on_enter(void* context) { + Infrared* infrared = context; + Submenu* submenu = infrared->submenu; + SceneManager* scene_manager = infrared->scene_manager; + + submenu_add_item( + submenu, + "Universal Remotes", + SubmenuIndexUniversalRemotes, + infrared_scene_start_submenu_callback, + infrared); + submenu_add_item( + submenu, + "Learn New Remote", + SubmenuIndexLearnNewRemote, + infrared_scene_start_submenu_callback, + infrared); + submenu_add_item( + submenu, + "Saved Remotes", + SubmenuIndexSavedRemotes, + infrared_scene_start_submenu_callback, + infrared); + + if(infrared->app_state.is_debug_enabled) { + submenu_add_item( + submenu, "Debug", SubmenuIndexDebug, infrared_scene_start_submenu_callback, infrared); + } + + const uint32_t submenu_index = + scene_manager_get_scene_state(scene_manager, InfraredSceneStart); + submenu_set_selected_item(submenu, submenu_index); + scene_manager_set_scene_state(scene_manager, InfraredSceneStart, SubmenuIndexUniversalRemotes); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); +} + +bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + const uint32_t submenu_index = event.event; + scene_manager_set_scene_state(scene_manager, InfraredSceneStart, submenu_index); + if(submenu_index == SubmenuIndexUniversalRemotes) { + scene_manager_next_scene(scene_manager, InfraredSceneUniversal); + consumed = true; + } else if(submenu_index == SubmenuIndexLearnNewRemote) { + infrared->app_state.is_learning_new_remote = true; + scene_manager_next_scene(scene_manager, InfraredSceneLearn); + consumed = true; + } else if(submenu_index == SubmenuIndexSavedRemotes) { + scene_manager_next_scene(scene_manager, InfraredSceneRemoteList); + consumed = true; + } else if(submenu_index == SubmenuIndexDebug) { + scene_manager_next_scene(scene_manager, InfraredSceneDebug); + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_start_on_exit(void* context) { + Infrared* infrared = context; + submenu_reset(infrared->submenu); +} diff --git a/applications/infrared/scenes/infrared_scene_universal.c b/applications/infrared/scenes/infrared_scene_universal.c new file mode 100644 index 00000000..cc656883 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_universal.c @@ -0,0 +1,53 @@ +#include "../infrared_i.h" + +typedef enum { + SubmenuIndexUniversalTV, + SubmenuIndexUniversalAudio, + SubmenuIndexUniversalAirConditioner, +} SubmenuIndex; + +static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) { + Infrared* infrared = context; + view_dispatcher_send_custom_event(infrared->view_dispatcher, index); +} + +void infrared_scene_universal_on_enter(void* context) { + Infrared* infrared = context; + Submenu* submenu = infrared->submenu; + + submenu_add_item( + submenu, + "TVs", + SubmenuIndexUniversalTV, + infrared_scene_universal_submenu_callback, + context); + submenu_set_selected_item(submenu, 0); + + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu); +} + +bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) { + Infrared* infrared = context; + SceneManager* scene_manager = infrared->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexUniversalTV) { + scene_manager_next_scene(scene_manager, InfraredSceneUniversalTV); + consumed = true; + } else if(event.event == SubmenuIndexUniversalAudio) { + //TODO Implement Audio universal remote + consumed = true; + } else if(event.event == SubmenuIndexUniversalAirConditioner) { + //TODO Implement A/C universal remote + consumed = true; + } + } + + return consumed; +} + +void infrared_scene_universal_on_exit(void* context) { + Infrared* infrared = context; + submenu_reset(infrared->submenu); +} diff --git a/applications/infrared/scenes/infrared_scene_universal_tv.c b/applications/infrared/scenes/infrared_scene_universal_tv.c new file mode 100644 index 00000000..83b084c3 --- /dev/null +++ b/applications/infrared/scenes/infrared_scene_universal_tv.c @@ -0,0 +1,111 @@ +#include "../infrared_i.h" + +#include "common/infrared_scene_universal_common.h" + +void infrared_scene_universal_tv_on_enter(void* context) { + infrared_scene_universal_common_on_enter(context); + + Infrared* infrared = context; + ButtonPanel* button_panel = infrared->button_panel; + InfraredBruteForce* brute_force = infrared->brute_force; + + infrared_brute_force_set_db_filename(brute_force, "/ext/infrared/assets/tv.ir"); + + 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, + infrared_scene_universal_common_item_callback, + context); + 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, + infrared_scene_universal_common_item_callback, + context); + 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, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "VOL+"); + button_panel_add_item( + button_panel, + i, + 1, + 1, + 36, + 66, + &I_Up_25x27, + &I_Up_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "CH+"); + button_panel_add_item( + button_panel, + i, + 0, + 2, + 3, + 98, + &I_Vol_down_25x27, + &I_Vol_down_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "VOL-"); + button_panel_add_item( + button_panel, + i, + 1, + 2, + 36, + 98, + &I_Down_25x27, + &I_Down_hvr_25x27, + infrared_scene_universal_common_item_callback, + context); + infrared_brute_force_add_record(brute_force, i++, "CH-"); + + 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"); + + view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical); + view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack); + + infrared_show_loading_popup(infrared, true); + bool success = infrared_brute_force_calculate_messages(brute_force); + infrared_show_loading_popup(infrared, false); + + if(!success) { + scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases); + } +} + +bool infrared_scene_universal_tv_on_event(void* context, SceneManagerEvent event) { + return infrared_scene_universal_common_on_event(context, event); +} + +void infrared_scene_universal_tv_on_exit(void* context) { + infrared_scene_universal_common_on_exit(context); +} diff --git a/applications/infrared/views/infrared_debug_view.c b/applications/infrared/views/infrared_debug_view.c new file mode 100644 index 00000000..ab2c679c --- /dev/null +++ b/applications/infrared/views/infrared_debug_view.c @@ -0,0 +1,59 @@ +#include "infrared_debug_view.h" + +#include +#include + +#include +#include + +#define INFRARED_DEBUG_TEXT_LENGTH 64 + +struct InfraredDebugView { + View* view; +}; + +typedef struct { + char text[INFRARED_DEBUG_TEXT_LENGTH]; +} InfraredDebugViewModel; + +static void infrared_debug_view_draw_callback(Canvas* canvas, void* model) { + InfraredDebugViewModel* debug_view_model = model; + + canvas_clear(canvas); + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 64, 0, AlignCenter, AlignTop, "INFRARED monitor\n"); + canvas_set_font(canvas, FontKeyboard); + + if(strlen(debug_view_model->text)) { + elements_multiline_text_aligned( + canvas, 64, 43, AlignCenter, AlignCenter, debug_view_model->text); + } +} + +InfraredDebugView* infrared_debug_view_alloc() { + InfraredDebugView* debug_view = malloc(sizeof(InfraredDebugView)); + debug_view->view = view_alloc(); + view_allocate_model(debug_view->view, ViewModelTypeLocking, sizeof(InfraredDebugViewModel)); + view_set_draw_callback(debug_view->view, infrared_debug_view_draw_callback); + view_set_context(debug_view->view, debug_view); + return debug_view; +} +void infrared_debug_view_free(InfraredDebugView* debug_view) { + view_free(debug_view->view); + free(debug_view); +} + +View* infrared_debug_view_get_view(InfraredDebugView* debug_view) { + return debug_view->view; +} + +void infrared_debug_view_set_text(InfraredDebugView* debug_view, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + InfraredDebugViewModel* model = view_get_model(debug_view->view); + vsnprintf(model->text, INFRARED_DEBUG_TEXT_LENGTH, fmt, args); + view_commit_model(debug_view->view, true); + + va_end(args); +} diff --git a/applications/infrared/views/infrared_debug_view.h b/applications/infrared/views/infrared_debug_view.h new file mode 100644 index 00000000..722850f8 --- /dev/null +++ b/applications/infrared/views/infrared_debug_view.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct InfraredDebugView InfraredDebugView; + +InfraredDebugView* infrared_debug_view_alloc(); +void infrared_debug_view_free(InfraredDebugView* debug_view); + +View* infrared_debug_view_get_view(InfraredDebugView* debug_view); +void infrared_debug_view_set_text(InfraredDebugView* debug_view, const char* fmt, ...); diff --git a/applications/infrared/view/infrared_progress_view.c b/applications/infrared/views/infrared_progress_view.c similarity index 100% rename from applications/infrared/view/infrared_progress_view.c rename to applications/infrared/views/infrared_progress_view.c diff --git a/applications/infrared/view/infrared_progress_view.h b/applications/infrared/views/infrared_progress_view.h similarity index 100% rename from applications/infrared/view/infrared_progress_view.h rename to applications/infrared/views/infrared_progress_view.h diff --git a/applications/infrared_monitor/infrared_monitor.c b/applications/infrared_monitor/infrared_monitor.c deleted file mode 100644 index 08691dfa..00000000 --- a/applications/infrared_monitor/infrared_monitor.c +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define INFRARED_TIMINGS_SIZE 700 - -typedef struct { - uint32_t timing_cnt; - struct { - uint8_t level; - uint32_t duration; - } timing[INFRARED_TIMINGS_SIZE]; -} InfraredDelaysArray; - -typedef struct { - char display_text[64]; - osMessageQueueId_t event_queue; - InfraredDelaysArray delays; - InfraredWorker* worker; - ViewPort* view_port; -} InfraredMonitor; - -void infrared_monitor_input_callback(InputEvent* input_event, void* ctx) { - furi_assert(ctx); - InfraredMonitor* infrared_monitor = (InfraredMonitor*)ctx; - - if((input_event->type == InputTypeShort) && (input_event->key == InputKeyBack)) { - osMessageQueuePut(infrared_monitor->event_queue, input_event, 0, 0); - } -} - -static void infrared_monitor_draw_callback(Canvas* canvas, void* ctx) { - furi_assert(canvas); - furi_assert(ctx); - InfraredMonitor* infrared_monitor = (InfraredMonitor*)ctx; - - canvas_clear(canvas); - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned(canvas, 64, 0, AlignCenter, AlignTop, "INFRARED monitor\n"); - canvas_set_font(canvas, FontKeyboard); - if(strlen(infrared_monitor->display_text)) { - elements_multiline_text_aligned( - canvas, 64, 43, AlignCenter, AlignCenter, infrared_monitor->display_text); - } -} - -static void signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { - furi_assert(context); - furi_assert(received_signal); - InfraredMonitor* infrared_monitor = context; - - if(infrared_worker_signal_is_decoded(received_signal)) { - const InfraredMessage* message = infrared_worker_get_decoded_signal(received_signal); - snprintf( - infrared_monitor->display_text, - sizeof(infrared_monitor->display_text), - "%s\nA:0x%0*lX\nC:0x%0*lX\n%s\n", - infrared_get_protocol_name(message->protocol), - ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), - message->address, - ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), - message->command, - message->repeat ? " R" : ""); - view_port_update(infrared_monitor->view_port); - printf( - "== %s, A:0x%0*lX, C:0x%0*lX%s ==\r\n", - infrared_get_protocol_name(message->protocol), - ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4), - message->address, - ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4), - message->command, - message->repeat ? " R" : ""); - } else { - const uint32_t* timings; - size_t timings_cnt; - infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt); - snprintf( - infrared_monitor->display_text, - sizeof(infrared_monitor->display_text), - "RAW\n%d samples\n", - timings_cnt); - view_port_update(infrared_monitor->view_port); - printf("RAW, %d samples:\r\n", timings_cnt); - for(size_t i = 0; i < timings_cnt; ++i) { - printf("%lu ", timings[i]); - } - printf("\r\n"); - } -} - -int32_t infrared_monitor_app(void* p) { - (void)p; - - InfraredMonitor* infrared_monitor = malloc(sizeof(InfraredMonitor)); - infrared_monitor->display_text[0] = 0; - infrared_monitor->event_queue = osMessageQueueNew(1, sizeof(InputEvent), NULL); - infrared_monitor->view_port = view_port_alloc(); - Gui* gui = furi_record_open("gui"); - - view_port_draw_callback_set( - infrared_monitor->view_port, infrared_monitor_draw_callback, infrared_monitor); - view_port_input_callback_set( - infrared_monitor->view_port, infrared_monitor_input_callback, infrared_monitor); - - gui_add_view_port(gui, infrared_monitor->view_port, GuiLayerFullscreen); - - infrared_monitor->worker = infrared_worker_alloc(); - infrared_worker_rx_start(infrared_monitor->worker); - infrared_worker_rx_set_received_signal_callback( - infrared_monitor->worker, signal_received_callback, infrared_monitor); - infrared_worker_rx_enable_blink_on_receiving(infrared_monitor->worker, true); - - while(1) { - InputEvent event; - if(osOK == osMessageQueueGet(infrared_monitor->event_queue, &event, NULL, 50)) { - if((event.type == InputTypeShort) && (event.key == InputKeyBack)) { - break; - } - } - } - - infrared_worker_rx_stop(infrared_monitor->worker); - infrared_worker_free(infrared_monitor->worker); - osMessageQueueDelete(infrared_monitor->event_queue); - view_port_enabled_set(infrared_monitor->view_port, false); - gui_remove_view_port(gui, infrared_monitor->view_port); - view_port_free(infrared_monitor->view_port); - furi_record_close("gui"); - free(infrared_monitor); - - return 0; -} diff --git a/applications/input/application.fam b/applications/input/application.fam new file mode 100644 index 00000000..545630e6 --- /dev/null +++ b/applications/input/application.fam @@ -0,0 +1,9 @@ +App( + appid="input", + name="InputSrv", + apptype=FlipperAppType.SERVICE, + entry_point="input_srv", + cdefines=["SRV_INPUT"], + stack_size=1 * 1024, + order=80, +) diff --git a/applications/input/input.c b/applications/input/input.c index dd824dcb..2be67a71 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -36,7 +36,7 @@ void input_press_timer_callback(void* arg) { void input_isr(void* _ctx) { UNUSED(_ctx); - osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR); + furi_thread_flags_set(input->thread_id, INPUT_THREAD_FLAG_ISR); } const char* input_get_key_name(InputKey key) { @@ -66,7 +66,7 @@ const char* input_get_type_name(InputType type) { int32_t input_srv() { input = malloc(sizeof(Input)); - input->thread = osThreadGetId(); + input->thread_id = furi_thread_get_current_id(); input->event_pubsub = furi_pubsub_alloc(); furi_record_create("input_events", input->event_pubsub); @@ -129,7 +129,7 @@ int32_t input_srv() { if(is_changing) { osDelay(1); } else { - osThreadFlagsWait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever); + furi_thread_flags_wait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever); } } diff --git a/applications/input/input_i.h b/applications/input/input_i.h index 4bd777ef..63a9c85a 100644 --- a/applications/input/input_i.h +++ b/applications/input/input_i.h @@ -32,7 +32,7 @@ typedef struct { /** Input state */ typedef struct { - osThreadId_t thread; + FuriThreadId thread_id; FuriPubSub* event_pubsub; InputPinState* pin_states; Cli* cli; diff --git a/applications/lfrfid/application.fam b/applications/lfrfid/application.fam new file mode 100644 index 00000000..8722bb4f --- /dev/null +++ b/applications/lfrfid/application.fam @@ -0,0 +1,26 @@ +App( + appid="lfrfid", + name="125 kHz RFID", + apptype=FlipperAppType.APP, + entry_point="lfrfid_app", + cdefines=["APP_LF_RFID"], + requires=[ + "gui", + "dialogs", + ], + provides=[ + "lfrfid_start", + "lfrfid_debug", + ], + icon="A_125khz_14", + stack_size=2 * 1024, + order=20, +) + +App( + appid="lfrfid_start", + apptype=FlipperAppType.STARTUP, + entry_point="lfrfid_on_system_start", + requires=["lfrfid"], + order=50, +) diff --git a/applications/lfrfid_debug/application.fam b/applications/lfrfid_debug/application.fam new file mode 100644 index 00000000..910f65cf --- /dev/null +++ b/applications/lfrfid_debug/application.fam @@ -0,0 +1,12 @@ +App( + appid="lfrfid_debug", + name="LF-RFID Debug", + apptype=FlipperAppType.DEBUG, + entry_point="lfrfid_debug_app", + requires=[ + "gui", + "lfrfid", + ], + stack_size=1 * 1024, + order=100, +) diff --git a/applications/loader/application.fam b/applications/loader/application.fam new file mode 100644 index 00000000..16351f8d --- /dev/null +++ b/applications/loader/application.fam @@ -0,0 +1,10 @@ +App( + appid="loader", + name="LoaderSrv", + apptype=FlipperAppType.SERVICE, + entry_point="loader_srv", + cdefines=["SRV_LOADER"], + requires=["gui"], + stack_size=1 * 1024, + order=90, +) diff --git a/applications/loader/loader.c b/applications/loader/loader.c index e5d59702..1acff8b7 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -29,13 +29,9 @@ static bool furi_thread_set_callback( loader_instance->application_thread, loader_instance->application->app); - bool result = furi_thread_start(loader_instance->application_thread); + furi_thread_start(loader_instance->application_thread); - if(!result) { - loader_instance->application = NULL; - } - - return result; + return true; } static void loader_menu_callback(void* _ctx, uint32_t index) { @@ -300,7 +296,7 @@ static Loader* loader_alloc() { UNUSED(loader_cli); #endif - instance->loader_thread = osThreadGetId(); + instance->loader_thread = furi_thread_get_current_id(); // Gui instance->gui = furi_record_open("gui"); @@ -444,7 +440,7 @@ static void loader_build_submenu() { void loader_show_menu() { furi_assert(loader_instance); - osThreadFlagsSet(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU); + furi_thread_flags_set(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU); } void loader_update_menu() { @@ -474,7 +470,8 @@ int32_t loader_srv(void* p) { #endif while(1) { - uint32_t flags = osThreadFlagsWait(LOADER_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + uint32_t flags = + furi_thread_flags_wait(LOADER_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); if(flags & LOADER_THREAD_FLAG_SHOW_MENU) { menu_set_selected_item(loader_instance->primary_menu, 0); view_dispatcher_switch_to_view( diff --git a/applications/loader/loader_i.h b/applications/loader/loader_i.h index 4c937b94..a311c6e8 100644 --- a/applications/loader/loader_i.h +++ b/applications/loader/loader_i.h @@ -15,7 +15,7 @@ #include struct Loader { - osThreadId_t loader_thread; + FuriThreadId loader_thread; const FlipperApplication* application; FuriThread* application_thread; diff --git a/applications/meta/application.fam b/applications/meta/application.fam new file mode 100644 index 00000000..a447b94a --- /dev/null +++ b/applications/meta/application.fam @@ -0,0 +1,41 @@ +App( + appid="basic_services", + name="Basic services", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "rpc", + "bt", + "desktop", + "loader", + "power", + ], +) + + +App( + appid="basic_apps", + name="Basic applications for main menu", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "gpio", + "ibutton", + "infrared", + "lfrfid", + "nfc", + "subghz", + "bad_usb", + "u2f", + ], +) + + +App( + appid="basic_plugins", + name="Basic applications for plug-in menu", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "music_player", + "snake_game", + "bt_hid", + ], +) diff --git a/applications/music_player/application.fam b/applications/music_player/application.fam new file mode 100644 index 00000000..70e29743 --- /dev/null +++ b/applications/music_player/application.fam @@ -0,0 +1,22 @@ +App( + appid="music_player", + name="Music Player", + apptype=FlipperAppType.PLUGIN, + entry_point="music_player_app", + cdefines=["APP_MUSIC_PLAYER"], + requires=[ + "gui", + "dialogs", + ], + provides=["music_player_start"], + stack_size=2 * 1024, + order=20, +) + +App( + appid="music_player_start", + apptype=FlipperAppType.STARTUP, + entry_point="music_player_on_system_start", + requires=["music_player"], + order=30, +) diff --git a/applications/nfc/application.fam b/applications/nfc/application.fam new file mode 100644 index 00000000..f43ed314 --- /dev/null +++ b/applications/nfc/application.fam @@ -0,0 +1,23 @@ +App( + appid="nfc", + name="NFC", + apptype=FlipperAppType.APP, + entry_point="nfc_app", + cdefines=["APP_NFC"], + requires=[ + "gui", + "dialogs", + ], + provides=["nfc_start"], + icon="A_NFC_14", + stack_size=4 * 1024, + order=30, +) + +App( + appid="nfc_start", + apptype=FlipperAppType.STARTUP, + entry_point="nfc_on_system_start", + requires=["nfc"], + order=30, +) diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index 51e14a6c..092d0089 100644 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -120,6 +120,12 @@ static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) } } if(!pages_saved) break; + + // Write authentication counter + uint32_t auth_counter = data->curr_authlim; + if(!flipper_format_write_uint32(file, "Failed authentication attempts", &auth_counter, 1)) + break; + saved = true; } while(false); @@ -169,6 +175,12 @@ bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { } } if(!pages_parsed) break; + + // Read authentication counter + uint32_t auth_counter; + if(!flipper_format_read_uint32(file, "Failed authentication attempts", &auth_counter, 1)) + auth_counter = 0; + parsed = true; } while(false); @@ -495,16 +507,17 @@ static bool nfc_device_save_mifare_df_data(FlipperFormat* file, NfcDevice* dev) n_apps++; } if(!flipper_format_write_uint32(file, "Application Count", &n_apps, 1)) break; - if(n_apps == 0) break; - tmp = malloc(n_apps * 3); - int i = 0; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - memcpy(tmp + i, app->id, 3); - i += 3; - } - if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - if(!nfc_device_save_mifare_df_app(file, app)) break; + if(n_apps) { + tmp = malloc(n_apps * 3); + int i = 0; + for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { + memcpy(tmp + i, app->id, 3); + i += 3; + } + if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break; + for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { + if(!nfc_device_save_mifare_df_app(file, app)) break; + } } saved = true; } while(false); @@ -532,32 +545,36 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { break; } } - data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); - memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); - if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) { - free(data->master_key_settings); - data->master_key_settings = NULL; - break; + if(flipper_format_key_exist(file, "PICC Change Key ID")) { + data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); + memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); + if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) { + free(data->master_key_settings); + data->master_key_settings = NULL; + break; + } } uint32_t n_apps; if(!flipper_format_read_uint32(file, "Application Count", &n_apps, 1)) break; - tmp = malloc(n_apps * 3); - if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break; - bool parsed_apps = true; - MifareDesfireApplication** app_head = &data->app_head; - for(uint32_t i = 0; i < n_apps; i++) { - MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication)); - memset(app, 0, sizeof(MifareDesfireApplication)); - memcpy(app->id, &tmp[i * 3], 3); - if(!nfc_device_load_mifare_df_app(file, app)) { - free(app); - parsed_apps = false; - break; + if(n_apps) { + tmp = malloc(n_apps * 3); + if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break; + bool parsed_apps = true; + MifareDesfireApplication** app_head = &data->app_head; + for(uint32_t i = 0; i < n_apps; i++) { + MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication)); + memset(app, 0, sizeof(MifareDesfireApplication)); + memcpy(app->id, &tmp[i * 3], 3); + if(!nfc_device_load_mifare_df_app(file, app)) { + free(app); + parsed_apps = false; + break; + } + *app_head = app; + app_head = &app->next; } - *app_head = app; - app_head = &app->next; + if(!parsed_apps) break; } - if(!parsed_apps) break; parsed = true; } while(false); diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 8c8512f3..176b15c6 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -319,11 +319,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { MfUltralightEmulator emulator = {}; mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data); while(nfc_worker->state == NfcWorkerStateEmulateMifareUltralight) { - emulator.auth_success = false; - if(emulator.data.type >= MfUltralightTypeNTAGI2C1K) { - // Sector index needs to be reset - emulator.curr_sector = 0; - } + mf_ul_reset_emulation(&emulator, true); furi_hal_nfc_emulate_nfca( nfc_data->uid, nfc_data->uid_len, @@ -576,28 +572,27 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); free(data->master_key_settings); data->master_key_settings = NULL; - continue; - } - - MifareDesfireKeyVersion** key_version_head = - &data->master_key_settings->key_version_head; - for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { - tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting key version"); - continue; + } else { + MifareDesfireKeyVersion** key_version_head = + &data->master_key_settings->key_version_head; + for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { + tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); + if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { + FURI_LOG_W(TAG, "Bad exchange getting key version"); + continue; + } + MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); + memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); + key_version->id = key_id; + if(!mf_df_parse_get_key_version_response( + tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { + FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); + free(key_version); + continue; + } + *key_version_head = key_version; + key_version_head = &key_version->next; } - MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); - memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); - key_version->id = key_id; - if(!mf_df_parse_get_key_version_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { - FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); - free(key_version); - continue; - } - *key_version_head = key_version; - key_version_head = &key_version->next; } } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c index 275e9b86..4b3be9e1 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c @@ -37,7 +37,7 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { // Add card name widget_add_string_element( nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name); - // Add cad number + // Add card number string_t pan_str; string_init(pan_str); for(uint8_t i = 0; i < emv_data->number_len; i += 2) { diff --git a/applications/notification/application.fam b/applications/notification/application.fam new file mode 100644 index 00000000..be730d51 --- /dev/null +++ b/applications/notification/application.fam @@ -0,0 +1,21 @@ +App( + appid="notification", + name="NotificationSrv", + apptype=FlipperAppType.SERVICE, + entry_point="notification_srv", + cdefines=["SRV_NOTIFICATION"], + requires=["input"], + provides=["notification_settings"], + stack_size=int(1.5 * 1024), + order=100, +) + +App( + appid="notification_settings", + name="LCD and Notifications", + apptype=FlipperAppType.SETTINGS, + entry_point="notification_settings_app", + requires=["notification"], + stack_size=1 * 1024, + order=20, +) diff --git a/applications/notification/notification_messages.c b/applications/notification/notification_messages.c index b14c08e3..b469cb5f 100644 --- a/applications/notification/notification_messages.c +++ b/applications/notification/notification_messages.c @@ -335,6 +335,15 @@ const NotificationSequence sequence_set_blue_255 = { NULL, }; +// Solid colors +const NotificationSequence sequence_solid_yellow = { + &message_red_255, + &message_green_255, + &message_blue_0, + &message_do_not_reset, + NULL, +}; + // Blink const NotificationSequence sequence_blink_blue_10 = { &message_blue_255, diff --git a/applications/notification/notification_messages.h b/applications/notification/notification_messages.h index a0ef654e..92a105f6 100644 --- a/applications/notification/notification_messages.h +++ b/applications/notification/notification_messages.h @@ -103,6 +103,9 @@ extern const NotificationSequence sequence_set_red_255; extern const NotificationSequence sequence_set_green_255; extern const NotificationSequence sequence_set_blue_255; +// Solid colors +extern const NotificationSequence sequence_solid_yellow; + // Blink extern const NotificationSequence sequence_blink_blue_10; extern const NotificationSequence sequence_blink_red_10; diff --git a/applications/power/application.fam b/applications/power/application.fam new file mode 100644 index 00000000..1e503749 --- /dev/null +++ b/applications/power/application.fam @@ -0,0 +1,53 @@ +App( + appid="power", + name="PowerSrv", + apptype=FlipperAppType.SERVICE, + entry_point="power_srv", + cdefines=["SRV_POWER"], + requires=[ + "gui", + "cli", + ], + provides=[ + "power_settings", + "power_start", + ], + stack_size=1 * 1024, + order=110, +) + +App( + appid="power_settings", + name="Power", + apptype=FlipperAppType.SETTINGS, + entry_point="power_settings_app", + requires=[ + "gui", + "power", + ], + flags=["InsomniaSafe"], + stack_size=1 * 1024, + order=40, +) + +App( + appid="power_start", + apptype=FlipperAppType.STARTUP, + entry_point="power_on_system_start", + requires=["power"], + order=80, +) + +App( + appid="battery_test", + name="Battery Test", + apptype=FlipperAppType.DEBUG, + entry_point="battery_test_app", + cdefines=["APP_BATTERY_TEST"], + requires=[ + "gui", + "power", + ], + stack_size=1 * 1024, + order=130, +) diff --git a/applications/rpc/application.fam b/applications/rpc/application.fam new file mode 100644 index 00000000..683396e3 --- /dev/null +++ b/applications/rpc/application.fam @@ -0,0 +1,12 @@ +App( + appid="rpc", + name="RpcSrv", + apptype=FlipperAppType.SERVICE, + entry_point="rpc_srv", + cdefines=["SRV_RPC"], + requires=[ + "cli", + ], + stack_size=4 * 1024, + order=10, +) diff --git a/applications/rpc/rpc.c b/applications/rpc/rpc.c index 7d51defd..c974a0e5 100644 --- a/applications/rpc/rpc.c +++ b/applications/rpc/rpc.c @@ -408,7 +408,7 @@ size_t furi_assert(session); size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout); - osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtNewData); + furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData); return bytes_sent; } @@ -441,7 +441,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { if(count == bytes_received) { break; } else { - flags = osThreadFlagsWait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever); + flags = furi_thread_flags_wait(RPC_ALL_EVENTS, osFlagsWaitAny, osWaitForever); if(flags & RpcEvtDisconnect) { if(xStreamBufferIsEmpty(session->stream)) { session->terminate = true; @@ -450,7 +450,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { break; } else { /* Save disconnect flag and continue reading buffer */ - osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect); } } else if(flags & RpcEvtNewData) { // Just wake thread up @@ -643,7 +643,7 @@ void rpc_session_close(RpcSession* session) { rpc_session_set_send_bytes_callback(session, NULL); rpc_session_set_close_callback(session, NULL); rpc_session_set_buffer_is_empty_callback(session, NULL); - osThreadFlagsSet(furi_thread_get_thread_id(session->thread), RpcEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect); } int32_t rpc_srv(void* p) { diff --git a/applications/rpc/rpc_gui.c b/applications/rpc/rpc_gui.c index f390d983..da91ae06 100644 --- a/applications/rpc/rpc_gui.c +++ b/applications/rpc/rpc_gui.c @@ -40,8 +40,7 @@ static void memcpy(buffer, data, size); - osThreadFlagsSet( - furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit); + furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagTransmit); } static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context) { @@ -50,7 +49,8 @@ static int32_t rpc_system_gui_screen_stream_frame_transmit_thread(void* context) RpcGuiSystem* rpc_gui = (RpcGuiSystem*)context; while(true) { - uint32_t flags = osThreadFlagsWait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever); + uint32_t flags = + furi_thread_flags_wait(RpcGuiWorkerFlagAny, osFlagsWaitAny, osWaitForever); if(flags & RpcGuiWorkerFlagTransmit) { rpc_send(rpc_gui->session, rpc_gui->transmit_frame); } @@ -117,8 +117,7 @@ static void rpc_system_gui_stop_screen_stream_process(const PB_Main* request, vo gui_remove_framebuffer_callback( rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context); // Stop and release worker thread - osThreadFlagsSet( - furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit); + furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit); furi_thread_join(rpc_gui->transmit_thread); furi_thread_free(rpc_gui->transmit_thread); // Release frame @@ -367,8 +366,7 @@ void rpc_system_gui_free(void* context) { gui_remove_framebuffer_callback( rpc_gui->gui, rpc_system_gui_screen_stream_frame_callback, context); // Stop and release worker thread - osThreadFlagsSet( - furi_thread_get_thread_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit); + furi_thread_flags_set(furi_thread_get_id(rpc_gui->transmit_thread), RpcGuiWorkerFlagExit); furi_thread_join(rpc_gui->transmit_thread); furi_thread_free(rpc_gui->transmit_thread); // Release frame diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index e6a59ea8..336346b5 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -10,6 +10,7 @@ #include "storage/storage.h" #include #include +#include #include #define TAG "RpcStorage" @@ -245,18 +246,23 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex FileInfo fileinfo; char* name = malloc(MAX_NAME_LENGTH + 1); if(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { - if(i == COUNT_OF(list->file)) { - list->file_count = i; - response.has_next = true; - rpc_send_and_release(session, &response); - i = 0; + if(path_contains_only_ascii(name)) { + if(i == COUNT_OF(list->file)) { + list->file_count = i; + response.has_next = true; + rpc_send_and_release(session, &response); + i = 0; + } + list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? + PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; + list->file[i].size = fileinfo.size; + list->file[i].data = NULL; + list->file[i].name = name; + ++i; + } else { + free(name); } - list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? PB_Storage_File_FileType_DIR : - PB_Storage_File_FileType_FILE; - list->file[i].size = fileinfo.size; - list->file[i].data = NULL; - list->file[i].name = name; - ++i; } else { list->file_count = i; finish = true; @@ -345,6 +351,14 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte bool result = true; + if(!path_contains_only_ascii(request->content.storage_write_request.path)) { + rpc_storage->current_command_id = request->command_id; + rpc_send_and_release_empty( + session, rpc_storage->current_command_id, PB_CommandStatus_ERROR_STORAGE_INVALID_NAME); + rpc_system_storage_reset_state(rpc_storage, session, false); + return; + } + if((request->command_id != rpc_storage->current_command_id) && (rpc_storage->state == RpcStorageStateWriting)) { rpc_system_storage_reset_state(rpc_storage, session, true); @@ -384,13 +398,18 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte static bool rpc_system_storage_is_dir_is_empty(Storage* fs_api, const char* path) { FileInfo fileinfo; - bool is_dir_is_empty = false; + bool is_dir_is_empty = true; FS_Error error = storage_common_stat(fs_api, path, &fileinfo); if((error == FSE_OK) && (fileinfo.flags & FSF_DIRECTORY)) { File* dir = storage_file_alloc(fs_api); if(storage_dir_open(dir, path)) { char* name = malloc(MAX_NAME_LENGTH); - is_dir_is_empty = !storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH); + while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { + if(path_contains_only_ascii(name)) { + is_dir_is_empty = false; + break; + } + } free(name); } storage_dir_close(dir); @@ -458,8 +477,12 @@ static void rpc_system_storage_mkdir_process(const PB_Main* request, void* conte Storage* fs_api = furi_record_open("storage"); char* path = request->content.storage_mkdir_request.path; if(path) { - FS_Error error = storage_common_mkdir(fs_api, path); - status = rpc_system_storage_get_error(error); + if(path_contains_only_ascii(path)) { + FS_Error error = storage_common_mkdir(fs_api, path); + status = rpc_system_storage_get_error(error); + } else { + status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME; + } } else { status = PB_CommandStatus_ERROR_INVALID_PARAMETERS; } @@ -551,11 +574,15 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont Storage* fs_api = furi_record_open("storage"); - FS_Error error = storage_common_rename( - fs_api, - request->content.storage_rename_request.old_path, - request->content.storage_rename_request.new_path); - status = rpc_system_storage_get_error(error); + if(path_contains_only_ascii(request->content.storage_rename_request.new_path)) { + FS_Error error = storage_common_rename( + fs_api, + request->content.storage_rename_request.old_path, + request->content.storage_rename_request.new_path); + status = rpc_system_storage_get_error(error); + } else { + status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME; + } furi_record_close("storage"); rpc_send_and_release_empty(session, request->command_id, status); diff --git a/applications/snake_game/application.fam b/applications/snake_game/application.fam new file mode 100644 index 00000000..5d6ad527 --- /dev/null +++ b/applications/snake_game/application.fam @@ -0,0 +1,11 @@ +App( + appid="snake_game", + name="Snake Game", + apptype=FlipperAppType.PLUGIN, + entry_point="snake_game_app", + cdefines=["APP_SNAKE_GAME"], + requires=["gui"], + stack_size=1 * 1024, + icon="A_Plugins_14", + order=30, +) diff --git a/applications/storage/application.fam b/applications/storage/application.fam new file mode 100644 index 00000000..21089635 --- /dev/null +++ b/applications/storage/application.fam @@ -0,0 +1,19 @@ +App( + appid="storage", + name="StorageSrv", + apptype=FlipperAppType.SERVICE, + entry_point="storage_srv", + cdefines=["SRV_STORAGE"], + requires=["storage_settings"], + provides=["storage_start"], + stack_size=3 * 1024, + order=120, +) + +App( + appid="storage_start", + apptype=FlipperAppType.STARTUP, + entry_point="storage_on_system_start", + requires=["storage"], + order=90, +) diff --git a/applications/storage_settings/application.fam b/applications/storage_settings/application.fam new file mode 100644 index 00000000..1ba0ccd4 --- /dev/null +++ b/applications/storage_settings/application.fam @@ -0,0 +1,9 @@ +App( + appid="storage_settings", + name="Storage", + apptype=FlipperAppType.SETTINGS, + entry_point="storage_settings_app", + requires=["storage"], + stack_size=2 * 1024, + order=30, +) diff --git a/applications/subghz/application.fam b/applications/subghz/application.fam new file mode 100644 index 00000000..7d31ecae --- /dev/null +++ b/applications/subghz/application.fam @@ -0,0 +1,24 @@ +App( + appid="subghz", + name="Sub-GHz", + apptype=FlipperAppType.APP, + entry_point="subghz_app", + cdefines=["APP_SUBGHZ"], + requires=[ + "gui", + "cli", + "dialogs", + ], + provides=["subghz_start"], + icon="A_Sub1ghz_14", + stack_size=2 * 1024, + order=10, +) + +App( + appid="subghz_start", + apptype=FlipperAppType.STARTUP, + entry_point="subghz_on_system_start", + requires=["subghz"], + order=40, +) diff --git a/applications/subghz/helpers/subghz_chat.c b/applications/subghz/helpers/subghz_chat.c index e6b7b7bc..7a359165 100644 --- a/applications/subghz/helpers/subghz_chat.c +++ b/applications/subghz/helpers/subghz_chat.c @@ -92,7 +92,9 @@ bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency) { instance->worker_running = true; instance->last_time_rx_data = 0; - res = furi_thread_start(instance->thread); + furi_thread_start(instance->thread); + + res = true; } return res; } diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c index 69e59759..43acf034 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -67,7 +67,8 @@ static uint32_t subghz_frequency_analyzer_worker_expRunningAverageAdaptive( static int32_t subghz_frequency_analyzer_worker_thread(void* context) { SubGhzFrequencyAnalyzerWorker* instance = context; - FrequencyRSSI frequency_rssi = {.frequency = 0, .rssi = 0}; + FrequencyRSSI frequency_rssi = { + .frequency_coarse = 0, .rssi_coarse = 0, .frequency_fine = 0, .rssi_fine = 0}; float rssi = 0; uint32_t frequency = 0; CC1101Status status; @@ -105,7 +106,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { float rssi_avg = 0; size_t rssi_avg_samples = 0; - frequency_rssi.rssi = -127.0f; + frequency_rssi.rssi_coarse = -127.0f; + frequency_rssi.rssi_fine = -127.0f; furi_hal_subghz_idle(); subghz_frequency_analyzer_worker_load_registers(subghz_preset_ook_650khz); @@ -137,9 +139,9 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { if(rssi < rssi_min) rssi_min = rssi; - if(frequency_rssi.rssi < rssi) { - frequency_rssi.rssi = rssi; - frequency_rssi.frequency = frequency; + if(frequency_rssi.rssi_coarse < rssi) { + frequency_rssi.rssi_coarse = rssi; + frequency_rssi.frequency_coarse = frequency; } } } @@ -148,20 +150,17 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { TAG, "RSSI: avg %f, max %f at %u, min %f", (double)(rssi_avg / rssi_avg_samples), - (double)frequency_rssi.rssi, - frequency_rssi.frequency, + (double)frequency_rssi.rssi_coarse, + frequency_rssi.frequency_coarse, (double)rssi_min); // Second stage: fine scan - if(frequency_rssi.rssi > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) { - FURI_LOG_D(TAG, "~:%u:%f", frequency_rssi.frequency, (double)frequency_rssi.rssi); - - frequency_rssi.rssi = -127.0; + if(frequency_rssi.rssi_coarse > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) { furi_hal_subghz_idle(); subghz_frequency_analyzer_worker_load_registers(subghz_preset_ook_58khz); - //-0.3 ... 433.92 ... +0.3 step 10KHz - for(uint32_t i = frequency_rssi.frequency - 300000; - i < frequency_rssi.frequency + 300000; + //for example -0.3 ... 433.92 ... +0.3 step 20KHz + for(uint32_t i = frequency_rssi.frequency_coarse - 300000; + i < frequency_rssi.frequency_coarse + 300000; i += 20000) { if(furi_hal_subghz_is_frequency_valid(i)) { furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); @@ -183,28 +182,51 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { FURI_LOG_T(TAG, "#:%u:%f", frequency, (double)rssi); - if(frequency_rssi.rssi < rssi) { - frequency_rssi.rssi = rssi; - frequency_rssi.frequency = frequency; + if(frequency_rssi.rssi_fine < rssi) { + frequency_rssi.rssi_fine = rssi; + frequency_rssi.frequency_fine = frequency; } } } } - // Deliver results - if(frequency_rssi.rssi > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) { - FURI_LOG_D(TAG, "=:%u:%f", frequency_rssi.frequency, (double)frequency_rssi.rssi); + // Deliver results fine + if(frequency_rssi.rssi_fine > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) { + FURI_LOG_D( + TAG, "=:%u:%f", frequency_rssi.frequency_fine, (double)frequency_rssi.rssi_fine); instance->sample_hold_counter = 20; if(instance->filVal) { - frequency_rssi.frequency = + frequency_rssi.frequency_fine = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( - instance, frequency_rssi.frequency); + instance, frequency_rssi.frequency_fine); } // Deliver callback if(instance->pair_callback) { instance->pair_callback( - instance->context, frequency_rssi.frequency, frequency_rssi.rssi); + instance->context, frequency_rssi.frequency_fine, frequency_rssi.rssi_fine); + } + } else if( // Deliver results coarse + (frequency_rssi.rssi_coarse > SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) && + (instance->sample_hold_counter < 10)) { + FURI_LOG_D( + TAG, + "~:%u:%f", + frequency_rssi.frequency_coarse, + (double)frequency_rssi.rssi_coarse); + + instance->sample_hold_counter = 20; + if(instance->filVal) { + frequency_rssi.frequency_coarse = + subghz_frequency_analyzer_worker_expRunningAverageAdaptive( + instance, frequency_rssi.frequency_coarse); + } + // Deliver callback + if(instance->pair_callback) { + instance->pair_callback( + instance->context, + frequency_rssi.frequency_coarse, + frequency_rssi.rssi_coarse); } } else { if(instance->sample_hold_counter > 0) { diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.h b/applications/subghz/helpers/subghz_frequency_analyzer_worker.h index 424270a0..50687c76 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.h +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.h @@ -9,8 +9,10 @@ typedef void ( *SubGhzFrequencyAnalyzerWorkerPairCallback)(void* context, uint32_t frequency, float rssi); typedef struct { - uint32_t frequency; - float rssi; + uint32_t frequency_coarse; + float rssi_coarse; + uint32_t frequency_fine; + float rssi_fine; } FrequencyRSSI; /** Allocate SubGhzFrequencyAnalyzerWorker diff --git a/applications/subghz/scenes/subghz_scene_save_success.c b/applications/subghz/scenes/subghz_scene_save_success.c index 53cd93ce..3d5c16ca 100644 --- a/applications/subghz/scenes/subghz_scene_save_success.c +++ b/applications/subghz/scenes/subghz_scene_save_success.c @@ -1,6 +1,6 @@ #include "../subghz_i.h" #include "../helpers/subghz_custom_event.h" -#include "dolphin/helpers/dolphin_deed.h" +#include #include void subghz_scene_save_success_popup_callback(void* context) { diff --git a/applications/system/application.fam b/applications/system/application.fam new file mode 100644 index 00000000..0fc456b2 --- /dev/null +++ b/applications/system/application.fam @@ -0,0 +1,9 @@ +App( + appid="system_settings", + name="System", + apptype=FlipperAppType.SETTINGS, + entry_point="system_settings_app", + requires=["gui"], + stack_size=1 * 1024, + order=70, +) diff --git a/applications/u2f/application.fam b/applications/u2f/application.fam new file mode 100644 index 00000000..6b32e022 --- /dev/null +++ b/applications/u2f/application.fam @@ -0,0 +1,14 @@ +App( + appid="u2f", + name="U2F", + apptype=FlipperAppType.APP, + entry_point="u2f_app", + cdefines=["APP_U2F"], + requires=[ + "gui", + "dialogs", + ], + stack_size=2 * 1024, + icon="A_U2F_14", + order=80, +) diff --git a/applications/u2f/u2f_hid.c b/applications/u2f/u2f_hid.c index a2b291d6..581feadb 100644 --- a/applications/u2f/u2f_hid.c +++ b/applications/u2f/u2f_hid.c @@ -72,18 +72,18 @@ static void u2f_hid_event_callback(HidU2fEvent ev, void* context) { U2fHid* u2f_hid = context; if(ev == HidU2fDisconnected) - osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtDisconnect); + furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtDisconnect); else if(ev == HidU2fConnected) - osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtConnect); + furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtConnect); else if(ev == HidU2fRequest) - osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtRequest); + furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtRequest); } static void u2f_hid_lock_timeout_callback(void* context) { furi_assert(context); U2fHid* u2f_hid = context; - osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtUnlock); + furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtUnlock); } static void u2f_hid_send_response(U2fHid* u2f_hid) { @@ -198,7 +198,7 @@ static int32_t u2f_hid_worker(void* context) { furi_hal_hid_u2f_set_callback(u2f_hid_event_callback, u2f_hid); while(1) { - uint32_t flags = osThreadFlagsWait( + uint32_t flags = furi_thread_flags_wait( WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest, osFlagsWaitAny, osWaitForever); @@ -292,7 +292,7 @@ U2fHid* u2f_hid_start(U2fData* u2f_inst) { void u2f_hid_stop(U2fHid* u2f_hid) { furi_assert(u2f_hid); - osThreadFlagsSet(furi_thread_get_thread_id(u2f_hid->thread), WorkerEvtStop); + furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtStop); furi_thread_join(u2f_hid->thread); furi_thread_free(u2f_hid->thread); free(u2f_hid); diff --git a/applications/unit_tests/application.fam b/applications/unit_tests/application.fam new file mode 100644 index 00000000..54e6feae --- /dev/null +++ b/applications/unit_tests/application.fam @@ -0,0 +1,18 @@ +App( + appid="unit_tests", + apptype=FlipperAppType.STARTUP, + entry_point="unit_tests_on_system_start", + cdefines=["APP_UNIT_TESTS"], + provides=["delay_test"], + order=100, +) + +App( + appid="delay_test", + name="Delay Test", + apptype=FlipperAppType.DEBUG, + entry_point="delay_test_app", + stack_size=1 * 1024, + requires=["unit_tests"], + order=110, +) diff --git a/applications/unit_tests/furi_valuemutex_test.c b/applications/unit_tests/furi_valuemutex_test.c index 4deb4f61..12613239 100644 --- a/applications/unit_tests/furi_valuemutex_test.c +++ b/applications/unit_tests/furi_valuemutex_test.c @@ -40,91 +40,3 @@ void test_furi_valuemutex() { mu_check(delete_mutex(&valuemutex)); } - -/* -TEST: concurrent access - -1. Create holding record -2. Open it twice -3. Change value simultaneously in two app and check integrity -*/ - -// TODO this test broke because mutex in furi is not implemented - -typedef struct { - // a and b must be equal - uint8_t a; - uint8_t b; -} ConcurrentValue; - -void furi_concurent_app(void* p) { - ValueMutex* mutex = (ValueMutex*)p; - if(mutex == NULL) { - printf("cannot open mutex\r\n"); - osThreadExit(); - } - - for(size_t i = 0; i < 10; i++) { - ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(mutex); - - if(value == NULL) { - printf("cannot take record\r\n"); - release_mutex(mutex, value); - osThreadExit(); - } - - // emulate read-modify-write broken by context switching - uint8_t a = value->a; - uint8_t b = value->b; - a++; - b++; - furi_hal_delay_ms(2); - value->a = a; - value->b = b; - release_mutex(mutex, value); - } - - osThreadExit(); -} - -void test_furi_concurrent_access() { - // TODO: reimplement or delete test - return; - /* - // 1. Create holding record - ConcurrentValue value = {.a = 0, .b = 0}; - ValueMutex mutex; - mu_check(init_mutex(&mutex, &value, sizeof(value))); - - // 3. Create second app for interact with it - FuriApp* second_app = furiac_start(furi_concurent_app, "furi concurent app", (void*)&mutex); - - // 4. multiply ConcurrentValue::a - for(size_t i = 0; i < 4; i++) { - ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(&mutex); - - if(value == NULL) { - release_mutex(&mutex, value); - mu_fail("cannot take record\r\n"); - } - - // emulate read-modify-write broken by context switching - uint8_t a = value->a; - uint8_t b = value->b; - a++; - b++; - value->a = a; - furi_hal_delay_ms(10); // this is only for test, do not add delay between take/give in prod! - value->b = b; - release_mutex(&mutex, value); - } - - furi_hal_delay_ms(50); - - mu_assert_pointers_eq(second_app->handler, NULL); - - mu_assert_int_eq(value.a, value.b); - - mu_check(delete_mutex(&mutex)); - */ -} diff --git a/applications/unit_tests/minunit_test.c b/applications/unit_tests/minunit_test.c index 1e71fd07..9d564df6 100644 --- a/applications/unit_tests/minunit_test.c +++ b/applications/unit_tests/minunit_test.c @@ -33,10 +33,6 @@ MU_TEST(mu_test_furi_valuemutex) { test_furi_valuemutex(); } -MU_TEST(mu_test_furi_concurrent_access) { - test_furi_concurrent_access(); -} - MU_TEST(mu_test_furi_pubsub) { test_furi_pubsub(); } @@ -55,7 +51,6 @@ MU_TEST_SUITE(test_suite) { // v2 tests MU_RUN_TEST(mu_test_furi_create_open); MU_RUN_TEST(mu_test_furi_valuemutex); - MU_RUN_TEST(mu_test_furi_concurrent_access); MU_RUN_TEST(mu_test_furi_pubsub); MU_RUN_TEST(mu_test_furi_memmgr); } diff --git a/applications/unit_tests/rpc/rpc_test.c b/applications/unit_tests/rpc/rpc_test.c index 2f97343e..ca894cb4 100644 --- a/applications/unit_tests/rpc/rpc_test.c +++ b/applications/unit_tests/rpc/rpc_test.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -495,7 +496,7 @@ static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) { case PB_Main_storage_list_response_tag: { size_t expected_msg_files = expected->content.storage_list_response.file_count; size_t result_msg_files = result->content.storage_list_response.file_count; - mu_check(result_msg_files == expected_msg_files); + mu_assert_int_eq(expected_msg_files, result_msg_files); for(size_t i = 0; i < expected_msg_files; ++i) { PB_Storage_File* result_msg_file = &result->content.storage_list_response.file[i]; PB_Storage_File* expected_msg_file = &expected->content.storage_list_response.file[i]; @@ -603,13 +604,17 @@ static void test_rpc_storage_list_create_expected_list( MsgList_push_back(msg_list, response); i = 0; } - list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? PB_Storage_File_FileType_DIR : - PB_Storage_File_FileType_FILE; - list->file[i].size = fileinfo.size; - list->file[i].data = NULL; - /* memory free inside rpc_encode_and_send() -> pb_release() */ - list->file[i].name = name; - ++i; + + if(path_contains_only_ascii(name)) { + list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? + PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; + list->file[i].size = fileinfo.size; + list->file[i].data = NULL; + /* memory free inside rpc_encode_and_send() -> pb_release() */ + list->file[i].name = name; + ++i; + } } else { finish = true; free(name); diff --git a/applications/unit_tests/storage/storage_test.c b/applications/unit_tests/storage/storage_test.c index 9f237bd0..db78583d 100644 --- a/applications/unit_tests/storage/storage_test.c +++ b/applications/unit_tests/storage/storage_test.c @@ -49,7 +49,7 @@ MU_TEST(storage_file_open_lock) { furi_thread_set_stack_size(locker_thread, 2048); furi_thread_set_context(locker_thread, semaphore); furi_thread_set_callback(locker_thread, storage_file_locker); - mu_check(furi_thread_start(locker_thread)); + furi_thread_start(locker_thread); // wait for file lock osSemaphoreAcquire(semaphore, osWaitForever); @@ -139,7 +139,7 @@ MU_TEST(storage_dir_open_lock) { furi_thread_set_stack_size(locker_thread, 2048); furi_thread_set_context(locker_thread, semaphore); furi_thread_set_callback(locker_thread, storage_dir_locker); - mu_check(furi_thread_start(locker_thread)); + furi_thread_start(locker_thread); // wait for dir lock osSemaphoreAcquire(semaphore, osWaitForever); diff --git a/applications/unit_tests/subghz/subghz_test.c b/applications/unit_tests/subghz/subghz_test.c index c8f23780..fea407ed 100644 --- a/applications/unit_tests/subghz/subghz_test.c +++ b/applications/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME "/ext/subghz/assets/came_atomo" #define NICE_FLOR_S_DIR_NAME "/ext/subghz/assets/nice_flor_s" #define TEST_RANDOM_DIR_NAME "/ext/unit_tests/subghz/test_random_raw.sub" -#define TEST_RANDOM_COUNT_PARSE 113 +#define TEST_RANDOM_COUNT_PARSE 119 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -75,7 +75,7 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); // Yield, to load data inside the worker - osThreadYield(); + furi_thread_yield(); decoder->protocol->decoder->feed(decoder, level, duration); } else { break; @@ -115,7 +115,7 @@ static bool subghz_decode_random_test(const char* path) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); // Yield, to load data inside the worker - osThreadYield(); + furi_thread_yield(); subghz_receiver_decode(receiver_handler, level, duration); } else { break; @@ -361,6 +361,13 @@ MU_TEST(subghz_decoder_holtek_test) { "Test decoder " SUBGHZ_PROTOCOL_HOLTEK_NAME " error\r\n"); } +MU_TEST(subghz_decoder_power_smart_test) { + mu_assert( + subghz_decoder_test( + "/ext/unit_tests/subghz/power_smart_raw.sub", SUBGHZ_PROTOCOL_POWER_SMART_NAME), + "Test decoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -428,6 +435,12 @@ MU_TEST(subghz_encoder_secplus_v2_test) { "Test encoder " SUBGHZ_PROTOCOL_SECPLUS_V2_NAME " error\r\n"); } +MU_TEST(subghz_encoder_power_smart_test) { + mu_assert( + subghz_encoder_test("/ext/unit_tests/subghz/power_smart.sub"), + "Test encoder " SUBGHZ_PROTOCOL_POWER_SMART_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -459,6 +472,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_secplus_v1_test); MU_RUN_TEST(subghz_decoder_secplus_v2_test); MU_RUN_TEST(subghz_decoder_holtek_test); + MU_RUN_TEST(subghz_decoder_power_smart_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -471,6 +485,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_holtek_test); MU_RUN_TEST(subghz_encoder_secplus_v1_test); MU_RUN_TEST(subghz_encoder_secplus_v2_test); + MU_RUN_TEST(subghz_encoder_power_smart_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/applications/unit_tests/test_index.c b/applications/unit_tests/test_index.c index a1acbed4..d8a8174c 100644 --- a/applications/unit_tests/test_index.c +++ b/applications/unit_tests/test_index.c @@ -32,7 +32,7 @@ void minunit_print_progress(void) { } void minunit_print_fail(const char* str) { - printf(FURI_LOG_CLR_E "%s\n" FURI_LOG_CLR_RESET, str); + printf(FURI_LOG_CLR_E "%s\r\n" FURI_LOG_CLR_RESET, str); } void unit_tests_cli(Cli* cli, string_t args, void* context) { diff --git a/applications/updater/application.fam b/applications/updater/application.fam new file mode 100644 index 00000000..a693fa6f --- /dev/null +++ b/applications/updater/application.fam @@ -0,0 +1,39 @@ +App( + appid="updater", + name="UpdaterSrv", + apptype=FlipperAppType.SERVICE, + cdefines=["SRV_UPDATER"], + requires=[ + "gui", + "storage", + ], + conflicts=["desktop"], + entry_point="updater_srv", + stack_size=2 * 1024, + order=130, +) + +App( + appid="updater_app", + name="UpdaterApp", + apptype=FlipperAppType.SYSTEM, + cdefines=["APP_UPDATER"], + requires=[ + "gui", + "storage", + "bt", + ], + conflicts=["updater"], + provides=["updater_start"], + entry_point="updater_srv", + stack_size=2 * 1024, + order=10, +) + +App( + appid="updater_start", + apptype=FlipperAppType.STARTUP, + entry_point="updater_on_system_start", + requires=["updater_app"], + order=110, +) diff --git a/applications/updater/scenes/updater_scene_loadcfg.c b/applications/updater/scenes/updater_scene_loadcfg.c index 8e477b14..1fd87d00 100644 --- a/applications/updater/scenes/updater_scene_loadcfg.c +++ b/applications/updater/scenes/updater_scene_loadcfg.c @@ -29,14 +29,16 @@ void updater_scene_loadcfg_on_enter(void* context) { widget_add_string_element( updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update"); - widget_add_string_multiline_element( + widget_add_text_box_element( updater->widget, - 64, + 5, + 20, + 118, 32, AlignCenter, AlignCenter, - FontSecondary, - string_get_cstr(pending_upd->manifest->version)); + string_get_cstr(pending_upd->manifest->version), + true); widget_add_button_element( updater->widget, diff --git a/applications/updater/util/update_task.c b/applications/updater/util/update_task.c index fd2344c1..316fe680 100644 --- a/applications/updater/util/update_task.c +++ b/applications/updater/util/update_task.c @@ -24,6 +24,7 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageLfsBackup] = "Backing up LFS", [UpdateTaskStageLfsRestore] = "Restoring LFS", [UpdateTaskStageResourcesUpdate] = "Updating resources", + [UpdateTaskStageSplashscreenInstall] = "Installing splashscreen", [UpdateTaskStageCompleted] = "Restarting...", [UpdateTaskStageError] = "Error", [UpdateTaskStageOBError] = "OB, report", @@ -41,13 +42,13 @@ static const UpdateTaskStageGroupMap update_task_stage_progress[] = { [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5), - [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 30), + [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15), - [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 30), + [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 10), [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 50), - [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 100), - [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 5), - [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 70), + [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 90), + [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 15), + [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10), @@ -58,6 +59,7 @@ static const UpdateTaskStageGroupMap update_task_stage_progress[] = { [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30), [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255), + [UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5), [UpdateTaskStageCompleted] = STAGE_DEF(UpdateTaskStageGroupMisc, 1), [UpdateTaskStageError] = STAGE_DEF(UpdateTaskStageGroupMisc, 1), @@ -79,6 +81,9 @@ static UpdateTaskStageGroup update_task_get_task_groups(UpdateTask* update_task) if(!string_empty_p(manifest->resource_bundle)) { ret |= UpdateTaskStageGroupResources; } + if(!string_empty_p(manifest->splash_file)) { + ret |= UpdateTaskStageGroupSplashscreen; + } return ret; } @@ -324,9 +329,9 @@ void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, v update_task->status_change_cb_state = state; } -bool update_task_start(UpdateTask* update_task) { +void update_task_start(UpdateTask* update_task) { furi_assert(update_task); - return furi_thread_start(update_task->thread); + furi_thread_start(update_task->thread); } bool update_task_is_running(UpdateTask* update_task) { diff --git a/applications/updater/util/update_task.h b/applications/updater/util/update_task.h index cfbbb850..1f291556 100644 --- a/applications/updater/util/update_task.h +++ b/applications/updater/util/update_task.h @@ -33,6 +33,7 @@ typedef enum { UpdateTaskStageLfsRestore, UpdateTaskStageResourcesUpdate, + UpdateTaskStageSplashscreenInstall, UpdateTaskStageCompleted, UpdateTaskStageError, @@ -52,6 +53,7 @@ typedef enum { UpdateTaskStageGroupRadio = 1 << 4, UpdateTaskStageGroupPostUpdate = 1 << 5, UpdateTaskStageGroupResources = 1 << 6, + UpdateTaskStageGroupSplashscreen = 1 << 7, } UpdateTaskStageGroup; typedef struct { @@ -74,7 +76,7 @@ void update_task_free(UpdateTask* update_task); void update_task_set_progress_cb(UpdateTask* update_task, updateProgressCb cb, void* state); -bool update_task_start(UpdateTask* update_task); +void update_task_start(UpdateTask* update_task); bool update_task_is_running(UpdateTask* update_task); diff --git a/applications/updater/util/update_task_worker_backup.c b/applications/updater/util/update_task_worker_backup.c index 011510ed..f1ce5281 100644 --- a/applications/updater/util/update_task_worker_backup.c +++ b/applications/updater/util/update_task_worker_backup.c @@ -93,6 +93,19 @@ static bool update_task_post_update(UpdateTask* update_task) { CHECK_RESULT(tar_archive_unpack_to(archive, EXT_PATH)); } } + + if(update_task->state.groups & UpdateTaskStageGroupSplashscreen) { + update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 0); + string_t tmp_path; + string_init_set(tmp_path, update_task->update_path); + path_append(tmp_path, string_get_cstr(update_task->manifest->splash_file)); + if(storage_common_copy( + update_task->storage, string_get_cstr(tmp_path), "/int/slideshow") != FSE_OK) { + // actually, not critical + } + string_clear(tmp_path); + update_task_set_progress(update_task, UpdateTaskStageSplashscreenInstall, 100); + } success = true; } while(false); diff --git a/assets/Makefile b/assets/Makefile deleted file mode 100644 index 2c743601..00000000 --- a/assets/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -PROJECT_ROOT = $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))..) - -include $(PROJECT_ROOT)/assets/assets.mk -include $(PROJECT_ROOT)/assets/copro.mk - -.PHONY: all -all: icons protobuf dolphin manifest - -$(ASSETS): $(ASSETS_SOURCES) $(ASSETS_COMPILER) - @echo "\tASSETS\t\t" $@ - @$(ASSETS_COMPILER) icons "$(ASSETS_SOURCE_DIR)" "$(ASSETS_COMPILED_DIR)" - -.PHONY: icons -icons: $(ASSETS) - -$(PROTOBUF) &: $(PROTOBUF_SOURCES) $(PROTOBUF_COMPILER) - @echo "\tPROTOBUF\t" $(PROTOBUF_FILENAMES) - @$(PROTOBUF_COMPILER) -q -I$(PROTOBUF_SOURCE_DIR) -D$(PROTOBUF_COMPILED_DIR) $(PROTOBUF_SOURCES) - @printf "#pragma once\n#define PROTOBUF_MAJOR_VERSION $(PROTOBUF_MAJOR_VERSION)\n#define PROTOBUF_MINOR_VERSION $(PROTOBUF_MINOR_VERSION)\n" > $(PROTOBUF_COMPILED_DIR)/protobuf_version.h - -.PHONY: protobuf -protobuf: $(PROTOBUF) - -$(DOLPHIN_EXTERNAL_OUTPUT_DIR): $(DOLPHIN_SOURCE_DIR) - @echo "\tDOLPHIN blocking" - @$(ASSETS_COMPILER) dolphin -s dolphin_blocking "$(DOLPHIN_SOURCE_DIR)/blocking" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" - @echo "\tDOLPHIN internal" - @$(ASSETS_COMPILER) dolphin -s dolphin_internal "$(DOLPHIN_SOURCE_DIR)/internal" "$(DOLPHIN_INTERNAL_OUTPUT_DIR)" - @echo "\tDOLPHIN external" - @$(ASSETS_COMPILER) dolphin "$(DOLPHIN_SOURCE_DIR)/external" "$(DOLPHIN_EXTERNAL_OUTPUT_DIR)" - -.PHONY: manifest -manifest: - $(ASSETS_COMPILER) manifest $(RESOURCES_DIR) - -.PHONY: dolphin -dolphin: $(DOLPHIN_EXTERNAL_OUTPUT_DIR) - -.PHONY: copro_bundle -copro_bundle: - @mkdir -p $(COPRO_BUNDLE_DIR) - @$(ASSETS_COMPILER) copro $(COPRO_CUBE_DIR) $(COPRO_BUNDLE_DIR) $(COPRO_MCU_FAMILY) --cube_ver=$(COPRO_CUBE_VERSION) --stack_type=$(COPRO_STACK_TYPE) --stack_file=$(COPRO_STACK_BIN) --stack_addr=$(COPRO_STACK_ADDR) - -clean: - @echo "\tCLEAN\t" - @$(RM) $(ASSETS_COMPILED_DIR)/* - @$(RM) -rf $(COPRO_BUNDLE_DIR) - @$(RM) -rf $(DOLPHIN_EXTERNAL_OUTPUT_DIR) diff --git a/assets/ReadMe.md b/assets/ReadMe.md index 0e5b0bdb..09ec4cff 100644 --- a/assets/ReadMe.md +++ b/assets/ReadMe.md @@ -1,20 +1,18 @@ # Requirements - Python3 -- ImageMagic -- Make +- Python3 packages: Pillow & heatshrink2 # Compiling ```bash -make all +./fbt icons proto dolphin_internal dolphin_blocking dolphin_ext resources ``` # Compiling with Docker-Compose ```bash -docker-compose exec dev make -C assets clean -docker-compose exec dev make -C assets all +docker-compose exec dev ./fbt icons proto dolphin_internal dolphin_blocking dolphin_ext resources ``` # Asset naming rules @@ -46,3 +44,4 @@ Don't include assets that you are not using, compiler is not going to strip unus - `icons` - Icons sources. Goes to `compiled` folder. - `protobuf` - Protobuf sources. Goes to `compiled` folder. - `resources` - Assets that is going to be provisioned to SD card. +- `slideshow` - One-time slideshows for desktop diff --git a/assets/SConscript b/assets/SConscript new file mode 100644 index 00000000..e70208ab --- /dev/null +++ b/assets/SConscript @@ -0,0 +1,113 @@ +Import("env") + +# HACHHACK +# Currently injected to CPPPATH by libs - since they are built earlier and depend on assets +# env.Append( +# CPPPATH=[ +# Dir("./compiled"), +# ] +# ) + +assetsenv = env.Clone( + tools=["fbt_assets"], + FW_LIB_NAME="assets", +) +assetsenv.ApplyLibFlags() + +if not assetsenv["VERBOSE"]: + assetsenv.SetDefault( + ICONSCOMSTR="\tICONS\t${TARGET}", + PROTOCOMSTR="\tPROTO\t${SOURCE}", + DOLPHINCOMSTR="\tDOLPHIN\t${DOLPHIN_RES_TYPE}", + RESMANIFESTCOMSTR="\tMANIFEST\t${TARGET}", + PBVERCOMSTR="\tPBVER\t${TARGET}", + ) + +# Gathering icons sources +icons_src = assetsenv.GlobRecursive("*.png", "icons") +icons_src += assetsenv.GlobRecursive("frame_rate", "icons") + +icons = assetsenv.IconBuilder(Dir("compiled"), Dir("#/assets/icons")) +Depends(icons, icons_src) +Alias("icons", icons) + + +# Protobuf .proto -> .c + .h + +proto_src = Glob("protobuf/*.proto", source=True) +proto_options = Glob("protobuf/*.options", source=True) +proto = assetsenv.ProtoBuilder(Dir("compiled"), proto_src) +Depends(proto, proto_options) +# Precious(proto) +Alias("proto", proto) + + +# Internal animations + +dolphin_internal = assetsenv.DolphinSymBuilder( + Dir("compiled"), + Dir("#/assets/dolphin"), + DOLPHIN_RES_TYPE="internal", +) +Alias("dolphin_internal", dolphin_internal) + + +# Blocking animations + +dolphin_blocking = assetsenv.DolphinSymBuilder( + Dir("compiled"), + Dir("#/assets/dolphin"), + DOLPHIN_RES_TYPE="blocking", +) +Alias("dolphin_blocking", dolphin_blocking) + + +# Protobuf version meta +proto_ver = assetsenv.ProtoVerBuilder( + "compiled/protobuf_version.h", + "#/assets/protobuf/Changelog", +) +Depends(proto_ver, proto) +Alias("proto_ver", proto_ver) + +# Gather everything into a static lib +assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver) + +assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts) +assetsenv.Install("${LIB_DIST_DIR}", assetslib) + + +# Resources for SD card + +if assetsenv["IS_BASE_FIRMWARE"]: + # External dolphin animations + dolphin_external = assetsenv.DolphinExtBuilder( + Dir("#/assets/resources/dolphin"), + Dir("#/assets/dolphin"), + DOLPHIN_RES_TYPE="external", + ) + NoClean(dolphin_external) + if assetsenv["FORCE"]: + AlwaysBuild(dolphin_external) + Alias("dolphin_ext", dolphin_external) + + # Resources manifest + + resources = assetsenv.Command( + "#/assets/resources/Manifest", + assetsenv.GlobRecursive("*", "resources", exclude="Manifest"), + action=Action( + '${PYTHON3} ${ASSETS_COMPILER} manifest "${TARGET.dir.posix}"', + "${RESMANIFESTCOMSTR}", + ), + ) + Precious(resources) + NoClean(resources) + if assetsenv["FORCE"]: + AlwaysBuild(resources) + + # Exporting resources node to external environment + env["FW_RESOURCES"] = resources + Alias("resources", resources) + +Return("assetslib") diff --git a/assets/assets.mk b/assets/assets.mk deleted file mode 100644 index 18e0a244..00000000 --- a/assets/assets.mk +++ /dev/null @@ -1,32 +0,0 @@ -ASSETS_DIR := $(PROJECT_ROOT)/assets -ASSETS_COMPILER := $(PROJECT_ROOT)/scripts/assets.py -ASSETS_COMPILED_DIR := $(ASSETS_DIR)/compiled -ASSETS_SOURCE_DIR := $(ASSETS_DIR)/icons - -ASSETS_SOURCES += $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') -ASSETS += $(ASSETS_COMPILED_DIR)/assets_icons.c - -RESOURCES_DIR := $(ASSETS_DIR)/resources -RESOURCES_MANIFEST := $(RESOURCES_DIR)/Manifest -RESOURCES_FILES := $(shell find $(RESOURCES_DIR) ! -name Manifest -type f) - -DOLPHIN_SOURCE_DIR := $(ASSETS_DIR)/dolphin -DOLPHIN_INTERNAL_OUTPUT_DIR := $(ASSETS_COMPILED_DIR) -DOLPHIN_EXTERNAL_OUTPUT_DIR := $(ASSETS_DIR)/resources/dolphin - -PROTOBUF_SOURCE_DIR := $(ASSETS_DIR)/protobuf -PROTOBUF_COMPILER := $(PROJECT_ROOT)/lib/nanopb/generator/nanopb_generator.py -PROTOBUF_COMPILED_DIR := $(ASSETS_COMPILED_DIR) -PROTOBUF_SOURCES := $(shell find $(PROTOBUF_SOURCE_DIR) -type f -iname '*.proto') -PROTOBUF_FILENAMES := $(notdir $(addsuffix .pb.c,$(basename $(PROTOBUF_SOURCES)))) -PROTOBUF := $(addprefix $(PROTOBUF_COMPILED_DIR)/,$(PROTOBUF_FILENAMES)) $(PROTOBUF_COMPILED_DIR)/protobuf_version.h -PROTOBUF_VERSION := $(shell git -C $(PROTOBUF_SOURCE_DIR) fetch --tags 2>/dev/null ; git -C $(PROTOBUF_SOURCE_DIR) describe --tags --abbrev=0 2>/dev/null || echo 'unknown') -PROTOBUF_MAJOR_VERSION := $(word 1,$(subst ., ,$(PROTOBUF_VERSION))) -PROTOBUF_MINOR_VERSION := $(word 2,$(subst ., ,$(PROTOBUF_VERSION))) -$(if $(PROTOBUF_MAJOR_VERSION),,$(error "Protobuf major version is not specified, $$PROTOBUF_VERSION=$(PROTOBUF_VERSION), please perform git fetch in assets/protobuf directory")) -$(if $(PROTOBUF_MINOR_VERSION),,$(error "Protobuf minor version is not specified, $$PROTOBUF_VERSION=$(PROTOBUF_VERSION), please perform git fetch in assets/protobuf directory")) - -PROTOBUF_CFLAGS += -DPB_ENABLE_MALLOC - -CFLAGS += -I$(ASSETS_COMPILED_DIR) $(PROTOBUF_CFLAGS) -C_SOURCES += $(wildcard $(ASSETS_COMPILED_DIR)/*.c) diff --git a/assets/compiled/application.pb.c b/assets/compiled/application.pb.c deleted file mode 100644 index a50850b2..00000000 --- a/assets/compiled/application.pb.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "application.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(PB_App_StartRequest, PB_App_StartRequest, AUTO) - - -PB_BIND(PB_App_LockStatusRequest, PB_App_LockStatusRequest, AUTO) - - -PB_BIND(PB_App_LockStatusResponse, PB_App_LockStatusResponse, AUTO) - - - diff --git a/assets/compiled/application.pb.h b/assets/compiled/application.pb.h deleted file mode 100644 index 4b05c46b..00000000 --- a/assets/compiled/application.pb.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_PB_APP_APPLICATION_PB_H_INCLUDED -#define PB_PB_APP_APPLICATION_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Struct definitions */ -typedef struct _PB_App_LockStatusRequest { - char dummy_field; -} PB_App_LockStatusRequest; - -typedef struct _PB_App_StartRequest { - char *name; - char *args; -} PB_App_StartRequest; - -typedef struct _PB_App_LockStatusResponse { - bool locked; -} PB_App_LockStatusResponse; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define PB_App_StartRequest_init_default {NULL, NULL} -#define PB_App_LockStatusRequest_init_default {0} -#define PB_App_LockStatusResponse_init_default {0} -#define PB_App_StartRequest_init_zero {NULL, NULL} -#define PB_App_LockStatusRequest_init_zero {0} -#define PB_App_LockStatusResponse_init_zero {0} - -/* Field tags (for use in manual encoding/decoding) */ -#define PB_App_StartRequest_name_tag 1 -#define PB_App_StartRequest_args_tag 2 -#define PB_App_LockStatusResponse_locked_tag 1 - -/* Struct field encoding specification for nanopb */ -#define PB_App_StartRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, name, 1) \ -X(a, POINTER, SINGULAR, STRING, args, 2) -#define PB_App_StartRequest_CALLBACK NULL -#define PB_App_StartRequest_DEFAULT NULL - -#define PB_App_LockStatusRequest_FIELDLIST(X, a) \ - -#define PB_App_LockStatusRequest_CALLBACK NULL -#define PB_App_LockStatusRequest_DEFAULT NULL - -#define PB_App_LockStatusResponse_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, locked, 1) -#define PB_App_LockStatusResponse_CALLBACK NULL -#define PB_App_LockStatusResponse_DEFAULT NULL - -extern const pb_msgdesc_t PB_App_StartRequest_msg; -extern const pb_msgdesc_t PB_App_LockStatusRequest_msg; -extern const pb_msgdesc_t PB_App_LockStatusResponse_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PB_App_StartRequest_fields &PB_App_StartRequest_msg -#define PB_App_LockStatusRequest_fields &PB_App_LockStatusRequest_msg -#define PB_App_LockStatusResponse_fields &PB_App_LockStatusResponse_msg - -/* Maximum encoded size of messages (where known) */ -/* PB_App_StartRequest_size depends on runtime parameters */ -#define PB_App_LockStatusRequest_size 0 -#define PB_App_LockStatusResponse_size 2 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/assets/compiled/assets_dolphin_blocking.c b/assets/compiled/assets_dolphin_blocking.c deleted file mode 100644 index a1ec14b4..00000000 --- a/assets/compiled/assets_dolphin_blocking.c +++ /dev/null @@ -1,330 +0,0 @@ -#include -#include -#include -#include - - - -const uint8_t _A_L0_NoDb_128x51_0[] = { - 0x1,0x0,0x43,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xff,0x11,0x0,0x88,0x0,0x4,0x16,0x34,0x0,0x10,0xc1,0x1,0xf7,0x20,0x7,0xbe,0x62,0x19,0x9c,0x9d,0xdd,0xf3,0x91,0x99,0x1c,0x9a,0x3b,0x7,0x27,0xa6,0xa2,0x25,0x52,0xc9,0x65,0x2a,0x5a,0x4b,0x4,0xa7,0x4a,0x1f,0x10,0x79,0xf2,0x1,0xe7,0x92,0x9e,0x48,0x41,0xef,0x88,0x7,0x9c,0x4a,0xb,0x22,0x7,0xc0,0xfc,0x62,0x77,0x7e,0xe6,0x62,0x43,0xc6,0x92,0x8f,0xd5,0x3f,0xe0,0xff,0x7,0xf8,0x3f,0xc1,0xf9,0x7,0x7,0xbd,0xc2,0x3c,0xaf,0x2a,0x7,0xff,0xf3,0xfc,0x7,0xb6,0x22,0x44,0xf,0x2d,0x7,0xff,0x1d,0xfb,0x7,0xa6,0x2,0x73,0x8,0x91,0x63,0x27,0x70,0x7e,0x85,0xff,0xf7,0xf7,0x7,0xa5,0x2,0x95,0x70,0x91,0x54,0xb1,0x50,0x4f,0x86,0xff,0xfb,0xef,0x7,0xb6,0x2,0x45,0x42,0x7,0x9f,0xfc,0x1e,0xe3,0xf1,0xf,0x9f,0x7e,0x3f,0xdf,0x1f,0xad,0x24,0xbe,0x38,0xc8,0x5c,0x1c,0x1e,0x3e,0xfe,0xf1,0xfe,0xc1,0xe3,0xff,0x7,0xe7,0x0,0x5a,0x22,0xf5,0x7,0xc6,0xfc,0x1f,0xa5,0xf7,0x7,0xc6,0xfc,0x1e,0xff,0xe6,0xd1,0x40,0x68,0x17,0xff,0xff,0x9c,0x1e,0xb8,0x8,0x8,0x10,0xa0,0x4b,0xf1,0xff,0x70,0xc1,0xeb,0xc0,0x2,0x1c,0x13,0xa0,0xdf,0x1c,0x0,0x3e,0xfe,0xf,0xf1,0x83,0x83,0xda,0x11,0x2,0x80,0x42,0x1,0xe5,0xff,0x87,0xdf,0x81,0xeb,0x18,0x81,0xc0,0x23,0x0,0xf3,0x8f,0xdf,0x1,0xeb,0xa8,0x99,0x59,0xe7,0x0,0xf3,0x9f,0xde,0x1,0xeb,0x48,0xa5,0x64,0x6f,0x0,0xf3,0xbf,0x83,0xda,0x11,0x4a,0xf8,0x87,0xd3,0xfe,0xf,0x88,0x88,0xfd,0x4,0x2,0xf,0x69,0x95,0x84,0xbe,0x80,0xf7,0x3f,0xb0,0x3f,0xc1,0xf0,0xbf,0x40,0x7c,0xe0,0x1,0x24,0xdf,0x1f,0x0,0x10,0xa7,0xee,0xf5,0x7,0x98,0x25,0x40,0x1e,0x0,0xf0,0x7,0x80,0x28 -}; - -const uint8_t _A_L0_NoDb_128x51_1[] = { - 0x1,0x0,0x45,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xff,0x11,0x0,0x88,0x0,0x4,0x16,0x34,0x0,0x10,0xc1,0x1,0xf7,0x20,0x7,0xbe,0x62,0x19,0x9c,0x9d,0xdd,0xf3,0x91,0x99,0x1c,0x9a,0x3b,0x7,0x27,0xa6,0xa2,0x25,0x52,0xc9,0x65,0x2a,0x5a,0x4b,0x4,0xa7,0x4a,0x1f,0x10,0x79,0xf2,0x1,0xe7,0x92,0x9e,0x48,0x41,0xef,0x88,0x7,0x9c,0x4a,0xb,0x22,0x7,0xc0,0xfc,0x62,0x77,0x7e,0xe6,0x62,0x43,0xc6,0x92,0x8f,0xd5,0x3f,0xe0,0xff,0x7,0xf8,0x3f,0xc1,0xf9,0x1f,0xfe,0x3,0xda,0xe1,0x1e,0x57,0x95,0x3,0xff,0xe7,0xf9,0x83,0xdb,0x11,0x22,0x7,0x96,0x83,0xff,0x3b,0xf7,0x3,0xd3,0x1,0x39,0x84,0x48,0xb1,0x93,0xb8,0x3f,0x43,0xff,0xed,0xef,0x83,0xd2,0x81,0x4a,0xb8,0x48,0xaa,0x58,0xa8,0x27,0xc3,0xff,0xf6,0xdf,0x83,0xdb,0x1,0x22,0xa1,0x3,0xcf,0xfc,0xf,0x71,0xf8,0x87,0xce,0xff,0x1f,0xbf,0x8f,0xd6,0x92,0x5f,0x1c,0x64,0x2e,0xe,0xf,0x1f,0x7d,0xf8,0xff,0x60,0xf1,0xff,0x83,0xf3,0x80,0x2d,0x11,0x7a,0x83,0xe0,0x9c,0x20,0xfc,0x2f,0xb8,0x3e,0x37,0xc0,0xf7,0xff,0x36,0x8a,0x2,0xbf,0x1f,0xee,0x7c,0x1e,0xb8,0x8,0x8,0x10,0xa0,0x4b,0xf1,0xfd,0xc3,0xc1,0xeb,0xc0,0x2,0x1c,0x11,0x7e,0x3e,0x78,0x1d,0xf8,0x1f,0x4a,0xf1,0x8f,0xc7,0x2f,0x80,0xf5,0x84,0x40,0xa0,0x10,0x80,0x79,0x7f,0xe7,0xf7,0x80,0x7a,0xc6,0x20,0x70,0x8,0xc0,0x3c,0xef,0xf7,0x0,0x7a,0xea,0x26,0x56,0x79,0xc0,0x3c,0xff,0xf6,0x0,0x7a,0xd2,0x29,0x59,0x1b,0xc0,0x3d,0x2c,0x23,0xf6,0xa5,0x7c,0x43,0xeb,0x63,0x7,0xbc,0x44,0x7e,0x84,0x1,0x7,0xb4,0xca,0xc2,0x5f,0x40,0x7b,0x9f,0xd8,0x1f,0xe0,0xf8,0x5f,0xa0,0x3e,0x70,0x0,0x92,0x6f,0x8f,0x80,0x8,0x53,0xf7,0x7a,0x83,0xcc,0x12,0xa0,0xf,0x0,0x78,0x3,0xc0,0x14 -}; - -const uint8_t _A_L0_NoDb_128x51_2[] = { - 0x1,0x0,0x43,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xff,0x11,0x0,0x88,0x0,0x4,0x16,0x34,0x0,0x10,0xc1,0x1,0xf7,0x20,0x7,0xbe,0x62,0x19,0x9c,0x9d,0xdd,0xf3,0x91,0x99,0x1c,0x9a,0x3b,0x7,0x27,0xa6,0xa2,0x25,0x52,0xc9,0x65,0x2a,0x5a,0x4b,0x4,0xa7,0x4a,0x1f,0x10,0x79,0xf2,0x1,0xe7,0x92,0x9e,0x48,0x41,0xef,0x88,0x7,0x9c,0x4a,0xb,0x22,0x7,0xc0,0xfc,0x62,0x77,0x7e,0xe6,0x62,0x43,0xc6,0x92,0x8f,0xd5,0x3f,0xe0,0xff,0x7,0xf8,0x3f,0xc1,0xfe,0xa,0x5b,0x84,0x79,0x5e,0x54,0x0,0x7c,0xe2,0x24,0x40,0xf2,0xd0,0x7f,0xe3,0xff,0xc0,0x7a,0x60,0x27,0x30,0x89,0x16,0x32,0x77,0x7,0xe8,0x7f,0xfc,0xff,0x30,0x7a,0x50,0x29,0x57,0x9,0x15,0x4b,0x15,0x4,0xf8,0x7f,0xe7,0x7e,0xe0,0x7b,0x60,0x24,0x54,0x20,0x79,0xfb,0x7b,0xe0,0xf6,0x1f,0x88,0x7d,0x22,0xdb,0xf1,0xfa,0xd2,0x4b,0xe3,0x8c,0x85,0xc1,0xc1,0xe3,0xee,0xdf,0x1f,0xef,0xe1,0x7f,0xff,0xdf,0x81,0xf7,0xc0,0xbf,0x80,0x8,0x1f,0x83,0xe1,0x7,0xea,0x78,0x43,0xfe,0xf,0x6f,0xf2,0xe8,0xa0,0x2b,0xf1,0xff,0x1b,0xd4,0xe0,0x30,0x10,0x21,0x40,0x97,0xe2,0xf,0x7e,0x0,0x10,0xe0,0x8b,0xf1,0xfe,0xe7,0xc1,0xf6,0x8f,0x1f,0xdc,0x3c,0x1e,0xd0,0x88,0x14,0x2,0x10,0xf,0x2f,0x3c,0xe,0xfc,0xf,0x58,0xc4,0xe,0x1,0x18,0x7,0x94,0x7e,0x39,0x7c,0x7,0xae,0xa2,0x65,0x67,0x9c,0x3,0xcb,0xff,0x3f,0xbc,0x3,0xd6,0x91,0x4a,0xc8,0xde,0x1,0xe7,0x7f,0xb8,0xf,0xda,0x95,0xf1,0xf,0xa7,0xfe,0xc0,0xf,0x78,0x88,0xfc,0xc0,0x3,0x61,0x7,0xb4,0xca,0xc2,0x5f,0x30,0x0,0xd8,0xcf,0xf8,0x40,0x20,0x7f,0x83,0xd5,0x7e,0x80,0xf9,0xc0,0x2,0x49,0xbe,0x3e,0x0,0x21,0x4f,0xdd,0xea,0xf,0x30,0x4a,0x80,0x3c,0x1,0xe0,0xf,0x0,0x50 -}; - -const uint8_t _A_L0_NoDb_128x51_3[] = { - 0x1,0x0,0x43,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xff,0x11,0x0,0x88,0x0,0x4,0x16,0x34,0x0,0x10,0xc1,0x1,0xf7,0x20,0x7,0xbe,0x62,0x19,0x9c,0x9d,0xdd,0xf3,0x91,0x99,0x1c,0x9a,0x3b,0x7,0x27,0xa6,0xa2,0x25,0x52,0xc9,0x65,0x2a,0x5a,0x4b,0x4,0xa7,0x4a,0x1f,0x10,0x79,0xf2,0x1,0xe7,0x92,0x9e,0x48,0x41,0xef,0x88,0x7,0x9c,0x4a,0xb,0x22,0x7,0xc0,0xfc,0x62,0x77,0x7e,0xe6,0x62,0x43,0xc6,0x92,0x8f,0xd5,0x3f,0xe0,0xff,0x7,0xf8,0x3f,0xc1,0xfe,0xa,0x5b,0x84,0x79,0x5e,0x54,0x0,0x7c,0xe2,0x24,0x40,0xf2,0xd0,0x7f,0xe0,0xe0,0xf5,0xc0,0x4e,0x61,0x12,0x2c,0x64,0xee,0xf,0xd0,0xff,0xfe,0x7f,0x80,0xf4,0xa0,0x52,0xae,0x12,0x2a,0x96,0x2a,0x9,0xf0,0xff,0xe3,0xbf,0x60,0xf6,0xc0,0x48,0xa8,0x40,0xf2,0xbf,0xfe,0xfe,0xe0,0xf6,0x1f,0x88,0x7c,0xf7,0xf1,0xdf,0x78,0xfd,0x69,0x25,0xf1,0xc6,0x42,0xe0,0xe0,0xf1,0xf7,0xfb,0x8f,0xf7,0xf0,0xef,0xff,0xfb,0xc0,0xfb,0xe0,0x77,0xef,0xe0,0x11,0x7,0xe6,0xfc,0x1f,0xdf,0xf0,0xff,0x83,0xdf,0xfc,0xba,0x28,0xd,0x3,0x7f,0xff,0x37,0xa9,0xc0,0x60,0x20,0x42,0x81,0x68,0x1,0xf1,0xc0,0x2,0x1c,0x13,0xa1,0x7f,0xff,0xf9,0xc1,0xf6,0xbf,0x1f,0xf7,0xc,0x1e,0xd0,0x88,0x14,0x2,0x10,0xf,0x2f,0xce,0x0,0x1e,0xd1,0x88,0x1c,0x2,0x30,0xf,0x28,0x3c,0x1c,0x1e,0xda,0x89,0x95,0x9e,0x70,0xf,0x2f,0xfc,0x3e,0xfc,0xf,0x5a,0x45,0x2b,0x23,0x78,0x7,0x9c,0x7e,0xf8,0x3f,0x6a,0x57,0xc4,0x3e,0x93,0xfb,0xc0,0x3d,0xe2,0x23,0xf3,0xff,0xdf,0xc1,0xef,0x32,0xb0,0x97,0xcc,0x0,0x20,0xf6,0x3f,0xb0,0x80,0x81,0xfe,0xf,0x55,0xfa,0x3,0xe7,0x0,0x9,0x26,0xf8,0xf8,0x0,0x85,0x3f,0x77,0xa8,0x3c,0xc1,0x2a,0x0,0xf0,0x7,0x80,0x3c,0x1,0x40 -}; - - -const uint8_t * const _A_L0_NoDb_128x51[] = { - - _A_L0_NoDb_128x51_0, - - _A_L0_NoDb_128x51_1, - - _A_L0_NoDb_128x51_2, - - _A_L0_NoDb_128x51_3, - -}; - - - -const uint8_t L0_NoDb_128x51_frame_order[] = { 0, 1, 2, 3 }; - -const BubbleAnimation BA_L0_NoDb_128x51 = { - .icon_animation = { - .width = 128, - .height = 51, - .frame_count = 4, - .frame_rate = 2, - .frames = _A_L0_NoDb_128x51 - }, - .frame_order = L0_NoDb_128x51_frame_order, - .passive_frames = 4, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 0, - - .frame_bubble_sequences = NULL, - .frame_bubble_sequences_count = 0, - -}; - - -const uint8_t _A_L0_SdBad_128x51_0[] = { - 0x1,0x0,0x1,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfe,0x1,0x82,0x4,0xc,0x4a,0x1,0x70,0x8f,0x1,0x46,0x8,0xf,0x5e,0x30,0x24,0x60,0x50,0xc,0x44,0x88,0x1f,0x1a,0xaa,0x64,0xeb,0xaf,0x71,0x84,0x48,0xb1,0x93,0xb8,0x39,0x3d,0x72,0x55,0x2a,0x50,0x4,0x6e,0x12,0x2a,0x96,0x28,0x3e,0x20,0xf4,0xc1,0x3,0xcf,0x1,0x22,0xa1,0x3,0xf0,0x7e,0x21,0xf9,0xc6,0x52,0xea,0x57,0x22,0xf8,0xe3,0x21,0x63,0xf6,0x0,0x1d,0x1,0x3f,0xd3,0x5,0x7f,0x83,0xfc,0x1f,0xe0,0xf5,0xcf,0xfc,0xee,0x77,0xe0,0x5b,0x7e,0x28,0x10,0x18,0x25,0x2,0x7f,0xf9,0x93,0x87,0xde,0x11,0x0,0x7,0x8e,0x82,0xff,0xfc,0xc7,0x83,0xe2,0xb9,0x19,0x83,0xf4,0x1,0xf5,0x78,0xa9,0x69,0x60,0x9f,0x1,0x7d,0xd4,0xb7,0xa0,0xf1,0x27,0xd0,0x3c,0x70,0xa0,0xf1,0x37,0xd0,0xfc,0xc1,0xf6,0x0,0x30,0x7f,0xf0,0x1,0xff,0xff,0x83,0xfe,0x1,0xfb,0xf9,0xf0,0x83,0xf6,0x19,0xc6,0x7,0xb0,0xe8,0xe0,0x34,0xf,0xfc,0x1b,0x90,0xf,0x69,0x80,0xc,0xa0,0x5a,0xf,0xfc,0xd8,0x1e,0xf1,0x80,0x19,0x41,0x3a,0x5,0xd1,0xfe,0x3,0xec,0xff,0x51,0x8b,0x84,0x8a,0x4,0xf,0xcc,0x44,0x4a,0xc,0xf,0xd8,0x54,0x38,0x1f,0xb0,0x68,0xf0,0x7f,0xc7,0xfe,0x5f,0xf0,0x7e,0x1f,0xfc,0x1f,0xd3,0x85,0xf9,0x83,0xe8,0x14,0x70,0x1f,0x0,0x10,0xa7,0xe0,0xf5,0x5,0x18,0x25,0x40,0x1e,0x0,0xf0,0x7,0x80,0x28 -}; - -const uint8_t _A_L0_SdBad_128x51_1[] = { - 0x1,0x0,0x12,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfe,0x1,0x82,0x4,0xc,0x4a,0x1,0x70,0x8f,0x1,0x46,0x8,0xf,0x5e,0x30,0x24,0x60,0x50,0xc,0x44,0x88,0x1f,0x1a,0xaa,0x64,0xeb,0xaf,0x71,0x84,0x48,0xb1,0x93,0xb8,0x39,0x3d,0x72,0x55,0x2a,0x50,0x4,0x6e,0x12,0x2a,0x96,0x28,0x3e,0x20,0xf4,0xc1,0x3,0xcf,0x1,0x22,0xa1,0x3,0xf0,0x7e,0x21,0xf9,0xc6,0x52,0xea,0x57,0x22,0xf8,0xe3,0x21,0x63,0xf6,0x0,0x1d,0x1,0x3f,0xd3,0x5,0x7f,0x83,0xfc,0x1f,0xe0,0xf5,0xcf,0xfc,0xee,0x77,0xe0,0x5b,0x7e,0x28,0x10,0x18,0x25,0x2,0x7f,0xf9,0x93,0x87,0xde,0x11,0x0,0x7,0x8e,0x82,0xff,0xfc,0xc7,0x83,0xe2,0xb9,0x19,0x83,0xf4,0x1,0xf5,0x78,0xa9,0x69,0x60,0x9f,0x1,0x7d,0xd4,0xb7,0xa0,0xf1,0x27,0xd0,0x3c,0x70,0xa0,0xf1,0x37,0xd0,0xfc,0xc1,0xf6,0x0,0x30,0x7f,0xf0,0x1,0xff,0xff,0x81,0xfc,0x1,0xfb,0xf8,0xe0,0x83,0xf2,0xff,0x4c,0xc3,0x3,0xd8,0x74,0x70,0x15,0xf8,0xe1,0xa1,0x0,0xf6,0x98,0x0,0xca,0x5,0xa0,0x9f,0xc5,0xa1,0x20,0xf6,0x8c,0x0,0xca,0x9,0xd0,0xbb,0xcf,0xb3,0x17,0xb0,0x7d,0x7c,0x3e,0xf3,0xff,0xc0,0x3d,0xee,0x12,0x28,0x10,0x3c,0x7d,0xee,0x1,0xbe,0x83,0xdb,0x11,0x12,0x83,0x2f,0xec,0x1e,0x30,0xa8,0x70,0x3f,0x60,0xd1,0xe0,0xff,0x83,0xf4,0x7f,0xc5,0xf4,0x7,0xd1,0xfd,0x1,0xfe,0xf,0x99,0xc2,0xfc,0xc1,0xf4,0xa,0x38,0xf,0x80,0x8,0x53,0xf0,0x7a,0x82,0x8c,0x12,0xa0,0xf,0x0,0x78,0x3,0xc0,0x14 -}; - - -const uint8_t * const _A_L0_SdBad_128x51[] = { - - _A_L0_SdBad_128x51_0, - - _A_L0_SdBad_128x51_1, - -}; - - - -const uint8_t L0_SdBad_128x51_frame_order[] = { 0, 1 }; - -const BubbleAnimation BA_L0_SdBad_128x51 = { - .icon_animation = { - .width = 128, - .height = 51, - .frame_count = 2, - .frame_rate = 2, - .frames = _A_L0_SdBad_128x51 - }, - .frame_order = L0_SdBad_128x51_frame_order, - .passive_frames = 2, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 0, - - .frame_bubble_sequences = NULL, - .frame_bubble_sequences_count = 0, - -}; - - -const uint8_t _A_L0_SdOk_128x51_0[] = { - 0x1,0x0,0x19,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0xe,0x54,0xec,0xe,0x0,0x8,0x35,0x48,0x20,0x3e,0x2a,0x20,0xf3,0xa8,0x3,0xeb,0xc3,0xdc,0x9c,0xc9,0x2a,0xb1,0xc8,0x19,0x3d,0xeb,0xf9,0x1c,0x94,0x90,0x1e,0x3a,0x48,0x20,0x3d,0xea,0x20,0xf5,0x83,0x83,0xf8,0xff,0x3,0xf1,0xce,0x4e,0x3b,0x15,0x41,0xfc,0xa7,0xfc,0x1f,0xe0,0xff,0x7,0xcc,0x1f,0xf8,0xf,0xdf,0xcf,0xcc,0x1e,0x8a,0xa1,0xb8,0x47,0x80,0xa5,0x40,0xff,0xff,0xbd,0xe0,0xf6,0xc4,0x48,0x80,0xa5,0xa0,0xbf,0xff,0xfb,0xe0,0xf1,0xb0,0x4b,0xa3,0x38,0x79,0xcc,0x22,0x45,0x8c,0x9d,0xc1,0xfa,0x1b,0xff,0xfe,0xfc,0x1e,0x31,0x9,0x4e,0x96,0x89,0x4a,0xb8,0x48,0xaa,0x58,0xa8,0x27,0xc0,0x1e,0x92,0x9,0x4e,0xf4,0x1e,0x38,0x9,0x15,0x8,0x1e,0x5d,0xf3,0x70,0x83,0xc6,0x81,0x29,0xc2,0x83,0xc4,0x7e,0x21,0xf3,0x7,0xa4,0xc3,0x9d,0x18,0xc3,0xd2,0x4b,0xe3,0x8c,0x85,0xc1,0xc1,0xea,0x0,0x90,0x78,0x9f,0x84,0x1f,0x7c,0x0,0x7f,0xf7,0xfe,0xe0,0xfe,0x1f,0xef,0x0,0xfe,0x80,0xa5,0x75,0x14,0x6,0x80,0xf,0x99,0x80,0xc,0xa0,0x4b,0xf5,0x0,0x24,0x61,0xaa,0x7d,0x6,0xfb,0x83,0xdb,0xe0,0xff,0x70,0x79,0x34,0x6,0x4,0xf,0x28,0x3f,0xf0,0x1e,0xf8,0x88,0x94,0x18,0x1e,0x40,0x1,0x7,0xc4,0x2a,0x1c,0xf,0xd8,0x34,0x78,0x3f,0xe0,0xfd,0x1f,0xf1,0x7d,0x41,0xf2,0x7f,0x50,0x7f,0x83,0xe2,0x70,0xbf,0x30,0x7d,0x2,0x8e,0x3,0xe0,0x2,0x14,0xfc,0x1e,0xa0,0xa3,0x4,0xa8,0x3,0xc0,0x1e,0x0,0xf0,0x5,0x0 -}; - -const uint8_t _A_L0_SdOk_128x51_1[] = { - 0x1,0x0,0x1e,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0xe,0x54,0xec,0xe,0x0,0x8,0x35,0x48,0x20,0x3e,0x2a,0x20,0xf3,0xa8,0x3,0xeb,0xc3,0xdc,0x9c,0xc9,0x2a,0xb1,0xc8,0x19,0x3d,0xeb,0xf9,0x1c,0x94,0x90,0x1e,0x3a,0x48,0x20,0x3d,0xea,0x20,0xf5,0x83,0x83,0xf8,0xff,0x3,0xf1,0xce,0x4e,0x3b,0x15,0x41,0xfc,0xa7,0xfc,0x1f,0xe0,0xff,0x7,0xcc,0x1f,0xf8,0xf,0xdf,0xcf,0xcc,0x1e,0x8a,0xa1,0xb8,0x47,0x80,0xa5,0x40,0xff,0xff,0xbd,0xe0,0xf6,0xc4,0x48,0x80,0xa5,0xa0,0xbf,0xff,0xfb,0xe0,0xf1,0xb0,0x4b,0xa3,0x38,0x79,0xcc,0x22,0x45,0x8c,0x9d,0xc1,0xfa,0x1b,0xff,0xfe,0xfc,0x1e,0x31,0x9,0x4e,0x96,0x89,0x4a,0xb8,0x48,0xaa,0x58,0xa8,0x27,0xc0,0x1e,0x92,0x9,0x4e,0xf4,0x1e,0x38,0x9,0x15,0x8,0x1e,0x5d,0xf3,0x70,0x83,0xc6,0x81,0x29,0xc2,0x83,0xc4,0x7e,0x21,0xf3,0x7,0xa4,0xc3,0x9d,0x18,0xc3,0xd2,0x4b,0xe3,0x8c,0x85,0xc1,0xc1,0xea,0x0,0x90,0x78,0x9f,0x84,0x1f,0x7c,0xe,0xff,0x8c,0x1f,0xd8,0x70,0x7f,0x63,0xc1,0xfb,0xbf,0xcf,0x9f,0xc8,0x14,0xae,0xa2,0x80,0xd0,0x11,0xe8,0x0,0x49,0x80,0xc,0xa0,0x4b,0xf5,0x0,0x24,0x61,0xaa,0x7d,0x6,0xfb,0x83,0xdb,0xe0,0xff,0x70,0x79,0x34,0x6,0x4,0xf,0x28,0x3f,0xf0,0x1e,0xf8,0x88,0x94,0x18,0x1e,0x40,0x1,0x7,0xc4,0x2a,0x1c,0xf,0xd8,0x34,0x78,0x3f,0xe0,0xfd,0x1f,0xf1,0x7d,0x41,0xf2,0x7f,0x50,0x7f,0x83,0xe2,0x70,0xbf,0x30,0x7d,0x2,0x8e,0x3,0xe0,0x2,0x14,0xfc,0x1e,0xa0,0xa3,0x4,0xa8,0x3,0xc0,0x1e,0x0,0xf0,0x5,0x0 -}; - -const uint8_t _A_L0_SdOk_128x51_2[] = { - 0x1,0x0,0x22,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0xe,0x54,0xec,0xe,0x0,0x8,0x35,0x48,0x20,0x3e,0x2a,0x20,0xf3,0xa8,0x3,0xeb,0xc3,0xdc,0x9c,0xc9,0x2a,0xb1,0xc8,0x19,0x3d,0xeb,0xf9,0x1c,0x94,0x90,0x1e,0x3a,0x48,0x20,0x3d,0xea,0x20,0xf5,0x83,0x83,0xf8,0xff,0x3,0xf1,0xce,0x4e,0x3b,0x15,0x41,0xfc,0xa7,0xfc,0x1f,0xe0,0xff,0x7,0xcc,0x1f,0xf8,0xf,0xdf,0xcf,0xcc,0x1e,0x8a,0xa1,0xb8,0x47,0x80,0xa5,0x40,0xff,0xff,0xbd,0xe0,0xf6,0xc4,0x48,0x80,0xa5,0xa0,0xbf,0xff,0xfb,0xe0,0xf1,0xb0,0x4b,0xa3,0x38,0x79,0xcc,0x22,0x45,0x8c,0x9d,0xc1,0xfa,0x1b,0xff,0xfe,0xfc,0x1e,0x31,0x9,0x4e,0x96,0x89,0x4a,0xb8,0x48,0xaa,0x58,0xa8,0x27,0xc0,0x1e,0x92,0x9,0x4e,0xf4,0x1e,0x38,0x9,0x15,0x8,0x1e,0x5d,0xf3,0x70,0x83,0xc6,0x81,0x29,0xc2,0x83,0xc4,0x7e,0x21,0xf3,0x7,0xa4,0xc3,0x9d,0x18,0xc3,0xd2,0x4b,0xe3,0x8c,0x85,0xc1,0xc1,0xe5,0x7d,0x3f,0xd8,0x3c,0x7e,0x77,0xc0,0x7d,0xf0,0x3b,0xf6,0x30,0x7f,0x41,0xef,0xc0,0xfd,0x87,0x93,0xc8,0x1f,0x5b,0xfc,0xf9,0xfc,0x81,0x4a,0xea,0x28,0xd,0x1,0x1e,0x80,0x4,0x98,0x0,0xca,0x4,0xbf,0x50,0x2,0x46,0x1a,0xa7,0xd0,0x6f,0xb8,0x3d,0xbe,0xf,0xf7,0x7,0x93,0x40,0x60,0x40,0xf2,0x83,0xff,0x1,0xef,0x88,0x89,0x41,0x81,0xe4,0x0,0x10,0x7c,0x42,0xa1,0xc0,0xfd,0x83,0x47,0x83,0xfe,0xf,0xd1,0xff,0x17,0xd4,0x1f,0x27,0xf5,0x7,0xf8,0x3e,0x27,0xb,0xf3,0x7,0xd0,0x28,0xe0,0x3e,0x0,0x21,0x4f,0xc1,0xea,0xa,0x30,0x4a,0x80,0x3c,0x1,0xe0,0xf,0x0,0x50 -}; - -const uint8_t _A_L0_SdOk_128x51_3[] = { - 0x1,0x0,0x26,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0xe,0x54,0xec,0xe,0x0,0x8,0x35,0x48,0x20,0x3e,0x2a,0x20,0xf3,0xa8,0x3,0xeb,0xc3,0xdc,0x9c,0xc9,0x2a,0xb1,0xc8,0x19,0x3d,0xeb,0xf9,0x1c,0x94,0x90,0x1e,0x3a,0x48,0x20,0x3d,0xea,0x20,0xf5,0x83,0x83,0xf8,0xff,0x3,0xf1,0xce,0x4e,0x3b,0x15,0x41,0xfc,0xa7,0xfc,0x1f,0xe0,0xff,0x7,0xcc,0x1f,0xf8,0xf,0xdf,0xcf,0xcc,0x1e,0x8a,0xa1,0xb8,0x47,0x80,0xa5,0x40,0xff,0xff,0xbd,0xe0,0xf6,0xc4,0x48,0x80,0xa5,0xa0,0xbf,0xff,0xfb,0xe0,0xf1,0xb0,0x4b,0xa3,0x38,0x79,0xcc,0x22,0x45,0x8c,0x9d,0xc1,0xfa,0x1b,0xff,0xfe,0xfc,0x1e,0x31,0x9,0x4e,0x96,0x89,0x4a,0xb8,0x48,0xaa,0x58,0xa8,0x27,0xc0,0x1e,0x92,0x9,0x4e,0xf4,0x1e,0x38,0x9,0x15,0x8,0x1e,0x5d,0xf3,0x70,0x83,0xc6,0x81,0x29,0xc2,0x83,0xc4,0x7e,0x21,0xf3,0x7,0x8d,0xcc,0x1e,0x33,0xe,0x74,0x63,0xf,0x49,0x2f,0x8e,0x32,0x17,0x7,0x7,0x95,0xc4,0xff,0x60,0xf1,0xf9,0xde,0x1,0xf7,0xc0,0xef,0xd8,0xef,0x80,0xfd,0x83,0xdf,0x81,0xfb,0xf,0x2f,0x90,0x3e,0xb7,0xf9,0xf3,0xf9,0x2,0x95,0xd4,0x50,0x1a,0x2,0x3d,0x0,0x9,0x30,0x1,0x94,0x9,0x7e,0xa0,0x4,0x8c,0x35,0x4f,0xa0,0xdf,0x70,0x7b,0x7c,0x1f,0xee,0xf,0x26,0x80,0xc0,0x81,0xe5,0x7,0xfe,0x3,0xdf,0x11,0x12,0x83,0x3,0xc8,0x0,0x20,0xf8,0x85,0x43,0x81,0xfb,0x6,0x8f,0x7,0xfc,0x1f,0xa3,0xfe,0x2f,0xa8,0x3e,0x4f,0xea,0xf,0xf0,0x7c,0x4e,0x17,0xe6,0xf,0xa0,0x51,0xc0,0x7c,0x0,0x42,0x9f,0x83,0xd4,0x14,0x60,0x95,0x0,0x78,0x3,0xc0,0x1e,0x0,0xa0 -}; - - -const uint8_t * const _A_L0_SdOk_128x51[] = { - - _A_L0_SdOk_128x51_0, - - _A_L0_SdOk_128x51_1, - - _A_L0_SdOk_128x51_2, - - _A_L0_SdOk_128x51_3, - -}; - - - -const uint8_t L0_SdOk_128x51_frame_order[] = { 0, 1, 2, 3 }; - -const BubbleAnimation BA_L0_SdOk_128x51 = { - .icon_animation = { - .width = 128, - .height = 51, - .frame_count = 4, - .frame_rate = 2, - .frames = _A_L0_SdOk_128x51 - }, - .frame_order = L0_SdOk_128x51_frame_order, - .passive_frames = 4, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 0, - - .frame_bubble_sequences = NULL, - .frame_bubble_sequences_count = 0, - -}; - - -const uint8_t _A_L0_Url_128x51_0[] = { - 0x1,0x0,0x2d,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0x16,0xf0,0x38,0x80,0x3f,0x28,0x10,0x40,0x7f,0x58,0x27,0x10,0x32,0x7d,0xd0,0x32,0xd9,0x8,0x20,0x3f,0x32,0x80,0xff,0x7,0xee,0x2,0xc7,0x10,0x1f,0xe2,0x7f,0xc1,0xfe,0xf,0xf0,0x7d,0x7e,0x1,0x89,0x4,0x7,0x9c,0x1c,0x1e,0x71,0xca,0xc,0x16,0x1,0x8,0x7,0x94,0xa,0x81,0xff,0xfc,0xff,0x1,0xe5,0xba,0x91,0x40,0x41,0xe5,0x2,0x0,0x8e,0x83,0xff,0x8e,0xfd,0x83,0xcb,0xe5,0x22,0xba,0xc3,0xb9,0xd2,0x4c,0x96,0x3a,0x7,0xd0,0xbf,0xfe,0xfe,0xe0,0xf2,0x9f,0x58,0xb2,0xb1,0x29,0x4c,0x97,0x23,0x52,0x81,0x7c,0x37,0xff,0xdf,0x78,0x3c,0xaf,0x52,0x20,0x78,0xfa,0x41,0xeb,0xff,0x7,0xa4,0x8c,0x3e,0x5a,0x4c,0x80,0x3c,0xbb,0xf1,0xfe,0xf8,0x3c,0xbf,0x92,0x1b,0xad,0x3b,0x9d,0x98,0xf0,0xf,0xc4,0x1e,0x3e,0xfe,0xf1,0xfd,0x22,0x5,0xc1,0x0,0x8,0xc,0x41,0xe3,0xff,0x7,0x98,0x0,0x41,0xed,0xc0,0x16,0x88,0xbc,0xc0,0x10,0xf,0x1d,0xf8,0x3f,0x4b,0xea,0xf,0xad,0xf8,0x3e,0x3f,0xd,0xa1,0x80,0xd0,0x2f,0xff,0xff,0x38,0x3d,0xe0,0xc5,0x2,0x5f,0x8f,0xfb,0x86,0xf,0x78,0x1b,0xc4,0xba,0xd,0xf1,0xc0,0x3,0xef,0xe0,0xff,0x18,0x38,0x3d,0xf8,0x78,0x98,0x40,0x3c,0xbf,0xf0,0xfb,0xf0,0x3d,0xa4,0x74,0xa8,0xc0,0x3c,0xe3,0xf7,0xc0,0x7b,0xca,0xa7,0x0,0xf3,0x9f,0xde,0x1,0xef,0x1a,0xbc,0x3,0xce,0xfe,0xf,0x80,0xfa,0xff,0xc1,0xf0,0x3f,0x51,0x0,0x97,0xf4,0x1f,0x7,0xf5,0x7,0xf8,0x3e,0x60,0xeb,0xf2,0x7,0xdf,0xf9,0xbe,0x5e,0x0,0x79,0x4f,0xc1,0xed,0xfc,0x5,0x8,0x25,0x80,0x1e,0x0,0xf0,0x7,0x80,0x24 -}; - -const uint8_t _A_L0_Url_128x51_1[] = { - 0x1,0x0,0x2d,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0x16,0xf0,0x38,0x80,0x3f,0x28,0x10,0x40,0x7f,0x58,0x27,0x10,0x32,0x7d,0xd0,0x32,0xd9,0x8,0x20,0x3f,0x32,0x80,0xff,0x7,0xee,0x2,0xc7,0x10,0x1f,0xe2,0x7f,0xc1,0xfe,0xf,0xf0,0x7d,0x7e,0x1,0x89,0x4,0x7,0x9c,0x7f,0xf8,0xf,0x28,0xe5,0x6,0xb,0x0,0x84,0x3,0xca,0x5,0x40,0xff,0xf9,0xfe,0x60,0xf2,0xdd,0x48,0xa0,0x20,0xf2,0x81,0x0,0x47,0x41,0xff,0x9d,0xfb,0x81,0xe5,0xf2,0x91,0x5d,0x61,0xdc,0xe9,0x26,0x4b,0x1d,0x3,0xe8,0x7f,0xfd,0xbd,0xf0,0x79,0x4f,0xac,0x59,0x58,0x94,0xa6,0x4b,0x91,0xa9,0x40,0xbe,0x1f,0xff,0xb6,0xfc,0x1e,0x57,0xa9,0x10,0x3c,0x7d,0x20,0xf5,0xff,0x3,0xd2,0x46,0x1f,0x2d,0x26,0x40,0x1e,0x57,0xf8,0xfd,0xfc,0x1e,0x5f,0xc9,0xd,0xd6,0x9d,0xce,0xcc,0x78,0x7,0xe2,0xf,0x1f,0x7d,0xf8,0xfe,0x91,0x2,0xe0,0x80,0x4,0x6,0x20,0xf1,0xff,0x83,0xcc,0x0,0x20,0xf6,0xe0,0xb,0x44,0x5e,0x60,0x8,0x7,0x89,0x38,0x41,0xf8,0x5f,0x50,0x7d,0x6f,0x81,0xf1,0xf8,0x6d,0xc,0x5,0x7e,0x3f,0xdc,0xf8,0x3d,0xe0,0xc5,0x2,0x5f,0x8f,0xee,0x1e,0xf,0x78,0x1b,0xc4,0x97,0xe3,0xe7,0x81,0xdf,0x81,0xf4,0xaf,0x18,0xfc,0x72,0xf8,0xf,0x6e,0x1e,0x26,0x10,0xf,0x2f,0xfc,0xfe,0xf0,0xf,0x69,0x1d,0x2a,0x30,0xf,0x3b,0xfd,0xc0,0x1e,0xf2,0xa9,0xc0,0x3c,0xff,0xf6,0x0,0x7b,0xc6,0xaf,0x0,0xf4,0xb0,0x87,0xfa,0xc6,0x3f,0xd2,0x0,0x97,0xf4,0x1f,0x7,0xf5,0x7,0xf8,0x3e,0x60,0xeb,0xf2,0x7,0xdf,0xf9,0xbe,0x5e,0x0,0x79,0x4f,0xc1,0xed,0xfc,0x5,0x8,0x25,0x80,0x1e,0x0,0xf0,0x7,0x80,0x24 -}; - -const uint8_t _A_L0_Url_128x51_2[] = { - 0x1,0x0,0x29,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0x16,0xf0,0x38,0x80,0x3f,0x28,0x10,0x40,0x7f,0x58,0x27,0x10,0x32,0x7d,0xd0,0x32,0xd9,0x8,0x20,0x3f,0x32,0x80,0xff,0x7,0xee,0x2,0xc7,0x10,0x1f,0xe2,0x7f,0xc1,0xfe,0xf,0xf0,0x7d,0x7e,0x1,0x89,0x4,0x7,0xc4,0x72,0x83,0x5,0x80,0x42,0x1,0xe5,0x2,0xa0,0x3,0xd7,0x75,0x22,0x80,0x83,0xca,0x4,0x1,0x1d,0x7,0xfe,0x3f,0xfc,0x7,0x97,0xca,0x45,0x75,0x87,0x73,0xa4,0x99,0x2c,0x74,0xf,0xa1,0xff,0xf3,0xfc,0xc1,0xe5,0x3e,0xb1,0x65,0x62,0x52,0x99,0x2e,0x46,0xa5,0x2,0xf8,0x7f,0xe7,0x7e,0xe0,0x79,0x5e,0xa4,0x40,0xf1,0xf4,0x83,0xd7,0xdb,0xdf,0x7,0x9c,0x8c,0x3e,0x5a,0x4c,0x80,0x3c,0xe2,0xdb,0xf0,0x79,0x7f,0x24,0x37,0x5a,0x77,0x3b,0x31,0xe0,0x1f,0x88,0x3c,0x7d,0xdb,0xe3,0xfa,0x44,0xb,0x82,0x0,0x10,0x18,0xfc,0x2f,0xff,0xfb,0xf2,0x7d,0x1,0xed,0xc0,0xbf,0x80,0x9,0x5f,0x40,0xf1,0x1f,0x8,0x3f,0x53,0xc2,0x1f,0xf0,0x7b,0xfe,0x17,0x43,0x1,0x5f,0x8f,0xf8,0xde,0x60,0x4,0x83,0x14,0x9,0x7e,0x20,0xf9,0x81,0xbc,0x49,0x7e,0x3f,0xdc,0xf8,0x3e,0xd1,0xe3,0xfb,0x87,0x83,0xdf,0x87,0x89,0x84,0x3,0xcb,0xcf,0x3,0xbf,0x3,0xda,0x47,0x4a,0x8c,0x3,0xca,0x3f,0x1c,0xbe,0x3,0xde,0x55,0x38,0x7,0x97,0xfe,0x7f,0x78,0x7,0xbc,0x6a,0xf0,0xf,0x3b,0xfd,0xc0,0x3f,0xbf,0xfb,0x0,0xff,0x0,0x3,0x61,0x2f,0xe0,0x0,0x6c,0x67,0xfc,0x20,0x10,0x3f,0xc1,0xed,0x7,0x5f,0x90,0x3e,0xff,0xcd,0xf2,0xf0,0x3,0xca,0x7e,0xf,0x6f,0xe0,0x28,0x41,0x2c,0x0,0xf0,0x7,0x80,0x3c,0x1,0x20 -}; - -const uint8_t _A_L0_Url_128x51_3[] = { - 0x1,0x0,0x2a,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf8,0x7,0xfc,0x0,0x33,0xf0,0x75,0x60,0x1,0xe5,0x7f,0x7,0xde,0x4e,0x49,0x49,0xb9,0x3,0xfc,0x16,0xf0,0x38,0x80,0x3f,0x28,0x10,0x40,0x7f,0x58,0x27,0x10,0x32,0x7d,0xd0,0x32,0xd9,0x8,0x20,0x3f,0x32,0x80,0xff,0x7,0xee,0x2,0xc7,0x10,0x1f,0xe2,0x7f,0xc1,0xfe,0xf,0xf0,0x7d,0x7e,0x1,0x89,0x4,0x7,0xc4,0x72,0x83,0x5,0x80,0x42,0x1,0xe5,0x2,0xa0,0x3,0xd7,0x75,0x22,0x80,0x83,0xca,0x4,0x1,0x1d,0x7,0xfe,0xe,0xf,0x3f,0x94,0x8a,0xeb,0xe,0xe7,0x49,0x32,0x58,0xe8,0x1f,0x43,0xff,0xf9,0xfe,0x3,0xca,0x7d,0x62,0xca,0xc4,0xa5,0x32,0x5c,0x8d,0x4a,0x5,0xf0,0xff,0xe3,0xbf,0x60,0xf2,0xbd,0x48,0x81,0xe3,0xe9,0x7,0xa5,0xff,0xf7,0xf7,0x7,0x9c,0x8c,0x3e,0x5a,0x4c,0x80,0x3c,0xb7,0xf1,0xdf,0x78,0x3c,0xbf,0x92,0x1b,0xad,0x3b,0x9d,0x98,0xf0,0xf,0xc4,0x1e,0x3e,0xff,0x71,0xfd,0x22,0x5,0xc1,0x0,0x8,0xc,0x7e,0x1d,0xff,0xff,0x79,0x3e,0x80,0xf6,0xe0,0x77,0xef,0xe0,0x11,0x57,0xd0,0x3c,0x77,0xe0,0xfe,0xff,0x87,0xfc,0x1f,0x1f,0x85,0xd0,0xc0,0x68,0x1b,0xff,0xf9,0xbc,0xc0,0x9,0x6,0x28,0x16,0x80,0x1f,0x50,0x37,0x89,0x74,0x2f,0xff,0xff,0x38,0x3e,0xd7,0xe3,0xfe,0xe1,0x83,0xdf,0x87,0x89,0x84,0x3,0xcb,0xf3,0x80,0x7,0xbc,0x8e,0x95,0x18,0x7,0x94,0x1e,0xe,0xf,0x89,0x54,0xe0,0x1e,0x5f,0xf8,0x7d,0xf8,0x1e,0xf1,0xab,0xc0,0x3c,0xe3,0xf7,0xc0,0xfe,0xcf,0xef,0x3,0xfc,0xff,0xdf,0xc1,0xee,0x5f,0x50,0x0,0x83,0xdc,0xfe,0xa2,0x2,0x7,0xf8,0x3d,0xa0,0xeb,0xf2,0x7,0xdf,0xf9,0xbe,0x5e,0x0,0x79,0x4f,0xc1,0xed,0xfc,0x5,0x8,0x25,0x80,0x1e,0x0,0xf0,0x7,0x80,0x24 -}; - - -const uint8_t * const _A_L0_Url_128x51[] = { - - _A_L0_Url_128x51_0, - - _A_L0_Url_128x51_1, - - _A_L0_Url_128x51_2, - - _A_L0_Url_128x51_3, - -}; - - - -const uint8_t L0_Url_128x51_frame_order[] = { 0, 1, 2, 3 }; - -const BubbleAnimation BA_L0_Url_128x51 = { - .icon_animation = { - .width = 128, - .height = 51, - .frame_count = 4, - .frame_rate = 2, - .frames = _A_L0_Url_128x51 - }, - .frame_order = L0_Url_128x51_frame_order, - .passive_frames = 4, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 0, - - .frame_bubble_sequences = NULL, - .frame_bubble_sequences_count = 0, - -}; - - -const uint8_t _A_L0_NewMail_128x51_0[] = { - 0x1,0x0,0x50,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf0,0x7,0x80,0x3c,0x1,0xe0,0x6,0xf8,0x40,0x40,0x63,0x30,0xfb,0x73,0x61,0x80,0xf7,0xfe,0x41,0xc0,0x63,0x70,0x9b,0x73,0x1,0xf1,0xfe,0x87,0x83,0xf7,0xff,0x1f,0x1,0x8e,0xc3,0xed,0xd9,0x83,0x3,0xdf,0x7e,0xf,0x39,0xb7,0x60,0x1e,0xf8,0xc,0xfc,0xfc,0x9e,0x53,0x7f,0xc1,0x14,0x81,0xeb,0xbf,0x7,0xa4,0xc2,0x6,0xa,0x2f,0xf8,0x0,0xc1,0xe9,0xf6,0x98,0x83,0xcb,0x80,0x1f,0x80,0x2,0xd0,0x11,0x24,0xf,0xc8,0x10,0x14,0xe1,0xf1,0xe0,0x7c,0x41,0xf,0xef,0xc,0xe3,0x6c,0x6c,0x20,0xf2,0x84,0x27,0xde,0x39,0xc7,0x7,0xa4,0x40,0x1e,0x7f,0xd3,0xc9,0x47,0x2c,0xfb,0x30,0x79,0xc8,0x9,0xe6,0xdf,0x3d,0xe0,0x3d,0x68,0x4,0x43,0x2,0x1e,0xb3,0xcd,0xb3,0x90,0x82,0x8b,0x0,0xa,0x29,0x0,0x3c,0xfd,0x93,0x6d,0xb0,0x3c,0xe0,0x2,0xa2,0x88,0x3,0xce,0x98,0xf,0x10,0x51,0x2,0x45,0x0,0x50,0x80,0x7b,0x5b,0xc1,0xe6,0x80,0x28,0x20,0x3c,0xd1,0xec,0x1c,0x10,0x20,0xc0,0x81,0xf6,0x80,0x28,0x8,0x3e,0xe6,0x7,0xe1,0x7,0xe5,0x21,0xa6,0x40,0xfb,0xc2,0x1f,0x84,0x9e,0x9f,0xef,0xf8,0x0,0x4e,0x2,0x6f,0x28,0xc,0x40,0xde,0x63,0x41,0x9,0x91,0xec,0x51,0xe5,0x2,0x84,0x23,0xcf,0x80,0x2d,0x33,0xd8,0xab,0xca,0x9,0x4,0x57,0x98,0x3d,0xc1,0x43,0xf8,0x81,0xb3,0xcf,0x81,0x8,0x16,0xc,0x20,0x1e,0x4e,0xf4,0x7,0x9c,0x62,0x7,0x0,0x8c,0x3,0xc9,0x1c,0x40,0x1,0xa0,0x83,0xcb,0x51,0x32,0xb3,0xce,0x1,0xe4,0xae,0x20,0x0,0xd0,0x81,0xe5,0x48,0xa5,0x64,0x6f,0x0,0xf2,0x67,0x10,0x0,0x68,0x83,0xf3,0xa5,0x7c,0x43,0xe6,0xee,0x20,0x0,0xa8,0xc4,0x1e,0x71,0x11,0xf9,0xa1,0x8e,0x1,0x50,0x7,0x9c,0xca,0xc2,0x5f,0x23,0xb2,0x40,0x2c,0x7,0xf8,0xc0,0x2d,0x48,0x0,0x33,0xf0,0x7c,0x0,0x23,0x80,0xbf,0x50,0x4,0xa,0x10,0x98,0x80,0x6,0x7,0x98,0x3a,0x80,0x1e,0x0,0xf0,0x7,0x80,0x14 -}; - -const uint8_t _A_L0_NewMail_128x51_1[] = { - 0x1,0x0,0x5d,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf0,0x7,0x80,0x3c,0x1,0xe0,0xa,0x98,0x7d,0xb9,0xb0,0xc0,0x7d,0xdc,0x26,0xdc,0xc0,0x7f,0x83,0xe3,0xe1,0x1,0x1,0x8e,0xc3,0xed,0xd9,0x83,0x3,0x13,0xfd,0xf,0x80,0x7f,0x20,0xe0,0xf2,0x9b,0x76,0x1,0xe9,0xc0,0x80,0xdc,0x2,0x46,0x4f,0x19,0xbf,0xe0,0x2a,0x40,0x1,0x9c,0x7f,0xb1,0xf0,0x3f,0xfc,0x7c,0x1e,0x73,0x8,0x18,0x38,0xb0,0x1c,0x7f,0xfd,0xfe,0x79,0xbf,0x7,0x9f,0xda,0x62,0xf,0x3b,0x87,0xf3,0xff,0xff,0xe3,0xe7,0xe7,0xe6,0x68,0xe7,0x3,0x84,0x0,0x3b,0xf0,0x7c,0x60,0x1,0xc6,0xf,0xae,0x0,0x3e,0x21,0x9c,0x6d,0x8d,0x84,0xa,0x34,0x0,0x7c,0x47,0x38,0xe0,0xf4,0x41,0xa4,0x3e,0x3c,0xf,0x2b,0x3e,0xcc,0x1e,0x70,0x40,0x79,0x9f,0xcf,0x78,0xf,0x58,0x42,0xc9,0xa0,0x1a,0xcf,0x36,0xce,0x42,0xf,0x28,0x80,0x3c,0xff,0xaa,0x92,0xf6,0x4d,0xb6,0xc0,0xf3,0xd0,0x13,0x8d,0xbe,0x74,0xc0,0x78,0x81,0x4a,0x81,0x40,0xf,0x10,0x11,0x1,0xe5,0x6f,0x5,0x16,0x0,0x14,0x52,0x0,0x79,0x80,0x14,0x12,0x22,0x42,0x88,0x3,0xef,0xfc,0x3f,0x18,0x78,0x3e,0xf0,0x82,0xe1,0x82,0x3,0xee,0x90,0x3,0x18,0x10,0x3e,0xe6,0xe,0x31,0x80,0x83,0xcc,0x6e,0x5f,0xf2,0x58,0x82,0x45,0x20,0x40,0xf3,0xa,0x8,0x4c,0xa0,0x40,0xf2,0x58,0x10,0xbc,0xf8,0x2,0xd3,0x66,0x8,0x24,0x5a,0x4,0x4f,0x30,0x7c,0x8,0xc4,0x44,0x20,0xf3,0x84,0x2,0x6,0x10,0xf,0x34,0x7b,0x70,0x23,0x10,0x38,0x4,0x60,0x1e,0x4a,0xf7,0xe0,0x6a,0x26,0x56,0x79,0xc0,0x3c,0x99,0xef,0xc0,0xa4,0x52,0xb2,0x37,0x80,0x79,0x48,0x1,0xe5,0x80,0x1f,0xa5,0x2b,0xe2,0x1f,0x33,0xf1,0x0,0x6,0x82,0xf,0x48,0x88,0xfc,0xcf,0xc4,0x0,0x1a,0x10,0x3c,0xe6,0x56,0x12,0xf9,0x9f,0x88,0x0,0x34,0x43,0xfc,0x9f,0x88,0x0,0x2d,0x31,0x7,0xc2,0xd8,0xe0,0x15,0x0,0x79,0x2f,0xd4,0x2c,0x90,0xb,0x1,0x8c,0x9b,0xc4,0xdf,0x20,0x32,0x7f,0xe7,0xe1,0x32,0x3,0x98,0x71,0x0,0x1e,0x0,0xf0,0x7,0x80,0x2c -}; - -const uint8_t _A_L0_NewMail_128x51_2[] = { - 0x1,0x0,0x79,0x1,0x0,0x78,0x3,0xc0,0x1e,0x0,0xf0,0x1,0xfc,0x20,0x20,0xfd,0x84,0x40,0x81,0xfb,0xf6,0x86,0x83,0xf7,0xf3,0x13,0x3,0x24,0xc3,0xed,0xcd,0x86,0x1,0xcf,0x81,0xfe,0xb7,0x83,0xd2,0xe1,0x36,0xe6,0x3,0xd2,0x41,0xff,0xcf,0x83,0xf3,0xb1,0xff,0xbf,0xc0,0xc0,0xe7,0xb0,0xfb,0x76,0x60,0xc0,0x73,0xf2,0x7f,0xff,0xf0,0x40,0x7a,0x4d,0xbb,0x0,0xf4,0xfd,0x83,0xc6,0x36,0x82,0x39,0x84,0xdf,0xf1,0x7,0x7,0x16,0x3,0xf8,0xf,0x19,0x3f,0xf0,0x12,0x40,0xf1,0x98,0xd,0xcc,0x1c,0x40,0x2,0x87,0x9b,0xce,0x62,0xf,0x31,0xda,0x7f,0xe3,0xe8,0xd8,0x7,0xa6,0xfc,0x1f,0x25,0x33,0xc0,0x67,0xe7,0xe0,0xf8,0x82,0x83,0xcf,0x7e,0xf,0x28,0x67,0x1b,0x63,0x61,0x5,0x16,0x1c,0x9a,0x5b,0xf0,0x79,0xc7,0x38,0xe0,0xf3,0xe0,0x1c,0xd0,0x1e,0x96,0x7d,0x98,0x3c,0xa8,0x0,0xf8,0xde,0x3,0xd5,0x46,0x90,0xf8,0xf0,0xc,0x75,0x9e,0x6d,0x9c,0x84,0x1e,0x58,0x41,0xf9,0x4f,0xcf,0xe7,0xec,0x9b,0x6d,0x81,0xe7,0x8,0xf,0x9f,0xf9,0x3e,0x54,0xc0,0x78,0xb1,0x4a,0x81,0x10,0x7,0x9f,0xf4,0x8a,0x40,0xf2,0xb7,0x83,0xca,0x40,0x4f,0x36,0xf9,0x80,0x16,0x81,0xc0,0x1f,0x95,0xfe,0x80,0x9e,0x8a,0x6,0x0,0x8,0x52,0x0,0x7d,0x40,0x5,0x45,0x10,0x7,0xdc,0x8,0xd8,0x30,0x80,0x7d,0xff,0x20,0x1e,0x8,0x38,0x3c,0xff,0xc4,0x82,0x15,0x88,0x24,0x69,0x0,0x31,0x81,0x3,0xcb,0x0,0x62,0x38,0x10,0x3c,0xa6,0x0,0xa2,0x7,0x97,0x0,0x5a,0x70,0x40,0x79,0x24,0x8,0x1f,0x8b,0x2,0x17,0x9f,0x2,0x10,0x2c,0x18,0x40,0x3c,0xc0,0x62,0x2,0x10,0x79,0xc6,0x20,0x70,0x8,0xc0,0x3c,0xc2,0xc2,0x17,0x10,0x79,0xea,0x26,0x56,0x79,0xc0,0x3c,0xd1,0xed,0xc0,0xa4,0x52,0xb2,0x37,0x80,0x79,0x2b,0xdc,0x7e,0x34,0xaf,0x88,0x7c,0xd1,0x46,0x4,0x30,0x79,0x44,0x47,0xe6,0xef,0x40,0x7a,0x4c,0xac,0x25,0xf3,0x3f,0x10,0x0,0x68,0x27,0xf9,0x3f,0x10,0x0,0x68,0x40,0xf9,0x3f,0x10,0x0,0x68,0x80,0xf2,0x5f,0xb1,0xf8,0x80,0x2,0xd3,0x12,0x18,0xb7,0x89,0xbe,0x61,0x63,0x80,0x54,0x0,0x64,0xf,0x31,0xb3,0x40,0x2c,0x0,0x54,0x0,0x18,0x99,0x3f,0xf3,0xf0,0x7c,0x0,0x3c,0x1,0xc0 -}; - -const uint8_t _A_L0_NewMail_128x51_3[] = { - 0x1,0x0,0x77,0x1,0x0,0x1f,0xe2,0x6,0xf,0xd8,0x24,0x10,0x1f,0xbf,0xa8,0x58,0x3f,0x7f,0xb1,0x70,0x76,0x60,0x3f,0xd2,0xf0,0x7e,0x50,0x3f,0xf5,0xf0,0x7e,0x68,0x3f,0xfb,0xf0,0x7e,0x74,0x3f,0xf7,0xf8,0x8,0x1c,0xe6,0x1f,0x6e,0x6c,0x30,0xc,0x5f,0xcf,0xf8,0x0,0xa0,0xe0,0x82,0xb8,0x4d,0xb9,0x80,0xf3,0x3e,0x20,0x10,0xc1,0xff,0xb0,0xfb,0x76,0x60,0xc0,0xfc,0x9b,0x76,0x1,0xf9,0x30,0x9b,0xfe,0x8,0xc7,0x84,0x27,0x14,0xff,0xe8,0x61,0x20,0x78,0xcc,0x1b,0x6,0x1f,0x4f,0xe0,0x64,0x8d,0xe3,0x31,0x7,0xc7,0xfa,0x1e,0xed,0x90,0x21,0xff,0xe3,0xe0,0xf8,0x1f,0xa6,0xfc,0x1f,0x26,0x33,0xc0,0x67,0xe7,0xe0,0x41,0x86,0x71,0xb6,0x36,0x10,0x59,0x41,0x41,0xe7,0xbf,0x7,0x94,0x73,0x8e,0xf,0x3c,0x0,0x7d,0x1,0xe9,0x67,0xd9,0x83,0xcb,0x81,0x87,0x1f,0x96,0xfc,0x1e,0x7b,0xc0,0x7a,0x50,0x12,0x66,0x1f,0x4d,0x67,0x9b,0x67,0x21,0x7,0x90,0xbc,0xe0,0x10,0xf8,0xf0,0xc,0x7d,0x93,0x6d,0xb0,0x3c,0xcf,0xf1,0x4c,0x7,0x8a,0xd4,0xa8,0x18,0x83,0xf9,0xa7,0xcc,0x1e,0x56,0xf0,0x79,0x44,0x3,0xe7,0xfd,0x22,0x98,0x1,0x28,0x12,0x2,0x79,0xfc,0x5,0x24,0xf,0x6a,0x0,0x11,0xc1,0xed,0x80,0x1f,0x98,0x3e,0xa0,0x2,0xa2,0x88,0x3,0xee,0x4,0x6c,0x18,0x40,0x3c,0xff,0xc2,0x82,0xd,0x88,0x24,0x70,0x90,0x9,0x4,0x10,0x1e,0x58,0x2,0x91,0xc0,0x81,0xe5,0x48,0x1,0x8c,0x8,0x1e,0x5c,0x1,0x69,0xa7,0x4,0x12,0x33,0x0,0xd1,0x3,0xed,0x20,0x40,0xf4,0x84,0xb,0x6,0x10,0xf,0x38,0x40,0xd8,0x81,0xe7,0x18,0x81,0xc0,0x23,0x0,0xf3,0x68,0x11,0x3c,0xf8,0x1a,0x89,0x95,0x9e,0x70,0xf,0x31,0x30,0x88,0x84,0x1e,0x74,0x8a,0x56,0x46,0xf0,0xf,0x34,0x7b,0xf,0xc6,0x95,0xf1,0xf,0x9e,0x0,0xac,0x52,0x0,0x7a,0xc4,0x47,0xe6,0xcf,0x70,0x78,0xcc,0xac,0x25,0xf3,0x77,0xa1,0xfe,0x8f,0xc4,0x0,0x1a,0x8,0x3e,0x4f,0xc4,0x0,0x1a,0x10,0x3c,0x97,0xec,0x7e,0x20,0x0,0xd1,0x6,0x64,0xde,0x26,0xf9,0x9f,0x88,0x0,0x2d,0x31,0x0,0x8,0x3c,0xcb,0x44,0x26,0x38,0x5,0x40,0x8,0x60,0x4,0x23,0x24,0x2,0xc0,0xf,0x81,0xb2,0x7f,0xe7,0xe0,0xf8,0x0,0x70 -}; - - -const uint8_t * const _A_L0_NewMail_128x51[] = { - - _A_L0_NewMail_128x51_0, - - _A_L0_NewMail_128x51_1, - - _A_L0_NewMail_128x51_2, - - _A_L0_NewMail_128x51_3, - -}; - - - -const uint8_t L0_NewMail_128x51_frame_order[] = { 0, 1, 2, 3, 2, 1 }; - -const BubbleAnimation BA_L0_NewMail_128x51 = { - .icon_animation = { - .width = 128, - .height = 51, - .frame_count = 4, - .frame_rate = 2, - .frames = _A_L0_NewMail_128x51 - }, - .frame_order = L0_NewMail_128x51_frame_order, - .passive_frames = 6, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 0, - - .frame_bubble_sequences = NULL, - .frame_bubble_sequences_count = 0, - -}; - - -const StorageAnimation dolphin_blocking[] = { - - { - .animation = &BA_L0_NoDb_128x51, - .manifest_info = { - .name = "L0_NoDb_128x51", - .min_butthurt = 0, - .max_butthurt = 0, - .min_level = 0, - .max_level = 0, - .weight = 0, - } - }, - - { - .animation = &BA_L0_SdBad_128x51, - .manifest_info = { - .name = "L0_SdBad_128x51", - .min_butthurt = 0, - .max_butthurt = 0, - .min_level = 0, - .max_level = 0, - .weight = 0, - } - }, - - { - .animation = &BA_L0_SdOk_128x51, - .manifest_info = { - .name = "L0_SdOk_128x51", - .min_butthurt = 0, - .max_butthurt = 0, - .min_level = 0, - .max_level = 0, - .weight = 0, - } - }, - - { - .animation = &BA_L0_Url_128x51, - .manifest_info = { - .name = "L0_Url_128x51", - .min_butthurt = 0, - .max_butthurt = 0, - .min_level = 0, - .max_level = 0, - .weight = 0, - } - }, - - { - .animation = &BA_L0_NewMail_128x51, - .manifest_info = { - .name = "L0_NewMail_128x51", - .min_butthurt = 0, - .max_butthurt = 0, - .min_level = 0, - .max_level = 0, - .weight = 0, - } - }, - -}; - -const size_t dolphin_blocking_size = COUNT_OF(dolphin_blocking); diff --git a/assets/compiled/assets_dolphin_blocking.h b/assets/compiled/assets_dolphin_blocking.h deleted file mode 100644 index ba3996ca..00000000 --- a/assets/compiled/assets_dolphin_blocking.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -extern const StorageAnimation dolphin_blocking[]; -extern const size_t dolphin_blocking_size; diff --git a/assets/compiled/assets_dolphin_internal.c b/assets/compiled/assets_dolphin_internal.c deleted file mode 100644 index 8400052c..00000000 --- a/assets/compiled/assets_dolphin_internal.c +++ /dev/null @@ -1,330 +0,0 @@ -#include -#include -#include -#include - - - -const uint8_t _A_L1_Tv_128x47_0[] = { - 0x1,0x0,0xca,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x66,0x33,0x30,0x50,0x81,0x88,0x1e,0xd0,0x50,0x19,0xa,0x8a,0x8,0x24,0x21,0x31,0x40,0x38,0x0,0x81,0x2d,0x20,0x8,0x41,0xeb,0x38,0x7,0xc0,0xb4,0x46,0xc4,0x78,0x10,0x79,0x80,0xc8,0x64,0x20,0xf4,0x86,0x2,0xcc,0x1e,0xa6,0x21,0xe8,0x40,0x21,0xe5,0x61,0x82,0x60,0x2f,0xe0,0xf7,0xa8,0x78,0x66,0x7,0x61,0x81,0x58,0x11,0xa3,0x2,0xc0,0x43,0xce,0x47,0x48,0x8f,0x25,0x8a,0x5,0x30,0x80,0x41,0x90,0x64,0xf,0x43,0xf9,0xc0,0x7f,0x5,0xb1,0x81,0x78,0x27,0xe0,0xf1,0xff,0xff,0xc7,0x2,0xba,0x20,0x30,0xc0,0x7e,0x10,0x3f,0x4,0x9f,0xc1,0x1f,0x22,0x8e,0x10,0x1e,0x56,0x1,0x39,0x2,0xc6,0xc1,0x26,0xf0,0x48,0xc4,0xc3,0x82,0x7,0x94,0x78,0x1e,0x5c,0x8,0x1f,0x2,0x27,0xc0,0xa0,0x8d,0x8a,0x7,0x0,0xf0,0x38,0x8a,0x8,0x55,0x12,0xf8,0xf0,0x11,0xc3,0x10,0x80,0xa3,0x44,0xec,0x41,0x71,0x30,0x8b,0x1c,0x81,0xe7,0xf0,0x9f,0xae,0x48,0x1e,0x20,0x43,0x7,0x96,0x80,0xa,0x34,0x0,0x51,0xc4,0x16,0x46,0xf,0xa9,0x7,0xd0,0x1e,0xbf,0x2,0x58,0x83,0xd6,0x18,0x5f,0x10,0x79,0xff,0x20,0xe0,0xf1,0x27,0x9d,0x2,0x9,0x7c,0x63,0x88,0x3c,0xbf,0xd0,0xf0,0x7a,0xe0,0x21,0x6,0xe1,0x16,0xe,0xf,0xff,0xfd,0xfb,0xaa,0xc7,0xfe,0xa6,0x10,0x78,0x9b,0xce,0x19,0x9c,0xff,0xa3,0x4,0x1e,0x51,0xd0,0x59,0x70,0x52,0xe2,0xa4,0x1d,0xc0,0x30,0x80,0x3,0x3f,0xf,0x97,0xe0,0x54,0x22,0xf1,0x45,0x88,0x3d,0x39,0xe0,0xf1,0xc0,0x15,0x87,0xff,0x3,0x26,0x8f,0x81,0xf8,0x64,0x61,0x7,0x8d,0xc0,0xa,0x3f,0xc0,0xa0,0x8f,0x10,0x0,0x3f,0x30,0x78,0xc3,0x82,0xe7,0x40,0x7,0xb7,0xd2,0x7f,0xf0,0xe0,0x83,0xd7,0xf8,0xe,0x3b,0xff,0xdf,0xbf,0xf,0xd3,0x18,0x8c,0x1e,0x3c,0x30,0x79,0xe7,0xfe,0xf1,0xfd,0x85,0xe6,0xfc,0xb3,0x3c,0x6,0x0,0x1e,0x7e,0xf0,0x78,0xd3,0xe9,0x39,0x26,0x38,0x83,0xc6,0x80,0xf,0x4f,0x9f,0xdf,0x3e,0x5,0x23,0xe8,0x83,0xc4,0x40,0x24,0x63,0xfe,0x3,0xc4,0xa,0x51,0x80,0x7a,0x7,0xcd,0x84,0x31,0xf1,0x61,0x47,0x1,0xe5,0x10,0x7,0xbc,0x8,0x18,0x31,0xe0,0x10,0xd8,0x1,0xf1,0x4,0x6,0x8,0xfc,0xae,0xf,0x31,0xf3,0x83,0xd4,0x78,0x3c,0x6,0x99,0x6f,0x1,0xe3,0xc3,0xb,0xf,0xe0,0x1e,0x56,0x6,0x18,0xdf,0xc1,0xe3,0x3f,0x83,0x83,0xc7,0x5f,0x32,0xfd,0x83,0xc5,0x6a,0x8f,0x72,0x68,0x8f,0x9c,0x3e,0xae,0x64,0x80,0x4e,0x1,0xe2,0x4f,0x60,0x7a,0xc8,0x1,0xfe,0x2f,0x20,0x7f,0x0 -}; - -const uint8_t _A_L1_Tv_128x47_1[] = { - 0x1,0x0,0xcc,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x9c,0xaf,0xe0,0xf9,0x10,0x88,0x28,0x6c,0x8,0xd1,0x81,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xe3,0x30,0x41,0x8a,0xdc,0x81,0xea,0x1,0x10,0x50,0xfe,0x0,0xa3,0x2,0xf0,0x4f,0xc1,0xe3,0xff,0x0,0x14,0x3e,0x1,0xfe,0x2,0xc,0x7,0xe1,0x3,0xf0,0x49,0xfc,0x11,0xf1,0x50,0xc1,0x3c,0xe,0x61,0x8,0x88,0x88,0x41,0x63,0x20,0x7,0x8c,0xfc,0x4c,0x30,0x68,0xe1,0x70,0x60,0x60,0xf2,0xe0,0x40,0xf8,0x11,0x3e,0x5,0x1c,0x1e,0x31,0xa0,0x60,0xf8,0xf,0xa6,0x75,0x12,0xf8,0xf0,0x30,0x65,0xc1,0xf2,0x82,0xc6,0xf0,0xad,0x33,0x8,0xae,0x8,0x1e,0x50,0x50,0x30,0xc7,0x81,0xe6,0xa3,0x30,0x79,0x68,0x12,0xc4,0x50,0x14,0xd1,0x1,0xc8,0x1e,0x81,0x72,0x27,0x12,0x28,0x7e,0x80,0xf5,0xf8,0x44,0x60,0x10,0xe0,0xf9,0xc8,0x21,0x85,0xf1,0x7,0x9f,0xf3,0xcf,0xc0,0x84,0xc1,0x81,0xe5,0x40,0x82,0x5f,0x26,0x10,0x10,0x79,0x7f,0xa1,0xf3,0xf8,0x80,0x3c,0xf0,0x10,0x83,0x70,0x8b,0x7,0x3f,0xff,0xfe,0xfd,0xd6,0x24,0xa6,0x10,0x78,0x9b,0xce,0x19,0xbc,0xff,0xa3,0x4,0x1e,0x51,0xd0,0x59,0x70,0x54,0x87,0xf8,0x67,0x9f,0xfe,0x7e,0x1f,0x2f,0xc6,0xc,0x4a,0x4d,0x41,0x7,0xa7,0x3c,0x12,0x38,0x3,0x18,0xff,0xe0,0xf8,0x5,0xca,0x0,0x7,0xe0,0xf,0x1b,0x80,0x14,0x7f,0x90,0x10,0x79,0x7,0xd3,0xe6,0xf,0x18,0x70,0x5c,0xe8,0x0,0xf6,0xfa,0x4f,0xfe,0x1c,0x10,0x7a,0xff,0x1,0xc7,0x7f,0xfb,0xf7,0xe1,0xfa,0x63,0x11,0x83,0xc4,0x3c,0x99,0xff,0xbc,0x7f,0x61,0x79,0xbf,0x2c,0xcf,0x1,0x87,0x7,0x9f,0xbc,0x1e,0x34,0xfa,0x4e,0x4a,0x2,0xf,0x2e,0x6,0x4,0x9c,0x9f,0x75,0x30,0x80,0x8,0x1e,0x5e,0x3,0x8,0x80,0xb,0xf8,0xf,0x10,0x29,0x7e,0x1,0xe5,0x60,0xc0,0x6,0xd,0x84,0x31,0xf1,0x61,0x7f,0x1,0xe5,0x30,0x7,0xbc,0x8,0x18,0x25,0x2,0xb0,0x3,0xe2,0x8,0xc,0x1b,0xf8,0x8,0x6e,0x11,0x8c,0x7,0x9c,0x1e,0xb1,0x88,0x7,0x0,0x9e,0x5b,0xc0,0x78,0xf0,0xe1,0xe4,0x81,0x7,0x95,0x81,0x86,0x3f,0xf7,0x78,0xcf,0xe1,0xe0,0xf1,0xd7,0xcc,0xbf,0x60,0xf1,0x4b,0x23,0xdc,0x9c,0xc3,0xe7,0xf,0xab,0x99,0x20,0x13,0x80,0x78,0x93,0xd8,0x1e,0xb2,0x0,0x7f,0x8b,0xc8,0x1f,0xc0 -}; - -const uint8_t _A_L1_Tv_128x47_2[] = { - 0x1,0x0,0xc1,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x66,0x33,0x30,0x50,0x81,0x88,0x1e,0xd0,0x50,0x19,0xa,0x8a,0x8,0x24,0x21,0x31,0x40,0x38,0x0,0x81,0x2d,0x20,0x8,0x41,0xeb,0x38,0x7,0xc0,0xb4,0x46,0xc4,0x78,0x10,0x79,0x80,0xc8,0x64,0x20,0xf4,0x86,0x2,0xcc,0x1e,0xa6,0x21,0xe8,0x40,0x21,0xe5,0x61,0x7,0xd5,0x43,0xc3,0x30,0x3b,0x9,0xbc,0xe0,0x58,0x8,0x79,0xc8,0xe9,0x11,0xe4,0xb1,0x3,0xd1,0x4,0xb4,0x83,0xf9,0xa8,0xce,0x5,0xe0,0x9f,0x83,0xc7,0xff,0xff,0xbf,0xae,0x8c,0xc,0x20,0x1,0x81,0xf8,0x24,0xfe,0x8,0xf9,0x14,0x70,0x80,0xf2,0xb0,0x8,0xce,0x3d,0x60,0x93,0x78,0x24,0x68,0x21,0xc1,0x2,0x8c,0x1e,0x70,0x3e,0x4,0x4f,0x81,0x41,0x7,0x8c,0xa,0x7,0x0,0xf0,0xf,0x8c,0xaa,0x25,0xf1,0xe0,0x23,0x86,0x21,0x1,0x46,0x89,0xd8,0x80,0x3,0x30,0x9,0x98,0x3c,0xfe,0x13,0xf5,0xc9,0x40,0x3f,0x10,0x90,0x7a,0xe8,0x0,0xa3,0x40,0x7,0x9c,0x1e,0xc,0xf,0xc1,0xe8,0xfd,0x1,0xeb,0xf0,0x25,0x88,0x3c,0xd1,0x23,0xfc,0x2f,0x88,0x3c,0xff,0x90,0x70,0x78,0x93,0xc8,0x4,0x3e,0xb,0xfb,0x1c,0x41,0xe5,0xfe,0x87,0x83,0xdb,0x81,0xe1,0x4,0x8f,0xc3,0x7,0xff,0xfe,0xfd,0xd5,0x44,0xa6,0x11,0x90,0xce,0x3e,0x1,0x51,0x86,0x67,0x3f,0xe2,0x71,0x7,0x94,0x74,0x1e,0x30,0x8f,0xe0,0x78,0x5a,0x43,0xb8,0x64,0x1f,0xfe,0x7e,0x1f,0x2f,0xc4,0x4e,0x1,0xe,0x73,0xf,0xc0,0x1e,0x9c,0xf0,0x79,0x44,0x3c,0x1c,0x8,0x19,0x34,0x7c,0xa,0x93,0x23,0x8,0x3c,0xdf,0x42,0xf,0x30,0xfa,0x7c,0xc1,0xe3,0x1e,0x40,0x9,0x3c,0x68,0x0,0xf6,0xfa,0x4f,0xfe,0x13,0x99,0x30,0x9c,0x81,0xe3,0xfc,0x7,0x1d,0xff,0xef,0xdf,0x87,0xfd,0xa7,0xe0,0xf4,0xe1,0x83,0xcf,0x3f,0xf7,0x8f,0xec,0x2f,0x37,0xe0,0x79,0x48,0x30,0x18,0x0,0x79,0xfb,0xc1,0xe3,0x4f,0xa4,0xe6,0x98,0xe2,0xf,0x1a,0x0,0x3d,0x3e,0x7f,0x7c,0xf8,0x14,0x91,0xc5,0x20,0x10,0x9,0xb8,0xff,0x80,0xf1,0x2,0x94,0x60,0x1e,0x81,0xf3,0x61,0xc,0x7c,0x58,0x51,0xc0,0x79,0x44,0x1,0xef,0x2,0x6,0xc,0x78,0x4,0x36,0x0,0x7c,0x41,0x1,0x82,0x3f,0x2b,0x84,0x23,0x1,0xe7,0x7,0xa8,0xf0,0x78,0xa,0x31,0x80,0x6f,0x1,0xe3,0xc3,0xb,0xf,0xe0,0x1e,0x56,0x5,0x68,0xdf,0xc1,0xe3,0x3f,0x83,0x83,0xc7,0x5f,0x32,0xfd,0x83,0xc5,0x6a,0x8f,0x72,0x80,0xb,0xc4,0x3e,0xae,0x64,0x80,0x4e,0x1,0xe2,0x4f,0x60,0x7a,0xb8,0xc4,0x1f,0xe5,0xf7,0x7,0xc0 -}; - -const uint8_t _A_L1_Tv_128x47_3[] = { - 0x1,0x0,0xc0,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x3f,0x44,0x22,0xa,0x23,0x61,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xea,0x82,0x50,0x78,0x80,0x45,0x84,0x90,0x2f,0x4,0xfc,0x1e,0x3f,0xf0,0x1,0x43,0xe0,0x1f,0xe0,0x31,0xc0,0xfc,0x12,0x7f,0x4,0x7c,0x54,0x30,0x4f,0x3,0x98,0x42,0x22,0x0,0x28,0xf4,0x80,0x1e,0x33,0xf1,0x60,0xc1,0xa3,0x87,0x41,0x81,0x83,0xce,0x7,0xc0,0x89,0xf0,0x28,0xe0,0xf1,0x8d,0x3,0x7,0xc0,0xe,0x33,0xa8,0x97,0xc7,0x81,0x83,0x2e,0xf,0x94,0x14,0x37,0x80,0x79,0xcc,0x2,0x66,0xf,0x28,0x28,0xe4,0x97,0xcc,0xf,0x3d,0x1,0xec,0x8a,0x2,0x9e,0x43,0x68,0x83,0xcc,0x2e,0x44,0xe4,0xf2,0x2e,0x4c,0x1e,0x3f,0x8,0x8c,0x2,0x1c,0x1f,0x39,0xe5,0xf2,0xd,0x18,0x7,0x9f,0xf3,0xcf,0xc0,0x84,0xc1,0x81,0xe5,0xc2,0x87,0xf3,0x11,0x82,0xf,0x2f,0xf4,0x3e,0x7f,0x10,0x7,0x9c,0x4,0x42,0x22,0xf1,0xf8,0x67,0xff,0xff,0xdf,0xba,0xa8,0x83,0x23,0x80,0x8,0x8c,0x38,0x9e,0x30,0xcd,0xe7,0xfd,0x18,0x20,0xf2,0x8e,0x83,0xcc,0x8a,0x50,0x2f,0xc3,0x20,0xff,0xf3,0xf0,0xf9,0xe0,0x4,0xa5,0x1,0xf8,0x3,0xd3,0x9e,0xf,0x31,0x38,0xc1,0xc0,0x84,0x79,0x32,0x30,0x83,0xc6,0xe1,0x1,0xfe,0x7f,0x20,0x21,0x43,0x0,0x1f,0xcc,0x1e,0x30,0xef,0xf3,0xa8,0x60,0x14,0x0,0x7b,0x7d,0x27,0xff,0xe,0x8,0x9c,0xc1,0xe3,0xfc,0x7,0x1d,0xff,0xef,0xdf,0x87,0xe9,0x8c,0x42,0xf,0x30,0xf2,0x67,0xfe,0xf1,0xfd,0x85,0xe6,0xfc,0xf,0x29,0x6,0x3,0xe,0xf,0x3f,0x78,0x3c,0x69,0xf4,0x9c,0x92,0x80,0x41,0xe3,0xc0,0xc0,0x93,0x93,0xee,0xa6,0x10,0x1,0x3,0xcb,0xc0,0x96,0x20,0x0,0xff,0x1,0xe2,0x5,0x2f,0xc0,0x3c,0xac,0x9,0x41,0x0,0x13,0x8,0x63,0xe2,0xc2,0xfe,0x3,0xca,0x60,0xf,0x78,0x10,0x30,0x4a,0x5,0x60,0x7,0xc4,0x10,0x18,0x37,0xf0,0x10,0xdc,0x23,0x18,0xf,0x38,0x3d,0x63,0x10,0xe,0x1,0x3c,0xb7,0x80,0xf1,0xe1,0xc3,0xc9,0x2,0xf,0x2b,0x3,0xc,0x7f,0xf0,0x38,0x4,0xfe,0x1e,0xf,0x1d,0x7c,0xcb,0xf6,0xf,0x14,0xb2,0x3d,0xc9,0xcc,0x3e,0x70,0xfa,0xb9,0x92,0x1,0x38,0x7,0x89,0x3d,0x81,0xeb,0x20,0x7,0xf8,0xbc,0x81,0xfc -}; - -const uint8_t _A_L1_Tv_128x47_4[] = { - 0x1,0x0,0xcb,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x9c,0xaf,0xe0,0xf9,0x10,0x88,0x28,0x6c,0x8,0xd1,0x81,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xe3,0x30,0x41,0x8a,0xdc,0x81,0xea,0x1,0x10,0x50,0xfe,0x0,0xa3,0x2,0xf0,0x4f,0xc1,0xe3,0xff,0x0,0x14,0x3e,0x1,0xfe,0x2,0xc,0x7,0xe1,0x3,0xf0,0x49,0xfc,0x11,0xf1,0x50,0xc1,0x3c,0xe,0x61,0x61,0x10,0x74,0x63,0xf6,0x9,0x37,0x82,0x46,0x26,0x18,0x34,0x71,0x64,0x90,0x2e,0x4,0xf,0x81,0x13,0xe0,0x50,0x41,0xe3,0x1a,0x81,0x97,0x4,0xfa,0x67,0x51,0x2f,0x8f,0x0,0x32,0x31,0xf,0x28,0x2c,0x63,0xa,0xd3,0x30,0x8a,0xe0,0x81,0xe5,0x5,0x77,0x2c,0x20,0xca,0x25,0xd1,0x7,0x96,0x81,0x2c,0x44,0xe2,0xb,0x88,0x1c,0x55,0x24,0xf,0x25,0xd9,0x3,0xce,0x41,0xf4,0x1b,0x10,0x3c,0xbe,0x11,0x18,0x4,0x38,0x1e,0x90,0xc8,0x7c,0x58,0x1e,0x7f,0xcf,0x3f,0x2,0x12,0xa9,0x28,0x5,0x2,0x8,0x19,0x20,0x79,0x7f,0xa1,0xf3,0xf8,0x80,0x3c,0xf0,0x4,0xf3,0xf8,0x60,0xff,0xff,0xdf,0xba,0xc4,0x94,0xc2,0xf,0x13,0x79,0xc3,0x33,0x9f,0xf8,0x7,0x80,0x1e,0x51,0xd0,0x59,0x70,0x52,0xe2,0xa4,0x1d,0xc3,0x3c,0xff,0xf3,0xf0,0xf9,0x7e,0x5,0x42,0xd7,0x16,0xa0,0x83,0xd3,0x9e,0xf,0x1c,0x3,0x50,0x7f,0xf0,0x32,0x68,0xf8,0x5,0x4,0x0,0x1f,0x80,0x3c,0x6e,0x0,0x51,0xfe,0x40,0x41,0xe4,0x1f,0x4f,0x98,0x3c,0x61,0xc1,0x73,0xa0,0x3,0xdb,0xe9,0x3f,0xf8,0x70,0x41,0xeb,0xfc,0x7,0x1d,0xff,0xef,0xdf,0x87,0xe9,0x8c,0x46,0xf,0x1e,0x18,0x3c,0xf3,0xff,0x78,0xfe,0xc2,0xf3,0x7e,0x59,0x9e,0x3,0x0,0xf,0x3f,0x78,0x3c,0x69,0xf4,0x9c,0x93,0x10,0xa4,0x14,0x0,0x7a,0x7c,0xfe,0xf9,0xf0,0x29,0x1f,0x44,0x1e,0x22,0x1,0x23,0x1f,0xf0,0x1e,0x20,0x52,0x76,0x88,0x3c,0xc3,0xe6,0xc2,0x18,0xf8,0xb0,0xa3,0x80,0xf2,0x88,0x3,0xdd,0xc2,0x51,0xe0,0x10,0xd8,0x1,0xf1,0x4,0x6,0x8,0xfc,0xae,0x10,0x8c,0x7,0x9c,0x1e,0xa3,0xc1,0xe0,0x34,0xcb,0x78,0xf,0x1e,0x18,0x58,0x7f,0x0,0xf2,0xb0,0x30,0xc6,0xfe,0xf,0x19,0xfc,0x1c,0x1e,0x3a,0xf9,0x97,0xec,0x1e,0x2b,0x54,0x7b,0x93,0x98,0x7c,0xe1,0xf5,0x73,0x24,0x2,0x70,0xf,0x12,0x7b,0x3,0xd6,0x40,0xf,0xf1,0x79,0x3,0xf8 -}; - -const uint8_t _A_L1_Tv_128x47_5[] = { - 0x1,0x0,0xd1,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x9c,0xaf,0xe0,0xf9,0x10,0x88,0x28,0x6c,0x8,0xd1,0x81,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xe3,0x30,0x41,0x8a,0xdc,0x81,0xea,0x1,0x10,0x50,0xfe,0x0,0xa3,0x2,0xf0,0x4f,0xc1,0xe3,0xff,0x0,0x14,0x3e,0x1,0xfe,0x2,0xc,0x7,0xe1,0x3,0xf0,0x49,0xfc,0x11,0xf1,0x50,0xc1,0x3c,0xe,0x61,0x8,0x88,0x88,0x41,0x63,0x20,0x7,0x8c,0xfc,0x4c,0x30,0x68,0xe1,0x70,0x60,0x60,0xf2,0xe0,0x40,0xf8,0x11,0x3e,0x5,0x1c,0x1e,0x31,0xa0,0x60,0xf8,0xf,0xa6,0x75,0x12,0xf8,0xf0,0x30,0x65,0xc1,0xf2,0x82,0xc6,0xf0,0xad,0x33,0x8,0xae,0x8,0x1e,0x50,0x50,0x30,0xc7,0x81,0xe6,0xa3,0x30,0x79,0x68,0x12,0xc4,0x50,0x14,0xd1,0x1,0xc8,0x1e,0x81,0x72,0x27,0x12,0x28,0x7e,0x9f,0x3,0xe8,0x83,0xcb,0xe1,0x11,0x80,0x43,0x83,0xe7,0x20,0x86,0x43,0xe2,0x60,0xf3,0xfe,0x79,0xf8,0x10,0x98,0x30,0x3c,0xa8,0x2,0xf1,0x3c,0x8,0x3c,0xbf,0xd0,0xf9,0xfc,0x40,0x1e,0x78,0x6,0x39,0xfc,0x33,0xff,0xff,0xef,0xdd,0x62,0x4a,0x61,0x7,0x89,0xbc,0x41,0xe3,0xc,0xde,0x7f,0xd1,0x82,0xf,0x28,0xe8,0x80,0xb8,0x30,0x32,0x78,0xc0,0xbf,0xc,0xf3,0xff,0xcf,0xc3,0xe5,0xf8,0xc1,0x89,0x49,0xa8,0x20,0xf4,0xe7,0x82,0x47,0x0,0x63,0x1f,0xfc,0x1f,0x0,0xb9,0x40,0x0,0xfc,0x1,0xe3,0x70,0x2,0x8f,0xf2,0x2,0xf,0x20,0xfa,0x7c,0xc1,0xe3,0xe,0xb,0x9d,0x0,0x1e,0xdf,0x49,0xff,0xc3,0x82,0xf,0x5f,0xe0,0x38,0xef,0xff,0x7e,0xfc,0x3f,0x4c,0x62,0x30,0x78,0x87,0x93,0x3f,0xf7,0x8f,0xec,0x2f,0x37,0xe5,0x99,0xe0,0x30,0xe0,0xf3,0xf7,0x83,0xc6,0x9f,0x49,0xc9,0x40,0x41,0xe5,0xc0,0xc0,0x93,0x93,0xee,0xa6,0x10,0x1,0x3,0xcb,0xc0,0x61,0x10,0x1,0x7f,0x1,0xe2,0x5,0x2f,0xc0,0x3c,0xac,0x18,0x0,0xc1,0xb0,0x86,0x3e,0x2c,0x2f,0xe0,0x3c,0xa6,0x0,0xf7,0x81,0x3,0x4,0xa0,0x56,0x0,0x7c,0x3f,0x6,0x1,0x7f,0x1,0xd,0xc2,0x31,0x80,0xf3,0x83,0xd6,0x31,0x0,0xe0,0x13,0xcb,0x78,0xf,0x1e,0x1c,0x3c,0x90,0x20,0xf2,0xb0,0x30,0xc7,0xff,0x3,0x80,0x4f,0xe1,0xe0,0xf1,0xd7,0xcc,0xbf,0x60,0xf1,0x4b,0x23,0xdc,0x9c,0xc3,0xe7,0xf,0xab,0x99,0x20,0x13,0x80,0x78,0x93,0xd8,0x1e,0xb2,0x0,0x7f,0x8b,0xc8,0x1f,0xc0 -}; - -const uint8_t _A_L1_Tv_128x47_6[] = { - 0x1,0x0,0xc1,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x3f,0x44,0x22,0xa,0x23,0x61,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xea,0x82,0x50,0x78,0x80,0x45,0x84,0x90,0x2f,0x4,0xfc,0x1e,0x3f,0xf0,0x1,0x43,0xe0,0x1f,0xe0,0x31,0xc0,0xfc,0x12,0x7f,0x4,0x7c,0x54,0x30,0x4f,0x3,0x98,0x58,0x49,0x1e,0xb0,0x49,0xbc,0x12,0x31,0x60,0xc1,0xa3,0x8b,0x24,0x0,0xc,0xf,0x81,0x13,0xe0,0x50,0x41,0xe3,0x1a,0x81,0xc0,0x2c,0x0,0xe3,0x3a,0x89,0x7c,0x78,0x1,0x91,0x88,0x79,0x41,0x43,0x18,0x7,0x9c,0xc0,0x26,0x60,0xf2,0x82,0xbb,0x8f,0xf0,0x41,0x14,0x99,0x83,0xcb,0x40,0x7b,0x20,0x60,0xc1,0x2f,0xc8,0x34,0x7,0x98,0x5c,0x81,0xe5,0x80,0x8f,0xfd,0x1,0xeb,0xf0,0x88,0xc0,0x21,0xc2,0xc3,0xf0,0x43,0xcf,0x62,0xf,0x3f,0xe7,0x9f,0x81,0x9,0x4f,0xb,0x20,0x90,0xe2,0x10,0x10,0x79,0x7f,0xa1,0xf3,0xf8,0x80,0x3c,0x57,0x4,0x22,0x10,0x20,0xfc,0x30,0x7f,0xff,0xef,0xdd,0x54,0x51,0xf3,0xe0,0x9b,0xd2,0x19,0x9c,0xff,0x8e,0x4,0x1e,0x51,0xd8,0x2,0xcc,0x78,0x9,0x71,0x69,0xe,0xe1,0x90,0x7f,0xf9,0xf8,0xe4,0x6f,0x1f,0x81,0x50,0xb5,0xc6,0x3,0xf0,0x7,0xa7,0x3c,0x1e,0x38,0x1,0x0,0xb8,0x4,0x9a,0x3e,0x6,0x4a,0x7c,0x1,0xe3,0x70,0x2,0x8f,0xf1,0xae,0x43,0xc3,0x0,0xf,0xcc,0x1e,0x30,0xe0,0xb9,0xd0,0x1,0xed,0xf4,0x9f,0xfc,0x38,0x20,0xf5,0xfe,0x3,0x8e,0xff,0xf7,0xef,0xc3,0xf4,0xc6,0x21,0x7,0x9f,0xc,0x1e,0x79,0xff,0xbc,0x7f,0x61,0x79,0x68,0x8,0x0,0x64,0x18,0xc,0x0,0x3c,0xfd,0xe0,0xf1,0xa7,0xd2,0x72,0x4c,0x41,0x7,0x8d,0x0,0x1e,0x9f,0x3f,0xbe,0x7c,0xa,0x47,0xd1,0x7,0x88,0x80,0x48,0xc7,0xfc,0x7,0x88,0x14,0xa3,0x0,0xf4,0xf,0x9b,0x8,0x63,0xe2,0xc2,0x8e,0x3,0xca,0x20,0xf,0x77,0x8,0xc0,0x23,0xc0,0x21,0xb0,0x3,0xe2,0x8,0xc,0x11,0xf9,0x5c,0x21,0x18,0xf,0x38,0x3d,0x47,0x83,0xc0,0x51,0x8c,0x3,0x78,0xf,0x1e,0x18,0x58,0x7f,0x0,0xf2,0xb0,0x30,0xc6,0xfe,0xf,0x19,0xfc,0x1c,0x1e,0x3a,0xf9,0x97,0xec,0x1e,0x2b,0x54,0x7b,0x93,0x44,0x7c,0xe1,0xf5,0x73,0x24,0x2,0x70,0xf,0x12,0x7b,0x3,0xd6,0x40,0xf,0xf1,0x79,0x3,0xf8 -}; - -const uint8_t _A_L1_Tv_128x47_7[] = { - 0x1,0x0,0xcd,0x1,0x84,0x0,0x86,0x4,0xb,0x7f,0x84,0x1c,0x1f,0xb0,0xe9,0xc0,0xc,0x62,0x0,0x21,0x80,0x83,0x9b,0x1,0x1,0xe0,0x3,0xf2,0x80,0xa,0x39,0x0,0x58,0x41,0x45,0x6,0x7,0x98,0x28,0x47,0x44,0xf,0x58,0x48,0x3c,0xc5,0x45,0x4,0x12,0x10,0x98,0x81,0xea,0x5a,0x20,0x10,0x83,0xd3,0x80,0xa,0x20,0x7b,0xb,0x44,0x6c,0x53,0x80,0x7a,0xb,0x4,0x64,0x40,0xf4,0x83,0x83,0xe4,0xc4,0x20,0x31,0x3b,0x8,0x3f,0x44,0x22,0xa,0x23,0x61,0x60,0x21,0xe7,0x23,0xd,0x88,0x44,0x41,0xea,0x82,0x50,0x78,0x80,0x45,0x84,0x7f,0x8,0x1f,0x82,0x7e,0xf,0x1f,0xf8,0x0,0xa1,0xf0,0xf,0xf0,0x14,0xe1,0xde,0x9,0x3f,0x82,0x3e,0x2a,0x18,0x27,0x81,0xcc,0x21,0x11,0x27,0x14,0xc2,0x40,0xf,0x19,0xf8,0xb0,0x60,0xd1,0xc3,0xa0,0xc0,0xc1,0xe5,0x74,0xe0,0x70,0x22,0x7c,0xa,0x38,0x3c,0x63,0x40,0xc1,0xf0,0x13,0x8f,0xf9,0x1,0x2f,0x8f,0x3,0x6,0x5c,0x1f,0x28,0x28,0x6f,0x0,0xf3,0xfc,0xd,0x85,0x12,0x20,0xf2,0x82,0x81,0x86,0x3c,0xc,0x17,0xc8,0x92,0xc8,0x1e,0x7a,0x3,0xd9,0x6,0x46,0x9,0x7e,0x22,0xd,0xfc,0x1e,0xaa,0xb2,0x20,0x8c,0x13,0x0,0x1d,0x1c,0x38,0x18,0x41,0xe5,0xf0,0x88,0xc0,0x21,0xc1,0xf1,0xa,0xf,0x83,0x1f,0x1,0x9,0x8,0x3c,0xbf,0x9e,0x7e,0x4,0x26,0xc,0xc8,0x3f,0xc7,0xfd,0x3a,0x20,0xf2,0xff,0x43,0xe7,0xf1,0x0,0x78,0xae,0x9,0xc6,0x7f,0xc,0xff,0xff,0xfb,0xf7,0x55,0x94,0x7d,0xe4,0x20,0xf4,0x86,0x6f,0x3f,0xe3,0x81,0x7,0x94,0x74,0xc4,0x53,0x7,0x11,0x8d,0x4,0x0,0x73,0xf2,0x48,0xde,0x3f,0x1c,0x31,0x28,0xc0,0x20,0x3f,0x0,0x7a,0x73,0xc1,0x23,0x80,0x83,0xe0,0x3f,0xe0,0x21,0x5c,0xa9,0x18,0x41,0xe3,0x70,0x2,0x8f,0xf9,0x80,0x23,0xc4,0x0,0xf,0xcc,0x1e,0x30,0xe0,0xb9,0xd0,0x1,0xed,0xf4,0x9f,0xfc,0x38,0x20,0xf5,0xfe,0x3,0x8e,0xff,0xf7,0xef,0xc3,0xf4,0xc6,0x21,0x7,0x98,0x79,0x33,0xff,0x78,0xfe,0xc2,0xf2,0xd0,0x10,0x0,0xc8,0x30,0x18,0x70,0x79,0xfb,0xc1,0xe3,0x4f,0xa4,0xe4,0x9e,0x22,0xf,0x1e,0x6,0x4,0x9c,0x9f,0x75,0x30,0x80,0x8,0x1e,0x5e,0x3,0x8,0x80,0xb,0xf8,0xf,0x10,0x29,0x7e,0x1,0xe5,0x60,0x42,0x8,0x0,0x98,0x43,0x1f,0x16,0x17,0xf0,0x1e,0x53,0x0,0x7b,0xc0,0x81,0x82,0x50,0x2b,0x0,0x3e,0x20,0x80,0xc1,0xbf,0x80,0x86,0xe1,0x18,0xc0,0x79,0xc1,0xeb,0x18,0x80,0x70,0x9,0xe5,0xbc,0x7,0x8f,0xe,0x1e,0x48,0x10,0x79,0x58,0x18,0x63,0xff,0x81,0xc0,0x27,0xf0,0xf0,0x78,0xeb,0xe6,0x5f,0xb0,0x78,0xa5,0x91,0xee,0x4e,0x61,0xf3,0x87,0xd5,0xcc,0x90,0x9,0xc0,0x3c,0x49,0xec,0xf,0x59,0x0,0x3f,0xc5,0xe4,0xf,0xe0 -}; - - -const uint8_t * const _A_L1_Tv_128x47[] = { - - _A_L1_Tv_128x47_0, - - _A_L1_Tv_128x47_1, - - _A_L1_Tv_128x47_2, - - _A_L1_Tv_128x47_3, - - _A_L1_Tv_128x47_4, - - _A_L1_Tv_128x47_5, - - _A_L1_Tv_128x47_6, - - _A_L1_Tv_128x47_7, - -}; - - - -const FrameBubble L1_Tv_128x47_bubble_0_0; - -const FrameBubble L1_Tv_128x47_bubble_1_0; - - -const FrameBubble* const L1_Tv_128x47_bubble_sequences[] = { - - &L1_Tv_128x47_bubble_0_0, - - &L1_Tv_128x47_bubble_1_0, - -}; - - - -const FrameBubble L1_Tv_128x47_bubble_0_0 = { - .bubble = { - .x = 1, - .y = 23, - .text = "Take the red pill", - .align_h = AlignRight, - .align_v = AlignBottom, - }, - .start_frame = 7, - .end_frame = 9, - .next_bubble = NULL, -}; - - -const FrameBubble L1_Tv_128x47_bubble_1_0 = { - .bubble = { - .x = 1, - .y = 23, - .text = "I can joke better", - .align_h = AlignRight, - .align_v = AlignBottom, - }, - .start_frame = 7, - .end_frame = 9, - .next_bubble = NULL, -}; - - - -const uint8_t L1_Tv_128x47_frame_order[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; - -const BubbleAnimation BA_L1_Tv_128x47 = { - .icon_animation = { - .width = 128, - .height = 47, - .frame_count = 8, - .frame_rate = 2, - .frames = _A_L1_Tv_128x47 - }, - .frame_order = L1_Tv_128x47_frame_order, - .passive_frames = 6, - .active_frames = 2, - .active_cooldown = 5, - .active_cycles = 2, - .duration = 3600, - - .frame_bubble_sequences = L1_Tv_128x47_bubble_sequences, - .frame_bubble_sequences_count = COUNT_OF(L1_Tv_128x47_bubble_sequences), - -}; - - -const uint8_t _A_L1_BadBattery_128x47_0[] = { - 0x1,0x0,0xb,0x1,0x0,0x47,0xfb,0xfe,0x0,0x2b,0x38,0x3e,0x60,0x40,0x43,0xbf,0x3,0xe7,0xa5,0xf3,0xff,0xf9,0x2f,0xf5,0x60,0xff,0x5a,0x81,0xf3,0xa,0x2,0x18,0x7e,0x81,0xe9,0xea,0x87,0x8b,0xf7,0xad,0x1d,0x7,0xef,0xaa,0x30,0x2f,0xd0,0xfd,0x62,0xa6,0x30,0x9,0x84,0x18,0x7f,0x50,0xa8,0xdc,0x2,0xc1,0x3,0x2f,0xdc,0x3a,0x1,0xc0,0x80,0x9f,0xec,0x1e,0x61,0xfb,0x17,0x98,0x7e,0x89,0xe8,0x9f,0xf5,0xff,0x87,0xfc,0xff,0x69,0xf4,0x8f,0x83,0xe3,0xc5,0x1,0xff,0x40,0xd7,0xf7,0xfa,0x83,0xfc,0x60,0xe1,0xfb,0x7,0x8f,0xfc,0x1e,0x23,0xfa,0xff,0x2,0x8c,0xbf,0x40,0xf4,0x3f,0xd0,0x7f,0xfe,0x5c,0xff,0xff,0xd2,0xa2,0x1f,0xaf,0x9,0x34,0x40,0x3,0x7e,0x7,0x46,0x3,0x8f,0xff,0x0,0x15,0x9c,0x1f,0x1c,0xe,0x7c,0x4,0x57,0x20,0x2,0xa0,0x4b,0xc1,0xd9,0x0,0x90,0x47,0x81,0xfb,0x10,0x87,0x3,0xf6,0x10,0x5e,0x30,0x5,0x61,0x20,0xa0,0xfd,0xa1,0x3,0xfa,0x4c,0xf,0x64,0x29,0x80,0xe,0x3e,0xf,0xe0,0x7,0x97,0x9f,0x8f,0x18,0xb3,0x62,0xe6,0xd6,0xed,0xc,0x6c,0x1e,0xfb,0x7e,0xb5,0x6f,0xbb,0xd4,0xa7,0xef,0x7d,0x70,0x78,0x84,0xe6,0x71,0xe6,0xf7,0x53,0xa0,0x21,0xf1,0xa1,0x77,0xaa,0x52,0xed,0xe,0x6a,0xf,0xb0,0x82,0xd2,0x29,0x32,0x4a,0x94,0x7,0x6f,0xda,0xf,0x8f,0x5a,0xdd,0xbd,0xbd,0x41,0xea,0x11,0x99,0xc5,0x3f,0xc9,0x8e,0x1f,0x8c,0x5a,0xb4,0x3f,0x1b,0x7d,0x87,0x1a,0x2f,0x19,0x8,0x7c,0xb1,0x46,0xf8,0x7,0x8e,0x76,0x71,0x49,0xf2,0x64,0x81,0xf2,0x5f,0x60,0x7f,0x80 -}; - -const uint8_t _A_L1_BadBattery_128x47_1[] = { - 0x1,0x0,0x11,0x1,0x0,0x47,0xfb,0xfe,0x0,0x2b,0x38,0x3e,0x60,0x40,0x43,0xbf,0x3,0xe7,0xa5,0xf3,0xff,0xf9,0x2f,0xf5,0x60,0xff,0x5a,0x81,0xf3,0xa,0x2,0x18,0x7e,0x81,0xe9,0xea,0x87,0x8b,0xf7,0xad,0x1d,0x7,0xef,0xaa,0x30,0x2f,0xd0,0xfd,0x62,0xa6,0x30,0x9,0x84,0x18,0x7f,0x50,0xa8,0xdc,0x2,0xc1,0x3,0x2f,0xdc,0x3a,0x1,0xc0,0x80,0x9f,0xec,0x1e,0x61,0xfb,0x17,0x98,0x7e,0x89,0xe8,0x9f,0xf5,0xff,0x87,0xfc,0xff,0x70,0xf,0xe4,0x5,0x3e,0x31,0xf0,0x7c,0x78,0xa0,0x3c,0x28,0x1a,0xfe,0xff,0x50,0x7f,0x8c,0x1c,0x3f,0x60,0xf1,0xfc,0x83,0xc4,0x7f,0x5f,0xe8,0x7f,0xfc,0x1e,0x25,0xfa,0x7,0x89,0xff,0x41,0xe8,0x1f,0xaf,0x97,0x3f,0xff,0xf4,0xa8,0x87,0xeb,0xc2,0x3d,0x10,0x0,0xdf,0x81,0xd1,0x80,0xe3,0xff,0xc0,0x5,0x67,0x7,0xc7,0x3,0x9e,0x9d,0x10,0x5,0xd0,0x25,0xe0,0xec,0x80,0x48,0x23,0xc0,0xfd,0x88,0x43,0x81,0xfb,0x8,0x2f,0x18,0x2,0xb0,0x90,0x50,0x7e,0xd0,0x81,0xfd,0x26,0x7,0xb2,0x14,0xc0,0x7,0x1f,0x7,0xf0,0x3,0xcb,0xcf,0xc7,0x8c,0x59,0xb1,0x73,0x6b,0x76,0x86,0x36,0xf,0x7d,0xbf,0x5a,0xb7,0xdd,0xea,0x53,0xf7,0xbe,0xb8,0x3c,0x42,0x73,0x38,0xf3,0x7b,0xa9,0xd0,0x10,0xf8,0xd0,0xbb,0xd5,0x29,0x76,0x87,0x35,0x7,0xd8,0x41,0x69,0x14,0x99,0x25,0x4a,0x3,0xb7,0xed,0x7,0xc7,0xad,0x6e,0xde,0xde,0xa0,0xf5,0x8,0xcc,0xe2,0x9f,0xe4,0xc7,0xf,0xc6,0x2d,0x5a,0x1f,0x8d,0xbe,0xc3,0x8d,0x17,0x8c,0x84,0x3e,0x58,0xa3,0x7c,0x3,0xc7,0x3b,0x38,0xa4,0xf9,0x32,0x40,0xf9,0x2f,0xb0,0x3f,0xc0 -}; - - -const uint8_t * const _A_L1_BadBattery_128x47[] = { - - _A_L1_BadBattery_128x47_0, - - _A_L1_BadBattery_128x47_1, - -}; - - - -const FrameBubble L1_BadBattery_128x47_bubble_0_0; - - -const FrameBubble* const L1_BadBattery_128x47_bubble_sequences[] = { - - &L1_BadBattery_128x47_bubble_0_0, - -}; - - - -const FrameBubble L1_BadBattery_128x47_bubble_0_0 = { - .bubble = { - .x = 4, - .y = 21, - .text = "I feel so sick!\nI'm dying...", - .align_h = AlignRight, - .align_v = AlignCenter, - }, - .start_frame = 0, - .end_frame = 1, - .next_bubble = NULL, -}; - - - -const uint8_t L1_BadBattery_128x47_frame_order[] = { 0, 1 }; - -const BubbleAnimation BA_L1_BadBattery_128x47 = { - .icon_animation = { - .width = 128, - .height = 47, - .frame_count = 2, - .frame_rate = 2, - .frames = _A_L1_BadBattery_128x47 - }, - .frame_order = L1_BadBattery_128x47_frame_order, - .passive_frames = 2, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 3600, - - .frame_bubble_sequences = L1_BadBattery_128x47_bubble_sequences, - .frame_bubble_sequences_count = COUNT_OF(L1_BadBattery_128x47_bubble_sequences), - -}; - - -const uint8_t _A_L1_NoSd_128x49_0[] = { - 0x1,0x0,0x49,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x80,0x86,0x1e,0xf,0xde,0x4,0xf0,0x1f,0xb6,0xb,0xc0,0x3f,0xc1,0xfb,0x70,0xfc,0x40,0x3a,0x0,0xfc,0xec,0x40,0x3d,0x0,0xfb,0xf8,0x7f,0x20,0x1f,0x40,0x7d,0xec,0x35,0xf0,0xf,0xe7,0x26,0x4d,0xe7,0xf,0xce,0xf4,0x1e,0x38,0xd,0xdf,0x68,0x1f,0x1e,0xa,0xe8,0x3c,0x72,0x9b,0xae,0xd8,0x3d,0xa0,0xb0,0x9,0x5,0x1c,0x1e,0x5a,0x61,0x7b,0xc0,0xd3,0xe3,0x30,0x7,0x92,0xff,0x7e,0x19,0x48,0x1f,0x44,0x1e,0xb8,0x0,0x1a,0x3,0xc7,0xf3,0x2f,0x7,0xad,0x0,0x6,0x54,0x88,0x17,0xc3,0xff,0xc0,0x8f,0x83,0xd6,0x40,0x3,0x29,0x24,0x4,0x1e,0x38,0x18,0x78,0x3d,0x62,0x0,0x32,0xc9,0x2f,0xcb,0x1f,0x0,0x7,0xac,0x20,0x6,0x54,0x95,0xf8,0xdf,0xf0,0x18,0x8,0x3f,0x80,0x22,0x70,0x40,0x10,0xc1,0x80,0x43,0xf4,0x7,0x8f,0x2,0xf,0x10,0xec,0x4,0x8,0x1e,0x38,0x3,0x89,0x7f,0x19,0xe7,0x10,0x90,0xb,0x8,0x1e,0x37,0x81,0x29,0x3,0xd8,0x98,0x40,0xf1,0x1a,0x98,0x3d,0x2c,0x0,0xf3,0xf2,0x78,0x16,0x24,0xf,0x5c,0x4,0xff,0xc0,0x3a,0x18,0xc4,0x7c,0x8,0x40,0xf6,0x45,0x8c,0xf8,0xfe,0x5f,0xc0,0x7b,0xd0,0x28,0x10,0x4e,0x4,0x3e,0xc1,0x80,0xff,0x8f,0xdc,0x1e,0x4c,0x81,0x3,0x8c,0xfc,0x1f,0x1c,0x2,0x49,0x40,0x3f,0xce,0xd1,0x7,0xc2,0xc0,0xff,0xc1,0x43,0x7,0xd4,0x8,0x8,0x60,0xff,0xfc,0x3,0xca,0x7,0x80,0xb0,0x2,0x8c,0xda,0x40,0x7,0xb0,0x83,0xfb,0xfc,0xb,0x30,0x7a,0x0 -}; - -const uint8_t _A_L1_NoSd_128x49_1[] = { - 0x1,0x0,0x42,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x80,0x86,0x1e,0xf,0xde,0x4,0xf0,0x1f,0xb6,0xb,0xc0,0x3f,0xc1,0xfb,0x70,0xfc,0x40,0x3a,0x0,0xfc,0xec,0x40,0x3d,0x0,0xfb,0xf8,0x7f,0x20,0x1f,0x40,0x7d,0xec,0x35,0xf0,0xf,0xe7,0x26,0x4d,0xe7,0xf,0xce,0xf4,0x1e,0x38,0xd,0xdf,0x68,0x1f,0x1e,0xa,0xe8,0x3c,0x72,0x9b,0xae,0xd8,0x3d,0xa0,0xb0,0x9,0x5,0x1c,0x1e,0x5a,0x61,0x7b,0xc0,0xd3,0xe3,0x30,0x7,0x92,0xff,0x7e,0x19,0x48,0x1f,0x44,0x1e,0xb8,0x0,0x1a,0x3,0xc7,0xf3,0x2f,0x7,0xad,0x0,0x6,0x54,0x88,0x17,0xc3,0xff,0xc0,0x8f,0x83,0xd6,0x40,0x3,0x29,0x24,0x4,0x1e,0x38,0x18,0x78,0x3d,0x62,0x0,0x32,0xc9,0x2f,0xcb,0x1f,0x0,0x7,0xac,0x20,0x6,0x54,0x95,0xf8,0xdf,0xf0,0x18,0x0,0x7a,0xc1,0x0,0x43,0x6,0x1,0xf,0xd0,0x1e,0x3c,0x0,0x78,0xf8,0x2,0x44,0xf,0x1c,0x1,0xc4,0xbf,0x8c,0xf4,0x88,0x76,0x0,0x62,0xf,0x1b,0xc0,0x94,0x81,0xed,0x20,0x1e,0x88,0x3c,0x46,0xe6,0xf,0x72,0xe8,0xf9,0x3c,0xb,0x12,0x7,0xb5,0x80,0x1e,0x51,0x88,0xff,0x80,0x7f,0x18,0x9,0xf8,0x2c,0x42,0x23,0xfc,0x7,0xca,0x70,0x67,0xd6,0xc,0x7,0xfc,0x7f,0x14,0xa,0x4,0x13,0x81,0x8f,0xff,0xcf,0xc1,0xf6,0xd9,0x1f,0xfb,0xb4,0x41,0xf1,0xc0,0x2d,0x17,0xf8,0x6,0x40,0xf8,0x5,0x14,0x9,0x6a,0x60,0xff,0xfc,0x3,0xc8,0x4e,0x20,0xf4,0x36,0x90,0x1,0xf0,0x16,0x0,0x7e,0xc0,0x2c,0x20,0xf7 -}; - -const uint8_t _A_L1_NoSd_128x49_2[] = { - 0x1,0x0,0x41,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x83,0xfc,0x1f,0xe0,0xff,0x2e,0x8c,0xfc,0x1f,0xbe,0xb,0xc4,0x3,0xa0,0xf,0xbb,0x6,0xe2,0x1,0xe8,0x7,0xdf,0xc3,0xf9,0x0,0xfa,0x3,0xef,0x61,0xdf,0x80,0x7f,0x39,0x32,0x6f,0x38,0x7e,0x77,0x20,0xf1,0xc0,0x6e,0xfb,0x44,0xf9,0xac,0x83,0xc7,0x29,0xba,0xed,0x83,0xda,0xb,0x0,0xe0,0x1b,0xc4,0x1e,0x3a,0x61,0x7b,0xc0,0xc0,0x86,0xf,0x14,0xfd,0xe4,0x8,0x43,0x94,0x81,0xf4,0x41,0xeb,0x80,0x1,0x95,0x22,0x4,0xf,0x1f,0xcc,0xbc,0x1e,0xb4,0x0,0x91,0x49,0x20,0x3f,0xf,0xff,0x2,0x3e,0xf,0x59,0x0,0x48,0xb2,0x50,0x40,0x78,0xe0,0x61,0xe0,0xf5,0x88,0x4,0x8a,0x93,0x2,0x5f,0x8e,0x3e,0x0,0xf,0x58,0x40,0x8c,0xe1,0x3e,0x8b,0xfe,0x3,0x0,0xf,0x58,0x20,0x8,0x60,0xd8,0x8,0x27,0xd0,0x1e,0x3c,0x0,0x7b,0xe0,0xe,0x25,0xfc,0x67,0xc0,0x3c,0x5f,0xa2,0xf,0x7f,0xc0,0x64,0x81,0xe3,0x1f,0x7,0xc4,0x13,0xec,0x10,0x1f,0x27,0x80,0x4e,0x60,0xf6,0x84,0x40,0xa0,0x1d,0x8f,0xf8,0x90,0x81,0xf0,0x2d,0x1f,0x7,0xc5,0x62,0x60,0xf5,0x8c,0x3,0xce,0x3f,0x70,0x7,0xc7,0x82,0x1e,0x5b,0x15,0x78,0xcf,0x1,0xf1,0x20,0x84,0x60,0x21,0xe0,0xf1,0x2f,0xcc,0x42,0x20,0xd8,0x1a,0x1f,0x2,0x1e,0xf,0xb0,0x49,0x1b,0xe6,0x21,0xf0,0x5,0x17,0xf8,0xde,0x7f,0x80,0x79,0x40,0xc1,0xe3,0x30,0x5,0x15,0xf5,0x6c,0x8f,0xb5,0x7,0x98,0x78,0xc1,0xff,0x0 -}; - -const uint8_t _A_L1_NoSd_128x49_3[] = { - 0x1,0x0,0x45,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x83,0xfc,0x1f,0xe0,0xff,0x2e,0x8c,0xfc,0x1f,0xbe,0xb,0xc4,0x3,0xa0,0xf,0xbb,0x6,0xe2,0x1,0xe8,0x7,0xdf,0xc3,0xf9,0x0,0xfa,0x3,0xef,0x61,0xdf,0x80,0x7f,0x39,0x32,0x6f,0x38,0x7e,0x77,0x20,0xf1,0xc0,0x6e,0xfb,0x44,0xf9,0xac,0x83,0xc7,0x29,0xba,0xed,0x83,0xda,0xb,0x0,0xe0,0x1b,0xc4,0x1e,0x3a,0x61,0x7b,0xc0,0xc0,0x86,0xf,0x14,0xfd,0xe4,0x8,0x43,0x94,0x81,0xf4,0x41,0xeb,0x80,0x1,0x95,0x22,0x4,0xf,0x1f,0xcc,0xbc,0x1e,0xb4,0x0,0x91,0x49,0x20,0x3f,0xf,0xff,0x2,0x3e,0xf,0x59,0x0,0x48,0xb2,0x50,0x40,0x78,0xe0,0x61,0xe0,0xf5,0x88,0x4,0x8a,0x93,0x2,0x5f,0x8e,0x3e,0x0,0xf,0x58,0x40,0x8c,0xe1,0x3e,0x8b,0xfe,0x3,0x0,0xf,0x58,0x20,0x8,0x60,0xd8,0x8,0x27,0xd0,0x1e,0x3c,0x0,0x7b,0xe0,0xe,0x25,0xfc,0x67,0xc0,0x3c,0x5f,0xa2,0xf,0x7f,0xc0,0x64,0x81,0xe2,0x17,0x30,0x7a,0xc1,0x3e,0xc1,0x1,0xf2,0x78,0x16,0x26,0xf,0x68,0x44,0xa,0x1,0x18,0x8f,0xf8,0x7,0xf0,0xf,0x11,0x68,0x9f,0xc7,0xf8,0xf,0x88,0xc0,0x3c,0xac,0x18,0xf,0xf8,0xfe,0x3c,0x10,0xf2,0xd8,0x83,0x85,0xfa,0x20,0xf7,0x90,0x42,0x30,0x10,0xf8,0x7,0xf8,0x4,0x20,0xf7,0x88,0x44,0x1b,0x3,0x3,0xff,0x17,0x88,0x1f,0x20,0x91,0x8f,0xa5,0x4c,0x1e,0xdf,0x0,0x51,0x1c,0x84,0x0,0x5f,0x80,0x79,0x9,0xc6,0x21,0x30,0x5,0x11,0xb4,0x80,0xe,0xf,0xf0,0x7c,0x80 -}; - -const uint8_t _A_L1_NoSd_128x49_4[] = { - 0x1,0x0,0x3d,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x83,0xfc,0x1f,0xe0,0xff,0x7,0xf8,0x10,0xfa,0x0,0xfc,0xe0,0x40,0x3d,0x0,0xfc,0xf0,0x40,0x3e,0x80,0xfb,0x98,0x7c,0x20,0x1f,0xce,0x4c,0x9b,0xce,0xf,0x8f,0x85,0xfc,0x1e,0x38,0xd,0xdf,0x68,0x1f,0x1e,0x9,0xf8,0x3c,0x72,0x9b,0xae,0xd8,0x3d,0xa0,0xa4,0xe1,0x8f,0x83,0xcb,0x4c,0x2f,0x78,0x18,0x10,0xc1,0xe2,0x5f,0xbc,0x81,0x8,0x72,0x90,0x3e,0x88,0x3d,0x70,0x0,0x32,0xa4,0x40,0x81,0xe3,0xf9,0x97,0x83,0xd6,0x80,0x12,0x29,0x24,0x7,0xe1,0xff,0x22,0x8,0x3d,0x64,0x1,0x22,0xc9,0x41,0x1,0xe3,0x81,0x87,0x83,0xd6,0x20,0x12,0x2a,0x4c,0x9,0x7e,0x38,0xf8,0x0,0x3d,0x61,0x2,0x33,0x84,0xfa,0x2f,0xf8,0xc,0x0,0x3d,0x60,0x80,0x21,0x83,0x60,0x20,0x9f,0x40,0x78,0xf0,0x1,0xef,0x80,0x38,0x97,0xf1,0x9f,0x0,0xf1,0xbc,0x23,0xcc,0x1e,0x9f,0x80,0xc9,0x3,0xc5,0x5a,0x20,0xf7,0x82,0x7d,0x82,0x3,0xe4,0xf0,0x9,0xcc,0x1e,0xd0,0x88,0x14,0x3,0xb1,0xff,0x12,0x10,0x3e,0x5,0xa3,0xe0,0xf8,0xac,0x4c,0x1e,0xb1,0x80,0x79,0xc7,0xee,0x0,0xf8,0xf0,0x43,0xcb,0x62,0xaf,0x19,0xe0,0x3e,0x24,0x10,0x8c,0x4,0x3c,0x1e,0x25,0xf9,0x88,0x44,0x1b,0x3,0x43,0xe0,0x43,0xc1,0xf6,0x9,0x23,0x7c,0xc4,0x3e,0x0,0xa2,0xff,0x1b,0xcf,0xf0,0xf,0x28,0x18,0x3c,0x66,0x0,0xa2,0xbe,0xad,0x91,0xf6,0xa0,0xf3,0xf,0x18,0x3f,0xe0,0x0 -}; - -const uint8_t _A_L1_NoSd_128x49_5[] = { - 0x1,0x0,0x43,0x1,0x0,0x5e,0x3,0xff,0x7,0x7,0xe5,0xc2,0x1,0x38,0x7,0xe4,0x32,0x1,0xc0,0x7,0xe4,0xc,0x4,0x5c,0xf,0xf8,0x0,0x40,0xe4,0x3e,0x40,0x19,0x41,0x3c,0x0,0xf2,0x22,0xb5,0x0,0x6,0x50,0x8b,0x6,0x4a,0x49,0x49,0x83,0x3,0xd6,0x40,0x3,0x28,0x80,0x3e,0xa2,0x1,0x33,0x7,0xd4,0x20,0x1f,0xe4,0x33,0x7,0xd4,0x10,0x1e,0x65,0xfa,0x7,0x9e,0x0,0x1f,0x50,0x20,0x7f,0x81,0xc,0x1f,0xe0,0xfa,0x80,0x80,0x86,0x1e,0xf,0xde,0x4,0xf0,0x1f,0xb6,0xb,0xc0,0x3f,0xc1,0xfb,0x70,0xfc,0x40,0x3a,0x0,0xfc,0xec,0x40,0x3d,0x0,0xfb,0xf8,0x7f,0x20,0x1f,0x40,0x7d,0xec,0x35,0xf0,0xf,0xe7,0x26,0x4d,0xe7,0xf,0xce,0xf4,0x1e,0x38,0xd,0xdf,0x68,0x1f,0x1e,0xa,0xe8,0x3c,0x72,0x9b,0xae,0xd8,0x3d,0xa0,0xb0,0x9,0x5,0x1c,0x1e,0x5a,0x61,0x7b,0xc0,0xd3,0xe3,0x30,0x7,0x92,0xff,0x7e,0x19,0x48,0x1f,0x44,0x1e,0xb8,0x0,0x1a,0x3,0xc7,0xf3,0x2f,0x7,0xad,0x0,0x6,0x54,0x88,0x17,0xc3,0xff,0xc0,0x8f,0x83,0xd6,0x40,0x3,0x29,0x24,0x4,0x1e,0x38,0x18,0x78,0x3d,0x62,0x0,0x32,0xc9,0x2f,0xcb,0x1f,0x0,0x7,0xac,0x20,0x6,0x54,0x95,0xf8,0xdf,0xf0,0x18,0x0,0x7a,0xc1,0x0,0x43,0x6,0x1,0xf,0xd0,0x1e,0x3c,0x0,0x7b,0xe0,0xe,0x25,0xfc,0x67,0xc0,0x3c,0x6f,0x0,0x52,0x7,0xaf,0xe0,0x32,0x40,0xf1,0x8f,0x83,0xe2,0x9,0xf6,0x8,0xf,0x93,0xc0,0x27,0x30,0x7b,0x42,0x20,0x50,0xe,0xc7,0xfc,0x48,0x40,0xf8,0x16,0x8f,0x83,0xe2,0xb1,0x30,0x7a,0xc6,0x1,0xe7,0x1f,0xb8,0x3,0xe3,0xc1,0xf,0x2d,0x8a,0xbc,0x67,0x80,0xf8,0x90,0x42,0x30,0x10,0xf0,0x78,0x97,0xe6,0x21,0x10,0x64,0xd,0xf,0x80,0xfd,0x10,0x7d,0x2,0x48,0xdf,0x31,0xf,0x80,0x28,0xbf,0xc6,0xf3,0xfc,0x3,0xca,0x6,0xf,0x19,0x80,0x28,0xaf,0xab,0x64,0x7d,0xa8,0x3c,0xc3,0xc6,0xf,0xf8,0x0 -}; - - -const uint8_t * const _A_L1_NoSd_128x49[] = { - - _A_L1_NoSd_128x49_0, - - _A_L1_NoSd_128x49_1, - - _A_L1_NoSd_128x49_2, - - _A_L1_NoSd_128x49_3, - - _A_L1_NoSd_128x49_4, - - _A_L1_NoSd_128x49_5, - -}; - - - -const FrameBubble L1_NoSd_128x49_bubble_0_0; - - -const FrameBubble* const L1_NoSd_128x49_bubble_sequences[] = { - - &L1_NoSd_128x49_bubble_0_0, - -}; - - - -const FrameBubble L1_NoSd_128x49_bubble_0_0 = { - .bubble = { - .x = 40, - .y = 18, - .text = "Need an\nSD card", - .align_h = AlignRight, - .align_v = AlignBottom, - }, - .start_frame = 0, - .end_frame = 9, - .next_bubble = NULL, -}; - - - -const uint8_t L1_NoSd_128x49_frame_order[] = { 0, 1, 0, 1, 0, 2, 3, 4, 3, 5 }; - -const BubbleAnimation BA_L1_NoSd_128x49 = { - .icon_animation = { - .width = 128, - .height = 49, - .frame_count = 6, - .frame_rate = 2, - .frames = _A_L1_NoSd_128x49 - }, - .frame_order = L1_NoSd_128x49_frame_order, - .passive_frames = 10, - .active_frames = 0, - .active_cooldown = 0, - .active_cycles = 0, - .duration = 3600, - - .frame_bubble_sequences = L1_NoSd_128x49_bubble_sequences, - .frame_bubble_sequences_count = COUNT_OF(L1_NoSd_128x49_bubble_sequences), - -}; - - -const StorageAnimation dolphin_internal[] = { - - { - .animation = &BA_L1_Tv_128x47, - .manifest_info = { - .name = "L1_Tv_128x47", - .min_butthurt = 0, - .max_butthurt = 14, - .min_level = 1, - .max_level = 3, - .weight = 3, - } - }, - - { - .animation = &BA_L1_BadBattery_128x47, - .manifest_info = { - .name = "L1_BadBattery_128x47", - .min_butthurt = 0, - .max_butthurt = 14, - .min_level = 1, - .max_level = 3, - .weight = 3, - } - }, - - { - .animation = &BA_L1_NoSd_128x49, - .manifest_info = { - .name = "L1_NoSd_128x49", - .min_butthurt = 0, - .max_butthurt = 14, - .min_level = 1, - .max_level = 3, - .weight = 6, - } - }, - -}; - -const size_t dolphin_internal_size = COUNT_OF(dolphin_internal); diff --git a/assets/compiled/assets_dolphin_internal.h b/assets/compiled/assets_dolphin_internal.h deleted file mode 100644 index f4f415fa..00000000 --- a/assets/compiled/assets_dolphin_internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include -#include - -extern const StorageAnimation dolphin_internal[]; -extern const size_t dolphin_internal_size; diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c deleted file mode 100644 index fb125095..00000000 --- a/assets/compiled/assets_icons.c +++ /dev/null @@ -1,829 +0,0 @@ -#include "assets_icons.h" - -#include - -const uint8_t _I_Certification1_103x23_0[] = {0x01,0x00,0x98,0x00,0x9f,0xff,0xbe,0x30,0x38,0x04,0xf2,0x01,0xe0,0x80,0x82,0x87,0xf9,0x01,0x06,0x24,0xfe,0x01,0xf8,0x80,0xfe,0x21,0xff,0xf8,0x3c,0xff,0x9c,0x0c,0x1e,0x00,0x30,0x7f,0xc0,0xc1,0xe3,0xc0,0xe3,0xd0,0x7e,0x75,0xc4,0x46,0x30,0x70,0xd9,0x46,0x3c,0x10,0x09,0xc0,0x30,0xfe,0x10,0x1c,0x04,0x3c,0x18,0x37,0x08,0x05,0xc0,0x18,0x77,0x88,0x07,0x00,0x6e,0x31,0x89,0x87,0xe2,0x00,0x0c,0x39,0xc0,0x30,0x49,0x83,0x18,0x8c,0x7f,0xa0,0x60,0xc3,0x2c,0xa0,0x30,0x60,0xe0,0x01,0x06,0x14,0x70,0x18,0x26,0x51,0x8c,0x43,0x20,0x70,0x20,0x64,0xe3,0x03,0xa2,0x74,0x10,0x62,0x5f,0xce,0xc3,0x8f,0x06,0x78,0x31,0xc4,0xc6,0x33,0xc2,0x6f,0x99,0xf5,0x03,0x89,0xb7,0xb0,0x2d,0x7d,0x9f,0x2e,0x98,0x8c,0x0a,0x86,0x3c,0x0c,0x30,0xb9,0x7e,0x20,0x30,0x88,0x07,0xfe,0x0e,0x0c,0x42,0xda,0x40,0x3f,0x90,0x10,}; -const uint8_t* const _I_Certification1_103x23[] = {_I_Certification1_103x23_0}; - -const uint8_t _I_Certification2_119x30_0[] = {0x01,0x00,0x3c,0x01,0x00,0x5c,0x06,0x01,0x40,0x07,0x5e,0x0b,0xff,0x20,0x07,0x5d,0x92,0x01,0x13,0x03,0xa4,0x70,0x06,0x5f,0xe0,0x10,0xc6,0x20,0x10,0xc8,0x1c,0xce,0x70,0x07,0x19,0xf0,0x08,0x70,0x10,0x18,0x1c,0x03,0xe1,0xff,0x83,0x83,0x84,0x34,0x57,0xf0,0x10,0xd8,0x03,0x23,0x00,0x1c,0x8c,0x08,0x1c,0x30,0xf0,0xc8,0xf8,0xc1,0xc3,0x10,0x00,0x90,0x48,0x60,0x70,0x3d,0x98,0x90,0x70,0x1c,0x10,0x70,0xc2,0x03,0x65,0xa0,0xc0,0x07,0x47,0xe6,0x6d,0x1e,0x07,0x04,0x06,0x20,0xe3,0x90,0x5f,0x41,0xc9,0xe0,0xc0,0x08,0x46,0x09,0x18,0x41,0x0c,0x82,0x44,0x0e,0x11,0x61,0x5c,0x27,0xd0,0x70,0x70,0xc5,0xc1,0xc3,0x40,0x8a,0x17,0x84,0x94,0x53,0x0a,0x0c,0x1a,0x01,0xe2,0x88,0x7e,0x01,0xc3,0x08,0x80,0xff,0xcd,0x05,0xb8,0x80,0x43,0xa0,0x11,0xe8,0x80,0x84,0x43,0xa5,0xfe,0x98,0xa1,0x86,0xb9,0x00,0x8e,0x9c,0x47,0xe0,0x5d,0x1a,0x04,0x88,0x8e,0x20,0x02,0x97,0x60,0x27,0x40,0xe1,0x03,0x95,0x02,0x82,0x0e,0x49,0x35,0x0a,0x65,0x00,0xe1,0x28,0x04,0xfe,0x38,0x05,0xc8,0xf8,0xe3,0xf0,0x09,0x3c,0x8a,0xe4,0x0e,0x4e,0x02,0xe0,0x7f,0xff,0x39,0xfe,0x02,0x47,0x14,0xf1,0x0b,0x13,0x41,0xc0,0x52,0x0c,0xc2,0x61,0xc0,0x90,0xc3,0x38,0x50,0x1e,0x27,0xfe,0x8f,0x00,0xc8,0x48,0x20,0xc0,0xe3,0x40,0x0e,0x04,0x1c,0x98,0x8d,0x04,0x28,0x1c,0x4a,0x31,0x00,0x0c,0x0e,0x11,0x38,0x59,0x8c,0x12,0x7f,0x12,0x81,0xfc,0x27,0xf7,0x08,0x05,0x06,0x01,0x07,0x07,0x1c,0x08,0x6c,0x20,0xe2,0x98,0x40,0x27,0xd0,0x08,0x34,0x42,0x70,0xef,0x13,0xa8,0xd0,0x05,0x84,0x1d,0x10,0x00,0xc1,0xdf,0x43,0x0c,0x41,0x1a,0xcc,0x47,0x63,0xff,0x00,0x0c,0x0c,0xe4,0x2d,0x91,0x00,0x17,0xf8,0x1c,0x3c,0x00,0x71,0x09,0xc7,0xfc,0x0d,0x30,0x06,0x7f,0x3f,0xea,0x11,0x07,0x78,0x3b,0xc1,0xd6,}; -const uint8_t* const _I_Certification2_119x30[] = {_I_Certification2_119x30_0}; - -const uint8_t _A_Levelup1_128x64_0[] = {0x01,0x00,0x22,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0x38,0x1f,0xe0,0x1d,0x97,0xff,0xe7,0x1c,0x1f,0x99,0xf8,0x1c,0xe0,0x1f,0x96,0x78,0x07,0x03,0xf8,0x0f,0xb8,0xdc,0x02,0x01,0xfb,0x07,0xdc,0x14,0x1e,0x3f,0x40,0x7d,0xc0,0x81,0xe3,0xe8,0x2f,0x5c,0x04,0x1e,0x3d,0x00,0x7d,0x6f,0xc1,0xc3,0x00,0xd0,0x03,0xea,0xbe,0x0f,0xf0,0x79,0x50,0x01,0xf5,0x2f,0x07,0xf8,0x38,0x63,0xf8,0x0f,0xf1,0x7a,0x62,0x10,0x0c,0x04,0x80,0x1f,0x59,0xf8,0xf8,0xb4,0x6f,0x80,0xfa,0xb7,0xcc,0x20,0x12,0x0f,0x34,0x03,0xfa,0x0f,0x88,0xbd,0x00,0x1e,0x3e,0x30,0x7d,0x42,0xf0,0x10,0x18,0x87,0x9c,0x1f,0x70,0x08,0x16,0x43,0xfe,0x0f,0xaf,0x5c,0x02,0x18,0x0f,0xc8,0xdc,0x0e,0x20,0x0f,0xc8,0x5c,0x31,0x7a,0x37,0xf0,0x7d,0xa3,0xc6,0x81,0x3f,0x37,0xdc,0x82,0x01,0xc0,0x49,0x09,0xff,0x61,0x00,0xfa,0x97,0x9f,0xc6,0x00,0x32,0x10,0x7d,0x40,0x20,0xc0,0xfc,0xaf,0xc0,0x23,0x0f,0x01,0x07,0xd6,0xfe,0x01,0xe0,0x07,0xe5,0xfc,0x7c,0x30,0xf0,0x7d,0xff,0xe0,0x41,0xe2,0x07,0xdc,0x14,0x1f,0xd0,0xd0,0x7f,0x45,0x45,0xfe,0x0f,0xf0,0x7f,0x17,0xd3,0xf4,0x7f,0x98,0x18,0x3f,0xc1,0xe7,0xf4,0x57,0xc8,0xbd,0x01,0xff,0xe8,0x6f,0xc8,0x3d,0x3a,0x0f,0xf9,0x67,0x88,0x00,0xb4,0x00,0xf8,0x8b,0x83,0xd2,0x80,0x0f,0x88,0x48,0x3d,0x30,0x1f,0xc0,0x6a,0xe3,0xef,0xf0,0x60,0x7a,0x40,0x3e,0x60,0xf5,0xbb,0xe0,0x20,0x20,0xf4,0x80,0xf3,0x01,0xeb,0x8b,0xbf,0x82,0x84,0x1e,0x93,0x0c,0x00,0x3d,0x21,0x60,0xa2,0x07,0xa7,0x02,0xfe,0x0f,0xd2,0x88,0xff,0x81,0xe6,}; -const uint8_t _A_Levelup1_128x64_1[] = {0x01,0x00,0x02,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x2f,0xf8,0x17,0x59,0xfe,0xf8,0x6b,0x37,0xf9,0xf0,0x32,0x7e,0xc1,0xac,0x02,0x19,0xff,0xfe,0x03,0xfc,0x11,0x5c,0xfe,0x7f,0xfe,0xf1,0x8c,0x2e,0x3d,0xce,0x80,0xe7,0x3e,0xff,0x90,0x7c,0xc3,0xe6,0x10,0x0b,0x07,0xfb,0xf0,0x61,0x8c,0x7c,0x3e,0x19,0x00,0xc0,0x43,0x6f,0xc1,0xe8,0xbf,0xe3,0xa0,0x50,0x08,0x04,0x0a,0xfe,0x83,0x7f,0xdf,0xf6,0x09,0x01,0x07,0x8e,0x11,0x25,0x1f,0x7f,0x7e,0x00,0x1c,0x30,0x09,0x41,0xfd,0xc0,0x03,0x1f,0xa0,0x03,0xca,0x21,0xfe,0x30,0x45,0xfe,0x90,0x0f,0x3f,0xe7,0xf4,0x1e,0xff,0x79,0x00,0x3c,0xa4,0x1b,0xc4,0xf4,0xca,0x01,0xe5,0xa0,0xfc,0x03,0xe6,0x20,0x0f,0x2a,0x00,0x3c,0x7c,0xef,0x96,0xbf,0xcc,0x81,0xc3,0xf8,0x07,0x93,0x0d,0xaf,0xbf,0xf5,0x70,0xc0,0x20,0x94,0x1d,0xc4,0x3f,0xf9,0xef,0x08,0x2f,0xf0,0x7e,0x5e,0x2c,0x17,0xf3,0xee,0x6f,0x89,0xc0,0x3c,0xb0,0x7f,0xc7,0x93,0x83,0x87,0xf1,0x07,0x80,0x79,0x70,0xbf,0x80,0x7b,0xc9,0xe0,0x13,0x86,0xf8,0xff,0x70,0xbc,0x0f,0x80,0x3d,0xb0,0xfa,0x18,0xe1,0x40,0x7f,0xb0,0x58,0x4f,0xf3,0xff,0xdf,0x08,0x2c,0x0e,0x18,0xc0,0x10,0x78,0xc0,0x7f,0xdb,0xfd,0xf8,0x3d,0x74,0x70,0x4c,0x04,0x07,0xfb,0x03,0x84,0xe3,0xfe,0xe0,0xf6,0x87,0xf9,0x20,0x10,0x6f,0xd4,0x0b,0x03,0xe7,0xf9,0xf7,0xce,0x47,0x7b,0xbf,0x67,0xe2,0x90,0x38,0x05,0xfe,0x03,0xc9,0xff,0xfe,0xfd,0xee,0x23,0x9f,0xff,0x27,0xd0,0xc2,0xf8,0xfc,0x20,0x18,0x16,0x6b,0xff,0xf3,0xf0,0xe6,0x81,0xca,0x7c,0x00,0xf5,0x22,0x0c,0x02,0x15,0x20,0x07,0x94,0x04,0x1e,0xd7,0xf8,0xfe,0x82,0x14,0x6f,0x10,0x00,0xea,0x51,0xe3,0xf3,0x08,0x26,0x7a,0x03,0x12,0x37,0x88,0x7c,0x91,0xe3,0xe7,0x3f,0xb4,0x48,0xde,0x21,0xf2,0xff,0x7f,0xf9,0xe7,0xf6,0x91,0x40,0x2f,0x01,0xf2,0x07,0xba,0x58,0x68,0x43,0xe2,0x0f,0x88,0xbc,0x7d,0xff,0xb0,0x79,0xf3,0xe1,0x78,0x20,0x79,0xc0,0x47,0xc2,0x8f,0x43,0xf0,0xe8,0xe0,0x44,0xe2,0x0f,0x8f,0xdf,0xc6,0xae,0x35,0x28,0xb7,0xc6,0x05,0x02,0x07,0x97,0x07,0xff,0xf1,0x17,0x20,0x10,0x74,0xe0,0xe3,0x80,0x72,0x67,0xff,0x82,0xf2,0xfc,0xe1,0xec,0xe1,0x00,0x15,0x0a,0x1e,0x60,0x12,0x72,0x70,0xe5,0xe0,0xf4,0x85,0x41,0x83,0xcb,0x37,0x83,0xe1,0xc5,0xe9,0x04,0x81,0x07,0xc7,0xde,0x0f,0x2a,0x5c,0x3b,0x40,0x0f,0x4d,0x24,0x83,0x3d,0xbf,0x30,0x1e,0x2e,0x39,0x40,0x07,0xa4,0x22,0x01,0x67,0xcf,0x8b,0xce,0x17,0x83,0x91,0x03,0xd2,0x61,0x2a,0xcc,0xf3,0x81,0xe9,0x1c,0x8c,0x03,0xd3,0x81,0x00,0xc3,0x18,0x12,0x2f,0xe0,0x83,0x83,0xd2,0x01,0xff,0xc0,0x83,0xd4,0x12,0x20,0xf5,0x80,0x60,0x01,0xe2,0x50,0x29,0x78,0x3d,0x98,0x63,0x40,0x48,0xa0,0x3e,0xac,0xc0,0xf3,0xa0,0x83,0xe2,0x41,0xc0,0x3f,0x9e,0x04,0x1f,0x3e,0x0f,0xc8,0x80,0xa0,0x60,0x81,0x07,0xb6,0x42,0x85,0xfc,0x0f,0x90,}; -const uint8_t _A_Levelup1_128x64_2[] = {0x01,0x00,0xc1,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x3f,0xe4,0x1f,0xdf,0x40,0x43,0xf3,0xc0,0xa9,0x7f,0xfb,0x03,0xdf,0x66,0x05,0x4d,0xff,0xbc,0x1e,0xf3,0xbf,0xf0,0x14,0xe3,0xf7,0x8f,0xf7,0xc4,0x1e,0xb1,0x3f,0xe0,0x14,0xe1,0xf9,0x02,0x0b,0xc5,0xc1,0xeb,0xcc,0xff,0x03,0xda,0x1e,0x0f,0x48,0x3f,0xbf,0xfd,0xf8,0x07,0xad,0xfc,0x1e,0x57,0xff,0xf4,0x0f,0xe7,0xff,0x07,0xaf,0x8e,0xff,0xf8,0xed,0xc7,0xee,0x1f,0xc8,0x18,0x34,0x41,0xeb,0xc3,0x9f,0xfc,0x3f,0x70,0xfe,0x07,0xfe,0x01,0x9c,0x0b,0x88,0x88,0x41,0xe7,0x1f,0xc8,0x5f,0xe0,0x7c,0x08,0x7c,0x03,0xf9,0x7f,0x9e,0x07,0xd3,0x8f,0x17,0x80,0x7e,0xe0,0x2f,0x71,0x85,0x7f,0xa7,0xf1,0xe0,0x7a,0x63,0xe7,0xf0,0x09,0x99,0x34,0x42,0x03,0xfb,0x9f,0xa5,0xd3,0xf1,0x3f,0xbf,0xc1,0x38,0x10,0x1c,0xe6,0xaa,0x04,0x1f,0x10,0xf2,0x7e,0x26,0xff,0x88,0x74,0xc2,0x01,0x60,0x0f,0x8d,0xfc,0x5c,0x2c,0x23,0xff,0x4c,0xed,0x18,0xe8,0x64,0x03,0x01,0xa9,0xc1,0x5e,0xf3,0xc1,0xf4,0x9f,0xcc,0xf8,0x10,0x48,0x10,0x74,0x60,0x58,0x0b,0xfe,0x32,0xfe,0xbe,0x50,0x78,0x97,0x8b,0x49,0xc0,0xf7,0xe0,0x14,0xc4,0xbe,0x3c,0x06,0x00,0x1c,0x30,0x08,0x46,0x02,0x78,0x0f,0x20,0x01,0xdf,0xb0,0x14,0x00,0x79,0x64,0x21,0x41,0x11,0x07,0x23,0x30,0x60,0x00,0xf3,0x88,0x00,0x87,0x81,0xbf,0x07,0x9e,0x73,0xdf,0x01,0x90,0x03,0xcb,0x40,0x53,0x19,0x02,0x3d,0x23,0x3f,0xf0,0x7a,0x00,0xc8,0x1e,0x5c,0x70,0x78,0xc6,0xb9,0xd0,0x11,0x59,0x0c,0xc7,0x51,0x0a,0x80,0x03,0x07,0x16,0x02,0x13,0xc0,0x83,0xd4,0x04,0x38,0xef,0xff,0x8f,0xfa,0x0f,0x18,0x3a,0x6c,0x43,0x22,0x00,0x1c,0x06,0xaa,0x14,0xd9,0x1f,0x38,0xfc,0xa1,0xa4,0x81,0x84,0x03,0xcc,0x02,0x3f,0xf0,0x71,0x80,0x06,0x02,0x1f,0x5d,0x14,0x2b,0xf0,0x0f,0x51,0x80,0xc1,0x01,0xe5,0x00,0x0b,0x0f,0xe7,0xf6,0x0f,0x5c,0x50,0x3d,0x35,0x3e,0x07,0x59,0x03,0x8a,0xff,0x0f,0x80,0x51,0x13,0xe7,0x01,0xf8,0x7b,0xff,0xa0,0xf2,0x87,0xff,0xe3,0xd2,0x8e,0x20,0x3c,0xa3,0x1a,0x9f,0x87,0x1e,0xff,0xde,0xc7,0x8b,0x47,0xd2,0x1f,0x10,0x7a,0x07,0xc7,0x8f,0x3f,0xff,0x61,0xff,0xff,0x7e,0xfc,0x1f,0x40,0x1f,0x5f,0x07,0x9d,0xfa,0x3e,0x37,0xf9,0x87,0xc6,0x02,0x0f,0x18,0xe4,0x07,0x80,0x0c,0x24,0xf9,0x14,0x04,0x3e,0x31,0xf7,0x58,0xc7,0xf5,0x38,0x0f,0x1b,0xbd,0x00,0x03,0x00,0xc2,0x03,0xca,0x1e,0x23,0x1f,0x80,0x28,0x73,0xe0,0x21,0xf9,0xff,0x70,0x30,0x41,0x90,0xe0,0x20,0xfa,0x98,0x17,0xf3,0xee,0x0f,0x2f,0xe7,0x83,0xdf,0x01,0x4f,0xac,0x03,0xfc,0x0f,0x10,0xe8,0xa4,0xc9,0x5e,0xba,0x96,0xf8,0x87,0x87,0xcf,0xf1,0xff,0xf1,0xe7,0x80,0xf1,0x88,0x3f,0x88,0x3e,0x3f,0xfe,0x7f,0x7f,0xcf,0xf9,0xff,0xc0,0xa3,0x1a,0x08,0x24,0x82,0x00,0x01,0x1d,0x4e,0x0b,0x3f,0xc7,0xf3,0xfc,0xff,0x9f,0xf9,0x08,0xa8,0x41,0xe8,0xdf,0x18,0x7f,0x07,0xcf,0x78,0x1e,0x8d,0xfe,0x00,0x1f,0x5c,0x0c,0x2a,0x0f,0xe0,0xbb,0xc7,0x0f,0xc7,0x00,0x83,0x0f,0x44,0x82,0x30,0x30,0x38,0xf8,0x22,0x78,0x00,0x70,0xf3,0xf0,0x1a,0xa0,0x7a,0x60,0xe1,0x50,0xaf,0x84,0x07,0xc0,0x0f,0x1d,0xb8,0x5c,0x60,0xbc,0x06,0x70,0x81,0x06,0x01,0x60,0xf0,0x28,0x85,0x64,0x34,0xad,0x46,0x2a,0x09,0x80,0xfc,0xc3,0x20,0x18,0x9d,0x56,0x48,0x32,0x3f,0x80,0xf8,0xe2,0xa0,0x36,0x00,0x78,0xc1,0xd6,0x23,0x31,0x80,0x63,0x01,0xe3,0xb8,0xfd,0xff,0xe1,0x10,0xe8,0xc2,0x7c,0x56,0x45,0xc1,0xc0,0x60,0xe0,0x52,0xae,0x41,0xb8,0x61,0x1f,0x08,0x38,0x30,0x60,0xc5,0xd1,0x80,0xdf,0xf0,0x06,0x12,0x17,0x89,0x64,0x57,0xe5,0xf8,0x60,0x9d,0x03,0x44,0x61,0x10,0x7b,0x00,0x10,0xea,0x25,0xf1,0x07,0x8a,0xbc,0xc1,0xeb,0xa0,0xd5,0x42,0x97,0xc3,0xff,0x54,0x88,0x3d,0xc1,0x25,0xfe,0x5f,0x88,0x94,0x80,0x0d,0x90,0xd5,0x4a,0x81,0xc3,0xfe,0xce,0x03,0xe2,0x10,0x1f,0x2f,0xff,0xe2,0x7f,0x01,0x06,0xa8,0x18,0x74,0x83,0xf1,0xfb,0x7f,0xff,0x33,0xf8,0x30,0xfd,0x41,0xe2,0xe1,0x25,0x79,0x41,0xcf,0x62,0x0f,0x5f,0xc6,0xa3,0x55,0x8a,0x07,0x90,}; -const uint8_t _A_Levelup1_128x64_3[] = {0x01,0x00,0x0a,0x03,0x8f,0xc0,0xb8,0x1f,0xfb,0xfd,0xe2,0x7f,0xf8,0x02,0x0f,0xff,0xff,0x03,0xff,0x00,0xc6,0xff,0x36,0xe0,0x47,0xfd,0xff,0x08,0xff,0xf3,0xff,0x3f,0x05,0x8f,0xf0,0x1e,0x5f,0xf8,0xfe,0x02,0xfb,0xff,0xf8,0x43,0xff,0x99,0xfd,0xf8,0x44,0x81,0xe7,0x17,0x88,0x7d,0x37,0xe0,0xf2,0x87,0xe7,0xff,0xe0,0x11,0xfe,0x83,0xca,0x1f,0x20,0xf8,0x0f,0x46,0x0f,0xfe,0x83,0xf6,0xff,0xfc,0xf0,0xfa,0x47,0xec,0x1e,0x08,0xf8,0x3c,0xa0,0x7c,0x3f,0xff,0x9c,0x1e,0x93,0xf8,0x06,0x02,0x1f,0xf8,0x2c,0x8c,0x07,0xc1,0xff,0xfd,0x83,0xdb,0xc1,0x07,0xfc,0x40,0x6f,0xda,0x0d,0x47,0xff,0xf2,0x0f,0x4b,0xf8,0x7c,0x60,0xda,0x88,0x0c,0x72,0x01,0xb0,0xff,0xe0,0x01,0xe9,0xff,0x80,0x68,0x21,0xff,0xa9,0x06,0x02,0x01,0xf2,0xbf,0x40,0x12,0x44,0x1f,0x2b,0x82,0xa1,0x7d,0x11,0xf8,0x05,0xf8,0x1e,0x74,0x7f,0x80,0xc0,0x75,0x50,0xa8,0x04,0x83,0xf0,0x0f,0x1b,0xe1,0x48,0x6f,0xfb,0x78,0x38,0x3c,0x40,0x09,0xfc,0x81,0x83,0xcb,0xfb,0xbf,0xbf,0xcb,0xbe,0x1a,0x8d,0x56,0xaa,0x55,0x80,0x85,0x18,0xc4,0x5e,0xb3,0xce,0x00,0x7d,0x7b,0x80,0x21,0xdf,0xcf,0xef,0xee,0x72,0x2f,0x8e,0xaa,0x01,0xa8,0xd1,0x62,0xa7,0xfa,0x0c,0x06,0x7d,0x82,0x33,0x8f,0x3d,0xfe,0x04,0x18,0x15,0x68,0xc0,0x1e,0xa2,0x02,0x1f,0x0f,0xff,0xbf,0x3f,0xe3,0xcf,0xc7,0x63,0xca,0xd5,0xe7,0xb5,0x58,0xa8,0x3e,0xa3,0x80,0x8e,0x29,0xfe,0x3c,0x2e,0x30,0x0b,0x85,0x56,0xea,0x73,0x11,0x10,0xd8,0x01,0xe5,0xcf,0x9f,0xcf,0xf5,0x50,0x2d,0x61,0x80,0x75,0x38,0xa2,0x28,0xda,0x09,0x63,0x9f,0x1f,0x0c,0xf8,0x3e,0x35,0x6a,0xad,0x54,0x3a,0x20,0x01,0xba,0x7f,0xf7,0xf9,0xff,0xbc,0xfe,0x7c,0x9c,0x1d,0x58,0x7c,0x74,0xd0,0xad,0x16,0xab,0x71,0xbf,0xef,0xfb,0xc1,0xe3,0x0c,0x1d,0x08,0x78,0x6a,0xb0,0xd0,0xf9,0x66,0x3f,0xbf,0xff,0x3f,0x9c,0x9c,0x3a,0x8e,0x50,0x78,0x75,0x59,0xa8,0x50,0x0c,0x7c,0x9f,0xff,0xcf,0x9f,0xe3,0x07,0x0b,0x8d,0x00,0x3e,0x51,0x50,0xf9,0x7c,0x3e,0x7f,0x99,0x3f,0xe2,0x0f,0x2a,0x5f,0x10,0x00,0xb1,0x4c,0x31,0xf8,0x7c,0x77,0x10,0x3f,0xe4,0x3c,0x2e,0x36,0x00,0xf9,0x4d,0x43,0xe5,0xe0,0x9c,0xfb,0xa0,0x7e,0x88,0x78,0x68,0x76,0x41,0xe2,0xb5,0x17,0x86,0x05,0xf8,0xcc,0x7f,0xe0,0x3f,0xc8,0x30,0x5c,0x6a,0x01,0xf2,0xaa,0x87,0xcb,0xf1,0xc2,0xff,0xc0,0x00,0x22,0x3e,0x50,0x01,0x42,0xaf,0x1d,0x09,0xfe,0x00,0x1e,0x20,0x01,0xac,0x07,0x8b,0xaa,0x07,0x29,0xe7,0x0a,0x1e,0x0f,0x20,0xfc,0x4a,0xa7,0x9e,0x85,0xa8,0xf0,0xc2,0xe5,0x54,0x1f,0x9c,0x04,0x3e,0x5e,0x00,0x18,0xf1,0xe0,0x3a,0x06,0xf1,0xb8,0x08,0x7e,0x33,0x8a,0x04,0x02,0x51,0xe3,0x4f,0x90,0x7d,0xc0,0x07,0xfa,0x80,0x68,0xe1,0x5e,0xc0,0xf1,0x6e,0x83,0xe4,0x0e,0x28,0x57,0xe3,0xce,0x18,0x1e,0xa0,0x78,0xab,0xa1,0xf6,0xfc,0x7f,0xf0,0x72,0xa0,0xfa,0xca,0xa5,0x50,0x08,0x46,0x01,0x46,0x3f,0xf3,0x18,0x87,0xf3,0xbf,0x00,0xd5,0x7b,0x37,0xfa,0xaf,0x56,0xff,0x53,0x82,0x0f,0x8c,0x83,0x51,0x02,0xff,0x5f,0xc2,0x63,0xd4,0xaf,0xa7,0x86,0xbe,0x1f,0x6d,0xf5,0xff,0x51,0x2a,0xd6,0x6b,0xc7,0xe3,0xaf,0xd4,0xe0,0x03,0xe2,0x06,0x18,0x17,0xf2,0xf6,0x7f,0xd2,0x78,0xea,0x21,0x49,0xf4,0x80,0xe0,0x35,0x40,0x11,0x0f,0x97,0xfc,0x30,0x21,0xfb,0xbf,0x43,0xc3,0xed,0x81,0x0e,0x90,0x7c,0xa7,0xd1,0xf1,0xf9,0x5d,0x6a,0xa0,0x11,0x0f,0xb4,0xf2,0x7c,0x57,0x16,0xfa,0xe2,0x80,0xa7,0x00,0x9c,0x07,0xca,0xac,0x3f,0x35,0x30,0x80,0x19,0x6e,0x3a,0xef,0x52,0xf8,0x75,0x5a,0xbd,0x10,0x80,0x90,0x43,0xe0,0x98,0x04,0x45,0x3a,0x2b,0xe1,0xaa,0xc1,0x60,0x16,0x00,0xe9,0xfd,0x2d,0x1a,0xac,0x56,0xbb,0x55,0xfb,0x01,0x0e,0x2f,0x45,0xb2,0x0f,0x8c,0x2a,0x01,0xfc,0xec,0x40,0x6c,0x01,0xf1,0xab,0xb0,0x46,0x6b,0x00,0xee,0x27,0xd3,0x51,0x0e,0xdc,0x07,0x07,0x56,0x02,0x1f,0x5e,0x03,0x56,0x1f,0x1d,0x04,0x2b,0xfd,0x59,0xfa,0xd5,0xcb,0x83,0x57,0x01,0x95,0xff,0xaa,0x1f,0x3f,0xfe,0xdc,0x2a,0x21,0xc1,0xfd,0x1e,0xce,0xd5,0x0a,0x85,0x10,0x06,0x7b,0x53,0x3e,0x18,0x01,0x43,0xe7,0xc0,0x7d,0x90,0x7c,0x40,0x09,0x2a,0x94,0x4a,0x17,0xe3,0xe3,0xb5,0x87,0xa0,0xc2,0x20,0x01,0xc0,0x78,0x7b,0xe1,0xc5,0x00,0x16,0x68,0x42,0x3a,0xae,0x17,0xc7,0x3e,0x1f,0x88,0x68,0xf8,0xfe,0x10,0x13,0xb1,0x00,0x0c,0x0c,0x3a,0x65,0x48,0x8f,0xc7,0xf0,0xdd,0x57,0x0c,0x7f,0x14,0x22,0x5f,0x5d,0x5f,0xeb,0x51,0xaa,0xd1,0x07,0xc7,0xf8,}; -const uint8_t _A_Levelup1_128x64_4[] = {0x01,0x00,0x7e,0x02,0xff,0x80,0x3c,0x01,0xf1,0xff,0xe0,0x3f,0x7d,0xff,0xd1,0x0f,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x2d,0xff,0xee,0x0f,0xef,0x47,0xff,0xfc,0x06,0x2d,0xf8,0x3d,0xe0,0x3e,0x49,0x3f,0xc0,0xfc,0x7f,0x8f,0xfc,0xed,0x02,0x37,0xff,0xc5,0xbe,0x01,0xf0,0xaf,0xe0,0xc1,0xe7,0xe0,0xff,0xc0,0xc2,0xe3,0x1f,0xf8,0x4f,0xe0,0x17,0x0b,0xf5,0x81,0x34,0x40,0xf1,0xb8,0xc1,0x38,0x1f,0xd8,0x3f,0xe2,0x73,0x00,0xf7,0xc7,0xe4,0x02,0xb1,0xff,0xcf,0xf0,0x02,0x81,0xc0,0x77,0xe0,0x37,0xf8,0x47,0x82,0xff,0x0e,0x6e,0x1c,0x1d,0xc4,0x3e,0x08,0x0d,0xfb,0x80,0x2e,0x1f,0x00,0x08,0x60,0x06,0x02,0xc3,0xc0,0x41,0x23,0x81,0x04,0x89,0x38,0x6c,0x11,0xfc,0x04,0x3c,0x1e,0x3f,0x78,0x3c,0x0e,0x01,0xc0,0x83,0xff,0xa0,0x60,0x52,0x8c,0x88,0x45,0x00,0x63,0x02,0xe2,0x6a,0xe3,0xc0,0x41,0x00,0x09,0xf8,0xd2,0x63,0x4f,0x04,0x1d,0xfc,0x1e,0x65,0xd2,0x01,0x09,0xc8,0x60,0xd0,0x0d,0x66,0xab,0x54,0x45,0x10,0x00,0xfb,0x3f,0xff,0x3f,0x8f,0xcf,0xd9,0xf9,0x87,0xd4,0x06,0xc5,0x03,0x8a,0x03,0xc7,0xf9,0xcf,0xf3,0xdf,0xfc,0xfc,0x4f,0xfc,0x2e,0x01,0xab,0x0f,0x88,0x90,0x45,0xe5,0x87,0x1f,0x94,0x02,0x9f,0x08,0xca,0x01,0x8a,0x9f,0x15,0x07,0x8d,0xe3,0x80,0x0f,0x30,0xc8,0xf0,0x03,0xc3,0xaa,0x8d,0x14,0x13,0x9f,0xfb,0x07,0x8c,0x02,0x21,0xd0,0x0b,0x15,0x7e,0x2a,0x51,0x1b,0x07,0xfb,0xcd,0xff,0xe1,0x9f,0x8b,0x40,0x1f,0x29,0x50,0x78,0xa7,0x93,0x9c,0x87,0xfe,0x03,0x1f,0x5f,0x90,0x7c,0xa7,0xf5,0x5a,0x84,0x07,0x7c,0x95,0x1f,0xbb,0x48,0x41,0xe3,0xb0,0x0f,0x95,0xa8,0x3e,0x51,0xe7,0x00,0xdf,0xe6,0x0a,0xf1,0x82,0x29,0xce,0xff,0x55,0xaa,0xc0,0x60,0x90,0x0c,0x04,0x7f,0xfd,0xfd,0x20,0x0e,0xa0,0x3e,0x5a,0xa2,0xf9,0x9a,0x47,0x8e,0x19,0x14,0xf0,0xfe,0x58,0xe7,0x54,0xaa,0x84,0x13,0xdf,0xfb,0x12,0x88,0x7e,0x4b,0x43,0xe3,0xb7,0xc0,0x2a,0x9f,0xd0,0xf9,0x8f,0xc5,0xe4,0x9c,0x38,0x18,0x10,0x5b,0xc4,0xe0,0x50,0x79,0x60,0x40,0x63,0x40,0x0f,0xbd,0x50,0x26,0xaf,0x71,0x0f,0x16,0xe8,0x16,0xd1,0xfb,0x85,0xc2,0x00,0x1f,0x50,0x80,0xd5,0x22,0x20,0xf1,0xff,0x7e,0x3f,0x01,0xfb,0xec,0x7f,0xef,0x12,0x08,0x07,0xf0,0x3e,0x71,0x58,0x24,0x16,0x28,0x1e,0x20,0x40,0xf8,0xe0,0x3e,0xcd,0xfe,0xab,0xd5,0xbf,0x0f,0xad,0x6d,0x3e,0x41,0xf5,0xa8,0xd5,0x60,0xa0,0x11,0x67,0x8e,0xfa,0xfe,0x0f,0x1d,0x66,0xbc,0x7e,0x3a,0xf0,0xfa,0xff,0xe3,0xe0,0x11,0x0f,0xad,0x56,0x8b,0x41,0xaa,0xc5,0x60,0x1f,0xb8,0x4e,0x5c,0x1e,0x29,0xf9,0xe0,0x7f,0xe1,0xb1,0xf8,0x7a,0xfd,0xc3,0xe3,0x05,0xb0,0x43,0xf8,0x17,0xf6,0xf8,0x87,0xe6,0x61,0x04,0xf0,0x46,0x20,0x15,0x50,0xfc,0x04,0xca,0xe4,0x15,0x26,0xfd,0x40,0x22,0x00,0x21,0xa8,0xa5,0x08,0x00,0x35,0x3a,0xad,0x50,0xbc,0x20,0x01,0xb0,0x00,0xcb,0x5d,0xea,0x5f,0x0e,0xaa,0x06,0x1f,0x5f,0xc4,0xc2,0x01,0x15,0x0f,0x1f,0xfe,0xaf,0x55,0xb2,0x9f,0xc8,0x1e,0x36,0x88,0x06,0x03,0x5d,0xaa,0xfd,0x80,0x86,0x17,0x00,0xd8,0x07,0xcf,0xdd,0xf9,0xa8,0xf9,0x43,0xe9,0x3f,0xaa,0xff,0x08,0x02,0x61,0x1f,0xf6,0xae,0x1d,0xb8,0x0e,0x0e,0xac,0x04,0x3e,0xbc,0x06,0xac,0x3c,0x58,0x0f,0xff,0xec,0x3a,0x80,0x04,0xaa,0x20,0xc7,0xc1,0x4f,0xd9,0x9e,0x84,0x38,0x3f,0xa4,0x09,0xda,0x87,0xe7,0x08,0xfb,0x87,0xa2,0xff,0x55,0xa8,0x18,0x0b,0x4e,0x1f,0x30,0x02,0x4a,0x90,0x09,0xef,0x0f,0xc1,0x84,0x60,0xb4,0x16,0xe0,0xf7,0x43,0x8a,0x00,0x28,0xd0,0x7d,0x0c,0x22,0x00,0x7a,0x79,0x78,0x55,0x62,0x10,0x1d,0x58,0x75,0x40,0xc3,0x06,0x60,0xab,0x75,0x1c,0x2b,0x55,0xa0,0xb0,0x4c,0xbe,0xba,0xbf,0xd0,0x79,0x40,}; -const uint8_t _A_Levelup1_128x64_5[] = {0x01,0x00,0x79,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1f,0xff,0xfb,0xcf,0xc0,0xc9,0xf0,0xf1,0x84,0x1e,0xff,0xfe,0x80,0xff,0x3f,0xb7,0xbf,0xe7,0x3c,0x1c,0xdb,0xff,0xfc,0xff,0xfc,0x1b,0x80,0x02,0x73,0xf5,0xf9,0xf8,0xff,0xff,0x8f,0x9f,0xfc,0x0b,0xde,0xe5,0xdd,0xba,0xf3,0xbe,0x3c,0x78,0x08,0xf5,0xe6,0x3a,0xcd,0x56,0xaa,0xc3,0xf0,0xa7,0xe0,0x3f,0xff,0xe1,0xf2,0x5f,0x20,0x15,0x6a,0xad,0x57,0x07,0xf3,0x87,0xf8,0x3f,0xfe,0x11,0x02,0x4d,0xe0,0x1a,0xbd,0x76,0xaf,0x0d,0xff,0x80,0x7c,0x3f,0xbc,0x70,0x7a,0x4f,0xf0,0x41,0xe1,0xaa,0xfb,0x67,0xf0,0x02,0x70,0x9c,0x4c,0x7c,0x33,0xfe,0x3e,0xa8,0x3e,0x31,0xa8,0x78,0x3c,0x89,0xc9,0xd0,0xff,0xd1,0xea,0xb5,0x7a,0xbc,0x56,0x01,0x00,0xfe,0x03,0xd4,0x2c,0x3a,0xf2,0xf0,0xea,0xa5,0x40,0xf1,0x9c,0x1f,0xdb,0x1f,0x67,0x0f,0x94,0xd6,0x01,0x04,0x80,0x18,0x07,0x7f,0xef,0x07,0x94,0x3f,0x64,0x1f,0x2b,0x50,0x7c,0x46,0x25,0xfd,0xef,0xb7,0x47,0x3f,0x0c,0xa8,0x07,0xc8,0xc2,0x30,0x10,0x78,0xfc,0x08,0x09,0x18,0xd4,0x6a,0x90,0x03,0xaa,0x06,0x8c,0x70,0x60,0x47,0xd2,0xff,0xcc,0xfb,0x01,0xd2,0xef,0xd5,0x20,0x37,0xf0,0x78,0xfe,0xc2,0x05,0xc7,0x83,0xfa,0x35,0x46,0x21,0xdd,0x40,0x30,0x10,0xfc,0x63,0xd4,0x5f,0x03,0xef,0x07,0x8d,0xd7,0xab,0x55,0xae,0xdd,0x6a,0xb8,0x58,0x7e,0xff,0xce,0x1d,0x12,0x10,0xfc,0xe0,0xfa,0xcf,0xd6,0xa8,0x02,0x24,0xe1,0x81,0xb7,0x84,0xdc,0x57,0xf9,0x7c,0x02,0xab,0x75,0x00,0x0d,0x56,0x82,0x10,0x10,0x78,0xc3,0xde,0x25,0x06,0x3b,0x0e,0xeb,0x55,0xea,0xfd,0x1b,0x8a,0xff,0x7f,0xbf,0x2c,0xc7,0xe7,0x0e,0x80,0x75,0x2a,0xb7,0x7a,0xbd,0x76,0x8b,0x05,0x80,0x06,0xc6,0xf8,0xb2,0x1b,0x1a,0x58,0x83,0xec,0x6e,0x41,0x70,0xd5,0x0b,0xc2,0x00,0x10,0xf9,0x08,0x04,0x7a,0x5f,0xf8,0x60,0x7c,0xb7,0xe1,0xf1,0xff,0x87,0xca,0x01,0xfd,0x07,0x96,0x26,0x07,0x40,0xfa,0xb1,0x47,0xbf,0x7f,0xa2,0xb0,0x0b,0xf1,0x7f,0x10,0x8f,0x82,0x0f,0x00,0xd6,0x7b,0xcf,0xe3,0xaf,0x0f,0x96,0x03,0xff,0x39,0xff,0x63,0x7f,0xf1,0xf3,0xf9,0x00,0x4a,0x82,0x01,0x1c,0x07,0x7c,0xc4,0x38,0x71,0x88,0xc0,0x75,0x83,0xf2,0x0f,0x9c,0x02,0x0c,0x21,0x17,0x01,0x41,0xea,0x85,0xf2,0x00,0x12,0x84,0xb0,0x0d,0x11,0xff,0xcf,0xa0,0xba,0xcd,0x50,0x00,0x83,0xe7,0x00,0xe0,0x7c,0x57,0xe3,0x78,0x9c,0x55,0x07,0xe7,0x55,0x8a,0xd0,0x02,0x43,0xe0,0xfe,0x7d,0xff,0xfe,0x9b,0xc0,0x7e,0x60,0x13,0x07,0x01,0x5e,0x2a,0xc3,0xd3,0x43,0x0a,0x04,0x42,0x05,0x8c,0xc1,0xc7,0xfe,0x1a,0xef,0x56,0xa9,0x82,0x30,0x30,0xfa,0x08,0x4a,0x1d,0x40,0xaa,0xb0,0x06,0xbb,0x55,0x82,0xd4,0x2c,0xa4,0x21,0x80,0x7c,0x20,0x76,0x83,0x20,0xeb,0xb5,0x5f,0xb0,0x10,0xc2,0xe0,0x1b,0x00,0xe9,0x2c,0x47,0xb1,0x01,0x0b,0x8f,0x56,0xaf,0x5f,0xaa,0xcd,0x6a,0x9d,0xca,0xa3,0x84,0xf5,0x10,0xed,0xc0,0x70,0x75,0x60,0x21,0xf5,0xe0,0x35,0x6c,0x13,0xbf,0x56,0xfe,0xb5,0x72,0xe0,0xd5,0xc0,0x65,0x7f,0xea,0xd1,0x20,0x14,0x0f,0x84,0xff,0x6e,0x7a,0x10,0xe0,0xfe,0x90,0x27,0x6a,0x1f,0x97,0x82,0x7e,0x19,0x20,0x03,0x8f,0x86,0x01,0xe7,0xbf,0xeb,0x43,0xe6,0x00,0x49,0x50,0x38,0x7f,0x9c,0xff,0xfd,0xbc,0x3d,0x13,0x5a,0xa9,0x38,0x78,0xf9,0xce,0xf0,0x71,0x40,0x05,0x1a,0x2f,0x0f,0x7f,0xff,0xf9,0xd8,0x07,0xe2,0x9b,0x50,0x80,0x33,0x47,0xc7,0x00,0xd5,0x87,0x54,0x0c,0x30,0x61,0xf8,0xdf,0xfe,0xc0,0xf1,0x6e,0xa3,0x85,0x0c,0x03,0x1c,0x10,0x0a,0xc8,0x4b,0xeb,0xab,0xfd,0x37,0x4e,0x77,0xfe,}; -const uint8_t _A_Levelup1_128x64_6[] = {0x01,0x00,0x38,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0x5f,0x78,0x37,0x20,0x3f,0xc0,0x7e,0x4f,0xff,0xde,0x3e,0x38,0xae,0xf9,0xf0,0x5c,0xe8,0x7e,0xf8,0xf3,0x3c,0x45,0x83,0xdc,0x1f,0xb8,0x6e,0x23,0x01,0xfd,0x1f,0xdc,0x0a,0x09,0x01,0xfd,0x03,0xaa,0xff,0x01,0x07,0x8f,0xd0,0x1f,0x5b,0xf8,0x00,0x3c,0x7d,0x00,0xfa,0xaf,0x83,0xcb,0xa0,0x0e,0x9f,0xb8,0x3c,0x60,0x50,0x20,0x7d,0xcb,0xc1,0xe5,0xa0,0xdb,0x83,0xe3,0xc6,0x0f,0x4d,0xff,0xdc,0x3f,0x11,0x70,0x79,0x50,0x23,0xe0,0xe7,0xfe,0x83,0xd7,0x7e,0x2f,0x8f,0xe4,0x2e,0x00,0x80,0x1c,0x06,0xf9,0x1b,0x1f,0xcc,0x5c,0x1c,0x1e,0x38,0xfd,0xf6,0x0f,0xbe,0xb3,0x5b,0xfd,0xf2,0x97,0x08,0xff,0xe1,0xf2,0x1e,0xec,0x38,0xfd,0xff,0x12,0x5c,0x84,0x06,0x99,0x20,0xfa,0xff,0x81,0xed,0xfb,0xfd,0xc9,0x6a,0x10,0x0a,0x84,0x80,0x58,0x9e,0xf3,0x7a,0x55,0x66,0x12,0x0b,0x05,0x40,0x1e,0x5f,0x11,0x0b,0x75,0x66,0x12,0x2b,0x15,0x63,0x7a,0x07,0x1f,0x80,0xf4,0xca,0x05,0xd5,0x88,0x48,0xa8,0x55,0x80,0x40,0xdf,0x3e,0x1f,0x30,0x60,0xff,0xb0,0xfe,0x3f,0xf0,0x3d,0x6e,0xf1,0xef,0xc7,0xec,0x40,0x58,0x7e,0x1f,0xbf,0xab,0x11,0x80,0x50,0x2b,0x81,0xf1,0x87,0xff,0x0c,0x49,0x07,0xc1,0xf5,0x63,0xf0,0x0e,0x05,0x7c,0x7e,0x30,0x70,0x71,0x35,0x0a,0x7f,0x02,0xd2,0xe7,0xff,0xfc,0xf9,0x78,0x7c,0x7c,0x7f,0xf8,0xf8,0x44,0xaf,0xb7,0xeb,0x14,0x92,0x9f,0x00,0xe8,0x49,0xf9,0xb3,0xdf,0x01,0x64,0x40,0x42,0x1e,0x1f,0xe5,0xda,0x89,0x30,0x80,0x58,0x22,0x1f,0x58,0xff,0xe2,0xf7,0xfc,0xf0,0x83,0xca,0x01,0x78,0xc2,0x0f,0xca,0x1f,0xfd,0x87,0xff,0xaf,0xbf,0xc1,0x90,0xff,0xe3,0xb0,0x0f,0x84,0x12,0x20,0x5f,0x18,0x07,0xf5,0x56,0x5f,0xcf,0xfe,0xff,0xbf,0x18,0x07,0x94,0x82,0x00,0x01,0x1f,0xe8,0x30,0x7f,0xbe,0xcf,0xf5,0xef,0xfd,0x38,0x83,0x70,0xa0,0xa0,0xf3,0x80,0xfe,0x38,0x56,0xf0,0x90,0xff,0xff,0x31,0x08,0x7c,0x10,0x3e,0x80,0xf1,0xa1,0x9b,0x87,0xef,0xfd,0xf9,0xc0,0x20,0xf1,0x88,0x30,0xf4,0x48,0x23,0x03,0xbf,0x79,0xe0,0x7f,0xe2,0x18,0xfc,0xf8,0x10,0x3f,0x80,0x3d,0x67,0x90,0x18,0x04,0x73,0xf8,0x10,0x1d,0x9c,0x0e,0xe1,0x05,0xe0,0x40,0x0a,0xa3,0x05,0x41,0x8c,0x00,0x04,0x2f,0x21,0xa5,0xc3,0xb2,0x10,0x4c,0x07,0xe6,0x19,0x00,0x84,0xc0,0x32,0x00,0xf1,0x80,0x78,0x3d,0xf8,0xb8,0x0d,0x80,0x1e,0x30,0x78,0x7c,0x02,0x63,0x00,0xc6,0x29,0x87,0xe0,0xb0,0x18,0x5c,0x3a,0x31,0x04,0x2e,0x08,0x08,0x78,0x38,0x0c,0x1e,0xe2,0x01,0xfe,0xf8,0x83,0xc7,0xe1,0x07,0x06,0x0c,0x1a,0x06,0x12,0x1b,0xfe,0x03,0x01,0x0f,0xf7,0x7f,0xfd,0x91,0x71,0xa0,0x83,0xc7,0xf0,0x3a,0x25,0x98,0xf0,0x21,0x69,0x01,0xe0,0x83,0xd0,0x00,0x80,0xf1,0x88,0xf6,0x3f,0x18,0x79,0x78,0x3e,0x14,0x62,0x6e,0x1b,0xc4,0x7e,0x4e,0x0f,0xaf,0x85,0xc7,0xf1,0x3f,0xa1,0x83,0x14,0x00,0x4a,0x31,0xf0,0x40,0xc1,0xe3,0x87,0x07,0xc7,0x20,0x04,0x30,0xee,0x7c,0xbe,0x06,0xb6,0x10,0x02,0x01,0x87,0xe9,0xc3,0x87,0xfe,0x23,0x77,0xc8,0x2c,0x18,0x7e,0xa0,0xf1,0xfd,0xf9,0xe3,0xf7,0x0b,0xdf,0xf0,0xf6,0x40,0xf5,0xfc,0x5c,0x27,0x93,0xc5,0x70,0xff,0xc0,}; -const uint8_t _A_Levelup1_128x64_7[] = {0x01,0x00,0xd0,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x05,0xfd,0x83,0xfb,0xbe,0x20,0xf0,0xff,0x83,0x72,0x01,0xfe,0x07,0xdf,0xf6,0x3f,0xff,0xf8,0x83,0xf3,0xcf,0x03,0xe7,0x40,0xff,0xc0,0xf9,0xfc,0x46,0x61,0x93,0x00,0xfe,0x41,0xa2,0x1c,0x0e,0xf0,0x3e,0xaf,0xb0,0x19,0x06,0x03,0xba,0x0f,0xad,0xfc,0x02,0x81,0x00,0xed,0x83,0xea,0xbe,0x0f,0x2f,0xa8,0x3e,0xa5,0xf0,0x0c,0x04,0x03,0xd4,0x0f,0xdf,0xc7,0xad,0xb5,0x51,0x70,0x78,0xc1,0xfa,0xdb,0xf0,0x84,0xc5,0xff,0xdc,0x08,0x07,0x60,0x3f,0x50,0xb8,0x0c,0x86,0x81,0xb0,0x0f,0xcf,0xef,0x17,0x7c,0x89,0x50,0x37,0x00,0xfa,0xa5,0xe0,0xa1,0x98,0x20,0x7d,0x78,0x28,0xb1,0xd8,0x2e,0x0a,0xa0,0xe3,0x10,0xfc,0x49,0x63,0xf0,0x9c,0x25,0xc2,0x17,0xfa,0x07,0xc6,0x97,0x3d,0x0a,0x82,0x5f,0xc3,0xf3,0xff,0xd2,0xff,0xa1,0x5c,0x0b,0x81,0x3e,0xb4,0x40,0xf1,0x98,0x78,0x37,0xc1,0xf9,0x07,0x94,0x23,0x81,0xbe,0xff,0x03,0xe2,0x85,0xff,0x85,0x41,0xb0,0x00,0xe1,0xfe,0x83,0x56,0x7e,0x0f,0x1b,0xef,0x36,0x03,0x9c,0x17,0xc5,0xff,0xdd,0x82,0xfd,0x4f,0xe0,0x1a,0x3e,0xf0,0xfe,0x70,0x51,0xc8,0x07,0x03,0x80,0x3e,0x9f,0xfc,0x0a,0x17,0x00,0x90,0x70,0x3f,0xbf,0x70,0x7c,0xc1,0x20,0x11,0x0a,0x01,0x34,0x7d,0xe3,0xe5,0x03,0x88,0x3c,0xa1,0x00,0xf2,0xf1,0x87,0xe6,0x03,0x06,0x90,0x03,0xc7,0xf7,0xe7,0x07,0xbc,0x03,0x0d,0x01,0x07,0x90,0x81,0x7f,0x00,0xf3,0xbc,0x10,0x04,0x1e,0x5f,0x10,0x79,0xfc,0x11,0xe2,0x0f,0x10,0x00,0xc2,0x01,0xe3,0x7f,0x50,0x27,0x82,0x7f,0xdc,0x07,0x9c,0x10,0x18,0x84,0x12,0x07,0x8f,0xf0,0x1e,0x70,0x2f,0xec,0xfd,0x22,0x5e,0x00,0x10,0xf0,0x7f,0x82,0xf4,0x80,0xef,0x63,0xe0,0xf1,0xdf,0x94,0x4a,0x0f,0xf0,0x07,0xa4,0x03,0xfb,0xc7,0xff,0xfd,0xe1,0xe2,0x22,0x8f,0xf2,0x2f,0xf0,0x10,0x79,0xfe,0xc7,0xc5,0x71,0xe0,0x28,0x0c,0x1e,0xfc,0xf0,0x58,0xe0,0x4a,0x87,0xbe,0x07,0x1c,0x03,0xeb,0xff,0xdb,0x8f,0x08,0xc4,0x7b,0xf0,0x7b,0x52,0xc1,0x83,0x0f,0xff,0xfc,0xf3,0x7f,0xfa,0x78,0x3d,0x3d,0x3f,0xfa,0x20,0x3c,0x71,0xea,0x31,0xb2,0xff,0xa6,0x60,0xf4,0xc8,0xc7,0xe8,0x7d,0x01,0xe9,0xe1,0x60,0x30,0xc0,0x7a,0x58,0x7c,0x14,0x0f,0x07,0x84,0xc8,0x50,0x5f,0xf4,0x0c,0x1e,0x98,0x18,0xfc,0x82,0x00,0x6e,0x38,0x28,0x35,0x14,0x05,0x00,0x90,0x7c,0x20,0x7f,0xe4,0x80,0xc2,0xd7,0x64,0x0f,0x58,0x87,0xc1,0x64,0x39,0xff,0xfc,0x20,0x1f,0x31,0x8b,0xf6,0x78,0xe0,0x31,0x70,0x7c,0x5a,0x26,0x1f,0x8c,0x7a,0x40,0x41,0xf3,0xf4,0xf0,0x40,0x70,0x04,0xf1,0x97,0x83,0xe3,0xf5,0xe1,0x83,0x98,0x08,}; -const uint8_t _A_Levelup1_128x64_8[] = {0x01,0x00,0xe6,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x00,0xbf,0xb0,0x7f,0x88,0x3c,0x3f,0xe1,0x0f,0x00,0x5c,0x3f,0xc0,0x1f,0xdf,0x8c,0x7c,0x1f,0x97,0xfb,0xf7,0x83,0xf8,0x21,0x10,0x04,0xe7,0xf0,0x30,0x7f,0x98,0x7e,0xed,0xf0,0x08,0x47,0xb0,0x1e,0x7c,0xf8,0x4c,0xcb,0xe6,0x0f,0x38,0xbc,0x02,0x21,0xd0,0x03,0x9e,0x3f,0x93,0x33,0x07,0xa4,0x2e,0x01,0x20,0xdc,0x07,0xcc,0x1e,0xf0,0x50,0x78,0xd1,0x80,0xe7,0x4f,0x84,0xc9,0xbf,0x20,0x62,0xff,0x40,0xa0,0x14,0x0c,0x0f,0xfb,0xde,0x0f,0x2e,0x4c,0x9c,0x1e,0xdc,0x08,0x07,0xf4,0x1e,0x5c,0xfe,0x44,0x1f,0xf0,0x7e,0x38,0x0f,0xfa,0x81,0x10,0xfe,0xf1,0xc1,0xe7,0xcf,0xfe,0x03,0xca,0xfd,0x01,0x80,0xc8,0x64,0x1f,0xa0,0xf9,0xc2,0x79,0xc0,0xf2,0xbf,0xff,0x30,0x17,0xc8,0x95,0x00,0x1e,0x60,0x06,0xdf,0x50,0x30,0x51,0x4a,0x0c,0x11,0x3d,0x3b,0xe9,0x04,0x7e,0x13,0x42,0xfe,0x0e,0x4c,0x00,0xb5,0xfd,0x04,0xce,0x15,0x04,0x83,0x24,0x07,0x9f,0x83,0xce,0x48,0x29,0xff,0x20,0x78,0xd7,0xb4,0x16,0x38,0x94,0x12,0x03,0xf4,0x07,0x8f,0xcf,0x39,0x3c,0x07,0x98,0x7c,0x6e,0x71,0x44,0x00,0xfa,0x01,0xe5,0xc9,0x07,0xb7,0xfe,0x29,0x20,0x07,0x9e,0x0f,0x92,0x2f,0x40,0x79,0xc6,0x30,0x1e,0xb0,0xfa,0x5b,0xda,0xe4,0x0f,0x38,0x3d,0x83,0xd8,0x0f,0x2f,0x18,0x3d,0x64,0x1f,0xfe,0x94,0x02,0x30,0x3f,0x30,0x78,0x9b,0xd2,0x81,0xfe,0x9d,0xc0,0x20,0x80,0xf1,0x87,0xe0,0xbe,0xf2,0x0a,0x40,0xfc,0xf0,0x11,0xc8,0x64,0x02,0x04,0x6f,0x14,0x7c,0x40,0x20,0xb0,0x88,0x01,0xfc,0x81,0xf3,0x02,0x80,0x1f,0xc7,0xf4,0x0f,0xc9,0x80,0x3f,0x30,0x10,0x02,0x00,0xff,0x41,0xf5,0x00,0xc1,0xc0,0xf0,0x1f,0xe0,0x7d,0xdf,0x20,0x14,0x00,0x41,0x43,0xc1,0x03,0x80,0x07,0xa8,0x00,0x54,0x62,0x00,0x1f,0x98,0x08,0x6f,0xe0,0xf7,0xe8,0x02,0x0a,0x1a,0x1f,0x21,0xb1,0x03,0xd3,0xb0,0x0f,0x28,0x30,0x1c,0x8a,0xc4,0x0f,0x4e,0xa0,0x3f,0x85,0xe7,0x06,0xce,0x62,0x01,0xe7,0x4f,0x07,0xc6,0x8b,0x09,0x01,0x07,0x8e,0xfe,0x5e,0x5f,0x70,0x78,0xe0,0xa0,0x61,0xf2,0x07,0xa5,0x80,0x1e,0x98,0x18,0x38,0x3c,0xa2,0xe0,0xf4,0xef,0xef,0xc3,0xee,0x0f,0x4d,0x01,0xe0,0x7f,0xc3,0xf5,0xff,0xc2,0xc1,0xed,0xfc,0x2f,0xaf,0x7e,0x0a,0x0f,0x39,0x00,0x60,0x8f,0xe9,0xf7,0xf8,0xbf,0x44,0x00,0x54,0x0f,0xd0,0x40,0x51,0xeb,0x78,0x80,0x83,0xd3,0xe8,0x1f,0x18,0x72,0xfd,0x33,0xe0,0xe3,0x07,0x8f,0x20,0x1e,0x23,0x22,0x6f,0x95,0x9c,0x1e,0xb3,0x0f,0xff,0xe3,0xf6,0x0c,0x13,0xa0,0xff,0xe3,0x34,0x00,0x7a,0x70,0x20,0x1f,0x78,0x38,0x18,0x78,0x1f,0xf8,0x0c,0x18,0x1e,0xb0,0x0f,0xff,0xa1,0x44,0x40,0x01,0xff,0x40,0x41,0xed,0x00,0xf4,0x7f,0x7b,0xe0,0xf2,0x2e,0x88,0x3e,0x3c,0x61,0xf3,}; -const uint8_t _A_Levelup1_128x64_9[] = {0x01,0x00,0xd6,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x01,0x3d,0xe0,0xff,0x06,0xe4,0x0f,0xf0,0x0f,0xab,0xf8,0x04,0x7f,0x9c,0x7c,0x18,0x7a,0xf3,0xf0,0xf9,0xc0,0x7f,0x2c,0xff,0x0e,0x07,0xb8,0x1f,0x71,0xb8,0x04,0x0f,0xda,0x09,0x3e,0x7c,0x26,0x65,0xf3,0x07,0x9c,0x16,0x01,0x0c,0xfd,0x03,0xcf,0x1f,0xc9,0x99,0x83,0xd2,0x05,0x00,0x88,0x71,0x0e,0x26,0x0f,0x59,0x7d,0xea,0x03,0x00,0x90,0x6f,0x81,0xe7,0x4f,0x84,0xc9,0xbf,0x21,0xf2,0xdf,0xc0,0x20,0x14,0x0a,0x08,0x3d,0x39,0x32,0x70,0x7b,0x60,0x30,0x1f,0xee,0x39,0x3c,0xb9,0x10,0x7f,0xc0,0x3c,0xab,0xf0,0x09,0xfd,0x03,0x21,0xfe,0x80,0x83,0xcf,0x9f,0xfc,0x2b,0x15,0x7f,0x81,0xc0,0x90,0x48,0x3f,0xa1,0xf3,0x84,0xf3,0x81,0xe5,0x7f,0x97,0xc8,0x23,0xd1,0x10,0x78,0xa8,0x66,0x5f,0x90,0xb0,0xc2,0xa4,0x3c,0x20,0x7d,0x54,0x33,0xf0,0x68,0x14,0xe8,0x1f,0x31,0x7e,0x46,0xce,0x09,0x02,0xe3,0x7f,0x87,0xc3,0x83,0xce,0x48,0x29,0xff,0x20,0x79,0x7a,0x2c,0x70,0x5c,0x14,0x07,0xfa,0x0f,0x1f,0x9e,0x72,0x78,0x0f,0x5b,0x9c,0x16,0x81,0x00,0x60,0x88,0x3c,0x79,0x20,0xf6,0xbf,0xc1,0x66,0x00,0xf3,0xc1,0xf2,0x45,0xec,0x0f,0x18,0x67,0x03,0xf6,0x1f,0x4b,0x78,0x18,0x7f,0xf0,0xbe,0x47,0xfe,0x09,0x03,0xf8,0x03,0xcf,0xc6,0x0f,0x5e,0x87,0xff,0x85,0x00,0xfc,0x5f,0x41,0xe8,0x6f,0x38,0x5e,0x42,0x1f,0x3f,0x80,0x7f,0x27,0xdf,0xe8,0x7e,0x0b,0xef,0x20,0xa4,0x0f,0xca,0x17,0x20,0x81,0x41,0x20,0x17,0xfb,0xfa,0x3e,0x21,0x7c,0x08,0x0b,0xc0,0x77,0xe0,0xe8,0x07,0x8c,0x00,0x1e,0x3e,0x0e,0xf8,0x3a,0x3e,0xe0,0xf3,0xfc,0x2f,0xa4,0x1e,0x49,0xd1,0xe7,0x40,0xd7,0xe2,0x00,0x6f,0x18,0x3c,0x70,0x1c,0x18,0x1f,0xfd,0x7e,0x21,0xf9,0x80,0x7f,0xa0,0x28,0xf2,0xff,0xc3,0xc1,0x03,0x80,0x07,0xa8,0x40,0x61,0xeb,0xf1,0xff,0xfc,0xc0,0x42,0x75,0x30,0x79,0x80,0x04,0x1e,0x50,0xd0,0xf9,0x11,0x88,0x1e,0xa2,0xf2,0x83,0x01,0x88,0x8c,0x40,0xf4,0xe0,0x7f,0x01,0xfb,0x30,0x1c,0x14,0x1b,0x39,0x88,0x07,0xc7,0x38,0x1e,0x7a,0x2c,0x24,0x04,0x1e,0xdc,0x01,0xf1,0x03,0xcb,0x05,0x03,0x07,0xb7,0xf0,0x1e,0xb8,0x18,0x38,0x3c,0xa0,0xa0,0xf2,0xfc,0x07,0xe8,0x1e,0x7e,0x0f,0xa8,0xfe,0x41,0xe7,0x00,0xfa,0x17,0xe6,0x04,0x0f,0x3f,0x60,0x3c,0xcf,0xea,0x0f,0xeb,0xfc,0x04,0x1e,0x7d,0x80,0x79,0x43,0x97,0xe8,0x0f,0x91,0x59,0x37,0xcb,0x7e,0xce,0x4d,0x40,0x3c,0x8e,0x65,0xbf,0x07,0x9d,0x00,0x1e,0xd0,0x75,0x39,0x01,0x46,0xbe,0x0f,0x4a,0x40,0x3c,0x80,0x0b,0x2f,0x80,0x48,0x01,0xe5,0x88,0x24,0x08,0x01,0xa2,0xe0,0xf4,0x84,0x13,0x08,0x00,0x80,}; -const uint8_t _A_Levelup1_128x64_10[] = {0x01,0x00,0xde,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x09,0xef,0x06,0xe4,0x0f,0xf0,0x0f,0xcb,0xff,0xf3,0x8f,0xc7,0x07,0xde,0x7e,0x1f,0x38,0x0f,0xe5,0x9f,0xe1,0xc0,0xf7,0x03,0xee,0x37,0x00,0x81,0xff,0x4a,0x27,0xcf,0x84,0xcc,0xbe,0x63,0xd2,0xff,0xc1,0x60,0x10,0xcf,0xd0,0x5c,0xf1,0xfc,0x99,0x98,0x3d,0x20,0x50,0x08,0x87,0x10,0x3e,0x60,0xf5,0x9f,0xdf,0xa0,0x30,0x09,0x06,0xf8,0x1e,0x74,0xf8,0x4c,0x9b,0xf2,0x1f,0x2d,0xfc,0x02,0x01,0x40,0xa0,0xff,0xce,0x25,0x4f,0xe4,0xc9,0xc1,0xed,0x80,0xc0,0x7f,0xb5,0x64,0xf2,0xe4,0x41,0xff,0x04,0x62,0xaf,0xc0,0x27,0xf4,0x0c,0x85,0xfa,0x22,0x62,0x10,0x78,0xf3,0xff,0x80,0xf3,0xe0,0x70,0x24,0x12,0x0f,0xe8,0x7c,0xe1,0x3c,0xe0,0x79,0xcb,0xe4,0x11,0xe8,0x88,0x3c,0x56,0x33,0x2f,0xc8,0x58,0x61,0x52,0x1e,0x12,0xc6,0x3f,0xd2,0xfa,0x86,0x7e,0x0d,0x02,0x9d,0x2b,0xa6,0x2f,0xc8,0xd9,0xc1,0x20,0x5c,0x66,0x08,0xf3,0xf0,0x79,0xc9,0x05,0x3f,0xe4,0x1f,0x18,0xbf,0xa2,0xc7,0x05,0xc1,0x40,0x4b,0xc5,0xf3,0xce,0x4f,0x01,0xeb,0x73,0x82,0xd0,0x20,0x0c,0x11,0x07,0x8f,0x24,0x1e,0xd7,0xf8,0x2c,0xc0,0x1e,0x78,0x3e,0x48,0xbc,0xab,0xff,0x40,0x79,0xc3,0x38,0x1f,0xb0,0xfa,0x5b,0xc0,0xc3,0xfe,0x85,0xf2,0x3f,0xf0,0x48,0x1f,0xc0,0x1e,0x7e,0x30,0x7a,0xf4,0x3f,0xfc,0x28,0x07,0xe0,0x9e,0x60,0xf1,0x37,0x9c,0x2f,0x21,0x0f,0x9f,0xc0,0x3f,0x9f,0xef,0xfc,0x3f,0x05,0xf7,0x90,0x52,0x09,0xe5,0x0b,0x90,0x40,0xa0,0x90,0x0b,0xfa,0x3e,0x61,0x7c,0x08,0x0b,0xc0,0x77,0xe0,0xfa,0x80,0x03,0xc7,0xc1,0xdf,0x07,0xef,0xe1,0x9d,0x00,0xf3,0x4e,0x8f,0x3a,0x06,0x4f,0x10,0x03,0x7d,0xc1,0xe3,0x80,0xe0,0xc0,0xff,0xe6,0xf1,0x0f,0xcc,0x03,0xfd,0x01,0x47,0x91,0xc0,0x41,0x03,0x80,0x07,0xa8,0x40,0x61,0xeb,0xf1,0xff,0xfc,0xc0,0x42,0x76,0x30,0x79,0x80,0x04,0x1e,0x50,0xd0,0xf9,0x11,0x88,0x1e,0xa2,0xf2,0x83,0x01,0x88,0x8c,0x40,0xf4,0xe0,0x7f,0x01,0xfb,0x30,0x1c,0x94,0x1b,0x39,0x88,0x07,0xc7,0x38,0x1e,0x7a,0x2c,0x24,0x04,0x1e,0xdc,0x0f,0xdc,0xfc,0x92,0x20,0xf1,0xc1,0x40,0xc1,0xed,0xfc,0xfd,0x87,0xd3,0x03,0x07,0x07,0x94,0x14,0x1e,0x5f,0x80,0x7a,0x87,0xd0,0x1e,0x7e,0x0f,0xaa,0x20,0x87,0xec,0x0f,0x38,0x07,0xd0,0x1e,0x65,0xf5,0x81,0x03,0xcf,0xd8,0x0f,0x33,0xfa,0x83,0xfa,0xff,0x01,0x07,0x9f,0x60,0x1e,0x50,0xe5,0xfa,0x03,0xe4,0x56,0x46,0x52,0xdf,0xb3,0x93,0x50,0x0f,0x26,0x91,0x6f,0xc1,0xe7,0x40,0x07,0xb4,0x1d,0x4e,0x40,0x51,0xaf,0x83,0xd2,0x90,0x0f,0x20,0x02,0xcb,0xe0,0x12,0x00,0x79,0x62,0x09,0x02,0x00,0x68,0xb8,0x3d,0x21,0x04,0xc2,0x00,0x20,}; -const uint8_t* const _A_Levelup1_128x64[] = {_A_Levelup1_128x64_0,_A_Levelup1_128x64_1,_A_Levelup1_128x64_2,_A_Levelup1_128x64_3,_A_Levelup1_128x64_4,_A_Levelup1_128x64_5,_A_Levelup1_128x64_6,_A_Levelup1_128x64_7,_A_Levelup1_128x64_8,_A_Levelup1_128x64_9,_A_Levelup1_128x64_10}; - -const uint8_t _A_Levelup2_128x64_0[] = {0x01,0x00,0x34,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0x38,0x1f,0xe0,0x1d,0x97,0xff,0xe7,0x1c,0x1f,0x99,0xf8,0x1c,0xfc,0x1f,0x96,0x7f,0x87,0x03,0xf8,0x0f,0xb8,0xdc,0x22,0x01,0xfb,0x07,0xdc,0x16,0x09,0x00,0xfa,0x03,0xee,0x1d,0x02,0x80,0x7a,0x0b,0xd7,0x31,0x07,0x8f,0x40,0x1f,0x5b,0xfa,0x04,0x06,0x01,0xa0,0x07,0xd5,0x7f,0x00,0x0f,0xe8,0x26,0x06,0x7f,0x40,0x07,0xd4,0xbe,0x05,0x42,0xa0,0x03,0xf2,0x03,0x24,0xcf,0xe0,0x3f,0xc5,0xe9,0x88,0x50,0x72,0x92,0x0c,0x08,0x3e,0x73,0xf1,0xf9,0x0d,0x22,0xf9,0x82,0x07,0xcd,0xbe,0x61,0x10,0x94,0x79,0xa0,0x5f,0xd0,0x7c,0x45,0xe8,0x11,0x09,0x27,0x8c,0x1f,0x50,0xb3,0xf0,0xc5,0x3c,0xe0,0xfb,0x80,0x40,0xb2,0x9f,0xf0,0x7d,0x7a,0xe0,0x10,0xc0,0x7e,0x46,0xe0,0x77,0x00,0x7e,0x42,0xe1,0x98,0x0d,0x2d,0xfc,0x1f,0x71,0x08,0x05,0x3a,0x7f,0x01,0x37,0xd4,0x81,0xfa,0x39,0xf8,0x01,0xfe,0xe0,0x12,0x0a,0x40,0x3e,0xa5,0xef,0xe2,0x98,0x03,0xee,0x01,0x06,0x80,0x10,0x84,0x1f,0x35,0xf8,0x04,0x62,0x00,0x00,0x10,0x7c,0xef,0xe0,0x1e,0x00,0x7e,0x5f,0xc7,0xc3,0x0f,0x07,0xda,0x6c,0x43,0xc4,0x0f,0xb8,0x28,0x3f,0xa1,0xa0,0xfe,0x8a,0x8b,0xfc,0x1f,0xe0,0xfe,0x2f,0xa7,0xe8,0xff,0x30,0x30,0x7f,0x83,0xcf,0xe8,0xaf,0x91,0x7a,0x03,0xff,0xd0,0xdf,0x90,0x7a,0x74,0x1f,0xf2,0xcf,0x10,0x01,0x68,0x01,0xf1,0x17,0x07,0xa5,0x00,0x1f,0x10,0x90,0x7a,0x60,0x3f,0x80,0xd5,0xc7,0xdf,0xe0,0xc0,0xf4,0x80,0x7c,0xc1,0xeb,0x77,0xc0,0x40,0x41,0xe9,0x01,0xe6,0x03,0xd7,0x17,0x7f,0x05,0x08,0x3d,0x26,0x18,0x00,0x7a,0x42,0xc1,0x44,0x0f,0x4e,0x05,0xfc,0x1f,0xa5,0x11,0xff,0x03,0xcc,}; -const uint8_t _A_Levelup2_128x64_1[] = {0x01,0x00,0x17,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x2f,0xf8,0x17,0x59,0xfe,0xf8,0x6b,0x37,0xf9,0xf0,0x32,0x7e,0xc1,0xac,0x02,0x19,0xff,0xfe,0x03,0xfc,0x11,0x5c,0xfe,0x7f,0xfe,0xf1,0x8c,0x2e,0x3d,0xce,0x80,0xe7,0xbe,0xff,0x90,0x7c,0xc3,0xe6,0x18,0x0b,0x0f,0xfb,0xf0,0x61,0x8c,0x7c,0x3e,0x19,0x40,0xc0,0x43,0x6f,0xc1,0xe8,0xbf,0xe3,0xa1,0x52,0x08,0x04,0x0a,0xfe,0x83,0x7f,0xdf,0xf6,0x09,0x05,0x88,0x40,0x30,0x89,0x28,0xfb,0xfb,0xf0,0x10,0x40,0x78,0xca,0x0f,0xee,0x00,0x18,0xfd,0x02,0x05,0x08,0x80,0x44,0x3f,0xc6,0x08,0xbf,0xd2,0x3f,0xc0,0xf2,0xfe,0x7f,0x41,0xef,0xf7,0x90,0x40,0xe1,0xf0,0x09,0x06,0xf1,0x3d,0x3a,0x88,0x04,0x63,0xf1,0xa3,0xfc,0x03,0xe6,0xa1,0x10,0x90,0x41,0x28,0x80,0xf1,0xf3,0xbe,0x5a,0xff,0xb2,0x88,0x50,0x3f,0x54,0x80,0x78,0xb0,0xda,0xfb,0xff,0xd8,0x42,0x30,0x50,0x5a,0x8e,0xe2,0x1f,0xfc,0xf7,0x84,0x17,0xf9,0x68,0x84,0x40,0xbc,0x79,0x2f,0xe7,0xdc,0xdf,0x17,0x88,0x46,0x07,0xc5,0xa3,0xfe,0x3c,0x9e,0xff,0x38,0xfc,0x41,0xf0,0x3e,0x5d,0x2f,0xe0,0x1e,0xf2,0x78,0x04,0xe2,0x19,0x80,0xfe,0xe9,0x78,0x1f,0x00,0x7b,0x61,0xf4,0x31,0xc7,0xf8,0xff,0x64,0xb0,0x9f,0xe7,0xff,0xbe,0x10,0x58,0x1b,0xf8,0x81,0xe3,0x01,0xff,0x6f,0xf7,0xe0,0xf5,0xd1,0xc1,0x30,0x18,0x1f,0xec,0x4e,0x13,0x8f,0xfb,0x83,0xda,0x1f,0xe4,0x80,0x65,0xbf,0x71,0x2c,0x0f,0x9f,0xe7,0xdf,0x39,0x1d,0xee,0xfd,0x9f,0x8a,0x40,0xfc,0x17,0xf8,0x4f,0x27,0xff,0xfb,0xf7,0xb8,0x8e,0x7f,0xfc,0x9f,0x43,0x21,0x90,0x0f,0x82,0x08,0x59,0xaf,0xff,0xcf,0xc3,0xa2,0x10,0x0c,0x04,0x1a,0x53,0xe0,0x07,0xa9,0x10,0x60,0x10,0xa9,0x04,0x02,0x01,0x01,0x80,0x83,0xda,0xff,0x1f,0xd0,0x42,0xa8,0x00,0xf1,0x80,0x6a,0x51,0xe3,0xf3,0x08,0x26,0x7a,0x03,0x12,0xc0,0x40,0x44,0x04,0x8f,0x1f,0x39,0xfd,0xa2,0x50,0x08,0x30,0x7c,0xbf,0xdf,0xfe,0x79,0xfd,0xa4,0x50,0x0b,0xc0,0x7c,0x81,0xee,0x96,0x1a,0x10,0xf8,0x83,0xe2,0x2f,0x1f,0x7f,0xec,0x1e,0x7c,0xf8,0x5e,0x08,0x1e,0x70,0x11,0xf0,0xa3,0xd0,0xfc,0x3a,0x38,0x11,0x38,0x83,0xe3,0xf7,0xf1,0xab,0x8d,0x4a,0x2d,0xf1,0x81,0x40,0x81,0xe5,0xc1,0xff,0xfc,0x45,0xc8,0x04,0x1d,0x38,0x38,0xe0,0x1c,0x99,0xff,0xe0,0xbc,0xbf,0x38,0x7c,0x0c,0x1e,0x74,0x28,0x79,0x80,0x49,0xc9,0xc3,0x97,0x83,0xd2,0x15,0x06,0x0f,0x2c,0xde,0x0f,0x87,0x17,0xa4,0x12,0x04,0x1f,0x1f,0x78,0x3c,0xa9,0x70,0xed,0x00,0x3d,0x34,0x92,0x0c,0xf6,0xfc,0xc0,0x78,0xb8,0xe5,0x00,0x1e,0x90,0x88,0x05,0x9f,0x3e,0x2f,0x38,0x5e,0x0e,0x44,0x0f,0x49,0x84,0xab,0x33,0xce,0x07,0xa4,0x72,0x30,0x0f,0x4e,0x04,0x03,0x0c,0x60,0x48,0xbf,0x82,0x0e,0x0f,0x48,0x07,0xff,0x02,0x0f,0x50,0x48,0x83,0xd6,0x01,0x80,0x07,0x89,0x40,0xa5,0xe0,0xf6,0x61,0x8d,0x01,0x22,0x80,0xfa,0xb3,0x03,0xce,0x82,0x0f,0x89,0x07,0x00,0xfe,0x78,0x10,0x7c,0xf8,0x3f,0x22,0x02,0x81,0x82,0x04,0x1e,0xd9,0x0a,0x17,0xf0,0x3e,0x40,}; -const uint8_t _A_Levelup2_128x64_2[] = {0x01,0x00,0xed,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x3f,0xe4,0x1f,0xdf,0x40,0x43,0xf3,0xc0,0xa9,0x7f,0xfb,0x03,0xdf,0x66,0x05,0x4d,0xff,0xbc,0x1e,0xf3,0xbf,0xf0,0x14,0xe3,0xf7,0x8f,0xf7,0xc4,0x1e,0xb1,0x3f,0xe0,0x14,0xe1,0xf9,0x02,0x0b,0xc5,0xc1,0xeb,0xcc,0xff,0x03,0xda,0x1e,0x0f,0x48,0x3f,0xbf,0xfd,0xf8,0x07,0xad,0xfc,0x1e,0x57,0xff,0xf4,0x0f,0xe7,0xff,0x07,0xaf,0x8e,0xff,0xf8,0xed,0xc7,0xee,0x1f,0xc8,0x18,0x34,0x41,0xeb,0xc3,0x9f,0xfc,0x3f,0x70,0xfe,0x07,0xfe,0x01,0x9c,0x0b,0x88,0x88,0x41,0xe7,0x1f,0xc8,0x5f,0xe0,0x7c,0x08,0x7c,0x03,0xf9,0x7f,0x9e,0x07,0xd3,0x8f,0x17,0x80,0x5e,0xde,0xe5,0x0a,0xff,0x4f,0xe3,0xc0,0xf4,0xc7,0xcf,0xe0,0x11,0x32,0x68,0x84,0x07,0xf7,0x3f,0x4b,0xa7,0xe2,0x7f,0x7f,0x82,0x70,0x20,0xb9,0xdd,0x54,0x08,0x3e,0x21,0xe4,0xfc,0x4d,0xff,0x10,0xe9,0x86,0x22,0xc0,0x1f,0x1b,0xf8,0xb8,0x58,0x47,0xfe,0x99,0xda,0x31,0xd0,0xcc,0x46,0x03,0x53,0x82,0xbd,0xe7,0x83,0xe9,0x3f,0x99,0xf0,0x20,0x90,0x28,0x24,0x06,0x05,0x80,0xbf,0xe3,0x2f,0xeb,0xe5,0x07,0x8c,0x04,0x02,0x3a,0x4e,0x07,0xbf,0x00,0xa6,0x25,0xf1,0xe0,0x30,0x10,0x00,0x78,0xc2,0x30,0x13,0xc0,0x79,0x00,0x0e,0xfd,0x80,0xa0,0x03,0xcb,0x21,0x0a,0x08,0x88,0x39,0x19,0x83,0x00,0x07,0x8c,0x0a,0x05,0x10,0x30,0x0f,0x03,0x7e,0x0f,0x3c,0xe7,0xbe,0x03,0x20,0x07,0x96,0x82,0x05,0x00,0x90,0x23,0xd2,0x33,0xff,0x07,0xa0,0x0c,0x41,0xe7,0xc7,0x07,0x8c,0x6b,0x9d,0x01,0x15,0x88,0x3c,0x68,0x1a,0x88,0x54,0x00,0x18,0x38,0xb0,0x10,0x9e,0x04,0x1e,0xa1,0xf1,0xc7,0x7f,0xfc,0x7f,0xd0,0x78,0xc1,0xe0,0x18,0x00,0xc8,0xa0,0x07,0x01,0xaa,0x85,0x36,0x47,0xce,0x3f,0x28,0x69,0x20,0x71,0x10,0x70,0x78,0xe3,0xc2,0xc3,0xff,0x07,0x18,0x00,0x60,0x38,0x0a,0x54,0x23,0xff,0x87,0xc8,0x68,0xa1,0x5f,0x80,0x7a,0x8c,0x06,0x49,0x90,0x80,0xd3,0x24,0x01,0x61,0xfc,0xfe,0xc1,0xeb,0x8a,0x92,0x54,0x20,0x15,0x09,0x06,0xa7,0xc0,0xeb,0x20,0x71,0x5f,0xe1,0xf0,0x0a,0xa4,0xc2,0x41,0x60,0xa8,0x40,0x7e,0x1e,0xff,0xe8,0x3c,0xa1,0xff,0xf8,0xf4,0xa3,0xa9,0x30,0x91,0x58,0xab,0x1a,0x9f,0x87,0x1e,0xff,0xde,0xc7,0x8b,0x47,0xd2,0x1f,0x1e,0xa4,0x42,0x45,0x42,0xac,0x07,0xc7,0x8f,0x3f,0xff,0x61,0xff,0xff,0x7e,0xfc,0x1f,0x40,0x0f,0x41,0xf8,0xf9,0xdf,0xa3,0xe3,0x7f,0x98,0x7c,0x62,0x2e,0x21,0xae,0x40,0x78,0x00,0xc2,0x4f,0x91,0x40,0x43,0xe3,0x1f,0x75,0x8d,0x7f,0x53,0x80,0xf1,0xbb,0xd0,0x00,0x30,0x0d,0x26,0x7f,0xff,0xcf,0x97,0xc0,0x60,0x1f,0x00,0x50,0x82,0x07,0xff,0xf3,0xfe,0xe0,0x64,0x94,0xf8,0x07,0x42,0x4f,0xa9,0x81,0x7f,0x3e,0xe0,0xf2,0xfe,0x78,0x3d,0xf0,0x1a,0x24,0xc2,0x01,0x60,0x88,0x07,0xc7,0xfc,0x0f,0x10,0xe8,0xa4,0xca,0x01,0x84,0x1f,0x94,0x3f,0x52,0xdf,0x10,0xf0,0xf9,0xfe,0x3f,0xfe,0x3c,0xf2,0x01,0x04,0x88,0x17,0xc5,0xe4,0x30,0x02,0x20,0xf7,0xfc,0xff,0x9f,0xfc,0x0a,0x31,0xa0,0x82,0x48,0x20,0x00,0x11,0xd4,0xe0,0xb3,0xfc,0x7f,0x3f,0xcf,0xf9,0xff,0x90,0xc0,0x03,0xe2,0x0f,0x36,0xf8,0xc3,0xf8,0x3e,0x7b,0xc0,0xf4,0x6f,0xf0,0x00,0xfa,0xe0,0x61,0x50,0x7f,0x05,0xde,0x38,0x7e,0x38,0x04,0x18,0x7a,0x24,0x11,0x81,0x81,0xc7,0xc1,0x13,0xc0,0x03,0x87,0x9f,0x80,0xd5,0x03,0xd3,0x07,0x0a,0x85,0x7c,0x20,0x3e,0x00,0x78,0xed,0xc2,0xe3,0x05,0xe0,0x40,0x23,0x00,0x41,0x41,0x8f,0x81,0x44,0x2b,0x21,0xa5,0x6a,0x31,0x50,0x4c,0x07,0xe6,0x19,0x00,0xc4,0xea,0xb2,0x41,0x91,0xfc,0x07,0xc7,0x15,0x01,0xb0,0x03,0xc6,0x0e,0xe4,0x19,0x8c,0x03,0x18,0x0f,0x1d,0xc7,0xef,0xff,0x08,0x87,0x46,0x20,0x86,0xc1,0x01,0x0f,0x07,0x01,0x83,0x81,0x4a,0xb9,0x06,0xe1,0x84,0x7c,0x20,0xe0,0xc1,0x83,0x17,0x46,0x03,0x7f,0xc0,0x18,0x48,0x5e,0x25,0x91,0x47,0x88,0xdc,0x40,0x82,0x00,0x1a,0x06,0x88,0xc2,0x20,0xf6,0x00,0x21,0xd4,0x4b,0xe2,0x0f,0x15,0x79,0x83,0xd7,0x41,0xaa,0x85,0x2f,0x87,0xfe,0xa9,0x10,0x7b,0x82,0x4b,0xfc,0xbf,0x11,0x29,0x00,0x1b,0x21,0xaa,0x95,0x03,0x87,0xfd,0x94,0x07,0xc4,0x20,0x3e,0x5f,0xff,0xc4,0x2e,0x02,0x0d,0x50,0x30,0xe9,0x07,0xe3,0xf6,0xff,0xfe,0x61,0x70,0x61,0xfa,0x83,0xc5,0xc2,0x4a,0xf2,0x81,0x9e,0xc4,0x1e,0xbf,0x8d,0x46,0xab,0x14,0x0f,0x20,}; -const uint8_t _A_Levelup2_128x64_3[] = {0x01,0x00,0x2d,0x03,0x8f,0xc0,0xb8,0x1f,0xfb,0xfd,0xe2,0x7f,0xf8,0x02,0x0f,0xff,0xff,0x03,0xff,0x00,0xc6,0xff,0x36,0xe0,0x47,0xfd,0xff,0x08,0xff,0xf3,0xff,0x3f,0x05,0x8f,0xf0,0x1e,0x5f,0xf8,0xfe,0x02,0xfb,0xff,0xf8,0x43,0xff,0x99,0xfd,0xf8,0x44,0x81,0xe7,0x17,0x88,0x7d,0x37,0xe0,0xf2,0x87,0xe7,0xff,0xe0,0x11,0xfe,0x83,0xca,0x1f,0x20,0xf8,0x0f,0x46,0x0f,0xfe,0x83,0xf6,0xff,0xfc,0xf0,0xfa,0x47,0xec,0x1e,0x08,0xf8,0x3c,0xa0,0x7c,0x3f,0xff,0x9c,0x1e,0x93,0xf8,0x06,0x02,0x1f,0xf8,0x2c,0x8c,0x07,0xc1,0xff,0xfd,0x83,0xdb,0xc1,0x07,0xfc,0x40,0x6f,0xda,0x0d,0x47,0xff,0xf2,0x0f,0x4b,0xf8,0x7c,0x60,0xda,0x88,0x0c,0x72,0x01,0xb0,0xff,0xe0,0x01,0xe9,0xff,0x80,0x68,0x21,0xff,0xa9,0x06,0x02,0x01,0xf2,0xbf,0x40,0x12,0x44,0x1f,0x2b,0x82,0xa1,0x7d,0x11,0xf8,0x05,0xf8,0x1e,0x74,0x7f,0x80,0xc0,0x75,0x50,0xa8,0x04,0x83,0xf0,0x0f,0x1b,0xe1,0x48,0x6f,0xfb,0x78,0x38,0x3c,0x40,0x09,0xfc,0x81,0x83,0xcb,0xfb,0xbf,0xbf,0xcb,0xbe,0x1a,0x8d,0x56,0xaa,0x55,0x80,0x85,0x18,0xc4,0x5e,0xb3,0xce,0x00,0x7d,0x7b,0x80,0x21,0xdf,0xcf,0xef,0xee,0x72,0x2f,0x8e,0xaa,0x01,0xa8,0xd1,0x62,0xa7,0xfa,0x0c,0x06,0x7d,0x82,0x33,0x8f,0x3d,0xfe,0x04,0x18,0x15,0x68,0xc0,0x1e,0xa2,0x02,0x1f,0x0f,0xff,0xbf,0x3f,0xe3,0xcf,0xc7,0x63,0xca,0xd7,0xe7,0xf5,0x58,0xa8,0x3e,0xa3,0x80,0x8e,0x29,0xfe,0x3c,0x2e,0x30,0x0b,0x87,0x76,0xea,0x73,0x11,0x10,0xd8,0x01,0xe5,0xcf,0x9f,0xcf,0xf5,0x50,0x2d,0x61,0x80,0x75,0x38,0xa2,0x28,0xda,0x09,0x63,0x9f,0x1f,0x0c,0xf8,0x3e,0x35,0x6a,0xad,0x54,0x3a,0x20,0x01,0xba,0x7f,0xf7,0xf9,0xff,0xbc,0xfe,0x7c,0x9c,0x1d,0x5e,0xbb,0x57,0xa6,0x85,0x68,0xb5,0x5b,0x8d,0xff,0x7f,0xde,0x0f,0x18,0x60,0xe8,0x43,0xc3,0x55,0x86,0x87,0xcb,0x31,0xfd,0xff,0xf9,0xfc,0xe4,0xe1,0xd4,0x72,0xb5,0x41,0xf1,0xcd,0x42,0x88,0x63,0xe4,0xff,0xfe,0x7c,0xff,0x18,0x38,0x5c,0x68,0x15,0x5a,0xbd,0x5e,0x2a,0x1f,0x2f,0x87,0xcf,0xf3,0x27,0xfc,0x41,0xe5,0x4b,0xe2,0x00,0x16,0x29,0x86,0x3f,0x0f,0x8e,0xe2,0x07,0xfc,0x87,0x85,0xc6,0xc0,0x1f,0x29,0xa8,0x7c,0xbc,0x13,0x9f,0x74,0x0f,0xd1,0x0f,0x0d,0x0e,0xc8,0x3c,0x56,0xa2,0xf0,0xc0,0xbf,0x19,0x8f,0xfc,0x07,0xf9,0x06,0x0b,0x8d,0x40,0x3e,0x55,0x50,0xf9,0x7e,0x38,0x5f,0xf8,0x00,0x04,0x47,0xc6,0x80,0x10,0x21,0x42,0xaf,0x1d,0x09,0xfe,0x00,0x1e,0x20,0x01,0xec,0x07,0x46,0xab,0xdf,0x03,0x94,0xf3,0x85,0x0f,0x07,0x90,0x7c,0x7d,0x5a,0xaf,0xfe,0xbf,0x74,0x1f,0x19,0x54,0xf3,0xd0,0xb5,0x1e,0x1a,0xdc,0xfa,0xb5,0x5a,0xed,0xd6,0x02,0x1f,0x2f,0x00,0x0c,0x78,0xf0,0x1d,0x03,0x78,0x7f,0x5a,0xa0,0x08,0xea,0x47,0xe3,0x38,0xa0,0x40,0x25,0x1e,0x34,0xf9,0x55,0x2e,0xa0,0x01,0xaa,0x87,0xc8,0x00,0x7f,0xa8,0x06,0x8e,0x15,0xfc,0x1e,0x0f,0xab,0xf4,0x1f,0x20,0x71,0x42,0xbf,0x1e,0x70,0xc0,0xf5,0x2a,0xb7,0x7a,0xbd,0x74,0x3e,0xdf,0x8f,0xfe,0x0e,0x54,0x1f,0x59,0x54,0xaa,0x01,0x08,0xc0,0x28,0xc7,0xfe,0x63,0x10,0xf8,0x80,0x04,0x3f,0x08,0x81,0xd5,0x7f,0x37,0xe1,0xf1,0xff,0xea,0x70,0x41,0xf1,0x90,0x6a,0x20,0x5f,0xeb,0xf8,0x4c,0x7e,0x9d,0xff,0xff,0x7e,0xfe,0x1f,0x6d,0xf5,0xff,0x51,0x2a,0xd6,0x7b,0xcf,0xe3,0xaf,0xd4,0xe0,0x03,0xe2,0xa3,0x18,0x17,0xf2,0xf6,0x7f,0x3a,0xa9,0xfe,0x09,0xe3,0xa8,0x85,0x6b,0x07,0xe5,0xaf,0x80,0xe0,0x35,0x40,0x11,0x0f,0x97,0xfc,0x30,0x35,0x42,0xf9,0x07,0xde,0xfd,0x0f,0x0f,0x93,0xf0,0xb5,0x58,0x10,0xe9,0x07,0xca,0x7d,0x1f,0x1f,0xec,0xf2,0x7c,0x57,0x10,0xfa,0x6a,0x71,0x40,0x53,0x80,0x4e,0x03,0xe5,0x56,0x1f,0x9a,0x98,0x40,0x0c,0xb7,0x1d,0x77,0xab,0x54,0xc1,0x1d,0x5e,0x88,0x40,0x48,0x21,0xf0,0x4c,0x02,0x23,0x55,0xea,0xaf,0x86,0xab,0x05,0x80,0x58,0x03,0xa7,0xf4,0xb4,0x6a,0xb1,0x5a,0xed,0x57,0xec,0x04,0x38,0xbd,0x16,0xc8,0x3e,0x30,0xa8,0x07,0xf3,0xb1,0x01,0xb0,0x07,0xc6,0xaf,0x5f,0xaa,0xcd,0x60,0x1d,0xc4,0xfa,0x6a,0x21,0xdb,0x80,0xe0,0xea,0xc0,0x43,0xeb,0xc0,0x6a,0xc3,0xe3,0xa0,0x85,0x7f,0xab,0x3f,0x5a,0xb9,0x70,0x6a,0xe0,0x32,0xbf,0xf5,0x43,0xe7,0xff,0xdb,0x85,0x44,0x38,0x3f,0xa3,0xd9,0xda,0xa1,0x50,0xa2,0x00,0xcf,0x6a,0x67,0xc3,0x00,0x28,0x7c,0xf8,0x1a,0xf0,0xf9,0x80,0x12,0x55,0x28,0x94,0x2f,0xc7,0xc7,0x6b,0x0f,0x41,0x84,0x40,0x03,0x80,0xf0,0xf7,0xc3,0x8a,0x00,0x2c,0xd0,0x84,0x75,0x5c,0x2f,0x8e,0x7c,0x3f,0x10,0xd1,0xf1,0xfc,0x20,0x27,0x62,0x00,0x18,0x18,0x74,0xca,0x91,0x1f,0x8f,0xe1,0xba,0xae,0x18,0xfe,0x28,0x44,0xbe,0xba,0xbf,0xd6,0xa3,0x55,0xa2,0x0f,0x8f,0xf0,}; -const uint8_t _A_Levelup2_128x64_4[] = {0x01,0x00,0x90,0x02,0xff,0x80,0x3c,0x01,0xf1,0xff,0xe0,0x3f,0x7d,0xff,0xd1,0x0f,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x2d,0xff,0xee,0x0f,0xef,0x47,0xff,0xfc,0x06,0x2d,0xf8,0x3d,0xe0,0x3e,0x49,0x3f,0xc0,0xfc,0x7f,0x8f,0xfc,0xed,0x02,0x37,0xff,0xc5,0xbe,0x01,0xf0,0xaf,0xe0,0xc1,0xe7,0xe0,0xff,0xc0,0xc2,0xe3,0x1f,0xf8,0x4f,0xe0,0x17,0x0b,0xf5,0x81,0x34,0x40,0xf1,0xb8,0xc1,0x38,0x1f,0xd8,0x3f,0xe2,0x73,0x00,0xf7,0xc7,0xe4,0x02,0xb1,0xff,0xcf,0xf0,0x02,0x81,0xc0,0x77,0xe0,0x37,0xf8,0x47,0x82,0xff,0x0e,0x6e,0x1c,0x1d,0xc4,0x3e,0x08,0x0c,0x0b,0x80,0x2e,0x1f,0x00,0x08,0x60,0x06,0x02,0xc3,0xc0,0x41,0xe4,0x09,0x12,0x70,0xd8,0x23,0xf8,0x08,0x78,0x3c,0x7e,0xf0,0x78,0x1c,0x03,0x81,0x07,0xff,0x40,0xc0,0xa5,0x19,0x10,0x8a,0x00,0xc6,0x05,0xc4,0xd7,0xc7,0xc0,0x82,0x00,0x13,0xf1,0xa4,0xc6,0x9e,0x08,0x3b,0xf8,0x3c,0xcb,0xa4,0x02,0x13,0x90,0xc1,0xa0,0x1a,0xcd,0x56,0xa8,0x84,0x50,0x0f,0x67,0xff,0xe7,0xf1,0xf9,0xfb,0x3f,0x30,0xfa,0x80,0xd8,0xa0,0x71,0x40,0x78,0xff,0x39,0xfe,0x7b,0xff,0x9f,0x89,0xff,0x85,0xc0,0x35,0x7a,0xed,0x58,0x90,0x45,0xe5,0x87,0x1f,0x94,0x02,0x9f,0x08,0xca,0x01,0x8a,0x9f,0x15,0x07,0x8d,0xe3,0x80,0x0f,0x30,0xc8,0xf0,0x35,0x41,0xf1,0x8d,0x14,0x13,0x9f,0xfb,0x07,0x8c,0x02,0x21,0xd0,0x0b,0x15,0x7e,0x2a,0x51,0x1b,0x07,0xfb,0xcd,0xff,0xe1,0x9f,0x8b,0x40,0x5e,0x1d,0x54,0xa8,0x3c,0x53,0xc9,0xce,0x43,0xff,0x01,0x44,0x93,0xc4,0x5a,0xc5,0x55,0xa8,0x40,0x77,0xd1,0xe8,0x07,0xdd,0xa4,0x20,0xf1,0xd8,0x07,0xca,0xd4,0x1f,0x28,0xf3,0x80,0x6f,0xf3,0x05,0x78,0xc1,0x14,0xe7,0x7f,0xaa,0xd5,0x60,0x30,0x48,0x06,0x02,0x3f,0xfe,0xfe,0x90,0x07,0x51,0xaa,0x40,0x0e,0xa8,0xbe,0x66,0x91,0xe3,0x86,0x45,0x3c,0x3f,0x96,0x39,0xd5,0x2a,0xa1,0x04,0xf7,0xfe,0xc4,0xa3,0xe8,0xd5,0x7f,0xf5,0xfb,0xa0,0xfa,0x16,0x87,0xc7,0x6f,0x80,0x55,0x3f,0xa1,0xf3,0x1f,0x8b,0xc9,0x38,0x70,0x30,0x20,0xeb,0x3f,0x5a,0xa0,0x08,0xb8,0x0c,0x1e,0x58,0x10,0x18,0xd0,0x03,0xef,0x54,0x09,0xab,0x9c,0x77,0x5a,0xaf,0x57,0xe8,0x16,0xd1,0xfb,0x85,0xc2,0x00,0x1f,0x50,0x80,0xd5,0x22,0x20,0xf1,0xff,0x7e,0x3f,0x01,0xfb,0xec,0x7f,0xef,0x12,0x00,0x78,0x87,0xce,0x2b,0x04,0x82,0xc5,0x03,0xc4,0x08,0x1f,0x1c,0x07,0xf9,0xbf,0x0f,0x8b,0x60,0x43,0xe9,0x5b,0x4f,0x90,0x7d,0x6a,0x35,0x58,0x28,0x04,0x59,0xe3,0xbe,0xbf,0x83,0xc7,0x59,0xef,0x3f,0x8e,0xbc,0x3e,0xbf,0xf8,0xf8,0x04,0x43,0xeb,0x55,0xa2,0xd0,0x6a,0xb1,0x58,0x07,0xee,0x13,0x97,0x07,0x8e,0xb0,0x7e,0x41,0xf5,0xe0,0x7f,0xe1,0xb1,0xf8,0x7a,0xfd,0xc3,0xe3,0x05,0xb0,0x43,0xf8,0x17,0xf6,0xf8,0xeb,0x35,0x40,0x02,0x0f,0xa4,0xc2,0x09,0xe0,0x8c,0x40,0x2a,0xa1,0xf8,0x09,0x95,0xc8,0x2a,0x41,0xf9,0x00,0x0c,0x40,0x04,0x35,0x14,0xa1,0x00,0x06,0xa7,0x55,0xaa,0x17,0x84,0x00,0x36,0x00,0x19,0x6b,0xbd,0x5a,0xa6,0x08,0xc0,0xc3,0xeb,0xf8,0x98,0x40,0x22,0xa1,0xe3,0xff,0xd5,0xea,0xb6,0x53,0xf9,0x03,0xc6,0xd1,0x00,0xc0,0x6b,0xb5,0x5f,0xb0,0x10,0xc2,0xe0,0x1b,0x00,0xf9,0xfb,0xbf,0x35,0x1f,0x28,0x7d,0x27,0xf5,0x5f,0xe1,0x00,0x4c,0x23,0xfe,0xd5,0xc3,0xb7,0x01,0xc1,0xd5,0x80,0x87,0xd7,0x80,0xd5,0x87,0x8b,0x01,0xff,0xfd,0x87,0x50,0x00,0x95,0x44,0x18,0xf8,0x29,0xfb,0x33,0xd0,0x87,0x07,0xf4,0x81,0x3b,0x50,0xfc,0xe1,0x1f,0x70,0xf4,0x5f,0xea,0xb5,0x03,0x01,0x69,0xc3,0xe6,0x00,0x49,0x52,0x01,0x3d,0xe1,0xf8,0x30,0x8c,0x16,0x82,0xdc,0x1e,0x68,0x71,0x40,0x05,0x1a,0x0f,0xa1,0x84,0x40,0x0f,0x4f,0x2f,0x0a,0xac,0x42,0x03,0xab,0x0e,0xa8,0x18,0x60,0xcc,0x15,0x6e,0xa3,0x85,0x6a,0xb4,0x16,0x09,0x97,0xd7,0x57,0xfa,0x0f,0x28,}; -const uint8_t _A_Levelup2_128x64_5[] = {0x01,0x00,0x9c,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1f,0xff,0xfb,0xcf,0xff,0xf0,0x3f,0xc0,0x18,0x7e,0x1e,0x30,0x83,0xdf,0xef,0xd0,0x0e,0x27,0xf6,0xf7,0xfc,0xe7,0x83,0x9b,0x7f,0xff,0x8f,0xff,0xa4,0x63,0x1c,0xe3,0xea,0xf3,0xd1,0xc0,0x20,0xe7,0xc6,0x84,0x2f,0x5b,0x97,0xfe,0xef,0xca,0xf8,0xf1,0xe0,0x20,0xd6,0xff,0x4c,0x7d,0x9a,0xad,0xd5,0x87,0xe1,0x4f,0xc0,0x7f,0xff,0xc3,0xe4,0xbe,0x40,0x2e,0xd5,0x5b,0xae,0x0f,0xe7,0x0f,0xf0,0x7f,0xfc,0x22,0x04,0x9b,0xc0,0x35,0x7a,0xad,0x56,0x1b,0xff,0x00,0xf8,0x7f,0x78,0xe0,0xf4,0x9f,0xe0,0xaa,0xa0,0x01,0xd6,0xcf,0xe0,0x04,0xe1,0x38,0x98,0xf8,0x67,0xfc,0x70,0xf0,0xea,0xa3,0x50,0xf0,0x79,0x13,0x93,0xa1,0xff,0xa3,0xd5,0xc3,0xe3,0x17,0x80,0x40,0x3f,0x80,0xf5,0x0b,0x0e,0xbf,0x56,0x02,0x19,0x70,0x3c,0x67,0x07,0xf6,0xc7,0xd9,0xee,0xa5,0xf1,0x9a,0xc0,0x20,0x90,0x03,0x00,0xef,0xfd,0xe0,0xf2,0x87,0xec,0x37,0x5a,0xaf,0x55,0xa8,0x3e,0x23,0x12,0xfe,0xf7,0xdb,0xa3,0x9f,0x86,0x74,0x2b,0xb5,0x5e,0xa8,0x08,0x60,0x20,0xf1,0xf8,0x10,0x12,0x11,0xa8,0xd7,0x17,0xc7,0x56,0x0d,0x18,0xe0,0xc0,0x8f,0xa5,0xff,0x89,0xf6,0x0b,0xe5,0xdf,0xaa,0x40,0x6f,0xe0,0xf1,0xfd,0xb7,0x0e,0x07,0xe8,0xd5,0x7f,0xb5,0x7b,0xa8,0x06,0x02,0x1f,0x8c,0xf1,0xb0,0x47,0xc7,0xef,0x07,0x8f,0xd7,0xaf,0x57,0xaf,0xdf,0xea,0xb8,0x58,0x7e,0xff,0xce,0x1d,0x12,0x10,0xfc,0xe0,0x7e,0xcf,0xd6,0xab,0xf5,0xba,0x27,0x0c,0x0d,0xbc,0x26,0xe2,0xbf,0xcb,0xe0,0x15,0x5b,0xed,0x5f,0xef,0x55,0xa0,0x84,0x04,0x1e,0x30,0xf7,0x89,0x41,0x8e,0xc2,0x7f,0x2f,0xd1,0xb8,0xaf,0xf7,0xfb,0xf2,0xcc,0x7e,0x70,0xe8,0x07,0x52,0xab,0x57,0xab,0xd7,0x68,0xb0,0x58,0x00,0x6c,0x6f,0x8b,0x21,0xb1,0xa5,0x88,0x3e,0xc6,0xe4,0x17,0x0d,0x53,0xaa,0x1f,0x51,0x00,0x8f,0x4b,0xff,0x0c,0x0f,0x96,0xfc,0x3e,0x3f,0xf0,0xf9,0x40,0x3f,0xa0,0xf2,0xc4,0xc0,0xe8,0x1f,0x5e,0xef,0xff,0xbf,0x7d,0xa2,0xb0,0x0b,0xf1,0x7f,0x10,0x8f,0x82,0x0f,0x00,0xd7,0x7f,0xf5,0x7f,0xed,0x7c,0x0c,0x3c,0x38,0x0f,0xfc,0xe7,0xfd,0x8d,0xff,0xc7,0xcf,0xe2,0xff,0x2a,0xa8,0x7c,0x68,0x38,0x0e,0xf9,0x88,0x70,0xe3,0x11,0x80,0xeb,0xf7,0xfa,0xbf,0x76,0xbc,0x4c,0x20,0x01,0x83,0x08,0x45,0xc0,0x50,0x76,0xe8,0x80,0x11,0x42,0x58,0x06,0x88,0xff,0xe7,0xd0,0x5d,0x5b,0xf8,0x40,0x02,0x77,0x10,0x01,0x70,0x3e,0x2b,0xf1,0xbc,0x4e,0x2b,0xb7,0x5a,0xbd,0xdd,0x06,0x31,0x5a,0x00,0x7c,0x7c,0x1f,0xcf,0xbf,0xff,0xd3,0x78,0xdd,0x87,0x8b,0xd4,0x1f,0x48,0x04,0xc1,0xc0,0x57,0x81,0xd0,0xa7,0xc6,0xab,0x05,0xa0,0x18,0x44,0x20,0x58,0xcc,0x1c,0x7f,0xe1,0xab,0xf5,0x6b,0x84,0x42,0x1f,0x51,0x09,0x43,0xa8,0x17,0x51,0xe0,0x90,0x86,0x0b,0x50,0xb2,0x90,0x86,0x01,0xf0,0x81,0xda,0x0c,0x82,0x5f,0x1f,0xfe,0xbf,0x54,0xf6,0x1d,0x80,0x74,0x96,0x23,0xd8,0x80,0x85,0xc7,0xab,0x57,0xaf,0xd5,0x66,0xb5,0x4e,0xe5,0x51,0xc2,0x7a,0x88,0x76,0xe0,0x78,0x3a,0xbd,0x77,0xab,0xdc,0x26,0x16,0x09,0xdf,0xab,0x7f,0x52,0xd8,0x97,0xce,0xab,0x7f,0xea,0xd1,0x20,0x14,0x0f,0x84,0xff,0x6e,0x7b,0x11,0xf8,0xfe,0x80,0x83,0xae,0xd5,0x5a,0x87,0xe5,0xe0,0x9f,0xd5,0xdb,0x43,0x5d,0x5e,0x11,0x88,0x40,0xe2,0x3e,0x18,0x07,0x9e,0xff,0xad,0x5e,0x18,0x00,0x83,0xe3,0x2a,0x07,0x0f,0xf3,0x9f,0xff,0xb7,0x85,0xc4,0xb8,0x21,0xf2,0x13,0x8c,0xd6,0xaa,0x4e,0x1e,0x3e,0x73,0x9d,0xba,0x10,0x37,0xaa,0x34,0x5e,0x1e,0xff,0xff,0xf3,0xb0,0x1e,0x88,0x7d,0x7a,0xb4,0xda,0x84,0x01,0x9a,0x3e,0x38,0x02,0x68,0x40,0x0d,0x07,0x1f,0x8d,0xff,0xec,0x0f,0x1a,0xb0,0x7d,0xaa,0xb0,0x33,0x00,0xc7,0x04,0x02,0xb2,0x10,0xf3,0x7e,0x9b,0xa7,0x3b,0xff,0x00,}; -const uint8_t _A_Levelup2_128x64_6[] = {0x01,0x00,0x54,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0x5f,0x78,0x37,0x20,0x3f,0xc0,0x7e,0x4f,0xff,0xde,0x3e,0x38,0xae,0xf9,0xf0,0x1c,0xe0,0x7e,0xf8,0xf3,0x3f,0xfd,0x9f,0xdc,0x1f,0xbe,0x6c,0x03,0x31,0xfd,0x1f,0xdc,0xca,0x01,0x60,0xfd,0x03,0xaa,0xff,0x09,0x80,0x60,0x3e,0x80,0xfa,0xdf,0xc1,0x20,0x10,0x0f,0x48,0x3e,0xab,0xf0,0x20,0x78,0xf4,0x81,0xd3,0xf7,0x07,0xfc,0xbf,0x03,0xff,0x87,0xe9,0x36,0xe0,0xf8,0xf1,0xcb,0xec,0x30,0x09,0x86,0x93,0x7f,0xf7,0x0f,0xc6,0x5e,0x21,0x00,0xa0,0x52,0x23,0xe0,0xe7,0xfe,0x83,0xc6,0x10,0x6f,0x1a,0x46,0xfc,0x5f,0x1f,0xcc,0x59,0xbc,0xb1,0x3b,0xe4,0x6c,0x03,0xc6,0x0e,0x0f,0x1c,0x7e,0xfb,0x07,0xdf,0x59,0xad,0xfe,0xf9,0x4b,0x84,0x7f,0xb0,0x79,0x0f,0x76,0x1c,0x7e,0xff,0x8d,0x2e,0x5e,0x07,0x4e,0x97,0xfd,0x7f,0xc0,0xf6,0xfd,0xfe,0xec,0xb5,0x88,0x17,0x4a,0x60,0x2c,0x4f,0x79,0xbd,0x2a,0xb3,0x88,0x17,0x8a,0xa0,0x0f,0x2f,0x88,0x85,0xaa,0xb3,0x08,0x15,0x8a,0xa1,0xbd,0x03,0x8f,0xc0,0x7a,0x65,0x02,0xea,0xc4,0x20,0x54,0x2a,0xc0,0x20,0x6f,0x9f,0x0f,0x98,0x30,0x7f,0xd8,0x7f,0x1f,0xf8,0x1e,0xb7,0x78,0xf7,0xe3,0xf6,0x20,0x2c,0x3f,0x0f,0xdf,0xd5,0x88,0x83,0xc6,0xb8,0x1f,0x18,0x7f,0xf0,0xc4,0x90,0x7c,0x1d,0x56,0x3f,0x02,0xe1,0x55,0xc7,0xe3,0x07,0x07,0x13,0x50,0xa7,0xf0,0x2d,0x2e,0x63,0xff,0xcf,0x94,0x07,0xc7,0xc7,0xff,0x8f,0x84,0x4a,0xfb,0x7e,0xb1,0x49,0xab,0xf0,0x1e,0xa4,0x9f,0x97,0x3d,0xf0,0x16,0x44,0x04,0x21,0xe1,0xfe,0x5d,0xa8,0xb3,0x08,0x0d,0x92,0x21,0xf5,0x8f,0xfe,0x2f,0x7f,0xcf,0x08,0x3c,0xa0,0x17,0x8c,0x2c,0x7e,0x03,0xc4,0x87,0xfd,0x61,0xff,0xeb,0xef,0xf0,0x64,0x3f,0xf8,0xec,0x02,0xe1,0x05,0x88,0x40,0x68,0x90,0x0f,0xaa,0xac,0xbf,0x9f,0xfd,0xff,0x7e,0x30,0x0f,0x18,0x4c,0x82,0x05,0x22,0xc0,0x7d,0x01,0x83,0xfd,0xf6,0x7f,0xaf,0x7f,0xe9,0xc4,0x1a,0x84,0x0f,0x48,0x27,0xe3,0x85,0x6f,0x09,0x0f,0xff,0xf3,0x10,0x87,0xc1,0x22,0x20,0xf2,0xa0,0x03,0xc6,0x86,0x6e,0x1f,0xbf,0xf7,0xe7,0x00,0x83,0xc6,0x22,0x34,0x08,0x14,0x48,0x1e,0x37,0xef,0x3c,0x0f,0xfc,0x43,0x1f,0x9f,0x02,0x07,0xf0,0x90,0x83,0x04,0x44,0x30,0x49,0xe4,0x06,0x01,0x1c,0xfe,0x04,0x07,0x67,0x03,0xb8,0x48,0x78,0x10,0x48,0xc8,0x3c,0x60,0x16,0x08,0x00,0x08,0x5e,0x43,0x4b,0x87,0x64,0x24,0x38,0x0f,0xec,0x36,0x41,0x0c,0x80,0x64,0x01,0xe3,0x00,0xf0,0x7b,0xf1,0x70,0x1b,0x04,0x47,0x01,0x07,0x87,0xd0,0x26,0x90,0x0c,0x64,0xc2,0x01,0xf0,0x58,0x0c,0x2e,0x1c,0x4f,0x18,0x04,0x06,0x09,0x40,0xe2,0x60,0x30,0x7b,0x88,0x07,0xfb,0xe2,0x0f,0x1f,0x84,0x1c,0x1e,0x30,0x68,0x19,0x48,0x6f,0xf8,0x0c,0x04,0x3f,0xdd,0xff,0xf6,0x45,0xe4,0x10,0x08,0x4c,0x03,0xf1,0x00,0x47,0x8c,0x82,0x81,0xc0,0x85,0xa4,0x07,0x82,0x0f,0x40,0x00,0x83,0xd2,0x23,0xd8,0xfc,0x61,0xe5,0xe0,0xf1,0x85,0x03,0xd4,0x10,0x26,0xe1,0xbc,0x47,0xe4,0xe0,0xf6,0x81,0x03,0xcb,0xe1,0x71,0xfc,0x4f,0xe8,0x71,0x00,0x7b,0x50,0x01,0x03,0xe0,0x81,0x83,0xc7,0x0f,0x08,0x07,0xb6,0x03,0x90,0x05,0x18,0x77,0x3e,0x5f,0x03,0x83,0x83,0xda,0x01,0xf7,0xe1,0xc3,0xff,0x11,0xbb,0xe4,0x16,0x0c,0x0f,0x7f,0xdf,0x9e,0x3f,0x70,0xbd,0xff,0x0f,0x64,0x0f,0x5f,0xc5,0xc2,0x79,0x3c,0x57,0x0f,0xfc,}; -const uint8_t _A_Levelup2_128x64_7[] = {0x01,0x00,0xf7,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x05,0xfd,0x83,0xfb,0xbe,0x20,0xf0,0xff,0x83,0x72,0x01,0xfe,0x07,0xdf,0xf6,0x3f,0xff,0xf8,0x83,0xf3,0xcf,0xf8,0xe7,0xc0,0xff,0xc0,0xf9,0xfc,0x46,0x60,0xd3,0x00,0xfe,0x41,0xa0,0x3c,0x0e,0xf0,0x3e,0xaf,0xb8,0x18,0x06,0x03,0xba,0x0f,0xad,0xfd,0x06,0x01,0x00,0xed,0x9e,0xee,0x80,0x0f,0x1f,0xa8,0x3e,0xb5,0xf2,0x00,0x78,0xfa,0x81,0xfb,0xf8,0xf5,0xb6,0xab,0x2e,0x0f,0x18,0x3f,0x5b,0x7e,0x10,0x9c,0xbf,0xfb,0x01,0x00,0xec,0x07,0xeb,0x17,0x01,0xa0,0xc0,0x76,0x01,0xf9,0x07,0x8d,0xf2,0x45,0x02,0x07,0xdd,0x2f,0x05,0x14,0x82,0x68,0x01,0xf3,0xe0,0xa2,0xe0,0xe1,0xb0,0x4b,0x03,0x8c,0x43,0xf1,0x25,0xa1,0xc2,0x61,0x16,0x08,0x5f,0xe8,0x1f,0x1a,0x59,0xe4,0x2b,0x11,0x6f,0x0f,0xcf,0xff,0x4b,0x24,0x85,0x5a,0x2e,0x04,0xfa,0xd1,0x03,0xc6,0x31,0xa0,0xdf,0x07,0xe7,0x44,0x2f,0x18,0x67,0x03,0x7d,0xfe,0x07,0xc5,0x0a,0x87,0x0a,0x89,0x60,0x01,0xc3,0xfd,0x06,0xac,0xff,0xff,0x46,0xc1,0xf3,0x64,0xf9,0xc1,0x7c,0x5f,0xfd,0xd8,0x6f,0x14,0xfe,0x51,0xa3,0xef,0x0f,0xe7,0x15,0x1c,0x80,0x7a,0x38,0x03,0xe9,0xff,0xc2,0xa1,0x70,0x09,0x47,0x03,0xfb,0xf7,0x07,0xc4,0x4a,0x09,0x00,0x8c,0x50,0x09,0xa3,0xef,0x1f,0x28,0x1c,0x41,0xe5,0x08,0x07,0x97,0x8c,0x3f,0x30,0x18,0x34,0x80,0x1e,0x3f,0xbf,0x38,0x3d,0xe0,0x18,0x68,0x08,0x3c,0x84,0x0b,0xf8,0x18,0x89,0x38,0x6f,0x10,0x08,0x80,0x3c,0xbe,0x20,0xf3,0xf8,0x4f,0xf7,0xf0,0x68,0x00,0x00,0x61,0x00,0xf1,0xbf,0xa8,0x13,0xc1,0x3f,0xce,0x40,0x81,0xe5,0x04,0x06,0x21,0x04,0x81,0xe3,0xbc,0x2f,0x08,0x00,0x60,0x5f,0x99,0xfa,0x44,0xbc,0x00,0x21,0xe0,0xff,0x37,0xf1,0x80,0x79,0x40,0x76,0xf1,0xf0,0x78,0xef,0xca,0x25,0x07,0xf8,0x6f,0xec,0x00,0xf2,0x80,0x7a,0x78,0xff,0xff,0xbc,0x3c,0x44,0x51,0xfe,0x46,0xff,0x81,0x01,0x07,0x98,0xf8,0xae,0x3c,0x05,0x01,0xef,0xe8,0x05,0x03,0x07,0x8f,0x3c,0x16,0x38,0x12,0xa1,0xef,0x81,0xed,0xb7,0x1e,0x11,0x88,0xc3,0xeb,0xed,0xff,0xd2,0xc1,0x83,0x0f,0xff,0xfc,0xf3,0x7f,0xfa,0x7c,0x84,0x7e,0x60,0xf1,0xa2,0x03,0xc7,0x1e,0xa3,0x1b,0x2f,0xfa,0x66,0x0f,0x4c,0xac,0x7e,0x87,0xd0,0x1e,0x9e,0x16,0x03,0x0c,0xd0,0x9b,0xce,0xc7,0xe0,0xa0,0x78,0x3c,0x3f,0xb0,0x78,0xc1,0x7f,0xd0,0x3c,0x88,0x3c,0xf0,0x71,0xf9,0x04,0x00,0xdc,0x70,0x58,0x44,0x02,0xa2,0x0f,0x38,0x1c,0x22,0x41,0xf0,0x81,0xff,0x92,0x03,0x0b,0x07,0x8d,0x28,0x1e,0x70,0x18,0x44,0x43,0xe0,0xb2,0x1c,0xff,0xfe,0x10,0x0f,0x19,0x50,0x3d,0x22,0x11,0x08,0xc5,0xfb,0x3c,0x70,0x18,0xbb,0x74,0x64,0xc0,0xf5,0xb4,0x4c,0x3f,0x18,0xf4,0x80,0x83,0xca,0x2c,0x0f,0x49,0x07,0xd3,0xc1,0x01,0xc0,0x13,0xc6,0x5e,0x9c,0x10,0x7a,0xd0,0x3f,0x5e,0x18,0x39,0x80,0x80,}; -const uint8_t _A_Levelup2_128x64_8[] = {0x01,0x00,0x02,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x00,0xbf,0xb0,0x7f,0x88,0x3c,0x3f,0xe1,0x0f,0x00,0x5c,0x3f,0xc0,0x1f,0xdf,0x8c,0x7c,0x1f,0x97,0xf8,0x77,0xf3,0xf8,0x21,0x10,0x04,0xe7,0xe0,0x30,0x2f,0x98,0x7e,0xed,0xf0,0x18,0x0f,0xb0,0x1e,0x7c,0xf8,0x4c,0xcb,0xe6,0x0f,0x38,0xb8,0x3c,0x7a,0x00,0x73,0xc7,0xf2,0x66,0x60,0xf4,0x85,0xe0,0x60,0x1a,0x00,0xf9,0x83,0xde,0x0b,0x82,0x80,0x50,0x00,0xe7,0x4f,0x84,0xc9,0xbf,0x20,0x62,0xff,0x40,0xa8,0x50,0x0f,0xc7,0xfb,0xde,0x0f,0x2e,0x4c,0x9c,0x1e,0xf0,0x6f,0xe8,0x3c,0xb9,0xfc,0x88,0x3f,0xe0,0xfc,0x70,0x1f,0xf4,0x02,0x03,0xfd,0xe3,0x83,0xcf,0x9f,0xfc,0x07,0x95,0xf8,0xbc,0x25,0x01,0xfd,0x07,0xce,0x13,0xce,0x07,0x95,0xff,0xf9,0x80,0xbe,0x0c,0x04,0x1e,0x60,0x06,0xdf,0x50,0x30,0x52,0x48,0x04,0x11,0x3d,0x3b,0xe9,0x06,0x0e,0x53,0x00,0x60,0x88,0x3e,0x2b,0xfa,0x0a,0x14,0x68,0xc0,0x29,0x01,0xe7,0xe0,0xf3,0x92,0x0a,0x7f,0xc8,0x1e,0x35,0xed,0x04,0xf0,0x1e,0x30,0x1f,0xa0,0x3c,0x7e,0x79,0xc9,0xe0,0x3c,0xc3,0xe3,0x24,0x85,0x70,0x20,0x1e,0x80,0x79,0x72,0x41,0xf1,0x30,0x80,0x83,0xcb,0x07,0xc9,0x17,0xa7,0x7c,0x5e,0x30,0xaf,0xc6,0x0b,0xd6,0x1f,0x4b,0x7b,0x5c,0x81,0xe3,0xc2,0x85,0x43,0xac,0xbe,0xc0,0x79,0x78,0xc1,0xeb,0x20,0x81,0xe2,0xe0,0x31,0xa1,0xf9,0x83,0xc4,0xde,0x94,0x1f,0x15,0xed,0x1e,0x20,0xf1,0x87,0xe0,0xbe,0xf2,0x0a,0x41,0x3c,0xf0,0x31,0xc8,0x64,0x02,0x04,0x6f,0x14,0x7c,0x40,0xa0,0xb0,0x83,0xf9,0x83,0xe2,0x09,0x02,0x80,0x1f,0xc7,0xf4,0x0f,0x98,0x40,0x3c,0x66,0x00,0xfb,0x88,0x60,0x20,0x04,0x01,0xfe,0x83,0xe6,0x41,0x00,0xc1,0xc0,0xf0,0x1f,0xe0,0x7d,0xdf,0x20,0x14,0x00,0x41,0x43,0xe0,0x10,0x0c,0x00,0x18,0xad,0xe0,0xf1,0x00,0x0e,0x80,0x10,0x5f,0x30,0x10,0xdf,0xc0,0xc5,0x97,0x8c,0x03,0xcb,0xa0,0x08,0x28,0x68,0x7c,0x86,0xc5,0x17,0x83,0x83,0xcb,0x30,0x0f,0x28,0x30,0x1c,0x8a,0xc5,0x17,0x37,0x08,0x00,0x6e,0x80,0xfa,0x82,0x01,0xcb,0x20,0x28,0x28,0x36,0x73,0x10,0x0f,0x45,0x68,0x83,0xdb,0x45,0x84,0x80,0x83,0xc7,0x7f,0x17,0x4e,0x09,0x7c,0x81,0xe9,0x82,0x81,0x87,0xcd,0x78,0x20,0xf7,0xc0,0xc1,0xc1,0xe7,0x40,0x80,0x83,0xcb,0xbd,0xbf,0x0f,0xc5,0x00,0xc0,0x41,0xf2,0xff,0x0f,0xd7,0xff,0x1b,0x07,0xb7,0xf0,0xbe,0xbd,0xf9,0x28,0x3c,0xfc,0x01,0x82,0x3f,0xa7,0xdf,0xe3,0x22,0x07,0x9f,0x03,0xf4,0x10,0x14,0x7a,0xde,0x24,0x20,0xf4,0xfa,0x07,0xc6,0x1c,0xbf,0x4c,0xfc,0x82,0x40,0x5f,0x2e,0x07,0x20,0x1e,0x23,0x22,0x6f,0x95,0x9c,0x1e,0xb3,0x0f,0xff,0xe3,0xf6,0x0c,0x13,0xa0,0xff,0xe3,0x20,0xf5,0x4a,0x0f,0xdd,0xce,0x5c,0x0f,0xfc,0x06,0x0d,0x40,0xc8,0x11,0xca,0x81,0x00,0xff,0xfa,0x1c,0x44,0x00,0x1f,0xf4,0x24,0x1e,0xd0,0x4f,0x47,0xf7,0xbe,0x0f,0x28,0x0c,0x22,0x81,0x50,0x07,0xa4,0x0b,0xd1,0xe3,0x0f,0x98,}; -const uint8_t _A_Levelup2_128x64_9[] = {0x01,0x00,0xfb,0x01,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x01,0x3d,0xe0,0xff,0x06,0xe4,0x07,0xe0,0x0f,0xab,0xff,0xfe,0x7f,0xfe,0xe7,0xe0,0xc3,0xd7,0xdf,0x80,0xce,0x03,0xf9,0x67,0x80,0x71,0xbd,0xc0,0xfb,0xad,0xc0,0x20,0x3e,0xd0,0x49,0xf3,0xe1,0x33,0x2f,0x98,0x3c,0xe8,0xb8,0x08,0x07,0xe8,0x1e,0x78,0xfe,0x4c,0xcc,0x1e,0x98,0x2a,0x04,0x03,0x88,0x71,0x30,0x7a,0xcb,0xef,0x58,0x10,0x78,0xee,0x01,0xe7,0x4f,0x84,0xc9,0xbf,0x21,0xf2,0xdf,0xe0,0x24,0x10,0x0a,0x30,0x3d,0x39,0x32,0x70,0x7a,0x40,0x24,0x30,0x0c,0x0f,0xfb,0x8e,0x4f,0x2e,0x44,0x1f,0xf0,0x0f,0x2a,0xfc,0x02,0x7f,0x80,0xc0,0x7f,0xa0,0x20,0xf3,0xe7,0xff,0x0a,0xc5,0x5f,0xe0,0x00,0x06,0x01,0xfd,0x0f,0x9c,0x27,0x9c,0x0f,0x2b,0xfc,0xbe,0x41,0x1e,0x90,0xc0,0x7f,0xaa,0x19,0x97,0xe4,0x2c,0x31,0x28,0x17,0x08,0x1f,0x5d,0x0e,0x04,0x3a,0x05,0x3a,0x07,0xcc,0x5e,0x91,0xa1,0x86,0x41,0x38,0xdf,0xe1,0xf0,0xe0,0xf3,0x92,0x0a,0x7f,0xc8,0x1e,0x52,0x88,0xf4,0x17,0x08,0x40,0x10,0x78,0xfc,0xf3,0x93,0xc0,0x7a,0xc4,0xa0,0xb4,0x86,0x09,0x03,0xc7,0x92,0x0f,0x8f,0xc0,0x3c,0xf0,0x7c,0x91,0x7c,0x43,0x38,0x3f,0xb0,0xfa,0x5b,0xc0,0xc3,0xff,0x9d,0x93,0xc6,0x09,0x7f,0xf9,0x03,0xcf,0xc6,0x0f,0x4a,0x5f,0x43,0xe1,0xc2,0xc0,0x7f,0x2f,0xa0,0xf4,0x37,0x9e,0x2f,0x21,0x0d,0x9f,0xc0,0x3f,0xf3,0xef,0xf4,0x3f,0x05,0xf7,0x90,0x52,0x07,0xe5,0x0b,0x90,0xc0,0xa0,0x90,0x0b,0xfd,0xfd,0x1f,0x10,0xbe,0x14,0x06,0x01,0x80,0xdf,0x83,0xa0,0x1e,0x30,0x40,0x78,0xf8,0x3b,0xe0,0xe8,0xfb,0xc2,0xe1,0x00,0xf1,0xfc,0x2f,0xa4,0x1e,0x54,0x08,0x07,0x3a,0x06,0xbf,0x10,0x03,0x78,0xc1,0xe3,0x80,0xe0,0xc0,0xff,0xeb,0xf1,0x0f,0xbc,0x34,0xba,0x3f,0xe8,0x0f,0xc1,0x10,0x50,0xf8,0x01,0x5c,0x41,0xe5,0x12,0x81,0x01,0xc4,0xf8,0x2b,0xf1,0xff,0xfc,0xc0,0x42,0x75,0x39,0x11,0x38,0x40,0x04,0x0f,0x28,0x68,0x7c,0x88,0xc5,0xc2,0x07,0x1c,0x00,0x5e,0x50,0x60,0x31,0x11,0x8a,0x05,0x03,0x03,0x97,0x03,0xf8,0x0f,0x98,0x60,0x1c,0xa6,0x03,0x82,0x83,0x67,0x31,0x00,0xf4,0x98,0x03,0xcb,0x9c,0x0f,0x3d,0x16,0x12,0x02,0x0f,0x3e,0x00,0xb8,0x87,0xc4,0x0f,0x2c,0x14,0x0c,0x1e,0x70,0x02,0x00,0xff,0x01,0xeb,0x81,0x83,0x83,0xd2,0x1c,0xbf,0x10,0xfe,0x44,0x9b,0xe3,0xf5,0x1f,0xd0,0x3c,0xa0,0x1f,0x42,0xfc,0xce,0xa0,0x10,0x90,0x78,0xfb,0x01,0xe6,0x7f,0x5a,0x30,0x3f,0x6f,0xf8,0x18,0x04,0x14,0x0e,0x3d,0x80,0x79,0x15,0x85,0x7e,0x77,0xf8,0x0e,0x05,0xe0,0x20,0xf4,0x15,0x93,0x7c,0xb7,0xf0,0x0c,0x13,0xc0,0xb5,0x00,0xf2,0x39,0x96,0xfc,0x1e,0x74,0x40,0x7b,0x41,0xd4,0xe4,0x05,0x1a,0xf8,0x3c,0x60,0x20,0x81,0xa4,0x03,0xc8,0x00,0xb2,0xf8,0x04,0xa0,0x1e,0x58,0x82,0x40,0x80,0x1a,0x2e,0x2b,0x13,0x39,0x42,0x09,0x84,0x00,0x40,}; -const uint8_t _A_Levelup2_128x64_10[] = {0x01,0x00,0x06,0x02,0xff,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x78,0x03,0xc0,0x09,0xef,0x06,0xe4,0x07,0xe0,0x0f,0xc9,0xff,0xfb,0x9f,0xc7,0x07,0xdf,0x7e,0x03,0x38,0x0f,0xe5,0x9e,0x01,0xc6,0xf7,0x03,0xee,0xb7,0x00,0x80,0xff,0x4a,0x27,0xcf,0x84,0xcc,0xbe,0x60,0x51,0xbf,0xff,0xe8,0xb8,0x08,0x07,0xe8,0x2e,0x78,0xfe,0x4c,0xcc,0x1e,0x98,0x2a,0x04,0x03,0x88,0x1f,0x30,0x7a,0xcf,0xef,0xd8,0x10,0x78,0xee,0x01,0xe7,0x4f,0x84,0xc9,0xbf,0x21,0xf2,0xdf,0xe0,0x24,0x10,0x0a,0x37,0xfc,0xe2,0x54,0xfe,0x4c,0x9c,0x1e,0x90,0x09,0x0c,0x03,0x03,0xfe,0xd5,0x93,0xcb,0x91,0x07,0xfc,0x11,0x8a,0xbf,0x00,0x9f,0xe0,0x30,0x17,0xe8,0x89,0x88,0x41,0xe3,0xcf,0xfe,0x03,0xcf,0x80,0x00,0x18,0x07,0xf4,0x3e,0x70,0x9e,0x70,0x3c,0xe5,0xf2,0x08,0xf4,0x85,0x00,0x2b,0x19,0x97,0xe4,0x2c,0x31,0x28,0x17,0x09,0x63,0x1f,0xe9,0x7f,0x43,0x81,0x0e,0x81,0x4e,0x95,0xd3,0x17,0xa4,0x68,0x61,0x90,0x46,0x09,0x73,0xf0,0x79,0xc9,0x05,0x3f,0xe4,0x1f,0x18,0xbc,0xa2,0x3d,0x05,0xc2,0x30,0x4b,0x9f,0xf3,0xce,0x4f,0x01,0xeb,0x12,0x82,0xd2,0x18,0x24,0x0f,0x1e,0x48,0x3e,0x3f,0x00,0xf3,0xc1,0xf2,0x45,0xe5,0x5f,0xfa,0x0b,0xce,0x19,0xc1,0xfd,0x87,0xd2,0xde,0x06,0x1f,0xf4,0xec,0x9e,0x30,0x4b,0xff,0xc8,0x1e,0x7e,0x30,0x7a,0x52,0xfa,0x1f,0x0e,0x16,0x03,0xf8,0x4f,0x30,0x78,0x9b,0xcf,0x17,0x90,0x86,0xcf,0xe0,0x01,0x61,0xff,0xc3,0xf0,0x5f,0x79,0x05,0x20,0x9e,0x50,0xb9,0x0c,0x0a,0x09,0x00,0xbf,0xa3,0xe6,0x17,0xc2,0x80,0xc0,0x30,0x1b,0xf0,0x7d,0x41,0x01,0xe3,0xe0,0xef,0x83,0xea,0x10,0x0f,0x1f,0xc3,0x3a,0x01,0xe7,0x40,0x80,0x73,0xa0,0x64,0xf1,0x00,0x37,0xdc,0x1e,0x38,0x0e,0x0c,0x0f,0xfe,0x6f,0x10,0x03,0xc3,0x4b,0xa3,0xfe,0x80,0xfc,0x11,0x02,0x70,0x18,0x01,0x5c,0x41,0xe5,0x12,0x81,0x01,0xc7,0xfd,0x0f,0x5f,0x8f,0xff,0xe6,0x02,0x13,0xb1,0xc8,0x89,0xc2,0x00,0x20,0x79,0x43,0x43,0xe4,0x46,0x2e,0x10,0x38,0xe0,0x02,0xf2,0x83,0x01,0x88,0x8c,0x50,0x28,0x18,0x1c,0xb8,0x1f,0xc0,0x7c,0xc3,0x00,0xe5,0x30,0x1c,0x94,0x1b,0x39,0x88,0x07,0xa4,0xc0,0x1e,0x5c,0xe0,0x79,0xe8,0xb0,0x90,0x10,0x79,0xf0,0x05,0xc5,0xfb,0x9f,0x92,0x44,0x1e,0x38,0x28,0x18,0x3c,0xe0,0x04,0x01,0xfe,0x7e,0xc3,0xe9,0x81,0x83,0x83,0xd2,0x1c,0xbf,0x10,0x7a,0x87,0xda,0x24,0xdf,0x1f,0xaa,0x20,0x87,0xee,0x0f,0x28,0x07,0xd0,0x1e,0x65,0xf5,0x9d,0x40,0x21,0x20,0xf1,0xf6,0x03,0xcc,0xfe,0xb4,0x60,0x7e,0xdf,0xf0,0x30,0x08,0x28,0x1c,0x7b,0x00,0xf2,0x2b,0x0a,0xfc,0xef,0xf0,0x1c,0x0b,0xc0,0x41,0xe8,0x2b,0x23,0x29,0x6f,0xe0,0x18,0x27,0x81,0x6a,0x01,0xe4,0xd2,0x2d,0xf8,0x3c,0xe8,0x80,0xf6,0x83,0xa9,0xc8,0x0a,0x35,0xf0,0x78,0xc0,0x41,0x03,0x48,0x07,0x90,0x01,0x65,0xf0,0x09,0x40,0x3c,0xb1,0x04,0x81,0x00,0x34,0x5c,0x56,0x26,0x72,0x84,0x13,0x08,0x00,0x80,}; -const uint8_t* const _A_Levelup2_128x64[] = {_A_Levelup2_128x64_0,_A_Levelup2_128x64_1,_A_Levelup2_128x64_2,_A_Levelup2_128x64_3,_A_Levelup2_128x64_4,_A_Levelup2_128x64_5,_A_Levelup2_128x64_6,_A_Levelup2_128x64_7,_A_Levelup2_128x64_8,_A_Levelup2_128x64_9,_A_Levelup2_128x64_10}; - -const uint8_t _I_125_10px_0[] = {0x00,0xE0,0x00,0x00,0x01,0x0E,0x02,0x31,0x02,0x45,0x02,0x91,0x00,0xAA,0x00,0x92,0x00,0x44,0x00,0x38,0x00,}; -const uint8_t* const _I_125_10px[] = {_I_125_10px_0}; - -const uint8_t _I_Nfc_10px_0[] = {0x00,0x80,0x00,0x00,0x01,0x22,0x02,0x43,0x02,0x45,0x02,0x49,0x02,0x31,0x02,0x22,0x02,0x00,0x01,0x80,0x00,}; -const uint8_t* const _I_Nfc_10px[] = {_I_Nfc_10px_0}; - -const uint8_t _I_back_10px_0[] = {0x00,0x00,0x00,0x10,0x00,0x38,0x00,0x7C,0x00,0xFE,0x00,0x38,0x00,0x38,0x00,0xF8,0x01,0xF8,0x01,0x00,0x00,}; -const uint8_t* const _I_back_10px[] = {_I_back_10px_0}; - -const uint8_t _I_badusb_10px_0[] = {0x01,0x00,0x11,0x00,0x00,0x0f,0xe2,0x01,0xfc,0x80,0xdd,0x20,0x32,0x48,0x08,0x14,0x40,0x23,0xa8,0x08,0xa0,}; -const uint8_t* const _I_badusb_10px[] = {_I_badusb_10px_0}; - -const uint8_t _I_ble_10px_0[] = {0x00,0x04,0x00,0x8C,0x00,0x15,0x01,0x56,0x02,0x8C,0x02,0x8C,0x02,0x56,0x02,0x15,0x01,0x8C,0x00,0x04,0x00,}; -const uint8_t* const _I_ble_10px[] = {_I_ble_10px_0}; - -const uint8_t _I_dir_10px_0[] = {0x01,0x00,0x11,0x00,0x00,0x0c,0xfe,0x01,0x41,0x80,0x7f,0xe0,0x70,0x18,0x10,0x05,0x7f,0xd0,0x10,0x88,0x80,}; -const uint8_t* const _I_dir_10px[] = {_I_dir_10px_0}; - -const uint8_t _I_ibutt_10px_0[] = {0x00,0x80,0x03,0x40,0x02,0x20,0x02,0x10,0x01,0x8E,0x00,0x41,0x00,0x2D,0x00,0x2D,0x00,0x21,0x00,0x1E,0x00,}; -const uint8_t* const _I_ibutt_10px[] = {_I_ibutt_10px_0}; - -const uint8_t _I_ir_10px_0[] = {0x00,0xFC,0x00,0x02,0x01,0x79,0x02,0x84,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x58,0x00,0x78,0x00,0xFF,0x03,}; -const uint8_t* const _I_ir_10px[] = {_I_ir_10px_0}; - -const uint8_t _I_loading_10px_0[] = {0x00,0xFE,0x00,0x82,0x00,0xBA,0x00,0x54,0x00,0x28,0x00,0x28,0x00,0x44,0x00,0x92,0x00,0xBA,0x00,0xFE,0x00,}; -const uint8_t* const _I_loading_10px[] = {_I_loading_10px_0}; - -const uint8_t _I_music_10px_0[] = {0x01,0x00,0x10,0x00,0xf0,0x00,0x46,0x03,0x20,0x80,0x00,0x4e,0x7d,0x00,0x9f,0x80,0x4a,0x3c,0x13,0x20,}; -const uint8_t* const _I_music_10px[] = {_I_music_10px_0}; - -const uint8_t _I_sub1_10px_0[] = {0x01,0x00,0x12,0x00,0x81,0x40,0x69,0x30,0x2c,0x2c,0x0b,0x6a,0x01,0x28,0x0c,0x0a,0x65,0x01,0x98,0x40,0x00,0x26,}; -const uint8_t* const _I_sub1_10px[] = {_I_sub1_10px_0}; - -const uint8_t _I_u2f_10px_0[] = {0x00,0x00,0x00,0xFE,0x01,0x01,0x02,0x0C,0x00,0xF2,0x03,0x92,0x02,0x0C,0x00,0x01,0x02,0xFE,0x01,0x00,0x00,}; -const uint8_t* const _I_u2f_10px[] = {_I_u2f_10px_0}; - -const uint8_t _I_unknown_10px_0[] = {0x01,0x00,0x12,0x00,0xbc,0x40,0x39,0x90,0x0c,0x24,0x03,0x81,0x00,0xb0,0x40,0x26,0x00,0x12,0x00,0x08,0x14,0xc0,}; -const uint8_t* const _I_unknown_10px[] = {_I_unknown_10px_0}; - -const uint8_t _I_update_10px_0[] = {0x00,0xFE,0x01,0x01,0x02,0xFF,0x03,0x01,0x02,0x31,0x02,0x79,0x02,0xFD,0x02,0x31,0x02,0x31,0x02,0xFF,0x03,}; -const uint8_t* const _I_update_10px[] = {_I_update_10px_0}; - -const uint8_t _I_BLE_Pairing_128x64_0[] = {0x01,0x00,0xb7,0x01,0x00,0x6c,0x38,0x1f,0xd0,0x10,0x76,0xe0,0x03,0xdd,0x40,0x07,0xf4,0x82,0x01,0x08,0x07,0xf4,0xc0,0x1f,0x91,0x08,0x07,0x00,0x1f,0xc0,0x0d,0x1e,0xe8,0x3f,0xc0,0x03,0x58,0x80,0xcf,0x11,0xd9,0xaf,0x85,0x77,0x01,0xf7,0x60,0xf8,0x45,0xff,0x05,0xed,0x9e,0x7c,0x09,0xdb,0xe0,0x2f,0x78,0x03,0x3c,0x8e,0xee,0x8a,0x43,0x81,0xfb,0x0c,0x66,0xe8,0xfc,0x59,0xba,0x6f,0x28,0x1b,0xfb,0xa3,0x80,0xfc,0xa0,0x1f,0xc6,0x86,0xbf,0xc3,0x78,0xce,0x04,0x19,0x26,0x77,0xfa,0x43,0xbe,0x12,0xa0,0x7e,0xf8,0x2a,0xa2,0x02,0xff,0x89,0x27,0x01,0xbf,0x99,0x38,0x8a,0xfc,0x0f,0x8e,0x07,0xfe,0x0e,0x94,0x2c,0x07,0xfc,0x7f,0x1f,0xf5,0x00,0xc3,0x00,0xe4,0x31,0x13,0xd1,0x00,0x0a,0xb8,0x19,0x25,0x91,0xc0,0x81,0xe2,0xb9,0x4d,0x5d,0x78,0x64,0x2e,0x84,0x80,0x61,0x07,0x02,0x3e,0x2a,0xa4,0xa2,0x00,0xf2,0x40,0x20,0xe3,0x21,0xa0,0x62,0x9f,0x60,0x05,0x02,0x3e,0x36,0x41,0x66,0x23,0x20,0x51,0xfc,0x40,0x68,0x0f,0x15,0x90,0x60,0x20,0x1b,0x09,0x89,0x70,0x46,0x42,0x07,0x14,0x99,0x41,0xe8,0x1f,0x18,0x0c,0x07,0xc1,0x19,0xff,0xc3,0xce,0x6b,0x54,0x8f,0xe0,0x3f,0x90,0x78,0x17,0x02,0x1a,0x70,0x39,0x01,0xa0,0xb1,0x53,0xb5,0x88,0xc7,0xe0,0x98,0x08,0x3a,0xd5,0xe8,0x97,0xd0,0x78,0xcf,0xe1,0x07,0xf1,0x0d,0x08,0x00,0x74,0x10,0x80,0x18,0xe8,0x97,0xc3,0xf2,0xff,0xc4,0x03,0xe3,0x04,0x8c,0x19,0xcc,0x00,0x35,0x0c,0x3c,0x03,0xf9,0x3f,0xb0,0x8f,0xc6,0x31,0x0e,0x0f,0x90,0x90,0xb5,0x45,0xc1,0xf8,0x4f,0xf0,0xde,0x18,0xcc,0x82,0x08,0x1f,0x22,0x20,0xd0,0x3a,0xab,0xd1,0xe0,0x5f,0xa1,0x1b,0x19,0x8d,0x02,0x04,0x9a,0x1d,0x04,0x28,0x26,0x36,0xa8,0x05,0xf0,0xe0,0x3f,0x04,0xf8,0xd0,0x30,0x55,0xfa,0xad,0x54,0x3e,0x35,0x09,0xab,0xac,0xbf,0x2b,0xf2,0x0a,0x0e,0xfb,0x55,0xaa,0x0f,0x94,0x68,0x04,0x30,0x6f,0xd3,0x7c,0xb0,0x15,0x0f,0xfd,0x7f,0xeb,0x05,0x4f,0x0b,0x60,0xa3,0x1f,0x28,0x0b,0xfc,0xbc,0x30,0x1f,0xf7,0xfe,0x54,0x2c,0x18,0x30,0x3c,0x6f,0x00,0xf2,0x1c,0x8c,0xf8,0x10,0x3c,0x00,0xf8,0xd5,0x5c,0x05,0xb8,0xb0,0xaa,0xdb,0x01,0x2b,0x31,0x0a,0xdc,0xa7,0x00,0xe6,0x00,0x0c,0x56,0x00,0x7e,0x10,0x00,0xcc,0x01,0xf0,0x1f,0x1b,0x40,0x2e,0x00,0x07,0x16,0x10,0x90,0x02,0xe5,0x90,0x06,0x29,0x00,0x2a,0xa9,0x00,0x2f,0x10,0x02,0xa5,0x10,0x02,0xf1,0x00,0x2a,0xa0,0x0d,0xc0,0x00,0xec,0x01,0xfd,0x60,0x17,0x6a,0xc0,0x60,0x40,0xfd,0xc0,0x30,0x04,0x01,0xb0,0xb0,0x7f,0x45,0x80,}; -const uint8_t* const _I_BLE_Pairing_128x64[] = {_I_BLE_Pairing_128x64_0}; - -const uint8_t _I_Ble_connected_38x34_0[] = {0x01,0x00,0x60,0x00,0x80,0x7f,0xc0,0x65,0xc0,0xff,0xc0,0xc0,0x83,0xf0,0xff,0xc3,0xc0,0x83,0xf8,0xff,0xc7,0xc0,0x83,0xfc,0xff,0xcf,0xc0,0x8d,0xfe,0xf9,0xdf,0xe0,0x10,0x30,0x21,0xc1,0xff,0xfc,0x31,0x40,0xc3,0x80,0x87,0x0c,0xff,0xcc,0xc0,0x83,0x1c,0x02,0x1c,0x62,0x7f,0xf3,0xfe,0x4c,0x27,0x00,0x42,0xb8,0x4e,0x3f,0xf3,0x0f,0xff,0x80,0x04,0x20,0x11,0xe0,0x00,0x84,0x44,0x20,0x47,0x07,0x20,0x60,0xc4,0x48,0x2c,0x41,0xb2,0x10,0x14,0x94,0x85,0x43,0x2f,0x21,0xa1,0x0e,0xf2,0x86,0x44,0x82,0x26,0x91,0x48,0x80,}; -const uint8_t* const _I_Ble_connected_38x34[] = {_I_Ble_connected_38x34_0}; - -const uint8_t _I_Ble_disconnected_24x34_0[] = {0x01,0x00,0x3c,0x00,0x80,0x7f,0xe0,0x1c,0x08,0x04,0x0e,0x61,0x00,0x86,0x42,0x20,0x11,0x08,0x24,0x02,0x40,0x02,0x28,0x14,0x32,0x80,0x02,0x28,0x0c,0xf3,0x00,0x02,0x3e,0x60,0x08,0xf8,0x30,0xcc,0x18,0x08,0xa0,0x3c,0xf0,0x58,0x80,0x88,0x2e,0xa0,0xb4,0x0b,0xb0,0x8d,0x02,0xea,0x3b,0x52,0x3a,0x94,0x08,0xac,0x45,0xc2,0x31,0x10,}; -const uint8_t* const _I_Ble_disconnected_24x34[] = {_I_Ble_disconnected_24x34_0}; - -const uint8_t _I_Button_18x18_0[] = {0x01,0x00,0x19,0x00,0xfc,0x7f,0xe0,0x10,0x68,0x04,0x06,0x07,0x00,0x81,0x00,0xbc,0x05,0xe0,0x23,0x83,0xc0,0x20,0x7f,0xef,0xfc,0x07,0xf8,0x32,0x10,}; -const uint8_t* const _I_Button_18x18[] = {_I_Button_18x18_0}; - -const uint8_t _I_Circles_47x47_0[] = {0x01,0x00,0x7e,0x00,0x00,0x0f,0xe2,0x3e,0x04,0x2c,0x04,0x1f,0xc0,0x05,0x2b,0x00,0x08,0x60,0x60,0x21,0x8c,0x00,0x86,0x18,0x02,0x18,0x20,0x08,0x62,0x00,0xe4,0x0a,0x0e,0x00,0x40,0x70,0x0a,0x00,0xb0,0xe0,0x32,0x00,0x29,0xc0,0x80,0xaa,0x1f,0x21,0x39,0x42,0x00,0xa7,0x08,0x02,0xa8,0xd0,0x86,0xc4,0x05,0x1f,0x84,0x1c,0x0a,0x30,0x22,0x28,0x92,0x46,0x40,0x05,0x11,0x61,0x01,0x4a,0x02,0x3e,0x10,0x28,0x91,0x04,0x02,0x32,0x08,0x08,0x14,0xe8,0x00,0xf2,0x09,0x90,0x17,0xc0,0xbe,0x05,0x41,0x7a,0x0e,0xd4,0x8e,0xc5,0x36,0x2f,0x99,0xad,0x4e,0xea,0x89,0xb4,0xda,0xab,0x6d,0x7e,0xac,0xb5,0x6b,0xab,0x8d,0x9d,0xea,0xfb,0x5c,0x04,0x1f,0xe0,0x26,0x3f,0xc4,0x3c,0x06,0x20,}; -const uint8_t* const _I_Circles_47x47[] = {_I_Circles_47x47_0}; - -const uint8_t _I_Ok_btn_9x9_0[] = {0x01,0x00,0x0f,0x00,0xbe,0x40,0x30,0x50,0x09,0xcc,0x06,0xfa,0x01,0x40,0x38,0x82,0xc4,0x1e,0x20,}; -const uint8_t* const _I_Ok_btn_9x9[] = {_I_Ok_btn_9x9_0}; - -const uint8_t _I_Pressed_Button_13x13_0[] = {0x01,0x00,0x12,0x00,0xf8,0x40,0x7f,0x90,0x7f,0xf4,0x3c,0x02,0x3f,0xf8,0xf8,0x05,0xc1,0xa6,0x13,0x10,0xb8,0x80,}; -const uint8_t* const _I_Pressed_Button_13x13[] = {_I_Pressed_Button_13x13_0}; - -const uint8_t _I_Space_65x18_0[] = {0x01,0x00,0x26,0x00,0xfc,0x7f,0xc0,0x09,0x7f,0x80,0x41,0x81,0xeb,0x80,0x80,0x40,0xc3,0x2d,0x01,0x04,0x78,0x23,0xc1,0x1e,0x08,0xf0,0x47,0x82,0x3c,0x11,0x70,0x73,0xeb,0x40,0x7f,0xc8,0xf5,0xff,0xc0,0x3f,0x89,0x87,}; -const uint8_t* const _I_Space_65x18[] = {_I_Space_65x18_0}; - -const uint8_t _I_Voldwn_6x6_0[] = {0x00,0x08,0x0C,0x2F,0x2F,0x0C,0x08,}; -const uint8_t* const _I_Voldwn_6x6[] = {_I_Voldwn_6x6_0}; - -const uint8_t _I_Volup_8x6_0[] = {0x00,0x48,0x8C,0xAF,0xAF,0x8C,0x48,}; -const uint8_t* const _I_Volup_8x6[] = {_I_Volup_8x6_0}; - -const uint8_t _I_Clock_18x18_0[] = {0x01,0x00,0x31,0x00,0xe0,0x43,0xe0,0x1f,0x09,0xfc,0x03,0xf1,0x7f,0x80,0x47,0x3c,0x10,0x0d,0xf7,0xde,0x02,0x02,0x2d,0xff,0xde,0x07,0x7f,0xfd,0xc0,0xff,0xff,0xc0,0x11,0xdf,0xff,0x30,0x3d,0xff,0xca,0x07,0x3e,0xfa,0x85,0xc7,0xe5,0x01,0x10,0x10,0x98,0x85,0x84,0x32,0x20,}; -const uint8_t* const _I_Clock_18x18[] = {_I_Clock_18x18_0}; - -const uint8_t _I_Error_18x18_0[] = {0x01,0x00,0x2c,0x00,0xe0,0x43,0xe0,0x1f,0x09,0xfc,0x03,0xf1,0x7f,0x80,0x7f,0x3f,0xf0,0x0e,0x77,0x3e,0x03,0x8e,0xe3,0xc0,0x63,0xfe,0x38,0x1c,0xff,0xe1,0x03,0xbf,0xfe,0x00,0x46,0x08,0x20,0x71,0x05,0x08,0x34,0x42,0x02,0x13,0x10,0xb0,0x86,0x44,}; -const uint8_t* const _I_Error_18x18[] = {_I_Error_18x18_0}; - -const uint8_t _I_EviSmile1_18x21_0[] = {0x01,0x00,0x39,0x00,0x86,0x70,0x20,0x10,0x6c,0x04,0x06,0x0f,0x80,0x81,0xf3,0xf9,0xf0,0x3f,0xff,0xfc,0x04,0x7f,0xef,0xfc,0x04,0x04,0xbf,0x7d,0xfc,0x0f,0xcf,0x9f,0x81,0xf1,0xf1,0xf0,0x3c,0x3e,0x1e,0x07,0x8f,0xe3,0x86,0x9b,0xbd,0xef,0x80,0xef,0x3e,0x90,0x0b,0xc5,0xe2,0x01,0xf0,0x9f,0xc0,0x38,0x10,0xf8,0x00,}; -const uint8_t* const _I_EviSmile1_18x21[] = {_I_EviSmile1_18x21_0}; - -const uint8_t _I_EviSmile2_18x21_0[] = {0x01,0x00,0x37,0x00,0x00,0x14,0x3b,0x81,0x01,0x83,0xe0,0x20,0x7c,0xfe,0x7c,0x0f,0xff,0xff,0x01,0x1f,0xfb,0xff,0x01,0x01,0x2f,0x9f,0x3f,0x03,0xe3,0xe3,0xe0,0x78,0x7c,0x3c,0x0f,0x1f,0xc7,0x0d,0x37,0x3b,0x99,0x01,0xcf,0x79,0x20,0x33,0xcf,0x84,0x03,0xf1,0x7f,0x80,0x7c,0x27,0xf0,0x0e,0x04,0x3e,0x00,}; -const uint8_t* const _I_EviSmile2_18x21[] = {_I_EviSmile2_18x21_0}; - -const uint8_t _I_EviWaiting1_18x21_0[] = {0x01,0x00,0x34,0x00,0x86,0x70,0x20,0x10,0x6c,0x04,0x06,0x0f,0x80,0x81,0xf3,0xf9,0xf0,0x3f,0xff,0xfc,0x04,0x7f,0xef,0xfc,0x04,0x04,0xa0,0xb2,0xdb,0xeb,0xe0,0x7b,0xfd,0xfc,0x0f,0x3f,0x9f,0x81,0xf1,0xf8,0xe1,0xa9,0xfe,0x7f,0xe0,0x1f,0x8b,0xfc,0x03,0xe1,0x3f,0x80,0x70,0x21,0xf0,0x00,}; -const uint8_t* const _I_EviWaiting1_18x21[] = {_I_EviWaiting1_18x21_0}; - -const uint8_t _I_EviWaiting2_18x21_0[] = {0x01,0x00,0x31,0x00,0x86,0x70,0x20,0x10,0x6c,0x04,0x06,0x0f,0x80,0x81,0xf3,0xf9,0xf0,0x3f,0xff,0xfc,0x04,0x7f,0xef,0xfc,0x04,0x04,0xa0,0xb2,0xeb,0xed,0xe0,0x7f,0x7f,0xb8,0x08,0xf1,0xf8,0xf0,0xd4,0xff,0x3f,0xf0,0x0f,0xc5,0xfe,0x01,0xf0,0x9f,0xc0,0x38,0x10,0xf8,0x00,}; -const uint8_t* const _I_EviWaiting2_18x21[] = {_I_EviWaiting2_18x21_0}; - -const uint8_t _I_Percent_10x14_0[] = {0x00,0x0C,0x03,0x1E,0x03,0x33,0x03,0xB3,0x03,0xDE,0x01,0xEC,0x00,0x70,0x00,0x38,0x00,0xDC,0x00,0xEE,0x01,0x37,0x03,0x33,0x03,0xE3,0x01,0xC3,0x00,}; -const uint8_t* const _I_Percent_10x14[] = {_I_Percent_10x14_0}; - -const uint8_t _I_Smile_18x18_0[] = {0x01,0x00,0x2d,0x00,0xe0,0x43,0xe0,0x1f,0x09,0xfc,0x03,0xf1,0x7f,0x80,0x7f,0x3f,0xf0,0x0f,0xf7,0xfe,0x02,0x02,0x2f,0xff,0xfe,0x07,0xcf,0xe7,0xc0,0xf0,0xf8,0x70,0x11,0x82,0x08,0x1c,0x41,0x42,0xdf,0x7d,0xe0,0x37,0xcf,0xc0,0x98,0xc5,0x84,0x32,0x20,}; -const uint8_t* const _I_Smile_18x18[] = {_I_Smile_18x18_0}; - -const uint8_t _I_UsbTree_48x22_0[] = {0x01,0x00,0x3c,0x00,0x00,0x14,0x3c,0x08,0x78,0x08,0xf8,0x10,0xff,0xe0,0x59,0xb0,0x04,0x52,0xc0,0x1d,0x48,0xc0,0x9d,0x00,0xa7,0x02,0x80,0x41,0x80,0xa5,0x0e,0x02,0xa4,0xfb,0xfe,0x00,0xa1,0x49,0x04,0x48,0x0a,0x81,0xd1,0xc0,0x40,0x45,0x26,0x05,0x30,0x01,0x41,0xbe,0x10,0x30,0x2c,0x7e,0x3f,0xe0,0x59,0x80,0x04,0x50,0x0a,0x60,}; -const uint8_t* const _I_UsbTree_48x22[] = {_I_UsbTree_48x22_0}; - -const uint8_t _I_ButtonCenter_7x7_0[] = {0x00,0x1C,0x22,0x5D,0x5D,0x5D,0x22,0x1C,}; -const uint8_t* const _I_ButtonCenter_7x7[] = {_I_ButtonCenter_7x7_0}; - -const uint8_t _I_ButtonDown_7x4_0[] = {0x00,0x7F,0x3E,0x1C,0x08,}; -const uint8_t* const _I_ButtonDown_7x4[] = {_I_ButtonDown_7x4_0}; - -const uint8_t _I_ButtonLeftSmall_3x5_0[] = {0x00,0x04,0x06,0x07,0x06,0x04,}; -const uint8_t* const _I_ButtonLeftSmall_3x5[] = {_I_ButtonLeftSmall_3x5_0}; - -const uint8_t _I_ButtonLeft_4x7_0[] = {0x00,0x08,0x0C,0x0E,0x0F,0x0E,0x0C,0x08,}; -const uint8_t* const _I_ButtonLeft_4x7[] = {_I_ButtonLeft_4x7_0}; - -const uint8_t _I_ButtonRightSmall_3x5_0[] = {0x00,0x01,0x03,0x07,0x03,0x01,}; -const uint8_t* const _I_ButtonRightSmall_3x5[] = {_I_ButtonRightSmall_3x5_0}; - -const uint8_t _I_ButtonRight_4x7_0[] = {0x00,0x01,0x03,0x07,0x0F,0x07,0x03,0x01,}; -const uint8_t* const _I_ButtonRight_4x7[] = {_I_ButtonRight_4x7_0}; - -const uint8_t _I_ButtonUp_7x4_0[] = {0x00,0x08,0x1C,0x3E,0x7F,}; -const uint8_t* const _I_ButtonUp_7x4[] = {_I_ButtonUp_7x4_0}; - -const uint8_t _I_DFU_128x50_0[] = {0x01,0x00,0x2e,0x02,0x00,0x57,0xfe,0x0e,0x0e,0xcf,0x84,0x02,0x70,0x0f,0xc8,0x74,0x03,0x80,0x0e,0xbc,0x7c,0x04,0x06,0x30,0x30,0x74,0xe0,0x2f,0xe0,0x42,0x82,0x03,0xe7,0x81,0xff,0x02,0x14,0x20,0x1f,0x3e,0x00,0x79,0xc4,0x01,0xfd,0x20,0x07,0xd5,0xd4,0xe2,0x53,0xf2,0x74,0xff,0xe1,0x40,0x41,0x87,0xd8,0x01,0xf1,0x60,0xf0,0x43,0xca,0x43,0xe0,0xa7,0x83,0xe2,0x30,0x01,0x29,0x84,0x7b,0x20,0x0f,0x88,0x30,0x3c,0xb1,0x90,0x1d,0x00,0xfa,0x30,0x3f,0xf8,0xcc,0x02,0xc6,0x31,0x1f,0x83,0x49,0xa8,0x16,0x0a,0xf4,0x7f,0x00,0x21,0x1f,0x04,0x38,0x06,0x20,0x04,0x90,0x46,0x35,0xf0,0xfa,0x00,0xcc,0x7f,0x10,0x14,0x0b,0x46,0x20,0xd5,0x70,0x50,0xb4,0x06,0xf1,0x00,0x9f,0x03,0xd7,0x09,0x81,0xd7,0xc0,0x8b,0x85,0x38,0xc0,0x50,0x41,0xeb,0x63,0xc0,0x07,0xc6,0x90,0xbf,0x2b,0x05,0x01,0xb8,0xb1,0x0c,0x06,0xae,0x01,0x24,0x6f,0x94,0x42,0x80,0xb2,0x49,0xc4,0x33,0x80,0x1f,0x18,0x93,0xfc,0xa1,0x14,0x0e,0x02,0x9c,0x43,0xc3,0x07,0x81,0xfc,0x03,0xe2,0xc0,0x28,0x14,0x10,0x5e,0x3f,0x03,0xc0,0xcf,0xf8,0x10,0x0f,0xe5,0x56,0x03,0x05,0xf0,0x40,0x20,0x20,0xf2,0x42,0x0d,0xfd,0x72,0x30,0x0f,0xf8,0x7c,0x41,0xe3,0x80,0x10,0x0d,0x00,0x5c,0x4a,0xd1,0x87,0xf8,0x39,0xf5,0x5c,0x0c,0x0b,0xe0,0x1c,0x10,0x78,0xfc,0x02,0x04,0x20,0x1f,0xf7,0x0f,0x57,0x80,0x81,0x5e,0x13,0x83,0x01,0x1f,0x97,0xff,0xfe,0x03,0x2e,0x07,0x57,0x03,0x01,0xbf,0x1d,0x45,0x70,0x27,0xe4,0xff,0x8c,0x07,0xf5,0x83,0xe0,0xcf,0xe1,0x00,0xf6,0x10,0x8c,0x07,0xb1,0x07,0xc1,0xfc,0x63,0xe5,0xd2,0x07,0x8f,0x80,0x1a,0x21,0xe1,0xc0,0x71,0xe0,0x20,0xf1,0x24,0x88,0x34,0x62,0x00,0xe3,0x3f,0x8d,0xfe,0x81,0x80,0xc1,0xf8,0x5b,0xe2,0x0f,0x18,0xc7,0xf0,0x1e,0x50,0x35,0xa0,0xc8,0x3f,0x98,0x30,0x70,0x87,0x44,0x1e,0x21,0xe3,0xf8,0x02,0x4b,0xaf,0x01,0x81,0xb3,0xca,0x01,0x1c,0x25,0x94,0x01,0x04,0x58,0x8d,0x5c,0x0b,0xc6,0x08,0x10,0x78,0xc3,0x3f,0xf0,0x72,0x88,0x98,0x8b,0x89,0x55,0x82,0xc7,0x9b,0xe5,0x00,0x87,0x26,0xc4,0x46,0x20,0xf2,0xd1,0x87,0xc6,0x0c,0xdf,0x21,0x50,0x8a,0xc7,0x00,0x38,0x2e,0x04,0x42,0xaf,0x05,0x06,0x0a,0xb8,0x70,0x0f,0x91,0x80,0x5c,0x03,0xc5,0x30,0x84,0x6a,0xe1,0x40,0xf1,0x7b,0x0f,0x00,0x7a,0x24,0x21,0x07,0x94,0x33,0x09,0x57,0x8a,0x93,0x85,0xec,0x3e,0x00,0x79,0x0b,0x88,0x06,0x3c,0x3f,0xfc,0xa8,0x1e,0x21,0x91,0x76,0x90,0x90,0x40,0x03,0xe0,0xe0,0x78,0x3f,0xd5,0x58,0x0e,0x08,0x32,0x3f,0x88,0xa8,0x90,0x8c,0x25,0x30,0xbc,0x7f,0xb5,0x50,0x1b,0xe0,0x20,0x7f,0x92,0x33,0x88,0x97,0x4a,0x07,0x0c,0x9e,0x5f,0xeb,0xaa,0xf2,0x74,0x8d,0x17,0x80,0x06,0x29,0xf1,0xe0,0x71,0xfb,0xfd,0x71,0xd8,0xff,0xf8,0x21,0x71,0x04,0x87,0x01,0xc1,0xa1,0xff,0x83,0xe7,0xf0,0xff,0xc1,0x51,0xe4,0xdd,0x1b,0x07,0xc2,0x63,0xf6,0x0f,0x9f,0xeb,0x5f,0x02,0x77,0x8a,0xc4,0xa3,0x17,0xc8,0x44,0x8c,0x34,0x20,0x71,0xfe,0x99,0x04,0x88,0x40,0x01,0xc3,0x47,0xf0,0x93,0x0f,0xf4,0x28,0x0e,0x3a,0xad,0x50,0x39,0x30,0x1f,0x18,0x3d,0x0e,0x31,0xff,0x3d,0x0c,0x02,0xa8,0x03,0x20,0x01,0x7e,0x3f,0xf8,0x09,0x06,0x33,0xfe,0x1b,0x50,}; -const uint8_t* const _I_DFU_128x50[] = {_I_DFU_128x50_0}; - -const uint8_t _I_Warning_30x23_0[] = {0x01,0x00,0x47,0x00,0x80,0x70,0x00,0x65,0xe0,0x80,0x80,0xc7,0xe1,0x03,0x01,0xaf,0xe2,0x0e,0x03,0x19,0xe4,0x3c,0x06,0xb3,0xe8,0xf8,0x0c,0x67,0xf3,0xf0,0x1a,0x60,0x27,0xf7,0xf1,0x50,0xcf,0xff,0xe0,0x34,0xf0,0x00,0xc6,0x03,0xf0,0x01,0x8c,0x0c,0x06,0x7f,0x80,0x18,0xc1,0xff,0x9f,0xff,0xfc,0x3c,0x06,0x7f,0xe0,0x58,0xc7,0xff,0xe0,0x31,0x00,0x88,0x00,0x67,0xff,0xe0,0x18,0xc7,0xc0,}; -const uint8_t* const _I_Warning_30x23[] = {_I_Warning_30x23_0}; - -const uint8_t _A_Loading_24_0[] = {0x01,0x00,0x37,0x00,0x00,0x17,0x83,0xff,0x0f,0x90,0x40,0x21,0x1c,0x0f,0xfc,0x1f,0x01,0x00,0x81,0x60,0x35,0x40,0x21,0xaa,0x00,0x86,0x51,0x02,0x80,0x44,0x60,0x30,0x0c,0x10,0x6c,0x6a,0x80,0x21,0x94,0x00,0x92,0x88,0x02,0x1c,0x90,0x08,0x60,0x30,0x11,0x19,0x80,0x9c,0x64,0x43,0x82,0x1f,0x11,0x10,0x80,}; -const uint8_t _A_Loading_24_1[] = {0x01,0x00,0x38,0x00,0x00,0x17,0x83,0xff,0x0f,0x90,0x40,0x21,0x1c,0x0f,0xfc,0x1f,0x01,0x00,0x81,0x00,0x8e,0xa8,0x02,0x19,0x44,0x0a,0x01,0x11,0x80,0xc0,0x30,0x41,0xb1,0xa2,0x00,0x86,0x50,0x02,0x40,0x41,0x64,0x80,0x43,0x01,0x80,0xe0,0x22,0x02,0x34,0x01,0x16,0xaa,0x04,0x32,0x21,0xc1,0x0f,0x88,0x88,0x40,}; -const uint8_t _A_Loading_24_2[] = {0x01,0x00,0x36,0x00,0x00,0x17,0x83,0xff,0x0f,0x90,0x40,0x21,0x1c,0x0f,0xfc,0x1f,0x01,0x00,0x81,0x00,0x9a,0x51,0x02,0x80,0x44,0x60,0x30,0x0c,0x10,0x6c,0x68,0x80,0x21,0x94,0x00,0x92,0xa8,0x02,0x10,0x71,0x05,0x04,0x3a,0x70,0x80,0x10,0xd5,0x00,0x43,0xaa,0x81,0x0c,0x88,0x70,0x43,0xe2,0x22,0x10,}; -const uint8_t _A_Loading_24_3[] = {0x01,0x00,0x33,0x00,0x00,0x17,0x83,0xff,0x0f,0x90,0x40,0x21,0x1c,0x0f,0xfc,0x1f,0x01,0x00,0x81,0x00,0xa2,0x01,0x01,0x80,0xc0,0x30,0x41,0xb1,0xa2,0x00,0x86,0x50,0x02,0x40,0x41,0x64,0x80,0x43,0x29,0x80,0xe0,0x2a,0x81,0xd1,0xd5,0x00,0x84,0x0a,0x83,0x22,0x1c,0x10,0xf8,0x88,0x84,}; -const uint8_t _A_Loading_24_4[] = {0x01,0x00,0x42,0x00,0x80,0x40,0x80,0x43,0x07,0x80,0x60,0x00,0xa3,0x40,0x82,0xc0,0x34,0x10,0x88,0x05,0x42,0x21,0x00,0x94,0x00,0x86,0x28,0x02,0x18,0x50,0x08,0x60,0xe0,0x54,0x88,0x78,0x20,0xe0,0x11,0x0c,0x0c,0xa2,0xa1,0x00,0xa4,0x79,0x60,0x1a,0x8a,0x90,0x14,0x65,0x20,0x51,0x8a,0x01,0x46,0x14,0x18,0x11,0x81,0x0d,0x8a,0x03,0x00,0xf0,0x10,0x46,0x81,0x00,}; -const uint8_t _A_Loading_24_5[] = {0x01,0x00,0x2d,0x00,0x00,0x74,0x1a,0x01,0x60,0x85,0x40,0x2a,0x1f,0xa8,0x05,0x7e,0x15,0x81,0xa8,0x42,0xa8,0x40,0x21,0x92,0x00,0x86,0x31,0x5a,0x85,0x50,0x2a,0xb0,0xac,0xc0,0x14,0x64,0x80,0x51,0xa1,0x01,0x44,0x2e,0x21,0xd3,0x11,0x88,0xa4,0x87,0x16,}; -const uint8_t _A_Loading_24_6[] = {0x01,0x00,0x43,0x00,0x80,0x50,0x00,0x43,0xe0,0x02,0x94,0x06,0x01,0xa0,0x81,0x40,0x22,0x10,0x58,0x04,0x22,0x14,0x02,0x18,0xa4,0x02,0x91,0x29,0x80,0x6a,0x2a,0x40,0x51,0xf2,0x81,0x4b,0xc1,0x07,0x84,0x44,0x00,0x63,0x0a,0x88,0x40,0x20,0xe0,0x21,0x02,0x94,0x50,0x04,0x32,0x80,0x10,0xd4,0x00,0x43,0xa0,0x84,0x0d,0x04,0x5c,0x38,0x01,0xa0,0x86,0x04,0x04,0x20,0x51,}; -const uint8_t* const _A_Loading_24[] = {_A_Loading_24_0,_A_Loading_24_1,_A_Loading_24_2,_A_Loading_24_3,_A_Loading_24_4,_A_Loading_24_5,_A_Loading_24_6}; - -const uint8_t _I_DolphinFirstStart0_70x53_0[] = {0x01,0x00,0x5a,0x01,0x80,0x60,0x3f,0xf7,0xf0,0x42,0xf8,0x01,0x43,0x07,0x04,0x24,0x72,0x01,0xc0,0x9d,0x82,0x13,0xff,0xff,0xbd,0x70,0x20,0x20,0x72,0xe0,0x40,0x2a,0x11,0xdb,0x00,0x6c,0xec,0x10,0x0d,0x44,0x3a,0x71,0x0e,0x04,0x14,0x42,0x01,0x54,0x86,0xd3,0x27,0x02,0x44,0xd4,0x41,0xb0,0xf2,0x10,0x42,0x55,0x38,0x71,0x1b,0x10,0x18,0xa0,0x41,0x11,0xb1,0xc8,0x28,0x98,0x09,0xfc,0x00,0x72,0x35,0x49,0x8d,0x0b,0xc1,0x70,0xf0,0x10,0x4b,0x51,0x11,0xc2,0x6c,0x0a,0xa3,0x03,0x80,0x7f,0xbf,0xf3,0x08,0x46,0x60,0x90,0x30,0x60,0x50,0xd8,0x2c,0x11,0x0c,0x71,0x5c,0x60,0xf8,0x0f,0xcf,0x3f,0x81,0x80,0xa1,0x9e,0x86,0x0f,0xc0,0x82,0x64,0x30,0x3e,0x09,0x84,0x03,0xf1,0x03,0xa0,0x40,0xa4,0x18,0x39,0xfc,0x20,0x52,0x30,0x19,0x07,0xc6,0x8e,0x4a,0x18,0x22,0x74,0x60,0x1a,0x0f,0xc6,0x3c,0x60,0x5c,0x05,0x28,0xe4,0x3f,0x99,0xf8,0x22,0x28,0x7e,0x05,0x91,0xa8,0x7f,0x23,0xf0,0x59,0x00,0xac,0x63,0xe0,0x81,0xcf,0x4f,0xe0,0xb1,0x81,0x58,0xc3,0xc1,0x08,0x24,0x1f,0xf9,0x68,0x6a,0x1f,0xe9,0xff,0x16,0x02,0x34,0x13,0x50,0x82,0x0a,0xea,0x60,0x1f,0xf9,0xf0,0x41,0x05,0x1d,0x30,0x09,0x18,0x60,0x15,0xa3,0xe8,0x83,0x47,0xe0,0xec,0x2c,0xaf,0xf2,0x0e,0x08,0x1f,0xc1,0x18,0x60,0x1a,0xaf,0xc2,0x6c,0x89,0x62,0x03,0x19,0xad,0xe5,0x70,0x44,0x62,0x80,0x5a,0xa1,0x4f,0x63,0x23,0x0c,0x7a,0xaa,0x4d,0x11,0xe9,0x00,0x06,0x73,0xaa,0x25,0x0a,0x78,0xaf,0x90,0x09,0x25,0x54,0x56,0x5f,0x04,0x30,0xc0,0x64,0x7a,0xa1,0x11,0x7e,0x20,0x18,0x0f,0x3c,0x82,0xaa,0x04,0x18,0x0d,0xf8,0x16,0x33,0xe8,0x84,0xa8,0x08,0x3c,0x33,0x00,0xf0,0x20,0x71,0x08,0xa9,0x38,0x86,0x62,0x62,0x18,0x40,0x44,0x80,0x09,0x04,0x08,0x90,0x01,0x20,0x41,0x17,0x22,0x90,0x01,0x3e,0x00,0x76,0x80,0x1d,0x48,0x00,0x8d,0x91,0x00,0x34,0xf8,0x20,0xe2,0xa7,0x9c,0x06,0x5c,0x11,0x02,0x28,0x5d,0x91,0x35,0x48,0xaf,0xf8,0x04,0x3f,0xf9,0x88,0x20,0x01,}; -const uint8_t* const _I_DolphinFirstStart0_70x53[] = {_I_DolphinFirstStart0_70x53_0}; - -const uint8_t _I_DolphinFirstStart1_59x53_0[] = {0x01,0x00,0x1e,0x01,0x00,0x0e,0x03,0xfe,0x07,0x5b,0x84,0x02,0x06,0x07,0x48,0x64,0x02,0x08,0x07,0x48,0x14,0x02,0x10,0x07,0x48,0x0c,0x03,0x21,0x3f,0x13,0x18,0x84,0xa8,0x00,0x75,0x8c,0x00,0xca,0x00,0x0b,0x28,0x20,0x1d,0xa0,0x59,0xe0,0x39,0x48,0x07,0x03,0x81,0xd5,0x81,0xd6,0x81,0x55,0x8c,0x01,0xc6,0x21,0x00,0x87,0x68,0x25,0x52,0x40,0x39,0x7c,0x21,0xf5,0x08,0xa8,0x1d,0x20,0xfa,0x88,0x70,0x1c,0xfd,0x10,0x3a,0xa4,0x1f,0x88,0x54,0x18,0x85,0x52,0x09,0xbe,0x81,0xc1,0x0c,0x83,0x10,0x94,0x40,0x39,0xf0,0x19,0x21,0xc8,0x62,0x12,0x0c,0x04,0x0e,0x0c,0x07,0x38,0x07,0x86,0x07,0x18,0x03,0x94,0xc2,0x01,0x9e,0x81,0xca,0x38,0x89,0x21,0x0f,0x0c,0x03,0xf9,0x27,0x13,0x94,0xd0,0xb6,0x70,0x20,0x38,0xda,0x80,0xe5,0x10,0x03,0x95,0x59,0x54,0x70,0x10,0x38,0xda,0xc0,0xc3,0xfe,0xc1,0xab,0x0b,0xaa,0x2a,0x1c,0x05,0x81,0x58,0x38,0x09,0xd0,0x5c,0xa3,0xe0,0x72,0x86,0xae,0x8d,0x40,0x34,0x06,0xa1,0xc0,0xc0,0xe3,0xc0,0x65,0x1c,0x19,0x58,0x29,0xe1,0x00,0x14,0x28,0x0a,0x26,0x61,0x00,0x15,0x58,0x0a,0x2e,0x34,0xd6,0x42,0x9e,0x6b,0x54,0x82,0x92,0x08,0x1e,0x63,0x41,0x1d,0x0a,0x88,0x60,0x1d,0x42,0x11,0x5c,0x01,0xe5,0x3c,0x03,0x97,0x30,0x0e,0x42,0x42,0x80,0xd0,0x82,0xe4,0x07,0x28,0x17,0x10,0x1e,0xb0,0x4a,0x20,0x3d,0x61,0x1a,0x80,0x79,0x0f,0x0a,0x21,0x70,0x07,0x90,0x1c,0xa4,0x1a,0x00,0x7a,0xd0,0x0e,0x42,0x34,0x20,0x10,0xe0,0x00,0xed,0x00,0xa1,0x82,0xc8,0xc6,0x74,0x40,0xd9,0x01,0xce,0x84,0x07,0x69,0x10,0xcc,0x80,0xe7,0x5c,0x03,0xb4,0xa8,0x96,0x40,0x73,0x8a,0x96,0xc8,0x0c,0x40,}; -const uint8_t* const _I_DolphinFirstStart1_59x53[] = {_I_DolphinFirstStart1_59x53_0}; - -const uint8_t _I_DolphinFirstStart2_59x51_0[] = {0x01,0x00,0x2e,0x01,0x00,0x1f,0xfe,0x06,0x05,0x3f,0xc7,0xfe,0x01,0x1c,0x03,0x16,0x02,0xaf,0x0f,0x80,0x58,0x01,0xc7,0xaa,0x80,0x82,0xc4,0x0e,0x55,0x6b,0x28,0x10,0x81,0x45,0xab,0x8d,0x01,0xca,0x04,0x1a,0x1a,0xac,0x1c,0x0e,0x50,0x48,0x06,0xc0,0x3c,0x40,0x01,0x84,0x40,0x2b,0x15,0x51,0xd9,0xc4,0x20,0x1a,0xc9,0x50,0x1c,0xe4,0x02,0xe1,0x8a,0x81,0xd7,0x55,0x0a,0x03,0x9d,0x02,0x01,0x5c,0x82,0x81,0xd7,0xc0,0x3a,0x10,0x3a,0x12,0x88,0xc8,0x60,0x11,0x07,0xa0,0x1c,0x68,0x00,0xf6,0xe0,0x22,0x50,0x0e,0x36,0x00,0x7b,0x68,0x00,0x83,0xa0,0x11,0x08,0x1c,0x6a,0x03,0x42,0x44,0x1e,0xc0,0x28,0x50,0x61,0xf9,0x56,0x00,0xe3,0x60,0x40,0x88,0x1c,0x75,0x01,0x42,0x07,0x9d,0x50,0x5e,0x4b,0x01,0x37,0x8e,0xb0,0x0e,0x51,0xd8,0x04,0xc2,0x01,0xd4,0x5d,0x1c,0x02,0x30,0x7f,0x14,0x99,0x5c,0x20,0x11,0x48,0x07,0x58,0x0e,0x20,0x81,0xd0,0x23,0x04,0x1e,0x30,0x80,0x38,0xd4,0x11,0x82,0x0f,0x18,0x40,0xb0,0xb0,0x50,0x3d,0x58,0x1c,0x52,0x85,0xf1,0x83,0x75,0x58,0x64,0x49,0x1a,0xfc,0x17,0x57,0x01,0x88,0x25,0x0b,0x55,0x02,0xaa,0xc0,0x64,0x14,0x08,0x1e,0x02,0xaa,0x1f,0x18,0x0f,0x00,0xbe,0x20,0xf1,0x80,0x82,0x46,0x01,0x03,0x82,0xe0,0x04,0xa3,0xab,0x46,0x0e,0x32,0x15,0x80,0xb5,0x40,0x2a,0xa4,0x21,0x98,0x43,0x70,0x13,0x58,0x04,0xac,0xa4,0x3c,0x08,0xd6,0x02,0x35,0x00,0x8a,0xcd,0x06,0xa3,0x1d,0xa0,0x24,0x46,0x57,0xe8,0x26,0x8c,0xdb,0x80,0x84,0x18,0xad,0x42,0x07,0x5f,0xbf,0xb9,0x8a,0x17,0x80,0xff,0x6a,0xb0,0x46,0x91,0x07,0x88,0xc4,0x4a,0x43,0x1f,0x07,0x92,0xc4,0x49,0x82,0x9b,0x25,0x98,0xc0,0x28,0xa0,0x73,0x1f,0x0b,0x50,0x81,0xea,0x07,0x40,0x7b,0xac,0x44,0x0e,0xa0,}; -const uint8_t* const _I_DolphinFirstStart2_59x51[] = {_I_DolphinFirstStart2_59x51_0}; - -const uint8_t _I_DolphinFirstStart3_57x48_0[] = {0x01,0x00,0x12,0x01,0x00,0x16,0x03,0xff,0x07,0x03,0xa5,0x82,0x01,0x38,0x03,0xa4,0x62,0x01,0xc0,0x03,0xa4,0x10,0x04,0x30,0x10,0x39,0xc0,0x80,0x48,0x0c,0x40,0x91,0x7e,0x20,0x60,0x72,0x84,0x02,0x8b,0x78,0x12,0x28,0x80,0x68,0x85,0x87,0x20,0x11,0x18,0x5c,0x80,0xe8,0x01,0x19,0xc5,0x00,0x0e,0x62,0xc1,0x9f,0x01,0xcb,0xe9,0x03,0x84,0x60,0x20,0xf8,0x00,0x38,0xd7,0x21,0xb1,0x0f,0x04,0x04,0x0e,0x5a,0x89,0xd4,0x83,0xc0,0x4b,0x3a,0xc5,0x54,0xcc,0x20,0x51,0x00,0x8e,0xc3,0x54,0x80,0x13,0xf8,0x81,0xc6,0xc1,0x55,0x01,0x8c,0x78,0x0e,0x30,0xee,0x06,0xaa,0x05,0xe0,0xae,0x01,0xc6,0x23,0x80,0xaa,0xc1,0x60,0x1a,0x90,0x38,0xc8,0x60,0x1a,0xb8,0x54,0x02,0xad,0x07,0x80,0xd0,0x40,0x83,0x15,0x80,0x7b,0x21,0x10,0x1c,0x0c,0x03,0x7f,0x2a,0x80,0x4d,0x00,0xe3,0x01,0xf8,0xf0,0x2a,0xf0,0x08,0x60,0x1c,0x60,0x41,0xd1,0xdf,0x1a,0x44,0x0e,0x50,0x68,0x05,0xe3,0x07,0x02,0x82,0x01,0xc6,0x19,0x00,0xf8,0x5f,0xe0,0x20,0x72,0xfa,0x40,0x7f,0xc2,0xb1,0x03,0x88,0x68,0x7f,0xf6,0xb4,0x28,0xc0,0x80,0xe3,0x88,0xaa,0xc7,0x40,0xe9,0x50,0xd5,0x41,0x94,0xa2,0x07,0x29,0x87,0x52,0x02,0x07,0x12,0x30,0xc1,0x22,0x16,0x86,0x29,0x01,0xca,0x30,0xf6,0x10,0x39,0xc2,0x23,0x10,0x6c,0x00,0x1d,0x3d,0x10,0x1b,0x02,0xe0,0x41,0x03,0x08,0x75,0x0c,0x60,0x0e,0x4f,0x11,0x0a,0x0c,0x18,0x0e,0x96,0x06,0x28,0x81,0xd3,0x01,0x1f,0x01,0x90,0x1c,0xdc,0xc2,0x01,0x15,0xd0,0x81,0xdc,0x4c,0x30,0x30,0x3f,0x00,0xc4,0x0e,0x30,0x20,0x3c,0x8c,0xc8,0x0f,0x2b,0x41,}; -const uint8_t* const _I_DolphinFirstStart3_57x48[] = {_I_DolphinFirstStart3_57x48_0}; - -const uint8_t _I_DolphinFirstStart4_67x53_0[] = {0x01,0x00,0x1f,0x01,0x00,0x17,0xc3,0xfe,0x08,0x68,0x74,0x02,0x0e,0x07,0x4c,0x04,0x06,0x01,0x18,0x04,0x25,0x00,0x04,0x36,0x00,0x42,0x48,0x02,0x88,0x00,0x28,0x80,0x0c,0xa0,0x40,0x83,0x84,0x00,0xca,0x08,0x08,0x30,0x21,0x83,0x0c,0x2c,0x81,0xe3,0x04,0x20,0xc0,0x80,0x02,0x31,0x32,0x11,0x02,0x27,0x00,0x5d,0x40,0x45,0x87,0x90,0x3e,0x7c,0x00,0x43,0x84,0x4e,0x60,0x43,0x30,0x89,0x82,0x12,0x80,0x15,0x20,0x40,0x99,0xc8,0x22,0x7b,0x88,0x10,0x20,0x82,0x27,0x7c,0x82,0x9d,0x48,0x22,0x5f,0x0d,0xfc,0x08,0x10,0x41,0x12,0xf8,0x57,0xc2,0x28,0x30,0x1e,0x07,0x9e,0x06,0x87,0x25,0x79,0xc4,0x20,0x40,0x83,0x21,0x14,0x22,0x08,0x08,0x38,0x2a,0xb8,0xd9,0x47,0x0a,0x14,0x09,0xf0,0x54,0x47,0x1f,0x81,0x82,0x1a,0xde,0x8e,0x33,0xd1,0xc7,0x81,0x0f,0x0e,0x45,0x18,0x20,0xa1,0xe6,0xf2,0x10,0x89,0xa0,0x70,0x11,0x00,0x41,0x46,0x03,0x86,0x55,0x10,0x40,0xc1,0x82,0x25,0x20,0x04,0x11,0x94,0x80,0x43,0x10,0x84,0x01,0x46,0xc0,0xbd,0x38,0x40,0x20,0x8f,0x49,0x08,0xc4,0x1c,0xc8,0x22,0x50,0x38,0x20,0x20,0x86,0xe4,0x83,0x10,0x41,0x8b,0x87,0xf9,0x03,0x81,0xc0,0x81,0x05,0x81,0xc0,0x40,0xf3,0x90,0x60,0x41,0x70,0x2c,0x17,0x01,0xc0,0xc1,0x41,0x05,0x30,0x98,0x43,0x04,0x65,0x01,0x04,0x0c,0x32,0x38,0x91,0x18,0x04,0x14,0x10,0x38,0x18,0x1e,0xac,0x7c,0x41,0x11,0x88,0x5f,0xfc,0x17,0x55,0xa9,0x82,0x06,0x05,0xbc,0x85,0x02,0x08,0xc6,0x32,0x0f,0xe5,0x5e,0x1a,0x08,0x5c,0x06,0xaa,0x34,0x08,0x4a,0x06,0x02,0xab,0x75,0xf0,0x4f,0xc1,0x05,0x80,0x08,0x8e,0xab,0x7f,0xea,0x04,0x11,0x80,0x6a,0xa0,0x02,0x03,0x08,}; -const uint8_t* const _I_DolphinFirstStart4_67x53[] = {_I_DolphinFirstStart4_67x53_0}; - -const uint8_t _I_DolphinFirstStart5_54x49_0[] = {0x01,0x00,0x0b,0x01,0x00,0x0f,0xf2,0xfe,0x06,0x48,0x1e,0x02,0x06,0x05,0x2e,0x00,0x08,0x61,0x80,0x62,0x98,0x00,0x86,0x20,0x06,0x28,0x40,0x08,0x64,0x00,0x62,0x82,0x00,0x86,0x80,0x06,0x28,0x14,0x72,0x01,0x80,0x03,0x14,0x06,0x44,0x03,0x20,0x49,0x00,0xc4,0x0c,0x61,0x13,0x81,0x07,0x90,0x0c,0xff,0xa8,0x18,0xcc,0xe0,0x10,0x78,0x60,0x18,0xc9,0xe3,0x10,0x03,0x0e,0x02,0x02,0x4f,0x19,0x00,0x18,0x78,0x10,0x12,0x78,0xc8,0x0a,0xc3,0xf8,0x80,0xc1,0x80,0xc5,0xe0,0xff,0x8f,0x47,0xe1,0x27,0x03,0x0d,0xfc,0x80,0x3b,0xc9,0x74,0x43,0x81,0x0f,0xb0,0x40,0x2b,0xd2,0xd3,0x71,0x07,0x87,0x5f,0x16,0x84,0x54,0x23,0xe3,0x21,0xab,0xc5,0x61,0x1a,0x82,0xf0,0xf0,0x35,0x70,0xa8,0x45,0x50,0x2a,0x3e,0x0a,0xac,0x1e,0x11,0x28,0x03,0x0f,0xc3,0xfe,0x06,0x19,0xa0,0x18,0x6f,0x9f,0x08,0x7c,0x22,0x30,0x06,0x1d,0xfc,0x3e,0x21,0x08,0x00,0x8f,0x01,0x7a,0x31,0x08,0x24,0x42,0x21,0xf0,0x5e,0x08,0x18,0x44,0xe3,0x0f,0x59,0x92,0xb4,0x96,0x66,0x06,0x58,0x10,0x19,0x60,0x20,0x64,0x46,0x08,0x19,0x27,0x00,0x65,0x9f,0x81,0x93,0xd1,0x2b,0x03,0x17,0x82,0x3f,0x50,0x9a,0x81,0x87,0x51,0x1e,0xf0,0x68,0x69,0x40,0x61,0xea,0x9d,0x86,0x1d,0x45,0x80,0x61,0x2d,0x48,0xc2,0x67,0x8d,0x12,0x3a,0x06,0x19,0x02,0x88,0x74,0x4b,0x21,0x03,0x1d,0x08,0xca,0x21,0x41,0x06,0x93,0xe8,0xa1,0x85,0x31,0xe9,0x24,0x48,0x20,0x30,0x1b,0x10,0x18,0x77,0x8f,0xa1,0x80,0xcc,0x40,0xc3,0x56,0x0b,0x8c,0x0a,0x22,0xba,0x12,0x88,0x81,0x84,}; -const uint8_t* const _I_DolphinFirstStart5_54x49[] = {_I_DolphinFirstStart5_54x49_0}; - -const uint8_t _I_DolphinFirstStart6_58x54_0[] = {0x01,0x00,0x21,0x01,0x00,0x0f,0xf2,0x7e,0x06,0x4c,0x04,0x0f,0x81,0x03,0x03,0x9d,0x80,0x04,0x30,0xc0,0x39,0xc6,0x00,0x43,0x30,0x03,0x9c,0x10,0x04,0x34,0x00,0x39,0xc0,0x84,0x44,0x07,0x38,0x08,0x0d,0x41,0x68,0x13,0x70,0x39,0x08,0xd0,0x56,0xa1,0xd1,0x03,0x94,0x80,0x04,0x30,0x68,0x04,0x20,0x0e,0x84,0x91,0x03,0xa9,0x64,0x62,0x80,0x41,0x88,0x40,0x3f,0xc6,0xf1,0xfe,0x43,0xc0,0xe3,0x80,0xff,0xff,0xe0,0x3f,0xf8,0xf8,0x1c,0x78,0x18,0x1f,0xfe,0x0f,0x02,0x12,0x18,0x47,0x03,0x82,0x10,0x1e,0x08,0x1c,0xf5,0x60,0x71,0xd4,0x81,0xcf,0xab,0xff,0xd5,0xf5,0xc0,0xe3,0x04,0xe0,0x03,0x86,0xae,0x27,0x28,0x27,0x40,0x0e,0x21,0x91,0x03,0x96,0x80,0x0e,0x34,0x18,0x79,0x28,0x60,0x95,0x00,0x38,0xf8,0x20,0x27,0xd1,0x82,0x6a,0x03,0xc3,0x1c,0x39,0x94,0x0a,0xa1,0xc0,0xc5,0x2f,0xca,0x05,0x02,0x90,0x24,0x56,0x04,0x68,0x10,0x01,0x4f,0x80,0xea,0x5b,0x10,0x38,0x83,0x8d,0xa0,0x30,0x30,0x38,0xa3,0x09,0xc0,0x20,0xf2,0x03,0x90,0xc0,0x46,0xe2,0x91,0x2f,0x80,0xfc,0xe0,0x1e,0x08,0x02,0x54,0x47,0x62,0x27,0x2f,0xfb,0x14,0xdc,0xc6,0xb5,0x30,0x38,0x8b,0x05,0x6a,0x60,0x01,0x89,0x00,0xc8,0x16,0x50,0x29,0x10,0x1c,0x8d,0x25,0x05,0xa1,0x15,0xc9,0xfe,0x50,0xaa,0x08,0x10,0x67,0x01,0x22,0x8a,0xe0,0x60,0xe5,0xf2,0x07,0x8e,0xa8,0xb0,0x49,0xe1,0x00,0x0d,0xd4,0x68,0x5a,0x00,0x39,0x46,0x88,0x84,0x07,0x30,0xe8,0x81,0xc6,0x40,0x4d,0x11,0x91,0x17,0x06,0x40,0x65,0x11,0x51,0x01,0xc6,0x81,0x04,0x32,0x18,0x1e,0x92,0x64,0x00,0x11,0x68,0x81,0xd6,0xa0,0x07,0x16,0x22,0x6b,0x0a,0x82,0x07,0x3f,0x05,0x4d,0xdc,0x24,0x21,}; -const uint8_t* const _I_DolphinFirstStart6_58x54[] = {_I_DolphinFirstStart6_58x54_0}; - -const uint8_t _I_DolphinFirstStart7_61x51_0[] = {0x01,0x00,0x13,0x01,0x00,0x17,0x03,0xff,0x01,0x03,0xa4,0xe2,0x01,0x0e,0x03,0xa4,0x1a,0x01,0x30,0x03,0x1e,0x00,0x2a,0x3c,0x00,0x39,0xd0,0x00,0x65,0x03,0x01,0x94,0x80,0x06,0x50,0x40,0x19,0x44,0x00,0x65,0x08,0x01,0xb0,0x2c,0xe2,0x81,0xb6,0x86,0x0a,0xd8,0x7c,0x20,0x75,0x85,0x10,0xcc,0x06,0x50,0x50,0x3b,0x10,0xce,0x00,0x69,0x20,0x79,0x7c,0x20,0x20,0x71,0xc0,0x07,0xca,0xf1,0x02,0x81,0x01,0xc6,0x3a,0x07,0x1f,0xe4,0x10,0x0e,0x53,0xe0,0x38,0xe7,0xa0,0xa0,0x72,0xbb,0x81,0xca,0x12,0x68,0x1c,0x05,0x5c,0x0e,0x3f,0xe8,0xc8,0x1c,0xab,0xe0,0x72,0x94,0x81,0xda,0xb2,0x07,0x5f,0xe0,0x3d,0xbf,0x95,0x44,0x20,0x81,0xce,0xf1,0x2f,0x03,0x94,0xb8,0xae,0x51,0x00,0x39,0x47,0x60,0xd0,0x84,0x70,0x81,0xcb,0x44,0x9d,0x10,0x3a,0x58,0xce,0xe6,0x07,0x29,0x10,0x18,0xa0,0x50,0x88,0x76,0x02,0x22,0x07,0x49,0x8e,0x02,0x24,0x07,0x4e,0x0e,0x02,0x12,0x96,0x38,0x44,0x07,0x02,0x8f,0x1c,0x07,0x1c,0x4e,0x30,0x1c,0x10,0x3c,0x6c,0x13,0x80,0x38,0xc0,0xb0,0x80,0xf1,0x6e,0x90,0x1c,0x71,0x10,0xd7,0x49,0x81,0xc7,0x20,0x0f,0x17,0xe9,0x42,0x20,0x91,0x09,0xeb,0x24,0xe2,0x10,0x49,0x07,0x6f,0xff,0x80,0x56,0x88,0x1c,0xa2,0xae,0xd1,0x66,0x89,0xe0,0x68,0x11,0xb8,0x06,0xc0,0x2e,0x40,0x71,0x9a,0xc0,0x2b,0x00,0x73,0xc0,0x7a,0xe0,0x09,0x12,0x03,0x95,0x57,0xff,0x17,0x03,0x9c,0x03,0x57,0xaa,0x78,0x94,0x40,0xa6,0x35,0x5a,0xac,0x14,0x0e,0x9a,0xad,0x50,0xf8,0x41,0x05,0x00,0x83,0x55,0x14,0x06,0x07,0x18,0x54,0xa0,0x0e,0xb0,0x60,0x31,0xc0,0x00,}; -const uint8_t* const _I_DolphinFirstStart7_61x51[] = {_I_DolphinFirstStart7_61x51_0}; - -const uint8_t _I_DolphinFirstStart8_56x51_0[] = {0x01,0x00,0xfd,0x00,0x00,0x17,0x83,0xff,0x01,0x03,0x1c,0x72,0x01,0x06,0x03,0x1c,0x0e,0x01,0x18,0x02,0x96,0x00,0x04,0x36,0x00,0x31,0x50,0x01,0x24,0x1c,0x29,0x00,0x28,0xa0,0x40,0x21,0x88,0x01,0x8a,0x08,0x02,0x18,0x40,0x18,0x80,0x64,0x09,0x20,0x89,0x81,0x98,0x3c,0x42,0x63,0x03,0x30,0xcc,0x70,0x10,0x71,0xd9,0x01,0x86,0xc1,0x1c,0x03,0x24,0x42,0x7e,0x50,0x12,0x91,0x62,0x2f,0xf8,0x0e,0x00,0x18,0xb9,0x17,0x1c,0x04,0x83,0x02,0x06,0x1e,0x27,0xc4,0x54,0x20,0x62,0xf2,0x7c,0xe0,0x52,0x0c,0x10,0x88,0x7c,0x9f,0xf8,0x28,0x18,0x41,0xa5,0xff,0x85,0x48,0x30,0x80,0xd1,0xe4,0x5f,0xc1,0xa3,0x84,0x26,0x0f,0x23,0xfe,0x1b,0x18,0x44,0x16,0x01,0x90,0x81,0xc1,0x62,0x10,0x84,0xc0,0xf8,0x20,0x30,0x28,0x84,0x40,0x1a,0x25,0x11,0x82,0x42,0x22,0x11,0xf4,0xd9,0xc1,0x02,0x22,0xb2,0x38,0x14,0xc1,0x8e,0x90,0x14,0xc1,0xa2,0x86,0x02,0xc6,0x30,0x31,0x06,0x8c,0x0c,0x26,0x02,0x56,0x9d,0x04,0x0c,0x6a,0xa1,0x03,0x21,0x20,0x68,0x5f,0xe7,0xa9,0x00,0x86,0x85,0x01,0x8f,0xe0,0x08,0xe3,0x00,0xe1,0x02,0xc6,0xfe,0x16,0x23,0xe1,0x13,0x10,0xa4,0x82,0xb1,0x12,0x88,0x00,0xf0,0x91,0xe0,0x6a,0xfd,0x63,0xfc,0x08,0x78,0x18,0xb5,0x5e,0xad,0xfb,0x84,0xa0,0x95,0x48,0xad,0x54,0x4a,0x50,0x4d,0x44,0x6b,0x56,0x0d,0x28,0x45,0x42,0x6a,0x0d,0x38,0x46,0x02,0x55,0xaa,0x35,0x25,0x52,0xac,0x06,0x4b,0x04,0xa8,0x0c,0x94,0x03,0xa0,0x80,0x04,}; -const uint8_t* const _I_DolphinFirstStart8_56x51[] = {_I_DolphinFirstStart8_56x51_0}; - -const uint8_t _I_DolphinOkay_41x43_0[] = {0x01,0x00,0xa0,0x00,0x00,0x0f,0x82,0x3e,0x05,0x38,0xf7,0x80,0x08,0x58,0x08,0x0c,0x02,0x0e,0x05,0x1b,0x00,0x08,0x63,0x00,0x21,0x88,0x00,0x86,0x40,0x02,0x18,0x40,0x08,0x68,0x00,0x21,0x82,0x06,0x88,0x0a,0xf0,0x21,0x39,0x09,0x84,0x02,0x20,0x57,0x09,0x98,0x15,0x67,0xc0,0x54,0xbe,0x81,0x4f,0x01,0xfe,0x02,0x9d,0x03,0xc4,0x20,0x10,0x29,0x7c,0x80,0xa9,0xfe,0x02,0xac,0x14,0x0a,0x77,0xc8,0x58,0x8c,0xf0,0x11,0x51,0x79,0xff,0x61,0x44,0x93,0x81,0x02,0xc4,0x9e,0x60,0xb2,0xf0,0xa0,0x46,0x0c,0x17,0x14,0x99,0x1a,0x07,0x80,0x59,0x49,0x82,0x21,0xc0,0xa4,0x82,0x24,0xb9,0x20,0x88,0x1c,0x47,0xc2,0x07,0x11,0x54,0xa0,0x60,0x53,0xb8,0x0a,0x4b,0xf3,0x03,0x87,0x81,0x4a,0x0d,0xfc,0x1a,0x98,0x68,0xb8,0x01,0x51,0x13,0x15,0xe0,0x82,0x7f,0x8d,0x78,0x38,0xbf,0xff,0xfa,0xb8,0x60,0xbf,0x1b,0xf9,0x50,0x14,0xea,0xe7,0x02,0x02,0x8e,0xac,0x94,0x40,}; -const uint8_t* const _I_DolphinOkay_41x43[] = {_I_DolphinOkay_41x43_0}; - -const uint8_t _I_ArrowDownEmpty_14x15_0[] = {0x01,0x00,0x17,0x00,0xfc,0x41,0xe1,0x10,0x40,0x0c,0xc3,0xe7,0x90,0x19,0x04,0x0a,0x20,0x08,0x10,0x48,0xc4,0x20,0x52,0x08,0x0f,0x02,0x00,}; -const uint8_t* const _I_ArrowDownEmpty_14x15[] = {_I_ArrowDownEmpty_14x15_0}; - -const uint8_t _I_ArrowDownFilled_14x15_0[] = {0x00,0xF8,0x07,0x08,0x04,0xE8,0x05,0x68,0x05,0xA8,0x05,0x68,0x05,0xA8,0x05,0x6F,0x3D,0xA1,0x21,0xFA,0x17,0xF4,0x0B,0xE8,0x05,0xD0,0x02,0x20,0x01,0xC0,0x00,}; -const uint8_t* const _I_ArrowDownFilled_14x15[] = {_I_ArrowDownFilled_14x15_0}; - -const uint8_t _I_ArrowUpEmpty_14x15_0[] = {0x01,0x00,0x18,0x00,0xe0,0x40,0x24,0x10,0x18,0x84,0x0a,0x11,0x04,0x82,0x42,0x20,0x51,0x08,0x0c,0x82,0x1f,0x3c,0x04,0x88,0x06,0x7f,0x10,0x70,}; -const uint8_t* const _I_ArrowUpEmpty_14x15[] = {_I_ArrowUpEmpty_14x15_0}; - -const uint8_t _I_ArrowUpFilled_14x15_0[] = {0x00,0xC0,0x00,0x20,0x01,0xD0,0x02,0xE8,0x05,0xF4,0x0B,0xFA,0x17,0x61,0x21,0xAF,0x3D,0x68,0x05,0xA8,0x05,0x68,0x05,0xA8,0x05,0xE8,0x05,0x08,0x04,0xF8,0x07,}; -const uint8_t* const _I_ArrowUpFilled_14x15[] = {_I_ArrowUpFilled_14x15_0}; - -const uint8_t _I_DolphinReadingSuccess_59x63_0[] = {0x01,0x00,0x19,0x01,0x00,0x1d,0x00,0x0f,0xd2,0x00,0x21,0xe0,0x3f,0xf0,0xf9,0x00,0x40,0xee,0x00,0x11,0x88,0x04,0x0e,0x18,0x11,0x18,0x8c,0x40,0x0e,0x50,0x30,0x10,0xc0,0xa1,0x01,0xe2,0x05,0x14,0x12,0x08,0x33,0x58,0x44,0x08,0x66,0xa1,0xe3,0x01,0x9c,0x83,0x00,0x24,0x11,0x11,0x06,0xc4,0x76,0x20,0x75,0x15,0x99,0x48,0xc0,0xe9,0x0f,0x03,0x95,0xfc,0x86,0x3c,0x09,0x80,0x1c,0x7c,0x00,0x91,0x81,0x48,0x2f,0xc1,0x41,0x8c,0xc0,0x20,0x30,0x1c,0x87,0xfc,0x0e,0x30,0x70,0x70,0x81,0xc7,0xe6,0x07,0x18,0x08,0x1c,0xb9,0x1e,0x38,0x0f,0x02,0x01,0xf0,0x03,0xa0,0xa4,0x7f,0x90,0x30,0x38,0xff,0xe0,0x28,0x21,0xff,0x06,0x44,0x0e,0x46,0xe1,0x01,0x8c,0x03,0x34,0x2f,0x25,0x18,0x80,0xc7,0x2a,0x03,0x2e,0x01,0x3c,0x70,0x12,0xa2,0x39,0x78,0x27,0xe0,0x31,0xea,0x82,0xc4,0x6c,0x31,0xf0,0x78,0xea,0xb0,0x22,0x31,0xfc,0x1a,0xc6,0x01,0x55,0x25,0x88,0xf8,0x4b,0x02,0x1f,0x13,0xe1,0x7f,0x97,0x85,0x15,0x03,0x90,0xf8,0xa0,0x10,0xa1,0xb1,0x0e,0x88,0x00,0x7f,0x0f,0xc0,0x7c,0x57,0x27,0x3c,0xb0,0x7f,0x5f,0xa9,0x1f,0xc0,0x6a,0xc5,0x05,0xc0,0xf0,0x11,0x46,0xac,0x18,0x3f,0xf9,0x54,0x75,0x00,0x73,0x1f,0x0f,0xfe,0xfe,0xc6,0x30,0x01,0xbc,0x48,0x00,0x84,0x82,0x00,0x1b,0x64,0xc0,0x07,0x60,0x03,0xb4,0x70,0x0c,0xbf,0x82,0x31,0x01,0x8d,0x0c,0x40,0x02,0x37,0x08,0x1d,0x74,0x00,0x76,0xa0,0x01,0xdb,0x01,0xfe,0x85,0x8b,0x96,0xaa,0x9b,0x30,0x01,0x6a,0xa3,0x40,0x75,0xaa,0x03,0xdb,0x50,0xbb,0x30,0x01,0x54,0x24,0x25,0xe6,0x51,0x08,0x1f,0x68,0x00,0x7f,0x03,0xf2,0x79,0xc0,0xf4,}; -const uint8_t* const _I_DolphinReadingSuccess_59x63[] = {_I_DolphinReadingSuccess_59x63_0}; - -const uint8_t _I_Down_25x27_0[] = {0x01,0x00,0x46,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x20,0x3f,0x01,0x9f,0xc7,0xff,0x1f,0x01,0xa7,0x87,0xff,0x0f,0x80,0xf0,0x7f,0xf0,0x78,0x0e,0x07,0xff,0x03,0x0b,0x8f,0xfc,0x04,0x30,0x1f,0xf0,0x7c,0xaf,0x80,0x32,0x9c,0x00,0xca,0x20,0x37,0xf0,0x18,0xc0,0xca,0x63,0x01,0x83,0x40,0x38,0x10,0x0f,0xe7,0xfe,0xfe,0x67,0x40,}; -const uint8_t* const _I_Down_25x27[] = {_I_Down_25x27_0}; - -const uint8_t _I_Down_hvr_25x27_0[] = {0x01,0x00,0x3a,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x20,0x3f,0x01,0x9c,0x3e,0x01,0xe0,0x01,0xa4,0x7e,0x01,0xf0,0x80,0x8b,0x47,0xf1,0x01,0x16,0x8f,0xf0,0x2e,0x23,0x11,0x01,0x88,0x04,0xf0,0x60,0x32,0xe3,0x80,0xcb,0xde,0x37,0xf0,0x1a,0x95,0xcc,0xbe,0x66,0x73,}; -const uint8_t* const _I_Down_hvr_25x27[] = {_I_Down_hvr_25x27_0}; - -const uint8_t _I_InfraredArrowDown_4x8_0[] = {0x00,0xFF,0x7E,0x3C,0x18,}; -const uint8_t* const _I_InfraredArrowDown_4x8[] = {_I_InfraredArrowDown_4x8_0}; - -const uint8_t _I_InfraredArrowUp_4x8_0[] = {0x00,0x18,0x3C,0x7E,0xFF,}; -const uint8_t* const _I_InfraredArrowUp_4x8[] = {_I_InfraredArrowUp_4x8_0}; - -const uint8_t _I_InfraredLearnShort_128x31_0[] = {0x01,0x00,0x10,0x01,0x00,0x47,0xfb,0xfe,0x00,0x38,0x38,0x3e,0x20,0x20,0x54,0x84,0x03,0x9f,0xc0,0x06,0x58,0x80,0x3d,0xf2,0x00,0x65,0x90,0x03,0xde,0x90,0x06,0x5a,0x07,0xc0,0x8a,0x70,0x1a,0x04,0x02,0x51,0x80,0x03,0x94,0x02,0x3f,0x40,0x20,0x24,0x0b,0x01,0x00,0x92,0x70,0x35,0x40,0x01,0xe0,0xdf,0xf0,0x10,0x40,0x71,0x58,0x20,0x90,0x88,0x0c,0x4a,0x81,0x55,0x00,0x0f,0x87,0xf7,0x00,0x82,0x43,0x36,0x16,0xdc,0x9c,0x12,0x21,0x01,0x85,0x70,0x3f,0xc1,0xf1,0xf8,0xfc,0x60,0x20,0xf5,0x90,0x40,0xa1,0x34,0x08,0x18,0x7c,0x7e,0x24,0x91,0x07,0x8c,0xc0,0x5e,0x52,0x28,0x14,0x17,0x81,0x01,0x0f,0x8f,0xe7,0xe3,0x03,0x1f,0x8e,0x02,0xdb,0x03,0x8e,0x49,0x20,0x50,0x2e,0x04,0x72,0xbd,0x55,0xdc,0xeb,0xa0,0x7c,0x4f,0x68,0xbc,0x60,0x72,0x40,0x79,0x50,0x23,0x9a,0x6d,0x56,0x66,0x5c,0x0f,0x21,0x78,0x9b,0x04,0x1e,0x28,0x21,0x8e,0x5c,0x43,0xe6,0x2f,0x10,0xf9,0x0b,0xc7,0x04,0x99,0x18,0x06,0xe0,0x7e,0x56,0x32,0x78,0x8f,0xc4,0x08,0x32,0x20,0x79,0x48,0x2b,0x85,0xf2,0xf8,0x83,0xc4,0x5c,0x3f,0x03,0x78,0xd0,0x81,0xe3,0xc0,0xdf,0x9f,0xcb,0xf3,0x04,0xc6,0x7d,0xfb,0xdf,0x34,0x78,0xd0,0x45,0xe5,0x7e,0x4f,0x97,0xe2,0x09,0x80,0x07,0x88,0xbc,0x61,0x00,0xf3,0xd8,0x2f,0xcb,0xe0,0xcf,0x60,0x68,0xd0,0x30,0x15,0xfa,0xac,0x36,0x3f,0x60,0x77,0xb3,0x80,0x5d,0xe6,0x4b,0x20,0x03,0x03,0xc4,0x01,0xd0,0x10,0x7f,0x40,0x81,0xfc,0xa7,0x10,0x06,0x99,0xd0,0x01,0x51,0x00,0x7f,0x48,0x01,0xfd,0xc0,0x43,0x98,0x00,0x8e,0xfe,0x00,0xf0,}; -const uint8_t* const _I_InfraredLearnShort_128x31[] = {_I_InfraredLearnShort_128x31_0}; - -const uint8_t _I_InfraredLearn_128x64_0[] = {0x01,0x00,0xcc,0x01,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x07,0x80,0x3f,0x01,0x07,0x82,0x41,0x21,0x20,0x73,0x00,0x8e,0x82,0x0f,0x00,0xa0,0x01,0x46,0x11,0x00,0x07,0xc0,0x28,0x41,0xe5,0xc8,0xba,0x63,0xa7,0x70,0x6b,0x3d,0xbb,0x99,0x19,0xee,0x68,0x71,0x16,0x3f,0x70,0x3c,0x64,0xf9,0x58,0x25,0x26,0x13,0x91,0xc9,0x64,0xa4,0x99,0x2d,0x06,0x1f,0x29,0x42,0x07,0x8c,0x80,0x1e,0x50,0xff,0x88,0x3c,0x67,0x80,0xf1,0xc1,0x03,0xde,0x03,0x11,0x07,0x8c,0x10,0x1e,0x38,0x40,0x79,0xf0,0x32,0x80,0xf1,0x83,0x58,0x72,0x58,0xc8,0xc6,0x73,0x40,0x3f,0x10,0x78,0x9e,0xf1,0x17,0xe9,0xcf,0x00,0x78,0x03,0xc0,0x1e,0x00,0xf0,0x02,0x44,0x18,0xa3,0x80,0x82,0x32,0x06,0x44,0x0f,0xf0,0x73,0x5d,0xe3,0x92,0x7e,0xcf,0x06,0x3b,0xc3,0xa4,0xdd,0xfc,0xc8,0x35,0xca,0x44,0xa5,0x34,0x5c,0x16,0x92,0x89,0x4a,0x91,0x4a,0x60,0x20,0xf7,0xa4,0x83,0xc6,0x8e,0x0f,0xba,0x88,0x3c,0x68,0x00,0xf7,0x80,0x65,0xe3,0x9c,0x7a,0x6e,0x0a,0x49,0xc3,0xb8,0xc8,0xa4,0xc0,0xf5,0x00,0x08,0x1d,0xc0,0x0e,0x0f,0xf0,0x07,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x2f,0xfb,0xfe,0x00,0x38,0x39,0x97,0xa1,0x00,0xe7,0xf0,0x3b,0x1c,0x00,0xd9,0x00,0x32,0xc8,0x01,0xef,0x48,0x03,0x2d,0x03,0xe0,0x45,0x38,0x0d,0x02,0x01,0x28,0xc0,0x01,0xca,0x01,0x1f,0xa0,0x10,0x12,0x05,0x80,0x80,0x49,0x38,0x1a,0xa0,0x00,0xf0,0x6f,0xf8,0x08,0x20,0x38,0xac,0x10,0x48,0x44,0x06,0x25,0x40,0xaa,0x80,0x07,0xc3,0xfb,0x80,0x41,0x21,0x9b,0x0b,0x6e,0x4e,0x09,0x10,0x80,0xc2,0xb8,0x1f,0xe0,0xf8,0xfc,0x7e,0x30,0x10,0x7a,0xc8,0x20,0x50,0x9a,0x04,0x0c,0x3e,0x3f,0x12,0x48,0x83,0xc6,0x60,0x2f,0x29,0x14,0x0a,0x0b,0xc0,0x80,0x87,0xc7,0xf3,0xf1,0x81,0x8f,0xc7,0x01,0x6d,0x81,0xc7,0x24,0x90,0x28,0x17,0x02,0x39,0x5e,0xaa,0xee,0x75,0xd0,0x3e,0x27,0xb4,0x5e,0x30,0x39,0x20,0x3c,0xa8,0x11,0xcd,0x36,0xab,0x33,0x2e,0x07,0x90,0xbc,0x4d,0x82,0x0f,0x14,0x10,0xc7,0x2e,0x21,0xf3,0x17,0x88,0x7c,0x85,0xe3,0x82,0x4c,0x8c,0x03,0x70,0x3f,0x2b,0x19,0x3c,0x47,0xe2,0x04,0x19,0x10,0x3c,0xa4,0x15,0xc2,0xf9,0x7c,0x41,0xe2,0x2e,0x1f,0x81,0xbc,0x68,0x40,0xf1,0xe0,0x6f,0xcf,0xe5,0xf9,0x82,0x63,0x3e,0xfd,0xef,0x9a,0x3c,0x68,0x22,0xf2,0xbf,0x27,0xcb,0xf1,0x04,0xc0,0x03,0xc4,0x5e,0x30,0x80,0x79,0xec,0x17,0xe5,0xf0,0x67,0xb0,0x34,0x68,0x18,0x0a,0xfd,0x56,0x1b,0x1f,0xb0,0x3b,0xd9,0xc0,0x2e,0xf3,0x25,0x90,0x01,0x81,0xe2,0x00,0xe8,0x08,0x3f,0xa0,0x40,0xfe,0x53,0x88,0x03,0x4c,0xe8,0x00,0xa8,0x80,0x3f,0xa4,0x00,0xfe,0xe0,0x21,0xcc,0x00,0x47,0x7f,0x00,0x78,}; -const uint8_t* const _I_InfraredLearn_128x64[] = {_I_InfraredLearn_128x64_0}; - -const uint8_t _I_InfraredSendShort_128x34_0[] = {0x01,0x00,0x42,0x01,0xfe,0x7f,0xc0,0x07,0x03,0x07,0xc4,0x10,0x0a,0x90,0x20,0x7f,0x83,0xfc,0x04,0x3c,0x01,0xc2,0x7f,0xf8,0x80,0x43,0x9f,0x83,0xca,0x40,0x1f,0x5e,0x27,0x7e,0xab,0x55,0xee,0x83,0xce,0x38,0x0f,0x6d,0x50,0x00,0xa5,0xc0,0xf2,0x89,0x03,0xda,0xfe,0x1f,0x1f,0xa8,0x7c,0x48,0xc3,0x09,0x07,0xb6,0xae,0x54,0x1f,0x19,0xd4,0x08,0x40,0x30,0x5f,0x81,0x1c,0x63,0xfe,0x08,0x1f,0x12,0xbe,0x3f,0x49,0x0e,0x02,0x09,0x58,0x04,0x0c,0xd7,0xf1,0x0f,0x1f,0x8e,0x2b,0x11,0xaa,0x95,0x40,0xa2,0x34,0x08,0x16,0xa0,0x4e,0x32,0xab,0xe4,0x7f,0x89,0x77,0x0b,0x0d,0xd6,0x7f,0x82,0x84,0x50,0x20,0x3d,0x81,0x48,0xcd,0x67,0xd3,0xe1,0xf8,0xc8,0xb4,0x43,0xf1,0xc1,0x62,0x24,0x10,0x1b,0x46,0x80,0x3e,0x3f,0xe9,0xf8,0xfc,0xfa,0xa1,0xf1,0xa4,0x68,0x20,0x13,0x8a,0x00,0x7c,0x67,0xf7,0xe3,0xfa,0x4a,0x81,0xe3,0x40,0x80,0x66,0x38,0x66,0xa1,0xeb,0xdd,0x47,0xec,0x0f,0x2c,0x47,0x0e,0xa9,0x35,0xe9,0xd9,0x47,0xe2,0x1f,0x21,0xf8,0xd2,0x17,0xc3,0x88,0x91,0xeb,0x83,0xe6,0xbf,0x42,0x78,0xc4,0x20,0x10,0x88,0x05,0x5c,0x7e,0x7a,0xe1,0xfa,0x42,0x01,0xe5,0x84,0x1f,0x89,0x7c,0xbf,0xf7,0x7b,0xaf,0xdd,0x3e,0x31,0x10,0xe8,0xc2,0x3f,0x01,0xf1,0x3f,0x98,0x7c,0xa7,0x6a,0xf1,0x07,0x97,0x03,0x5e,0x9f,0x36,0x28,0xf7,0x7f,0xa1,0xf1,0x81,0x03,0xca,0x01,0x56,0x5f,0x9f,0xb8,0x3c,0x3e,0xa7,0xf8,0xc1,0x01,0xe5,0xf0,0x15,0x0f,0x85,0xbe,0x21,0xf1,0x00,0x08,0x7c,0x60,0x04,0xf1,0x77,0x96,0x7e,0x02,0xff,0x10,0x7c,0x00,0x16,0x08,0x05,0x40,0x78,0xa3,0xc4,0x00,0xb2,0x40,0x7b,0x2b,0xc4,0x00,0xb5,0x48,0x78,0x3d,0x70,0x01,0xf7,0x07,0xb4,0x00,0x94,0x23,0xfc,0x01,0x18,0x00,0xff,0x85,0xf3,0xff,0xc0,0xc3,0x0f,0x00,0xf0,0x09,0xce,0xf0,0x03,0x2f,0xc0,0x61,0x3f,0xe0,0xf8,0x00,0x30,0x3f,0xc0,}; -const uint8_t* const _I_InfraredSendShort_128x34[] = {_I_InfraredSendShort_128x34_0}; - -const uint8_t _I_InfraredSend_128x64_0[] = {0x01,0x00,0xe2,0x01,0x00,0x78,0x03,0xc0,0x1e,0x00,0xfe,0x04,0x0e,0x05,0x82,0xd7,0x81,0xca,0x21,0x08,0x01,0x8c,0x10,0x0e,0x54,0x00,0x20,0xe0,0xa4,0x00,0xfb,0xb2,0x4e,0xb0,0xfa,0x0e,0x74,0xc7,0x0f,0x3b,0xce,0x4e,0xec,0xf0,0xe1,0x79,0xe4,0xe9,0x58,0x2d,0x3d,0x4a,0x95,0x41,0x89,0x52,0x31,0x59,0x40,0xfa,0x64,0x01,0xe3,0xa0,0xa9,0x5e,0x81,0xe7,0xf4,0x07,0xcc,0x28,0x1e,0x71,0x40,0x7a,0x58,0x01,0xe4,0x3f,0x1c,0x0c,0x4f,0x11,0x0b,0xb3,0x83,0xcc,0x00,0x94,0x20,0x2a,0x03,0xa0,0x1e,0xd0,0x34,0xdf,0x80,0x3c,0x01,0xe0,0x0f,0x00,0x4c,0xf0,0x17,0x4c,0x81,0xa0,0x18,0x18,0x1f,0x39,0x90,0x6c,0x60,0x27,0x70,0xe9,0x3f,0x67,0x03,0x3c,0x80,0x83,0xde,0x81,0x4a,0x84,0xca,0x68,0xb8,0x2b,0xf0,0x3f,0x29,0x20,0xfe,0xa8,0xe0,0x85,0xf3,0x80,0xa5,0xc3,0xb8,0xf4,0xd8,0x11,0x3e,0x40,0x04,0x1b,0x23,0x7d,0x83,0xcd,0x1f,0x60,0x0f,0x00,0x78,0x03,0x7f,0x9f,0xf0,0x01,0xc0,0xc1,0xf1,0x04,0x02,0xa4,0x08,0x1f,0xe0,0xff,0x01,0x0f,0x00,0x70,0x9f,0xfe,0x20,0x10,0xe7,0xe0,0xf2,0x90,0x07,0xd7,0x89,0xdf,0xaa,0xd5,0x7b,0xa0,0xf3,0x8e,0x03,0xdb,0x54,0x00,0x29,0x70,0x3c,0xa2,0x40,0xf6,0xbf,0x87,0xc7,0xea,0x1f,0x12,0x30,0xc2,0x41,0xed,0xab,0x95,0x07,0xc6,0x75,0x02,0x10,0x0c,0x17,0xe0,0x47,0x18,0xff,0x82,0x07,0xc4,0xaf,0x8f,0xd2,0x43,0x80,0x82,0x56,0x01,0x03,0x35,0xfc,0x43,0xc7,0xe3,0x8a,0xc4,0x6a,0xa5,0x50,0x28,0x8d,0x02,0x05,0xa8,0x13,0x8c,0xaa,0xf9,0x1f,0xe2,0x5d,0xc2,0xc3,0x75,0x9f,0xe0,0xa1,0x14,0x08,0x0f,0x60,0x52,0x33,0x59,0xf4,0xf8,0x7e,0x32,0x2d,0x10,0xfc,0x70,0x58,0x89,0x04,0x06,0xd1,0xa0,0x0f,0x8f,0xfa,0x7e,0x3f,0x3e,0xa8,0x7c,0x69,0x1a,0x08,0x04,0xe2,0x80,0x1f,0x19,0xfd,0xf8,0xfe,0x92,0xa0,0x78,0xd0,0x20,0x19,0x8e,0x19,0xa8,0x7a,0xf7,0x51,0xfb,0x03,0xcb,0x11,0xc3,0xaa,0x4d,0x7a,0x76,0x51,0xf8,0x87,0xc8,0x7e,0x34,0x85,0xf0,0xe2,0x24,0x7a,0xe0,0xf9,0xaf,0xd0,0x9e,0x31,0x08,0x04,0x22,0x01,0x57,0x1f,0x9e,0xb8,0x7e,0x90,0x80,0x79,0x61,0x07,0xe2,0x5f,0x2f,0xfd,0xde,0xeb,0xf7,0x4f,0x8c,0x44,0x3a,0x30,0x8f,0xc0,0x7c,0x4f,0xe6,0x1f,0x29,0xda,0xbc,0x41,0xe5,0xc0,0xd7,0xa7,0xcd,0x8a,0x3d,0xdf,0xe8,0x7c,0x60,0x40,0xf2,0x80,0x55,0x97,0xe7,0xee,0x0f,0x0f,0xa9,0xfe,0x30,0x40,0x79,0x7c,0x05,0x43,0xe1,0x6f,0x88,0x7c,0x40,0x02,0x1f,0x18,0x01,0x3c,0x5d,0xe5,0x9f,0x80,0xbf,0xc4,0x1f,0x00,0x05,0x82,0x01,0x50,0x1e,0x28,0xf1,0x00,0x2c,0x90,0x1e,0xca,0xf1,0x00,0x2d,0x52,0x1e,0x0f,0x5c,0x00,0x7d,0xc1,0xed,0x00,0x25,0x08,0xff,0x00,0x46,0x00,0x3f,0xe1,0x7c,0xff,0xf0,0x30,0xc3,0xc0,0x3c,0x02,0x73,0xbc,0x00,0xcb,0xf0,0x18,0x4f,0xf8,0x3e,0x00,0x0c,0x0f,0xf0,}; -const uint8_t* const _I_InfraredSend_128x64[] = {_I_InfraredSend_128x64_0}; - -const uint8_t _I_Mute_25x27_0[] = {0x01,0x00,0x51,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x20,0x31,0x81,0xc0,0x64,0x38,0x08,0xa4,0x06,0x83,0x40,0x86,0x40,0x70,0x32,0x08,0x20,0x3c,0x63,0xf0,0x60,0x38,0xc0,0xa0,0xa0,0x31,0xc2,0x02,0xc7,0x03,0x48,0x01,0x94,0xc0,0x06,0xc0,0xb3,0x09,0x98,0x6c,0x84,0x68,0x2b,0x21,0x99,0x8e,0xcc,0x86,0x64,0xb3,0x81,0x94,0xc6,0x03,0x06,0x80,0x70,0x20,0x1f,0xcf,0xfd,0xfc,0xce,0x80,}; -const uint8_t* const _I_Mute_25x27[] = {_I_Mute_25x27_0}; - -const uint8_t _I_Mute_hvr_25x27_0[] = {0x01,0x00,0x4a,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x20,0x21,0xfe,0x40,0x7b,0xf7,0xff,0x5c,0x07,0x7f,0xbf,0xf9,0xc0,0x6f,0xfd,0xff,0xd8,0x3c,0x7c,0x1f,0x90,0x38,0xff,0x7f,0x40,0x31,0xbd,0x82,0xc6,0xff,0xb7,0x01,0x97,0x3c,0x06,0xc0,0xb3,0x09,0x98,0x6c,0x84,0x68,0x2b,0x21,0x99,0x8e,0xcc,0x86,0x64,0xb5,0x01,0x89,0x5c,0xcb,0xe6,0x67,0x30,}; -const uint8_t* const _I_Mute_hvr_25x27[] = {_I_Mute_hvr_25x27_0}; - -const uint8_t _I_Power_25x27_0[] = {0x01,0x00,0x54,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x30,0x18,0x80,0x0c,0xa7,0x00,0x35,0xc0,0xce,0x60,0x70,0x1e,0x0c,0xe6,0x0f,0x01,0xf0,0xce,0x21,0xd0,0x1b,0x0c,0xe2,0x18,0x03,0x58,0x80,0x0c,0xa0,0x00,0x39,0xf0,0xc0,0x03,0x63,0xc1,0x80,0x88,0xc7,0x03,0x83,0x15,0x8c,0x07,0xfe,0x02,0x18,0x0d,0xf0,0x76,0x44,0x73,0x01,0x94,0x0c,0xa6,0x30,0x18,0x34,0x03,0x81,0x00,0xfe,0x7f,0xef,0xe6,0x74,}; -const uint8_t* const _I_Power_25x27[] = {_I_Power_25x27_0}; - -const uint8_t _I_Power_hvr_25x27_0[] = {0x01,0x00,0x4b,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x3f,0xff,0x78,0x0c,0xb8,0xe0,0x35,0xbf,0xf1,0xbf,0x90,0x19,0xff,0x1b,0xf1,0x01,0x8f,0xf1,0xfe,0x30,0x1c,0xff,0x1f,0xe6,0x03,0x5f,0x78,0x0c,0xbf,0xe0,0x39,0x8f,0xff,0xc3,0x63,0x3f,0xff,0x08,0xc6,0xff,0x7c,0x15,0x89,0x04,0x7f,0xc0,0x31,0xc1,0x8e,0xc8,0x8e,0x60,0x36,0x2b,0x99,0x7c,0xcc,0xe6,}; -const uint8_t* const _I_Power_hvr_25x27[] = {_I_Power_hvr_25x27_0}; - -const uint8_t _I_Up_25x27_0[] = {0x01,0x00,0x44,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x20,0x3c,0x88,0x00,0xca,0x70,0x03,0x2b,0xe0,0x0c,0xbf,0xc0,0x32,0xff,0x80,0x87,0x03,0xff,0x81,0xc0,0x78,0x3f,0xf8,0x3c,0x07,0xc3,0xff,0x87,0xc0,0x7e,0x3f,0xf8,0xf8,0x0d,0x06,0xfe,0x03,0x78,0x19,0x4c,0x60,0x30,0x68,0x07,0x02,0x01,0xfc,0xff,0xdf,0xcc,0xe8,}; -const uint8_t* const _I_Up_25x27[] = {_I_Up_25x27_0}; - -const uint8_t _I_Up_hvr_25x27_0[] = {0x01,0x00,0x39,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x20,0x3c,0xf7,0x80,0xcb,0x8e,0x03,0x2c,0x18,0x0c,0x80,0x26,0x25,0x18,0x08,0xa4,0x7f,0x90,0x11,0x88,0xfe,0x20,0x31,0xf8,0x07,0xc2,0x03,0x0f,0x80,0x78,0x00,0x68,0x37,0xf0,0x1d,0x95,0xcc,0xbe,0x66,0x73,}; -const uint8_t* const _I_Up_hvr_25x27[] = {_I_Up_hvr_25x27_0}; - -const uint8_t _I_Vol_down_25x27_0[] = {0x01,0x00,0x2c,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x20,0x3f,0x01,0xff,0x07,0xff,0x07,0x01,0xa0,0x5f,0xc0,0x7e,0x03,0x38,0x19,0x4c,0x60,0x30,0x68,0x07,0x02,0x01,0xfc,0xff,0xdf,0xcc,0xe8,}; -const uint8_t* const _I_Vol_down_25x27[] = {_I_Vol_down_25x27_0}; - -const uint8_t _I_Vol_down_hvr_25x27_0[] = {0x01,0x00,0x23,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x20,0x3f,0x01,0xf8,0xb4,0x7f,0x00,0x34,0x0b,0xf8,0x0f,0xc0,0x6e,0x57,0x32,0xf9,0x99,0xcc,}; -const uint8_t* const _I_Vol_down_hvr_25x27[] = {_I_Vol_down_hvr_25x27_0}; - -const uint8_t _I_Vol_up_25x27_0[] = {0x01,0x00,0x2f,0x00,0xfc,0x7f,0xe7,0xf0,0x08,0x24,0x02,0x81,0x00,0x81,0x40,0x30,0x10,0x08,0x08,0x38,0x60,0x20,0x38,0x88,0x00,0xfc,0x06,0xbc,0x1f,0xfc,0x1c,0x06,0x81,0x7f,0x01,0xc1,0x0e,0xa0,0x65,0x31,0x80,0xc1,0xa0,0x1c,0x08,0x07,0xf3,0xff,0x7f,0x33,0xa0,}; -const uint8_t* const _I_Vol_up_25x27[] = {_I_Vol_up_25x27_0}; - -const uint8_t _I_Vol_up_hvr_25x27_0[] = {0x01,0x00,0x28,0x00,0xfc,0x7f,0xe7,0xf0,0x0f,0xe7,0xfe,0xff,0x00,0xff,0x7f,0xff,0xf0,0x00,0x10,0xff,0xe0,0x20,0x38,0xf7,0x80,0xfc,0x06,0xa2,0xd1,0xfc,0x00,0xd0,0x2f,0xe0,0x38,0x21,0xd8,0x0c,0x8a,0xe6,0x5f,0x33,0x39,0x80,}; -const uint8_t* const _I_Vol_up_hvr_25x27[] = {_I_Vol_up_hvr_25x27_0}; - -const uint8_t _I_DoorLeft_70x55_0[] = {0x01,0x00,0x19,0x01,0x00,0x2c,0x32,0x01,0x03,0x04,0x2c,0x18,0x10,0xf0,0x40,0x47,0x82,0x06,0x81,0x03,0xff,0x80,0x08,0x1a,0x20,0x82,0x15,0x28,0x21,0x87,0x82,0x08,0x6f,0xc0,0xb1,0xe6,0x10,0x10,0x8b,0x46,0x20,0x43,0x55,0x8f,0x82,0x10,0x32,0x73,0x0a,0x09,0x89,0x6c,0x1e,0x09,0x00,0x18,0x60,0xf0,0x0c,0x84,0x93,0x82,0x03,0x18,0x0c,0x02,0x1d,0x00,0x90,0x52,0x70,0x50,0x1e,0x00,0x58,0x63,0x90,0x0a,0x06,0x4a,0x09,0x03,0xb0,0x02,0x06,0x70,0x62,0x49,0xf8,0x0c,0x66,0x3f,0xf0,0x41,0x63,0x04,0x43,0x00,0x99,0x60,0x00,0x85,0xc8,0x06,0x14,0xd0,0x80,0x3f,0xc8,0x0d,0xb8,0x10,0x70,0xf8,0x34,0x13,0x03,0x39,0x04,0x1c,0x42,0x19,0xf8,0xa0,0xc2,0x01,0x07,0xef,0x02,0x8c,0x80,0x10,0x9d,0x00,0x43,0xec,0x00,0xa3,0x10,0x04,0x25,0xce,0x19,0xfc,0x88,0x82,0x12,0x0c,0x35,0x10,0x42,0x4c,0xa1,0x90,0x3f,0xc0,0x21,0x22,0x39,0x82,0xc8,0x88,0xd2,0x11,0xf0,0x01,0x88,0xd5,0x18,0xe2,0x08,0x68,0x10,0x0c,0xa8,0x00,0x83,0x81,0xcc,0xd5,0xc3,0x80,0x84,0x82,0x0e,0xcc,0xc0,0x15,0x79,0x02,0x0b,0x98,0xf8,0x11,0x88,0x82,0x0f,0x31,0x19,0x02,0x08,0x2c,0x9f,0x6a,0x1d,0x20,0x41,0x31,0x4c,0x10,0x8d,0x73,0x04,0x23,0xa4,0xc4,0x6c,0xde,0x20,0x42,0xcc,0x01,0x07,0x07,0xff,0x80,0x06,0x3e,0x08,0x38,0x70,0x20,0xa1,0xe0,0x83,0x8e,0x01,0x0c,0xf0,0x73,0x80,0x43,0x70,0x05,0x08,0x00,0x2c,0x04,0xc4,0x46,0x53,0x09,0x98,0x24,0x80,0x65,0x80,0xb0,0xd9,0x84,0x65,0x32,0x06,0x17,0x0f,0x98,0x23,0x63,0xe1,0x88,0xc4,0x08,0x5f,0xc1,0x30,0x9d,0x84,0x4e,0x66,0x94,0x11,0x98,0x75,0x26,0x00,}; -const uint8_t* const _I_DoorLeft_70x55[] = {_I_DoorLeft_70x55_0}; - -const uint8_t _I_DoorLocked_10x56_0[] = {0x01,0x00,0x4e,0x00,0x86,0x40,0x25,0xb0,0x0b,0x6c,0x03,0x9b,0x00,0xc6,0xc0,0x65,0x90,0x10,0x3a,0xc3,0x20,0x31,0xc8,0x04,0xe2,0x01,0x70,0x80,0x78,0x20,0x1c,0x48,0x07,0x22,0x01,0xd0,0x00,0xf0,0x44,0x68,0x90,0x09,0x04,0x02,0x21,0x00,0x84,0x40,0x25,0x80,0x12,0x1e,0x88,0x14,0xc0,0x2e,0x0d,0x11,0xca,0xf8,0x60,0x1c,0x38,0x07,0x1a,0x05,0xcc,0x80,0x72,0x60,0x5c,0x38,0x10,0x1c,0xf9,0x10,0x2e,0x00,0x05,0x60,0x00,0x11,}; -const uint8_t* const _I_DoorLocked_10x56[] = {_I_DoorLocked_10x56_0}; - -const uint8_t _I_DoorRight_70x55_0[] = {0x01,0x00,0x16,0x01,0x81,0xcc,0x01,0x0f,0x60,0x04,0x3f,0x00,0x10,0xf8,0x08,0x0c,0x02,0x05,0x01,0x84,0x02,0x06,0x26,0x0a,0x10,0x8a,0xcc,0xe0,0x1d,0x68,0xe0,0x18,0xab,0xd0,0x0b,0x18,0x10,0x46,0xe6,0x16,0x1e,0x18,0x10,0x46,0xe4,0x28,0x2c,0x98,0x14,0x68,0x00,0x21,0x1d,0x10,0x8c,0x40,0x02,0x0e,0x10,0xa1,0x08,0xc8,0x40,0x42,0x62,0x11,0x94,0x03,0xfd,0xff,0x00,0x0c,0xff,0x0c,0x08,0x28,0x60,0xe4,0xc0,0x85,0x00,0x83,0x00,0x87,0xf1,0x00,0x8c,0x02,0x0b,0x07,0x24,0x84,0xff,0x04,0xc7,0x80,0xa0,0xe4,0xa0,0x81,0x41,0x04,0x17,0x02,0x41,0x49,0x81,0x0e,0x10,0xb2,0xa0,0x82,0x0e,0x9f,0xfc,0x0a,0x62,0xf2,0xc0,0x03,0x92,0xf0,0x08,0x2d,0x78,0x20,0xff,0x02,0x01,0x08,0xae,0x60,0x64,0x38,0x0d,0xb0,0x8d,0x08,0x82,0x11,0x58,0xc4,0x13,0xc0,0x35,0x68,0x62,0x68,0x81,0x09,0x08,0x84,0x40,0x81,0x0d,0x18,0x69,0x10,0x47,0x44,0x66,0x5f,0x21,0xa9,0x29,0x94,0x10,0x2f,0x23,0x53,0x14,0x60,0x42,0x3c,0x08,0xfc,0x02,0x2c,0x62,0x23,0x58,0xd0,0x22,0x00,0x83,0x3e,0x98,0x44,0x43,0x46,0x22,0x30,0x89,0xce,0x01,0x0f,0x70,0x04,0x3f,0x81,0x8a,0x3c,0x21,0xaa,0x70,0x1a,0xe3,0x44,0x1a,0xa6,0x01,0xd2,0x38,0x90,0x8a,0x40,0x20,0xe5,0x96,0x80,0x43,0x81,0x06,0x6b,0x28,0x07,0xf3,0xfe,0x00,0x19,0xf9,0x34,0xc1,0x08,0x8f,0x20,0xf1,0x3e,0x16,0x00,0xa8,0x19,0x00,0x10,0x76,0x03,0xe2,0x3e,0x90,0x45,0x38,0x01,0x42,0x05,0x88,0x44,0x67,0x15,0x70,0x41,0x38,0x04,0x10,0x24,0x03,0x00,0x10,0x20,0x4a,0x46,0xe9,0x46,0xe1,0x04,0x50,0x66,0x40,0x85,0x19,0x98,0x00,0xc0,}; -const uint8_t* const _I_DoorRight_70x55[] = {_I_DoorRight_70x55_0}; - -const uint8_t _I_PassportBottom_128x17_0[] = {0x01,0x00,0x5e,0x00,0x96,0x01,0x97,0xe1,0xff,0x00,0x2e,0x3e,0x68,0x0f,0x5a,0xc5,0x54,0x00,0xb9,0x50,0xfb,0x6a,0x35,0x40,0x05,0xcd,0x4e,0x03,0xfd,0x30,0x0f,0xf8,0x7f,0xa0,0x81,0xfe,0xf9,0x1b,0xfb,0xf3,0x01,0x47,0x66,0x02,0x1b,0x03,0x07,0xe7,0x02,0x0b,0x02,0x07,0xe5,0x82,0x0b,0xf2,0x1c,0xb0,0x01,0x67,0xf0,0x5f,0xd0,0x3f,0x23,0xf0,0x9b,0xc9,0xe5,0x80,0x03,0xd5,0xc0,0x00,0x86,0x01,0xf3,0xe6,0x1e,0x58,0x00,0x36,0xa8,0x06,0xac,0x04,0x30,0x6c,0x30,0xee,0x60,0x1f,0xe0,0x10,0xff,0x0d,0xfb,0x00,}; -const uint8_t* const _I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0}; - -const uint8_t _I_PassportLeft_6x47_0[] = {0x01,0x00,0x1c,0x00,0x9e,0x40,0xa3,0x32,0x59,0x2c,0x66,0x03,0x01,0x82,0xc2,0x62,0x32,0x50,0x16,0xc8,0x60,0x30,0x28,0x24,0x32,0x39,0x3c,0x9e,0x4d,0x25,0x80,0x1a,}; -const uint8_t* const _I_PassportLeft_6x47[] = {_I_PassportLeft_6x47_0}; - -const uint8_t _I_WarningDolphin_45x42_0[] = {0x01,0x00,0xc6,0x00,0x00,0x1c,0x22,0x04,0x05,0x7f,0xfc,0x1e,0x20,0x05,0x1e,0x04,0x02,0x30,0x05,0x29,0x84,0x02,0xc1,0x20,0x02,0x8c,0x22,0x01,0x80,0x02,0x94,0x10,0x32,0x30,0x10,0x10,0x87,0xca,0x84,0x03,0x10,0x42,0x81,0x48,0x28,0x38,0x08,0x04,0x3e,0x01,0x84,0x83,0xe0,0x30,0x11,0x08,0x05,0xa2,0x11,0x40,0xa0,0x4b,0xc6,0xc5,0x40,0xd0,0x56,0xe0,0x10,0x60,0x29,0x54,0xf0,0x10,0x18,0xf0,0x14,0x6b,0xf6,0x0c,0x04,0x3e,0x40,0x05,0x12,0x80,0xc1,0xe4,0x01,0xd2,0xf8,0x40,0xe4,0x18,0x09,0xf4,0x03,0xf1,0x01,0x90,0x40,0x28,0x30,0x0f,0xe4,0x00,0x16,0x24,0x11,0xbf,0x01,0x44,0xee,0x53,0xf0,0x29,0xf0,0x3e,0x02,0x91,0x3b,0x8c,0xc3,0x81,0x13,0x90,0x48,0x20,0x3f,0xf9,0xfc,0x42,0x60,0x05,0x10,0x98,0x81,0x56,0x11,0x38,0x02,0x9c,0x1a,0x31,0x1e,0x02,0x8f,0x02,0x03,0x1c,0x90,0xc0,0x7c,0x02,0xf1,0xce,0x02,0x07,0x01,0x1f,0x80,0x63,0xa8,0x08,0x71,0x3c,0x8e,0x39,0x24,0x40,0x51,0xc7,0x81,0x53,0x0f,0x3c,0x02,0x9d,0x1e,0x38,0x29,0x10,0x29,0x17,0xc8,0x0a,0x32,0x3a,0x00,0x14,0x4b,0xa2,0x05,0x58,0x98,0x15,0x22,0x20,0x54,0x84,0x81,0x50,}; -const uint8_t* const _I_WarningDolphin_45x42[] = {_I_WarningDolphin_45x42_0}; - -const uint8_t _I_KeyBackspaceSelected_16x9_0[] = {0x00,0xFE,0x7F,0xFF,0xFF,0xEF,0xFF,0xE7,0xFF,0x03,0xC0,0xE7,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0x7F,}; -const uint8_t* const _I_KeyBackspaceSelected_16x9[] = {_I_KeyBackspaceSelected_16x9_0}; - -const uint8_t _I_KeyBackspace_16x9_0[] = {0x00,0xFE,0x7F,0x01,0x80,0x11,0x80,0x19,0x80,0xFD,0xBF,0x19,0x80,0x11,0x80,0x01,0x80,0xFE,0x7F,}; -const uint8_t* const _I_KeyBackspace_16x9[] = {_I_KeyBackspace_16x9_0}; - -const uint8_t _I_KeySaveSelected_24x11_0[] = {0x01,0x00,0x1a,0x00,0xff,0x7f,0xc0,0x0d,0xcf,0xb4,0x7c,0xee,0xf6,0xbf,0x6d,0xbe,0xd7,0xe1,0xaf,0xda,0xff,0xbe,0x7c,0xc7,0xcc,0x28,0xa1,0xd1,0xbf,0x80,}; -const uint8_t* const _I_KeySaveSelected_24x11[] = {_I_KeySaveSelected_24x11_0}; - -const uint8_t _I_KeySave_24x11_0[] = {0x01,0x00,0x1e,0x00,0xff,0x7f,0xff,0xf0,0x18,0x06,0x00,0x04,0x53,0x1c,0xbe,0x33,0x13,0x94,0xc9,0x64,0x72,0x99,0xed,0x0e,0x53,0x05,0x19,0xb3,0xe3,0x02,0x8a,0x1d,0x1b,0xf8,}; -const uint8_t* const _I_KeySave_24x11[] = {_I_KeySave_24x11_0}; - -const uint8_t _A_125khz_14_0[] = {0x00,0x80,0x07,0x00,0x08,0x00,0x13,0x00,0x24,0x0E,0x28,0x71,0x28,0x85,0x21,0x01,0x02,0x62,0x02,0x92,0x02,0x92,0x02,0x64,0x02,0x04,0x01,0xF8,0x00,}; -const uint8_t _A_125khz_14_1[] = {0x00,0x80,0x07,0x00,0x08,0x00,0x10,0x00,0x20,0x0E,0x20,0x71,0x20,0x85,0x21,0x01,0x02,0x62,0x02,0x92,0x02,0x92,0x02,0x64,0x02,0x04,0x01,0xF8,0x00,}; -const uint8_t _A_125khz_14_2[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x3a,0x01,0x71,0x80,0x61,0x60,0x30,0x18,0x15,0x8a,0x05,0x92,0x00,0x95,0x92,0x05,0x04,0x80,0xfe,0x20,0x00,}; -const uint8_t _A_125khz_14_3[] = {0x01,0x00,0x1a,0x00,0x00,0x24,0x0e,0x01,0x04,0x87,0x42,0x2e,0x30,0x8c,0x2c,0x06,0x03,0x02,0xb1,0x40,0xb2,0x40,0x12,0xb2,0x40,0xa0,0x90,0x1f,0xc4,0x00,}; -const uint8_t* const _A_125khz_14[] = {_A_125khz_14_0,_A_125khz_14_1,_A_125khz_14_2,_A_125khz_14_3}; - -const uint8_t _A_BadUsb_14_0[] = {0x00,0xFF,0x1F,0x01,0x10,0x01,0x10,0xF1,0x11,0xF9,0x13,0xE9,0x12,0x49,0x12,0xF9,0x13,0xF1,0x11,0x51,0x11,0x01,0x10,0xFF,0x1F,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_1[] = {0x00,0x01,0x10,0x01,0x10,0xE1,0x13,0xFD,0x10,0xF9,0x13,0x01,0x17,0xF9,0x13,0x3D,0x10,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x06,0x0C,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_2[] = {0x00,0x01,0x10,0xF1,0x11,0xF9,0x13,0x59,0x13,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB6,0x0D,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_3[] = {0x00,0xF1,0x11,0xF9,0x13,0x59,0x13,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB4,0x05,0x06,0x0C,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_4[] = {0x00,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB4,0x05,0x04,0x04,0xFC,0x07,0xFC,0x07,0xFE,0x0F,0xFE,0x0F,0x02,0x08,}; -const uint8_t _A_BadUsb_14_5[] = {0x00,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB4,0x05,0x04,0x04,0xFC,0x07,0xFC,0x07,0x04,0x04,0xFC,0x07,0x00,0x00,0xFE,0x0F,0xFE,0x0F,0x02,0x08,}; -const uint8_t _A_BadUsb_14_6[] = {0x00,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB4,0x05,0x04,0x04,0xFC,0x07,0xFC,0x07,0xFE,0x0F,0xFE,0x0F,0x02,0x08,}; -const uint8_t _A_BadUsb_14_7[] = {0x00,0xF1,0x11,0xF9,0x13,0x59,0x13,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB4,0x05,0x06,0x0C,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_8[] = {0x00,0x01,0x10,0xF1,0x11,0xF9,0x13,0x59,0x13,0xF9,0x13,0xE9,0x12,0x19,0x13,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x04,0x04,0xB6,0x0D,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_9[] = {0x00,0x01,0x10,0x01,0x10,0xE1,0x13,0xFD,0x10,0xF9,0x13,0x01,0x17,0xF9,0x13,0x3D,0x10,0xF1,0x11,0x01,0x10,0xFF,0x1F,0x06,0x0C,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t _A_BadUsb_14_10[] = {0x00,0xFF,0x1F,0x01,0x10,0x01,0x10,0xF1,0x11,0xF9,0x13,0xE9,0x12,0x49,0x12,0xF9,0x13,0xF1,0x11,0x51,0x11,0x01,0x10,0xFF,0x1F,0xFE,0x0F,0xFE,0x0F,}; -const uint8_t* const _A_BadUsb_14[] = {_A_BadUsb_14_0,_A_BadUsb_14_1,_A_BadUsb_14_2,_A_BadUsb_14_3,_A_BadUsb_14_4,_A_BadUsb_14_5,_A_BadUsb_14_6,_A_BadUsb_14_7,_A_BadUsb_14_8,_A_BadUsb_14_9,_A_BadUsb_14_10}; - -const uint8_t _A_Bluetooth_14_0[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x08,0x92,0x10,0x94,0x24,0x58,0x28,0x30,0x29,0x30,0x29,0x58,0x28,0x94,0x24,0x92,0x10,0x51,0x08,0x30,0x00,0x10,0x00,}; -const uint8_t _A_Bluetooth_14_1[] = {0x01,0x00,0x1a,0x00,0x88,0x40,0x26,0x10,0x0a,0x8c,0x23,0x25,0x10,0xca,0x49,0x2b,0x12,0x89,0x80,0x04,0x80,0xa2,0x09,0x10,0x68,0x84,0x44,0x2a,0x21,0x91,}; -const uint8_t _A_Bluetooth_14_2[] = {0x01,0x00,0x1a,0x00,0x88,0x40,0x26,0x10,0x0a,0x8c,0x23,0x25,0x10,0xca,0x48,0x2b,0x12,0x09,0x80,0x04,0x80,0xa2,0x09,0x10,0x68,0x84,0x44,0x2a,0x21,0x91,}; -const uint8_t _A_Bluetooth_14_3[] = {0x01,0x00,0x1a,0x00,0x88,0x40,0x26,0x10,0x0a,0x8c,0x03,0x25,0x00,0xca,0x40,0x2b,0x00,0x92,0x00,0x88,0x14,0x41,0x22,0x0d,0x10,0x88,0x82,0x44,0x32,0x20,}; -const uint8_t _A_Bluetooth_14_4[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x94,0x00,0x58,0x00,0x30,0x01,0x30,0x01,0x58,0x00,0x94,0x00,0x92,0x00,0x51,0x00,0x30,0x00,0x10,0x00,}; -const uint8_t _A_Bluetooth_14_5[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x94,0x04,0x58,0x08,0x30,0x09,0x30,0x09,0x58,0x08,0x94,0x04,0x92,0x00,0x51,0x00,0x30,0x00,0x10,0x00,}; -const uint8_t* const _A_Bluetooth_14[] = {_A_Bluetooth_14_0,_A_Bluetooth_14_1,_A_Bluetooth_14_2,_A_Bluetooth_14_3,_A_Bluetooth_14_4,_A_Bluetooth_14_5}; - -const uint8_t _A_Debug_14_0[] = {0x00,0x20,0x01,0xC1,0x20,0x22,0x11,0x24,0x09,0xD9,0x26,0x16,0x1A,0xD8,0x06,0xD8,0x06,0xD6,0x1A,0x19,0x26,0xE4,0x09,0xC2,0x10,0x01,0x20,0x00,0x00,}; -const uint8_t _A_Debug_14_1[] = {0x00,0x20,0x01,0xC0,0x00,0x22,0x11,0x25,0x29,0xD8,0x06,0x16,0x1A,0xD9,0x26,0xD8,0x06,0xD4,0x0A,0x12,0x12,0xEA,0x15,0xC5,0x28,0x02,0x10,0x02,0x10,}; -const uint8_t _A_Debug_14_2[] = {0x00,0x20,0x01,0xC0,0x00,0x20,0x01,0x24,0x09,0xDA,0x16,0x11,0x22,0xDC,0x0E,0xDA,0x16,0xD9,0x26,0x14,0x0A,0xF2,0x13,0xD1,0x22,0x08,0x04,0x06,0x18,}; -const uint8_t _A_Debug_14_3[] = {0x00,0x22,0x11,0xC4,0x08,0x24,0x09,0x25,0x29,0xD9,0x26,0x12,0x12,0xDC,0x0E,0xD8,0x06,0xD8,0x06,0x14,0x0A,0xF4,0x0B,0xD2,0x12,0x19,0x26,0x06,0x18,}; -const uint8_t* const _A_Debug_14[] = {_A_Debug_14_0,_A_Debug_14_1,_A_Debug_14_2,_A_Debug_14_3}; - -const uint8_t _A_FileManager_14_0[] = {0x00,0xFC,0x07,0x04,0x04,0xF4,0x05,0x04,0x04,0xF7,0x05,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; -const uint8_t _A_FileManager_14_1[] = {0x00,0x00,0x00,0x00,0x00,0xFC,0x07,0x04,0x04,0xF7,0x05,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; -const uint8_t _A_FileManager_14_2[] = {0x01,0x00,0x17,0x00,0x00,0x3f,0xfe,0x0f,0x05,0x82,0x7d,0x67,0xf1,0x59,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_3[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x3e,0x01,0x11,0x80,0x7f,0x67,0xf1,0x59,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_4[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x3e,0x01,0x11,0x80,0x7c,0x67,0xf1,0x19,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_5[] = {0x01,0x00,0x0f,0x00,0x00,0x3c,0x3e,0x01,0x11,0x80,0x7f,0xe0,0xf0,0x18,0x40,0x06,0x7f,0xd0,0x70,}; -const uint8_t _A_FileManager_14_6[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x3e,0x01,0x11,0x80,0x7c,0x67,0xf1,0x19,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_7[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x3e,0x01,0x11,0x80,0x7f,0x67,0xf1,0x59,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_8[] = {0x01,0x00,0x17,0x00,0x00,0x3f,0xfe,0x0f,0x05,0x82,0x7d,0x67,0xf1,0x59,0x04,0x34,0x02,0x31,0x08,0x28,0x04,0x61,0x10,0x38,0x47,0xfa,0x0e,}; -const uint8_t _A_FileManager_14_9[] = {0x00,0x00,0x00,0x00,0x00,0xFC,0x07,0x04,0x04,0xF7,0x05,0x05,0x04,0xF5,0x3F,0x15,0x20,0x0D,0x20,0x0D,0x10,0x05,0x10,0x05,0x08,0x03,0x08,0xFE,0x07,}; -const uint8_t* const _A_FileManager_14[] = {_A_FileManager_14_0,_A_FileManager_14_1,_A_FileManager_14_2,_A_FileManager_14_3,_A_FileManager_14_4,_A_FileManager_14_5,_A_FileManager_14_6,_A_FileManager_14_7,_A_FileManager_14_8,_A_FileManager_14_9}; - -const uint8_t _A_GPIO_14_0[] = {0x01,0x00,0x15,0x00,0xa2,0x41,0x00,0x23,0xee,0x87,0x00,0x54,0x16,0x60,0x11,0x09,0x8f,0xfe,0x3f,0x11,0x88,0xd5,0x62,0xa0,0x31,}; -const uint8_t _A_GPIO_14_1[] = {0x01,0x00,0x12,0x00,0xa2,0x41,0x00,0x27,0xee,0x87,0x00,0x54,0x1a,0xbf,0xf8,0xfc,0x46,0x23,0x55,0x8a,0x80,0xc4,}; -const uint8_t _A_GPIO_14_2[] = {0x01,0x00,0x12,0x00,0xa2,0x41,0x00,0x2f,0xee,0x87,0x00,0x54,0x12,0x3f,0xf8,0xfd,0x56,0x2a,0x01,0x18,0x8c,0x44,}; -const uint8_t _A_GPIO_14_3[] = {0x01,0x00,0x11,0x00,0xa2,0x41,0x00,0x37,0xee,0x87,0x00,0x4f,0xff,0x1f,0xaa,0xc5,0x40,0x23,0x11,0x88,0x80,}; -const uint8_t _A_GPIO_14_4[] = {0x01,0x00,0x0d,0x00,0xa2,0x41,0x00,0x3f,0xee,0x87,0x7f,0xe3,0xe0,0x13,0x88,0xc4,0x40,}; -const uint8_t _A_GPIO_14_5[] = {0x01,0x00,0x11,0x00,0xa2,0x41,0x00,0x3b,0xee,0x87,0x00,0x47,0xff,0x1f,0x00,0x8d,0x56,0x2b,0x11,0x88,0x80,}; -const uint8_t _A_GPIO_14_6[] = {0x01,0x00,0x11,0x00,0xa2,0x41,0x00,0x33,0xee,0x87,0x00,0x57,0xff,0x1f,0xaa,0xc5,0x40,0x23,0x11,0x88,0x80,}; -const uint8_t _A_GPIO_14_7[] = {0x01,0x00,0x12,0x00,0xa2,0x41,0x00,0x2b,0xee,0x87,0x00,0x54,0x16,0x7f,0xf8,0xfc,0x46,0x23,0x55,0x8a,0x80,0xc4,}; -const uint8_t* const _A_GPIO_14[] = {_A_GPIO_14_0,_A_GPIO_14_1,_A_GPIO_14_2,_A_GPIO_14_3,_A_GPIO_14_4,_A_GPIO_14_5,_A_GPIO_14_6,_A_GPIO_14_7}; - -const uint8_t _A_Games_14_0[] = {0x01,0x00,0x17,0x00,0x00,0x3c,0x62,0x0d,0xfc,0x87,0xc0,0xa2,0x10,0x99,0x24,0x76,0x54,0x03,0x1f,0x0c,0x86,0x23,0x22,0x02,0x8c,0x1a,0x30,}; -const uint8_t _A_Games_14_1[] = {0x01,0x00,0x1a,0x00,0x00,0x2c,0x62,0x0d,0xfc,0x87,0xc0,0xa2,0x10,0x99,0x24,0x76,0x54,0x03,0x1f,0x0c,0x87,0x23,0x22,0x02,0x8c,0x5a,0x35,0x01,0x90,0x00,}; -const uint8_t _A_Games_14_2[] = {0x00,0x00,0x00,0x00,0x00,0x18,0x06,0xFC,0x0F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x91,0x22,0x89,0x24,0x16,0x1A,0x11,0x22,0x01,0x20,}; -const uint8_t _A_Games_14_3[] = {0x00,0x00,0x00,0x18,0x06,0xFC,0x0F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x91,0x22,0x89,0x24,0x96,0x1A,0x11,0x22,0x11,0x22,0x01,0x20,}; -const uint8_t _A_Games_14_4[] = {0x00,0x18,0x06,0xFC,0x0F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x91,0x22,0x89,0x24,0x16,0x1A,0x11,0x22,0x01,0x20,0x00,0x00,0x00,0x00,}; -const uint8_t _A_Games_14_5[] = {0x00,0x84,0x08,0x18,0x06,0xFD,0x2F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x91,0x22,0x09,0x24,0x16,0x1A,0x01,0x20,0x00,0x00,0x00,0x00,}; -const uint8_t _A_Games_14_6[] = {0x00,0x84,0x08,0x84,0x08,0x19,0x26,0xFD,0x2F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x11,0x22,0x09,0x24,0x06,0x18,0x00,0x00,0x00,0x00,}; -const uint8_t _A_Games_14_7[] = {0x00,0x84,0x08,0x84,0x08,0x85,0x28,0x19,0x26,0xFD,0x2F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x11,0x22,0x09,0x24,0x06,0x18,0x00,0x00,}; -const uint8_t _A_Games_14_8[] = {0x00,0x00,0x00,0x00,0x00,0x84,0x08,0x84,0x08,0x19,0x26,0xFD,0x2F,0x02,0x10,0x09,0x24,0x1D,0x2A,0x09,0x24,0xE1,0x21,0x11,0x22,0x09,0x24,0x06,0x18,}; -const uint8_t* const _A_Games_14[] = {_A_Games_14_0,_A_Games_14_1,_A_Games_14_2,_A_Games_14_3,_A_Games_14_4,_A_Games_14_5,_A_Games_14_6,_A_Games_14_7,_A_Games_14_8}; - -const uint8_t _A_Infrared_14_0[] = {0x01,0x00,0x1a,0x00,0xfc,0x41,0xe0,0xd1,0x88,0x0c,0x83,0xe1,0x03,0x84,0x41,0x01,0x63,0xe0,0x80,0x84,0x4c,0x0a,0x20,0xd1,0x0a,0x88,0x04,0x7f,0xf3,0xf0,}; -const uint8_t _A_Infrared_14_1[] = {0x01,0x00,0x17,0x00,0xfc,0x41,0xe0,0xd1,0x88,0x0c,0x83,0xe1,0x03,0x84,0x41,0x02,0x2f,0xe0,0x80,0x83,0x44,0x2a,0x20,0x11,0xff,0xcf,0xc0,}; -const uint8_t _A_Infrared_14_2[] = {0x01,0x00,0x13,0x00,0xfc,0x41,0xe0,0xd1,0x88,0x0c,0x80,0x23,0x7e,0x08,0x0f,0xc2,0x06,0x15,0x10,0x08,0xff,0xe7,0xe0,}; -const uint8_t _A_Infrared_14_3[] = {0x01,0x00,0x0e,0x00,0x00,0x78,0x00,0x7c,0x10,0x1f,0x84,0x0f,0xf1,0x07,0x00,0x8f,0xfe,0x7e,}; -const uint8_t _A_Infrared_14_4[] = {0x01,0x00,0x0e,0x00,0x00,0x5f,0x82,0x02,0x05,0x5f,0x84,0x0f,0xf1,0x07,0x00,0x8f,0xfe,0x7e,}; -const uint8_t _A_Infrared_14_5[] = {0x01,0x00,0x15,0x00,0x00,0x2f,0xc2,0x07,0x08,0x82,0x01,0x47,0xc1,0x01,0x05,0x98,0x14,0x41,0xa3,0xf8,0x83,0x80,0x47,0xff,0x3f,}; -const uint8_t* const _A_Infrared_14[] = {_A_Infrared_14_0,_A_Infrared_14_1,_A_Infrared_14_2,_A_Infrared_14_3,_A_Infrared_14_4,_A_Infrared_14_5}; - -const uint8_t _A_NFC_14_0[] = {0x00,0x00,0x08,0x00,0x10,0x00,0x12,0x00,0x22,0x42,0x24,0x87,0x24,0x8D,0x24,0x99,0x24,0xF1,0x24,0x62,0x24,0x00,0x22,0x00,0x12,0x00,0x10,0x00,0x08,}; -const uint8_t _A_NFC_14_1[] = {0x01,0x00,0x1a,0x00,0x80,0x42,0x20,0x11,0x00,0x09,0x48,0x28,0x52,0x0c,0x3c,0x83,0x1b,0x20,0xcc,0xc8,0x3e,0x32,0x0b,0x14,0x80,0x1a,0x21,0x34,0x84,0x00,}; -const uint8_t _A_NFC_14_2[] = {0x01,0x00,0x10,0x00,0x00,0x3d,0x0a,0x01,0x87,0x80,0x63,0x60,0x19,0x98,0x07,0xc6,0x01,0x62,0x09,0xc0,}; -const uint8_t _A_NFC_14_3[] = {0x01,0x00,0x16,0x00,0x00,0x24,0x08,0x02,0x34,0x28,0x26,0x1e,0x09,0x8d,0x82,0x66,0x60,0x9f,0x18,0x25,0x8a,0x08,0x0f,0x30,0xb1,0x80,}; -const uint8_t* const _A_NFC_14[] = {_A_NFC_14_0,_A_NFC_14_1,_A_NFC_14_2,_A_NFC_14_3}; - -const uint8_t _A_Passport_14_0[] = {0x00,0xC0,0x00,0x20,0x01,0x20,0x01,0xFE,0x1F,0x01,0x20,0x39,0x2F,0x39,0x20,0x39,0x2F,0x11,0x20,0x39,0x2B,0x45,0x20,0x7D,0x25,0x01,0x20,0xFE,0x1F,}; -const uint8_t _A_Passport_14_1[] = {0x01,0x00,0x0e,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x42,0x00,0xf0,0x4c,0x40,}; -const uint8_t _A_Passport_14_2[] = {0x01,0x00,0x13,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x42,0x90,0x42,0x40,0x24,0x07,0x30,0x0a,0x84,0xc4,}; -const uint8_t _A_Passport_14_3[] = {0x01,0x00,0x14,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0xc8,0x21,0x20,0x12,0x06,0x10,0x05,0x82,0x62,}; -const uint8_t _A_Passport_14_4[] = {0x01,0x00,0x13,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0x80,0x52,0x22,0x0e,0x30,0x0a,0x04,0xc4,}; -const uint8_t _A_Passport_14_5[] = {0x01,0x00,0x18,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0x80,0x52,0x23,0x20,0x84,0xc8,0x20,0xa0,0x12,0x07,0x88,0x4c,0x40,}; -const uint8_t _A_Passport_14_6[] = {0x01,0x00,0x18,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0x80,0x52,0x23,0x20,0x84,0xc8,0x20,0xb2,0x0b,0xe8,0x50,0x82,0x62,}; -const uint8_t _A_Passport_14_7[] = {0x01,0x00,0x1a,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0xc8,0xe7,0x20,0x31,0x90,0x44,0x40,0x65,0x45,0x90,0x5f,0x42,0x84,0x13,0x10,}; -const uint8_t _A_Passport_14_8[] = {0x00,0xC0,0x00,0x20,0x01,0x20,0x01,0xFE,0x1F,0x01,0x20,0x39,0x2F,0x39,0x20,0x39,0x23,0x11,0x20,0x39,0x20,0x45,0x20,0x7D,0x20,0x01,0x20,0xFE,0x1F,}; -const uint8_t _A_Passport_14_9[] = {0x01,0x00,0x1a,0x00,0xe0,0x40,0x24,0x10,0x10,0x08,0xff,0xa3,0xe0,0x41,0x9c,0xcb,0xe7,0x20,0x32,0x88,0x80,0xc6,0x47,0x45,0x90,0x5f,0x42,0x84,0x13,0x10,}; -const uint8_t* const _A_Passport_14[] = {_A_Passport_14_0,_A_Passport_14_1,_A_Passport_14_2,_A_Passport_14_3,_A_Passport_14_4,_A_Passport_14_5,_A_Passport_14_6,_A_Passport_14_7,_A_Passport_14_8,_A_Passport_14_9}; - -const uint8_t _A_Plugins_14_0[] = {0x00,0xE7,0x00,0xA5,0x00,0x99,0x01,0x01,0x02,0x01,0x02,0x81,0x01,0x81,0x0E,0xE7,0x08,0x24,0x18,0x58,0x20,0x40,0x20,0x30,0x18,0x10,0x08,0xF0,0x0F,}; -const uint8_t _A_Plugins_14_1[] = {0x00,0x70,0x0E,0x50,0x0A,0x90,0x19,0x10,0x20,0x10,0x20,0x18,0x18,0x1E,0x08,0x72,0x0E,0x46,0x02,0x88,0x05,0x08,0x04,0x06,0x03,0x02,0x01,0xFE,0x01,}; -const uint8_t _A_Plugins_14_2[] = {0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xE4,0x1C,0xA7,0x14,0x21,0x33,0x23,0x00,0x24,0x00,0x24,0x30,0x23,0x10,0xE1,0x1C,0xFF,0x04,0x00,0x03,0x00,0x00,}; -const uint8_t _A_Plugins_14_3[] = {0x00,0x30,0x00,0x48,0x00,0xCE,0x01,0x02,0x01,0x3E,0x07,0x28,0x05,0xC8,0x0C,0x0E,0x10,0x0A,0x10,0x0E,0x0C,0x08,0x04,0x38,0x07,0x20,0x01,0xC0,0x00,}; -const uint8_t _A_Plugins_14_4[] = {0x00,0x40,0x02,0x70,0x0E,0x10,0x08,0x30,0x18,0xCE,0x21,0x4A,0x21,0x32,0x1B,0x02,0x0C,0x02,0x0C,0x02,0x03,0x02,0x01,0xCE,0x01,0x48,0x00,0x30,0x00,}; -const uint8_t _A_Plugins_14_5[] = {0x00,0x00,0x0C,0x00,0x12,0x80,0x33,0x80,0x00,0xB9,0x01,0x29,0x02,0x66,0x02,0x80,0x01,0x80,0x00,0x60,0x3F,0x20,0x00,0x39,0x00,0x09,0x00,0x06,0x00,}; -const uint8_t _A_Plugins_14_6[] = {0x00,0x00,0x00,0x00,0x06,0x00,0x09,0xF3,0x39,0x52,0x20,0xCC,0x20,0x00,0x01,0x00,0x01,0xC0,0x20,0x40,0x20,0xF3,0x3F,0x12,0x00,0x0C,0x00,0x00,0x00,}; -const uint8_t _A_Plugins_14_7[] = {0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0xB9,0x33,0xA9,0x00,0x66,0x01,0x80,0x02,0x80,0x02,0x60,0x01,0xA0,0x00,0xB9,0x3F,0x09,0x00,0x06,0x00,0x00,0x00,}; -const uint8_t _A_Plugins_14_8[] = {0x00,0x00,0x00,0x39,0x00,0x29,0x00,0x66,0x06,0x80,0x09,0x80,0x39,0x60,0x20,0xE0,0x20,0x39,0x01,0x09,0x01,0xC6,0x20,0x40,0x20,0xC0,0x3F,0x00,0x00,}; -const uint8_t* const _A_Plugins_14[] = {_A_Plugins_14_0,_A_Plugins_14_1,_A_Plugins_14_2,_A_Plugins_14_3,_A_Plugins_14_4,_A_Plugins_14_5,_A_Plugins_14_6,_A_Plugins_14_7,_A_Plugins_14_8}; - -const uint8_t _A_Power_14_0[] = {0x01,0x00,0x17,0x00,0xa0,0x00,0x4a,0x99,0x06,0xa1,0x42,0x00,0x23,0x41,0x88,0x00,0x56,0x05,0x08,0x00,0x8c,0x32,0x0d,0xf0,0x80,0x86,0xc4,}; -const uint8_t* const _A_Power_14[] = {_A_Power_14_0}; - -const uint8_t _A_Settings_14_0[] = {0x00,0x03,0x07,0x87,0x04,0x8E,0x02,0x9C,0x32,0xF8,0x2C,0x50,0x20,0x30,0x1E,0x1E,0x03,0x81,0x04,0xCD,0x09,0x53,0x13,0x50,0x26,0x48,0x2C,0x38,0x18,}; -const uint8_t _A_Settings_14_1[] = {0x00,0x03,0x00,0x87,0x03,0x4E,0x02,0x7C,0x01,0x48,0x19,0x58,0x16,0x30,0x10,0x10,0x0F,0x8F,0x04,0xC0,0x09,0x26,0x13,0x29,0x16,0x28,0x0C,0x24,0x00,}; -const uint8_t _A_Settings_14_2[] = {0x00,0x03,0x00,0x07,0x00,0xDE,0x01,0x24,0x01,0xAC,0x00,0xB8,0x0C,0x30,0x0B,0x10,0x08,0x88,0x07,0xC7,0x09,0x20,0x0B,0x13,0x06,0x14,0x00,0x14,0x00,}; -const uint8_t _A_Settings_14_3[] = {0x00,0x04,0x0C,0x09,0x00,0x13,0x20,0x26,0x20,0x4C,0x00,0xB8,0x00,0xA4,0x00,0x74,0x00,0x94,0x01,0x64,0x01,0x02,0x01,0xF1,0x18,0x08,0x38,0x04,0x30,}; -const uint8_t _A_Settings_14_4[] = {0x00,0x04,0x0F,0x89,0x00,0x93,0x26,0xA6,0x29,0x2C,0x28,0x18,0x24,0x00,0x1C,0x0E,0x00,0x09,0x00,0x05,0x06,0x65,0x0E,0x59,0x1C,0x40,0x38,0x3C,0x30,}; -const uint8_t _A_Settings_14_5[] = {0x00,0x04,0x08,0x05,0x04,0xC3,0x23,0x20,0x10,0xA0,0x09,0x60,0x0A,0x00,0x0A,0x80,0x09,0x80,0x07,0x03,0x07,0x02,0x0E,0x01,0x3C,0x19,0x08,0x16,0x18,}; -const uint8_t _A_Settings_14_6[] = {0x00,0x00,0x14,0x00,0x24,0x00,0x02,0x18,0x31,0xF8,0x08,0x08,0x04,0x68,0x02,0xD8,0x02,0x80,0x06,0xC0,0x0A,0xC0,0x13,0x00,0x26,0x00,0x0C,0x00,0x18,}; -const uint8_t _A_Settings_14_7[] = {0x00,0x00,0x0A,0x00,0x0A,0x0C,0x32,0x1C,0x01,0xB8,0x38,0x78,0x04,0x04,0x02,0x34,0x03,0x4C,0x05,0x40,0x09,0x20,0x13,0xE0,0x26,0x00,0x0C,0x00,0x18,}; -const uint8_t _A_Settings_14_8[] = {0x00,0x00,0x09,0x06,0x05,0x0E,0x25,0x1C,0x19,0xB8,0x00,0x70,0x3C,0x3C,0x02,0x02,0x03,0x9A,0x04,0xA6,0x09,0xA0,0x13,0x90,0x26,0x70,0x0C,0x00,0x18,}; -const uint8_t _A_Settings_14_9[] = {0x00,0x03,0x07,0x87,0x04,0x8E,0x02,0x9C,0x32,0xF8,0x2C,0x50,0x20,0x30,0x1E,0x1E,0x03,0x81,0x04,0xCD,0x09,0x53,0x13,0x50,0x26,0x48,0x2C,0x38,0x18,}; -const uint8_t* const _A_Settings_14[] = {_A_Settings_14_0,_A_Settings_14_1,_A_Settings_14_2,_A_Settings_14_3,_A_Settings_14_4,_A_Settings_14_5,_A_Settings_14_6,_A_Settings_14_7,_A_Settings_14_8,_A_Settings_14_9}; - -const uint8_t _A_Sub1ghz_14_0[] = {0x01,0x00,0x1a,0x00,0x82,0x42,0x20,0x51,0x08,0x4c,0x92,0x0b,0x28,0xea,0xca,0x80,0x22,0x05,0x1e,0x4c,0x93,0x85,0x10,0xe2,0x42,0x38,0x10,0x00,0x0a,0x80,}; -const uint8_t _A_Sub1ghz_14_1[] = {0x01,0x00,0x18,0x00,0x82,0x42,0x20,0x51,0x08,0x4c,0x92,0x0b,0x28,0xe2,0x80,0x48,0x0a,0x3c,0x99,0x27,0x0a,0x21,0xc4,0x84,0x70,0x20,0x00,0x15,}; -const uint8_t _A_Sub1ghz_14_2[] = {0x01,0x00,0x16,0x00,0x82,0x42,0x20,0x51,0x08,0x0c,0x80,0x02,0x3c,0x10,0x09,0x01,0x4f,0x85,0x10,0xe2,0x42,0x38,0x10,0x00,0x0a,0x80,}; -const uint8_t _A_Sub1ghz_14_3[] = {0x01,0x00,0x08,0x00,0x00,0x3f,0x00,0x02,0x40,0x55,0x00,0xc8,}; -const uint8_t _A_Sub1ghz_14_4[] = {0x01,0x00,0x0a,0x00,0x00,0x3f,0x42,0x04,0x01,0x10,0x28,0xf0,0x00,0x38,}; -const uint8_t _A_Sub1ghz_14_5[] = {0x01,0x00,0x12,0x00,0x00,0x1c,0x22,0x09,0x04,0x84,0x75,0x21,0x40,0x11,0x02,0x8f,0x22,0x09,0xc0,0x80,0x00,0x64,}; -const uint8_t* const _A_Sub1ghz_14[] = {_A_Sub1ghz_14_0,_A_Sub1ghz_14_1,_A_Sub1ghz_14_2,_A_Sub1ghz_14_3,_A_Sub1ghz_14_4,_A_Sub1ghz_14_5}; - -const uint8_t _A_Tamagotchi_14_0[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x2A,0x1A,0x19,0x33,0x89,0x32,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t _A_Tamagotchi_14_1[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x1A,0x1B,0xA9,0x32,0x19,0x33,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t _A_Tamagotchi_14_2[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x8A,0x1A,0x19,0x33,0x29,0x32,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t _A_Tamagotchi_14_3[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x4A,0x1B,0xA9,0x32,0x59,0x32,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t _A_Tamagotchi_14_4[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0xAA,0x1A,0x49,0x32,0xA9,0x32,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t _A_Tamagotchi_14_5[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x5A,0x1A,0xA9,0x32,0x49,0x33,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; -const uint8_t* const _A_Tamagotchi_14[] = {_A_Tamagotchi_14_0,_A_Tamagotchi_14_1,_A_Tamagotchi_14_2,_A_Tamagotchi_14_3,_A_Tamagotchi_14_4,_A_Tamagotchi_14_5}; - -const uint8_t _A_U2F_14_0[] = {0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; -const uint8_t _A_U2F_14_1[] = {0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; -const uint8_t _A_U2F_14_2[] = {0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x00,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; -const uint8_t _A_U2F_14_3[] = {0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; -const uint8_t* const _A_U2F_14[] = {_A_U2F_14_0,_A_U2F_14_1,_A_U2F_14_2,_A_U2F_14_3}; - -const uint8_t _A_iButton_14_0[] = {0x00,0x00,0x1C,0x00,0x3E,0x00,0x35,0x80,0x3A,0x78,0x15,0x84,0x0A,0x32,0x05,0x49,0x02,0x85,0x02,0x85,0x02,0x49,0x02,0x32,0x01,0x84,0x00,0x78,0x00,}; -const uint8_t _A_iButton_14_1[] = {0x00,0x00,0x00,0x00,0x38,0x00,0x26,0x80,0x21,0xE0,0x10,0x38,0x0D,0x6C,0x03,0x56,0x01,0x2B,0x01,0x97,0x00,0x4D,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,}; -const uint8_t _A_iButton_14_2[] = {0x01,0x00,0x1a,0x00,0x00,0x24,0xc2,0x01,0x2c,0x80,0x48,0xfb,0x11,0x89,0x64,0x1b,0x2d,0x01,0xa5,0xc0,0x24,0xb0,0x08,0x94,0x02,0x13,0x00,0x83,0x85,0x88,}; -const uint8_t _A_iButton_14_3[] = {0x00,0x00,0x00,0x00,0x38,0x00,0x26,0x80,0x21,0x60,0x18,0x98,0x06,0x04,0x01,0x02,0x01,0x01,0x01,0x81,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,}; -const uint8_t _A_iButton_14_4[] = {0x01,0x00,0x1a,0x00,0x80,0x47,0x20,0x13,0xe8,0x04,0xd7,0x01,0x3a,0xbc,0x45,0x70,0x90,0xa8,0x14,0x16,0x03,0x02,0x00,0xa8,0x08,0x70,0x90,0x0b,0xc4,0x00,}; -const uint8_t _A_iButton_14_5[] = {0x01,0x00,0x1a,0x00,0x00,0x14,0xe2,0x01,0x24,0x80,0x48,0xb0,0x11,0x1f,0x04,0x22,0x31,0x05,0x83,0x40,0xa0,0x20,0x13,0x80,0xf0,0x60,0x13,0xe0,0xc1,0x00,}; -const uint8_t _A_iButton_14_6[] = {0x00,0x00,0x00,0x00,0x38,0x00,0x24,0x00,0x23,0x80,0x20,0xF0,0x10,0x0C,0x0D,0xE2,0x02,0x91,0x01,0x69,0x01,0x15,0x01,0x8D,0x00,0x4D,0x00,0x3E,0x00,}; -const uint8_t* const _A_iButton_14[] = {_A_iButton_14_0,_A_iButton_14_1,_A_iButton_14_2,_A_iButton_14_3,_A_iButton_14_4,_A_iButton_14_5,_A_iButton_14_6}; - -const uint8_t _I_Detailed_chip_17x13_0[] = {0x01,0x00,0x1e,0x00,0xfe,0x5f,0xe0,0x10,0x2c,0x04,0x02,0x23,0x11,0x80,0xe4,0x62,0x50,0x1a,0xff,0xc2,0x03,0x21,0x84,0x00,0x9a,0xbf,0xf4,0x08,0x98,0x5c,0x83,0xa4,0x23,0x20,}; -const uint8_t* const _I_Detailed_chip_17x13[] = {_I_Detailed_chip_17x13_0}; - -const uint8_t _I_Medium_chip_22x21_0[] = {0x01,0x00,0x35,0x00,0xfe,0x7f,0xe1,0xf0,0x28,0x04,0x43,0xf3,0xff,0x93,0xe1,0x6a,0x52,0x8e,0x2f,0xfe,0x51,0x25,0x80,0x4a,0x72,0xb6,0x79,0x55,0x76,0xc1,0x2e,0xaa,0xc0,0x25,0x51,0xdc,0x00,0x14,0x70,0x00,0x56,0xae,0x81,0x47,0x2b,0x7d,0x95,0x07,0x48,0x46,0x42,0x92,0x17,0x90,0xd4,0x87,0x64,}; -const uint8_t* const _I_Medium_chip_22x21[] = {_I_Medium_chip_22x21_0}; - -const uint8_t _I_Pin_arrow_down_7x9_0[] = {0x00,0x1C,0x1C,0x1C,0x1C,0x1C,0x7F,0x3E,0x1C,0x08,}; -const uint8_t* const _I_Pin_arrow_down_7x9[] = {_I_Pin_arrow_down_7x9_0}; - -const uint8_t _I_Pin_arrow_left_9x7_0[] = {0x00,0x08,0x00,0x0C,0x00,0xFE,0x01,0xFF,0x01,0xFE,0x01,0x0C,0x00,0x08,0x00,}; -const uint8_t* const _I_Pin_arrow_left_9x7[] = {_I_Pin_arrow_left_9x7_0}; - -const uint8_t _I_Pin_arrow_right_9x7_0[] = {0x00,0x20,0x00,0x60,0x00,0xFF,0x00,0xFF,0x01,0xFF,0x00,0x60,0x00,0x20,0x00,}; -const uint8_t* const _I_Pin_arrow_right_9x7[] = {_I_Pin_arrow_right_9x7_0}; - -const uint8_t _I_Pin_arrow_up7x9_0[] = {0x00,0x08,0x1C,0x3E,0x7F,0x1C,0x1C,0x1C,0x1C,0x1C,}; -const uint8_t* const _I_Pin_arrow_up7x9[] = {_I_Pin_arrow_up7x9_0}; - -const uint8_t _I_Pin_attention_dpad_29x29_0[] = {0x01,0x00,0x56,0x00,0x80,0x7f,0x20,0xe0,0x31,0x81,0xc6,0x20,0x1c,0x08,0x05,0x82,0x01,0x20,0xa0,0x60,0x20,0x11,0x0f,0x04,0x02,0x03,0x08,0xf8,0x40,0x60,0x50,0x4f,0xc4,0x0e,0x09,0x04,0x05,0x8c,0x12,0x04,0x03,0x18,0x44,0x08,0x42,0x30,0x88,0x08,0x0c,0x62,0x14,0x18,0x05,0x02,0x21,0x61,0x14,0x8c,0x43,0xe3,0x01,0xf8,0x44,0x7f,0x20,0x31,0x89,0x81,0xcc,0x1e,0x61,0x73,0x0f,0x98,0x9c,0xc5,0xe6,0x37,0x31,0xf9,0x91,0xcc,0x9e,0x65,0x73,0x2f,0x99,0x9c,0xcd,0xe6,}; -const uint8_t* const _I_Pin_attention_dpad_29x29[] = {_I_Pin_attention_dpad_29x29_0}; - -const uint8_t _I_Pin_back_arrow_10x8_0[] = {0x00,0x04,0x00,0x06,0x00,0xFF,0x00,0x06,0x01,0x04,0x02,0x00,0x02,0x00,0x01,0xF8,0x00,}; -const uint8_t* const _I_Pin_back_arrow_10x8[] = {_I_Pin_back_arrow_10x8_0}; - -const uint8_t _I_Pin_back_full_40x8_0[] = {0x01,0x00,0x26,0x00,0x82,0x01,0x0e,0x0c,0x02,0x18,0x14,0x03,0xfe,0x04,0x38,0x37,0xc6,0xc3,0x32,0xf7,0x41,0x20,0x59,0x0a,0x54,0xa6,0x01,0xf2,0x88,0xde,0x80,0x83,0x01,0xc8,0x42,0xa5,0x3f,0x88,0x05,0x82,0x65,0x2e,}; -const uint8_t* const _I_Pin_back_full_40x8[] = {_I_Pin_back_full_40x8_0}; - -const uint8_t _I_Pin_cell_13x13_0[] = {0x01,0x00,0x0a,0x00,0xff,0xc7,0xe0,0x31,0x00,0x0f,0x80,0x4c,0x2e,0x20,}; -const uint8_t* const _I_Pin_cell_13x13[] = {_I_Pin_cell_13x13_0}; - -const uint8_t _I_Pin_pointer_5x3_0[] = {0x00,0x04,0x0E,0x1F,}; -const uint8_t* const _I_Pin_pointer_5x3[] = {_I_Pin_pointer_5x3_0}; - -const uint8_t _I_Pin_star_7x7_0[] = {0x00,0x49,0x2A,0x1C,0x7F,0x1C,0x2A,0x49,}; -const uint8_t* const _I_Pin_star_7x7[] = {_I_Pin_star_7x7_0}; - -const uint8_t _I_passport_bad1_46x49_0[] = {0x01,0x00,0xd2,0x00,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x18,0x0f,0xe0,0x0a,0x57,0xff,0xf7,0x9c,0x0a,0x59,0xf8,0x0e,0x60,0x0a,0x56,0xf8,0x05,0x83,0xfc,0x05,0x18,0xbc,0x03,0x01,0xfd,0x02,0x8c,0x2c,0x5a,0x3f,0xa0,0x28,0xc1,0x40,0xa3,0xf4,0x02,0x8c,0x08,0x0a,0x77,0xf8,0x08,0x14,0x7d,0x13,0xfd,0xf9,0x14,0x80,0xab,0xd0,0x9f,0xd7,0xe0,0x10,0x60,0x2a,0x42,0x20,0x1a,0x09,0xfc,0xbe,0x01,0x10,0x02,0xa5,0x9c,0x0a,0x78,0x0e,0x74,0x04,0x0a,0x31,0x7a,0x06,0x7a,0x06,0x05,0x39,0xb0,0x44,0x80,0xa3,0x7e,0x02,0xa5,0xf0,0x0a,0x78,0x0a,0x00,0x14,0xf8,0x13,0xf0,0x29,0xc8,0x07,0x66,0x70,0x11,0xd8,0xea,0xa7,0xf1,0xb2,0x99,0x4c,0x00,0xa9,0xc0,0x9f,0x01,0x4e,0x01,0x3d,0x02,0x8c,0x38,0x0a,0x33,0xa8,0x6c,0x02,0x62,0x05,0x19,0xa0,0x14,0x78,0x00,0x51,0x94,0x01,0x46,0x01,0x03,0x02,0xa4,0x30,0x0a,0x2a,0x02,0x98,0x7c,0x25,0x60,0x52,0xe0,0x43,0xe5,0x80,0x51,0xc0,0x27,0x46,0x51,0x09,0x05,0x88,0xc0,0x66,0x80,0x52,0xfe,0x40,0x27,0x60,0x52,0xf8,0x7f,0xe7,0xa0,0x52,0xe0,0x5f,0xe7,0xc0,0x52,0x80,0x6f,0xe7,0xe0,0x53,0xde,0x01,0x50,0xe2,0x20,0x5f,0x02,0xbf,0xfb,0xfe,0x00,0x28,0xf8,}; -const uint8_t* const _I_passport_bad1_46x49[] = {_I_passport_bad1_46x49_0}; - -const uint8_t _I_passport_bad2_46x49_0[] = {0x01,0x00,0xee,0x00,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x18,0x0f,0xe0,0x0a,0x57,0xff,0xf7,0x9c,0x0a,0x59,0xf8,0x0e,0x60,0x0a,0x5e,0xf8,0xfd,0x83,0xfc,0x05,0x18,0xbd,0x83,0x01,0xfd,0x02,0x8c,0x2f,0x01,0x01,0xfd,0x01,0x46,0x0b,0x00,0x81,0x7d,0x00,0xa3,0x02,0x80,0x41,0x3d,0x13,0xfb,0xfc,0x04,0x0a,0x3d,0x09,0xfe,0xfc,0x88,0x30,0x80,0x2a,0xea,0xa7,0xf5,0xf8,0x04,0x7e,0xa1,0xb5,0x02,0x8f,0x02,0xc1,0xb8,0xbf,0x4f,0xe5,0xf2,0x0e,0x07,0x53,0x03,0x3e,0x02,0x8e,0x9e,0x75,0x80,0x02,0x8e,0x42,0x9d,0x05,0xd1,0x4f,0xa2,0xf5,0x08,0xf4,0x0c,0x0a,0x73,0x69,0x08,0x14,0xab,0x17,0xe0,0x29,0xd4,0x2f,0x80,0x53,0xcc,0x50,0x24,0x22,0x31,0x8b,0xfc,0x08,0x62,0x05,0x29,0x07,0x32,0x0f,0x40,0x9f,0xc5,0xe2,0x13,0x8f,0xc5,0xfe,0x7f,0x1b,0x4f,0x90,0x44,0x40,0xa7,0x00,0x9e,0x81,0x52,0x75,0x1d,0x80,0x43,0x80,0xa3,0x34,0x86,0xc0,0x26,0x20,0x54,0xe0,0x01,0x46,0x51,0x0b,0x01,0x8c,0x0c,0x0a,0x90,0xc0,0x2a,0x4c,0x3e,0x12,0xb0,0x28,0xcc,0x38,0x10,0xf9,0x64,0x24,0x3a,0x29,0xd1,0x94,0x01,0x47,0x00,0x30,0x19,0xa0,0x14,0x60,0x1f,0xd8,0x04,0xec,0x0a,0x5f,0xaf,0xfc,0xf4,0x0a,0x5f,0x4b,0xfc,0xf8,0x0a,0x5a,0x8d,0xfc,0xfc,0x0a,0x54,0x00,0x2a,0x60,0x37,0x40,0x53,0x80,0x2e,0x44,0x0a,0x7a,0x00,0x2e,0x7f,0xbf,0xe0,0x02,0x8f,0x80,}; -const uint8_t* const _I_passport_bad2_46x49[] = {_I_passport_bad2_46x49_0}; - -const uint8_t _I_passport_bad3_46x49_0[] = {0x01,0x00,0x07,0x01,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x18,0x0f,0xc0,0x0a,0x57,0xff,0xf7,0xbc,0x0a,0x59,0xf8,0x0f,0x40,0x0a,0x56,0xf8,0x04,0xe0,0x0a,0x51,0x78,0x07,0x1b,0xfc,0x05,0x18,0x5c,0x02,0x03,0xfd,0x02,0x8c,0x37,0x01,0x00,0xfd,0x01,0x46,0x15,0x40,0x80,0x7d,0x27,0xf7,0xf8,0x48,0x14,0xf7,0xf0,0x80,0x28,0xfa,0x00,0xa5,0x20,0x80,0x72,0x27,0xf5,0xf8,0x80,0x14,0x76,0x00,0x52,0x9f,0xc0,0x2f,0xd3,0xf9,0x7e,0x82,0x81,0xc0,0xc8,0xcf,0xa5,0xf6,0x0d,0x3c,0xe3,0x20,0x05,0x1d,0x05,0x32,0x4b,0xa0,0x9f,0x45,0xec,0x11,0xc9,0x18,0x14,0xe6,0x94,0x10,0x29,0xd7,0x00,0xa9,0x62,0x02,0x9f,0x02,0x83,0x41,0x11,0x88,0x14,0x77,0xf2,0x00,0x29,0x48,0x39,0x92,0x7a,0x84,0xfe,0x27,0x10,0x9c,0x7e,0x2f,0xf3,0xf8,0xea,0x78,0x68,0x18,0x09,0xf4,0x7c,0x0a,0x27,0x21,0x9e,0xc6,0xd5,0x65,0x01,0x9d,0x44,0xe0,0x10,0xe8,0x04,0x0a,0x69,0x63,0x80,0x4c,0x60,0x10,0x49,0xa6,0x0e,0x03,0xc0,0x80,0x42,0x25,0x10,0x38,0x34,0x02,0x06,0x05,0x28,0x44,0x02,0x19,0x10,0x02,0x8c,0x42,0x01,0x30,0xf8,0x4b,0xe0,0x71,0x48,0x07,0x02,0x3f,0x2c,0x05,0x8e,0x02,0x03,0x00,0x94,0x43,0xc2,0x22,0x30,0x19,0xa5,0xc4,0x0a,0x3f,0xc8,0x04,0xef,0x02,0x3c,0x16,0xe8,0xcf,0x60,0x31,0xc0,0xe8,0xdf,0xe7,0xd0,0x1b,0x01,0x34,0x77,0xf3,0xf8,0x08,0x88,0xb7,0x80,0x51,0x80,0x10,0x87,0x40,0x05,0x22,0x10,0xd8,0x00,0xa5,0x0a,0x05,0x88,0x74,0x41,0x64,0x05,0x7f,0xf7,0xfc,0x00,0x51,0xf0,}; -const uint8_t* const _I_passport_bad3_46x49[] = {_I_passport_bad3_46x49_0}; - -const uint8_t _I_passport_bottom_128x18_0[] = {0x01,0x00,0x54,0x00,0x99,0x01,0x97,0xf1,0xff,0x00,0x2e,0x1c,0x1e,0xdf,0xc0,0x7b,0x63,0xe6,0xc0,0xfe,0x9e,0x03,0xfa,0x70,0x0f,0xe9,0x80,0x7f,0xc1,0xfd,0x04,0x37,0xf7,0xc9,0x1d,0xb8,0x08,0x4c,0x04,0x1f,0xb0,0x58,0x10,0x3f,0x38,0x00,0xfe,0xb0,0x41,0x7e,0x44,0x96,0x00,0x2c,0xfe,0x0b,0xfa,0x07,0xe4,0x7e,0x13,0x79,0x1d,0xce,0x02,0x03,0xc0,0x80,0x7c,0xf9,0x83,0xb9,0x80,0x40,0xc0,0x43,0x06,0xc3,0x0e,0xe6,0x01,0xfe,0x01,0x0f,0xf2,0x06,0x90,0xd0,}; -const uint8_t* const _I_passport_bottom_128x18[] = {_I_passport_bottom_128x18_0}; - -const uint8_t _I_passport_happy1_46x49_0[] = {0x01,0x00,0x09,0x01,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7f,0xff,0x87,0xe0,0x00,0xa7,0xf1,0xbf,0x85,0x04,0x0a,0x30,0xec,0x07,0xe4,0x0a,0x37,0xf8,0x0c,0x03,0xec,0x05,0x1d,0xf8,0x98,0x7d,0x00,0x51,0xaf,0x81,0x47,0xa0,0x05,0x19,0x78,0x14,0xa0,0x73,0xf8,0xb8,0x14,0x74,0x1f,0xc9,0xf0,0x14,0xa4,0x10,0x39,0xec,0x2c,0x0a,0x3c,0x08,0x04,0xe8,0x0a,0x52,0x00,0x28,0xc1,0x7c,0x10,0x08,0x87,0x82,0x77,0x05,0xfc,0x40,0xe1,0x1f,0x80,0x28,0xff,0x20,0x70,0x4f,0xe4,0xf6,0x07,0xfe,0x80,0xc0,0xbf,0xd3,0xe8,0x1e,0x7a,0x0f,0x00,0xbf,0xcf,0xe0,0x74,0xe8,0x46,0x03,0x7e,0x05,0x19,0x70,0xbc,0x7b,0xe0,0x51,0x8a,0x40,0x3c,0x1e,0xf0,0x28,0xc4,0x20,0x1f,0x0f,0xb8,0x14,0xff,0x1f,0xb9,0xf9,0xa8,0x60,0x3f,0xcf,0xc8,0x14,0xff,0xde,0x70,0x29,0x61,0xb0,0xf9,0xf0,0x29,0x12,0x06,0xfd,0x3e,0x02,0x8f,0x82,0x0f,0xf8,0x9c,0x81,0x44,0x80,0x3e,0x09,0xb8,0x14,0x94,0x43,0x2b,0x80,0xcc,0x20,0xc0,0x71,0x94,0x40,0x69,0x10,0x90,0x29,0xe2,0x21,0x00,0x51,0x9b,0x01,0x4f,0xc0,0x23,0x1c,0x24,0x43,0xf5,0x1f,0x17,0x88,0x14,0x7e,0x1e,0x31,0xd8,0xe0,0xa4,0x18,0x02,0x99,0x01,0x46,0x01,0xfa,0x02,0x8e,0x06,0x80,0x05,0x6f,0xa4,0xff,0x03,0x80,0xc0,0x01,0x4a,0x82,0x04,0x18,0x08,0x14,0xb8,0x10,0x18,0x0f,0xa2,0x7f,0x21,0x02,0x8c,0x08,0x0a,0x31,0x10,0x28,0xc1,0x3a,0x13,0xf8,0x6f,0x82,0x07,0x18,0x02,0x8c,0x0c,0x0a,0x3e,0x0d,0x00,0xbc,0x7e,0x0b,0x31,0xb3,0xcf,0xff,0xdf,0xf0,0x01,0x47,0xc0,}; -const uint8_t* const _I_passport_happy1_46x49[] = {_I_passport_happy1_46x49_0}; - -const uint8_t _I_passport_happy2_46x49_0[] = {0x01,0x00,0x16,0x01,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7f,0xff,0x87,0xe0,0x00,0xa7,0xf1,0xbf,0x85,0x04,0x0a,0x30,0xec,0x07,0x84,0x0a,0x37,0xf8,0x0c,0x03,0xbe,0x05,0x1d,0xfc,0xfb,0x81,0xa0,0x02,0x8f,0x7f,0x83,0x21,0xa4,0x43,0xe7,0xf2,0xf8,0x06,0x4a,0xa1,0xf3,0x9f,0x45,0xe0,0x10,0xcc,0x8c,0x32,0x7b,0x17,0xb8,0x42,0x30,0x50,0x39,0xd4,0x2f,0x19,0x25,0xe1,0x40,0x26,0x90,0xb8,0x15,0x1a,0x40,0x05,0x18,0x2f,0x86,0x89,0x18,0xf0,0x4d,0xe0,0xbf,0x98,0x2c,0x13,0xf1,0x3b,0xc2,0xff,0x20,0xb0,0x2f,0xe4,0xf7,0x07,0xfe,0x82,0xc0,0x7f,0xd3,0xec,0x1e,0x7b,0x8f,0x00,0xbf,0xcf,0xf0,0x74,0xc9,0xc6,0x03,0x7f,0x3f,0x81,0xc8,0x60,0x1c,0x0e,0xf8,0x14,0x62,0xd0,0x0f,0x07,0xbc,0x0a,0x31,0x88,0x07,0xc3,0xee,0x05,0x18,0x84,0x03,0xf1,0xfb,0x9f,0x9a,0x86,0x03,0xfc,0xfc,0x81,0x4f,0xfd,0xe7,0x02,0x96,0x1b,0x0f,0x9f,0x02,0x97,0xe2,0x07,0x7e,0x9f,0x01,0x47,0xc1,0x07,0xfc,0x4c,0x40,0xa2,0x40,0x1f,0x04,0xbc,0x0a,0x4a,0x21,0x95,0xc0,0x66,0x10,0x60,0x38,0xca,0x20,0x34,0x88,0x48,0x14,0xf1,0x10,0x80,0x28,0xcd,0x80,0xa7,0xe0,0x9c,0xc0,0x70,0x91,0x0f,0xd4,0x7c,0x5e,0x20,0x51,0xf8,0x78,0xc7,0x63,0x82,0x90,0x60,0x0a,0x64,0x05,0x18,0x07,0xe8,0x0a,0x38,0x1a,0x00,0x15,0xbe,0x93,0xfc,0x0e,0x03,0x00,0x05,0x2a,0x08,0x10,0x60,0x20,0x52,0xe0,0x40,0x60,0x3e,0x89,0xfc,0x84,0x0a,0x30,0x20,0x28,0xc4,0x40,0xa3,0x04,0xe8,0x4f,0xe1,0xbe,0x04,0x88,0x81,0x46,0x06,0x05,0x1f,0x06,0x80,0x5e,0x3f,0x08,0x3c,0x02,0xcf,0x3f,0xff,0x7f,0xc0,0x05,0x1f,}; -const uint8_t* const _I_passport_happy2_46x49[] = {_I_passport_happy2_46x49_0}; - -const uint8_t _I_passport_happy3_46x49_0[] = {0x01,0x00,0x23,0x01,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7f,0xff,0x81,0xe0,0x00,0xa7,0xfc,0xbf,0xff,0x00,0xa3,0x7f,0x85,0xe0,0x3e,0x60,0x51,0xdf,0xc1,0x38,0x1e,0xc0,0x28,0xd7,0xe0,0x52,0x0e,0x98,0x14,0x65,0xf0,0x28,0x86,0x92,0x1f,0x3f,0x8b,0xc0,0xa1,0x14,0x8f,0x9c,0xfa,0x2f,0x04,0x84,0x64,0x21,0x93,0xd8,0x5f,0xf2,0x6b,0xa0,0x81,0xce,0xa1,0x70,0x2a,0x37,0x82,0x05,0x34,0x82,0xfe,0x70,0x92,0x08,0x24,0xd3,0x1b,0x04,0x82,0xc4,0x7d,0x13,0x7c,0xbf,0xca,0x0b,0x0d,0xfc,0x4e,0xf4,0x7f,0xa8,0x2c,0x0f,0xf9,0x3d,0xe1,0xe7,0xa0,0xf0,0x1f,0xf4,0xfb,0x07,0x8e,0xe3,0xc0,0x2f,0xf3,0xfc,0x0d,0xd2,0x71,0x80,0xdf,0x81,0x46,0x73,0x00,0xe0,0x77,0xe7,0xf0,0x18,0x9c,0x03,0xc1,0xef,0x02,0x8c,0x7a,0x01,0xf0,0xfb,0x81,0x46,0x21,0x00,0xfc,0x7e,0xe7,0xf0,0x38,0x04,0x07,0xf9,0xf9,0x9f,0xc1,0x40,0xa3,0xfe,0xf3,0xcf,0xe1,0x30,0x0c,0x36,0x1f,0x3f,0x3f,0x88,0x85,0x86,0x07,0x7e,0x9f,0x48,0x45,0x03,0x07,0xfc,0x4c,0x68,0x2a,0xa1,0xbf,0xf8,0x25,0xf4,0x30,0x28,0xa8,0x86,0x57,0x47,0x98,0x41,0x80,0xe3,0x28,0x96,0xd2,0x04,0xa2,0x05,0x18,0xce,0x22,0x10,0x05,0x19,0xb4,0xc4,0x0a,0x5e,0x09,0xcd,0x87,0x09,0x10,0xfd,0x47,0xe7,0xdc,0x10,0x28,0xfc,0x3c,0x66,0x51,0xc1,0x48,0x30,0x05,0x31,0x02,0x94,0x03,0xf4,0x05,0x1c,0x0d,0x00,0x0a,0xdf,0x40,0x28,0xe0,0x30,0x00,0x52,0xa0,0x81,0x06,0x02,0x05,0x2e,0x04,0x06,0x03,0xe8,0x9f,0xc8,0x40,0xa3,0x02,0x02,0x8c,0x44,0x0a,0x30,0x4e,0x84,0xfe,0x1b,0xe0,0x81,0xc6,0x00,0xa3,0x03,0x02,0x8f,0x83,0x40,0x95,0x1f,0x84,0x1e,0x01,0x67,0x9f,0xff,0xbf,0xe0,0x02,0x8f,0x80,}; -const uint8_t* const _I_passport_happy3_46x49[] = {_I_passport_happy3_46x49_0}; - -const uint8_t _I_passport_left_6x46_0[] = {0x01,0x00,0x1b,0x00,0x9e,0x40,0xa3,0x32,0x59,0x2c,0x66,0x03,0x01,0x82,0xc2,0x62,0x32,0x50,0x16,0xc8,0x60,0x30,0x28,0x34,0x3a,0x3d,0x3e,0x9d,0x4c,0x80,0x14,}; -const uint8_t* const _I_passport_left_6x46[] = {_I_passport_left_6x46_0}; - -const uint8_t _I_passport_okay1_46x49_0[] = {0x01,0x00,0xcc,0x00,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x1b,0xfc,0x00,0x0a,0x78,0xff,0xff,0xe0,0x0a,0x57,0x38,0x07,0x9c,0x0a,0x50,0xc8,0x06,0x60,0x0a,0x37,0xf8,0x1c,0x02,0xc0,0x05,0x1d,0xf8,0xb4,0x70,0x13,0xef,0xfd,0x7c,0x68,0x53,0xdf,0xfc,0xbc,0x0a,0x53,0xaf,0xfc,0x5c,0x0b,0x13,0x4f,0xfc,0x2c,0x0b,0x12,0x8f,0xfc,0x14,0x0a,0xdf,0x08,0x0c,0xc3,0xff,0x02,0x80,0x7a,0x20,0x60,0x53,0xfa,0x41,0xc0,0xa7,0x12,0x87,0xc8,0x00,0xa5,0x92,0x02,0xa7,0xc8,0x0b,0x5e,0x28,0x58,0x14,0xe0,0x90,0xc0,0x29,0xfa,0x20,0xe0,0x51,0x1d,0x8c,0x42,0x10,0x05,0x38,0x44,0x40,0x0a,0x38,0x58,0x78,0x30,0x40,0xa3,0x7d,0x29,0x94,0x82,0xff,0x06,0x02,0x9e,0x7e,0x02,0x88,0x10,0x28,0xdb,0xd1,0xc4,0x05,0x13,0xe1,0x50,0x00,0xa2,0x76,0x29,0x00,0x15,0x22,0x00,0x51,0x3e,0x14,0x38,0x0a,0x7c,0x01,0x28,0xc8,0x3c,0xb0,0xf9,0xe0,0x64,0xa3,0x7f,0x05,0xf8,0x8a,0x50,0x0a,0x4b,0x83,0x02,0x8f,0x7e,0x01,0xe0,0x2a,0x0c,0x81,0xbc,0x41,0x81,0x2c,0x8f,0x83,0xfe,0x11,0x2f,0xff,0xbe,0x3e,0x05,0x40,0xb0,0x81,0x4c,0x74,0x20,0x52,0x15,0x1c,0x83,0xfc,0x23,0x10,0x00,0xc7,0xc0,}; -const uint8_t* const _I_passport_okay1_46x49[] = {_I_passport_okay1_46x49_0}; - -const uint8_t _I_passport_okay2_46x49_0[] = {0x01,0x00,0xe5,0x00,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x1b,0xfe,0x00,0x0a,0x78,0x7b,0xff,0xf0,0x0a,0x57,0x9c,0x77,0x8c,0x0a,0x37,0xfc,0x34,0x07,0x38,0x05,0x1d,0xfd,0x06,0x01,0x60,0x02,0x8d,0x7e,0x41,0x00,0xc0,0x4f,0xbf,0xf2,0xf8,0x80,0xd0,0x67,0xbf,0xf8,0xb8,0x14,0xa7,0x40,0x51,0x84,0x01,0x4e,0x17,0x0c,0x02,0x8c,0xd3,0xff,0x05,0x82,0x01,0x5e,0x51,0xff,0x81,0x40,0xbf,0x10,0x30,0x29,0xc1,0x20,0x93,0x00,0x29,0x7c,0xa1,0x20,0x51,0xff,0x40,0xfd,0x31,0x39,0x85,0xfe,0x03,0x1c,0x8a,0xc4,0xe4,0x17,0xf8,0x2f,0x83,0x2b,0x17,0x90,0x6f,0xf0,0x90,0x0f,0xa8,0x16,0xbc,0xa0,0x52,0x84,0x40,0x61,0x51,0x20,0x29,0xfd,0xa3,0xe0,0x52,0x80,0x46,0xa1,0x02,0x91,0x80,0xf8,0x21,0x31,0x00,0x28,0xe0,0x63,0xf0,0x80,0x28,0xff,0xef,0xca,0xc2,0x90,0x4f,0xe0,0x68,0x21,0x02,0x8f,0x7c,0x12,0x20,0x52,0x97,0x81,0x52,0x2e,0x05,0x1a,0x00,0x14,0x61,0x61,0xb2,0x00,0x8c,0x14,0x0a,0x31,0x80,0x2a,0x41,0x80,0xa7,0xc0,0x80,0x81,0x47,0xcb,0x03,0x9e,0x06,0x4a,0x37,0xfc,0x1b,0x08,0xa5,0x00,0xa4,0x35,0x20,0x29,0x10,0x47,0xc1,0x0f,0x26,0x93,0x90,0x43,0x02,0x59,0x1f,0x07,0xfc,0x22,0x5f,0xff,0x7c,0x7c,0x0a,0x81,0x61,0x02,0x98,0xe8,0x40,0xa4,0x2a,0x39,0x07,0xf8,0x46,0x20,0x01,0x8f,0x80,}; -const uint8_t* const _I_passport_okay2_46x49[] = {_I_passport_okay2_46x49_0}; - -const uint8_t _I_passport_okay3_46x49_0[] = {0x01,0x00,0x06,0x01,0xff,0x7f,0xc0,0x05,0x1f,0x02,0x1f,0xfe,0x7e,0x02,0x2c,0x00,0x14,0xfb,0xf7,0xff,0xe0,0x14,0xa4,0xf8,0x0f,0x18,0x14,0xaf,0x30,0x0c,0xe0,0x14,0x6f,0xf8,0x68,0x05,0xa0,0x0a,0x3b,0xf8,0x0c,0x07,0x11,0x3e,0xff,0xd7,0xe0,0x10,0x28,0x44,0xf7,0xff,0x2f,0x02,0x8c,0x12,0x75,0xff,0x8b,0xc0,0x20,0x80,0x52,0x85,0x81,0x4a,0x68,0x05,0x28,0x44,0x08,0x0a,0x30,0x50,0x29,0x4a,0x00,0xa5,0xfc,0x81,0x81,0x4e,0x05,0x06,0x98,0x01,0x4b,0xf3,0x04,0x02,0x8f,0xfb,0x07,0x04,0x84,0xcc,0x2f,0xf0,0x1c,0xee,0x2a,0x15,0x28,0x02,0x8f,0x86,0xe4,0x05,0x1d,0xfe,0x03,0x01,0x52,0x02,0xa0,0x2c,0x64,0x80,0x52,0xc5,0x43,0x80,0xa7,0x07,0x87,0x81,0x4a,0x01,0xff,0x83,0xc8,0xb7,0xf0,0x08,0x0c,0x3a,0x09,0x22,0x14,0x94,0x16,0x11,0x21,0xbf,0xe0,0x6f,0xf0,0x40,0x28,0xff,0xef,0xd1,0x45,0x60,0xc8,0x67,0xf0,0x38,0x58,0x7c,0x64,0x5d,0xfe,0x04,0x18,0x0a,0x33,0xc9,0x7e,0x82,0x03,0x40,0x80,0x48,0x22,0xf5,0x08,0x00,0x14,0xa1,0x60,0x51,0x90,0x40,0x26,0x10,0x59,0x44,0x02,0x21,0x00,0x94,0x01,0x4a,0x1d,0x00,0x92,0x01,0x47,0x81,0x01,0x02,0x8f,0x96,0x57,0x3c,0x1a,0x8c,0x8a,0x36,0x8d,0x10,0x29,0x2b,0x04,0x00,0x52,0x15,0xc0,0x80,0x07,0x00,0x41,0x18,0x07,0x82,0x1f,0x80,0x92,0x37,0x88,0x30,0x32,0x9f,0xff,0x83,0xfe,0x12,0x19,0x97,0xff,0xdf,0x1f,0x02,0x8c,0x90,0x0a,0x30,0xf0,0x28,0xae,0x47,0xde,0x3a,0x12,0x68,0xb8,0xc8,0x00,0x32,0x0f,0xf0,0x8c,0x40,0x03,0x1f,}; -const uint8_t* const _I_passport_okay3_46x49[] = {_I_passport_okay3_46x49_0}; - -const uint8_t _I_BatteryBody_52x28_0[] = {0x01,0x00,0x45,0x00,0xe0,0x7f,0x3f,0xe0,0x02,0x87,0xf0,0x21,0xe0,0xc3,0x84,0x50,0x39,0xbf,0xff,0x27,0xfe,0xf3,0x09,0xe0,0x42,0x81,0xab,0x0d,0x03,0x1c,0x2b,0xfc,0x0d,0x48,0x55,0xdc,0x1a,0x90,0x8f,0x18,0x6d,0x41,0xaa,0x1b,0x71,0x4b,0x0d,0xd4,0x1b,0xe0,0xdf,0x1b,0xd5,0xfc,0x1a,0xa5,0x36,0x06,0xac,0x20,0xa7,0xe0,0xdc,0xa5,0x7c,0x7c,0xb7,0xff,0xb4,0x21,0x5c,0xcb,0xc6,}; -const uint8_t* const _I_BatteryBody_52x28[] = {_I_BatteryBody_52x28_0}; - -const uint8_t _I_Battery_16x16_0[] = {0x01,0x00,0x12,0x00,0x00,0x1e,0x02,0x03,0xc0,0x81,0xc8,0x20,0x80,0x11,0xd0,0x41,0x40,0x72,0x11,0x10,0xda,0x80,}; -const uint8_t* const _I_Battery_16x16[] = {_I_Battery_16x16_0}; - -const uint8_t _I_FaceCharging_29x14_0[] = {0x01,0x00,0x28,0x00,0xa0,0x00,0x86,0x05,0x60,0x01,0x8c,0x0e,0x61,0x00,0xc0,0x40,0x63,0x10,0x0e,0x04,0x03,0xf9,0x00,0xf0,0x41,0xc0,0x66,0x13,0xb8,0x40,0x94,0xc0,0x07,0x04,0x82,0x00,0xc6,0x11,0x02,0x01,0x8f,0xc2,0x03,0x00,}; -const uint8_t* const _I_FaceCharging_29x14[] = {_I_FaceCharging_29x14_0}; - -const uint8_t _I_FaceConfused_29x14_0[] = {0x01,0x00,0x30,0x00,0xc0,0x00,0x46,0x1f,0x38,0x80,0xd0,0x22,0x14,0x48,0x0c,0x82,0x0f,0x52,0x80,0xe8,0x21,0x14,0xa0,0x18,0xc2,0xa6,0x59,0x19,0x24,0x27,0x09,0x48,0xa1,0x41,0x2f,0x12,0x4c,0x0c,0x0c,0x51,0x1f,0xc8,0x78,0x0c,0x7f,0xd1,0xf0,0x18,0xc3,0xa3,0x00,0x74,}; -const uint8_t* const _I_FaceConfused_29x14[] = {_I_FaceConfused_29x14_0}; - -const uint8_t _I_FaceNopower_29x14_0[] = {0x01,0x00,0x24,0x00,0x00,0x1f,0x02,0x01,0x60,0x01,0xa7,0x80,0x02,0x57,0xe0,0x48,0xc3,0xe7,0xd0,0x0c,0x04,0x3c,0x39,0x1f,0x88,0x18,0x0c,0x61,0x90,0x60,0x18,0xff,0x82,0x44,0x03,0x38,0x74,0x38,0x2c,0x80,}; -const uint8_t* const _I_FaceNopower_29x14[] = {_I_FaceNopower_29x14_0}; - -const uint8_t _I_FaceNormal_29x14_0[] = {0x01,0x00,0x1e,0x00,0x00,0x1c,0xf2,0x01,0x80,0x83,0xd7,0xa0,0x1c,0x08,0x5d,0xf8,0x06,0x30,0xf0,0x1b,0x84,0xcc,0x41,0x10,0x88,0x10,0x0e,0x62,0x10,0x10,0x18,0xf8,0x00,0x42,}; -const uint8_t* const _I_FaceNormal_29x14[] = {_I_FaceNormal_29x14_0}; - -const uint8_t _I_Health_16x16_0[] = {0x01,0x00,0x12,0x00,0x00,0x2f,0x02,0x03,0x40,0x00,0x95,0xe2,0x1f,0x08,0x84,0x00,0xc4,0x12,0x60,0xf1,0x0c,0xb8,}; -const uint8_t* const _I_Health_16x16[] = {_I_Health_16x16_0}; - -const uint8_t _I_Temperature_16x16_0[] = {0x01,0x00,0x12,0x00,0x00,0x1e,0x02,0x01,0x40,0x80,0x80,0x66,0x41,0x02,0xf0,0x40,0xc0,0x23,0xc0,0x80,0x86,0xd4,}; -const uint8_t* const _I_Temperature_16x16[] = {_I_Temperature_16x16_0}; - -const uint8_t _I_Voltage_16x16_0[] = {0x01,0x00,0x1a,0x00,0x00,0x24,0x0a,0x01,0x03,0xc0,0x40,0x78,0x10,0x1f,0x04,0x03,0xe1,0x07,0xc0,0x40,0xc0,0xe3,0xc0,0x80,0x58,0x20,0x12,0x00,0xd3,0x00,}; -const uint8_t* const _I_Voltage_16x16[] = {_I_Voltage_16x16_0}; - -const uint8_t _I_RFIDBigChip_37x36_0[] = {0x01,0x00,0x6e,0x00,0x83,0x01,0x0f,0xcd,0xff,0x00,0x0c,0x1e,0x24,0x08,0x28,0x47,0x24,0x12,0x51,0x39,0x28,0x24,0xa2,0x91,0x5e,0x07,0xab,0xfe,0x04,0x1c,0x04,0xaa,0x01,0x15,0x02,0x28,0x4c,0x81,0x2c,0x04,0x4e,0x05,0xfc,0x08,0x35,0x59,0x06,0x02,0x81,0x15,0xca,0xe4,0x26,0xf2,0x10,0x70,0xd7,0x66,0x11,0x70,0x70,0xd4,0x20,0x14,0x10,0x70,0xc7,0x68,0x13,0x70,0x70,0xd4,0x28,0x10,0x10,0x4a,0x84,0xc6,0x80,0x13,0x10,0xe8,0xd0,0x03,0xa2,0x27,0x19,0xf0,0x9c,0x46,0x28,0x3b,0x42,0xcf,0x96,0x6a,0xd4,0x13,0x6f,0x2a,0x2c,0xa2,0x90,0x54,0x59,0xfe,0x52,0xa7,0x02,0x4f,0x9f,0xf1,0x52,0x60,}; -const uint8_t* const _I_RFIDBigChip_37x36[] = {_I_RFIDBigChip_37x36_0}; - -const uint8_t _I_RFIDDolphinReceive_97x61_0[] = {0x01,0x00,0x87,0x01,0x00,0x0f,0xfa,0x3e,0x04,0x28,0x08,0x2d,0x78,0x10,0x1f,0x00,0x24,0x70,0x01,0x86,0x98,0x00,0x86,0x0c,0x0c,0x88,0x60,0x08,0x63,0x10,0x0a,0x00,0x31,0xa0,0x40,0x21,0x90,0x03,0x04,0x1a,0x5a,0x08,0x50,0xe9,0x01,0x23,0x20,0x07,0x88,0x30,0xc5,0xa6,0x03,0x10,0x61,0xfc,0x0a,0xa2,0x2d,0x48,0x0c,0x82,0x20,0x04,0x18,0x40,0x40,0x42,0x44,0x37,0x28,0x80,0x30,0xbc,0x94,0xd0,0x62,0x4f,0x20,0x91,0x08,0x44,0x12,0x01,0x17,0xe6,0x40,0x42,0x45,0x00,0xa1,0x03,0x08,0xa8,0x31,0x41,0x88,0x83,0x0f,0x03,0x08,0x06,0x1c,0x1f,0xa1,0x01,0x84,0x1f,0x8a,0x31,0x09,0x0c,0xa5,0x40,0x86,0x30,0x98,0x46,0x02,0x48,0x0c,0x40,0xc9,0x61,0x00,0xe2,0x0c,0x18,0x88,0x65,0xb8,0x85,0x51,0x06,0x21,0x34,0x83,0x23,0x44,0x06,0x29,0x1c,0xb4,0x94,0xf8,0x05,0x19,0x12,0x20,0xc2,0x40,0xb4,0xa8,0x18,0xa9,0xb5,0x9b,0x48,0x28,0x05,0xa1,0x06,0x22,0xd4,0xa3,0x7e,0x05,0x98,0xe0,0x62,0x0c,0xf6,0x86,0xf8,0x16,0x63,0x42,0x06,0x0b,0xa1,0x60,0xfe,0x06,0xe8,0xcf,0x23,0x0d,0x53,0x00,0x14,0x0f,0xe0,0xea,0x28,0xa0,0x31,0xa0,0x3f,0x08,0x18,0x10,0x45,0xa2,0x11,0x20,0x01,0xf4,0x3f,0xe0,0x81,0x84,0x02,0x94,0x18,0xb0,0xc0,0x63,0xc6,0x3f,0xe0,0x31,0x87,0x03,0x1e,0x11,0x3c,0x80,0x47,0xc1,0x91,0x18,0x80,0x58,0x30,0x0e,0x01,0x00,0x30,0xbc,0x47,0xc3,0x05,0x06,0x3c,0x52,0x00,0xe4,0x20,0xcc,0x80,0x04,0x4d,0x00,0x83,0x73,0x08,0x01,0x8f,0xa2,0x0c,0xa1,0xe1,0xa0,0x62,0x16,0x0c,0xac,0x04,0x14,0xd0,0x30,0x08,0x80,0x31,0xb8,0x10,0x27,0x89,0x03,0x1e,0x81,0x05,0xe0,0x01,0x04,0x1e,0x40,0x04,0xd0,0x1c,0x85,0x6a,0x20,0xc7,0xa8,0x02,0x84,0xd2,0x34,0x00,0x63,0x6c,0x11,0xe2,0x4b,0x10,0x63,0xd6,0x20,0x16,0xa9,0x80,0x32,0x35,0x90,0x0e,0xa5,0x04,0x19,0x15,0x48,0x06,0xa3,0x07,0x01,0x06,0x3c,0xa8,0x84,0x30,0xf8,0x10,0x31,0xe2,0xa5,0xc1,0x8f,0x7f,0x2b,0xe9,0xa8,0xa0,0x5f,0x60,0x04,0x21,0x00,0x29,0x98,0x74,0x1f,0xa8,0x0a,0x39,0xc0,0x05,0xf5,0x83,0xb0,0xa0,0x00,0x3e,0xaf,0xfc,0x1c,0x19,0x3d,0x01,0xfb,0xaa,0xd3,0x3c,0x0c,0xaa,0x06,0x54,0x19,0x50,0x0c,0xd0,0x32,0xe2,0x05,0xf1,0x00,0x4c,0x20,0x19,0xe0,0xc9,0x7d,0x08,0x33,0xc0,0x04,}; -const uint8_t* const _I_RFIDDolphinReceive_97x61[] = {_I_RFIDDolphinReceive_97x61_0}; - -const uint8_t _I_RFIDDolphinSend_97x61_0[] = {0x01,0x00,0x8d,0x01,0x00,0x0f,0xfa,0x3e,0x04,0x2a,0x00,0x2d,0x78,0x10,0x1f,0x04,0x04,0x0a,0x38,0x00,0x62,0xcc,0x00,0x43,0x06,0x06,0x44,0x30,0x04,0x31,0x80,0x31,0x07,0x48,0x00,0x50,0x20,0x10,0xc8,0x01,0x64,0x0c,0x1d,0x04,0x28,0x24,0x83,0xd2,0x81,0x04,0xc4,0x18,0x42,0xc3,0x01,0x90,0x30,0xbe,0x05,0x51,0x29,0xa0,0x74,0x60,0x80,0xc1,0x84,0x0b,0x44,0x5e,0x43,0x73,0x82,0x41,0x20,0x1e,0x4a,0x68,0x31,0x27,0x90,0x48,0x84,0x20,0x18,0x31,0x7e,0x64,0x06,0x20,0x0c,0x2a,0x14,0x12,0x40,0x0c,0x28,0xa0,0xc4,0x41,0x87,0x81,0x17,0x08,0x30,0xa0,0xfd,0x08,0x0c,0x20,0xfc,0x38,0x08,0xc4,0x24,0x32,0x95,0x02,0x18,0xc2,0x61,0x18,0x09,0x20,0x31,0x03,0x25,0x84,0x1d,0x88,0x30,0x62,0x21,0x96,0xe2,0x44,0x22,0x00,0xc2,0x26,0xa0,0x64,0x68,0x80,0xc4,0x33,0x9e,0x92,0x9f,0x00,0xa3,0x48,0x24,0x00,0xc4,0x40,0xa4,0xa8,0x18,0xa9,0xb5,0x9b,0x48,0x28,0x05,0xa1,0x06,0x22,0xd4,0xa3,0x7e,0x05,0x98,0xe0,0x4f,0x22,0xcf,0x58,0x6f,0x80,0x10,0x34,0x24,0x31,0x3a,0x52,0x0f,0xe0,0x03,0x0c,0xf1,0xee,0x2d,0x63,0x00,0x0c,0x0f,0xe0,0x13,0x28,0xa0,0x31,0xa0,0x3f,0x08,0x18,0x10,0x45,0xa2,0xe3,0x40,0x00,0xf4,0x3f,0xe1,0xa1,0x84,0x02,0x94,0x18,0xb0,0xc0,0x63,0xc6,0x3f,0xe0,0x31,0x87,0x03,0x1e,0x11,0x3c,0x80,0x47,0xc1,0x90,0x56,0x1b,0x06,0x01,0xc0,0x20,0x06,0x17,0x88,0xf8,0x60,0xa0,0xc7,0x31,0x8a,0x58,0x60,0xe1,0x99,0x00,0x08,0x9a,0x01,0x06,0xd9,0x10,0x03,0x1f,0x44,0x19,0x43,0xc3,0x40,0xc4,0x2c,0x19,0x58,0x08,0x29,0xa0,0x60,0x0c,0xf2,0x00,0x27,0x02,0x05,0x20,0x06,0x4d,0x02,0x0b,0xc0,0x02,0x08,0x3c,0x80,0x09,0xa0,0x39,0x0a,0xd4,0x41,0x8f,0x50,0x05,0x09,0xa4,0x5b,0x4d,0x00,0xd8,0x23,0xc4,0x96,0x20,0xc7,0xac,0x40,0x2d,0x53,0x00,0x64,0x6b,0x20,0x1d,0x4a,0x08,0x32,0x2a,0x90,0x0d,0x46,0x0e,0x02,0x0c,0x79,0x51,0x08,0x61,0xf0,0x20,0x63,0xc5,0x4b,0x83,0x1e,0xfe,0x57,0xd3,0x51,0x40,0xbe,0xc0,0x08,0x42,0x00,0x53,0x30,0xe8,0x3f,0x50,0x14,0x73,0x80,0x0b,0xeb,0x07,0x61,0x40,0x00,0x7d,0x5f,0xf8,0x38,0x32,0x7a,0x03,0xf7,0x55,0xa6,0x78,0x19,0x54,0x0c,0xa8,0x32,0xa0,0x19,0xa0,0x65,0xc4,0x0b,0xe2,0x00,0x98,0x40,0x33,0xc1,0x92,0xfa,0x10,0x67,0x80,0x08,}; -const uint8_t* const _I_RFIDDolphinSend_97x61[] = {_I_RFIDDolphinSend_97x61_0}; - -const uint8_t _I_RFIDDolphinSuccess_108x57_0[] = {0x01,0x00,0xe7,0x01,0x00,0x0f,0x03,0xff,0x1f,0x06,0xd4,0xe2,0x01,0xe0,0x06,0xd4,0x18,0x04,0x30,0x30,0x64,0x60,0x20,0x20,0x31,0x86,0x03,0x62,0x80,0x03,0x28,0x80,0x36,0x24,0x00,0x36,0x00,0x28,0x5c,0xc3,0xe6,0x00,0x58,0x40,0xec,0xc1,0xb1,0x04,0x02,0x19,0x24,0x80,0x0b,0x02,0x02,0x40,0x37,0xc4,0x8c,0x2e,0x40,0x6f,0x93,0x8b,0x81,0x07,0x06,0xdc,0xc2,0x38,0x66,0x50,0x6a,0xe2,0x27,0xe0,0xd2,0xfc,0x08,0x09,0x0c,0x9c,0x4b,0x98,0x34,0xa0,0xe1,0xd5,0x06,0x8f,0x92,0xc2,0x05,0x1e,0x42,0xe1,0x81,0xa3,0xe2,0xf0,0xbc,0x4c,0x1a,0xff,0x2f,0x9b,0x80,0xd8,0xca,0x05,0x1f,0x97,0xfd,0xf8,0x60,0xd2,0x01,0x1e,0x00,0x1a,0x5c,0x00,0x08,0xc9,0xc1,0xab,0x40,0xf9,0x83,0x46,0x61,0x00,0xd8,0x4a,0x81,0xab,0xa0,0xf3,0x5f,0xc6,0x05,0x58,0x8a,0xa4,0x09,0x76,0x21,0xb1,0xf2,0x83,0x4f,0x5d,0x1a,0x01,0x8c,0x90,0x1a,0x31,0x0d,0x07,0xa9,0x16,0x50,0x0a,0xac,0x34,0xba,0x42,0xa1,0x88,0x50,0x23,0xaa,0x72,0xe0,0x6a,0xa1,0x4a,0x32,0x39,0x88,0x6c,0x60,0xc7,0x82,0xb0,0x55,0x60,0xa2,0x92,0x80,0xc0,0x43,0x63,0x03,0x25,0x96,0xe3,0x54,0x33,0x18,0xc4,0x90,0x22,0x21,0x81,0x81,0x03,0x4a,0xa9,0x55,0x7a,0x17,0xf3,0x82,0x9f,0x6d,0x5e,0xa9,0xb6,0x50,0x38,0x70,0x35,0x70,0x15,0x5a,0xa9,0xb8,0xa3,0x46,0x12,0x06,0x9f,0x83,0x54,0x8a,0x28,0x80,0x34,0xfc,0x08,0x93,0xaa,0xc7,0x40,0x83,0x83,0x81,0xd3,0xa1,0xd1,0x08,0x84,0x0c,0x24,0x3f,0xed,0x54,0x18,0x26,0x50,0x20,0xd9,0x42,0x21,0x90,0x4c,0x07,0xff,0xae,0x52,0x20,0x6a,0xc4,0x23,0x1f,0x88,0x3f,0xf0,0x1a,0x45,0x31,0xe7,0x03,0x4a,0x41,0xe0,0x69,0x0f,0xc2,0x1e,0x0d,0x19,0x80,0x48,0xa2,0x10,0xc5,0x68,0xdf,0x0a,0x82,0xb9,0x28,0x22,0x2c,0xe3,0x0a,0xd1,0x2b,0x0f,0x00,0x3c,0x22,0x91,0x53,0x9c,0x50,0x1a,0x30,0x08,0x39,0x1c,0x60,0x6d,0x12,0x3d,0x8c,0xc2,0x51,0x00,0x17,0x0c,0xe2,0x01,0xff,0x83,0x84,0xc6,0x40,0xb0,0x19,0x84,0xd0,0x1a,0x5c,0x08,0x1f,0xf8,0x8c,0x50,0x43,0x08,0xce,0x2d,0x06,0x71,0x5f,0x17,0xfe,0x12,0xdf,0x20,0x69,0x55,0x01,0xa6,0x00,0x18,0x40,0xa4,0x80,0x63,0x3c,0xb5,0x03,0x56,0x08,0x8b,0x20,0x10,0xcf,0x03,0x62,0x08,0x20,0x00,0x94,0xc6,0x01,0x70,0x01,0x0c,0xe8,0x36,0x20,0xd3,0xe0,0x00,0xcb,0x10,0x02,0x19,0xf3,0x9c,0x41,0xa3,0x15,0x31,0x90,0x00,0x70,0xc0,0x21,0xdd,0x86,0xc4,0x78,0x3e,0xa3,0x71,0xe0,0x30,0x20,0x31,0xbe,0x86,0xc4,0x1a,0x35,0x40,0x20,0x8d,0x89,0x28,0x5b,0xa0,0xd9,0xea,0x3d,0x44,0x42,0x87,0x83,0x48,0x36,0x49,0xe1,0xa0,0x75,0x67,0x8d,0x41,0x54,0x14,0x03,0xf5,0x2a,0x06,0x96,0x03,0x54,0xc4,0x14,0xd0,0x83,0x4a,0xfb,0x35,0x06,0x90,0x38,0x4e,0x46,0xb4,0x10,0xd9,0x81,0x49,0x72,0x40,0x01,0x0a,0x95,0xd4,0x36,0x20,0xd7,0x55,0x10,}; -const uint8_t* const _I_RFIDDolphinSuccess_108x57[] = {_I_RFIDDolphinSuccess_108x57_0}; - -const uint8_t _I_SDQuestion_35x43_0[] = {0x01,0x00,0x67,0x00,0xf8,0x7f,0xc0,0x03,0x03,0xfc,0x01,0x0a,0x0f,0x38,0xa4,0xe4,0xa4,0x80,0x4f,0x0c,0x20,0x13,0xc0,0x9f,0x80,0x02,0x15,0xfe,0x00,0x04,0x29,0xfc,0x03,0xfd,0x07,0xfa,0x47,0xe7,0xdf,0xc8,0x3f,0xea,0x1f,0x7f,0xfc,0x41,0xff,0xb8,0xff,0xf8,0x10,0x7f,0xe0,0x4e,0xef,0x86,0x08,0x68,0x33,0xf1,0x10,0xff,0x3f,0xf1,0xf1,0x60,0x81,0x06,0x1e,0x36,0x10,0x20,0xe1,0xc0,0x87,0xc7,0x02,0x0f,0xd3,0xff,0xe3,0x02,0x0f,0xe8,0x08,0x7f,0xd0,0x21,0x89,0xc4,0x08,0x9f,0x70,0x21,0x9a,0x08,0x08,0xc1,0x89,0x02,0x20,0x62,0x40,0x8f,0xfe,0x68,0x98,}; -const uint8_t* const _I_SDQuestion_35x43[] = {_I_SDQuestion_35x43_0}; - -const uint8_t _I_Cry_dolph_55x52_0[] = {0x01,0x00,0xe8,0x00,0x00,0x0f,0xe3,0xff,0x01,0x03,0x1f,0xfb,0xff,0x0f,0x02,0x96,0x02,0x0f,0x00,0x9f,0x01,0x8b,0xc0,0x12,0x1f,0x80,0x18,0xae,0x00,0x21,0xe0,0x07,0x0a,0x30,0x0a,0x28,0x18,0x08,0x61,0x80,0x62,0x83,0x00,0x90,0x14,0x61,0x02,0x0c,0x16,0x00,0x76,0x60,0x66,0x98,0x0b,0x04,0x90,0x60,0x66,0xb0,0x00,0x48,0x0d,0x21,0x21,0x03,0x30,0x74,0x40,0xd3,0x80,0x03,0x34,0x04,0xc0,0x52,0x00,0x32,0xc7,0xa0,0x18,0x80,0x31,0x80,0x07,0xe1,0x01,0x37,0x18,0x50,0x80,0xc2,0x92,0x10,0x31,0xe8,0x23,0xe9,0x63,0x86,0x54,0x3f,0xe0,0xe1,0x0d,0x96,0x83,0xfc,0x06,0x40,0x69,0x6c,0x3c,0x60,0xd2,0xfc,0xc0,0x60,0x58,0x48,0x0c,0x1b,0x81,0x08,0x14,0x9c,0x1a,0x81,0x04,0x03,0x46,0x80,0x0c,0x50,0x26,0x21,0xc1,0x94,0x26,0x14,0x27,0x8a,0x40,0xc0,0xc2,0xe7,0x26,0x40,0x81,0x86,0xc0,0x6b,0x28,0x64,0x0f,0x01,0x10,0x4e,0x14,0x60,0x0c,0x29,0x02,0x48,0x8b,0x5c,0x45,0x22,0x01,0x10,0x31,0x3a,0x4c,0x0c,0x34,0x06,0xf1,0xd8,0x00,0xc5,0x1a,0x64,0x94,0x0c,0xc0,0x37,0x52,0x20,0x81,0x84,0x26,0x3e,0x88,0x0c,0x38,0x28,0x54,0x0e,0xac,0x1f,0xe1,0x3f,0x06,0x96,0x82,0x7e,0x29,0x4a,0xaf,0xfd,0x76,0x30,0x3a,0x41,0x14,0x7f,0xd0,0xf8,0x78,0x18,0xaa,0x9f,0xd4,0xe0,0x83,0x4f,0xf5,0xf7,0x38,0x0b,0x9c,0x6a,0x1f,0x5b,0x5c,0x00,}; -const uint8_t* const _I_Cry_dolph_55x52[] = {_I_Cry_dolph_55x52_0}; - -const uint8_t _I_Attention_5x8_0[] = {0x00,0x0E,0x0A,0x0A,0x0A,0x0E,0x04,0x00,0x0E,}; -const uint8_t* const _I_Attention_5x8[] = {_I_Attention_5x8_0}; - -const uint8_t _I_Background_128x11_0[] = {0x01,0x00,0x70,0x00,0xff,0x40,0x40,0xc9,0xe0,0xff,0x80,0x06,0x1e,0x08,0x38,0x0c,0x0c,0x1e,0x93,0x00,0x19,0x46,0x01,0x07,0x7d,0x83,0x03,0xd2,0x31,0xff,0xdb,0xd5,0x66,0x20,0x83,0xc0,0xff,0x05,0x24,0x00,0x1c,0x78,0x28,0xbc,0x40,0x72,0xbf,0xcf,0x47,0xeb,0x40,0xdb,0x7a,0xbf,0xf0,0x40,0x39,0x60,0x28,0x3f,0xe0,0xa0,0xea,0x80,0x63,0x3f,0x0b,0x17,0xe4,0x3e,0x5a,0xbc,0xf9,0x99,0x70,0x1f,0x81,0x50,0xc0,0x80,0xe7,0x3e,0x1e,0x9d,0x57,0xfb,0x7f,0x23,0x15,0xb0,0x12,0x5b,0x5b,0x02,0x1d,0x8c,0xc3,0x80,0x24,0x9e,0x03,0x80,0x5e,0x40,0x00,0xa1,0x88,0x0e,0x98,0x00,0x7b,0x07,0x08,0xb2,0x44,0x41,}; -const uint8_t* const _I_Background_128x11[] = {_I_Background_128x11_0}; - -const uint8_t _I_BadUsb_9x8_0[] = {0x00,0x01,0x01,0xBB,0x01,0xFE,0x00,0xFE,0x00,0xD6,0x00,0xD6,0x00,0x7C,0x00,0x38,0x00,}; -const uint8_t* const _I_BadUsb_9x8[] = {_I_BadUsb_9x8_0}; - -const uint8_t _I_Battery_19x8_0[] = {0x01,0x00,0x0f,0x00,0xff,0x7f,0xe0,0x30,0x18,0x04,0x08,0x04,0x90,0x60,0x12,0x02,0xcc,0x28,0x40,}; -const uint8_t* const _I_Battery_19x8[] = {_I_Battery_19x8_0}; - -const uint8_t _I_Battery_26x8_0[] = {0x01,0x00,0x13,0x00,0xff,0x7f,0xef,0xf0,0x08,0x0c,0x03,0x00,0x03,0x38,0x18,0x0c,0xa0,0x40,0x36,0x05,0x98,0x6d,0x00,}; -const uint8_t* const _I_Battery_26x8[] = {_I_Battery_26x8_0}; - -const uint8_t _I_Bluetooth_Connected_16x8_0[] = {0x00,0x04,0x00,0x0D,0x00,0x16,0x60,0x4C,0x97,0x4C,0x97,0x16,0x60,0x0D,0x00,0x04,0x00,}; -const uint8_t* const _I_Bluetooth_Connected_16x8[] = {_I_Bluetooth_Connected_16x8_0}; - -const uint8_t _I_Bluetooth_Idle_5x8_0[] = {0x00,0x04,0x0D,0x16,0x0C,0x0C,0x16,0x0D,0x04,}; -const uint8_t* const _I_Bluetooth_Idle_5x8[] = {_I_Bluetooth_Idle_5x8_0}; - -const uint8_t _I_Charging_lightning_9x10_0[] = {0x00,0x40,0x01,0xA0,0x00,0x50,0x00,0xE8,0x01,0x84,0x00,0x42,0x00,0x2F,0x00,0x14,0x00,0x0A,0x00,0x05,0x00,}; -const uint8_t* const _I_Charging_lightning_9x10[] = {_I_Charging_lightning_9x10_0}; - -const uint8_t _I_Charging_lightning_mask_9x10_0[] = {0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x78,0x00,0x3C,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,}; -const uint8_t* const _I_Charging_lightning_mask_9x10[] = {_I_Charging_lightning_mask_9x10_0}; - -const uint8_t _I_Lock_8x8_0[] = {0x00,0x3C,0x42,0x42,0xFF,0xFF,0xE7,0xFF,0xFF,}; -const uint8_t* const _I_Lock_8x8[] = {_I_Lock_8x8_0}; - -const uint8_t _I_PlaceholderL_11x13_0[] = {0x01,0x00,0x10,0x00,0xfe,0x40,0x60,0x50,0x28,0x0c,0x10,0x03,0xb0,0x38,0x37,0xfe,0x07,0xfe,0x80,0x80,}; -const uint8_t* const _I_PlaceholderL_11x13[] = {_I_PlaceholderL_11x13_0}; - -const uint8_t _I_PlaceholderR_30x13_0[] = {0x01,0x00,0x19,0x00,0xfe,0x7f,0xff,0xf0,0xf8,0x10,0x18,0x62,0x10,0x10,0x18,0xc8,0x00,0x7e,0x03,0xb8,0x18,0x0c,0x66,0x1f,0xe1,0x58,0xc7,0xc5,0xe6,}; -const uint8_t* const _I_PlaceholderR_30x13[] = {_I_PlaceholderR_30x13_0}; - -const uint8_t _I_SDcardFail_11x8_0[] = {0x00,0xFF,0x07,0xB7,0x07,0xFF,0x07,0x87,0x07,0x7B,0x07,0xFF,0x07,0xFF,0x07,0x67,0x00,}; -const uint8_t* const _I_SDcardFail_11x8[] = {_I_SDcardFail_11x8_0}; - -const uint8_t _I_SDcardMounted_11x8_0[] = {0x01,0x00,0x09,0x00,0xff,0xc1,0xff,0xf0,0x40,0x1c,0xd9,0xe0,0x00,}; -const uint8_t* const _I_SDcardMounted_11x8[] = {_I_SDcardMounted_11x8_0}; - -const uint8_t _I_Lock_7x8_0[] = {0x00,0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,}; -const uint8_t* const _I_Lock_7x8[] = {_I_Lock_7x8_0}; - -const uint8_t _I_MHz_25x11_0[] = {0x01,0x00,0x21,0x00,0xe1,0xe1,0xa0,0x30,0x0f,0x38,0x0c,0xbf,0xe0,0x34,0xfe,0xc0,0x7b,0x7f,0xe0,0x19,0xf0,0x60,0x1d,0xbc,0x35,0x84,0x36,0x53,0x10,0x19,0x46,0x40,0x64,0x13,0x10,0x19,0x80,}; -const uint8_t* const _I_MHz_25x11[] = {_I_MHz_25x11_0}; - -const uint8_t _I_Quest_7x8_0[] = {0x00,0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,}; -const uint8_t* const _I_Quest_7x8[] = {_I_Quest_7x8_0}; - -const uint8_t _I_Scanning_123x52_0[] = {0x01,0x00,0xd3,0x01,0x00,0x78,0x03,0xc0,0x1f,0x00,0xe0,0x7f,0xc1,0xfb,0xf0,0x80,0x41,0xc0,0xc7,0x03,0x07,0xbe,0xb2,0x07,0x18,0x07,0xc4,0x40,0x06,0x55,0x68,0x2d,0x80,0x0a,0x58,0x08,0x10,0x3c,0xe1,0x00,0x32,0xc0,0xc2,0xb0,0x00,0xf8,0x82,0x02,0x0a,0x01,0x15,0x80,0x40,0x40,0xc3,0x40,0x07,0xa0,0x10,0xa8,0x10,0x09,0xc0,0x19,0x01,0xe9,0x82,0x01,0x0c,0x82,0x01,0x74,0x13,0x1d,0x03,0x04,0x24,0x28,0x05,0x04,0x1e,0x76,0x80,0x79,0xc8,0x30,0x50,0x28,0x30,0x14,0x64,0x26,0x23,0xe8,0x78,0x21,0xe0,0xf4,0x85,0x43,0x30,0x12,0x03,0x00,0x83,0xc7,0x41,0x1c,0x3b,0x10,0x3c,0xe2,0x98,0x08,0x80,0xa4,0x61,0x1e,0x0e,0x9c,0x0c,0x1e,0x51,0x00,0x7a,0x95,0x46,0x11,0x90,0xd3,0xd0,0x24,0x80,0xfb,0xe4,0x5f,0xf0,0x92,0x80,0x79,0x61,0x01,0xe3,0xff,0x07,0x9e,0x22,0xcf,0x3e,0xc4,0x03,0xd3,0xf5,0xff,0x07,0xa5,0x12,0xc9,0x2e,0x07,0xa7,0xf3,0x5f,0xff,0x8a,0x93,0xce,0x89,0xe4,0x97,0xe2,0x25,0x40,0xf1,0x8c,0x75,0x3b,0xf1,0xf1,0xf8,0x9b,0xc8,0x1e,0x55,0x0f,0xfc,0x03,0xfd,0x1f,0xf6,0x4f,0xc9,0xe2,0x8f,0x3a,0x27,0x12,0x5f,0xea,0x68,0x0c,0x06,0x35,0xfc,0x2f,0x92,0xbc,0xf0,0x98,0x89,0x7c,0x75,0x8e,0x37,0xd8,0xf1,0x7c,0xa3,0x0c,0xf3,0xc3,0x47,0xf8,0xcb,0x81,0xc2,0x5f,0x62,0xc0,0xf2,0x77,0xa5,0x1b,0xeb,0xc3,0x6c,0x8d,0x12,0x03,0x22,0x07,0x8c,0x30,0x18,0x2d,0x82,0xc3,0xc2,0xaf,0x84,0x42,0x81,0xc8,0xb1,0x01,0xb2,0x4e,0x08,0x08,0x68,0xb0,0x50,0x20,0xdf,0xb4,0x90,0x3a,0x10,0x3d,0x19,0x05,0x86,0x1e,0x8f,0x03,0x03,0xa5,0x83,0xd0,0xa1,0x10,0x30,0x79,0x00,0x0a,0x0a,0x02,0x19,0x84,0x03,0xa5,0xff,0xc0,0x8a,0x88,0x00,0x81,0xe1,0x80,0x12,0x07,0xa5,0x1f,0xc0,0x03,0xde,0x0b,0x80,0x80,0x0a,0x47,0xa3,0x1f,0x80,0x42,0x43,0xf1,0xe1,0x80,0x60,0x3d,0x30,0xf8,0x04,0x48,0x3e,0xf0,0x08,0xf1,0x40,0x7d,0x00,0xf1,0x56,0x08,0xfe,0x20,0x17,0x0f,0x70,0x3c,0x55,0x82,0x00,0x58,0x38,0x0c,0xa7,0x9f,0x90,0x78,0x80,0x1c,0xec,0x5a,0xac,0xff,0xc0,0x1f,0x30,0x1a,0x05,0x57,0xfb,0x5f,0xf8,0x45,0xc3,0xf3,0x80,0xf5,0x7f,0xe7,0xfe,0x00,0x7c,0x87,0xc7,0xab,0xff,0x8f,0x83,0xea,0x05,0x80,0xd5,0x7f,0xe1,0xfe,0x08,0x98,0x7e,0x60,0x15,0x5a,0xac,0x0f,0xe1,0x15,0x0f,0xc9,0x78,0x75,0x50,0x0d,0x84,0x28,0x3f,0x55,0x4b,0xac,0x02,0xb1,0x0d,0x0f,0xd6,0xa0,0xf8,0x3a,0x85,0x29,0xaf,0xde,0xf8,0x04,0x1a,0xe2,0x54,0x83,0xf0,0x00,0x2d,0x70,0xd4,0x43,0xf2,0x00,0x2e,0xb8,0x3a,0x20,0x05,0x93,0xc0,0x5e,0xc1,0xf2,0x79,0x3e,0x04,0x7c,0x1f,0x32,0xa0,0x19,0x7c,0x1e,0x86,0x00,0x6a,0xa8,0x0c,0xbf,0x84,0xe9,0x4e,0x88,0x0c,0x85,0xd5,0x00,}; -const uint8_t* const _I_Scanning_123x52[] = {_I_Scanning_123x52_0}; - -const uint8_t _I_Unlock_7x8_0[] = {0x00,0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,}; -const uint8_t* const _I_Unlock_7x8[] = {_I_Unlock_7x8_0}; - -const uint8_t _I_Auth_62x31_0[] = {0x01,0x00,0xaf,0x00,0x00,0x47,0xc2,0xfe,0x07,0x58,0x66,0x02,0x02,0x07,0x48,0x1c,0x02,0x0c,0x06,0x3c,0x00,0x08,0x61,0x00,0x73,0xa0,0x00,0x86,0x20,0x02,0x1b,0x04,0x02,0x40,0x04,0x10,0x11,0x01,0xc4,0x18,0x40,0x72,0xf0,0x40,0x40,0xe4,0x1a,0x20,0x38,0xc2,0x3e,0x00,0x71,0xbc,0x05,0xca,0x11,0x08,0x80,0xe0,0x30,0xc0,0x72,0x82,0x7d,0x20,0x44,0x81,0x80,0x81,0xcb,0x75,0x05,0x02,0x08,0x1c,0xe7,0x50,0x58,0xc0,0x94,0x40,0xe5,0xfa,0x82,0xc1,0xbf,0x06,0xc1,0x80,0x40,0x80,0xe3,0x00,0xbe,0x40,0x3f,0x10,0x18,0x17,0xd0,0xd0,0x33,0xf3,0xa0,0xc0,0xe0,0x52,0x88,0x26,0x02,0x3e,0x1d,0x18,0x14,0x08,0xa0,0x3c,0x08,0x78,0x3c,0xc0,0xe3,0xe0,0x83,0x87,0xcd,0x32,0x42,0x11,0x17,0x90,0x04,0x61,0x9f,0xf8,0x06,0x20,0x0e,0x41,0xb1,0x9e,0x1b,0x44,0x2e,0x5f,0x0f,0xfc,0x0c,0x0e,0x80,0x02,0x80,0xc1,0x00,0xe8,0xab,0x11,0xf9,0x01,0xca,0xe0,0x07,0x68,0x60,0xb4,0x40,0xe7,0xfe,0x1f,0x88,0x1d,0x09,0x82,0x28,0x10,0xba,0x01,0xcc,}; -const uint8_t* const _I_Auth_62x31[] = {_I_Auth_62x31_0}; - -const uint8_t _I_Connect_me_62x31_0[] = {0x01,0x00,0xb7,0x00,0x00,0x47,0xc2,0xfe,0x07,0x58,0x66,0x02,0x02,0x07,0x48,0x1c,0x02,0x0c,0x06,0x3c,0x00,0x08,0x61,0x00,0x73,0xa0,0x00,0x86,0x20,0x02,0x1b,0xe4,0x02,0x40,0x04,0x10,0x11,0x51,0x01,0x86,0x07,0x2b,0x60,0x1c,0xc3,0x44,0x0f,0x18,0x47,0xc0,0x0e,0x37,0x80,0xf9,0x42,0x21,0x10,0x1c,0x06,0x1a,0x01,0x82,0x80,0x41,0x3e,0x90,0x22,0x40,0xc0,0x40,0xe5,0xba,0x82,0xd8,0x20,0x00,0x73,0x9d,0x41,0x63,0x1e,0x00,0x39,0xfe,0xa0,0xb0,0x6f,0xc0,0x7c,0xa0,0x40,0x71,0x16,0x90,0x1c,0xbe,0x86,0x81,0x9f,0x81,0xce,0x51,0x04,0xc0,0x47,0xe0,0x1f,0xe0,0x38,0x94,0x07,0x81,0x0f,0x80,0x4a,0x00,0xe7,0xe0,0x83,0x81,0xcd,0x32,0x42,0x11,0x03,0x9c,0x0a,0x19,0xff,0x80,0x4e,0x00,0xe5,0x0c,0x81,0xcf,0x20,0x21,0xc1,0x03,0x8f,0xc3,0xff,0x03,0x80,0x92,0x44,0x3e,0x40,0x01,0x80,0xc1,0x20,0x60,0x73,0x55,0x8c,0x0a,0x08,0x07,0x3b,0x80,0x1c,0x61,0x00,0x73,0x86,0x11,0x48,0x0e,0x5f,0xe1,0xf8,0xc3,0x00,0xe7,0xf8,0x6c,0x0c,0x42,0x40,0x17,0x30,0x38,0xcc,0x24,0x00,}; -const uint8_t* const _I_Connect_me_62x31[] = {_I_Connect_me_62x31_0}; - -const uint8_t _I_Connected_62x31_0[] = {0x01,0x00,0xaa,0x00,0x00,0x47,0xc2,0xfe,0x07,0x58,0x66,0x02,0x02,0x07,0x48,0x1c,0x02,0x0c,0x06,0x3c,0x00,0x08,0x61,0x00,0x73,0xa0,0x00,0x86,0x20,0x07,0x39,0x00,0x09,0x01,0x88,0x07,0x70,0xd1,0x09,0x0b,0xe0,0x07,0x1b,0xc0,0x1c,0xe1,0x10,0x1c,0x06,0x18,0x0e,0x50,0x4f,0xa4,0x08,0x90,0x24,0x92,0x82,0x6e,0xa0,0xb6,0x08,0x07,0x04,0x10,0x30,0x49,0xd4,0x16,0x31,0xe0,0xa0,0xfc,0x80,0xe3,0xfa,0x82,0xc1,0xbf,0x14,0x08,0x64,0x06,0x04,0x07,0x18,0x05,0xf2,0x81,0x04,0x81,0x40,0xbe,0x86,0x81,0x9f,0xe0,0x20,0x80,0x81,0x94,0x41,0x30,0x11,0xf0,0x39,0x94,0x07,0x81,0x0f,0x03,0xaf,0x82,0x0f,0x00,0x84,0x81,0xc5,0x32,0x42,0x11,0x98,0x89,0xc6,0x01,0x02,0x86,0x7f,0xc9,0x03,0x03,0x03,0x8c,0x32,0x07,0x3c,0x2c,0x08,0x3c,0xbe,0x1f,0xf8,0x18,0x1d,0x00,0x05,0x81,0x0e,0x08,0x1c,0xf0,0x0a,0xc1,0x03,0xa5,0xc0,0x0e,0xd0,0xc4,0xc8,0x81,0xcf,0xfd,0x03,0x03,0xaf,0xe2,0x02,0xb1,0x10,0xba,0x01,0xcc,}; -const uint8_t* const _I_Connected_62x31[] = {_I_Connected_62x31_0}; - -const uint8_t _I_Drive_112x35_0[] = {0x01,0x00,0x72,0x00,0xf0,0x7f,0xc0,0x0f,0x1f,0x06,0x94,0x40,0x2f,0x12,0x00,0x19,0x42,0x01,0xb1,0x40,0x01,0x94,0x10,0x1b,0x18,0x00,0x19,0x41,0x81,0xb9,0x07,0x06,0xc9,0x24,0x81,0xb4,0x02,0x20,0x6f,0x83,0x66,0x7c,0x0d,0xc9,0x10,0x6f,0xc1,0xbe,0x0d,0xf2,0x9f,0x83,0x7c,0x14,0x3f,0x8f,0xff,0xe4,0x1b,0x4c,0xe1,0xc4,0x83,0x6a,0x1f,0x00,0xc7,0x8d,0xfc,0xc3,0xe0,0xdf,0x06,0xfa,0xd7,0xc3,0x7e,0x99,0xf0,0x6d,0x7f,0xc0,0x02,0x0d,0xcb,0xf8,0x37,0x27,0xe3,0x7c,0x80,0x2a,0x84,0x00,0xf4,0x00,0x19,0x47,0xc1,0xb1,0x20,0x01,0x97,0xf8,0x92,0x40,0x05,0x0b,0x9f,0xf0,0x1b,0x03,0x33,0x7f,0x08,0x01,0xc9,0xe6,}; -const uint8_t* const _I_Drive_112x35[] = {_I_Drive_112x35_0}; - -const uint8_t _I_Error_62x31_0[] = {0x01,0x00,0x9e,0x00,0x00,0x47,0xc2,0xfe,0x07,0x58,0x66,0x02,0x02,0x07,0x48,0x1c,0x02,0x0c,0x06,0x3c,0x00,0x08,0x61,0x00,0x73,0xa0,0x00,0x86,0x20,0x07,0x39,0x00,0x09,0x01,0x88,0x07,0x70,0xd1,0x09,0x0b,0xe0,0x07,0x38,0x1c,0x62,0x11,0x08,0x80,0x8c,0x8a,0x0f,0x1c,0x82,0x7d,0x20,0x58,0x0b,0xe4,0x02,0x1d,0x0e,0x82,0x6e,0xa0,0xb8,0x0c,0x1c,0x02,0x39,0x07,0x82,0x4e,0xa0,0xb7,0x08,0x04,0x07,0x71,0x03,0x82,0x7e,0xa0,0xb0,0xe8,0x04,0x0b,0xe1,0x01,0x81,0x01,0xc6,0x01,0xc0,0x81,0xf8,0x01,0x42,0x27,0x18,0x04,0xc0,0x1e,0x63,0x71,0x3d,0x0c,0x08,0x3e,0x20,0xa1,0x22,0x94,0x08,0x5e,0x21,0x51,0x0f,0x08,0xbc,0x47,0xe2,0x07,0x29,0x81,0x40,0x49,0xe2,0x07,0x28,0x61,0x80,0x4b,0xe2,0x07,0x28,0x19,0xe0,0xc0,0xe2,0x0d,0x18,0xc0,0x1d,0x00,0x02,0xa8,0x30,0x39,0x2e,0x10,0x0e,0x5e,0x00,0x3b,0x7e,0x00,0xec,0x46,0x10,0x3f,0x80,0xc8,}; -const uint8_t* const _I_Error_62x31[] = {_I_Error_62x31_0}; - -const uint8_t _I_Updating_32x40_0[] = {0x01,0x00,0x56,0x00,0xc0,0x7f,0xc0,0x03,0xc0,0x01,0x97,0x82,0x07,0x00,0xe0,0x5c,0x00,0x65,0x38,0x01,0x94,0x70,0x06,0x50,0xe0,0x19,0x41,0xc0,0x65,0xff,0x01,0xb4,0x0c,0x02,0x7e,0x08,0x38,0x0c,0x7c,0xd6,0x70,0x18,0xfb,0xfe,0xfc,0x0c,0x18,0xc8,0x78,0x20,0x33,0x81,0x8f,0x8a,0x07,0x3e,0xbe,0x70,0x38,0x71,0xff,0xc7,0x0f,0xc7,0x0f,0xf8,0x71,0xc0,0x76,0x13,0x30,0xd9,0x88,0xcc,0x5f,0x03,0xb2,0x21,0xa1,0x2c,0xc0,0x26,0x82,0x10,0x1f,0x80,0xd1,0x24,0x40,0x04,}; -const uint8_t* const _I_Updating_32x40[] = {_I_Updating_32x40_0}; - -const uint8_t _I_DolphinMafia_115x62_0[] = {0x01,0x00,0x21,0x02,0x00,0x1e,0x02,0x06,0x0e,0xcb,0x04,0x10,0x1d,0x91,0x88,0x40,0x3b,0x20,0xc0,0xec,0xc0,0x40,0x62,0x03,0xac,0x80,0x03,0xb2,0x31,0x00,0x90,0x03,0xae,0x5e,0x0e,0xcf,0xc4,0x56,0x01,0x40,0x07,0x56,0xbe,0x14,0x0e,0x2f,0xf1,0x5e,0x2a,0xa1,0xd1,0xc0,0x7c,0x3f,0xf0,0x70,0x73,0x70,0x35,0x41,0xd1,0xc0,0x7f,0xff,0xf0,0xf0,0x73,0x50,0x03,0xa4,0x0d,0x10,0x74,0x07,0x46,0x55,0xe0,0x07,0x10,0xb1,0xc3,0xa3,0x55,0xfe,0x03,0x88,0x94,0xe1,0xd1,0xd5,0x03,0x4a,0x3e,0x59,0x9e,0xaf,0xfe,0xff,0x05,0x60,0x4e,0xab,0xf5,0xff,0x95,0xb4,0xa4,0x3a,0x3f,0xd0,0xe0,0xfa,0x20,0x20,0xf8,0xd5,0xff,0xb5,0xf0,0x0f,0x88,0x3a,0x6a,0xbf,0xf8,0xaf,0x82,0x6f,0x03,0x07,0x47,0xaf,0xff,0x0a,0xfe,0x5f,0xc1,0xd3,0xf6,0xbf,0xe0,0x7f,0xfe,0xf0,0x73,0x41,0x00,0x43,0xfa,0xd7,0xf8,0x27,0xfe,0xe0,0x73,0x40,0x80,0x43,0xfe,0xab,0xfe,0x21,0xfc,0xe5,0x9b,0x05,0x48,0xea,0x3f,0xc8,0xfa,0xc4,0x66,0x07,0x44,0x0e,0x8f,0x00,0xb0,0x2b,0x31,0x07,0x0f,0x00,0x1c,0x72,0x00,0x70,0xf8,0x37,0xe5,0x81,0xff,0x89,0x08,0xf2,0x71,0x80,0x20,0xfe,0x2b,0xf0,0x5f,0xc0,0x38,0xc8,0xa5,0x60,0xc3,0x00,0xc7,0xf9,0xaf,0x81,0x2d,0x04,0x34,0x40,0xe1,0x98,0x47,0x68,0x04,0x92,0xab,0xc0,0x7e,0xb7,0xf7,0x39,0x03,0x85,0x8e,0x24,0xf1,0xc0,0x7f,0xf5,0x78,0x0f,0x53,0xb4,0xbc,0x1f,0xb8,0x1a,0x0c,0x61,0xc5,0x82,0xab,0xc0,0x3e,0xa3,0xa2,0xfc,0x07,0x46,0x09,0x60,0x19,0x8f,0x80,0xec,0x38,0x08,0x52,0x6c,0xb8,0xdc,0x28,0x7c,0x10,0x2a,0x5f,0x0f,0xfc,0x5a,0x01,0x05,0x1a,0x8e,0x02,0x02,0x1d,0x1f,0x81,0xa8,0xbe,0x13,0xf8,0x52,0x2c,0x8c,0x62,0x77,0x42,0x11,0x40,0xe0,0xca,0x93,0x8e,0x03,0x8a,0x30,0x10,0x48,0x54,0x03,0x04,0xbb,0x2c,0x00,0x0c,0x64,0x80,0xe4,0x0e,0x88,0x38,0x7c,0x10,0x04,0x09,0x48,0x83,0xac,0x1b,0x18,0xf3,0x44,0xc1,0xca,0x1d,0x15,0x40,0x8e,0x05,0x02,0x20,0xe6,0x24,0x12,0x8c,0x8b,0x05,0x21,0x07,0x24,0x14,0x08,0x73,0x80,0x19,0x78,0x43,0xb2,0xff,0x15,0x30,0xc4,0x01,0x26,0x8f,0x14,0x61,0xa9,0x8a,0x09,0x10,0x02,0x12,0x1c,0x80,0x84,0xaf,0x10,0x71,0xaa,0xc4,0x00,0x3b,0x04,0xea,0x24,0x48,0x1c,0xbd,0x8f,0xf8,0x00,0x67,0xf0,0x09,0x40,0x20,0x61,0x00,0xe4,0xf6,0x07,0x4b,0xc1,0x1f,0x07,0x14,0x40,0x1c,0x9d,0x66,0x79,0x24,0xc6,0xa0,0x0e,0x32,0x51,0xfa,0xce,0xe7,0x50,0x07,0x1c,0x80,0x30,0x58,0x0e,0xa2,0xcc,0xa0,0x19,0x00,0x71,0x42,0x13,0x27,0x40,0xf5,0x45,0x41,0xc5,0x08,0xb0,0x80,0xc6,0x18,0xf2,0x28,0x04,0x83,0xe8,0x58,0x10,0x30,0xc2,0x2c,0x40,0x91,0x89,0x3c,0x88,0x62,0x21,0xd2,0xff,0x03,0x87,0xc8,0x12,0x19,0x08,0x39,0x3e,0x83,0xb2,0x4a,0x0e,0xa2,0x0d,0xc0,0xe0,0x50,0x06,0xa7,0xe8,0x2c,0x94,0xc2,0x09,0x50,0x8c,0xce,0x20,0x34,0x70,0x71,0x41,0x3e,0x85,0xe2,0xe0,0x41,0x38,0x1e,0x28,0x3c,0x19,0xc8,0x70,0x4f,0xc1,0xdc,0xe0,0x74,0x01,0xd8,0xc6,0x24,0x00,0x82,0x81,0x7c,0x12,0xa6,0x7e,0x10,0x28,0xd8,0x22,0x00,0xe3,0xfc,0x34,0x53,0x00,0x23,0x1c,0x04,0x44,0x0e,0x50,0x10,0xeb,0x17,0xca,0x1c,0x07,0x20,}; -const uint8_t* const _I_DolphinMafia_115x62[] = {_I_DolphinMafia_115x62_0}; - -const uint8_t _I_DolphinNice_96x59_0[] = {0x01,0x00,0x8a,0x01,0x00,0x37,0xfa,0x3e,0x0a,0x8f,0x04,0x04,0x02,0x20,0xb7,0x8c,0x00,0x86,0x1c,0x0b,0x78,0x20,0x08,0x66,0x00,0xb7,0x81,0x00,0x86,0x80,0x0b,0x71,0x61,0x60,0x01,0x4c,0x07,0x41,0xe3,0x07,0xd0,0x4e,0x40,0xb8,0x1f,0x90,0x00,0xe4,0x00,0xba,0x88,0x01,0x0e,0x10,0x0a,0x48,0xf9,0x6c,0xbe,0x10,0x70,0x82,0x78,0x3c,0x15,0x82,0x18,0xc2,0x21,0x00,0xb4,0x02,0x0e,0xbc,0x86,0x30,0x48,0x80,0xd1,0x05,0x03,0x78,0x82,0xc0,0x3e,0x52,0x32,0x63,0x70,0x20,0x70,0x09,0xd4,0x98,0xb0,0xf0,0x60,0x58,0xc9,0xce,0x12,0x0b,0xbf,0xd4,0x9d,0x28,0x9e,0x24,0xa9,0x82,0xda,0x24,0x2d,0x10,0x00,0xfd,0x2a,0x60,0xb4,0x85,0x4e,0x00,0x85,0xf8,0xd4,0x82,0xd2,0x09,0xc0,0x12,0x14,0x12,0xad,0x81,0x29,0xa8,0x90,0xf5,0x01,0x75,0x80,0x46,0x00,0xa5,0x50,0x0b,0x90,0x1c,0x41,0x63,0x60,0x05,0x96,0xc0,0x2e,0x52,0x44,0x79,0x60,0x06,0x05,0x50,0x05,0x94,0x89,0x88,0x63,0x02,0x98,0x02,0xc7,0xc1,0x21,0x6a,0x98,0xa0,0x62,0x11,0x00,0x58,0xc6,0x02,0xe2,0xb8,0x21,0x80,0xc3,0x05,0x02,0x38,0x11,0x78,0xa5,0x0b,0x01,0x81,0x5a,0x88,0x2c,0x60,0x40,0xb1,0xc0,0x27,0x0a,0xfc,0x0f,0x28,0x04,0x06,0x50,0x05,0x18,0xa9,0x94,0xc1,0x67,0x48,0x02,0x8c,0xb8,0x16,0xf8,0x80,0x28,0xd6,0x16,0x86,0x0b,0x38,0x40,0xd4,0x76,0x0c,0xd4,0x05,0x94,0x10,0x9a,0x34,0x01,0x82,0x1f,0x06,0x05,0x02,0x98,0x01,0x47,0x54,0x18,0x35,0xc8,0xff,0x20,0x3c,0x00,0x58,0xd5,0x6a,0xa0,0xb3,0x81,0xa3,0x0a,0x0f,0x80,0xd5,0xea,0x81,0x67,0x07,0x46,0x14,0xe3,0xe1,0x55,0x18,0x18,0x2c,0x51,0x85,0xc0,0xef,0x85,0x8c,0x0c,0x30,0xf4,0x61,0x40,0x2d,0x46,0xb4,0x05,0x8b,0x04,0xb0,0x15,0x40,0x5a,0x50,0x23,0xe6,0x01,0x02,0x8c,0xa8,0x2e,0xb1,0xe5,0x40,0x81,0x46,0x6a,0x17,0x59,0xeb,0xe4,0xa8,0x11,0xa0,0x5a,0x68,0x27,0x4e,0xd3,0x59,0xad,0x82,0xfa,0xed,0x2a,0x04,0x28,0x2e,0xb7,0xa7,0x69,0xc3,0x42,0xeb,0xf5,0x1f,0x09,0x4c,0x42,0xed,0xea,0x01,0x8c,0x06,0x41,0x05,0x0b,0xbc,0x02,0x0d,0x80,0x83,0x05,0xe2,0x11,0x40,0x0b,0xb7,0x14,0x06,0x33,0x0c,0x83,0x89,0x02,0xe3,0xca,0x3d,0x95,0x01,0xe2,0x21,0x74,0xc2,0x81,0x0b,0x0e,0x17,0x6c,0x10,0x10,0xaf,0x09,0xe2,0x0b,0xbb,0xd0,0x42,0xeb,0x02,}; -const uint8_t* const _I_DolphinNice_96x59[] = {_I_DolphinNice_96x59_0}; - -const uint8_t _I_DolphinWait_61x59_0[] = {0x01,0x00,0x56,0x01,0x00,0x17,0xfa,0x1e,0x06,0x4f,0x84,0x06,0xe0,0x07,0x48,0x64,0x03,0x01,0x01,0x03,0x9c,0x0c,0x04,0x30,0x60,0x31,0x70,0x00,0x65,0x08,0x01,0x94,0xc0,0x06,0x51,0x00,0x5b,0x48,0x00,0x65,0x04,0x01,0x95,0x00,0x82,0xd8,0x00,0x19,0x40,0x7e,0x00,0x75,0x1f,0x88,0xe0,0x88,0x02,0x1a,0x1f,0x94,0x14,0x0e,0xbf,0x98,0x58,0x5c,0x42,0x45,0x00,0x9e,0x99,0x87,0x01,0x02,0x11,0x94,0xf2,0x2e,0x03,0x18,0x39,0x28,0x70,0x1f,0xc0,0x3e,0x42,0x00,0xe5,0x80,0xff,0xdf,0xc0,0xe5,0xf8,0x85,0xd8,0x10,0x27,0x40,0xf9,0xc2,0x63,0x88,0x12,0x82,0x6a,0x20,0x50,0x41,0xe9,0x42,0x20,0x95,0x48,0x6e,0x0c,0xfa,0x9a,0xaf,0xf9,0x90,0xe2,0x10,0x2e,0xac,0xe0,0x0e,0x98,0x29,0x52,0x11,0x13,0x23,0x15,0x3e,0x20,0x3c,0x61,0x40,0x52,0xfc,0x4f,0xe2,0x10,0x38,0x68,0x1c,0xa0,0xfc,0x08,0xbe,0x04,0x1e,0x5e,0x01,0xb9,0x03,0xc5,0x60,0x24,0xf2,0x84,0x60,0x63,0x40,0x71,0x27,0x9c,0x0e,0x2b,0x04,0x6c,0xa4,0x06,0x15,0x08,0x6c,0x99,0x8c,0xa6,0x0f,0x81,0x00,0x0c,0x08,0xf0,0x3c,0x05,0x61,0xc0,0x40,0x86,0xd0,0x30,0x78,0x80,0x0c,0xc6,0x2b,0x92,0x00,0x0d,0x51,0xf0,0x2d,0x42,0x0a,0x8e,0xaa,0x34,0x0f,0x4a,0x85,0x55,0x6e,0x20,0xf3,0xd5,0x6a,0x84,0xa2,0x66,0x2a,0x05,0xf7,0xaa,0x07,0x18,0xaf,0xfb,0x7f,0xea,0xc1,0xef,0xc0,0xe3,0xea,0x80,0xf8,0x27,0xf0,0x0a,0xc0,0x1c,0x67,0xa2,0xd1,0xb1,0xc0,0x34,0x00,0x71,0x14,0x8f,0x00,0x98,0x34,0x02,0x69,0xd0,0x37,0x90,0x16,0xf1,0x00,0x06,0xe1,0x84,0x31,0x89,0x14,0xe9,0xdc,0x40,0x38,0xa4,0xc4,0x4c,0x3c,0x1f,0x88,0x8c,0x5b,0xc3,0x01,0xbc,0x40,0x3f,0xf0,0xf6,0x71,0x0c,0x0b,0xe0,0x07,0x3c,0x0a,0xf8,0xa3,0xf0,0x03,0xb8,0xd8,0x80,0xe8,0x87,0x1b,0xa8,0x1c,0x78,0x1f,0xf8,0x0e,0x7e,0x01,0x6a,0x03,0x94,0x0f,0xfd,0xa0,0x80,0x7d,0x49,0x04,0x4d,0x12,0xc0,0xfa,0x83,0x83,0xbe,0x26,0x8d,0x02,0x05,0xd5,0xff,0xff,0xeb,0xe9,0x31,0x90,0x40,0x80,}; -const uint8_t* const _I_DolphinWait_61x59[] = {_I_DolphinWait_61x59_0}; - -const uint8_t _I_iButtonDolphinVerySuccess_108x52_0[] = {0x01,0x00,0xc2,0x01,0x00,0x0f,0xe2,0xfe,0x0d,0xb8,0x3e,0x02,0x06,0x0c,0x9f,0x00,0x08,0x61,0x80,0xd9,0x8c,0x00,0x86,0x60,0x0d,0x98,0x30,0x08,0x6a,0x00,0xd9,0x80,0x80,0x87,0x40,0x0c,0x8c,0x00,0x0c,0xa8,0x01,0x12,0x00,0x2d,0x00,0x22,0x70,0x20,0x6b,0xc8,0x02,0x26,0x62,0x88,0x80,0x6c,0xc9,0x24,0x0d,0x9a,0x07,0x17,0xfe,0x1d,0x68,0x40,0x6c,0xe7,0x48,0x04,0x28,0x10,0x34,0xe8,0x10,0xd1,0x11,0xc4,0x01,0xa5,0x04,0x06,0x96,0xa0,0xa6,0x24,0xc2,0x88,0x17,0x88,0x1a,0x7d,0x43,0x78,0x82,0x4a,0x40,0x03,0x20,0xb0,0xff,0x20,0x16,0xa3,0xb2,0x48,0x03,0xe4,0x0d,0x1f,0xfc,0x06,0x3a,0x0d,0x4a,0x00,0x34,0xf8,0x00,0xd1,0x37,0x0f,0x82,0x9e,0x95,0x58,0x17,0x83,0xff,0x81,0x1b,0x0f,0xf1,0xfe,0x71,0xe0,0x69,0x7c,0x3f,0xe0,0x82,0xff,0xcf,0xc0,0x85,0x61,0x80,0x43,0xb0,0x5f,0xa8,0x79,0xdc,0x81,0xa5,0x70,0xc0,0x68,0x3c,0x10,0x1a,0x17,0xd5,0x28,0x42,0xd1,0x8f,0x84,0x46,0x83,0xb0,0x8e,0x40,0x34,0x5f,0xa8,0x38,0x34,0x45,0xa2,0x0d,0x18,0x04,0x9b,0x50,0x03,0x1a,0x14,0x35,0x36,0x5f,0x8f,0xf8,0xb8,0xa4,0x19,0x40,0x18,0xe8,0xa0,0xca,0x22,0xfe,0x7f,0xc4,0x05,0x20,0xa5,0x80,0xc6,0x82,0xcb,0x3f,0xf3,0x44,0xfc,0x12,0x40,0x18,0xe8,0x51,0x82,0x52,0x28,0xfc,0x38,0x0a,0x3e,0x48,0x98,0x6c,0x8f,0x43,0x00,0xe0,0x63,0xe0,0x62,0xe2,0x91,0x90,0x0a,0x02,0x0d,0x2f,0x82,0x50,0x41,0xa3,0x80,0x90,0x41,0x04,0xc3,0x01,0xc0,0x83,0x46,0x71,0x30,0x06,0x95,0x82,0x21,0x02,0x6e,0x88,0x6c,0x43,0x83,0x1f,0x2f,0x88,0x34,0x62,0x00,0xd1,0x15,0x08,0x2c,0x60,0xcc,0x51,0x0f,0x08,0xcc,0x81,0xa2,0x12,0x10,0x68,0xc6,0x3f,0x06,0xc2,0x06,0x8e,0x02,0x16,0x41,0x20,0x10,0xf8,0x01,0x85,0x00,0x19,0x0d,0x82,0x18,0x07,0x20,0x81,0x00,0x0c,0x9c,0x31,0x08,0x42,0x74,0x81,0xab,0x80,0x03,0x0c,0x32,0x11,0x0b,0x06,0xb9,0xc0,0x43,0xa3,0x10,0x8b,0x83,0x5c,0xe0,0x20,0x81,0xc8,0x26,0x49,0x4c,0x40,0x02,0x86,0x0a,0xc5,0x22,0x32,0x50,0x6b,0x93,0x86,0xc0,0x0d,0x19,0x18,0x35,0x8c,0x84,0x79,0x1a,0x84,0x84,0x1a,0xdf,0xc2,0xe0,0x8a,0xc7,0x51,0x22,0x06,0xb5,0x5e,0x3f,0x00,0x77,0x0d,0x60,0x36,0xfa,0xa9,0xd7,0x00,0x08,0x3a,0xc9,0x02,0x48,0xc0,0x05,0x54,0xba,0x98,0x8a,0xa8,0xf1,0x20,0x6a,0x6a,0x3d,0x43,0x61,0x80,0x4a,0x81,0xaf,0x40,0xea,0x8d,0x86,0x01,0x56,0x06,0x93,0x60,0x80,0x05,0xea,0x01,0x94,0xac,0x1b,0x11,0x80,0x19,0x45,0x41,0x44,0x0d,0x58,0x33,0x18,0xa1,0x4f,0xf3,0x06,0x1f,0x01,0x76,0x58,0x00,0xd9,0x83,0x52,0x7c,0x11,0x38,0x51,0x40,0x80,}; -const uint8_t* const _I_iButtonDolphinVerySuccess_108x52[] = {_I_iButtonDolphinVerySuccess_108x52_0}; - -const uint8_t _I_iButtonKey_49x44_0[] = {0x01,0x00,0xb4,0x00,0x00,0x24,0xfc,0x0a,0x9c,0x0e,0x00,0x19,0x26,0x18,0x00,0x32,0x43,0x20,0x10,0x10,0x31,0xc0,0x80,0xc9,0x80,0x02,0x08,0x18,0xec,0x00,0x21,0x03,0x1c,0x40,0x1e,0x22,0x15,0xa0,0x08,0x56,0x40,0x06,0x30,0xc0,0x85,0x84,0x86,0x40,0x21,0x84,0x10,0xcc,0x04,0x30,0x40,0x31,0x02,0x88,0x3a,0x20,0x01,0x83,0x0d,0x94,0x06,0x26,0x03,0xf8,0x43,0xc5,0xe9,0x0c,0x11,0x08,0xbc,0xe0,0x64,0x21,0x23,0x09,0x38,0x80,0x22,0x28,0x20,0x58,0x99,0xc4,0x50,0x41,0xe1,0xc0,0x60,0xcc,0xab,0x47,0x21,0xa6,0x02,0x9e,0x06,0x22,0x70,0xf0,0x00,0xcb,0x40,0x03,0x18,0xb0,0x78,0x14,0xe0,0x32,0x58,0x28,0xa5,0x84,0xd0,0x51,0x80,0xc9,0x30,0x06,0xae,0x62,0x84,0x06,0x48,0x64,0x88,0x0c,0x90,0x29,0x08,0x19,0x30,0x31,0x13,0x71,0xb8,0xc4,0xea,0x70,0x6b,0xc5,0x01,0x4a,0x7f,0xc8,0x7c,0x81,0x4a,0x77,0x8a,0xac,0x45,0x4a,0x7f,0x08,0x54,0x39,0x4a,0x7e,0x0e,0xa9,0xf0,0xcb,0xe3,0x7f,0x6e,0x22,0x5c,0x59,0x44,0x00,0x28,0x7a,0xd4,0x40,0x07,0xf0,0x02,0xa0,}; -const uint8_t* const _I_iButtonKey_49x44[] = {_I_iButtonKey_49x44_0}; - -const Icon I_Certification1_103x23 = {.width=103,.height=23,.frame_count=1,.frame_rate=0,.frames=_I_Certification1_103x23}; -const Icon I_Certification2_119x30 = {.width=119,.height=30,.frame_count=1,.frame_rate=0,.frames=_I_Certification2_119x30}; -const Icon A_Levelup1_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rate=2,.frames=_A_Levelup1_128x64}; -const Icon A_Levelup2_128x64 = {.width=128,.height=64,.frame_count=11,.frame_rate=2,.frames=_A_Levelup2_128x64}; -const Icon I_125_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_125_10px}; -const Icon I_Nfc_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Nfc_10px}; -const Icon I_back_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_back_10px}; -const Icon I_badusb_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_badusb_10px}; -const Icon I_ble_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ble_10px}; -const Icon I_dir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_dir_10px}; -const Icon I_ibutt_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ibutt_10px}; -const Icon I_ir_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_ir_10px}; -const Icon I_loading_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_loading_10px}; -const Icon I_music_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_music_10px}; -const Icon I_sub1_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_sub1_10px}; -const Icon I_u2f_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_u2f_10px}; -const Icon I_unknown_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_unknown_10px}; -const Icon I_update_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_update_10px}; -const Icon I_BLE_Pairing_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_BLE_Pairing_128x64}; -const Icon I_Ble_connected_38x34 = {.width=38,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_Ble_connected_38x34}; -const Icon I_Ble_disconnected_24x34 = {.width=24,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_Ble_disconnected_24x34}; -const Icon I_Button_18x18 = {.width=18,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_Button_18x18}; -const Icon I_Circles_47x47 = {.width=47,.height=47,.frame_count=1,.frame_rate=0,.frames=_I_Circles_47x47}; -const Icon I_Ok_btn_9x9 = {.width=9,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_Ok_btn_9x9}; -const Icon I_Pressed_Button_13x13 = {.width=13,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Pressed_Button_13x13}; -const Icon I_Space_65x18 = {.width=65,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_Space_65x18}; -const Icon I_Voldwn_6x6 = {.width=6,.height=6,.frame_count=1,.frame_rate=0,.frames=_I_Voldwn_6x6}; -const Icon I_Volup_8x6 = {.width=8,.height=6,.frame_count=1,.frame_rate=0,.frames=_I_Volup_8x6}; -const Icon I_Clock_18x18 = {.width=18,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_Clock_18x18}; -const Icon I_Error_18x18 = {.width=18,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_Error_18x18}; -const Icon I_EviSmile1_18x21 = {.width=18,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_EviSmile1_18x21}; -const Icon I_EviSmile2_18x21 = {.width=18,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_EviSmile2_18x21}; -const Icon I_EviWaiting1_18x21 = {.width=18,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_EviWaiting1_18x21}; -const Icon I_EviWaiting2_18x21 = {.width=18,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_EviWaiting2_18x21}; -const Icon I_Percent_10x14 = {.width=10,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_Percent_10x14}; -const Icon I_Smile_18x18 = {.width=18,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_Smile_18x18}; -const Icon I_UsbTree_48x22 = {.width=48,.height=22,.frame_count=1,.frame_rate=0,.frames=_I_UsbTree_48x22}; -const Icon I_ButtonCenter_7x7 = {.width=7,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonCenter_7x7}; -const Icon I_ButtonDown_7x4 = {.width=7,.height=4,.frame_count=1,.frame_rate=0,.frames=_I_ButtonDown_7x4}; -const Icon I_ButtonLeftSmall_3x5 = {.width=3,.height=5,.frame_count=1,.frame_rate=0,.frames=_I_ButtonLeftSmall_3x5}; -const Icon I_ButtonLeft_4x7 = {.width=4,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonLeft_4x7}; -const Icon I_ButtonRightSmall_3x5 = {.width=3,.height=5,.frame_count=1,.frame_rate=0,.frames=_I_ButtonRightSmall_3x5}; -const Icon I_ButtonRight_4x7 = {.width=4,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonRight_4x7}; -const Icon I_ButtonUp_7x4 = {.width=7,.height=4,.frame_count=1,.frame_rate=0,.frames=_I_ButtonUp_7x4}; -const Icon I_DFU_128x50 = {.width=128,.height=50,.frame_count=1,.frame_rate=0,.frames=_I_DFU_128x50}; -const Icon I_Warning_30x23 = {.width=30,.height=23,.frame_count=1,.frame_rate=0,.frames=_I_Warning_30x23}; -const Icon A_Loading_24 = {.width=24,.height=24,.frame_count=7,.frame_rate=5,.frames=_A_Loading_24}; -const Icon I_DolphinFirstStart0_70x53 = {.width=70,.height=53,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart0_70x53}; -const Icon I_DolphinFirstStart1_59x53 = {.width=59,.height=53,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart1_59x53}; -const Icon I_DolphinFirstStart2_59x51 = {.width=59,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart2_59x51}; -const Icon I_DolphinFirstStart3_57x48 = {.width=57,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart3_57x48}; -const Icon I_DolphinFirstStart4_67x53 = {.width=67,.height=53,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart4_67x53}; -const Icon I_DolphinFirstStart5_54x49 = {.width=54,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart5_54x49}; -const Icon I_DolphinFirstStart6_58x54 = {.width=58,.height=54,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart6_58x54}; -const Icon I_DolphinFirstStart7_61x51 = {.width=61,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart7_61x51}; -const Icon I_DolphinFirstStart8_56x51 = {.width=56,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart8_56x51}; -const Icon I_DolphinOkay_41x43 = {.width=41,.height=43,.frame_count=1,.frame_rate=0,.frames=_I_DolphinOkay_41x43}; -const Icon I_ArrowDownEmpty_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowDownEmpty_14x15}; -const Icon I_ArrowDownFilled_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowDownFilled_14x15}; -const Icon I_ArrowUpEmpty_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowUpEmpty_14x15}; -const Icon I_ArrowUpFilled_14x15 = {.width=14,.height=15,.frame_count=1,.frame_rate=0,.frames=_I_ArrowUpFilled_14x15}; -const Icon I_DolphinReadingSuccess_59x63 = {.width=59,.height=63,.frame_count=1,.frame_rate=0,.frames=_I_DolphinReadingSuccess_59x63}; -const Icon I_Down_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Down_25x27}; -const Icon I_Down_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Down_hvr_25x27}; -const Icon I_InfraredArrowDown_4x8 = {.width=8,.height=4,.frame_count=1,.frame_rate=0,.frames=_I_InfraredArrowDown_4x8}; -const Icon I_InfraredArrowUp_4x8 = {.width=8,.height=4,.frame_count=1,.frame_rate=0,.frames=_I_InfraredArrowUp_4x8}; -const Icon I_InfraredLearnShort_128x31 = {.width=128,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_InfraredLearnShort_128x31}; -const Icon I_InfraredLearn_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_InfraredLearn_128x64}; -const Icon I_InfraredSendShort_128x34 = {.width=128,.height=34,.frame_count=1,.frame_rate=0,.frames=_I_InfraredSendShort_128x34}; -const Icon I_InfraredSend_128x64 = {.width=128,.height=64,.frame_count=1,.frame_rate=0,.frames=_I_InfraredSend_128x64}; -const Icon I_Mute_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Mute_25x27}; -const Icon I_Mute_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Mute_hvr_25x27}; -const Icon I_Power_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Power_25x27}; -const Icon I_Power_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Power_hvr_25x27}; -const Icon I_Up_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Up_25x27}; -const Icon I_Up_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Up_hvr_25x27}; -const Icon I_Vol_down_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Vol_down_25x27}; -const Icon I_Vol_down_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Vol_down_hvr_25x27}; -const Icon I_Vol_up_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Vol_up_25x27}; -const Icon I_Vol_up_hvr_25x27 = {.width=25,.height=27,.frame_count=1,.frame_rate=0,.frames=_I_Vol_up_hvr_25x27}; -const Icon I_DoorLeft_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_70x55}; -const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56}; -const Icon I_DoorRight_70x55 = {.width=70,.height=55,.frame_count=1,.frame_rate=0,.frames=_I_DoorRight_70x55}; -const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17}; -const Icon I_PassportLeft_6x47 = {.width=6,.height=47,.frame_count=1,.frame_rate=0,.frames=_I_PassportLeft_6x47}; -const Icon I_WarningDolphin_45x42 = {.width=45,.height=42,.frame_count=1,.frame_rate=0,.frames=_I_WarningDolphin_45x42}; -const Icon I_KeyBackspaceSelected_16x9 = {.width=16,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_KeyBackspaceSelected_16x9}; -const Icon I_KeyBackspace_16x9 = {.width=16,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_KeyBackspace_16x9}; -const Icon I_KeySaveSelected_24x11 = {.width=24,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_KeySaveSelected_24x11}; -const Icon I_KeySave_24x11 = {.width=24,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_KeySave_24x11}; -const Icon A_125khz_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_125khz_14}; -const Icon A_BadUsb_14 = {.width=14,.height=14,.frame_count=11,.frame_rate=3,.frames=_A_BadUsb_14}; -const Icon A_Bluetooth_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Bluetooth_14}; -const Icon A_Debug_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_Debug_14}; -const Icon A_FileManager_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_FileManager_14}; -const Icon A_GPIO_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_GPIO_14}; -const Icon A_Games_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Games_14}; -const Icon A_Infrared_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Infrared_14}; -const Icon A_NFC_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_NFC_14}; -const Icon A_Passport_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_Passport_14}; -const Icon A_Plugins_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Plugins_14}; -const Icon A_Power_14 = {.width=14,.height=14,.frame_count=1,.frame_rate=3,.frames=_A_Power_14}; -const Icon A_Settings_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_Settings_14}; -const Icon A_Sub1ghz_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Sub1ghz_14}; -const Icon A_Tamagotchi_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Tamagotchi_14}; -const Icon A_U2F_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_U2F_14}; -const Icon A_iButton_14 = {.width=14,.height=14,.frame_count=7,.frame_rate=3,.frames=_A_iButton_14}; -const Icon I_Detailed_chip_17x13 = {.width=17,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Detailed_chip_17x13}; -const Icon I_Medium_chip_22x21 = {.width=22,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_Medium_chip_22x21}; -const Icon I_Pin_arrow_down_7x9 = {.width=7,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_down_7x9}; -const Icon I_Pin_arrow_left_9x7 = {.width=9,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_left_9x7}; -const Icon I_Pin_arrow_right_9x7 = {.width=9,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_right_9x7}; -const Icon I_Pin_arrow_up7x9 = {.width=7,.height=9,.frame_count=1,.frame_rate=0,.frames=_I_Pin_arrow_up7x9}; -const Icon I_Pin_attention_dpad_29x29 = {.width=29,.height=29,.frame_count=1,.frame_rate=0,.frames=_I_Pin_attention_dpad_29x29}; -const Icon I_Pin_back_arrow_10x8 = {.width=10,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Pin_back_arrow_10x8}; -const Icon I_Pin_back_full_40x8 = {.width=40,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Pin_back_full_40x8}; -const Icon I_Pin_cell_13x13 = {.width=13,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Pin_cell_13x13}; -const Icon I_Pin_pointer_5x3 = {.width=5,.height=3,.frame_count=1,.frame_rate=0,.frames=_I_Pin_pointer_5x3}; -const Icon I_Pin_star_7x7 = {.width=7,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_Pin_star_7x7}; -const Icon I_passport_bad1_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad1_46x49}; -const Icon I_passport_bad2_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad2_46x49}; -const Icon I_passport_bad3_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_bad3_46x49}; -const Icon I_passport_bottom_128x18 = {.width=128,.height=18,.frame_count=1,.frame_rate=0,.frames=_I_passport_bottom_128x18}; -const Icon I_passport_happy1_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_happy1_46x49}; -const Icon I_passport_happy2_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_happy2_46x49}; -const Icon I_passport_happy3_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_happy3_46x49}; -const Icon I_passport_left_6x46 = {.width=6,.height=46,.frame_count=1,.frame_rate=0,.frames=_I_passport_left_6x46}; -const Icon I_passport_okay1_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_okay1_46x49}; -const Icon I_passport_okay2_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_okay2_46x49}; -const Icon I_passport_okay3_46x49 = {.width=46,.height=49,.frame_count=1,.frame_rate=0,.frames=_I_passport_okay3_46x49}; -const Icon I_BatteryBody_52x28 = {.width=52,.height=28,.frame_count=1,.frame_rate=0,.frames=_I_BatteryBody_52x28}; -const Icon I_Battery_16x16 = {.width=16,.height=16,.frame_count=1,.frame_rate=0,.frames=_I_Battery_16x16}; -const Icon I_FaceCharging_29x14 = {.width=29,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_FaceCharging_29x14}; -const Icon I_FaceConfused_29x14 = {.width=29,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_FaceConfused_29x14}; -const Icon I_FaceNopower_29x14 = {.width=29,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_FaceNopower_29x14}; -const Icon I_FaceNormal_29x14 = {.width=29,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_FaceNormal_29x14}; -const Icon I_Health_16x16 = {.width=16,.height=16,.frame_count=1,.frame_rate=0,.frames=_I_Health_16x16}; -const Icon I_Temperature_16x16 = {.width=16,.height=16,.frame_count=1,.frame_rate=0,.frames=_I_Temperature_16x16}; -const Icon I_Voltage_16x16 = {.width=16,.height=16,.frame_count=1,.frame_rate=0,.frames=_I_Voltage_16x16}; -const Icon I_RFIDBigChip_37x36 = {.width=37,.height=36,.frame_count=1,.frame_rate=0,.frames=_I_RFIDBigChip_37x36}; -const Icon I_RFIDDolphinReceive_97x61 = {.width=97,.height=61,.frame_count=1,.frame_rate=0,.frames=_I_RFIDDolphinReceive_97x61}; -const Icon I_RFIDDolphinSend_97x61 = {.width=97,.height=61,.frame_count=1,.frame_rate=0,.frames=_I_RFIDDolphinSend_97x61}; -const Icon I_RFIDDolphinSuccess_108x57 = {.width=108,.height=57,.frame_count=1,.frame_rate=0,.frames=_I_RFIDDolphinSuccess_108x57}; -const Icon I_SDQuestion_35x43 = {.width=35,.height=43,.frame_count=1,.frame_rate=0,.frames=_I_SDQuestion_35x43}; -const Icon I_Cry_dolph_55x52 = {.width=55,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Cry_dolph_55x52}; -const Icon I_Attention_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Attention_5x8}; -const Icon I_Background_128x11 = {.width=128,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_Background_128x11}; -const Icon I_BadUsb_9x8 = {.width=9,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_BadUsb_9x8}; -const Icon I_Battery_19x8 = {.width=19,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Battery_19x8}; -const Icon I_Battery_26x8 = {.width=26,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Battery_26x8}; -const Icon I_Bluetooth_Connected_16x8 = {.width=16,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_Connected_16x8}; -const Icon I_Bluetooth_Idle_5x8 = {.width=5,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Bluetooth_Idle_5x8}; -const Icon I_Charging_lightning_9x10 = {.width=9,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Charging_lightning_9x10}; -const Icon I_Charging_lightning_mask_9x10 = {.width=9,.height=10,.frame_count=1,.frame_rate=0,.frames=_I_Charging_lightning_mask_9x10}; -const Icon I_Lock_8x8 = {.width=8,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_8x8}; -const Icon I_PlaceholderL_11x13 = {.width=11,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_PlaceholderL_11x13}; -const Icon I_PlaceholderR_30x13 = {.width=30,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_PlaceholderR_30x13}; -const Icon I_SDcardFail_11x8 = {.width=11,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_SDcardFail_11x8}; -const Icon I_SDcardMounted_11x8 = {.width=11,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_SDcardMounted_11x8}; -const Icon I_Lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_7x8}; -const Icon I_MHz_25x11 = {.width=25,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_MHz_25x11}; -const Icon I_Quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Quest_7x8}; -const Icon I_Scanning_123x52 = {.width=123,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_123x52}; -const Icon I_Unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Unlock_7x8}; -const Icon I_Auth_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Auth_62x31}; -const Icon I_Connect_me_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Connect_me_62x31}; -const Icon I_Connected_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Connected_62x31}; -const Icon I_Drive_112x35 = {.width=112,.height=35,.frame_count=1,.frame_rate=0,.frames=_I_Drive_112x35}; -const Icon I_Error_62x31 = {.width=62,.height=31,.frame_count=1,.frame_rate=0,.frames=_I_Error_62x31}; -const Icon I_Updating_32x40 = {.width=32,.height=40,.frame_count=1,.frame_rate=0,.frames=_I_Updating_32x40}; -const Icon I_DolphinMafia_115x62 = {.width=115,.height=62,.frame_count=1,.frame_rate=0,.frames=_I_DolphinMafia_115x62}; -const Icon I_DolphinNice_96x59 = {.width=96,.height=59,.frame_count=1,.frame_rate=0,.frames=_I_DolphinNice_96x59}; -const Icon I_DolphinWait_61x59 = {.width=61,.height=59,.frame_count=1,.frame_rate=0,.frames=_I_DolphinWait_61x59}; -const Icon I_iButtonDolphinVerySuccess_108x52 = {.width=108,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_iButtonDolphinVerySuccess_108x52}; -const Icon I_iButtonKey_49x44 = {.width=49,.height=44,.frame_count=1,.frame_rate=0,.frames=_I_iButtonKey_49x44}; - diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h deleted file mode 100644 index 45947880..00000000 --- a/assets/compiled/assets_icons.h +++ /dev/null @@ -1,178 +0,0 @@ -#pragma once -#include - -extern const Icon I_Certification1_103x23; -extern const Icon I_Certification2_119x30; -extern const Icon A_Levelup1_128x64; -extern const Icon A_Levelup2_128x64; -extern const Icon I_125_10px; -extern const Icon I_Nfc_10px; -extern const Icon I_back_10px; -extern const Icon I_badusb_10px; -extern const Icon I_ble_10px; -extern const Icon I_dir_10px; -extern const Icon I_ibutt_10px; -extern const Icon I_ir_10px; -extern const Icon I_loading_10px; -extern const Icon I_music_10px; -extern const Icon I_sub1_10px; -extern const Icon I_u2f_10px; -extern const Icon I_unknown_10px; -extern const Icon I_update_10px; -extern const Icon I_BLE_Pairing_128x64; -extern const Icon I_Ble_connected_38x34; -extern const Icon I_Ble_disconnected_24x34; -extern const Icon I_Button_18x18; -extern const Icon I_Circles_47x47; -extern const Icon I_Ok_btn_9x9; -extern const Icon I_Pressed_Button_13x13; -extern const Icon I_Space_65x18; -extern const Icon I_Voldwn_6x6; -extern const Icon I_Volup_8x6; -extern const Icon I_Clock_18x18; -extern const Icon I_Error_18x18; -extern const Icon I_EviSmile1_18x21; -extern const Icon I_EviSmile2_18x21; -extern const Icon I_EviWaiting1_18x21; -extern const Icon I_EviWaiting2_18x21; -extern const Icon I_Percent_10x14; -extern const Icon I_Smile_18x18; -extern const Icon I_UsbTree_48x22; -extern const Icon I_ButtonCenter_7x7; -extern const Icon I_ButtonDown_7x4; -extern const Icon I_ButtonLeftSmall_3x5; -extern const Icon I_ButtonLeft_4x7; -extern const Icon I_ButtonRightSmall_3x5; -extern const Icon I_ButtonRight_4x7; -extern const Icon I_ButtonUp_7x4; -extern const Icon I_DFU_128x50; -extern const Icon I_Warning_30x23; -extern const Icon A_Loading_24; -extern const Icon I_DolphinFirstStart0_70x53; -extern const Icon I_DolphinFirstStart1_59x53; -extern const Icon I_DolphinFirstStart2_59x51; -extern const Icon I_DolphinFirstStart3_57x48; -extern const Icon I_DolphinFirstStart4_67x53; -extern const Icon I_DolphinFirstStart5_54x49; -extern const Icon I_DolphinFirstStart6_58x54; -extern const Icon I_DolphinFirstStart7_61x51; -extern const Icon I_DolphinFirstStart8_56x51; -extern const Icon I_DolphinOkay_41x43; -extern const Icon I_ArrowDownEmpty_14x15; -extern const Icon I_ArrowDownFilled_14x15; -extern const Icon I_ArrowUpEmpty_14x15; -extern const Icon I_ArrowUpFilled_14x15; -extern const Icon I_DolphinReadingSuccess_59x63; -extern const Icon I_Down_25x27; -extern const Icon I_Down_hvr_25x27; -extern const Icon I_InfraredArrowDown_4x8; -extern const Icon I_InfraredArrowUp_4x8; -extern const Icon I_InfraredLearnShort_128x31; -extern const Icon I_InfraredLearn_128x64; -extern const Icon I_InfraredSendShort_128x34; -extern const Icon I_InfraredSend_128x64; -extern const Icon I_Mute_25x27; -extern const Icon I_Mute_hvr_25x27; -extern const Icon I_Power_25x27; -extern const Icon I_Power_hvr_25x27; -extern const Icon I_Up_25x27; -extern const Icon I_Up_hvr_25x27; -extern const Icon I_Vol_down_25x27; -extern const Icon I_Vol_down_hvr_25x27; -extern const Icon I_Vol_up_25x27; -extern const Icon I_Vol_up_hvr_25x27; -extern const Icon I_DoorLeft_70x55; -extern const Icon I_DoorLocked_10x56; -extern const Icon I_DoorRight_70x55; -extern const Icon I_PassportBottom_128x17; -extern const Icon I_PassportLeft_6x47; -extern const Icon I_WarningDolphin_45x42; -extern const Icon I_KeyBackspaceSelected_16x9; -extern const Icon I_KeyBackspace_16x9; -extern const Icon I_KeySaveSelected_24x11; -extern const Icon I_KeySave_24x11; -extern const Icon A_125khz_14; -extern const Icon A_BadUsb_14; -extern const Icon A_Bluetooth_14; -extern const Icon A_Debug_14; -extern const Icon A_FileManager_14; -extern const Icon A_GPIO_14; -extern const Icon A_Games_14; -extern const Icon A_Infrared_14; -extern const Icon A_NFC_14; -extern const Icon A_Passport_14; -extern const Icon A_Plugins_14; -extern const Icon A_Power_14; -extern const Icon A_Settings_14; -extern const Icon A_Sub1ghz_14; -extern const Icon A_Tamagotchi_14; -extern const Icon A_U2F_14; -extern const Icon A_iButton_14; -extern const Icon I_Detailed_chip_17x13; -extern const Icon I_Medium_chip_22x21; -extern const Icon I_Pin_arrow_down_7x9; -extern const Icon I_Pin_arrow_left_9x7; -extern const Icon I_Pin_arrow_right_9x7; -extern const Icon I_Pin_arrow_up7x9; -extern const Icon I_Pin_attention_dpad_29x29; -extern const Icon I_Pin_back_arrow_10x8; -extern const Icon I_Pin_back_full_40x8; -extern const Icon I_Pin_cell_13x13; -extern const Icon I_Pin_pointer_5x3; -extern const Icon I_Pin_star_7x7; -extern const Icon I_passport_bad1_46x49; -extern const Icon I_passport_bad2_46x49; -extern const Icon I_passport_bad3_46x49; -extern const Icon I_passport_bottom_128x18; -extern const Icon I_passport_happy1_46x49; -extern const Icon I_passport_happy2_46x49; -extern const Icon I_passport_happy3_46x49; -extern const Icon I_passport_left_6x46; -extern const Icon I_passport_okay1_46x49; -extern const Icon I_passport_okay2_46x49; -extern const Icon I_passport_okay3_46x49; -extern const Icon I_BatteryBody_52x28; -extern const Icon I_Battery_16x16; -extern const Icon I_FaceCharging_29x14; -extern const Icon I_FaceConfused_29x14; -extern const Icon I_FaceNopower_29x14; -extern const Icon I_FaceNormal_29x14; -extern const Icon I_Health_16x16; -extern const Icon I_Temperature_16x16; -extern const Icon I_Voltage_16x16; -extern const Icon I_RFIDBigChip_37x36; -extern const Icon I_RFIDDolphinReceive_97x61; -extern const Icon I_RFIDDolphinSend_97x61; -extern const Icon I_RFIDDolphinSuccess_108x57; -extern const Icon I_SDQuestion_35x43; -extern const Icon I_Cry_dolph_55x52; -extern const Icon I_Attention_5x8; -extern const Icon I_Background_128x11; -extern const Icon I_BadUsb_9x8; -extern const Icon I_Battery_19x8; -extern const Icon I_Battery_26x8; -extern const Icon I_Bluetooth_Connected_16x8; -extern const Icon I_Bluetooth_Idle_5x8; -extern const Icon I_Charging_lightning_9x10; -extern const Icon I_Charging_lightning_mask_9x10; -extern const Icon I_Lock_8x8; -extern const Icon I_PlaceholderL_11x13; -extern const Icon I_PlaceholderR_30x13; -extern const Icon I_SDcardFail_11x8; -extern const Icon I_SDcardMounted_11x8; -extern const Icon I_Lock_7x8; -extern const Icon I_MHz_25x11; -extern const Icon I_Quest_7x8; -extern const Icon I_Scanning_123x52; -extern const Icon I_Unlock_7x8; -extern const Icon I_Auth_62x31; -extern const Icon I_Connect_me_62x31; -extern const Icon I_Connected_62x31; -extern const Icon I_Drive_112x35; -extern const Icon I_Error_62x31; -extern const Icon I_Updating_32x40; -extern const Icon I_DolphinMafia_115x62; -extern const Icon I_DolphinNice_96x59; -extern const Icon I_DolphinWait_61x59; -extern const Icon I_iButtonDolphinVerySuccess_108x52; -extern const Icon I_iButtonKey_49x44; diff --git a/assets/compiled/flipper.pb.c b/assets/compiled/flipper.pb.c deleted file mode 100644 index 684ffe8c..00000000 --- a/assets/compiled/flipper.pb.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "flipper.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(PB_Empty, PB_Empty, AUTO) - - -PB_BIND(PB_StopSession, PB_StopSession, AUTO) - - -PB_BIND(PB_Main, PB_Main, AUTO) - - - - diff --git a/assets/compiled/flipper.pb.h b/assets/compiled/flipper.pb.h deleted file mode 100644 index 3199090d..00000000 --- a/assets/compiled/flipper.pb.h +++ /dev/null @@ -1,302 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_PB_FLIPPER_PB_H_INCLUDED -#define PB_PB_FLIPPER_PB_H_INCLUDED -#include -#include "storage.pb.h" -#include "system.pb.h" -#include "application.pb.h" -#include "gui.pb.h" - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _PB_CommandStatus { - PB_CommandStatus_OK = 0, - /* *< Common Errors */ - PB_CommandStatus_ERROR = 1, /* *< Unknown error */ - PB_CommandStatus_ERROR_DECODE = 2, /* *< Command can't be decoded successfully - command_id in response may be wrong! */ - PB_CommandStatus_ERROR_NOT_IMPLEMENTED = 3, /* *< Command succesfully decoded, but not implemented (deprecated or not yet implemented) */ - PB_CommandStatus_ERROR_BUSY = 4, /* *< Somebody took global lock, so not all commands are available */ - PB_CommandStatus_ERROR_CONTINUOUS_COMMAND_INTERRUPTED = 14, /* *< Not received has_next == 0 */ - PB_CommandStatus_ERROR_INVALID_PARAMETERS = 15, /* *< not provided (or provided invalid) crucial parameters to perform rpc */ - /* *< Storage Errors */ - PB_CommandStatus_ERROR_STORAGE_NOT_READY = 5, /* *< FS not ready */ - PB_CommandStatus_ERROR_STORAGE_EXIST = 6, /* *< File/Dir alrady exist */ - PB_CommandStatus_ERROR_STORAGE_NOT_EXIST = 7, /* *< File/Dir does not exist */ - PB_CommandStatus_ERROR_STORAGE_INVALID_PARAMETER = 8, /* *< Invalid API parameter */ - PB_CommandStatus_ERROR_STORAGE_DENIED = 9, /* *< Access denied */ - PB_CommandStatus_ERROR_STORAGE_INVALID_NAME = 10, /* *< Invalid name/path */ - PB_CommandStatus_ERROR_STORAGE_INTERNAL = 11, /* *< Internal error */ - PB_CommandStatus_ERROR_STORAGE_NOT_IMPLEMENTED = 12, /* *< Functon not implemented */ - PB_CommandStatus_ERROR_STORAGE_ALREADY_OPEN = 13, /* *< File/Dir already opened */ - PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY = 18, /* *< Directory, you're going to remove is not empty */ - /* *< Application Errors */ - PB_CommandStatus_ERROR_APP_CANT_START = 16, /* *< Can't start app - internal error */ - PB_CommandStatus_ERROR_APP_SYSTEM_LOCKED = 17, /* *< Another app is running */ - /* *< Virtual Display Errors */ - PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_ALREADY_STARTED = 19, /* *< Virtual Display session can't be started twice */ - PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED = 20 /* *< Virtual Display session can't be stopped when it's not started */ -} PB_CommandStatus; - -/* Struct definitions */ -/* There are Server commands (e.g. Storage_write), which have no body message - in response. But 'oneof' obligate to have at least 1 encoded message - in scope. For this needs Empty message is implemented. */ -typedef struct _PB_Empty { - char dummy_field; -} PB_Empty; - -typedef struct _PB_StopSession { - char dummy_field; -} PB_StopSession; - -typedef struct _PB_Main { - uint32_t command_id; - PB_CommandStatus command_status; - bool has_next; - pb_callback_t cb_content; - pb_size_t which_content; - union { - PB_Empty empty; - PB_System_PingRequest system_ping_request; - PB_System_PingResponse system_ping_response; - PB_Storage_ListRequest storage_list_request; - PB_Storage_ListResponse storage_list_response; - PB_Storage_ReadRequest storage_read_request; - PB_Storage_ReadResponse storage_read_response; - PB_Storage_WriteRequest storage_write_request; - PB_Storage_DeleteRequest storage_delete_request; - PB_Storage_MkdirRequest storage_mkdir_request; - PB_Storage_Md5sumRequest storage_md5sum_request; - PB_Storage_Md5sumResponse storage_md5sum_response; - PB_App_StartRequest app_start_request; - PB_App_LockStatusRequest app_lock_status_request; - PB_App_LockStatusResponse app_lock_status_response; - PB_StopSession stop_session; - PB_Gui_StartScreenStreamRequest gui_start_screen_stream_request; - PB_Gui_StopScreenStreamRequest gui_stop_screen_stream_request; - PB_Gui_ScreenFrame gui_screen_frame; - PB_Gui_SendInputEventRequest gui_send_input_event_request; - PB_Storage_StatRequest storage_stat_request; - PB_Storage_StatResponse storage_stat_response; - PB_Gui_StartVirtualDisplayRequest gui_start_virtual_display_request; - PB_Gui_StopVirtualDisplayRequest gui_stop_virtual_display_request; - PB_Storage_InfoRequest storage_info_request; - PB_Storage_InfoResponse storage_info_response; - PB_Storage_RenameRequest storage_rename_request; - PB_System_RebootRequest system_reboot_request; - PB_System_DeviceInfoRequest system_device_info_request; - PB_System_DeviceInfoResponse system_device_info_response; - PB_System_FactoryResetRequest system_factory_reset_request; - PB_System_GetDateTimeRequest system_get_datetime_request; - PB_System_GetDateTimeResponse system_get_datetime_response; - PB_System_SetDateTimeRequest system_set_datetime_request; - PB_System_PlayAudiovisualAlertRequest system_play_audiovisual_alert_request; - PB_System_ProtobufVersionRequest system_protobuf_version_request; - PB_System_ProtobufVersionResponse system_protobuf_version_response; - PB_System_UpdateRequest system_update_request; - PB_Storage_BackupCreateRequest storage_backup_create_request; - PB_Storage_BackupRestoreRequest storage_backup_restore_request; - PB_System_PowerInfoRequest system_power_info_request; - PB_System_PowerInfoResponse system_power_info_response; - PB_System_UpdateResponse system_update_response; - } content; -} PB_Main; - - -/* Helper constants for enums */ -#define _PB_CommandStatus_MIN PB_CommandStatus_OK -#define _PB_CommandStatus_MAX PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED -#define _PB_CommandStatus_ARRAYSIZE ((PB_CommandStatus)(PB_CommandStatus_ERROR_VIRTUAL_DISPLAY_NOT_STARTED+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define PB_Empty_init_default {0} -#define PB_StopSession_init_default {0} -#define PB_Main_init_default {0, _PB_CommandStatus_MIN, 0, {{NULL}, NULL}, 0, {PB_Empty_init_default}} -#define PB_Empty_init_zero {0} -#define PB_StopSession_init_zero {0} -#define PB_Main_init_zero {0, _PB_CommandStatus_MIN, 0, {{NULL}, NULL}, 0, {PB_Empty_init_zero}} - -/* Field tags (for use in manual encoding/decoding) */ -#define PB_Main_command_id_tag 1 -#define PB_Main_command_status_tag 2 -#define PB_Main_has_next_tag 3 -#define PB_Main_empty_tag 4 -#define PB_Main_system_ping_request_tag 5 -#define PB_Main_system_ping_response_tag 6 -#define PB_Main_storage_list_request_tag 7 -#define PB_Main_storage_list_response_tag 8 -#define PB_Main_storage_read_request_tag 9 -#define PB_Main_storage_read_response_tag 10 -#define PB_Main_storage_write_request_tag 11 -#define PB_Main_storage_delete_request_tag 12 -#define PB_Main_storage_mkdir_request_tag 13 -#define PB_Main_storage_md5sum_request_tag 14 -#define PB_Main_storage_md5sum_response_tag 15 -#define PB_Main_app_start_request_tag 16 -#define PB_Main_app_lock_status_request_tag 17 -#define PB_Main_app_lock_status_response_tag 18 -#define PB_Main_stop_session_tag 19 -#define PB_Main_gui_start_screen_stream_request_tag 20 -#define PB_Main_gui_stop_screen_stream_request_tag 21 -#define PB_Main_gui_screen_frame_tag 22 -#define PB_Main_gui_send_input_event_request_tag 23 -#define PB_Main_storage_stat_request_tag 24 -#define PB_Main_storage_stat_response_tag 25 -#define PB_Main_gui_start_virtual_display_request_tag 26 -#define PB_Main_gui_stop_virtual_display_request_tag 27 -#define PB_Main_storage_info_request_tag 28 -#define PB_Main_storage_info_response_tag 29 -#define PB_Main_storage_rename_request_tag 30 -#define PB_Main_system_reboot_request_tag 31 -#define PB_Main_system_device_info_request_tag 32 -#define PB_Main_system_device_info_response_tag 33 -#define PB_Main_system_factory_reset_request_tag 34 -#define PB_Main_system_get_datetime_request_tag 35 -#define PB_Main_system_get_datetime_response_tag 36 -#define PB_Main_system_set_datetime_request_tag 37 -#define PB_Main_system_play_audiovisual_alert_request_tag 38 -#define PB_Main_system_protobuf_version_request_tag 39 -#define PB_Main_system_protobuf_version_response_tag 40 -#define PB_Main_system_update_request_tag 41 -#define PB_Main_storage_backup_create_request_tag 42 -#define PB_Main_storage_backup_restore_request_tag 43 -#define PB_Main_system_power_info_request_tag 44 -#define PB_Main_system_power_info_response_tag 45 -#define PB_Main_system_update_response_tag 46 - -/* Struct field encoding specification for nanopb */ -#define PB_Empty_FIELDLIST(X, a) \ - -#define PB_Empty_CALLBACK NULL -#define PB_Empty_DEFAULT NULL - -#define PB_StopSession_FIELDLIST(X, a) \ - -#define PB_StopSession_CALLBACK NULL -#define PB_StopSession_DEFAULT NULL - -#define PB_Main_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, command_id, 1) \ -X(a, STATIC, SINGULAR, UENUM, command_status, 2) \ -X(a, STATIC, SINGULAR, BOOL, has_next, 3) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,empty,content.empty), 4) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_ping_request,content.system_ping_request), 5) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_ping_response,content.system_ping_response), 6) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_list_request,content.storage_list_request), 7) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_list_response,content.storage_list_response), 8) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_read_request,content.storage_read_request), 9) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_read_response,content.storage_read_response), 10) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_write_request,content.storage_write_request), 11) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_delete_request,content.storage_delete_request), 12) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_mkdir_request,content.storage_mkdir_request), 13) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_request,content.storage_md5sum_request), 14) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_md5sum_response,content.storage_md5sum_response), 15) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,app_start_request,content.app_start_request), 16) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_request,content.app_lock_status_request), 17) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,app_lock_status_response,content.app_lock_status_response), 18) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,stop_session,content.stop_session), 19) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_screen_stream_request,content.gui_start_screen_stream_request), 20) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_screen_stream_request,content.gui_stop_screen_stream_request), 21) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_screen_frame,content.gui_screen_frame), 22) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_send_input_event_request,content.gui_send_input_event_request), 23) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_request,content.storage_stat_request), 24) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_stat_response,content.storage_stat_response), 25) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_start_virtual_display_request,content.gui_start_virtual_display_request), 26) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,gui_stop_virtual_display_request,content.gui_stop_virtual_display_request), 27) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_info_request,content.storage_info_request), 28) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_info_response,content.storage_info_response), 29) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_rename_request,content.storage_rename_request), 30) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_reboot_request,content.system_reboot_request), 31) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_device_info_request,content.system_device_info_request), 32) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_device_info_response,content.system_device_info_response), 33) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_factory_reset_request,content.system_factory_reset_request), 34) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_get_datetime_request,content.system_get_datetime_request), 35) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_get_datetime_response,content.system_get_datetime_response), 36) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_set_datetime_request,content.system_set_datetime_request), 37) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_play_audiovisual_alert_request,content.system_play_audiovisual_alert_request), 38) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_protobuf_version_request,content.system_protobuf_version_request), 39) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_protobuf_version_response,content.system_protobuf_version_response), 40) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_request,content.system_update_request), 41) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_create_request,content.storage_backup_create_request), 42) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,storage_backup_restore_request,content.storage_backup_restore_request), 43) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_request,content.system_power_info_request), 44) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_power_info_response,content.system_power_info_response), 45) \ -X(a, STATIC, ONEOF, MSG_W_CB, (content,system_update_response,content.system_update_response), 46) -#define PB_Main_CALLBACK NULL -#define PB_Main_DEFAULT NULL -#define PB_Main_content_empty_MSGTYPE PB_Empty -#define PB_Main_content_system_ping_request_MSGTYPE PB_System_PingRequest -#define PB_Main_content_system_ping_response_MSGTYPE PB_System_PingResponse -#define PB_Main_content_storage_list_request_MSGTYPE PB_Storage_ListRequest -#define PB_Main_content_storage_list_response_MSGTYPE PB_Storage_ListResponse -#define PB_Main_content_storage_read_request_MSGTYPE PB_Storage_ReadRequest -#define PB_Main_content_storage_read_response_MSGTYPE PB_Storage_ReadResponse -#define PB_Main_content_storage_write_request_MSGTYPE PB_Storage_WriteRequest -#define PB_Main_content_storage_delete_request_MSGTYPE PB_Storage_DeleteRequest -#define PB_Main_content_storage_mkdir_request_MSGTYPE PB_Storage_MkdirRequest -#define PB_Main_content_storage_md5sum_request_MSGTYPE PB_Storage_Md5sumRequest -#define PB_Main_content_storage_md5sum_response_MSGTYPE PB_Storage_Md5sumResponse -#define PB_Main_content_app_start_request_MSGTYPE PB_App_StartRequest -#define PB_Main_content_app_lock_status_request_MSGTYPE PB_App_LockStatusRequest -#define PB_Main_content_app_lock_status_response_MSGTYPE PB_App_LockStatusResponse -#define PB_Main_content_stop_session_MSGTYPE PB_StopSession -#define PB_Main_content_gui_start_screen_stream_request_MSGTYPE PB_Gui_StartScreenStreamRequest -#define PB_Main_content_gui_stop_screen_stream_request_MSGTYPE PB_Gui_StopScreenStreamRequest -#define PB_Main_content_gui_screen_frame_MSGTYPE PB_Gui_ScreenFrame -#define PB_Main_content_gui_send_input_event_request_MSGTYPE PB_Gui_SendInputEventRequest -#define PB_Main_content_storage_stat_request_MSGTYPE PB_Storage_StatRequest -#define PB_Main_content_storage_stat_response_MSGTYPE PB_Storage_StatResponse -#define PB_Main_content_gui_start_virtual_display_request_MSGTYPE PB_Gui_StartVirtualDisplayRequest -#define PB_Main_content_gui_stop_virtual_display_request_MSGTYPE PB_Gui_StopVirtualDisplayRequest -#define PB_Main_content_storage_info_request_MSGTYPE PB_Storage_InfoRequest -#define PB_Main_content_storage_info_response_MSGTYPE PB_Storage_InfoResponse -#define PB_Main_content_storage_rename_request_MSGTYPE PB_Storage_RenameRequest -#define PB_Main_content_system_reboot_request_MSGTYPE PB_System_RebootRequest -#define PB_Main_content_system_device_info_request_MSGTYPE PB_System_DeviceInfoRequest -#define PB_Main_content_system_device_info_response_MSGTYPE PB_System_DeviceInfoResponse -#define PB_Main_content_system_factory_reset_request_MSGTYPE PB_System_FactoryResetRequest -#define PB_Main_content_system_get_datetime_request_MSGTYPE PB_System_GetDateTimeRequest -#define PB_Main_content_system_get_datetime_response_MSGTYPE PB_System_GetDateTimeResponse -#define PB_Main_content_system_set_datetime_request_MSGTYPE PB_System_SetDateTimeRequest -#define PB_Main_content_system_play_audiovisual_alert_request_MSGTYPE PB_System_PlayAudiovisualAlertRequest -#define PB_Main_content_system_protobuf_version_request_MSGTYPE PB_System_ProtobufVersionRequest -#define PB_Main_content_system_protobuf_version_response_MSGTYPE PB_System_ProtobufVersionResponse -#define PB_Main_content_system_update_request_MSGTYPE PB_System_UpdateRequest -#define PB_Main_content_storage_backup_create_request_MSGTYPE PB_Storage_BackupCreateRequest -#define PB_Main_content_storage_backup_restore_request_MSGTYPE PB_Storage_BackupRestoreRequest -#define PB_Main_content_system_power_info_request_MSGTYPE PB_System_PowerInfoRequest -#define PB_Main_content_system_power_info_response_MSGTYPE PB_System_PowerInfoResponse -#define PB_Main_content_system_update_response_MSGTYPE PB_System_UpdateResponse - -extern const pb_msgdesc_t PB_Empty_msg; -extern const pb_msgdesc_t PB_StopSession_msg; -extern const pb_msgdesc_t PB_Main_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PB_Empty_fields &PB_Empty_msg -#define PB_StopSession_fields &PB_StopSession_msg -#define PB_Main_fields &PB_Main_msg - -/* Maximum encoded size of messages (where known) */ -#define PB_Empty_size 0 -#define PB_StopSession_size 0 -#if defined(PB_System_PingRequest_size) && defined(PB_System_PingResponse_size) && defined(PB_Storage_ListRequest_size) && defined(PB_Storage_ListResponse_size) && defined(PB_Storage_ReadRequest_size) && defined(PB_Storage_ReadResponse_size) && defined(PB_Storage_WriteRequest_size) && defined(PB_Storage_DeleteRequest_size) && defined(PB_Storage_MkdirRequest_size) && defined(PB_Storage_Md5sumRequest_size) && defined(PB_App_StartRequest_size) && defined(PB_Gui_ScreenFrame_size) && defined(PB_Storage_StatRequest_size) && defined(PB_Storage_StatResponse_size) && defined(PB_Gui_StartVirtualDisplayRequest_size) && defined(PB_Storage_InfoRequest_size) && defined(PB_Storage_RenameRequest_size) && defined(PB_System_DeviceInfoResponse_size) && defined(PB_System_UpdateRequest_size) && defined(PB_Storage_BackupCreateRequest_size) && defined(PB_Storage_BackupRestoreRequest_size) && defined(PB_System_PowerInfoResponse_size) -#define PB_Main_size (10 + sizeof(union PB_Main_content_size_union)) -union PB_Main_content_size_union {char f5[(6 + PB_System_PingRequest_size)]; char f6[(6 + PB_System_PingResponse_size)]; char f7[(6 + PB_Storage_ListRequest_size)]; char f8[(6 + PB_Storage_ListResponse_size)]; char f9[(6 + PB_Storage_ReadRequest_size)]; char f10[(6 + PB_Storage_ReadResponse_size)]; char f11[(6 + PB_Storage_WriteRequest_size)]; char f12[(6 + PB_Storage_DeleteRequest_size)]; char f13[(6 + PB_Storage_MkdirRequest_size)]; char f14[(6 + PB_Storage_Md5sumRequest_size)]; char f16[(7 + PB_App_StartRequest_size)]; char f22[(7 + PB_Gui_ScreenFrame_size)]; char f24[(7 + PB_Storage_StatRequest_size)]; char f25[(7 + PB_Storage_StatResponse_size)]; char f26[(7 + PB_Gui_StartVirtualDisplayRequest_size)]; char f28[(7 + PB_Storage_InfoRequest_size)]; char f30[(7 + PB_Storage_RenameRequest_size)]; char f33[(7 + PB_System_DeviceInfoResponse_size)]; char f41[(7 + PB_System_UpdateRequest_size)]; char f42[(7 + PB_Storage_BackupCreateRequest_size)]; char f43[(7 + PB_Storage_BackupRestoreRequest_size)]; char f45[(7 + PB_System_PowerInfoResponse_size)]; char f0[36];}; -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/assets/compiled/gui.pb.c b/assets/compiled/gui.pb.c deleted file mode 100644 index 2c1d8490..00000000 --- a/assets/compiled/gui.pb.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "gui.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(PB_Gui_ScreenFrame, PB_Gui_ScreenFrame, AUTO) - - -PB_BIND(PB_Gui_StartScreenStreamRequest, PB_Gui_StartScreenStreamRequest, AUTO) - - -PB_BIND(PB_Gui_StopScreenStreamRequest, PB_Gui_StopScreenStreamRequest, AUTO) - - -PB_BIND(PB_Gui_SendInputEventRequest, PB_Gui_SendInputEventRequest, AUTO) - - -PB_BIND(PB_Gui_StartVirtualDisplayRequest, PB_Gui_StartVirtualDisplayRequest, AUTO) - - -PB_BIND(PB_Gui_StopVirtualDisplayRequest, PB_Gui_StopVirtualDisplayRequest, AUTO) - - - - - diff --git a/assets/compiled/gui.pb.h b/assets/compiled/gui.pb.h deleted file mode 100644 index 7ab8a97d..00000000 --- a/assets/compiled/gui.pb.h +++ /dev/null @@ -1,152 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_PB_GUI_GUI_PB_H_INCLUDED -#define PB_PB_GUI_GUI_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _PB_Gui_InputKey { - PB_Gui_InputKey_UP = 0, - PB_Gui_InputKey_DOWN = 1, - PB_Gui_InputKey_RIGHT = 2, - PB_Gui_InputKey_LEFT = 3, - PB_Gui_InputKey_OK = 4, - PB_Gui_InputKey_BACK = 5 -} PB_Gui_InputKey; - -typedef enum _PB_Gui_InputType { - PB_Gui_InputType_PRESS = 0, /* *< Press event, emitted after debounce */ - PB_Gui_InputType_RELEASE = 1, /* *< Release event, emitted after debounce */ - PB_Gui_InputType_SHORT = 2, /* *< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ - PB_Gui_InputType_LONG = 3, /* *< Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease */ - PB_Gui_InputType_REPEAT = 4 /* *< Repeat event, emmited with INPUT_REPEATE_PRESS period after InputTypeLong event */ -} PB_Gui_InputType; - -/* Struct definitions */ -typedef struct _PB_Gui_ScreenFrame { - pb_bytes_array_t *data; -} PB_Gui_ScreenFrame; - -typedef struct _PB_Gui_StartScreenStreamRequest { - char dummy_field; -} PB_Gui_StartScreenStreamRequest; - -typedef struct _PB_Gui_StopScreenStreamRequest { - char dummy_field; -} PB_Gui_StopScreenStreamRequest; - -typedef struct _PB_Gui_StopVirtualDisplayRequest { - char dummy_field; -} PB_Gui_StopVirtualDisplayRequest; - -typedef struct _PB_Gui_SendInputEventRequest { - PB_Gui_InputKey key; - PB_Gui_InputType type; -} PB_Gui_SendInputEventRequest; - -typedef struct _PB_Gui_StartVirtualDisplayRequest { - bool has_first_frame; - PB_Gui_ScreenFrame first_frame; /* optional */ -} PB_Gui_StartVirtualDisplayRequest; - - -/* Helper constants for enums */ -#define _PB_Gui_InputKey_MIN PB_Gui_InputKey_UP -#define _PB_Gui_InputKey_MAX PB_Gui_InputKey_BACK -#define _PB_Gui_InputKey_ARRAYSIZE ((PB_Gui_InputKey)(PB_Gui_InputKey_BACK+1)) - -#define _PB_Gui_InputType_MIN PB_Gui_InputType_PRESS -#define _PB_Gui_InputType_MAX PB_Gui_InputType_REPEAT -#define _PB_Gui_InputType_ARRAYSIZE ((PB_Gui_InputType)(PB_Gui_InputType_REPEAT+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define PB_Gui_ScreenFrame_init_default {NULL} -#define PB_Gui_StartScreenStreamRequest_init_default {0} -#define PB_Gui_StopScreenStreamRequest_init_default {0} -#define PB_Gui_SendInputEventRequest_init_default {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN} -#define PB_Gui_StartVirtualDisplayRequest_init_default {false, PB_Gui_ScreenFrame_init_default} -#define PB_Gui_StopVirtualDisplayRequest_init_default {0} -#define PB_Gui_ScreenFrame_init_zero {NULL} -#define PB_Gui_StartScreenStreamRequest_init_zero {0} -#define PB_Gui_StopScreenStreamRequest_init_zero {0} -#define PB_Gui_SendInputEventRequest_init_zero {_PB_Gui_InputKey_MIN, _PB_Gui_InputType_MIN} -#define PB_Gui_StartVirtualDisplayRequest_init_zero {false, PB_Gui_ScreenFrame_init_zero} -#define PB_Gui_StopVirtualDisplayRequest_init_zero {0} - -/* Field tags (for use in manual encoding/decoding) */ -#define PB_Gui_ScreenFrame_data_tag 1 -#define PB_Gui_SendInputEventRequest_key_tag 1 -#define PB_Gui_SendInputEventRequest_type_tag 2 -#define PB_Gui_StartVirtualDisplayRequest_first_frame_tag 1 - -/* Struct field encoding specification for nanopb */ -#define PB_Gui_ScreenFrame_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, BYTES, data, 1) -#define PB_Gui_ScreenFrame_CALLBACK NULL -#define PB_Gui_ScreenFrame_DEFAULT NULL - -#define PB_Gui_StartScreenStreamRequest_FIELDLIST(X, a) \ - -#define PB_Gui_StartScreenStreamRequest_CALLBACK NULL -#define PB_Gui_StartScreenStreamRequest_DEFAULT NULL - -#define PB_Gui_StopScreenStreamRequest_FIELDLIST(X, a) \ - -#define PB_Gui_StopScreenStreamRequest_CALLBACK NULL -#define PB_Gui_StopScreenStreamRequest_DEFAULT NULL - -#define PB_Gui_SendInputEventRequest_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, key, 1) \ -X(a, STATIC, SINGULAR, UENUM, type, 2) -#define PB_Gui_SendInputEventRequest_CALLBACK NULL -#define PB_Gui_SendInputEventRequest_DEFAULT NULL - -#define PB_Gui_StartVirtualDisplayRequest_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, first_frame, 1) -#define PB_Gui_StartVirtualDisplayRequest_CALLBACK NULL -#define PB_Gui_StartVirtualDisplayRequest_DEFAULT NULL -#define PB_Gui_StartVirtualDisplayRequest_first_frame_MSGTYPE PB_Gui_ScreenFrame - -#define PB_Gui_StopVirtualDisplayRequest_FIELDLIST(X, a) \ - -#define PB_Gui_StopVirtualDisplayRequest_CALLBACK NULL -#define PB_Gui_StopVirtualDisplayRequest_DEFAULT NULL - -extern const pb_msgdesc_t PB_Gui_ScreenFrame_msg; -extern const pb_msgdesc_t PB_Gui_StartScreenStreamRequest_msg; -extern const pb_msgdesc_t PB_Gui_StopScreenStreamRequest_msg; -extern const pb_msgdesc_t PB_Gui_SendInputEventRequest_msg; -extern const pb_msgdesc_t PB_Gui_StartVirtualDisplayRequest_msg; -extern const pb_msgdesc_t PB_Gui_StopVirtualDisplayRequest_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PB_Gui_ScreenFrame_fields &PB_Gui_ScreenFrame_msg -#define PB_Gui_StartScreenStreamRequest_fields &PB_Gui_StartScreenStreamRequest_msg -#define PB_Gui_StopScreenStreamRequest_fields &PB_Gui_StopScreenStreamRequest_msg -#define PB_Gui_SendInputEventRequest_fields &PB_Gui_SendInputEventRequest_msg -#define PB_Gui_StartVirtualDisplayRequest_fields &PB_Gui_StartVirtualDisplayRequest_msg -#define PB_Gui_StopVirtualDisplayRequest_fields &PB_Gui_StopVirtualDisplayRequest_msg - -/* Maximum encoded size of messages (where known) */ -/* PB_Gui_ScreenFrame_size depends on runtime parameters */ -/* PB_Gui_StartVirtualDisplayRequest_size depends on runtime parameters */ -#define PB_Gui_SendInputEventRequest_size 4 -#define PB_Gui_StartScreenStreamRequest_size 0 -#define PB_Gui_StopScreenStreamRequest_size 0 -#define PB_Gui_StopVirtualDisplayRequest_size 0 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/assets/compiled/protobuf_version.h b/assets/compiled/protobuf_version.h deleted file mode 100644 index 6b401411..00000000 --- a/assets/compiled/protobuf_version.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#define PROTOBUF_MAJOR_VERSION 0 -#define PROTOBUF_MINOR_VERSION 7 diff --git a/assets/compiled/storage.pb.c b/assets/compiled/storage.pb.c deleted file mode 100644 index 244b273d..00000000 --- a/assets/compiled/storage.pb.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "storage.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(PB_Storage_File, PB_Storage_File, AUTO) - - -PB_BIND(PB_Storage_InfoRequest, PB_Storage_InfoRequest, AUTO) - - -PB_BIND(PB_Storage_InfoResponse, PB_Storage_InfoResponse, AUTO) - - -PB_BIND(PB_Storage_StatRequest, PB_Storage_StatRequest, AUTO) - - -PB_BIND(PB_Storage_StatResponse, PB_Storage_StatResponse, AUTO) - - -PB_BIND(PB_Storage_ListRequest, PB_Storage_ListRequest, AUTO) - - -PB_BIND(PB_Storage_ListResponse, PB_Storage_ListResponse, AUTO) - - -PB_BIND(PB_Storage_ReadRequest, PB_Storage_ReadRequest, AUTO) - - -PB_BIND(PB_Storage_ReadResponse, PB_Storage_ReadResponse, AUTO) - - -PB_BIND(PB_Storage_WriteRequest, PB_Storage_WriteRequest, AUTO) - - -PB_BIND(PB_Storage_DeleteRequest, PB_Storage_DeleteRequest, AUTO) - - -PB_BIND(PB_Storage_MkdirRequest, PB_Storage_MkdirRequest, AUTO) - - -PB_BIND(PB_Storage_Md5sumRequest, PB_Storage_Md5sumRequest, AUTO) - - -PB_BIND(PB_Storage_Md5sumResponse, PB_Storage_Md5sumResponse, AUTO) - - -PB_BIND(PB_Storage_RenameRequest, PB_Storage_RenameRequest, AUTO) - - -PB_BIND(PB_Storage_BackupCreateRequest, PB_Storage_BackupCreateRequest, AUTO) - - -PB_BIND(PB_Storage_BackupRestoreRequest, PB_Storage_BackupRestoreRequest, AUTO) - - - - diff --git a/assets/compiled/storage.pb.h b/assets/compiled/storage.pb.h deleted file mode 100644 index 9b31dc31..00000000 --- a/assets/compiled/storage.pb.h +++ /dev/null @@ -1,328 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_PB_STORAGE_STORAGE_PB_H_INCLUDED -#define PB_PB_STORAGE_STORAGE_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _PB_Storage_File_FileType { - PB_Storage_File_FileType_FILE = 0, - PB_Storage_File_FileType_DIR = 1 -} PB_Storage_File_FileType; - -/* Struct definitions */ -typedef struct _PB_Storage_BackupCreateRequest { - char *archive_path; -} PB_Storage_BackupCreateRequest; - -typedef struct _PB_Storage_BackupRestoreRequest { - char *archive_path; -} PB_Storage_BackupRestoreRequest; - -typedef struct _PB_Storage_InfoRequest { - char *path; -} PB_Storage_InfoRequest; - -typedef struct _PB_Storage_ListRequest { - char *path; -} PB_Storage_ListRequest; - -typedef struct _PB_Storage_Md5sumRequest { - char *path; -} PB_Storage_Md5sumRequest; - -typedef struct _PB_Storage_MkdirRequest { - char *path; -} PB_Storage_MkdirRequest; - -typedef struct _PB_Storage_ReadRequest { - char *path; -} PB_Storage_ReadRequest; - -typedef struct _PB_Storage_RenameRequest { - char *old_path; - char *new_path; -} PB_Storage_RenameRequest; - -typedef struct _PB_Storage_StatRequest { - char *path; -} PB_Storage_StatRequest; - -typedef struct _PB_Storage_DeleteRequest { - char *path; - bool recursive; -} PB_Storage_DeleteRequest; - -typedef struct _PB_Storage_File { - PB_Storage_File_FileType type; - char *name; - uint32_t size; - pb_bytes_array_t *data; -} PB_Storage_File; - -typedef struct _PB_Storage_InfoResponse { - uint64_t total_space; - uint64_t free_space; -} PB_Storage_InfoResponse; - -typedef struct _PB_Storage_Md5sumResponse { - char md5sum[33]; -} PB_Storage_Md5sumResponse; - -typedef struct _PB_Storage_ListResponse { - pb_size_t file_count; - PB_Storage_File file[8]; -} PB_Storage_ListResponse; - -typedef struct _PB_Storage_ReadResponse { - bool has_file; - PB_Storage_File file; -} PB_Storage_ReadResponse; - -typedef struct _PB_Storage_StatResponse { - bool has_file; - PB_Storage_File file; -} PB_Storage_StatResponse; - -typedef struct _PB_Storage_WriteRequest { - char *path; - bool has_file; - PB_Storage_File file; -} PB_Storage_WriteRequest; - - -/* Helper constants for enums */ -#define _PB_Storage_File_FileType_MIN PB_Storage_File_FileType_FILE -#define _PB_Storage_File_FileType_MAX PB_Storage_File_FileType_DIR -#define _PB_Storage_File_FileType_ARRAYSIZE ((PB_Storage_File_FileType)(PB_Storage_File_FileType_DIR+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define PB_Storage_File_init_default {_PB_Storage_File_FileType_MIN, NULL, 0, NULL} -#define PB_Storage_InfoRequest_init_default {NULL} -#define PB_Storage_InfoResponse_init_default {0, 0} -#define PB_Storage_StatRequest_init_default {NULL} -#define PB_Storage_StatResponse_init_default {false, PB_Storage_File_init_default} -#define PB_Storage_ListRequest_init_default {NULL} -#define PB_Storage_ListResponse_init_default {0, {PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default, PB_Storage_File_init_default}} -#define PB_Storage_ReadRequest_init_default {NULL} -#define PB_Storage_ReadResponse_init_default {false, PB_Storage_File_init_default} -#define PB_Storage_WriteRequest_init_default {NULL, false, PB_Storage_File_init_default} -#define PB_Storage_DeleteRequest_init_default {NULL, 0} -#define PB_Storage_MkdirRequest_init_default {NULL} -#define PB_Storage_Md5sumRequest_init_default {NULL} -#define PB_Storage_Md5sumResponse_init_default {""} -#define PB_Storage_RenameRequest_init_default {NULL, NULL} -#define PB_Storage_BackupCreateRequest_init_default {NULL} -#define PB_Storage_BackupRestoreRequest_init_default {NULL} -#define PB_Storage_File_init_zero {_PB_Storage_File_FileType_MIN, NULL, 0, NULL} -#define PB_Storage_InfoRequest_init_zero {NULL} -#define PB_Storage_InfoResponse_init_zero {0, 0} -#define PB_Storage_StatRequest_init_zero {NULL} -#define PB_Storage_StatResponse_init_zero {false, PB_Storage_File_init_zero} -#define PB_Storage_ListRequest_init_zero {NULL} -#define PB_Storage_ListResponse_init_zero {0, {PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero, PB_Storage_File_init_zero}} -#define PB_Storage_ReadRequest_init_zero {NULL} -#define PB_Storage_ReadResponse_init_zero {false, PB_Storage_File_init_zero} -#define PB_Storage_WriteRequest_init_zero {NULL, false, PB_Storage_File_init_zero} -#define PB_Storage_DeleteRequest_init_zero {NULL, 0} -#define PB_Storage_MkdirRequest_init_zero {NULL} -#define PB_Storage_Md5sumRequest_init_zero {NULL} -#define PB_Storage_Md5sumResponse_init_zero {""} -#define PB_Storage_RenameRequest_init_zero {NULL, NULL} -#define PB_Storage_BackupCreateRequest_init_zero {NULL} -#define PB_Storage_BackupRestoreRequest_init_zero {NULL} - -/* Field tags (for use in manual encoding/decoding) */ -#define PB_Storage_BackupCreateRequest_archive_path_tag 1 -#define PB_Storage_BackupRestoreRequest_archive_path_tag 1 -#define PB_Storage_InfoRequest_path_tag 1 -#define PB_Storage_ListRequest_path_tag 1 -#define PB_Storage_Md5sumRequest_path_tag 1 -#define PB_Storage_MkdirRequest_path_tag 1 -#define PB_Storage_ReadRequest_path_tag 1 -#define PB_Storage_RenameRequest_old_path_tag 1 -#define PB_Storage_RenameRequest_new_path_tag 2 -#define PB_Storage_StatRequest_path_tag 1 -#define PB_Storage_DeleteRequest_path_tag 1 -#define PB_Storage_DeleteRequest_recursive_tag 2 -#define PB_Storage_File_type_tag 1 -#define PB_Storage_File_name_tag 2 -#define PB_Storage_File_size_tag 3 -#define PB_Storage_File_data_tag 4 -#define PB_Storage_InfoResponse_total_space_tag 1 -#define PB_Storage_InfoResponse_free_space_tag 2 -#define PB_Storage_Md5sumResponse_md5sum_tag 1 -#define PB_Storage_ListResponse_file_tag 1 -#define PB_Storage_ReadResponse_file_tag 1 -#define PB_Storage_StatResponse_file_tag 1 -#define PB_Storage_WriteRequest_path_tag 1 -#define PB_Storage_WriteRequest_file_tag 2 - -/* Struct field encoding specification for nanopb */ -#define PB_Storage_File_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, type, 1) \ -X(a, POINTER, SINGULAR, STRING, name, 2) \ -X(a, STATIC, SINGULAR, UINT32, size, 3) \ -X(a, POINTER, SINGULAR, BYTES, data, 4) -#define PB_Storage_File_CALLBACK NULL -#define PB_Storage_File_DEFAULT NULL - -#define PB_Storage_InfoRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_InfoRequest_CALLBACK NULL -#define PB_Storage_InfoRequest_DEFAULT NULL - -#define PB_Storage_InfoResponse_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT64, total_space, 1) \ -X(a, STATIC, SINGULAR, UINT64, free_space, 2) -#define PB_Storage_InfoResponse_CALLBACK NULL -#define PB_Storage_InfoResponse_DEFAULT NULL - -#define PB_Storage_StatRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_StatRequest_CALLBACK NULL -#define PB_Storage_StatRequest_DEFAULT NULL - -#define PB_Storage_StatResponse_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, file, 1) -#define PB_Storage_StatResponse_CALLBACK NULL -#define PB_Storage_StatResponse_DEFAULT NULL -#define PB_Storage_StatResponse_file_MSGTYPE PB_Storage_File - -#define PB_Storage_ListRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_ListRequest_CALLBACK NULL -#define PB_Storage_ListRequest_DEFAULT NULL - -#define PB_Storage_ListResponse_FIELDLIST(X, a) \ -X(a, STATIC, REPEATED, MESSAGE, file, 1) -#define PB_Storage_ListResponse_CALLBACK NULL -#define PB_Storage_ListResponse_DEFAULT NULL -#define PB_Storage_ListResponse_file_MSGTYPE PB_Storage_File - -#define PB_Storage_ReadRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_ReadRequest_CALLBACK NULL -#define PB_Storage_ReadRequest_DEFAULT NULL - -#define PB_Storage_ReadResponse_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, file, 1) -#define PB_Storage_ReadResponse_CALLBACK NULL -#define PB_Storage_ReadResponse_DEFAULT NULL -#define PB_Storage_ReadResponse_file_MSGTYPE PB_Storage_File - -#define PB_Storage_WriteRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, file, 2) -#define PB_Storage_WriteRequest_CALLBACK NULL -#define PB_Storage_WriteRequest_DEFAULT NULL -#define PB_Storage_WriteRequest_file_MSGTYPE PB_Storage_File - -#define PB_Storage_DeleteRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) \ -X(a, STATIC, SINGULAR, BOOL, recursive, 2) -#define PB_Storage_DeleteRequest_CALLBACK NULL -#define PB_Storage_DeleteRequest_DEFAULT NULL - -#define PB_Storage_MkdirRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_MkdirRequest_CALLBACK NULL -#define PB_Storage_MkdirRequest_DEFAULT NULL - -#define PB_Storage_Md5sumRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, path, 1) -#define PB_Storage_Md5sumRequest_CALLBACK NULL -#define PB_Storage_Md5sumRequest_DEFAULT NULL - -#define PB_Storage_Md5sumResponse_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, md5sum, 1) -#define PB_Storage_Md5sumResponse_CALLBACK NULL -#define PB_Storage_Md5sumResponse_DEFAULT NULL - -#define PB_Storage_RenameRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, old_path, 1) \ -X(a, POINTER, SINGULAR, STRING, new_path, 2) -#define PB_Storage_RenameRequest_CALLBACK NULL -#define PB_Storage_RenameRequest_DEFAULT NULL - -#define PB_Storage_BackupCreateRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, archive_path, 1) -#define PB_Storage_BackupCreateRequest_CALLBACK NULL -#define PB_Storage_BackupCreateRequest_DEFAULT NULL - -#define PB_Storage_BackupRestoreRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, archive_path, 1) -#define PB_Storage_BackupRestoreRequest_CALLBACK NULL -#define PB_Storage_BackupRestoreRequest_DEFAULT NULL - -extern const pb_msgdesc_t PB_Storage_File_msg; -extern const pb_msgdesc_t PB_Storage_InfoRequest_msg; -extern const pb_msgdesc_t PB_Storage_InfoResponse_msg; -extern const pb_msgdesc_t PB_Storage_StatRequest_msg; -extern const pb_msgdesc_t PB_Storage_StatResponse_msg; -extern const pb_msgdesc_t PB_Storage_ListRequest_msg; -extern const pb_msgdesc_t PB_Storage_ListResponse_msg; -extern const pb_msgdesc_t PB_Storage_ReadRequest_msg; -extern const pb_msgdesc_t PB_Storage_ReadResponse_msg; -extern const pb_msgdesc_t PB_Storage_WriteRequest_msg; -extern const pb_msgdesc_t PB_Storage_DeleteRequest_msg; -extern const pb_msgdesc_t PB_Storage_MkdirRequest_msg; -extern const pb_msgdesc_t PB_Storage_Md5sumRequest_msg; -extern const pb_msgdesc_t PB_Storage_Md5sumResponse_msg; -extern const pb_msgdesc_t PB_Storage_RenameRequest_msg; -extern const pb_msgdesc_t PB_Storage_BackupCreateRequest_msg; -extern const pb_msgdesc_t PB_Storage_BackupRestoreRequest_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PB_Storage_File_fields &PB_Storage_File_msg -#define PB_Storage_InfoRequest_fields &PB_Storage_InfoRequest_msg -#define PB_Storage_InfoResponse_fields &PB_Storage_InfoResponse_msg -#define PB_Storage_StatRequest_fields &PB_Storage_StatRequest_msg -#define PB_Storage_StatResponse_fields &PB_Storage_StatResponse_msg -#define PB_Storage_ListRequest_fields &PB_Storage_ListRequest_msg -#define PB_Storage_ListResponse_fields &PB_Storage_ListResponse_msg -#define PB_Storage_ReadRequest_fields &PB_Storage_ReadRequest_msg -#define PB_Storage_ReadResponse_fields &PB_Storage_ReadResponse_msg -#define PB_Storage_WriteRequest_fields &PB_Storage_WriteRequest_msg -#define PB_Storage_DeleteRequest_fields &PB_Storage_DeleteRequest_msg -#define PB_Storage_MkdirRequest_fields &PB_Storage_MkdirRequest_msg -#define PB_Storage_Md5sumRequest_fields &PB_Storage_Md5sumRequest_msg -#define PB_Storage_Md5sumResponse_fields &PB_Storage_Md5sumResponse_msg -#define PB_Storage_RenameRequest_fields &PB_Storage_RenameRequest_msg -#define PB_Storage_BackupCreateRequest_fields &PB_Storage_BackupCreateRequest_msg -#define PB_Storage_BackupRestoreRequest_fields &PB_Storage_BackupRestoreRequest_msg - -/* Maximum encoded size of messages (where known) */ -/* PB_Storage_File_size depends on runtime parameters */ -/* PB_Storage_InfoRequest_size depends on runtime parameters */ -/* PB_Storage_StatRequest_size depends on runtime parameters */ -/* PB_Storage_StatResponse_size depends on runtime parameters */ -/* PB_Storage_ListRequest_size depends on runtime parameters */ -/* PB_Storage_ListResponse_size depends on runtime parameters */ -/* PB_Storage_ReadRequest_size depends on runtime parameters */ -/* PB_Storage_ReadResponse_size depends on runtime parameters */ -/* PB_Storage_WriteRequest_size depends on runtime parameters */ -/* PB_Storage_DeleteRequest_size depends on runtime parameters */ -/* PB_Storage_MkdirRequest_size depends on runtime parameters */ -/* PB_Storage_Md5sumRequest_size depends on runtime parameters */ -/* PB_Storage_RenameRequest_size depends on runtime parameters */ -/* PB_Storage_BackupCreateRequest_size depends on runtime parameters */ -/* PB_Storage_BackupRestoreRequest_size depends on runtime parameters */ -#define PB_Storage_InfoResponse_size 22 -#define PB_Storage_Md5sumResponse_size 34 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/assets/compiled/system.pb.c b/assets/compiled/system.pb.c deleted file mode 100644 index e05ff90e..00000000 --- a/assets/compiled/system.pb.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "system.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(PB_System_PingRequest, PB_System_PingRequest, AUTO) - - -PB_BIND(PB_System_PingResponse, PB_System_PingResponse, AUTO) - - -PB_BIND(PB_System_RebootRequest, PB_System_RebootRequest, AUTO) - - -PB_BIND(PB_System_DeviceInfoRequest, PB_System_DeviceInfoRequest, AUTO) - - -PB_BIND(PB_System_DeviceInfoResponse, PB_System_DeviceInfoResponse, AUTO) - - -PB_BIND(PB_System_FactoryResetRequest, PB_System_FactoryResetRequest, AUTO) - - -PB_BIND(PB_System_GetDateTimeRequest, PB_System_GetDateTimeRequest, AUTO) - - -PB_BIND(PB_System_GetDateTimeResponse, PB_System_GetDateTimeResponse, AUTO) - - -PB_BIND(PB_System_SetDateTimeRequest, PB_System_SetDateTimeRequest, AUTO) - - -PB_BIND(PB_System_DateTime, PB_System_DateTime, AUTO) - - -PB_BIND(PB_System_PlayAudiovisualAlertRequest, PB_System_PlayAudiovisualAlertRequest, AUTO) - - -PB_BIND(PB_System_ProtobufVersionRequest, PB_System_ProtobufVersionRequest, AUTO) - - -PB_BIND(PB_System_ProtobufVersionResponse, PB_System_ProtobufVersionResponse, AUTO) - - -PB_BIND(PB_System_UpdateRequest, PB_System_UpdateRequest, AUTO) - - -PB_BIND(PB_System_UpdateResponse, PB_System_UpdateResponse, AUTO) - - -PB_BIND(PB_System_PowerInfoRequest, PB_System_PowerInfoRequest, AUTO) - - -PB_BIND(PB_System_PowerInfoResponse, PB_System_PowerInfoResponse, AUTO) - - - - - diff --git a/assets/compiled/system.pb.h b/assets/compiled/system.pb.h deleted file mode 100644 index aef2c75b..00000000 --- a/assets/compiled/system.pb.h +++ /dev/null @@ -1,342 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_PB_SYSTEM_SYSTEM_PB_H_INCLUDED -#define PB_PB_SYSTEM_SYSTEM_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _PB_System_RebootRequest_RebootMode { - PB_System_RebootRequest_RebootMode_OS = 0, - PB_System_RebootRequest_RebootMode_DFU = 1, - PB_System_RebootRequest_RebootMode_UPDATE = 2 -} PB_System_RebootRequest_RebootMode; - -typedef enum _PB_System_UpdateResponse_UpdateResultCode { - PB_System_UpdateResponse_UpdateResultCode_OK = 0, - PB_System_UpdateResponse_UpdateResultCode_ManifestPathInvalid = 1, - PB_System_UpdateResponse_UpdateResultCode_ManifestFolderNotFound = 2, - PB_System_UpdateResponse_UpdateResultCode_ManifestInvalid = 3, - PB_System_UpdateResponse_UpdateResultCode_StageMissing = 4, - PB_System_UpdateResponse_UpdateResultCode_StageIntegrityError = 5, - PB_System_UpdateResponse_UpdateResultCode_ManifestPointerError = 6, - PB_System_UpdateResponse_UpdateResultCode_TargetMismatch = 7 -} PB_System_UpdateResponse_UpdateResultCode; - -/* Struct definitions */ -typedef struct _PB_System_DeviceInfoRequest { - char dummy_field; -} PB_System_DeviceInfoRequest; - -typedef struct _PB_System_DeviceInfoResponse { - char *key; - char *value; -} PB_System_DeviceInfoResponse; - -typedef struct _PB_System_FactoryResetRequest { - char dummy_field; -} PB_System_FactoryResetRequest; - -typedef struct _PB_System_GetDateTimeRequest { - char dummy_field; -} PB_System_GetDateTimeRequest; - -typedef struct _PB_System_PingRequest { - pb_bytes_array_t *data; -} PB_System_PingRequest; - -typedef struct _PB_System_PingResponse { - pb_bytes_array_t *data; -} PB_System_PingResponse; - -typedef struct _PB_System_PlayAudiovisualAlertRequest { - char dummy_field; -} PB_System_PlayAudiovisualAlertRequest; - -typedef struct _PB_System_PowerInfoRequest { - char dummy_field; -} PB_System_PowerInfoRequest; - -typedef struct _PB_System_PowerInfoResponse { - char *key; - char *value; -} PB_System_PowerInfoResponse; - -typedef struct _PB_System_ProtobufVersionRequest { - char dummy_field; -} PB_System_ProtobufVersionRequest; - -typedef struct _PB_System_UpdateRequest { - char *update_manifest; -} PB_System_UpdateRequest; - -typedef struct _PB_System_DateTime { - /* Time */ - uint8_t hour; /* *< Hour in 24H format: 0-23 */ - uint8_t minute; /* *< Minute: 0-59 */ - uint8_t second; /* *< Second: 0-59 */ - /* Date */ - uint8_t day; /* *< Current day: 1-31 */ - uint8_t month; /* *< Current month: 1-12 */ - uint16_t year; /* *< Current year: 2000-2099 */ - uint8_t weekday; /* *< Current weekday: 1-7 */ -} PB_System_DateTime; - -typedef struct _PB_System_ProtobufVersionResponse { - uint32_t major; - uint32_t minor; -} PB_System_ProtobufVersionResponse; - -typedef struct _PB_System_RebootRequest { - PB_System_RebootRequest_RebootMode mode; -} PB_System_RebootRequest; - -typedef struct _PB_System_UpdateResponse { - PB_System_UpdateResponse_UpdateResultCode code; -} PB_System_UpdateResponse; - -typedef struct _PB_System_GetDateTimeResponse { - bool has_datetime; - PB_System_DateTime datetime; -} PB_System_GetDateTimeResponse; - -typedef struct _PB_System_SetDateTimeRequest { - bool has_datetime; - PB_System_DateTime datetime; -} PB_System_SetDateTimeRequest; - - -/* Helper constants for enums */ -#define _PB_System_RebootRequest_RebootMode_MIN PB_System_RebootRequest_RebootMode_OS -#define _PB_System_RebootRequest_RebootMode_MAX PB_System_RebootRequest_RebootMode_UPDATE -#define _PB_System_RebootRequest_RebootMode_ARRAYSIZE ((PB_System_RebootRequest_RebootMode)(PB_System_RebootRequest_RebootMode_UPDATE+1)) - -#define _PB_System_UpdateResponse_UpdateResultCode_MIN PB_System_UpdateResponse_UpdateResultCode_OK -#define _PB_System_UpdateResponse_UpdateResultCode_MAX PB_System_UpdateResponse_UpdateResultCode_TargetMismatch -#define _PB_System_UpdateResponse_UpdateResultCode_ARRAYSIZE ((PB_System_UpdateResponse_UpdateResultCode)(PB_System_UpdateResponse_UpdateResultCode_TargetMismatch+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define PB_System_PingRequest_init_default {NULL} -#define PB_System_PingResponse_init_default {NULL} -#define PB_System_RebootRequest_init_default {_PB_System_RebootRequest_RebootMode_MIN} -#define PB_System_DeviceInfoRequest_init_default {0} -#define PB_System_DeviceInfoResponse_init_default {NULL, NULL} -#define PB_System_FactoryResetRequest_init_default {0} -#define PB_System_GetDateTimeRequest_init_default {0} -#define PB_System_GetDateTimeResponse_init_default {false, PB_System_DateTime_init_default} -#define PB_System_SetDateTimeRequest_init_default {false, PB_System_DateTime_init_default} -#define PB_System_DateTime_init_default {0, 0, 0, 0, 0, 0, 0} -#define PB_System_PlayAudiovisualAlertRequest_init_default {0} -#define PB_System_ProtobufVersionRequest_init_default {0} -#define PB_System_ProtobufVersionResponse_init_default {0, 0} -#define PB_System_UpdateRequest_init_default {NULL} -#define PB_System_UpdateResponse_init_default {_PB_System_UpdateResponse_UpdateResultCode_MIN} -#define PB_System_PowerInfoRequest_init_default {0} -#define PB_System_PowerInfoResponse_init_default {NULL, NULL} -#define PB_System_PingRequest_init_zero {NULL} -#define PB_System_PingResponse_init_zero {NULL} -#define PB_System_RebootRequest_init_zero {_PB_System_RebootRequest_RebootMode_MIN} -#define PB_System_DeviceInfoRequest_init_zero {0} -#define PB_System_DeviceInfoResponse_init_zero {NULL, NULL} -#define PB_System_FactoryResetRequest_init_zero {0} -#define PB_System_GetDateTimeRequest_init_zero {0} -#define PB_System_GetDateTimeResponse_init_zero {false, PB_System_DateTime_init_zero} -#define PB_System_SetDateTimeRequest_init_zero {false, PB_System_DateTime_init_zero} -#define PB_System_DateTime_init_zero {0, 0, 0, 0, 0, 0, 0} -#define PB_System_PlayAudiovisualAlertRequest_init_zero {0} -#define PB_System_ProtobufVersionRequest_init_zero {0} -#define PB_System_ProtobufVersionResponse_init_zero {0, 0} -#define PB_System_UpdateRequest_init_zero {NULL} -#define PB_System_UpdateResponse_init_zero {_PB_System_UpdateResponse_UpdateResultCode_MIN} -#define PB_System_PowerInfoRequest_init_zero {0} -#define PB_System_PowerInfoResponse_init_zero {NULL, NULL} - -/* Field tags (for use in manual encoding/decoding) */ -#define PB_System_DeviceInfoResponse_key_tag 1 -#define PB_System_DeviceInfoResponse_value_tag 2 -#define PB_System_PingRequest_data_tag 1 -#define PB_System_PingResponse_data_tag 1 -#define PB_System_PowerInfoResponse_key_tag 1 -#define PB_System_PowerInfoResponse_value_tag 2 -#define PB_System_UpdateRequest_update_manifest_tag 1 -#define PB_System_DateTime_hour_tag 1 -#define PB_System_DateTime_minute_tag 2 -#define PB_System_DateTime_second_tag 3 -#define PB_System_DateTime_day_tag 4 -#define PB_System_DateTime_month_tag 5 -#define PB_System_DateTime_year_tag 6 -#define PB_System_DateTime_weekday_tag 7 -#define PB_System_ProtobufVersionResponse_major_tag 1 -#define PB_System_ProtobufVersionResponse_minor_tag 2 -#define PB_System_RebootRequest_mode_tag 1 -#define PB_System_UpdateResponse_code_tag 1 -#define PB_System_GetDateTimeResponse_datetime_tag 1 -#define PB_System_SetDateTimeRequest_datetime_tag 1 - -/* Struct field encoding specification for nanopb */ -#define PB_System_PingRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, BYTES, data, 1) -#define PB_System_PingRequest_CALLBACK NULL -#define PB_System_PingRequest_DEFAULT NULL - -#define PB_System_PingResponse_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, BYTES, data, 1) -#define PB_System_PingResponse_CALLBACK NULL -#define PB_System_PingResponse_DEFAULT NULL - -#define PB_System_RebootRequest_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, mode, 1) -#define PB_System_RebootRequest_CALLBACK NULL -#define PB_System_RebootRequest_DEFAULT NULL - -#define PB_System_DeviceInfoRequest_FIELDLIST(X, a) \ - -#define PB_System_DeviceInfoRequest_CALLBACK NULL -#define PB_System_DeviceInfoRequest_DEFAULT NULL - -#define PB_System_DeviceInfoResponse_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, key, 1) \ -X(a, POINTER, SINGULAR, STRING, value, 2) -#define PB_System_DeviceInfoResponse_CALLBACK NULL -#define PB_System_DeviceInfoResponse_DEFAULT NULL - -#define PB_System_FactoryResetRequest_FIELDLIST(X, a) \ - -#define PB_System_FactoryResetRequest_CALLBACK NULL -#define PB_System_FactoryResetRequest_DEFAULT NULL - -#define PB_System_GetDateTimeRequest_FIELDLIST(X, a) \ - -#define PB_System_GetDateTimeRequest_CALLBACK NULL -#define PB_System_GetDateTimeRequest_DEFAULT NULL - -#define PB_System_GetDateTimeResponse_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, datetime, 1) -#define PB_System_GetDateTimeResponse_CALLBACK NULL -#define PB_System_GetDateTimeResponse_DEFAULT NULL -#define PB_System_GetDateTimeResponse_datetime_MSGTYPE PB_System_DateTime - -#define PB_System_SetDateTimeRequest_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, datetime, 1) -#define PB_System_SetDateTimeRequest_CALLBACK NULL -#define PB_System_SetDateTimeRequest_DEFAULT NULL -#define PB_System_SetDateTimeRequest_datetime_MSGTYPE PB_System_DateTime - -#define PB_System_DateTime_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, hour, 1) \ -X(a, STATIC, SINGULAR, UINT32, minute, 2) \ -X(a, STATIC, SINGULAR, UINT32, second, 3) \ -X(a, STATIC, SINGULAR, UINT32, day, 4) \ -X(a, STATIC, SINGULAR, UINT32, month, 5) \ -X(a, STATIC, SINGULAR, UINT32, year, 6) \ -X(a, STATIC, SINGULAR, UINT32, weekday, 7) -#define PB_System_DateTime_CALLBACK NULL -#define PB_System_DateTime_DEFAULT NULL - -#define PB_System_PlayAudiovisualAlertRequest_FIELDLIST(X, a) \ - -#define PB_System_PlayAudiovisualAlertRequest_CALLBACK NULL -#define PB_System_PlayAudiovisualAlertRequest_DEFAULT NULL - -#define PB_System_ProtobufVersionRequest_FIELDLIST(X, a) \ - -#define PB_System_ProtobufVersionRequest_CALLBACK NULL -#define PB_System_ProtobufVersionRequest_DEFAULT NULL - -#define PB_System_ProtobufVersionResponse_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, major, 1) \ -X(a, STATIC, SINGULAR, UINT32, minor, 2) -#define PB_System_ProtobufVersionResponse_CALLBACK NULL -#define PB_System_ProtobufVersionResponse_DEFAULT NULL - -#define PB_System_UpdateRequest_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, update_manifest, 1) -#define PB_System_UpdateRequest_CALLBACK NULL -#define PB_System_UpdateRequest_DEFAULT NULL - -#define PB_System_UpdateResponse_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, code, 1) -#define PB_System_UpdateResponse_CALLBACK NULL -#define PB_System_UpdateResponse_DEFAULT NULL - -#define PB_System_PowerInfoRequest_FIELDLIST(X, a) \ - -#define PB_System_PowerInfoRequest_CALLBACK NULL -#define PB_System_PowerInfoRequest_DEFAULT NULL - -#define PB_System_PowerInfoResponse_FIELDLIST(X, a) \ -X(a, POINTER, SINGULAR, STRING, key, 1) \ -X(a, POINTER, SINGULAR, STRING, value, 2) -#define PB_System_PowerInfoResponse_CALLBACK NULL -#define PB_System_PowerInfoResponse_DEFAULT NULL - -extern const pb_msgdesc_t PB_System_PingRequest_msg; -extern const pb_msgdesc_t PB_System_PingResponse_msg; -extern const pb_msgdesc_t PB_System_RebootRequest_msg; -extern const pb_msgdesc_t PB_System_DeviceInfoRequest_msg; -extern const pb_msgdesc_t PB_System_DeviceInfoResponse_msg; -extern const pb_msgdesc_t PB_System_FactoryResetRequest_msg; -extern const pb_msgdesc_t PB_System_GetDateTimeRequest_msg; -extern const pb_msgdesc_t PB_System_GetDateTimeResponse_msg; -extern const pb_msgdesc_t PB_System_SetDateTimeRequest_msg; -extern const pb_msgdesc_t PB_System_DateTime_msg; -extern const pb_msgdesc_t PB_System_PlayAudiovisualAlertRequest_msg; -extern const pb_msgdesc_t PB_System_ProtobufVersionRequest_msg; -extern const pb_msgdesc_t PB_System_ProtobufVersionResponse_msg; -extern const pb_msgdesc_t PB_System_UpdateRequest_msg; -extern const pb_msgdesc_t PB_System_UpdateResponse_msg; -extern const pb_msgdesc_t PB_System_PowerInfoRequest_msg; -extern const pb_msgdesc_t PB_System_PowerInfoResponse_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define PB_System_PingRequest_fields &PB_System_PingRequest_msg -#define PB_System_PingResponse_fields &PB_System_PingResponse_msg -#define PB_System_RebootRequest_fields &PB_System_RebootRequest_msg -#define PB_System_DeviceInfoRequest_fields &PB_System_DeviceInfoRequest_msg -#define PB_System_DeviceInfoResponse_fields &PB_System_DeviceInfoResponse_msg -#define PB_System_FactoryResetRequest_fields &PB_System_FactoryResetRequest_msg -#define PB_System_GetDateTimeRequest_fields &PB_System_GetDateTimeRequest_msg -#define PB_System_GetDateTimeResponse_fields &PB_System_GetDateTimeResponse_msg -#define PB_System_SetDateTimeRequest_fields &PB_System_SetDateTimeRequest_msg -#define PB_System_DateTime_fields &PB_System_DateTime_msg -#define PB_System_PlayAudiovisualAlertRequest_fields &PB_System_PlayAudiovisualAlertRequest_msg -#define PB_System_ProtobufVersionRequest_fields &PB_System_ProtobufVersionRequest_msg -#define PB_System_ProtobufVersionResponse_fields &PB_System_ProtobufVersionResponse_msg -#define PB_System_UpdateRequest_fields &PB_System_UpdateRequest_msg -#define PB_System_UpdateResponse_fields &PB_System_UpdateResponse_msg -#define PB_System_PowerInfoRequest_fields &PB_System_PowerInfoRequest_msg -#define PB_System_PowerInfoResponse_fields &PB_System_PowerInfoResponse_msg - -/* Maximum encoded size of messages (where known) */ -/* PB_System_PingRequest_size depends on runtime parameters */ -/* PB_System_PingResponse_size depends on runtime parameters */ -/* PB_System_DeviceInfoResponse_size depends on runtime parameters */ -/* PB_System_UpdateRequest_size depends on runtime parameters */ -/* PB_System_PowerInfoResponse_size depends on runtime parameters */ -#define PB_System_DateTime_size 22 -#define PB_System_DeviceInfoRequest_size 0 -#define PB_System_FactoryResetRequest_size 0 -#define PB_System_GetDateTimeRequest_size 0 -#define PB_System_GetDateTimeResponse_size 24 -#define PB_System_PlayAudiovisualAlertRequest_size 0 -#define PB_System_PowerInfoRequest_size 0 -#define PB_System_ProtobufVersionRequest_size 0 -#define PB_System_ProtobufVersionResponse_size 12 -#define PB_System_RebootRequest_size 2 -#define PB_System_SetDateTimeRequest_size 24 -#define PB_System_UpdateResponse_size 2 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/assets/copro.mk b/assets/copro.mk deleted file mode 100644 index eb9b83b7..00000000 --- a/assets/copro.mk +++ /dev/null @@ -1,14 +0,0 @@ -COPRO_CUBE_VERSION := 1.13.3 -COPRO_MCU_FAMILY := STM32WB5x -COPRO_STACK_BIN ?= stm32wb5x_BLE_Stack_light_fw.bin -# See __STACK_TYPE_CODES in scripts/flipper/assets/coprobin.py -COPRO_STACK_TYPE ?= ble_light -COPRO_DISCLAIMER ?= -COPRO_OB_DATA ?= ob.data -# Keep 0 for auto, or put a value from release_notes for chosen stack -COPRO_STACK_ADDR := 0 - -COPRO_BUNDLE_DIR := $(ASSETS_DIR)/core2_firmware -COPRO_CUBE_DIR := $(PROJECT_ROOT)/lib/STM32CubeWB -COPRO_FIRMWARE_DIR := $(COPRO_CUBE_DIR)/Projects/STM32WB_Copro_Wireless_Binaries/$(COPRO_MCU_FAMILY) -COPRO_STACK_BIN_PATH := $(COPRO_FIRMWARE_DIR)/$(COPRO_STACK_BIN) diff --git a/assets/icons/About/Certification1_103x23.png b/assets/icons/About/Certification1_103x23.png deleted file mode 100644 index 4713dc35..00000000 Binary files a/assets/icons/About/Certification1_103x23.png and /dev/null differ diff --git a/assets/icons/About/Certification1_103x56.png b/assets/icons/About/Certification1_103x56.png new file mode 100644 index 00000000..6e11bbbb Binary files /dev/null and b/assets/icons/About/Certification1_103x56.png differ diff --git a/assets/icons/About/Certification2_119x30.png b/assets/icons/About/Certification2_119x30.png deleted file mode 100644 index 8b01b0d1..00000000 Binary files a/assets/icons/About/Certification2_119x30.png and /dev/null differ diff --git a/assets/icons/About/Certification2_98x33.png b/assets/icons/About/Certification2_98x33.png new file mode 100644 index 00000000..49c5581c Binary files /dev/null and b/assets/icons/About/Certification2_98x33.png differ diff --git a/assets/icons/Archive/back_10px.png b/assets/icons/Archive/back_10px.png index 008efe82..f9c615a9 100644 Binary files a/assets/icons/Archive/back_10px.png and b/assets/icons/Archive/back_10px.png differ diff --git a/assets/icons/Common/Loading_24/frame_01.png b/assets/icons/Common/Loading_24/frame_01.png index 438f971f..d1f35692 100644 Binary files a/assets/icons/Common/Loading_24/frame_01.png and b/assets/icons/Common/Loading_24/frame_01.png differ diff --git a/assets/icons/Common/Loading_24/frame_02.png b/assets/icons/Common/Loading_24/frame_02.png index 3455cd40..b1617692 100644 Binary files a/assets/icons/Common/Loading_24/frame_02.png and b/assets/icons/Common/Loading_24/frame_02.png differ diff --git a/assets/icons/Common/Loading_24/frame_03.png b/assets/icons/Common/Loading_24/frame_03.png index 76d48a4d..a915f527 100644 Binary files a/assets/icons/Common/Loading_24/frame_03.png and b/assets/icons/Common/Loading_24/frame_03.png differ diff --git a/assets/icons/Common/Loading_24/frame_04.png b/assets/icons/Common/Loading_24/frame_04.png index 12d127e0..7f55b0df 100644 Binary files a/assets/icons/Common/Loading_24/frame_04.png and b/assets/icons/Common/Loading_24/frame_04.png differ diff --git a/assets/icons/Common/Loading_24/frame_05.png b/assets/icons/Common/Loading_24/frame_05.png index bfab3eca..29d5c6aa 100644 Binary files a/assets/icons/Common/Loading_24/frame_05.png and b/assets/icons/Common/Loading_24/frame_05.png differ diff --git a/assets/icons/Common/Loading_24/frame_06.png b/assets/icons/Common/Loading_24/frame_06.png index a876adc5..3354ecda 100644 Binary files a/assets/icons/Common/Loading_24/frame_06.png and b/assets/icons/Common/Loading_24/frame_06.png differ diff --git a/assets/icons/Common/Loading_24/frame_07.png b/assets/icons/Common/Loading_24/frame_07.png index 04049ebd..70bb37f6 100644 Binary files a/assets/icons/Common/Loading_24/frame_07.png and b/assets/icons/Common/Loading_24/frame_07.png differ diff --git a/assets/icons/Dolphin/DolphinFirstStart5_54x49.png b/assets/icons/Dolphin/DolphinFirstStart5_54x49.png index 44ad3ef1..28ee477f 100644 Binary files a/assets/icons/Dolphin/DolphinFirstStart5_54x49.png and b/assets/icons/Dolphin/DolphinFirstStart5_54x49.png differ diff --git a/assets/slideshow/update_default/frame_00.png b/assets/slideshow/update_default/frame_00.png new file mode 100644 index 00000000..385fbbe0 Binary files /dev/null and b/assets/slideshow/update_default/frame_00.png differ diff --git a/assets/unit_tests/subghz/power_smart.sub b/assets/unit_tests/subghz/power_smart.sub new file mode 100644 index 00000000..445458b8 --- /dev/null +++ b/assets/unit_tests/subghz/power_smart.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433420000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Power Smart +Bit: 64 +Key: FD C1 36 AC AA 3E C9 52 diff --git a/assets/unit_tests/subghz/power_smart_raw.sub b/assets/unit_tests/subghz/power_smart_raw.sub new file mode 100644 index 00000000..0aafc87c --- /dev/null +++ b/assets/unit_tests/subghz/power_smart_raw.sub @@ -0,0 +1,7 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433420000 +Preset: FuriHalSubGhzPresetOok270Async +Protocol: RAW +RAW_Data: -68 521674 -200 213 -258 217 -218 217 -246 193 -242 211 -466 451 -450 225 -212 211 -242 211 -238 243 -200 223 -254 419 -226 221 -432 251 -212 467 -240 203 -450 449 -246 205 -238 217 -218 217 -444 439 -478 431 -230 211 -462 247 -214 435 -454 449 -456 441 -442 471 -448 449 -246 205 -238 215 -220 217 -244 201 -254 217 -430 235 -220 461 -198 223 -442 275 -212 429 -458 245 -212 203 -228 253 -218 431 -448 451 -442 235 -218 463 -426 485 -214 209 -234 221 -254 219 -214 207 -228 253 -428 459 -418 245 -216 243 -194 241 -212 241 -212 211 -244 441 -228 215 -460 217 -244 435 -236 235 -440 439 -246 213 -208 229 -256 217 -430 445 -450 445 -236 253 -420 225 -232 429 -450 465 -448 439 -448 449 -454 453 -230 225 -214 241 -212 211 -242 211 -244 237 -442 237 -218 429 -230 221 -442 241 -246 425 -458 245 -212 203 -228 255 -218 427 -448 451 -446 235 -256 425 -462 417 -244 251 -208 201 -256 217 -218 209 -232 255 -420 451 -448 217 -242 211 -238 209 -234 221 -256 217 -218 437 -238 217 -464 203 -256 419 -226 223 -464 441 -244 213 -240 197 -254 219 -430 445 -452 479 -204 253 -420 225 -222 463 -452 449 -450 449 -452 447 -450 451 -238 215 -220 217 -244 199 -256 217 -218 207 -440 241 -254 423 -238 217 -462 197 -224 471 -448 225 -220 213 -242 211 -212 465 -446 449 -456 245 -214 437 -456 449 -232 233 -216 219 -254 207 -204 253 -218 219 -440 451 -456 237 -216 217 -254 209 -202 253 -218 219 -210 437 -244 253 -422 237 -218 423 -226 247 -430 451 -242 203 -228 253 -220 217 -442 449 -454 449 -240 217 -430 237 -218 461 -426 453 -450 465 -448 451 -440 443 -246 215 -250 201 -224 255 -218 215 -208 227 -442 239 -208 457 -238 219 -464 201 -256 425 -464 201 -256 217 -210 241 -216 451 -426 445 -486 207 -236 441 -430 479 -194 223 -256 217 -218 209 -234 253 -218 217 -438 449 -454 239 -216 217 -256 207 -202 255 -218 217 -210 439 -244 253 -424 235 -218 457 -224 229 -436 449 -230 221 -214 211 -242 211 -468 447 -450 449 -250 207 -454 239 -218 431 -446 451 -448 443 -486 447 -448 431 -240 207 -232 223 -254 219 -216 209 -230 253 -426 233 -234 433 -244 213 -432 237 -218 463 -446 221 -212 211 -242 239 -208 457 -456 451 -456 223 -212 467 -450 453 -204 253 -218 211 -240 215 -218 255 -208 201 -442 479 -452 203 -254 217 -212 241 -216 217 -256 207 -202 439 -240 245 -430 237 -218 463 -240 217 -428 465 -202 253 -218 213 -234 219 +RAW_Data: -444 443 -452 455 -244 213 -440 237 -254 427 -450 429 -480 417 -454 477 -430 445 -244 217 -250 203 -224 253 -220 215 -206 221 -462 217 -212 467 -234 231 -440 239 -220 427 -446 219 -242 211 -244 237 -206 451 -458 451 -458 203 -254 427 -450 441 -246 213 -242 193 -244 211 -242 211 -212 241 -442 451 -454 245 -214 241 -198 255 -218 217 -210 225 -212 461 -246 213 -440 225 -242 435 -240 209 -456 457 -246 211 -204 229 -254 219 -428 445 -452 445 -238 253 -426 231 -232 435 -448 455 -448 439 -446 449 -456 451 -230 223 -214 241 -212 211 -242 211 -244 237 -442 237 -218 427 -232 221 -442 239 -246 427 -458 245 -212 205 -228 253 -220 427 -446 471 -442 237 -216 451 -462 411 -244 251 -216 205 -222 211 -242 211 -242 211 -480 453 -418 245 -252 207 -202 253 -218 219 -210 229 -256 425 -232 221 -430 251 -212 469 -204 235 -446 441 -246 213 -242 193 -244 211 -464 451 -456 441 -248 215 -450 201 -256 427 -452 457 -450 455 -450 439 -446 451 -238 217 -256 207 -202 255 -218 217 -210 231 -442 237 -244 423 -240 217 -464 203 -254 419 -454 227 -210 243 -212 241 -212 477 -418 453 -484 199 -226 431 -267004 97 -422 97 -164 65 -490 97 -2222 559 -66 163 -64 295 -100 497 -100 263 -98 361 -460 793 -66 1803 -100 339 -68 1733 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 9d1cdd67..df36e125 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -100,3 +100,6 @@ RAW_Data: -202 531 -66 531 -66 1093 -66 1389 -66 1551 -134 2699 -66 1291 -132 65 RAW_Data: -132 2291 -66 3057 -68 2521 -166 333 -134 503 -400 3235 -66 2329 -68 995 -100 333 -100 97 -166 1757 -100 397 -100 165 -66 2755 -132 297 -134 163 -100 565 -100 1793 -100 1813 -162 1293 -98 97 -66 999 -66 1763 -68 261 -68 2391 -100 765 -364 859 -100 1855 -98 1399 -230 463 -134 301 -198 397 -100 961 -68 431 -134 695 -202 133 -100 365 -66 925 -98 165 -66 365 -132 663 -98 4573 -134 1479 -66 1019 -66 629 -66 233 -68 201 -66 569 -66 295 -134 1755 -296 3199 -100 3261 -168 3373 -132 1425 -100 759 -66 895 -98 201 -100 265 -166 99 -66 695 -66 1091 -66 855 -168 299 -100 229 -164 589 -66 521 -66 655 -134 329 -98 493 -200 429 -66 929 -66 673 -100 953 -66 823 -66 1283 -66 1979 -68 233 -66 1547 -164 589 -132 597 -66 131 -66 265 -100 761 -200 759 -66 689 -332 263 -100 1227 -68 1067 -164 2945 -100 959 -100 995 -100 399 -100 1193 -100 625 -66 399 -66 3021 -134 393 -66 4805 -66 1095 -68 231 -332 399 -166 1663 -68 561 -66 927 -98 1085 -164 1155 -98 627 -66 265 -132 263 -130 2211 -66 2159 -66 1029 -264 2669 -66 295 -66 8747 -100 329 -232 625 -134 429 -68 1329 -168 1355 -98 987 -66 1545 -98 1015 -98 699 -134 133 -134 1263 -66 4687 -166 8299 -66 1349 -434 933 -906 443 -452 949 -894 441 -480 909 -486 907 -456 947 -448 949 -434 969 -454 931 -460 941 -448 933 -450 979 -450 945 -450 935 -458 935 -486 927 -456 947 -450 951 -482 945 -428 975 -446 967 -452 955 -458 945 -912 485 -434 971 -902 481 -450 949 -926 451 -478 941 -920 481 -450 949 -920 473 -450 955 -916 471 -452 981 -918 449 -486 945 -910 483 -924 473 -15780 479 -450 967 -948 449 -482 943 -944 485 -468 941 -484 979 -446 1001 -444 999 -446 967 -484 969 -482 979 -478 947 -484 985 -470 973 -458 983 -492 971 -458 979 -494 971 -458 983 -494 973 -458 981 -498 975 -458 1013 -466 973 -952 475 -458 973 -950 489 -450 1011 -916 481 -478 1001 -918 481 -478 1001 -916 481 -478 1001 -920 483 -480 983 -946 479 -458 1013 -932 485 -952 479 -16040 493 -476 1009 -912 515 -464 1007 -910 517 -464 1007 -450 1001 -488 1001 -484 1011 -450 1019 -458 1039 -450 1031 -454 1005 -484 1009 -458 1015 -476 1009 -478 1035 -462 1015 -468 1007 -480 1001 -486 1015 -460 1041 -450 1017 -484 1019 -482 1009 -952 477 -494 1003 -944 485 -478 1013 -944 519 -482 1013 -942 487 -482 1013 -946 487 -484 1015 -944 487 -484 1015 -946 519 -454 1019 -942 505 -952 487 -16238 517 -468 1007 -942 521 -482 1011 -944 519 RAW_Data: -450 1019 -482 1035 -480 1033 -460 1047 -476 1017 -484 1007 -484 1051 -484 1027 -452 1039 -478 1035 -458 1049 -480 1017 -480 1035 -480 1035 -472 1047 -484 1027 -454 1039 -480 1033 -488 1031 -488 1009 -962 521 -486 1017 -966 485 -490 1015 -139210 229 -98 461 -364 165 -334 131 -168 2121 -66 1049 -66 1215 -166 297 -136 1449 -100 3877 -100 1495 -234 331 -64 1345 -262 393 -100 529 -132 2921 -164 1223 -132 1807 -66 765 -66 397 -98 3405 -132 2123 -230 231 -66 2541 -100 2489 -98 4397 -132 461 -98 293 -64 991 -66 1125 -166 401 -100 131 -100 99 -100 265 -100 2555 -100 499 -98 1361 -134 265 -166 895 -100 2253 -100 1057 -100 129 -296 1147 -198 197 -66 1163 -66 1935 -98 1675 -66 1103 -100 891 -100 989 -164 1019 -66 2967 -68 1293 -166 3161 -66 133 -264 1065 -100 731 -66 1693 -66 529 -100 165 -68 865 -66 825 -232 1117 -196 2401 -66 3051 -296 229 -132 1843 -132 1687 -68 1119 -68 299 -68 97 -66 4741 -66 197 -200 2319 -100 1097 -66 3765 -66 131 -100 695 -132 2753 -66 2287 -100 1129 -68 331 -98 1433 -132 893 -100 465 -100 801 -66 529 -66 1515 -264 393 -98 263 -66 1831 -166 3533 -100 633 -100 1051 -100 331 -98 795 -134 959 -132 1229 -100 627 -132 2517 -66 165 -98 131 -66 2301 -166 163 -134 465 -66 2767 -66 1019 -66 401 -134 397 -232 893 -66 397 -66 833 -66 199 -66 303 -66 2775 -66 2069 -98 1841 -100 399 -66 793 -98 2793 -68 3769 -100 867 -66 861 -100 399 -66 1859 -100 631 -132 755 -100 689 -66 163 -64 2045 -64 2191 -102 1127 -68 727 -68 625 -164 1381 -66 1153 -132 1115 -98 1017 -100 491 -100 593 -132 991 -98 1415 -98 4813 -66 331 -98 131 -102 1847 -98 197 -68 263 -100 3265 -66 431 -100 493 -98 435 -134 133 -68 1185 -134 395 -100 131 -66 399 -134 767 -134 1125 -66 429 -198 3185 -100 2261 -66 523 -230 2475 -168 1297 -66 3243 -66 1853 -100 1657 -66 459 -66 827 -100 263 -66 303 -234 197 -166 1167 -100 2299 -66 1329 -68 461 -100 763 -132 3819 -366 757 -66 591 -164 621 -98 1445 -100 2155 -100 231 -100 631 -68 1161 -66 131 -166 67 -98 1915 -166 1891 -66 1261 -68 999 -164 165 -132 133 -168 2695 -68 1055 -198 97 -98 229 -66 229 -66 1215 -66 885 -100 303 -132 297 -164 619 -198 459 -64 989 -66 229 -66 597 -134 693 -64 1255 -100 65 -132 331 -66 199 -98 529 -100 2831 -98 1259 -66 4855 -100 1163 -166 299 -66 395 -98 3141 -66 1319 -66 2139 -100 161 -132 261 -130 821 -200 263 -134 931 -330 65 -98 99 -134 793 RAW_Data: -66 597 -100 231 -68 167 -66 1659 -100 733 -66 1631 -100 165 -66 199 -66 233 -166 165 -100 1925 -68 595 -198 1785 -134 2177 -134 131 -66 1049 -98 3087 -132 195 -64 589 -66 397 -134 329 -66 2565 -164 327 -100 689 -64 1775 -100 5183 -132 1187 -66 329 -66 395 -132 165 -98 261 -98 1247 -64 1217 -66 927 -66 997 -66 199 -98 1419 -66 531 -166 1231 -66 697 -100 97 -66 563 -66 161 -264 3205 -200 525 -98 293 -100 291 -100 133 -66 759 -66 659 -100 983 -64 523 -130 431 -166 919 -66 1097 -100 1757 -66 1119 -66 917 -98 2647 -166 1247 -66 165 -264 1189 -100 899 -134 597 -68 2323 -66 1893 -66 1095 -100 533 -64 965 -100 1817 -130 1215 -66 1879 -64 821 -164 1117 -132 263 -132 131 -66 557 -66 431 -132 661 -100 1183 -98 629 -100 1679 -132 259 -66 623 -98 431 -66 399 -164 923 -100 297 -66 165 -166 2521 -198 99 -66 431 -132 1225 -66 1063 -68 131 -136 631 -66 163 -100 99 -298 965 -68 465 -68 465 -298 2545 -134 2639 -230 1489 -66 299 -66 1991 -234 65 -132 693 -134 429 -102 101 -68 461 -66 3333 -64 1229 -68 333 -66 265 -66 885 -64 3163 -100 467 -66 2651 -164 1221 -100 1527 -66 1259 -134 431 -232 1259 -100 6029 -164 297 -98 1151 -66 1415 -100 5289 -66 2467 -100 493 -132 495 -200 1121 -66 129 -66 757 -166 327 -130 5477 -66 1227 -230 395 -100 265 -132 497 -132 1133 -132 361 -100 1051 -164 3089 -132 1583 -100 65 -68 2315 -100 529 -132 2157 -68 1257 -66 1975 -98 427 -98 1347 -66 719 -164 857 -66 165 -66 1029 -132 297 -132 467 -100 731 -130 1985 -98 199 -166 899 -100 1391 -166 3425 -100 261 -132 721 -66 4845 -98 1193 -68 1225 -66 721 -100 1015 -64 983 -66 557 -130 693 -98 99 -64 1091 -98 197 -100 2321 -66 431 -134 727 -66 467 -102 891 -98 167 -134 2619 -66 393 -64 97 -100 589 -98 1583 -164 301 -68 1481 -98 295 -98 959 -66 365 -98 1253 -66 231 -100 1255 -132 1813 -132 1645 -100 361 -132 395 -100 427 -164 1197 -98 1001 -100 861 -66 1161 -98 195 -100 197 -66 1429 -66 663 -66 1427 -98 665 -66 699 -100 663 -66 855 -196 161 -100 361 -98 823 -66 227 -66 621 -132 1853 -230 461 -230 623 -100 557 -98 229 -98 133 -134 1291 -66 533 -166 627 -134 195 -134 593 -64 591 -66 1019 -66 1049 -262 297 -100 2921 -66 133 -66 963 -134 165 -100 +RAW_Data: -68 521674 -200 213 -258 217 -218 217 -246 193 -242 211 -466 451 -450 225 -212 211 -242 211 -238 243 -200 223 -254 419 -226 221 -432 251 -212 467 -240 203 -450 449 -246 205 -238 217 -218 217 -444 439 -478 431 -230 211 -462 247 -214 435 -454 449 -456 441 -442 471 -448 449 -246 205 -238 215 -220 217 -244 201 -254 217 -430 235 -220 461 -198 223 -442 275 -212 429 -458 245 -212 203 -228 253 -218 431 -448 451 -442 235 -218 463 -426 485 -214 209 -234 221 -254 219 -214 207 -228 253 -428 459 -418 245 -216 243 -194 241 -212 241 -212 211 -244 441 -228 215 -460 217 -244 435 -236 235 -440 439 -246 213 -208 229 -256 217 -430 445 -450 445 -236 253 -420 225 -232 429 -450 465 -448 439 -448 449 -454 453 -230 225 -214 241 -212 211 -242 211 -244 237 -442 237 -218 429 -230 221 -442 241 -246 425 -458 245 -212 203 -228 255 -218 427 -448 451 -446 235 -256 425 -462 417 -244 251 -208 201 -256 217 -218 209 -232 255 -420 451 -448 217 -242 211 -238 209 -234 221 -256 217 -218 437 -238 217 -464 203 -256 419 -226 223 -464 441 -244 213 -240 197 -254 219 -430 445 -452 479 -204 253 -420 225 -222 463 -452 449 -450 449 -452 447 -450 451 -238 215 -220 217 -244 199 -256 217 -218 207 -440 241 -254 423 -238 217 -462 197 -224 471 -448 225 -220 213 -242 211 -212 465 -446 449 -456 245 -214 437 -456 449 -232 233 -216 219 -254 207 -204 253 -218 219 -440 451 -456 237 -216 217 -254 209 -202 253 -218 219 -210 437 -244 253 -422 237 -218 423 -226 247 -430 451 -242 203 -228 253 -220 217 -442 449 -454 449 -240 217 -430 237 -218 461 -426 453 -450 465 -448 451 -440 443 -246 215 -250 201 -224 255 -218 215 -208 227 -442 239 -208 457 -238 219 -464 201 -256 425 -464 201 -256 217 -210 241 -216 451 -426 445 -486 207 -236 441 -430 479 -194 223 -256 217 -218 209 -234 253 -218 217 -438 449 -454 239 -216 217 -256 207 -202 255 -218 217 -210 439 -244 253 -424 235 -218 457 -224 229 -436 449 -230 221 -214 211 -242 211 -468 447 -450 449 -250 207 -454 239 -218 431 -446 451 -448 443 -486 447 -448 431 -240 207 -232 223 -254 219 -216 209 -230 253 -426 233 -234 433 -244 213 -432 237 -218 463 -446 221 -212 211 -242 239 -208 457 -456 451 -456 223 -212 467 -450 453 -204 253 -218 211 -240 215 -218 255 -208 201 -442 479 -452 203 -254 217 -212 241 -216 217 -256 207 -202 439 -240 245 -430 237 -218 463 -240 217 -428 465 -202 253 -218 213 -234 219 +RAW_Data: -444 443 -452 455 -244 213 -440 237 -254 427 -450 429 -480 417 -454 477 -430 445 -244 217 -250 203 -224 253 -220 215 -206 221 -462 217 -212 467 -234 231 -440 239 -220 427 -446 219 -242 211 -244 237 -206 451 -458 451 -458 203 -254 427 -450 441 -246 213 -242 193 -244 211 -242 211 -212 241 -442 451 -454 245 -214 241 -198 255 -218 217 -210 225 -212 461 -246 213 -440 225 -242 435 -240 209 -456 457 -246 211 -204 229 -254 219 -428 445 -452 445 -238 253 -426 231 -232 435 -448 455 -448 439 -446 449 -456 451 -230 223 -214 241 -212 211 -242 211 -244 237 -442 237 -218 427 -232 221 -442 239 -246 427 -458 245 -212 205 -228 253 -220 427 -446 471 -442 237 -216 451 -462 411 -244 251 -216 205 -222 211 -242 211 -242 211 -480 453 -418 245 -252 207 -202 253 -218 219 -210 229 -256 425 -232 221 -430 251 -212 469 -204 235 -446 441 -246 213 -242 193 -244 211 -464 451 -456 441 -248 215 -450 201 -256 427 -452 457 -450 455 -450 439 -446 451 -238 217 -256 207 -202 255 -218 217 -210 231 -442 237 -244 423 -240 217 -464 203 -254 419 -454 227 -210 243 -212 241 -212 477 -418 453 -484 199 -226 431 -267004 97 -422 97 -164 65 -490 97 -2222 559 -66 163 -64 295 -100 497 -100 263 -98 361 -460 793 -66 1803 -100 339 -68 1733 + diff --git a/core/SConscript b/core/SConscript new file mode 100644 index 00000000..83548355 --- /dev/null +++ b/core/SConscript @@ -0,0 +1,13 @@ +Import("env") + +env.Append(LINT_SOURCES=["core"]) + + +libenv = env.Clone(FW_LIB_NAME="core") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/core/core.mk b/core/core.mk deleted file mode 100644 index 59d27c5a..00000000 --- a/core/core.mk +++ /dev/null @@ -1,8 +0,0 @@ -CORE_DIR = $(PROJECT_ROOT)/core - -CFLAGS += -I$(CORE_DIR) -D_GNU_SOURCE -ASM_SOURCES += $(wildcard $(CORE_DIR)/*.s) -C_SOURCES += $(wildcard $(CORE_DIR)/*.c) -C_SOURCES += $(wildcard $(CORE_DIR)/furi/*.c) -C_SOURCES += $(wildcard $(CORE_DIR)/furi_hal/*.c) -CPP_SOURCES += $(wildcard $(CORE_DIR)/*.cpp) diff --git a/core/furi.h b/core/furi.h index 6a0d1b0a..7a36c1ba 100644 --- a/core/furi.h +++ b/core/furi.h @@ -6,16 +6,19 @@ #include -#include #include +#include +#include +#include #include #include +#include #include #include +#include #include #include #include -#include #include diff --git a/core/furi/base.h b/core/furi/base.h new file mode 100644 index 00000000..41873fbd --- /dev/null +++ b/core/furi/base.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +// FreeRTOS part +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Timeout value. +#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. + +// Flags options (\ref furi_thread_flags_wait and \ref osEventFlagsWait). +#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). +#define osFlagsWaitAll 0x00000001U ///< Wait for all flags. +#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. + +// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). +#define osFlagsError 0x80000000U ///< Error indicator. +#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). +#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2). +#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). +#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). +#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). + +/// Status code values returned by CMSIS-RTOS functions. +typedef enum { + osOK = 0, ///< Operation completed successfully. + osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits. + osErrorTimeout = -2, ///< Operation not completed within the timeout period. + osErrorResource = -3, ///< Resource not available. + osErrorParameter = -4, ///< Parameter error. + osErrorNoMemory = + -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. + osErrorISR = + -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. + osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. +} osStatus_t; + +#ifdef __cplusplus +} +#endif diff --git a/core/furi/check.c b/core/furi/check.c index b59e490c..ca945ada 100644 --- a/core/furi/check.c +++ b/core/furi/check.c @@ -6,11 +6,14 @@ #include #include +#include +#include + void __furi_print_name() { if(FURI_IS_ISR()) { furi_hal_console_puts("[ISR] "); } else { - const char* name = osThreadGetName(osThreadGetId()); + const char* name = pcTaskGetName(xTaskGetCurrentTaskHandle()); if(name == NULL) { furi_hal_console_puts("[main] "); } else { diff --git a/core/furi/check.h b/core/furi/check.h index 4165c3c2..30efdf01 100644 --- a/core/furi/check.h +++ b/core/furi/check.h @@ -1,4 +1,5 @@ #pragma once + #ifdef __cplusplus extern "C" { #define FURI_NORETURN [[noreturn]] diff --git a/core/furi/event_flags.c b/core/furi/event_flags.c new file mode 100644 index 00000000..ba8cba48 --- /dev/null +++ b/core/furi/event_flags.c @@ -0,0 +1,222 @@ +#include "event_flags.h" +#include "common_defines.h" + +#include + +#define MAX_BITS_EVENT_GROUPS 24U +#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U)) + +osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t* attr) { + EventGroupHandle_t hEventGroup; + int32_t mem; + + hEventGroup = NULL; + + if(FURI_IS_IRQ_MODE() == 0U) { + mem = -1; + + if(attr != NULL) { + if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) { + /* The memory for control block is provided, use static object */ + mem = 1; + } else { + if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { + /* Control block will be allocated from the dynamic pool */ + mem = 0; + } + } + } else { + mem = 0; + } + + if(mem == 1) { +#if(configSUPPORT_STATIC_ALLOCATION == 1) + hEventGroup = xEventGroupCreateStatic(attr->cb_mem); +#endif + } else { + if(mem == 0) { +#if(configSUPPORT_DYNAMIC_ALLOCATION == 1) + hEventGroup = xEventGroupCreate(); +#endif + } + } + } + + /* Return event flags ID */ + return ((osEventFlagsId_t)hEventGroup); +} + +/* + Set the specified Event Flags. + + Limitations: + - Event flags are limited to 24 bits. +*/ +uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags) { + EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; + uint32_t rflags; + BaseType_t yield; + + if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { + rflags = (uint32_t)osErrorParameter; + } else if(FURI_IS_IRQ_MODE() != 0U) { +#if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0) + (void)yield; + /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */ + rflags = (uint32_t)osErrorResource; +#else + yield = pdFALSE; + + if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) { + rflags = (uint32_t)osErrorResource; + } else { + rflags = flags; + portYIELD_FROM_ISR(yield); + } +#endif + } else { + rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags); + } + + /* Return event flags after setting */ + return (rflags); +} + +/* + Clear the specified Event Flags. + + Limitations: + - Event flags are limited to 24 bits. +*/ +uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags) { + EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; + uint32_t rflags; + + if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { + rflags = (uint32_t)osErrorParameter; + } else if(FURI_IS_IRQ_MODE() != 0U) { +#if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0) + /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */ + rflags = (uint32_t)osErrorResource; +#else + rflags = xEventGroupGetBitsFromISR(hEventGroup); + + if(xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) { + rflags = (uint32_t)osErrorResource; + } else { + /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */ + /* Yield is required here otherwise clear operation might not execute in the right order. */ + /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info. */ + portYIELD_FROM_ISR(pdTRUE); + } +#endif + } else { + rflags = xEventGroupClearBits(hEventGroup, (EventBits_t)flags); + } + + /* Return event flags before clearing */ + return (rflags); +} + +/* + Get the current Event Flags. + + Limitations: + - Event flags are limited to 24 bits. +*/ +uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) { + EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; + uint32_t rflags; + + if(ef_id == NULL) { + rflags = 0U; + } else if(FURI_IS_IRQ_MODE() != 0U) { + rflags = xEventGroupGetBitsFromISR(hEventGroup); + } else { + rflags = xEventGroupGetBits(hEventGroup); + } + + /* Return current event flags */ + return (rflags); +} + +/* + Wait for one or more Event Flags to become signaled. + + Limitations: + - Event flags are limited to 24 bits. + - osEventFlagsWait cannot be called from an ISR. +*/ +uint32_t + osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) { + EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; + BaseType_t wait_all; + BaseType_t exit_clr; + uint32_t rflags; + + if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { + rflags = (uint32_t)osErrorParameter; + } else if(FURI_IS_IRQ_MODE() != 0U) { + rflags = (uint32_t)osErrorISR; + } else { + if(options & osFlagsWaitAll) { + wait_all = pdTRUE; + } else { + wait_all = pdFAIL; + } + + if(options & osFlagsNoClear) { + exit_clr = pdFAIL; + } else { + exit_clr = pdTRUE; + } + + rflags = xEventGroupWaitBits( + hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout); + + if(options & osFlagsWaitAll) { + if((flags & rflags) != flags) { + if(timeout > 0U) { + rflags = (uint32_t)osErrorTimeout; + } else { + rflags = (uint32_t)osErrorResource; + } + } + } else { + if((flags & rflags) == 0U) { + if(timeout > 0U) { + rflags = (uint32_t)osErrorTimeout; + } else { + rflags = (uint32_t)osErrorResource; + } + } + } + } + + /* Return event flags before clearing */ + return (rflags); +} + +/* + Delete an Event Flags object. +*/ +osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) { + EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; + osStatus_t stat; + +#ifndef USE_FreeRTOS_HEAP_1 + if(FURI_IS_IRQ_MODE() != 0U) { + stat = osErrorISR; + } else if(hEventGroup == NULL) { + stat = osErrorParameter; + } else { + stat = osOK; + vEventGroupDelete(hEventGroup); + } +#else + stat = osError; +#endif + + /* Return execution status */ + return (stat); +} diff --git a/core/furi/event_flags.h b/core/furi/event_flags.h new file mode 100644 index 00000000..66aa2d7a --- /dev/null +++ b/core/furi/event_flags.h @@ -0,0 +1,63 @@ +#pragma once + +#include "base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// Attributes structure for event flags. +typedef struct { + const char* name; ///< name of the event flags + uint32_t attr_bits; ///< attribute bits + void* cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osEventFlagsAttr_t; + +/// \details Event Flags ID identifies the event flags. +typedef void* osEventFlagsId_t; + +/// Create and Initialize an Event Flags object. +/// \param[in] attr event flags attributes; NULL: default values. +/// \return event flags ID for reference by other functions or NULL in case of error. +osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t* attr); + +/// Get name of an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return name as null-terminated string. +const char* osEventFlagsGetName(osEventFlagsId_t ef_id); + +/// Set the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be set. +/// \return event flags after setting or error code if highest bit set. +uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags); + +/// Clear the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be cleared. +/// \return event flags before clearing or error code if highest bit set. +uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags); + +/// Get the current Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return current event flags. +uint32_t osEventFlagsGet(osEventFlagsId_t ef_id); + +/// Wait for one or more Event Flags to become signaled. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags to wait for. +/// \param[in] options specifies flags options (osFlagsXxxx). +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return event flags before clearing or error code if highest bit set. +uint32_t + osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout); + +/// Delete an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id); + +#ifdef __cplusplus +} +#endif diff --git a/core/furi/log.c b/core/furi/log.c index 9ce025b9..4653603c 100644 --- a/core/furi/log.c +++ b/core/furi/log.c @@ -1,5 +1,6 @@ #include "log.h" #include "check.h" +#include "mutex.h" #include #include diff --git a/core/furi/memmgr_heap.c b/core/furi/memmgr_heap.c index 618d7e74..92e99b92 100644 --- a/core/furi/memmgr_heap.c +++ b/core/furi/memmgr_heap.c @@ -133,7 +133,7 @@ void memmgr_heap_init() { MemmgrHeapThreadDict_init(memmgr_heap_thread_dict); } -void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) { +void memmgr_heap_enable_thread_trace(FuriThreadId thread_id) { vTaskSuspendAll(); { memmgr_heap_thread_trace_depth++; @@ -147,7 +147,7 @@ void memmgr_heap_enable_thread_trace(osThreadId_t thread_id) { (void)xTaskResumeAll(); } -void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) { +void memmgr_heap_disable_thread_trace(FuriThreadId thread_id) { vTaskSuspendAll(); { memmgr_heap_thread_trace_depth++; @@ -158,7 +158,7 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) { (void)xTaskResumeAll(); } -size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) { +size_t memmgr_heap_get_thread_memory(FuriThreadId thread_id) { size_t leftovers = MEMMGR_HEAP_UNKNOWN; vTaskSuspendAll(); { @@ -192,7 +192,7 @@ size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) { #undef traceMALLOC static inline void traceMALLOC(void* pointer, size_t size) { - osThreadId_t thread_id = osThreadGetId(); + FuriThreadId thread_id = furi_thread_get_current_id(); if(thread_id && memmgr_heap_thread_trace_depth == 0) { memmgr_heap_thread_trace_depth++; MemmgrHeapAllocDict_t* alloc_dict = @@ -207,7 +207,7 @@ static inline void traceMALLOC(void* pointer, size_t size) { #undef traceFREE static inline void traceFREE(void* pointer, size_t size) { UNUSED(size); - osThreadId_t thread_id = osThreadGetId(); + FuriThreadId thread_id = furi_thread_get_current_id(); if(thread_id && memmgr_heap_thread_trace_depth == 0) { memmgr_heap_thread_trace_depth++; MemmgrHeapAllocDict_t* alloc_dict = @@ -297,7 +297,7 @@ static void print_heap_init() { static void print_heap_malloc(void* ptr, size_t size) { char tmp_str[33]; - const char* name = osThreadGetName(osThreadGetId()); + const char* name = furi_thread_get_name(furi_thread_get_current_id()); if(!name) { name = ""; } @@ -318,7 +318,7 @@ static void print_heap_malloc(void* ptr, size_t size) { static void print_heap_free(void* ptr) { char tmp_str[33]; - const char* name = osThreadGetName(osThreadGetId()); + const char* name = furi_thread_get_name(furi_thread_get_current_id()); if(!name) { name = ""; } diff --git a/core/furi/memmgr_heap.h b/core/furi/memmgr_heap.h index 04dced06..f76102ec 100644 --- a/core/furi/memmgr_heap.h +++ b/core/furi/memmgr_heap.h @@ -6,7 +6,7 @@ #pragma once #include -#include +#include "furi/thread.h" #ifdef __cplusplus extern "C" { @@ -18,13 +18,13 @@ extern "C" { * * @param thread_id - thread id to track */ -void memmgr_heap_enable_thread_trace(osThreadId_t thread_id); +void memmgr_heap_enable_thread_trace(FuriThreadId taks_handle); /** Memmgr heap disable thread allocation tracking * * @param thread_id - thread id to track */ -void memmgr_heap_disable_thread_trace(osThreadId_t thread_id); +void memmgr_heap_disable_thread_trace(FuriThreadId taks_handle); /** Memmgr heap get allocatred thread memory * @@ -32,7 +32,7 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id); * * @return bytes allocated right now */ -size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id); +size_t memmgr_heap_get_thread_memory(FuriThreadId taks_handle); /** Memmgr heap get the max contiguous block size on the heap * diff --git a/core/furi/mutex.c b/core/furi/mutex.c new file mode 100644 index 00000000..42f1d528 --- /dev/null +++ b/core/furi/mutex.c @@ -0,0 +1,217 @@ +#include "mutex.h" +#include "check.h" +#include "common_defines.h" + +#include + +osMutexId_t osMutexNew(const osMutexAttr_t* attr) { + SemaphoreHandle_t hMutex; + uint32_t type; + uint32_t rmtx; + int32_t mem; + + hMutex = NULL; + + if(FURI_IS_IRQ_MODE() == 0U) { + if(attr != NULL) { + type = attr->attr_bits; + } else { + type = 0U; + } + + if((type & osMutexRecursive) == osMutexRecursive) { + rmtx = 1U; + } else { + rmtx = 0U; + } + + if((type & osMutexRobust) != osMutexRobust) { + mem = -1; + + if(attr != NULL) { + if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) { + /* The memory for control block is provided, use static object */ + mem = 1; + } else { + if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { + /* Control block will be allocated from the dynamic pool */ + mem = 0; + } + } + } else { + mem = 0; + } + + if(mem == 1) { +#if(configSUPPORT_STATIC_ALLOCATION == 1) + if(rmtx != 0U) { +#if(configUSE_RECURSIVE_MUTEXES == 1) + hMutex = xSemaphoreCreateRecursiveMutexStatic(attr->cb_mem); +#endif + } else { + hMutex = xSemaphoreCreateMutexStatic(attr->cb_mem); + } +#endif + } else { + if(mem == 0) { +#if(configSUPPORT_DYNAMIC_ALLOCATION == 1) + if(rmtx != 0U) { +#if(configUSE_RECURSIVE_MUTEXES == 1) + hMutex = xSemaphoreCreateRecursiveMutex(); +#endif + } else { + hMutex = xSemaphoreCreateMutex(); + } +#endif + } + } + +#if(configQUEUE_REGISTRY_SIZE > 0) + if(hMutex != NULL) { + if((attr != NULL) && (attr->name != NULL)) { + /* Only non-NULL name objects are added to the Queue Registry */ + vQueueAddToRegistry(hMutex, attr->name); + } + } +#endif + + if((hMutex != NULL) && (rmtx != 0U)) { + /* Set LSB as 'recursive mutex flag' */ + hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U); + } + } + } + + /* Return mutex ID */ + return ((osMutexId_t)hMutex); +} + +/* + Acquire a Mutex or timeout if it is locked. +*/ +osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) { + SemaphoreHandle_t hMutex; + osStatus_t stat; + uint32_t rmtx; + + hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); + + /* Extract recursive mutex flag */ + rmtx = (uint32_t)mutex_id & 1U; + + stat = osOK; + + if(FURI_IS_IRQ_MODE() != 0U) { + stat = osErrorISR; + } else if(hMutex == NULL) { + stat = osErrorParameter; + } else { + if(rmtx != 0U) { +#if(configUSE_RECURSIVE_MUTEXES == 1) + if(xSemaphoreTakeRecursive(hMutex, timeout) != pdPASS) { + if(timeout != 0U) { + stat = osErrorTimeout; + } else { + stat = osErrorResource; + } + } +#endif + } else { + if(xSemaphoreTake(hMutex, timeout) != pdPASS) { + if(timeout != 0U) { + stat = osErrorTimeout; + } else { + stat = osErrorResource; + } + } + } + } + + /* Return execution status */ + return (stat); +} + +/* + Release a Mutex that was acquired by osMutexAcquire. +*/ +osStatus_t osMutexRelease(osMutexId_t mutex_id) { + SemaphoreHandle_t hMutex; + osStatus_t stat; + uint32_t rmtx; + + hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); + + /* Extract recursive mutex flag */ + rmtx = (uint32_t)mutex_id & 1U; + + stat = osOK; + + if(FURI_IS_IRQ_MODE() != 0U) { + stat = osErrorISR; + } else if(hMutex == NULL) { + stat = osErrorParameter; + } else { + if(rmtx != 0U) { +#if(configUSE_RECURSIVE_MUTEXES == 1) + if(xSemaphoreGiveRecursive(hMutex) != pdPASS) { + stat = osErrorResource; + } +#endif + } else { + if(xSemaphoreGive(hMutex) != pdPASS) { + stat = osErrorResource; + } + } + } + + /* Return execution status */ + return (stat); +} + +/* + Get Thread which owns a Mutex object. +*/ +FuriThreadId osMutexGetOwner(osMutexId_t mutex_id) { + SemaphoreHandle_t hMutex; + FuriThreadId owner; + + hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); + + if((FURI_IS_IRQ_MODE() != 0U) || (hMutex == NULL)) { + owner = 0; + } else { + owner = (FuriThreadId)xSemaphoreGetMutexHolder(hMutex); + } + + /* Return owner thread ID */ + return (owner); +} + +/* + Delete a Mutex object. +*/ +osStatus_t osMutexDelete(osMutexId_t mutex_id) { + osStatus_t stat; +#ifndef USE_FreeRTOS_HEAP_1 + SemaphoreHandle_t hMutex; + + hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); + + if(FURI_IS_IRQ_MODE() != 0U) { + stat = osErrorISR; + } else if(hMutex == NULL) { + stat = osErrorParameter; + } else { +#if(configQUEUE_REGISTRY_SIZE > 0) + vQueueUnregisterQueue(hMutex); +#endif + stat = osOK; + vSemaphoreDelete(hMutex); + } +#else + stat = osError; +#endif + + /* Return execution status */ + return (stat); +} diff --git a/core/furi/mutex.h b/core/furi/mutex.h new file mode 100644 index 00000000..44f351b7 --- /dev/null +++ b/core/furi/mutex.h @@ -0,0 +1,56 @@ +#pragma once + +#include "base.h" +#include "thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Mutex attributes (attr_bits in \ref osMutexAttr_t). +#define osMutexRecursive 0x00000001U ///< Recursive mutex. +#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol. +#define osMutexRobust 0x00000008U ///< Robust mutex. + +/// Attributes structure for mutex. +typedef struct { + const char* name; ///< name of the mutex + uint32_t attr_bits; ///< attribute bits + void* cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osMutexAttr_t; + +/// \details Mutex ID identifies the mutex. +typedef void* osMutexId_t; + +/// Create and Initialize a Mutex object. +/// \param[in] attr mutex attributes; NULL: default values. +/// \return mutex ID for reference by other functions or NULL in case of error. +osMutexId_t osMutexNew(const osMutexAttr_t* attr); + +/// Get name of a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return name as null-terminated string. +const char* osMutexGetName(osMutexId_t mutex_id); + +/// Acquire a Mutex or timeout if it is locked. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout); + +/// Release a Mutex that was acquired by \ref osMutexAcquire. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexRelease(osMutexId_t mutex_id); + +/// Delete a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexDelete(osMutexId_t mutex_id); + +FuriThreadId osMutexGetOwner(osMutexId_t mutex_id); + +#ifdef __cplusplus +} +#endif diff --git a/core/furi/pubsub.c b/core/furi/pubsub.c index 8e9adda8..88839ec2 100644 --- a/core/furi/pubsub.c +++ b/core/furi/pubsub.c @@ -1,9 +1,9 @@ #include "pubsub.h" #include "memmgr.h" #include "check.h" +#include "mutex.h" #include -#include struct FuriPubSubSubscription { FuriPubSubCallback callback; diff --git a/core/furi/record.c b/core/furi/record.c index 501091d4..d7afbf9c 100644 --- a/core/furi/record.c +++ b/core/furi/record.c @@ -1,8 +1,9 @@ #include "record.h" #include "check.h" #include "memmgr.h" +#include "mutex.h" +#include "event_flags.h" -#include #include #include diff --git a/core/furi/semaphore.c b/core/furi/semaphore.c new file mode 100644 index 00000000..cbacdef0 --- /dev/null +++ b/core/furi/semaphore.c @@ -0,0 +1,190 @@ +#include "semaphore.h" +#include "check.h" +#include "common_defines.h" + +#include + +osSemaphoreId_t + osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t* attr) { + SemaphoreHandle_t hSemaphore; + int32_t mem; + + hSemaphore = NULL; + + if((FURI_IS_IRQ_MODE() == 0U) && (max_count > 0U) && (initial_count <= max_count)) { + mem = -1; + + if(attr != NULL) { + if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) { + /* The memory for control block is provided, use static object */ + mem = 1; + } else { + if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { + /* Control block will be allocated from the dynamic pool */ + mem = 0; + } + } + } else { + mem = 0; + } + + if(mem != -1) { + if(max_count == 1U) { + if(mem == 1) { +#if(configSUPPORT_STATIC_ALLOCATION == 1) + hSemaphore = xSemaphoreCreateBinaryStatic((StaticSemaphore_t*)attr->cb_mem); +#endif + } else { +#if(configSUPPORT_DYNAMIC_ALLOCATION == 1) + hSemaphore = xSemaphoreCreateBinary(); +#endif + } + + if((hSemaphore != NULL) && (initial_count != 0U)) { + if(xSemaphoreGive(hSemaphore) != pdPASS) { + vSemaphoreDelete(hSemaphore); + hSemaphore = NULL; + } + } + } else { + if(mem == 1) { +#if(configSUPPORT_STATIC_ALLOCATION == 1) + hSemaphore = xSemaphoreCreateCountingStatic( + max_count, initial_count, (StaticSemaphore_t*)attr->cb_mem); +#endif + } else { +#if(configSUPPORT_DYNAMIC_ALLOCATION == 1) + hSemaphore = xSemaphoreCreateCounting(max_count, initial_count); +#endif + } + } + +#if(configQUEUE_REGISTRY_SIZE > 0) + if(hSemaphore != NULL) { + if((attr != NULL) && (attr->name != NULL)) { + /* Only non-NULL name objects are added to the Queue Registry */ + vQueueAddToRegistry(hSemaphore, attr->name); + } + } +#endif + } + } + + /* Return semaphore ID */ + return ((osSemaphoreId_t)hSemaphore); +} + +/* + Acquire a Semaphore token or timeout if no tokens are available. +*/ +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) { + SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; + osStatus_t stat; + BaseType_t yield; + + stat = osOK; + + if(hSemaphore == NULL) { + stat = osErrorParameter; + } else if(FURI_IS_IRQ_MODE() != 0U) { + if(timeout != 0U) { + stat = osErrorParameter; + } else { + yield = pdFALSE; + + if(xSemaphoreTakeFromISR(hSemaphore, &yield) != pdPASS) { + stat = osErrorResource; + } else { + portYIELD_FROM_ISR(yield); + } + } + } else { + if(xSemaphoreTake(hSemaphore, (TickType_t)timeout) != pdPASS) { + if(timeout != 0U) { + stat = osErrorTimeout; + } else { + stat = osErrorResource; + } + } + } + + /* Return execution status */ + return (stat); +} + +/* + Release a Semaphore token up to the initial maximum count. +*/ +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) { + SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; + osStatus_t stat; + BaseType_t yield; + + stat = osOK; + + if(hSemaphore == NULL) { + stat = osErrorParameter; + } else if(FURI_IS_IRQ_MODE() != 0U) { + yield = pdFALSE; + + if(xSemaphoreGiveFromISR(hSemaphore, &yield) != pdTRUE) { + stat = osErrorResource; + } else { + portYIELD_FROM_ISR(yield); + } + } else { + if(xSemaphoreGive(hSemaphore) != pdPASS) { + stat = osErrorResource; + } + } + + /* Return execution status */ + return (stat); +} + +/* + Get current Semaphore token count. +*/ +uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) { + SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; + uint32_t count; + + if(hSemaphore == NULL) { + count = 0U; + } else if(FURI_IS_IRQ_MODE() != 0U) { + count = (uint32_t)uxSemaphoreGetCountFromISR(hSemaphore); + } else { + count = (uint32_t)uxSemaphoreGetCount(hSemaphore); + } + + /* Return number of tokens */ + return (count); +} + +/* + Delete a Semaphore object. +*/ +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) { + SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; + osStatus_t stat; + +#ifndef USE_FreeRTOS_HEAP_1 + if(FURI_IS_IRQ_MODE() != 0U) { + stat = osErrorISR; + } else if(hSemaphore == NULL) { + stat = osErrorParameter; + } else { +#if(configQUEUE_REGISTRY_SIZE > 0) + vQueueUnregisterQueue(hSemaphore); +#endif + + stat = osOK; + vSemaphoreDelete(hSemaphore); + } +#else + stat = osError; +#endif + + /* Return execution status */ + return (stat); +} diff --git a/core/furi/semaphore.h b/core/furi/semaphore.h new file mode 100644 index 00000000..b4de78fd --- /dev/null +++ b/core/furi/semaphore.h @@ -0,0 +1,57 @@ +#pragma once + +#include "base.h" +#include "thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// Attributes structure for semaphore. +typedef struct { + const char* name; ///< name of the semaphore + uint32_t attr_bits; ///< attribute bits + void* cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block +} osSemaphoreAttr_t; + +/// \details Semaphore ID identifies the semaphore. +typedef void* osSemaphoreId_t; + +/// Create and Initialize a Semaphore object. +/// \param[in] max_count maximum number of available tokens. +/// \param[in] initial_count initial number of available tokens. +/// \param[in] attr semaphore attributes; NULL: default values. +/// \return semaphore ID for reference by other functions or NULL in case of error. +osSemaphoreId_t + osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t* attr); + +/// Get name of a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return name as null-terminated string. +const char* osSemaphoreGetName(osSemaphoreId_t semaphore_id); + +/// Acquire a Semaphore token or timeout if no tokens are available. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout); + +/// Release a Semaphore token up to the initial maximum count. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id); + +/// Get current Semaphore token count. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return number of tokens available. +uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id); + +/// Delete a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id); + +#ifdef __cplusplus +} +#endif diff --git a/core/furi/stdglue.c b/core/furi/stdglue.c index 1eccafc9..8c1d0813 100644 --- a/core/furi/stdglue.c +++ b/core/furi/stdglue.c @@ -26,13 +26,13 @@ static ssize_t stdout_write(void* _cookie, const char* data, size_t size) { furi_assert(furi_stdglue); bool consumed = false; osKernelState_t state = osKernelGetState(); - osThreadId_t thread_id = osThreadGetId(); - if(state == osKernelRunning && thread_id && + FuriThreadId task_id = furi_thread_get_current_id(); + if(state == osKernelRunning && task_id && osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK) { // We are in the thread context // Handle thread callbacks FuriStdglueWriteCallback* callback_ptr = - FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)thread_id); + FuriStdglueCallbackDict_get(furi_stdglue->thread_outputs, (uint32_t)task_id); if(callback_ptr) { (*callback_ptr)(_cookie, data, size); consumed = true; @@ -76,14 +76,14 @@ void furi_stdglue_init() { bool furi_stdglue_set_thread_stdout_callback(FuriStdglueWriteCallback callback) { furi_assert(furi_stdglue); - osThreadId_t thread_id = osThreadGetId(); - if(thread_id) { + FuriThreadId task_id = furi_thread_get_current_id(); + if(task_id) { furi_check(osMutexAcquire(furi_stdglue->mutex, osWaitForever) == osOK); if(callback) { FuriStdglueCallbackDict_set_at( - furi_stdglue->thread_outputs, (uint32_t)thread_id, callback); + furi_stdglue->thread_outputs, (uint32_t)task_id, callback); } else { - FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)thread_id); + FuriStdglueCallbackDict_erase(furi_stdglue->thread_outputs, (uint32_t)task_id); } furi_check(osMutexRelease(furi_stdglue->mutex) == osOK); return true; diff --git a/core/furi/thread.c b/core/furi/thread.c index a2898c1a..692e5e05 100644 --- a/core/furi/thread.c +++ b/core/furi/thread.c @@ -2,7 +2,9 @@ #include "memmgr.h" #include "memmgr_heap.h" #include "check.h" +#include "common_defines.h" +#include #include struct FuriThread { @@ -15,14 +17,22 @@ struct FuriThread { FuriThreadStateCallback state_callback; void* state_context; - osThreadAttr_t attr; - volatile osThreadId_t id; + char* name; + configSTACK_DEPTH_TYPE stack_size; + FuriThreadPriority priority; + TaskHandle_t task_handle; bool heap_trace_enabled; size_t heap_size; }; -void furi_thread_set_state(FuriThread* thread, FuriThreadState state) { +/** Catch threads that are trying to exit wrong way */ +__attribute__((__noreturn__)) void furi_thread_catch() { + asm volatile("nop"); // extra magic + furi_crash("You are doing it wrong"); +} + +static void furi_thread_set_state(FuriThread* thread, FuriThreadState state) { furi_assert(thread); thread->state = state; if(thread->state_callback) { @@ -37,23 +47,24 @@ static void furi_thread_body(void* context) { furi_assert(thread->state == FuriThreadStateStarting); furi_thread_set_state(thread, FuriThreadStateRunning); - osThreadId_t thread_id = osThreadGetId(); + TaskHandle_t task_handle = xTaskGetCurrentTaskHandle(); if(thread->heap_trace_enabled == true) { - memmgr_heap_enable_thread_trace(thread_id); + memmgr_heap_enable_thread_trace((FuriThreadId)task_handle); } thread->ret = thread->callback(thread->context); if(thread->heap_trace_enabled == true) { osDelay(33); - thread->heap_size = memmgr_heap_get_thread_memory(thread_id); - memmgr_heap_disable_thread_trace(thread_id); + thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle); + memmgr_heap_disable_thread_trace((FuriThreadId)task_handle); } furi_assert(thread->state == FuriThreadStateRunning); furi_thread_set_state(thread, FuriThreadStateStopped); - osThreadExit(); + vTaskDelete(thread->task_handle); + furi_thread_catch(); } FuriThread* furi_thread_alloc() { @@ -66,21 +77,22 @@ void furi_thread_free(FuriThread* thread) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); - if(thread->attr.name) free((void*)thread->attr.name); + if(thread->name) free((void*)thread->name); free(thread); } void furi_thread_set_name(FuriThread* thread, const char* name) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); - if(thread->attr.name) free((void*)thread->attr.name); - thread->attr.name = strdup(name); + if(thread->name) free((void*)thread->name); + thread->name = strdup(name); } void furi_thread_set_stack_size(FuriThread* thread, size_t stack_size) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); - thread->attr.stack_size = stack_size; + furi_assert(stack_size % 4 == 0); + thread->stack_size = stack_size; } void furi_thread_set_callback(FuriThread* thread, FuriThreadCallback callback) { @@ -95,6 +107,13 @@ void furi_thread_set_context(FuriThread* thread, void* context) { thread->context = context; } +void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority) { + furi_assert(thread); + furi_assert(thread->state == FuriThreadStateStopped); + furi_assert(priority >= FuriThreadPriorityIdle && priority <= FuriThreadPriorityIsr); + thread->priority = priority; +} + void furi_thread_set_state_callback(FuriThread* thread, FuriThreadStateCallback callback) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); @@ -112,41 +131,39 @@ FuriThreadState furi_thread_get_state(FuriThread* thread) { return thread->state; } -bool furi_thread_start(FuriThread* thread) { +void furi_thread_start(FuriThread* thread) { furi_assert(thread); furi_assert(thread->callback); furi_assert(thread->state == FuriThreadStateStopped); - furi_assert(thread->attr.stack_size > 0); + furi_assert(thread->stack_size > 0 && thread->stack_size < 0xFFFF * 4); + furi_thread_set_state(thread, FuriThreadStateStarting); - thread->id = osThreadNew(furi_thread_body, thread, &thread->attr); - if(thread->id) { - return true; - } else { - furi_assert(thread->state == FuriThreadStateStarting); - furi_thread_set_state(thread, FuriThreadStateStopped); - return false; - } + + BaseType_t ret = xTaskCreate( + furi_thread_body, + thread->name, + thread->stack_size / 4, + thread, + thread->priority ? thread->priority : FuriThreadPriorityNormal, + &thread->task_handle); + + furi_check(ret == pdPASS); + furi_check(thread->task_handle); } -osStatus_t furi_thread_terminate(FuriThread* thread) { +bool furi_thread_join(FuriThread* thread) { furi_assert(thread); - osStatus_t ret = osThreadTerminate(thread->id); - if(ret == osOK) { - furi_thread_set_state(thread, FuriThreadStateStopped); - } - return ret; -} -osStatus_t furi_thread_join(FuriThread* thread) { - furi_assert(thread); while(thread->state != FuriThreadStateStopped) { osDelay(10); } + return osOK; } -osThreadId_t furi_thread_get_thread_id(FuriThread* thread) { - return thread->id; +FuriThreadId furi_thread_get_id(FuriThread* thread) { + furi_assert(thread); + return thread->task_handle; } void furi_thread_enable_heap_trace(FuriThread* thread) { @@ -174,3 +191,213 @@ int32_t furi_thread_get_return_code(FuriThread* thread) { furi_assert(thread->state == FuriThreadStateStopped); return thread->ret; } + +FuriThreadId furi_thread_get_current_id() { + return xTaskGetCurrentTaskHandle(); +} + +void furi_thread_yield() { + furi_assert(!FURI_IS_IRQ_MODE()); + taskYIELD(); +} + +/* Limits */ +#define MAX_BITS_TASK_NOTIFY 31U +#define MAX_BITS_EVENT_GROUPS 24U + +#define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY) - 1U)) +#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U)) + +uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + uint32_t rflags; + BaseType_t yield; + + if((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) { + rflags = (uint32_t)osErrorParameter; + } else { + rflags = (uint32_t)osError; + + if(FURI_IS_IRQ_MODE()) { + yield = pdFALSE; + + (void)xTaskNotifyFromISR(hTask, flags, eSetBits, &yield); + (void)xTaskNotifyAndQueryFromISR(hTask, 0, eNoAction, &rflags, NULL); + + portYIELD_FROM_ISR(yield); + } else { + (void)xTaskNotify(hTask, flags, eSetBits); + (void)xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags); + } + } + /* Return flags after setting */ + return (rflags); +} + +uint32_t furi_thread_flags_clear(uint32_t flags) { + TaskHandle_t hTask; + uint32_t rflags, cflags; + + if(FURI_IS_IRQ_MODE()) { + rflags = (uint32_t)osErrorISR; + } else if((flags & THREAD_FLAGS_INVALID_BITS) != 0U) { + rflags = (uint32_t)osErrorParameter; + } else { + hTask = xTaskGetCurrentTaskHandle(); + + if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &cflags) == pdPASS) { + rflags = cflags; + cflags &= ~flags; + + if(xTaskNotify(hTask, cflags, eSetValueWithOverwrite) != pdPASS) { + rflags = (uint32_t)osError; + } + } else { + rflags = (uint32_t)osError; + } + } + + /* Return flags before clearing */ + return (rflags); +} + +uint32_t furi_thread_flags_get(void) { + TaskHandle_t hTask; + uint32_t rflags; + + if(FURI_IS_IRQ_MODE()) { + rflags = (uint32_t)osErrorISR; + } else { + hTask = xTaskGetCurrentTaskHandle(); + + if(xTaskNotifyAndQuery(hTask, 0, eNoAction, &rflags) != pdPASS) { + rflags = (uint32_t)osError; + } + } + + return (rflags); +} + +uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout) { + uint32_t rflags, nval; + uint32_t clear; + TickType_t t0, td, tout; + BaseType_t rval; + + if(FURI_IS_IRQ_MODE()) { + rflags = (uint32_t)osErrorISR; + } else if((flags & THREAD_FLAGS_INVALID_BITS) != 0U) { + rflags = (uint32_t)osErrorParameter; + } else { + if((options & osFlagsNoClear) == osFlagsNoClear) { + clear = 0U; + } else { + clear = flags; + } + + rflags = 0U; + tout = timeout; + + t0 = xTaskGetTickCount(); + do { + rval = xTaskNotifyWait(0, clear, &nval, tout); + + if(rval == pdPASS) { + rflags &= flags; + rflags |= nval; + + if((options & osFlagsWaitAll) == osFlagsWaitAll) { + if((flags & rflags) == flags) { + break; + } else { + if(timeout == 0U) { + rflags = (uint32_t)osErrorResource; + break; + } + } + } else { + if((flags & rflags) != 0) { + break; + } else { + if(timeout == 0U) { + rflags = (uint32_t)osErrorResource; + break; + } + } + } + + /* Update timeout */ + td = xTaskGetTickCount() - t0; + + if(td > tout) { + tout = 0; + } else { + tout -= td; + } + } else { + if(timeout == 0) { + rflags = (uint32_t)osErrorResource; + } else { + rflags = (uint32_t)osErrorTimeout; + } + } + } while(rval != pdFAIL); + } + + /* Return flags before clearing */ + return (rflags); +} + +uint32_t furi_thread_enumerate(FuriThreadId* thread_array, uint32_t array_items) { + uint32_t i, count; + TaskStatus_t* task; + + if(FURI_IS_IRQ_MODE() || (thread_array == NULL) || (array_items == 0U)) { + count = 0U; + } else { + vTaskSuspendAll(); + + count = uxTaskGetNumberOfTasks(); + task = pvPortMalloc(count * sizeof(TaskStatus_t)); + + if(task != NULL) { + count = uxTaskGetSystemState(task, count, NULL); + + for(i = 0U; (i < count) && (i < array_items); i++) { + thread_array[i] = (FuriThreadId)task[i].xHandle; + } + count = i; + } + (void)xTaskResumeAll(); + + vPortFree(task); + } + + return (count); +} + +const char* furi_thread_get_name(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + const char* name; + + if(FURI_IS_IRQ_MODE() || (hTask == NULL)) { + name = NULL; + } else { + name = pcTaskGetName(hTask); + } + + return (name); +} + +uint32_t furi_thread_get_stack_space(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + uint32_t sz; + + if(FURI_IS_IRQ_MODE() || (hTask == NULL)) { + sz = 0U; + } else { + sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t)); + } + + return (sz); +} diff --git a/core/furi/thread.h b/core/furi/thread.h index 83e6bb93..11dd997c 100644 --- a/core/furi/thread.h +++ b/core/furi/thread.h @@ -5,9 +5,7 @@ #pragma once -#include -#include -#include +#include "base.h" #ifdef __cplusplus extern "C" { @@ -20,9 +18,24 @@ typedef enum { FuriThreadStateRunning, } FuriThreadState; +/** FuriThreadPriority */ +typedef enum { + FuriThreadPriorityNone = 0, /**< Uninitialized, choose system default */ + FuriThreadPriorityIdle = 1, /**< Idle priority */ + FuriThreadPriorityLowest = 14, /**< Lowest */ + FuriThreadPriorityLow = 15, /**< Low */ + FuriThreadPriorityNormal = 16, /**< Normal */ + FuriThreadPriorityHigh = 17, /**< High */ + FuriThreadPriorityHighest = 18, /**< Highest */ + FuriThreadPriorityIsr = 32, /**< Deffered Isr (highest possible) */ +} FuriThreadPriority; + /** FuriThread anonymous structure */ typedef struct FuriThread FuriThread; +/** FuriThreadId proxy type to OS low level functions */ +typedef void* FuriThreadId; + /** FuriThreadCallback Your callback to run in new thread * @warning never use osThreadExit in FuriThread */ @@ -74,6 +87,13 @@ void furi_thread_set_callback(FuriThread* thread, FuriThreadCallback callback); */ void furi_thread_set_context(FuriThread* thread, void* context); +/** Set FuriThread priority + * + * @param thread FuriThread instance + * @param priority FuriThreadPriority value + */ +void furi_thread_set_priority(FuriThread* thread, FuriThreadPriority priority); + /** Set FuriThread state change callback * * @param thread FuriThread instance @@ -99,36 +119,24 @@ FuriThreadState furi_thread_get_state(FuriThread* thread); /** Start FuriThread * * @param thread FuriThread instance - * - * @return true on success */ -bool furi_thread_start(FuriThread* thread); - -/** Treminate FuriThread - * - * @param thread FuriThread instance - * - * @return osStatus_t - * @warning terminating statefull thread is dangerous use only if you know - * what you doing - */ -osStatus_t furi_thread_terminate(FuriThread* thread); +void furi_thread_start(FuriThread* thread); /** Join FuriThread * * @param thread FuriThread instance * - * @return osStatus_t + * @return bool */ -osStatus_t furi_thread_join(FuriThread* thread); +bool furi_thread_join(FuriThread* thread); -/** Get CMSIS Thread ID +/** Get FreeRTOS FuriThreadId for FuriThread instance * * @param thread FuriThread instance * - * @return osThreadId_t or NULL + * @return FuriThreadId or NULL */ -osThreadId_t furi_thread_get_thread_id(FuriThread* thread); +FuriThreadId furi_thread_get_id(FuriThread* thread); /** Enable heap tracing * @@ -158,6 +166,33 @@ size_t furi_thread_get_heap_size(FuriThread* thread); */ int32_t furi_thread_get_return_code(FuriThread* thread); +/** Thread releated methods that doesn't involve FuriThread directly */ + +/** Get FreeRTOS FuriThreadId for current thread + * + * @param thread FuriThread instance + * + * @return FuriThreadId or NULL + */ +FuriThreadId furi_thread_get_current_id(); + +/** Return control to scheduler */ +void furi_thread_yield(); + +uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags); + +uint32_t furi_thread_flags_clear(uint32_t flags); + +uint32_t furi_thread_flags_get(void); + +uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout); + +uint32_t furi_thread_enumerate(FuriThreadId* thread_array, uint32_t array_items); + +const char* furi_thread_get_name(FuriThreadId thread_id); + +uint32_t furi_thread_get_stack_space(FuriThreadId thread_id); + #ifdef __cplusplus } #endif diff --git a/core/furi/valuemutex.h b/core/furi/valuemutex.h index 63dfac61..bd149316 100644 --- a/core/furi/valuemutex.h +++ b/core/furi/valuemutex.h @@ -2,6 +2,7 @@ #include #include +#include "mutex.h" #ifdef __cplusplus extern "C" { diff --git a/docker/Dockerfile b/docker/Dockerfile index 5aec3aae..64db408f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -16,9 +16,11 @@ RUN apt-get update \ libxslt1-dev \ zlib1g-dev \ wget \ - imagemagick \ python3-protobuf \ protobuf-compiler \ + python3-pip \ + libpython3-dev \ + ccache \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* @@ -30,8 +32,7 @@ RUN wget --progress=dot:giga "https://developer.arm.com/-/media/Files/downloads/ for file in * ; do ln -s "${PWD}/${file}" "/usr/bin/${file}" ; done && \ cd / && arm-none-eabi-gcc -v && arm-none-eabi-gdb -v -RUN git clone --depth 1 --branch v0.4.1 https://github.com/atomicobject/heatshrink.git && \ - cd heatshrink && make && mv ./heatshrink /usr/local/bin/heatshrink +RUN pip3 install heatshrink2==0.11.0 Pillow==9.1.1 RUN ln -s `which clang-format-12` /usr/local/bin/clang-format diff --git a/documentation/AppManifests.md b/documentation/AppManifests.md new file mode 100644 index 00000000..7b117789 --- /dev/null +++ b/documentation/AppManifests.md @@ -0,0 +1,3 @@ +# Flipper Application Manifests (.fam) + +TBD \ No newline at end of file diff --git a/documentation/OTA.md b/documentation/OTA.md index 3f4e400a..3e82336c 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -110,15 +110,15 @@ Even if something goes wrong, Updater gives you an option to retry failed operat ## Full package -To build a basic update package, run `make COMPACT=1 DEBUG=0 updater_package` +To build a basic update package, run `./fbt --with-updater COMPACT=1 DEBUG=0 updater_package` ## Customizing update bundles Default update packages are built with Bluetooth Light stack. -You can pick a different stack, if your firmware version supports it, and build a bundle with it passing stack type and binary name to `make`: +You can pick a different stack, if your firmware version supports it, and build a bundle with it passing stack type and binary name to `fbt`: -`make updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` +`./fbt --with-updater updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full` Note that `COPRO_OB_DATA` must point to a valid file in `scripts` folder containing reference Option Byte data matching to your radio stack type. diff --git a/documentation/fbt.md b/documentation/fbt.md new file mode 100644 index 00000000..061339da --- /dev/null +++ b/documentation/fbt.md @@ -0,0 +1,79 @@ +# Flipper Build Tool + +FBT is the entry point for most firmware-related commands and utilities. +It is invoked by `./fbt` in firmware project root directory. Internally, it is a wrapper around [scons](https://scons.org/) build system. + +## Requirements + +Please install Python packages required by assets build scripts: `pip3 install -r scripts/requirements.txt` + +## NB + +FBT constructs all referenced environments & their targets' dependency trees on startup. So, to keep startup time as low as possible, we're hiding construction of certain targets behind command-line options. + +## Invoking FBT + +To build with FBT, call it specifying configuration options & targets to build. For example, + +`./fbt --with-updater COMPACT=1 DEBUG=0 VERBOSE=1 updater_package copro_dist` + +To run cleanup (think of `make clean`) for specified targets, all `-c` option. + +## FBT targets + +FBT keeps track of internal dependencies, so you only need to build the highest-level target you need, and FBT will make sure everything it needs is up-to-date. + +### High-level (what you most likely need) + +- `fw_dist` - build & publish firmware to `dist` folder +- `updater_package` - build self-update package. _Requires `--with-updater` option_ +- `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper +- `flash` - flash attached device with OpenOCD over ST-Link +- `flash_usb` - build, upload and install update package to device over USB. _Requires `--with-updater` option_ +- `debug` - build and flash firmware, then attach with gdb with firmware's .elf loaded +- `debug_updater` - attach gdb with updater's .elf loaded. _Requires `--with-updater` option_ +- `debug_other` - attach gdb without loading built elf. Allows to manually add external elf files with `add-symbol-file` in gdb. +- `openocd` - just start OpenOCD + +### Firmware targets + +- `firmware_extapps` - build all plug-ins as separate .elf files + - `firmware_snake_game`, etc - build single plug-in as .elf by its name + - Check out `--extra-ext-apps` for force adding extra apps to external build + - `firmware_snake_game_list`, etc - generate source + assembler listing for app's .elf +- `flash`, `firmware_flash` - flash current version to attached device with OpenOCD over ST-Link +- `firmware_cdb` - generate compilation database +- `firmware_all`, `updater_all` - build basic set of binaries +- `firmware_list`, `updater_list` - generate source + assembler listing + +### Assets + +- `resources` - build resources and their Manifest + - `dolphin_ext` - process dolphin animations for SD card +- `icons` - generate .c+.h for icons from png assets +- `proto` - generate .pb.c+.pb.h for .proto sources +- `proto_ver` - generate .h with protobuf version +- `dolphin_internal`, `dolphin_blocking` - generate .c+.h for corresponding dolphin assets + + +## Command-line parameters + +- `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values +- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this options introduces extra startup time costs, so use it when bundling update packages. Or if you have a fast computer and don't care about a few extra seconds of startup time +- `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target +- `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target + + +## Configuration + +Default configuration variables are set in configuration file `fbt_options.py`. +Values set on command-line have higher precedence over configuration file. + +You can find out available options with `./fbt -h`. + +### Firmware application set + +You can create customized firmware builds by modifying application list to be included in the build. Application presets are configured with `FIRMWARE_APPS` option, which is a map(configuration_name:str -> application_list:tuple(str)). To specify application set to use in a build, set `FIRMWARE_APP_SET` to its name. +For example, to build firmware image with unit tests, run `./fbt FIRMWARE_APP_SET=unit_tests`. + +Check out `fbt_options.py` for details. diff --git a/fbt b/fbt new file mode 100755 index 00000000..81193a46 --- /dev/null +++ b/fbt @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +if [[ -d .git ]]; then + echo "Updating git submodules" + git submodule update --init +fi + +SCRIPTDIR="$( dirname -- "$0"; )"; +SCONS_DEFAULT_FLAGS="-Q --warn=target-not-built" +python3 ${SCRIPTDIR}/lib/scons/scripts/scons.py ${SCONS_DEFAULT_FLAGS} "$@" diff --git a/fbt.cmd b/fbt.cmd new file mode 100644 index 00000000..7711e44b --- /dev/null +++ b/fbt.cmd @@ -0,0 +1,8 @@ +@echo off +if exist ".git" ( + echo Prepairing git submodules + git submodule update --init +) + +set "SCONS_DEFAULT_FLAGS=-Q --warn=target-not-built" +python lib/scons/scripts/scons.py %SCONS_DEFAULT_FLAGS% %* diff --git a/fbt_options.py b/fbt_options.py new file mode 100644 index 00000000..ddeff048 --- /dev/null +++ b/fbt_options.py @@ -0,0 +1,72 @@ +import posixpath + + +# Default hardware target +TARGET_HW = 7 + +# Optimization flags +## Optimize for size +COMPACT = 0 +## Optimize for debugging experience +DEBUG = 1 + +# Suffix to add to files when building distribution. +# If OS environment has DIST_SUFFIX set, it will be used instead.. +DIST_SUFFIX = "local" + +# Coprocessor firmware +COPRO_OB_DATA = "scripts/ob.data" + +# Must match lib/STM32CubeWB version +COPRO_CUBE_VERSION = "1.13.3" + +COPRO_CUBE_DIR = "lib/STM32CubeWB" + +# Default radio stack +COPRO_STACK_BIN = "stm32wb5x_BLE_Stack_light_fw.bin" +# Firmware also supports "ble_full", but it might not fit into debug builds +COPRO_STACK_TYPE = "ble_light" + +# Leave 0 to lets scripts automatically calculate it +COPRO_STACK_ADDR = "0x0" + +# If you override COPRO_CUBE_DIR on commandline, override this aswell +COPRO_STACK_BIN_DIR = posixpath.join( + COPRO_CUBE_DIR, + "Projects", + "STM32WB_Copro_Wireless_Binaries", + "STM32WB5x", +) + +# Supported toolchain versions +FBT_TOOLCHAIN_VERSIONS = (" 10.3.",) + +OPENOCD_OPTS = '-f interface/stlink.cfg -c "transport select hla_swd" -f debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init"' + +SVD_FILE = "debug/STM32WB55_CM4.svd" + +FIRMWARE_APPS = { + "default": ( + "crypto_start", + # Svc + "basic_services", + # Apps + "basic_apps", + "updater_app", + "archive", + # Settings + "passport", + "system_settings", + "about", + # Plugins + "basic_plugins", + # Debug + "debug_apps", + ), + "unit_tests": ( + "basic_services", + "unit_tests", + ), +} + +FIRMWARE_APP_SET = "default" diff --git a/firmware.scons b/firmware.scons new file mode 100644 index 00000000..890be5f8 --- /dev/null +++ b/firmware.scons @@ -0,0 +1,238 @@ +Import("ENV", "fw_build_meta") + +import os + + +# Building initial C environment for libs +env = ENV.Clone( + tools=["compilation_db", "fwbin", "openocd", "fbt_apps"], + COMPILATIONDB_USE_ABSPATH=True, + BUILD_DIR=fw_build_meta["build_dir"], + IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", + FW_FLAVOR=fw_build_meta["flavor"], + PLUGIN_ELF_DIR="${BUILD_DIR}", + LIB_DIST_DIR="${BUILD_DIR}/lib", + LINT_SOURCES=[ + "applications", + ], + LIBPATH=[ + "${LIB_DIST_DIR}", + ], + CPPPATH=[ + "#/core", + "#/applications", + "#/firmware/targets/f${TARGET_HW}/ble_glue", + "#/firmware/targets/f${TARGET_HW}/fatfs", + "#/firmware/targets/f${TARGET_HW}/furi_hal", + "#/firmware/targets/f${TARGET_HW}/Inc", + "#/firmware/targets/furi_hal_include", + ], + # Specific flags for building libraries - always do optimized builds + FW_LIB_OPTS={ + "Default": { + "CCFLAGS": [ + "-Os", + ], + "CPPDEFINES": [ + "NDEBUG", + "FURI_NDEBUG", + ], + # You can add other entries named after libraries + # If they are present, they have precedence over Default + }, + # for furi_check to respect build type + "core": { + "CCFLAGS": [ + "-Os", + ], + "CPPDEFINES": [ + "NDEBUG", + "FURI_DEBUG" if ENV["DEBUG"] else "FURI_NDEBUG", + ], + }, + }, +) + + +def ApplyLibFlags(env): + flags_to_apply = env["FW_LIB_OPTS"].get( + env.get("FW_LIB_NAME"), + env["FW_LIB_OPTS"]["Default"], + ) + # print("Flags for ", env.get("FW_LIB_NAME", "Default"), flags_to_apply) + env.MergeFlags(flags_to_apply) + + +env.AddMethod(ApplyLibFlags) + +Export("env") + +if not env["VERBOSE"]: + env.SetDefault( + HEXCOMSTR="\tHEX\t${TARGET}", + BINCOMSTR="\tBIN\t${TARGET}", + DFUCOMSTR="\tDFU\t${TARGET}", + OOCDCOMSTR="\tFLASH\t${SOURCE}", + ) + + +if fw_build_meta["type"] == "updater": + env.Append( + FIRMWARE_BUILD_CFG="updater", + RAM_EXEC=True, + CPPDEFINES=[ + "FURI_RAM_EXEC", + ], + ) +else: + env.Append( + FIRMWARE_BUILD_CFG="firmware", + RAM_EXEC=False, + ) +# print(env.Dump()) + + +# Invoke child SCopscripts to populate global `env` + build their own part of the code +lib_targets = env.BuildModules( + [ + "lib", + "assets", + "firmware", + "core", + ], +) + + +# Now, env is fully set up with everything to build apps +fwenv = env.Clone() + +# Set up additional app-specific build flags +SConscript("site_scons/firmwareopts.scons", exports={"ENV": fwenv}) + +# Set up app configuration +if env["IS_BASE_FIRMWARE"]: + fwenv.Append(APPS=fwenv["FIRMWARE_APPS"].get(fwenv.subst("$FIRMWARE_APP_SET"))) +else: + fwenv.Append(APPS=["updater"]) + +if extra_int_apps := GetOption("extra_int_apps"): + for extra_int_app in extra_int_apps.split(","): + fwenv.Append(APPS=[extra_int_app]) + +fwenv.LoadApplicationManifests() +fwenv.PrepareApplicationsBuild() + +# Build external apps +extapps = SConscript("applications/extapps.scons", exports={"ENV": fwenv}) + + +# Add preprocessor definitions for current set of apps +fwenv.AppendUnique( + CPPDEFINES=fwenv["APPBUILD"].get_apps_cdefs(), +) + + +# Build applications.c for selected services & apps + +# Depends on virtual value-only node, so it only gets rebuilt when set of apps changes +apps_c = fwenv.ApplicationsC( + "applications/applications.c", + Value(fwenv["APPS"]), +) + +sources = [apps_c] +# Gather sources only from app folders from current configuration +for app_folder in fwenv["APPBUILD"].get_builtin_app_folders(): + sources += fwenv.GlobRecursive("*.c*", os.path.join("applications", app_folder)) + + +fwenv.AppendUnique( + LINKFLAGS=[ + "-specs=nano.specs", + "-specs=nosys.specs", + "-Wl,--start-group", + "-lstdc++", + "-lsupc++", + "-Wl,--end-group", + "-Wl,--gc-sections", + "-Wl,--undefined=uxTopUsedPriority", + "-Wl,--wrap,_malloc_r", + "-Wl,--wrap,_free_r", + "-Wl,--wrap,_calloc_r", + "-Wl,--wrap,_realloc_r", + "-u", + "_printf_float", + "-n", + ], +) + +# Debug +# print(fwenv.Dump()) + +# Full firmware definition + +fwelf = fwenv["FW_ELF"] = fwenv.Program( + "${FIRMWARE_BUILD_CFG}", + sources, + LIBS=[ + "flipper${TARGET_HW}", + "core", + "freertos", + "stm32cubewb", + "hwdrivers", + "fatfs", + "littlefs", + "subghz", + "flipperformat", + "toolbox", + "microtar", + "usb_stm32", + "st25rfal002", + "infrared", + "appframe", + "assets", + "misc", + # 2nd round + "flipperformat", + "toolbox", + ], +) + +# Make it depend on everything child builders returned +Depends(fwelf, lib_targets) +AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) +AddPostAction(fwelf, Action("@$SIZECOM")) + + +fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") +fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") +fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") +# Default(dfu) +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu) + +fwdump = fwenv.ObjDump("${FIRMWARE_BUILD_CFG}") +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_list", fwdump) + +# Additional FW-related pseudotargets +flash = fwenv["FW_FLASH"] = fwenv.OOCDFlashCommand( + "${FIRMWARE_BUILD_CFG}", + OPENOCD_COMMAND='-c "program ${SOURCE.posix} reset exit ${IMAGE_BASE_ADDRESS}"', +) +if fwenv["FORCE"]: + AlwaysBuild(flash) +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_flash", flash) +if fwenv["IS_BASE_FIRMWARE"]: + Alias("flash", flash) + + +# Compile DB generation +fwcdb = fwenv["FW_CDB"] = fwenv.CompilationDatabase("compile_commands.json") +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb) + + +artifacts = [fwhex, fwbin, fwdfu, env["FW_VERSION_JSON"]] +fwenv["FW_ARTIFACTS"] = artifacts + +Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", artifacts) + +Return("fwenv") diff --git a/firmware/Makefile b/firmware/Makefile deleted file mode 100644 index efa185ca..00000000 --- a/firmware/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -MAKEFILE_DIR := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) -PROJECT_ROOT := $(abspath $(MAKEFILE_DIR)/..) - -include $(PROJECT_ROOT)/make/base.mk -include $(PROJECT_ROOT)/make/freertos-heap.mk -include $(PROJECT_ROOT)/assets/assets.mk -include $(PROJECT_ROOT)/core/core.mk -include $(PROJECT_ROOT)/applications/applications.mk -include $(PROJECT_ROOT)/lib/lib.mk - -CFLAGS += -I$(PROJECT_ROOT) -Itargets/furi_hal_include -CFLAGS += -Werror -Wno-address-of-packed-member -CPPFLAGS += -Werror - -include $(PROJECT_ROOT)/make/defaults.mk -TARGET_DIR = targets/$(TARGET) -include $(TARGET_DIR)/target.mk - -ifeq ($(RAM_EXEC), 0) -PROJECT := firmware -else -PROJECT := updater -endif - -include $(PROJECT_ROOT)/make/git.mk -include $(PROJECT_ROOT)/make/toolchain.mk -include $(PROJECT_ROOT)/make/rules.mk diff --git a/firmware/ReadMe.md b/firmware/ReadMe.md index 38271fd2..d2baedfd 100644 --- a/firmware/ReadMe.md +++ b/firmware/ReadMe.md @@ -19,37 +19,4 @@ Target independent code and headers in `target/include` folders. More details in # Building -## With dev docker image: - -`docker-compose exec dev make -C firmware` - -## With toolchain installed in path: - -`make -C firmware` - -## Build Options - -- `DEBUG` - 0/1 - enable or disable debug build. Default is 1. -- `COMPACT` - 0/1 - enable or disable compiler optimizations. Significantly reduces binary size. Default is 0. -- `TARGET` - string - target to build. Default is `f7`. -- `RAM_EXEC` - 0/1 - whether to build full firmware or RAM-based stage for firmware update. 0 is default, builds firmware. - -# Building self-update package - -`make DEBUG=0 COMPACT=1 updater_package` - -# Flashing - -Using SWD (STLink): - -`make -C firmware flash` - -Or use DFU (USB): - -`make -C firmware upload` - -# Debug - -Using SWD (STLink): - -`make -C firmware debug` +Check out `documentation/fbt.md` on how to build and flash firmware. \ No newline at end of file diff --git a/firmware/SConscript b/firmware/SConscript new file mode 100644 index 00000000..8dade34e --- /dev/null +++ b/firmware/SConscript @@ -0,0 +1,14 @@ +Import("env") + +env.Append(LINT_SOURCES=["firmware"]) + +libenv = env.Clone(FW_LIB_NAME="flipper${TARGET_HW}") +libenv.ApplyLibFlags() + + +sources = ["targets/f${TARGET_HW}/startup_stm32wb55xx_cm4.s"] +sources += libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index 0204826a..9f1b83c0 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -20,7 +20,7 @@ extern uint32_t SystemCoreClock; #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ (SystemCoreClock) #define configTICK_RATE_HZ ((TickType_t)1000) -#define configMAX_PRIORITIES (56) +#define configMAX_PRIORITIES (32) #define configMINIMAL_STACK_SIZE ((uint16_t)128) /* Heap size determined automatically by linker */ @@ -35,7 +35,7 @@ extern uint32_t SystemCoreClock; #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_COUNTING_SEMAPHORES 1 #define configENABLE_BACKWARD_COMPATIBILITY 0 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_TICKLESS_IDLE 2 #define configRECORD_STACK_HIGH_ADDRESS 1 #define configUSE_NEWLIB_REENTRANT 0 @@ -89,6 +89,9 @@ to exclude the API function. */ #define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 #define CMSIS_TASK_NOTIFY_INDEX 1 +extern __attribute__((__noreturn__)) void furi_thread_catch(); +#define configTASK_RETURN_ADDRESS (furi_thread_catch + 2) + /* * The CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation used * by the application thus the correct define need to be enabled below diff --git a/firmware/targets/f7/Src/main.c b/firmware/targets/f7/Src/main.c index 3de1c6ca..82a2819b 100644 --- a/firmware/targets/f7/Src/main.c +++ b/firmware/targets/f7/Src/main.c @@ -7,19 +7,16 @@ #define TAG "Main" -static const osThreadAttr_t init_thread_attr = { - .name = "Init", - .stack_size = 4096, -}; +int32_t init_task(void* context) { + UNUSED(context); -void init_task() { // Flipper FURI HAL furi_hal_init(); // Init flipper flipper_init(); - osThreadExit(); + return 0; } int main() { @@ -29,8 +26,13 @@ int main() { // Flipper critical FURI HAL furi_hal_init_early(); + FuriThread* main_thread = furi_thread_alloc(); + furi_thread_set_name(main_thread, "Init"); + furi_thread_set_stack_size(main_thread, 4096); + furi_thread_set_callback(main_thread, init_task); + #ifdef FURI_RAM_EXEC - osThreadNew(init_task, NULL, &init_thread_attr); + furi_thread_start(main_thread); #else furi_hal_light_sequence("RGB"); @@ -52,7 +54,7 @@ int main() { furi_hal_power_reset(); } else { furi_hal_light_sequence("rgb G"); - osThreadNew(init_task, NULL, &init_thread_attr); + furi_thread_start(main_thread); } #endif diff --git a/firmware/targets/f7/application-ext.ld b/firmware/targets/f7/application-ext.ld new file mode 100644 index 00000000..45fe431c --- /dev/null +++ b/firmware/targets/f7/application-ext.ld @@ -0,0 +1,37 @@ +SECTIONS +{ + .text 0x00000000 : + { + *(.text) + *(.text.*) + } + + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.*) + } + + .data : + { + *(.data) + *(.data1) + *(.data.*) + } + + .bss : + { + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(COMMON) + } + + /DISCARD/ : + { + *(.comment) + *(.comment.*) + } +} diff --git a/firmware/targets/f7/ble_glue/ble_app.c b/firmware/targets/f7/ble_glue/ble_app.c index 618e2b94..f0406a88 100644 --- a/firmware/targets/f7/ble_glue/ble_app.c +++ b/firmware/targets/f7/ble_glue/ble_app.c @@ -6,6 +6,7 @@ #include "gap.h" #include +#include #define TAG "Bt" @@ -106,9 +107,9 @@ void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) { void ble_app_thread_stop() { if(ble_app) { - osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread); + FuriThreadId thread_id = furi_thread_get_id(ble_app->thread); furi_assert(thread_id); - osThreadFlagsSet(thread_id, BLE_APP_FLAG_KILL_THREAD); + furi_thread_flags_set(thread_id, BLE_APP_FLAG_KILL_THREAD); furi_thread_join(ble_app->thread); furi_thread_free(ble_app->thread); // Free resources @@ -125,7 +126,7 @@ static int32_t ble_app_hci_thread(void* arg) { uint32_t flags = 0; while(1) { - flags = osThreadFlagsWait(BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever); + flags = furi_thread_flags_wait(BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever); if(flags & BLE_APP_FLAG_KILL_THREAD) { break; } @@ -141,9 +142,9 @@ static int32_t ble_app_hci_thread(void* arg) { void hci_notify_asynch_evt(void* pdata) { UNUSED(pdata); if(ble_app) { - osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread); + FuriThreadId thread_id = furi_thread_get_id(ble_app->thread); furi_assert(thread_id); - osThreadFlagsSet(thread_id, BLE_APP_FLAG_HCI_EVENT); + furi_thread_flags_set(thread_id, BLE_APP_FLAG_HCI_EVENT); } } diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 6a100bea..6fa3dbd0 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -113,13 +113,34 @@ BleGlueStatus ble_glue_get_c2_status() { return ble_glue->status; } +static const char* ble_glue_get_reltype_str(const uint8_t reltype) { + static char relcode[3] = {0}; + switch(reltype) { + case INFO_STACK_TYPE_BLE_FULL: + return "F"; + case INFO_STACK_TYPE_BLE_HCI: + return "H"; + case INFO_STACK_TYPE_BLE_LIGHT: + return "L"; + case INFO_STACK_TYPE_BLE_BEACON: + return "Be"; + case INFO_STACK_TYPE_BLE_BASIC: + return "Ba"; + case INFO_STACK_TYPE_BLE_FULL_EXT_ADV: + return "F+"; + case INFO_STACK_TYPE_BLE_HCI_EXT_ADV: + return "H+"; + default: + snprintf(relcode, sizeof(relcode), "%X", reltype); + return relcode; + } +} + static void ble_glue_update_c2_fw_info() { WirelessFwInfo_t wireless_info; SHCI_GetWirelessFwInfo(&wireless_info); BleGlueC2Info* local_info = &ble_glue->c2_info; - local_info->VersionMajor = wireless_info.VersionMajor; - local_info->VersionMinor = wireless_info.VersionMinor; local_info->VersionMajor = wireless_info.VersionMajor; local_info->VersionMinor = wireless_info.VersionMinor; local_info->VersionSub = wireless_info.VersionSub; @@ -132,6 +153,14 @@ static void ble_glue_update_c2_fw_info() { local_info->MemorySizeFlash = wireless_info.MemorySizeFlash; local_info->StackType = wireless_info.StackType; + snprintf( + local_info->StackTypeString, + BLE_GLUE_MAX_VERSION_STRING_LEN, + "%d.%d.%d.%s", + local_info->VersionMajor, + local_info->VersionMinor, + local_info->VersionSub, + ble_glue_get_reltype_str(local_info->StackType)); local_info->FusVersionMajor = wireless_info.FusVersionMajor; local_info->FusVersionMinor = wireless_info.FusVersionMinor; @@ -333,9 +362,9 @@ static void ble_glue_clear_shared_memory() { void ble_glue_thread_stop() { if(ble_glue) { - osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread); + FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread); furi_assert(thread_id); - osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_KILL_THREAD); + furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_KILL_THREAD); furi_thread_join(ble_glue->thread); furi_thread_free(ble_glue->thread); // Free resources @@ -353,7 +382,7 @@ static int32_t ble_glue_shci_thread(void* context) { uint32_t flags = 0; while(true) { - flags = osThreadFlagsWait(BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever); + flags = furi_thread_flags_wait(BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever); if(flags & BLE_GLUE_FLAG_SHCI_EVENT) { shci_user_evt_proc(); } @@ -368,9 +397,9 @@ static int32_t ble_glue_shci_thread(void* context) { void shci_notify_asynch_evt(void* pdata) { UNUSED(pdata); if(ble_glue) { - osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread); + FuriThreadId thread_id = furi_thread_get_id(ble_glue->thread); furi_assert(thread_id); - osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_SHCI_EVENT); + furi_thread_flags_set(thread_id, BLE_GLUE_FLAG_SHCI_EVENT); } } diff --git a/firmware/targets/f7/ble_glue/ble_glue.h b/firmware/targets/f7/ble_glue/ble_glue.h index fe43ae09..bd2588a0 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.h +++ b/firmware/targets/f7/ble_glue/ble_glue.h @@ -13,6 +13,7 @@ typedef enum { BleGlueC2ModeStack, } BleGlueC2Mode; +#define BLE_GLUE_MAX_VERSION_STRING_LEN 20 typedef struct { BleGlueC2Mode mode; /** @@ -28,6 +29,7 @@ typedef struct { uint8_t MemorySizeSram1; /*< Multiple of 1K */ uint8_t MemorySizeFlash; /*< Multiple of 4K */ uint8_t StackType; + char StackTypeString[BLE_GLUE_MAX_VERSION_STRING_LEN]; /** * Fus Info */ diff --git a/firmware/targets/f7/ble_glue/dev_info_service.c b/firmware/targets/f7/ble_glue/dev_info_service.c index 4adfce59..d6d1e479 100755 --- a/firmware/targets/f7/ble_glue/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/dev_info_service.c @@ -5,6 +5,7 @@ #include #include #include +#include #define TAG "BtDevInfoSvc" @@ -15,15 +16,14 @@ typedef struct { uint16_t firmware_rev_char_handle; uint16_t software_rev_char_handle; uint16_t rpc_version_char_handle; + string_t version_string; + char hardware_revision[4]; } DevInfoSvc; static DevInfoSvc* dev_info_svc = NULL; static const char dev_info_man_name[] = "Flipper Devices Inc."; static const char dev_info_serial_num[] = "1.0"; -static const char dev_info_firmware_rev_num[] = TOSTRING(TARGET); -static const char dev_info_software_rev_num[] = GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM - " " BUILD_DATE; static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); static const uint8_t dev_info_rpc_version_uuid[] = @@ -31,6 +31,18 @@ static const uint8_t dev_info_rpc_version_uuid[] = void dev_info_svc_start() { dev_info_svc = malloc(sizeof(DevInfoSvc)); + string_init_printf( + dev_info_svc->version_string, + "%s %s %s %s", + version_get_githash(NULL), + version_get_gitbranch(NULL), + version_get_gitbranchnum(NULL), + version_get_builddate(NULL)); + snprintf( + dev_info_svc->hardware_revision, + sizeof(dev_info_svc->hardware_revision), + "%d", + version_get_target(NULL)); tBleStatus status; // Add Device Information Service @@ -77,7 +89,7 @@ void dev_info_svc_start() { dev_info_svc->service_handle, UUID_TYPE_16, (Char_UUID_t*)&uuid, - strlen(dev_info_firmware_rev_num), + strlen(dev_info_svc->hardware_revision), CHAR_PROP_READ, ATTR_PERMISSION_AUTHEN_READ, GATT_DONT_NOTIFY_EVENTS, @@ -92,7 +104,7 @@ void dev_info_svc_start() { dev_info_svc->service_handle, UUID_TYPE_16, (Char_UUID_t*)&uuid, - strlen(dev_info_software_rev_num), + string_size(dev_info_svc->version_string), CHAR_PROP_READ, ATTR_PERMISSION_AUTHEN_READ, GATT_DONT_NOTIFY_EVENTS, @@ -140,8 +152,8 @@ void dev_info_svc_start() { dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle, 0, - strlen(dev_info_firmware_rev_num), - (uint8_t*)dev_info_firmware_rev_num); + strlen(dev_info_svc->hardware_revision), + (uint8_t*)dev_info_svc->hardware_revision); if(status) { FURI_LOG_E(TAG, "Failed to update firmware revision char: %d", status); } @@ -149,8 +161,8 @@ void dev_info_svc_start() { dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle, 0, - strlen(dev_info_software_rev_num), - (uint8_t*)dev_info_software_rev_num); + string_size(dev_info_svc->version_string), + (uint8_t*)string_get_cstr(dev_info_svc->version_string)); if(status) { FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); } @@ -168,6 +180,7 @@ void dev_info_svc_start() { void dev_info_svc_stop() { tBleStatus status; if(dev_info_svc) { + string_clear(dev_info_svc->version_string); // Delete service characteristics status = aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); diff --git a/firmware/targets/f7/ble_glue/dev_info_service.h b/firmware/targets/f7/ble_glue/dev_info_service.h index 2faac8a6..8cce20a6 100644 --- a/firmware/targets/f7/ble_glue/dev_info_service.h +++ b/firmware/targets/f7/ble_glue/dev_info_service.h @@ -7,12 +7,6 @@ extern "C" { #endif -#define DEV_INFO_MANUFACTURER_NAME "Flipper Devices Inc." -#define DEV_INFO_SERIAL_NUMBER "1.0" -#define DEV_INFO_FIRMWARE_REVISION_NUMBER TARGET -#define DEV_INFO_SOFTWARE_REVISION_NUMBER \ - GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM " " BUILD_DATE - void dev_info_svc_start(); void dev_info_svc_stop(); diff --git a/firmware/targets/f7/ble_glue/tl_dbg_conf.h b/firmware/targets/f7/ble_glue/tl_dbg_conf.h index 1f09b7e4..ce58af32 100644 --- a/firmware/targets/f7/ble_glue/tl_dbg_conf.h +++ b/firmware/targets/f7/ble_glue/tl_dbg_conf.h @@ -33,7 +33,6 @@ extern "C" { #include "app_conf.h" /* required as some configuration used in dbg_trace.h are set there */ #include "dbg_trace.h" #include "hw_if.h" -#include /** * Enable or Disable traces diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index c7ee7dc2..ad12d773 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -322,7 +322,7 @@ void furi_hal_bt_set_key_storage_change_callback( void furi_hal_bt_nvm_sram_sem_acquire() { while(LL_HSEM_1StepLock(HSEM, CFG_HW_BLE_NVM_SRAM_SEMID)) { - osThreadYield(); + furi_thread_yield(); } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_crc.c b/firmware/targets/f7/furi_hal/furi_hal_crc.c index 322a83bb..9ac13e97 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_crc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_crc.c @@ -34,7 +34,7 @@ void furi_hal_crc_init(bool synchronize) { void furi_hal_crc_reset() { furi_check(hal_crc_control.state == CRC_State_Ready); if(hal_crc_control.mtx) { - furi_check(osMutexGetOwner(hal_crc_control.mtx) == osThreadGetId()); + furi_check(osMutexGetOwner(hal_crc_control.mtx) == furi_thread_get_current_id()); osMutexRelease(hal_crc_control.mtx); } LL_CRC_ResetCRCCalculationUnit(CRC); diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index 1d9c3fd9..ac141db0 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -112,7 +112,7 @@ static void furi_hal_flash_lock(void) { static void furi_hal_flash_begin_with_core2(bool erase_flag) { // Take flash controller ownership while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) { - osThreadYield(); + furi_thread_yield(); } // Unlock flash operation @@ -128,7 +128,7 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) { while(true) { // Wait till flash controller become usable while(LL_FLASH_IsActiveFlag_OperationSuspended()) { - osThreadYield(); + furi_thread_yield(); }; // Just a little more love @@ -137,14 +137,14 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) { // Actually we already have mutex for it, but specification is specification if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { taskEXIT_CRITICAL(); - osThreadYield(); + furi_thread_yield(); continue; } // Take sempahopre and prevent core2 from anything funky if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) { taskEXIT_CRITICAL(); - osThreadYield(); + furi_thread_yield(); continue; } @@ -173,7 +173,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) { // Doesn't make much sense, does it? while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) { - osThreadYield(); + furi_thread_yield(); } // Erase activity over, core2 can continue @@ -498,7 +498,7 @@ bool furi_hal_flash_ob_set_word(size_t word_idx, const uint32_t value) { /* 3. Check that no Flash memory operation is on going by checking the BSY && PESD */ furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT)); while(LL_FLASH_IsActiveFlag_OperationSuspended()) { - osThreadYield(); + furi_thread_yield(); }; /* 4. Set the Options start bit OPTSTRT */ diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 6ffb6e3a..cba2a703 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -179,7 +179,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { FURI_LOG_T(TAG, "Timeout"); return false; } - osThreadYield(); + furi_thread_yield(); } rfalNfcGetDevicesFound(&dev_list, &dev_cnt); // Take first device and set cuid @@ -277,7 +277,7 @@ bool furi_hal_nfc_emulate_nfca( uint8_t buff_rx[256]; uint16_t buff_rx_size = 256; uint16_t buff_rx_len = 0; - uint8_t buff_tx[256]; + uint8_t buff_tx[1040]; uint16_t buff_tx_len = 0; uint32_t data_type = FURI_HAL_NFC_TXRX_DEFAULT; @@ -397,14 +397,14 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ } // Manually wait for interrupt - furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE); uint32_t irq = 0; uint8_t rxe = 0; uint32_t start = DWT->CYCCNT; while(true) { - if(furi_hal_gpio_read(&gpio_rfid_pull) == true) { + if(furi_hal_gpio_read(&gpio_nfc_irq_rfid_pull) == true) { st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe); if(rxe & (1 << 4)) { irq = 1; diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 0af33cac..21fac834 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -42,7 +42,7 @@ const GpioPin gpio_ext_pa4 = {.port = GPIOA, .pin = LL_GPIO_PIN_4}; const GpioPin gpio_ext_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6}; const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7}; -const GpioPin gpio_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin}; +const GpioPin gpio_nfc_irq_rfid_pull = {.port = RFID_PULL_GPIO_Port, .pin = RFID_PULL_Pin}; const GpioPin gpio_rfid_carrier_out = {.port = RFID_OUT_GPIO_Port, .pin = RFID_OUT_Pin}; const GpioPin gpio_rfid_data_in = {.port = RFID_RF_IN_GPIO_Port, .pin = RFID_RF_IN_Pin}; const GpioPin gpio_rfid_carrier = {.port = RFID_CARRIER_GPIO_Port, .pin = RFID_CARRIER_Pin}; @@ -138,7 +138,7 @@ void furi_hal_resources_init() { furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInterruptRise, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullNo, GpioSpeedLow); furi_hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index e9d19827..820760a1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -77,7 +77,7 @@ extern const GpioPin gpio_ext_pa4; extern const GpioPin gpio_ext_pa6; extern const GpioPin gpio_ext_pa7; -extern const GpioPin gpio_rfid_pull; +extern const GpioPin gpio_nfc_irq_rfid_pull; extern const GpioPin gpio_rfid_carrier_out; extern const GpioPin gpio_rfid_data_in; extern const GpioPin gpio_rfid_carrier; diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/firmware/targets/f7/furi_hal/furi_hal_rfid.c index 86fecc99..507c53bf 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.c @@ -69,8 +69,8 @@ void furi_hal_rfid_pins_reset() { furi_hal_gpio_write(&gpio_rfid_carrier_out, false); // from both sides - furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_rfid_pull, true); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true); furi_hal_gpio_init_simple(&gpio_rfid_carrier, GpioModeAnalog); @@ -84,7 +84,11 @@ void furi_hal_rfid_pins_emulate() { // pull pin to timer out furi_hal_gpio_init_ex( - &gpio_rfid_pull, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); + &gpio_nfc_irq_rfid_pull, + GpioModeAltFunctionPushPull, + GpioPullNo, + GpioSpeedLow, + GpioAltFn1TIM2); // pull rfid antenna from carrier side furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -100,8 +104,8 @@ void furi_hal_rfid_pins_read() { furi_hal_ibutton_pin_low(); // dont pull rfid antenna - furi_hal_gpio_init(&gpio_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_rfid_pull, false); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false); // carrier pin to timer out furi_hal_gpio_init_ex( @@ -116,11 +120,11 @@ void furi_hal_rfid_pins_read() { } void furi_hal_rfid_pin_pull_release() { - furi_hal_gpio_write(&gpio_rfid_pull, true); + furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true); } void furi_hal_rfid_pin_pull_pulldown() { - furi_hal_gpio_write(&gpio_rfid_pull, false); + furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false); } void furi_hal_rfid_tim_read(float freq, float duty_cycle) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index 6a5e534e..cedcc82a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -101,7 +101,7 @@ bool furi_hal_usb_set_config(FuriHalUsbInterface* new_if, void* ctx) { return true; } furi_assert(usb.thread); - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventModeChange); return true; } @@ -125,17 +125,17 @@ bool furi_hal_usb_is_locked() { void furi_hal_usb_disable() { furi_assert(usb.thread); - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventDisable); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventDisable); } void furi_hal_usb_enable() { furi_assert(usb.thread); - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventEnable); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventEnable); } void furi_hal_usb_reinit() { furi_assert(usb.thread); - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReinit); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventReinit); } /* Get device / configuration descriptors */ @@ -148,7 +148,7 @@ static usbd_respond usb_descriptor_get(usbd_ctlreq* req, void** address, uint16_ switch(dtype) { case USB_DTYPE_DEVICE: - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventRequest); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventRequest); if(usb.callback != NULL) { usb.callback(FuriHalUsbStateEventDescriptorRequest, usb.cb_ctx); } @@ -192,7 +192,7 @@ static void reset_evt(usbd_device* dev, uint8_t event, uint8_t ep) { UNUSED(dev); UNUSED(event); UNUSED(ep); - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventReset); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventReset); if(usb.callback != NULL) { usb.callback(FuriHalUsbStateEventReset, usb.cb_ctx); } @@ -236,11 +236,11 @@ static int32_t furi_hal_usb_thread(void* context) { FuriHalUsbInterface* if_ctx_new = NULL; if(usb.if_next != NULL) { - osThreadFlagsSet(furi_thread_get_thread_id(usb.thread), EventModeChange); + furi_thread_flags_set(furi_thread_get_id(usb.thread), EventModeChange); } while(true) { - uint32_t flags = osThreadFlagsWait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500); + uint32_t flags = furi_thread_flags_wait(USB_SRV_ALL_EVENTS, osFlagsWaitAny, 500); if((flags & osFlagsError) == 0) { if(flags & EventModeChange) { if(usb.if_next != usb.if_cur) { diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk deleted file mode 100644 index 8e58a71c..00000000 --- a/firmware/targets/f7/target.mk +++ /dev/null @@ -1,162 +0,0 @@ -TOOLCHAIN = arm - -FLASH_ADDRESS = 0x08000000 - -RAM_EXEC ?= 0 -ifeq ($(RAM_EXEC), 1) -CFLAGS += -DFURI_RAM_EXEC -DVECT_TAB_SRAM -DFLIPPER_STREAM_LITE -else -LDFLAGS += -u _printf_float -endif - -DEBUG_RTOS_THREADS ?= 1 -ifeq ($(DEBUG_RTOS_THREADS), 1) -OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" -else -OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "init" -endif - -MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard - -# Warnings configuration -CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion - -CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant -LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs - -CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions -LDFLAGS += -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group - -HARDWARE_TARGET = 7 - -MXPROJECT_DIR = $(TARGET_DIR) - -# Entry Point -ASM_SOURCES += $(MXPROJECT_DIR)/startup_stm32wb55xx_cm4.s - -# STM32WB HAL -CUBE_DIR = ../lib/STM32CubeWB -CFLAGS += \ - -DUSE_FULL_LL_DRIVER \ - -DUSE_FULL_ASSERT \ - -DHAVE_FREERTOS -CFLAGS += \ - -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ - -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST \ - -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include \ - -I$(CUBE_DIR)/Drivers/CMSIS/Include -C_SOURCES += \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_comp.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_dma.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_gpio.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lptim.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rtc.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lpuart.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rng.c - -# FreeRTOS -CFLAGS += \ - -I$(LIB_DIR)/FreeRTOS-Kernel/include \ - -I$(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F \ - -I$(LIB_DIR)/FreeRTOS-glue/ - -C_SOURCES += \ - $(LIB_DIR)/FreeRTOS-Kernel/event_groups.c \ - $(LIB_DIR)/FreeRTOS-Kernel/list.c \ - $(LIB_DIR)/FreeRTOS-Kernel/queue.c \ - $(LIB_DIR)/FreeRTOS-Kernel/stream_buffer.c \ - $(LIB_DIR)/FreeRTOS-Kernel/tasks.c \ - $(LIB_DIR)/FreeRTOS-Kernel/timers.c \ - $(LIB_DIR)/FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c \ - $(LIB_DIR)/FreeRTOS-glue/cmsis_os2.c \ - -# BLE glue -CFLAGS += \ - -I$(TARGET_DIR)/ble_glue \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/template \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci -C_SOURCES += \ - $(wildcard $(TARGET_DIR)/ble_glue/*.c) \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/otp.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/stm_list.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/dbg_trace.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/svc/Src/svc_ctl.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/template/osal.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hci_le.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gap_aci.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gatt_aci.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hal_aci.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_l2cap_aci.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/tl_mbox.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/hci_tl_if.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/shci_tl.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/shci_tl_if.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci/shci.c - -# USB stack -CFLAGS += \ - -DSTM32WB \ - -DUSB_PMASIZE=0x400 - -# Furi HAL -FURI_HAL_OS_DEBUG ?= 0 -ifeq ($(FURI_HAL_OS_DEBUG), 1) -CFLAGS += -DFURI_HAL_OS_DEBUG -endif - -FURI_HAL_USB_VCP_DEBUG ?= 0 -ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1) -CFLAGS += -DFURI_HAL_USB_VCP_DEBUG -endif - -ifeq ($(FURI_HAL_POWER_DEEP_SLEEP_ENABLED), 1) -CFLAGS += -DFURI_HAL_POWER_DEEP_SLEEP_ENABLED -endif - -FURI_HAL_SUBGHZ_TX_GPIO ?= 0 -ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) -CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) -endif - -ifeq ($(INVERT_RFID_IN), 1) -CFLAGS += -DINVERT_RFID_IN -endif - -ifeq ($(BLE_GLUE_DEBUG), 1) -CFLAGS += -DBLE_GLUE_DEBUG -endif - -FURI_HAL_DIR = $(TARGET_DIR)/furi_hal -CFLAGS += -I$(FURI_HAL_DIR) -C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) - -# Other -CFLAGS += \ - -I$(MXPROJECT_DIR)/Inc \ - -I$(MXPROJECT_DIR)/fatfs -C_SOURCES += \ - $(wildcard $(MXPROJECT_DIR)/Src/*.c) \ - $(wildcard $(MXPROJECT_DIR)/fatfs/*.c) - -ifeq ($(RAM_EXEC), 1) -LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_ram_fw.ld -else # RAM_EXEC -# Linker options -LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_flash.ld -endif # RAM_EXEC - -SVD_FILE = ../debug/STM32WB55_CM4.svd diff --git a/lib/FreeRTOS-glue/cmsis_os2.c b/lib/FreeRTOS-glue/cmsis_os2.c index 4e59fb54..bee37572 100644 --- a/lib/FreeRTOS-glue/cmsis_os2.c +++ b/lib/FreeRTOS-glue/cmsis_os2.c @@ -26,15 +26,11 @@ #include "cmsis_os2.h" // ::CMSIS:RTOS2 #include "cmsis_compiler.h" // Compiler agnostic definitions -#include "os_tick.h" // OS Tick API #include "FreeRTOS.h" // ARM.FreeRTOS::RTOS:Core -#include "task.h" // ARM.FreeRTOS::RTOS:Core -#include "event_groups.h" // ARM.FreeRTOS::RTOS:Event Groups -#include "semphr.h" // ARM.FreeRTOS::RTOS:Core #include "timers.h" // ARM.FreeRTOS::RTOS:Timers +#include "queue.h" -#include "freertos_mpool.h" // osMemoryPool definitions #include "freertos_os2.h" // Configuration check and setup #include CMSIS_device_header @@ -87,10 +83,8 @@ /* Limits */ #define MAX_BITS_TASK_NOTIFY 31U -#define MAX_BITS_EVENT_GROUPS 24U #define THREAD_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_TASK_NOTIFY) - 1U)) -#define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U)) /* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */ #define KERNEL_VERSION (((uint32_t)tskKERNEL_VERSION_MAJOR * 10000000UL) | \ @@ -453,31 +447,6 @@ uint32_t osKernelGetTickFreq (void) { return (configTICK_RATE_HZ); } -/* - Get the RTOS kernel system timer count. -*/ -uint32_t osKernelGetSysTimerCount (void) { - TickType_t ticks; - uint32_t val; - - FURI_CRITICAL_ENTER(); - - ticks = xTaskGetTickCount(); - val = OS_Tick_GetCount(); - - /* Update tick count and timer value when timer overflows */ - if (OS_Tick_GetOverflow() != 0U) { - val = OS_Tick_GetCount(); - ticks++; - } - val += ticks * OS_Tick_GetInterval(); - - FURI_CRITICAL_EXIT(); - - /* Return system timer count */ - return (val); -} - /* Get the RTOS kernel system timer frequency. */ @@ -486,531 +455,6 @@ uint32_t osKernelGetSysTimerFreq (void) { return (configCPU_CLOCK_HZ); } - -/* ==== Thread Management Functions ==== */ - -/* - Create a thread and add it to Active Threads. - - Limitations: - - The memory for control block and stack must be provided in the osThreadAttr_t - structure in order to allocate object statically. - - Attribute osThreadJoinable is not supported, NULL is returned if used. -*/ -osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) { - const char *name; - uint32_t stack; - TaskHandle_t hTask; - UBaseType_t prio; - int32_t mem; - - hTask = NULL; - - if ((IRQ_Context() == 0U) && (func != NULL)) { - stack = configMINIMAL_STACK_SIZE; - prio = (UBaseType_t)osPriorityNormal; - - name = NULL; - mem = -1; - - if (attr != NULL) { - if (attr->name != NULL) { - name = attr->name; - } - if (attr->priority != osPriorityNone) { - prio = (UBaseType_t)attr->priority; - } - - if ((prio < osPriorityIdle) || (prio > osPriorityISR) || ((attr->attr_bits & osThreadJoinable) == osThreadJoinable)) { - /* Invalid priority or unsupported osThreadJoinable attribute used */ - return (NULL); - } - - if (attr->stack_size > 0U) { - /* In FreeRTOS stack is not in bytes, but in sizeof(StackType_t) which is 4 on ARM ports. */ - /* Stack size should be therefore 4 byte aligned in order to avoid division caused side effects */ - stack = attr->stack_size / sizeof(StackType_t); - } - - if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticTask_t)) && - (attr->stack_mem != NULL) && (attr->stack_size > 0U)) { - /* The memory for control block and stack is provided, use static object */ - mem = 1; - } - else { - if ((attr->cb_mem == NULL) && (attr->cb_size == 0U) && (attr->stack_mem == NULL)) { - /* Control block and stack memory will be allocated from the dynamic pool */ - mem = 0; - } - } - } - else { - mem = 0; - } - - if (mem == 1) { - #if (configSUPPORT_STATIC_ALLOCATION == 1) - hTask = xTaskCreateStatic ((TaskFunction_t)func, name, stack, argument, prio, (StackType_t *)attr->stack_mem, - (StaticTask_t *)attr->cb_mem); - #endif - } - else { - if (mem == 0) { - #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if (xTaskCreate ((TaskFunction_t)func, name, (configSTACK_DEPTH_TYPE)stack, argument, prio, &hTask) != pdPASS) { - hTask = NULL; - } - #endif - } - } - } - - /* Return thread ID */ - return ((osThreadId_t)hTask); -} - -/* - Get name of a thread. -*/ -const char *osThreadGetName (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - const char *name; - - if ((IRQ_Context() != 0U) || (hTask == NULL)) { - name = NULL; - } else if(osKernelGetState() == osKernelRunning) { - name = pcTaskGetName (hTask); - } else { - name = NULL; - } - - /* Return name as null-terminated string */ - return (name); -} - -/* - Return the thread ID of the current running thread. -*/ -osThreadId_t osThreadGetId (void) { - osThreadId_t id; - - id = (osThreadId_t)xTaskGetCurrentTaskHandle(); - - /* Return thread ID */ - return (id); -} - -/* - Get current thread state of a thread. -*/ -osThreadState_t osThreadGetState (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osThreadState_t state; - - if ((IRQ_Context() != 0U) || (hTask == NULL)) { - state = osThreadError; - } - else { - switch (eTaskGetState (hTask)) { - case eRunning: state = osThreadRunning; break; - case eReady: state = osThreadReady; break; - case eBlocked: - case eSuspended: state = osThreadBlocked; break; - case eDeleted: state = osThreadTerminated; break; - case eInvalid: - default: state = osThreadError; break; - } - } - - /* Return current thread state */ - return (state); -} - -/* - Get available stack space of a thread based on stack watermark recording during execution. -*/ -uint32_t osThreadGetStackSpace (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - uint32_t sz; - - if ((IRQ_Context() != 0U) || (hTask == NULL)) { - sz = 0U; - } else { - sz = (uint32_t)(uxTaskGetStackHighWaterMark(hTask) * sizeof(StackType_t)); - } - - /* Return remaining stack space in bytes */ - return (sz); -} - -/* - Change priority of a thread. -*/ -osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osStatus_t stat; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if ((hTask == NULL) || (priority < osPriorityIdle) || (priority > osPriorityISR)) { - stat = osErrorParameter; - } - else { - stat = osOK; - vTaskPrioritySet (hTask, (UBaseType_t)priority); - } - - /* Return execution status */ - return (stat); -} - -/* - Get current priority of a thread. -*/ -osPriority_t osThreadGetPriority (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osPriority_t prio; - - if ((IRQ_Context() != 0U) || (hTask == NULL)) { - prio = osPriorityError; - } else { - prio = (osPriority_t)((int32_t)uxTaskPriorityGet (hTask)); - } - - /* Return current thread priority */ - return (prio); -} - -/* - Pass control to next thread that is in state READY. -*/ -osStatus_t osThreadYield (void) { - osStatus_t stat; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } else { - stat = osOK; - taskYIELD(); - } - - /* Return execution status */ - return (stat); -} - -#if (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) -/* - Suspend execution of a thread. -*/ -osStatus_t osThreadSuspend (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osStatus_t stat; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hTask == NULL) { - stat = osErrorParameter; - } - else { - stat = osOK; - vTaskSuspend (hTask); - } - - /* Return execution status */ - return (stat); -} - -/* - Resume execution of a thread. -*/ -osStatus_t osThreadResume (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osStatus_t stat; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hTask == NULL) { - stat = osErrorParameter; - } - else { - stat = osOK; - vTaskResume (hTask); - } - - /* Return execution status */ - return (stat); -} -#endif /* (configUSE_OS2_THREAD_SUSPEND_RESUME == 1) */ - -/* - Terminate execution of current running thread. -*/ -__NO_RETURN void osThreadExit (void) { -#ifndef USE_FreeRTOS_HEAP_1 - vTaskDelete (NULL); -#endif - for (;;); -} - -/* - Terminate execution of a thread. -*/ -osStatus_t osThreadTerminate (osThreadId_t thread_id) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - osStatus_t stat; -#ifndef USE_FreeRTOS_HEAP_1 - eTaskState tstate; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hTask == NULL) { - stat = osErrorParameter; - } - else { - tstate = eTaskGetState (hTask); - - if (tstate != eDeleted) { - stat = osOK; - vTaskDelete (hTask); - } else { - stat = osErrorResource; - } - } -#else - stat = osError; -#endif - - /* Return execution status */ - return (stat); -} - -/* - Get number of active threads. -*/ -uint32_t osThreadGetCount (void) { - uint32_t count; - - if (IRQ_Context() != 0U) { - count = 0U; - } else { - count = uxTaskGetNumberOfTasks(); - } - - /* Return number of active threads */ - return (count); -} - -#if (configUSE_OS2_THREAD_ENUMERATE == 1) -/* - Enumerate active threads. -*/ -uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items) { - uint32_t i, count; - TaskStatus_t *task; - - if ((IRQ_Context() != 0U) || (thread_array == NULL) || (array_items == 0U)) { - count = 0U; - } else { - vTaskSuspendAll(); - - /* Allocate memory on heap to temporarily store TaskStatus_t information */ - count = uxTaskGetNumberOfTasks(); - task = pvPortMalloc (count * sizeof(TaskStatus_t)); - - if (task != NULL) { - /* Retrieve task status information */ - count = uxTaskGetSystemState (task, count, NULL); - - /* Copy handles from task status array into provided thread array */ - for (i = 0U; (i < count) && (i < array_items); i++) { - thread_array[i] = (osThreadId_t)task[i].xHandle; - } - count = i; - } - (void)xTaskResumeAll(); - - vPortFree (task); - } - - /* Return number of enumerated threads */ - return (count); -} -#endif /* (configUSE_OS2_THREAD_ENUMERATE == 1) */ - - -/* ==== Thread Flags Functions ==== */ - -#if (configUSE_OS2_THREAD_FLAGS == 1) -/* - Set the specified Thread Flags of a thread. -*/ -uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags) { - TaskHandle_t hTask = (TaskHandle_t)thread_id; - uint32_t rflags; - BaseType_t yield; - - if ((hTask == NULL) || ((flags & THREAD_FLAGS_INVALID_BITS) != 0U)) { - rflags = (uint32_t)osErrorParameter; - } - else { - rflags = (uint32_t)osError; - - if (IRQ_Context() != 0U) { - yield = pdFALSE; - - (void)xTaskNotifyIndexedFromISR (hTask, CMSIS_TASK_NOTIFY_INDEX, flags, eSetBits, &yield); - (void)xTaskNotifyAndQueryIndexedFromISR (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags, NULL); - - portYIELD_FROM_ISR (yield); - } - else { - (void)xTaskNotifyIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, flags, eSetBits); - (void)xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags); - } - } - /* Return flags after setting */ - return (rflags); -} - -/* - Clear the specified Thread Flags of current running thread. -*/ -uint32_t osThreadFlagsClear (uint32_t flags) { - TaskHandle_t hTask; - uint32_t rflags, cflags; - - if (IRQ_Context() != 0U) { - rflags = (uint32_t)osErrorISR; - } - else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) { - rflags = (uint32_t)osErrorParameter; - } - else { - hTask = xTaskGetCurrentTaskHandle(); - - if (xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &cflags) == pdPASS) { - rflags = cflags; - cflags &= ~flags; - - if (xTaskNotifyIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, cflags, eSetValueWithOverwrite) != pdPASS) { - rflags = (uint32_t)osError; - } - } - else { - rflags = (uint32_t)osError; - } - } - - /* Return flags before clearing */ - return (rflags); -} - -/* - Get the current Thread Flags of current running thread. -*/ -uint32_t osThreadFlagsGet (void) { - TaskHandle_t hTask; - uint32_t rflags; - - if (IRQ_Context() != 0U) { - rflags = (uint32_t)osErrorISR; - } - else { - hTask = xTaskGetCurrentTaskHandle(); - - if (xTaskNotifyAndQueryIndexed (hTask, CMSIS_TASK_NOTIFY_INDEX, 0, eNoAction, &rflags) != pdPASS) { - rflags = (uint32_t)osError; - } - } - - /* Return current flags */ - return (rflags); -} - -/* - Wait for one or more Thread Flags of the current running thread to become signaled. -*/ -uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout) { - uint32_t rflags, nval; - uint32_t clear; - TickType_t t0, td, tout; - BaseType_t rval; - - if (IRQ_Context() != 0U) { - rflags = (uint32_t)osErrorISR; - } - else if ((flags & THREAD_FLAGS_INVALID_BITS) != 0U) { - rflags = (uint32_t)osErrorParameter; - } - else { - if ((options & osFlagsNoClear) == osFlagsNoClear) { - clear = 0U; - } else { - clear = flags; - } - - rflags = 0U; - tout = timeout; - - t0 = xTaskGetTickCount(); - do { - rval = xTaskNotifyWaitIndexed (CMSIS_TASK_NOTIFY_INDEX, 0, clear, &nval, tout); - - if (rval == pdPASS) { - rflags &= flags; - rflags |= nval; - - if ((options & osFlagsWaitAll) == osFlagsWaitAll) { - if ((flags & rflags) == flags) { - break; - } else { - if (timeout == 0U) { - rflags = (uint32_t)osErrorResource; - break; - } - } - } - else { - if ((flags & rflags) != 0) { - break; - } else { - if (timeout == 0U) { - rflags = (uint32_t)osErrorResource; - break; - } - } - } - - /* Update timeout */ - td = xTaskGetTickCount() - t0; - - if (td > timeout) { - tout = 0; - } else { - tout = timeout - td; - } - } - else { - if (timeout == 0) { - rflags = (uint32_t)osErrorResource; - } else { - rflags = (uint32_t)osErrorTimeout; - } - } - } - while (rval != pdFAIL); - } - - /* Return flags before clearing */ - return (rflags); -} -#endif /* (configUSE_OS2_THREAD_FLAGS == 1) */ - - /* ==== Generic Wait Functions ==== */ /* @@ -1330,681 +774,6 @@ osStatus_t osTimerDelete (osTimerId_t timer_id) { #endif /* (configUSE_OS2_TIMER == 1) */ -/* ==== Event Flags Management Functions ==== */ - -/* - Create and Initialize an Event Flags object. - - Limitations: - - Event flags are limited to 24 bits. -*/ -osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) { - EventGroupHandle_t hEventGroup; - int32_t mem; - - hEventGroup = NULL; - - if (IRQ_Context() == 0U) { - mem = -1; - - if (attr != NULL) { - if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) { - /* The memory for control block is provided, use static object */ - mem = 1; - } - else { - if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { - /* Control block will be allocated from the dynamic pool */ - mem = 0; - } - } - } - else { - mem = 0; - } - - if (mem == 1) { - #if (configSUPPORT_STATIC_ALLOCATION == 1) - hEventGroup = xEventGroupCreateStatic (attr->cb_mem); - #endif - } - else { - if (mem == 0) { - #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - hEventGroup = xEventGroupCreate(); - #endif - } - } - } - - /* Return event flags ID */ - return ((osEventFlagsId_t)hEventGroup); -} - -/* - Set the specified Event Flags. - - Limitations: - - Event flags are limited to 24 bits. -*/ -uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) { - EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; - uint32_t rflags; - BaseType_t yield; - - if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { - rflags = (uint32_t)osErrorParameter; - } - else if (IRQ_Context() != 0U) { - #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0) - (void)yield; - /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */ - rflags = (uint32_t)osErrorResource; - #else - yield = pdFALSE; - - if (xEventGroupSetBitsFromISR (hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) { - rflags = (uint32_t)osErrorResource; - } else { - rflags = flags; - portYIELD_FROM_ISR (yield); - } - #endif - } - else { - rflags = xEventGroupSetBits (hEventGroup, (EventBits_t)flags); - } - - /* Return event flags after setting */ - return (rflags); -} - -/* - Clear the specified Event Flags. - - Limitations: - - Event flags are limited to 24 bits. -*/ -uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) { - EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; - uint32_t rflags; - - if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { - rflags = (uint32_t)osErrorParameter; - } - else if (IRQ_Context() != 0U) { - #if (configUSE_OS2_EVENTFLAGS_FROM_ISR == 0) - /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */ - rflags = (uint32_t)osErrorResource; - #else - rflags = xEventGroupGetBitsFromISR (hEventGroup); - - if (xEventGroupClearBitsFromISR (hEventGroup, (EventBits_t)flags) == pdFAIL) { - rflags = (uint32_t)osErrorResource; - } - else { - /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */ - /* Yield is required here otherwise clear operation might not execute in the right order. */ - /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info. */ - portYIELD_FROM_ISR (pdTRUE); - } - #endif - } - else { - rflags = xEventGroupClearBits (hEventGroup, (EventBits_t)flags); - } - - /* Return event flags before clearing */ - return (rflags); -} - -/* - Get the current Event Flags. - - Limitations: - - Event flags are limited to 24 bits. -*/ -uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) { - EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; - uint32_t rflags; - - if (ef_id == NULL) { - rflags = 0U; - } - else if (IRQ_Context() != 0U) { - rflags = xEventGroupGetBitsFromISR (hEventGroup); - } - else { - rflags = xEventGroupGetBits (hEventGroup); - } - - /* Return current event flags */ - return (rflags); -} - -/* - Wait for one or more Event Flags to become signaled. - - Limitations: - - Event flags are limited to 24 bits. - - osEventFlagsWait cannot be called from an ISR. -*/ -uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) { - EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; - BaseType_t wait_all; - BaseType_t exit_clr; - uint32_t rflags; - - if ((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) { - rflags = (uint32_t)osErrorParameter; - } - else if (IRQ_Context() != 0U) { - rflags = (uint32_t)osErrorISR; - } - else { - if (options & osFlagsWaitAll) { - wait_all = pdTRUE; - } else { - wait_all = pdFAIL; - } - - if (options & osFlagsNoClear) { - exit_clr = pdFAIL; - } else { - exit_clr = pdTRUE; - } - - rflags = xEventGroupWaitBits (hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout); - - if (options & osFlagsWaitAll) { - if ((flags & rflags) != flags) { - if (timeout > 0U) { - rflags = (uint32_t)osErrorTimeout; - } else { - rflags = (uint32_t)osErrorResource; - } - } - } - else { - if ((flags & rflags) == 0U) { - if (timeout > 0U) { - rflags = (uint32_t)osErrorTimeout; - } else { - rflags = (uint32_t)osErrorResource; - } - } - } - } - - /* Return event flags before clearing */ - return (rflags); -} - -/* - Delete an Event Flags object. -*/ -osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) { - EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id; - osStatus_t stat; - -#ifndef USE_FreeRTOS_HEAP_1 - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hEventGroup == NULL) { - stat = osErrorParameter; - } - else { - stat = osOK; - vEventGroupDelete (hEventGroup); - } -#else - stat = osError; -#endif - - /* Return execution status */ - return (stat); -} - - -/* ==== Mutex Management Functions ==== */ - -#if (configUSE_OS2_MUTEX == 1) -/* - Create and Initialize a Mutex object. - - Limitations: - - Priority inherit protocol is used by default, osMutexPrioInherit attribute is ignored. - - Robust mutex is not supported, NULL is returned if used. -*/ -osMutexId_t osMutexNew (const osMutexAttr_t *attr) { - SemaphoreHandle_t hMutex; - uint32_t type; - uint32_t rmtx; - int32_t mem; - - hMutex = NULL; - - if (IRQ_Context() == 0U) { - if (attr != NULL) { - type = attr->attr_bits; - } else { - type = 0U; - } - - if ((type & osMutexRecursive) == osMutexRecursive) { - rmtx = 1U; - } else { - rmtx = 0U; - } - - if ((type & osMutexRobust) != osMutexRobust) { - mem = -1; - - if (attr != NULL) { - if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) { - /* The memory for control block is provided, use static object */ - mem = 1; - } - else { - if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { - /* Control block will be allocated from the dynamic pool */ - mem = 0; - } - } - } - else { - mem = 0; - } - - if (mem == 1) { - #if (configSUPPORT_STATIC_ALLOCATION == 1) - if (rmtx != 0U) { - #if (configUSE_RECURSIVE_MUTEXES == 1) - hMutex = xSemaphoreCreateRecursiveMutexStatic (attr->cb_mem); - #endif - } - else { - hMutex = xSemaphoreCreateMutexStatic (attr->cb_mem); - } - #endif - } - else { - if (mem == 0) { - #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - if (rmtx != 0U) { - #if (configUSE_RECURSIVE_MUTEXES == 1) - hMutex = xSemaphoreCreateRecursiveMutex (); - #endif - } else { - hMutex = xSemaphoreCreateMutex (); - } - #endif - } - } - - #if (configQUEUE_REGISTRY_SIZE > 0) - if (hMutex != NULL) { - if ((attr != NULL) && (attr->name != NULL)) { - /* Only non-NULL name objects are added to the Queue Registry */ - vQueueAddToRegistry (hMutex, attr->name); - } - } - #endif - - if ((hMutex != NULL) && (rmtx != 0U)) { - /* Set LSB as 'recursive mutex flag' */ - hMutex = (SemaphoreHandle_t)((uint32_t)hMutex | 1U); - } - } - } - - /* Return mutex ID */ - return ((osMutexId_t)hMutex); -} - -/* - Acquire a Mutex or timeout if it is locked. -*/ -osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout) { - SemaphoreHandle_t hMutex; - osStatus_t stat; - uint32_t rmtx; - - hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); - - /* Extract recursive mutex flag */ - rmtx = (uint32_t)mutex_id & 1U; - - stat = osOK; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hMutex == NULL) { - stat = osErrorParameter; - } - else { - if (rmtx != 0U) { - #if (configUSE_RECURSIVE_MUTEXES == 1) - if (xSemaphoreTakeRecursive (hMutex, timeout) != pdPASS) { - if (timeout != 0U) { - stat = osErrorTimeout; - } else { - stat = osErrorResource; - } - } - #endif - } - else { - if (xSemaphoreTake (hMutex, timeout) != pdPASS) { - if (timeout != 0U) { - stat = osErrorTimeout; - } else { - stat = osErrorResource; - } - } - } - } - - /* Return execution status */ - return (stat); -} - -/* - Release a Mutex that was acquired by osMutexAcquire. -*/ -osStatus_t osMutexRelease (osMutexId_t mutex_id) { - SemaphoreHandle_t hMutex; - osStatus_t stat; - uint32_t rmtx; - - hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); - - /* Extract recursive mutex flag */ - rmtx = (uint32_t)mutex_id & 1U; - - stat = osOK; - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hMutex == NULL) { - stat = osErrorParameter; - } - else { - if (rmtx != 0U) { - #if (configUSE_RECURSIVE_MUTEXES == 1) - if (xSemaphoreGiveRecursive (hMutex) != pdPASS) { - stat = osErrorResource; - } - #endif - } - else { - if (xSemaphoreGive (hMutex) != pdPASS) { - stat = osErrorResource; - } - } - } - - /* Return execution status */ - return (stat); -} - -/* - Get Thread which owns a Mutex object. -*/ -osThreadId_t osMutexGetOwner (osMutexId_t mutex_id) { - SemaphoreHandle_t hMutex; - osThreadId_t owner; - - hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); - - if ((IRQ_Context() != 0U) || (hMutex == NULL)) { - owner = NULL; - } else { - owner = (osThreadId_t)xSemaphoreGetMutexHolder (hMutex); - } - - /* Return owner thread ID */ - return (owner); -} - -/* - Delete a Mutex object. -*/ -osStatus_t osMutexDelete (osMutexId_t mutex_id) { - osStatus_t stat; -#ifndef USE_FreeRTOS_HEAP_1 - SemaphoreHandle_t hMutex; - - hMutex = (SemaphoreHandle_t)((uint32_t)mutex_id & ~1U); - - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hMutex == NULL) { - stat = osErrorParameter; - } - else { - #if (configQUEUE_REGISTRY_SIZE > 0) - vQueueUnregisterQueue (hMutex); - #endif - stat = osOK; - vSemaphoreDelete (hMutex); - } -#else - stat = osError; -#endif - - /* Return execution status */ - return (stat); -} -#endif /* (configUSE_OS2_MUTEX == 1) */ - - -/* ==== Semaphore Management Functions ==== */ - -/* - Create and Initialize a Semaphore object. -*/ -osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) { - SemaphoreHandle_t hSemaphore; - int32_t mem; - - hSemaphore = NULL; - - if ((IRQ_Context() == 0U) && (max_count > 0U) && (initial_count <= max_count)) { - mem = -1; - - if (attr != NULL) { - if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticSemaphore_t))) { - /* The memory for control block is provided, use static object */ - mem = 1; - } - else { - if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { - /* Control block will be allocated from the dynamic pool */ - mem = 0; - } - } - } - else { - mem = 0; - } - - if (mem != -1) { - if (max_count == 1U) { - if (mem == 1) { - #if (configSUPPORT_STATIC_ALLOCATION == 1) - hSemaphore = xSemaphoreCreateBinaryStatic ((StaticSemaphore_t *)attr->cb_mem); - #endif - } - else { - #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - hSemaphore = xSemaphoreCreateBinary(); - #endif - } - - if ((hSemaphore != NULL) && (initial_count != 0U)) { - if (xSemaphoreGive (hSemaphore) != pdPASS) { - vSemaphoreDelete (hSemaphore); - hSemaphore = NULL; - } - } - } - else { - if (mem == 1) { - #if (configSUPPORT_STATIC_ALLOCATION == 1) - hSemaphore = xSemaphoreCreateCountingStatic (max_count, initial_count, (StaticSemaphore_t *)attr->cb_mem); - #endif - } - else { - #if (configSUPPORT_DYNAMIC_ALLOCATION == 1) - hSemaphore = xSemaphoreCreateCounting (max_count, initial_count); - #endif - } - } - - #if (configQUEUE_REGISTRY_SIZE > 0) - if (hSemaphore != NULL) { - if ((attr != NULL) && (attr->name != NULL)) { - /* Only non-NULL name objects are added to the Queue Registry */ - vQueueAddToRegistry (hSemaphore, attr->name); - } - } - #endif - } - } - - /* Return semaphore ID */ - return ((osSemaphoreId_t)hSemaphore); -} - -/* - Acquire a Semaphore token or timeout if no tokens are available. -*/ -osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout) { - SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; - osStatus_t stat; - BaseType_t yield; - - stat = osOK; - - if (hSemaphore == NULL) { - stat = osErrorParameter; - } - else if (IRQ_Context() != 0U) { - if (timeout != 0U) { - stat = osErrorParameter; - } - else { - yield = pdFALSE; - - if (xSemaphoreTakeFromISR (hSemaphore, &yield) != pdPASS) { - stat = osErrorResource; - } else { - portYIELD_FROM_ISR (yield); - } - } - } - else { - if (xSemaphoreTake (hSemaphore, (TickType_t)timeout) != pdPASS) { - if (timeout != 0U) { - stat = osErrorTimeout; - } else { - stat = osErrorResource; - } - } - } - - /* Return execution status */ - return (stat); -} - -/* - Release a Semaphore token up to the initial maximum count. -*/ -osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id) { - SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; - osStatus_t stat; - BaseType_t yield; - - stat = osOK; - - if (hSemaphore == NULL) { - stat = osErrorParameter; - } - else if (IRQ_Context() != 0U) { - yield = pdFALSE; - - if (xSemaphoreGiveFromISR (hSemaphore, &yield) != pdTRUE) { - stat = osErrorResource; - } else { - portYIELD_FROM_ISR (yield); - } - } - else { - if (xSemaphoreGive (hSemaphore) != pdPASS) { - stat = osErrorResource; - } - } - - /* Return execution status */ - return (stat); -} - -/* - Get current Semaphore token count. -*/ -uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id) { - SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; - uint32_t count; - - if (hSemaphore == NULL) { - count = 0U; - } - else if (IRQ_Context() != 0U) { - count = (uint32_t)uxSemaphoreGetCountFromISR (hSemaphore); - } else { - count = (uint32_t)uxSemaphoreGetCount (hSemaphore); - } - - /* Return number of tokens */ - return (count); -} - -/* - Delete a Semaphore object. -*/ -osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id) { - SemaphoreHandle_t hSemaphore = (SemaphoreHandle_t)semaphore_id; - osStatus_t stat; - -#ifndef USE_FreeRTOS_HEAP_1 - if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else if (hSemaphore == NULL) { - stat = osErrorParameter; - } - else { - #if (configQUEUE_REGISTRY_SIZE > 0) - vQueueUnregisterQueue (hSemaphore); - #endif - - stat = osOK; - vSemaphoreDelete (hSemaphore); - } -#else - stat = osError; -#endif - - /* Return execution status */ - return (stat); -} - - /* ==== Message Queue Management Functions ==== */ /* @@ -2301,498 +1070,6 @@ osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) { return (stat); } - -/* ==== Memory Pool Management Functions ==== */ - -#ifdef FREERTOS_MPOOL_H_ -/* Static memory pool functions */ -static void FreeBlock (MemPool_t *mp, void *block); -static void *AllocBlock (MemPool_t *mp); -static void *CreateBlock (MemPool_t *mp); - -/* - Create and Initialize a Memory Pool object. -*/ -osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) { - MemPool_t *mp; - const char *name; - int32_t mem_cb, mem_mp; - uint32_t sz; - - if (IRQ_Context() != 0U) { - mp = NULL; - } - else if ((block_count == 0U) || (block_size == 0U)) { - mp = NULL; - } - else { - mp = NULL; - sz = MEMPOOL_ARR_SIZE (block_count, block_size); - - name = NULL; - mem_cb = -1; - mem_mp = -1; - - if (attr != NULL) { - if (attr->name != NULL) { - name = attr->name; - } - - if ((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(MemPool_t))) { - /* Static control block is provided */ - mem_cb = 1; - } - else if ((attr->cb_mem == NULL) && (attr->cb_size == 0U)) { - /* Allocate control block memory on heap */ - mem_cb = 0; - } - - if ((attr->mp_mem == NULL) && (attr->mp_size == 0U)) { - /* Allocate memory array on heap */ - mem_mp = 0; - } - else { - if (attr->mp_mem != NULL) { - /* Check if array is 4-byte aligned */ - if (((uint32_t)attr->mp_mem & 3U) == 0U) { - /* Check if array big enough */ - if (attr->mp_size >= sz) { - /* Static memory pool array is provided */ - mem_mp = 1; - } - } - } - } - } - else { - /* Attributes not provided, allocate memory on heap */ - mem_cb = 0; - mem_mp = 0; - } - - if (mem_cb == 0) { - mp = pvPortMalloc (sizeof(MemPool_t)); - } else { - mp = attr->cb_mem; - } - - if (mp != NULL) { - /* Create a semaphore (max count == initial count == block_count) */ - #if (configSUPPORT_STATIC_ALLOCATION == 1) - mp->sem = xSemaphoreCreateCountingStatic (block_count, block_count, &mp->mem_sem); - #elif (configSUPPORT_DYNAMIC_ALLOCATION == 1) - mp->sem = xSemaphoreCreateCounting (block_count, block_count); - #else - mp->sem = NULL; - #endif - - if (mp->sem != NULL) { - /* Setup memory array */ - if (mem_mp == 0) { - mp->mem_arr = pvPortMalloc (sz); - } else { - mp->mem_arr = attr->mp_mem; - } - } - } - - if ((mp != NULL) && (mp->mem_arr != NULL)) { - /* Memory pool can be created */ - mp->head = NULL; - mp->mem_sz = sz; - mp->name = name; - mp->bl_sz = block_size; - mp->bl_cnt = block_count; - mp->n = 0U; - - /* Set heap allocated memory flags */ - mp->status = MPOOL_STATUS; - - if (mem_cb == 0) { - /* Control block on heap */ - mp->status |= 1U; - } - if (mem_mp == 0) { - /* Memory array on heap */ - mp->status |= 2U; - } - } - else { - /* Memory pool cannot be created, release allocated resources */ - if ((mem_cb == 0) && (mp != NULL)) { - /* Free control block memory */ - vPortFree (mp); - } - mp = NULL; - } - } - - /* Return memory pool ID */ - return (mp); -} - -/* - Get name of a Memory Pool object. -*/ -const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) { - MemPool_t *mp = (osMemoryPoolId_t)mp_id; - const char *p; - - if (IRQ_Context() != 0U) { - p = NULL; - } - else if (mp_id == NULL) { - p = NULL; - } - else { - p = mp->name; - } - - /* Return name as null-terminated string */ - return (p); -} - -/* - Allocate a memory block from a Memory Pool. -*/ -void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) { - MemPool_t *mp; - void *block; - uint32_t isrm; - - if (mp_id == NULL) { - /* Invalid input parameters */ - block = NULL; - } - else { - block = NULL; - - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) { - if (IRQ_Context() != 0U) { - if (timeout == 0U) { - if (xSemaphoreTakeFromISR (mp->sem, NULL) == pdTRUE) { - if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) { - isrm = taskENTER_CRITICAL_FROM_ISR(); - - /* Get a block from the free-list */ - block = AllocBlock(mp); - - if (block == NULL) { - /* List of free blocks is empty, 'create' new block */ - block = CreateBlock(mp); - } - - taskEXIT_CRITICAL_FROM_ISR(isrm); - } - } - } - } - else { - if (xSemaphoreTake (mp->sem, (TickType_t)timeout) == pdTRUE) { - if ((mp->status & MPOOL_STATUS) == MPOOL_STATUS) { - taskENTER_CRITICAL(); - - /* Get a block from the free-list */ - block = AllocBlock(mp); - - if (block == NULL) { - /* List of free blocks is empty, 'create' new block */ - block = CreateBlock(mp); - } - - taskEXIT_CRITICAL(); - } - } - } - } - } - - /* Return memory block address */ - return (block); -} - -/* - Return an allocated memory block back to a Memory Pool. -*/ -osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) { - MemPool_t *mp; - osStatus_t stat; - uint32_t isrm; - BaseType_t yield; - - if ((mp_id == NULL) || (block == NULL)) { - /* Invalid input parameters */ - stat = osErrorParameter; - } - else { - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) { - /* Invalid object status */ - stat = osErrorResource; - } - else if ((block < (void *)&mp->mem_arr[0]) || (block > (void*)&mp->mem_arr[mp->mem_sz-1])) { - /* Block pointer outside of memory array area */ - stat = osErrorParameter; - } - else { - stat = osOK; - - if (IRQ_Context() != 0U) { - if (uxSemaphoreGetCountFromISR (mp->sem) == mp->bl_cnt) { - stat = osErrorResource; - } - else { - isrm = taskENTER_CRITICAL_FROM_ISR(); - - /* Add block to the list of free blocks */ - FreeBlock(mp, block); - - taskEXIT_CRITICAL_FROM_ISR(isrm); - - yield = pdFALSE; - xSemaphoreGiveFromISR (mp->sem, &yield); - portYIELD_FROM_ISR (yield); - } - } - else { - if (uxSemaphoreGetCount (mp->sem) == mp->bl_cnt) { - stat = osErrorResource; - } - else { - taskENTER_CRITICAL(); - - /* Add block to the list of free blocks */ - FreeBlock(mp, block); - - taskEXIT_CRITICAL(); - - xSemaphoreGive (mp->sem); - } - } - } - } - - /* Return execution status */ - return (stat); -} - -/* - Get maximum number of memory blocks in a Memory Pool. -*/ -uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) { - MemPool_t *mp; - uint32_t n; - - if (mp_id == NULL) { - /* Invalid input parameters */ - n = 0U; - } - else { - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) { - /* Invalid object status */ - n = 0U; - } - else { - n = mp->bl_cnt; - } - } - - /* Return maximum number of memory blocks */ - return (n); -} - -/* - Get memory block size in a Memory Pool. -*/ -uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) { - MemPool_t *mp; - uint32_t sz; - - if (mp_id == NULL) { - /* Invalid input parameters */ - sz = 0U; - } - else { - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) { - /* Invalid object status */ - sz = 0U; - } - else { - sz = mp->bl_sz; - } - } - - /* Return memory block size in bytes */ - return (sz); -} - -/* - Get number of memory blocks used in a Memory Pool. -*/ -uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) { - MemPool_t *mp; - uint32_t n; - - if (mp_id == NULL) { - /* Invalid input parameters */ - n = 0U; - } - else { - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) { - /* Invalid object status */ - n = 0U; - } - else { - if (IRQ_Context() != 0U) { - n = uxSemaphoreGetCountFromISR (mp->sem); - } else { - n = uxSemaphoreGetCount (mp->sem); - } - - n = mp->bl_cnt - n; - } - } - - /* Return number of memory blocks used */ - return (n); -} - -/* - Get number of memory blocks available in a Memory Pool. -*/ -uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) { - MemPool_t *mp; - uint32_t n; - - if (mp_id == NULL) { - /* Invalid input parameters */ - n = 0U; - } - else { - mp = (MemPool_t *)mp_id; - - if ((mp->status & MPOOL_STATUS) != MPOOL_STATUS) { - /* Invalid object status */ - n = 0U; - } - else { - if (IRQ_Context() != 0U) { - n = uxSemaphoreGetCountFromISR (mp->sem); - } else { - n = uxSemaphoreGetCount (mp->sem); - } - } - } - - /* Return number of memory blocks available */ - return (n); -} - -/* - Delete a Memory Pool object. -*/ -osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) { - MemPool_t *mp; - osStatus_t stat; - - if (mp_id == NULL) { - /* Invalid input parameters */ - stat = osErrorParameter; - } - else if (IRQ_Context() != 0U) { - stat = osErrorISR; - } - else { - mp = (MemPool_t *)mp_id; - - taskENTER_CRITICAL(); - - /* Invalidate control block status */ - mp->status = mp->status & 3U; - - /* Wake-up tasks waiting for pool semaphore */ - while (xSemaphoreGive (mp->sem) == pdTRUE); - - mp->head = NULL; - mp->bl_sz = 0U; - mp->bl_cnt = 0U; - - if ((mp->status & 2U) != 0U) { - /* Memory pool array allocated on heap */ - vPortFree (mp->mem_arr); - } - if ((mp->status & 1U) != 0U) { - /* Memory pool control block allocated on heap */ - vPortFree (mp); - } - - taskEXIT_CRITICAL(); - - stat = osOK; - } - - /* Return execution status */ - return (stat); -} - -/* - Create new block given according to the current block index. -*/ -static void *CreateBlock (MemPool_t *mp) { - MemPoolBlock_t *p = NULL; - - if (mp->n < mp->bl_cnt) { - /* Unallocated blocks exist, set pointer to new block */ - p = (void *)(mp->mem_arr + (mp->bl_sz * mp->n)); - - /* Increment block index */ - mp->n += 1U; - } - - return (p); -} - -/* - Allocate a block by reading the list of free blocks. -*/ -static void *AllocBlock (MemPool_t *mp) { - MemPoolBlock_t *p = NULL; - - if (mp->head != NULL) { - /* List of free block exists, get head block */ - p = mp->head; - - /* Head block is now next on the list */ - mp->head = p->next; - } - - return (p); -} - -/* - Free block by putting it to the list of free blocks. -*/ -static void FreeBlock (MemPool_t *mp, void *block) { - MemPoolBlock_t *p = block; - - /* Store current head into block memory space */ - p->next = mp->head; - - /* Store current block as new head */ - mp->head = p; -} -#endif /* FREERTOS_MPOOL_H_ */ -/*---------------------------------------------------------------------------*/ - /* Callback function prototypes */ extern void vApplicationIdleHook (void); extern void vApplicationMallocFailedHook (void); @@ -2841,34 +1118,3 @@ __WEAK void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) configASSERT(0); } #endif - -/*---------------------------------------------------------------------------*/ -#if (configSUPPORT_STATIC_ALLOCATION == 1) -/* - vApplicationGetIdleTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION - equals to 1 and is required for static memory allocation support. -*/ -__WEAK void vApplicationGetIdleTaskMemory (StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) { - /* Idle task control block and stack */ - static StaticTask_t Idle_TCB; - static StackType_t Idle_Stack[configMINIMAL_STACK_SIZE]; - - *ppxIdleTaskTCBBuffer = &Idle_TCB; - *ppxIdleTaskStackBuffer = &Idle_Stack[0]; - *pulIdleTaskStackSize = (uint32_t)configMINIMAL_STACK_SIZE; -} - -/* - vApplicationGetTimerTaskMemory gets called when configSUPPORT_STATIC_ALLOCATION - equals to 1 and is required for static memory allocation support. -*/ -__WEAK void vApplicationGetTimerTaskMemory (StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) { - /* Timer task control block and stack */ - static StaticTask_t Timer_TCB; - static StackType_t Timer_Stack[configTIMER_TASK_STACK_DEPTH]; - - *ppxTimerTaskTCBBuffer = &Timer_TCB; - *ppxTimerTaskStackBuffer = &Timer_Stack[0]; - *pulTimerTaskStackSize = (uint32_t)configTIMER_TASK_STACK_DEPTH; -} -#endif diff --git a/lib/FreeRTOS-glue/cmsis_os2.h b/lib/FreeRTOS-glue/cmsis_os2.h index 76612e29..044c9851 100644 --- a/lib/FreeRTOS-glue/cmsis_os2.h +++ b/lib/FreeRTOS-glue/cmsis_os2.h @@ -43,10 +43,10 @@ * Version 2.0.0 * Initial Release *---------------------------------------------------------------------------*/ - + #ifndef CMSIS_OS2_H_ #define CMSIS_OS2_H_ - + #ifndef __NO_RETURN #if defined(__CC_ARM) #define __NO_RETURN __declspec(noreturn) @@ -60,24 +60,23 @@ #define __NO_RETURN #endif #endif - -#include -#include - + +#include + #ifdef __cplusplus extern "C" { #endif - - + + // ==== Enumerations, structures, defines ==== - + /// Version information. typedef struct { uint32_t api; ///< API version (major.minor.rev: mmnnnrrrr dec). uint32_t kernel; ///< Kernel version (major.minor.rev: mmnnnrrrr dec). } osVersion_t; - + /// Kernel state. typedef enum { osKernelInactive = 0, ///< Inactive. @@ -88,167 +87,31 @@ typedef enum { osKernelError = -1, ///< Error. osKernelReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. } osKernelState_t; - -/// Thread state. -typedef enum { - osThreadInactive = 0, ///< Inactive. - osThreadReady = 1, ///< Ready. - osThreadRunning = 2, ///< Running. - osThreadBlocked = 3, ///< Blocked. - osThreadTerminated = 4, ///< Terminated. - osThreadError = -1, ///< Error. - osThreadReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. -} osThreadState_t; - -/// Priority values. -typedef enum { - osPriorityNone = 0, ///< No priority (not initialized). - osPriorityIdle = 1, ///< Reserved for Idle thread. - osPriorityLow = 8, ///< Priority: low - osPriorityLow1 = 8+1, ///< Priority: low + 1 - osPriorityLow2 = 8+2, ///< Priority: low + 2 - osPriorityLow3 = 8+3, ///< Priority: low + 3 - osPriorityLow4 = 8+4, ///< Priority: low + 4 - osPriorityLow5 = 8+5, ///< Priority: low + 5 - osPriorityLow6 = 8+6, ///< Priority: low + 6 - osPriorityLow7 = 8+7, ///< Priority: low + 7 - osPriorityBelowNormal = 16, ///< Priority: below normal - osPriorityBelowNormal1 = 16+1, ///< Priority: below normal + 1 - osPriorityBelowNormal2 = 16+2, ///< Priority: below normal + 2 - osPriorityBelowNormal3 = 16+3, ///< Priority: below normal + 3 - osPriorityBelowNormal4 = 16+4, ///< Priority: below normal + 4 - osPriorityBelowNormal5 = 16+5, ///< Priority: below normal + 5 - osPriorityBelowNormal6 = 16+6, ///< Priority: below normal + 6 - osPriorityBelowNormal7 = 16+7, ///< Priority: below normal + 7 - osPriorityNormal = 24, ///< Priority: normal - osPriorityNormal1 = 24+1, ///< Priority: normal + 1 - osPriorityNormal2 = 24+2, ///< Priority: normal + 2 - osPriorityNormal3 = 24+3, ///< Priority: normal + 3 - osPriorityNormal4 = 24+4, ///< Priority: normal + 4 - osPriorityNormal5 = 24+5, ///< Priority: normal + 5 - osPriorityNormal6 = 24+6, ///< Priority: normal + 6 - osPriorityNormal7 = 24+7, ///< Priority: normal + 7 - osPriorityAboveNormal = 32, ///< Priority: above normal - osPriorityAboveNormal1 = 32+1, ///< Priority: above normal + 1 - osPriorityAboveNormal2 = 32+2, ///< Priority: above normal + 2 - osPriorityAboveNormal3 = 32+3, ///< Priority: above normal + 3 - osPriorityAboveNormal4 = 32+4, ///< Priority: above normal + 4 - osPriorityAboveNormal5 = 32+5, ///< Priority: above normal + 5 - osPriorityAboveNormal6 = 32+6, ///< Priority: above normal + 6 - osPriorityAboveNormal7 = 32+7, ///< Priority: above normal + 7 - osPriorityHigh = 40, ///< Priority: high - osPriorityHigh1 = 40+1, ///< Priority: high + 1 - osPriorityHigh2 = 40+2, ///< Priority: high + 2 - osPriorityHigh3 = 40+3, ///< Priority: high + 3 - osPriorityHigh4 = 40+4, ///< Priority: high + 4 - osPriorityHigh5 = 40+5, ///< Priority: high + 5 - osPriorityHigh6 = 40+6, ///< Priority: high + 6 - osPriorityHigh7 = 40+7, ///< Priority: high + 7 - osPriorityRealtime = 48, ///< Priority: realtime - osPriorityRealtime1 = 48+1, ///< Priority: realtime + 1 - osPriorityRealtime2 = 48+2, ///< Priority: realtime + 2 - osPriorityRealtime3 = 48+3, ///< Priority: realtime + 3 - osPriorityRealtime4 = 48+4, ///< Priority: realtime + 4 - osPriorityRealtime5 = 48+5, ///< Priority: realtime + 5 - osPriorityRealtime6 = 48+6, ///< Priority: realtime + 6 - osPriorityRealtime7 = 48+7, ///< Priority: realtime + 7 - osPriorityISR = 56, ///< Reserved for ISR deferred thread. - osPriorityError = -1, ///< System cannot determine priority or illegal priority. - osPriorityReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. -} osPriority_t; - -/// Entry point of a thread. -typedef void (*osThreadFunc_t) (void *argument); - + /// Timer callback function. typedef void (*osTimerFunc_t) (void *argument); - + /// Timer type. typedef enum { osTimerOnce = 0, ///< One-shot timer. osTimerPeriodic = 1 ///< Repeating timer. } osTimerType_t; - -// Timeout value. -#define osWaitForever 0xFFFFFFFFU ///< Wait forever timeout value. - -// Flags options (\ref osThreadFlagsWait and \ref osEventFlagsWait). -#define osFlagsWaitAny 0x00000000U ///< Wait for any flag (default). -#define osFlagsWaitAll 0x00000001U ///< Wait for all flags. -#define osFlagsNoClear 0x00000002U ///< Do not clear flags which have been specified to wait for. - -// Flags errors (returned by osThreadFlagsXxxx and osEventFlagsXxxx). -#define osFlagsError 0x80000000U ///< Error indicator. -#define osFlagsErrorUnknown 0xFFFFFFFFU ///< osError (-1). -#define osFlagsErrorTimeout 0xFFFFFFFEU ///< osErrorTimeout (-2). -#define osFlagsErrorResource 0xFFFFFFFDU ///< osErrorResource (-3). -#define osFlagsErrorParameter 0xFFFFFFFCU ///< osErrorParameter (-4). -#define osFlagsErrorISR 0xFFFFFFFAU ///< osErrorISR (-6). - -// Thread attributes (attr_bits in \ref osThreadAttr_t). -#define osThreadDetached 0x00000000U ///< Thread created in detached mode (default) -#define osThreadJoinable 0x00000001U ///< Thread created in joinable mode - -// Mutex attributes (attr_bits in \ref osMutexAttr_t). -#define osMutexRecursive 0x00000001U ///< Recursive mutex. -#define osMutexPrioInherit 0x00000002U ///< Priority inherit protocol. -#define osMutexRobust 0x00000008U ///< Robust mutex. - -/// Status code values returned by CMSIS-RTOS functions. -typedef enum { - osOK = 0, ///< Operation completed successfully. - osError = -1, ///< Unspecified RTOS error: run-time error but no other error message fits. - osErrorTimeout = -2, ///< Operation not completed within the timeout period. - osErrorResource = -3, ///< Resource not available. - osErrorParameter = -4, ///< Parameter error. - osErrorNoMemory = -5, ///< System is out of memory: it was impossible to allocate or reserve memory for the operation. - osErrorISR = -6, ///< Not allowed in ISR context: the function cannot be called from interrupt service routines. - osStatusReserved = 0x7FFFFFFF ///< Prevents enum down-size compiler optimization. -} osStatus_t; - - -/// \details Thread ID identifies the thread. -typedef void *osThreadId_t; - + + /// \details Timer ID identifies the timer. typedef void *osTimerId_t; - -/// \details Event Flags ID identifies the event flags. -typedef void *osEventFlagsId_t; - -/// \details Mutex ID identifies the mutex. -typedef void *osMutexId_t; - -/// \details Semaphore ID identifies the semaphore. -typedef void *osSemaphoreId_t; - -/// \details Memory Pool ID identifies the memory pool. -typedef void *osMemoryPoolId_t; - + /// \details Message Queue ID identifies the message queue. typedef void *osMessageQueueId_t; - - + + #ifndef TZ_MODULEID_T #define TZ_MODULEID_T /// \details Data type that identifies secure software modules called by a process. typedef uint32_t TZ_ModuleId_t; #endif - - -/// Attributes structure for thread. -typedef struct { - const char *name; ///< name of the thread - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block - void *stack_mem; ///< memory for stack - uint32_t stack_size; ///< size of stack - osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) - TZ_ModuleId_t tz_module; ///< TrustZone module identifier - uint32_t reserved; ///< reserved (must be 0) -} osThreadAttr_t; - + + /// Attributes structure for timer. typedef struct { const char *name; ///< name of the timer @@ -256,41 +119,7 @@ typedef struct { void *cb_mem; ///< memory for control block uint32_t cb_size; ///< size of provided memory for control block } osTimerAttr_t; - -/// Attributes structure for event flags. -typedef struct { - const char *name; ///< name of the event flags - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block -} osEventFlagsAttr_t; - -/// Attributes structure for mutex. -typedef struct { - const char *name; ///< name of the mutex - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block -} osMutexAttr_t; - -/// Attributes structure for semaphore. -typedef struct { - const char *name; ///< name of the semaphore - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block -} osSemaphoreAttr_t; - -/// Attributes structure for memory pool. -typedef struct { - const char *name; ///< name of the memory pool - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block - void *mp_mem; ///< memory for data storage - uint32_t mp_size; ///< size of provided memory for data storage -} osMemoryPoolAttr_t; - + /// Attributes structure for message queue. typedef struct { const char *name; ///< name of the message queue @@ -298,196 +127,79 @@ typedef struct { void *cb_mem; ///< memory for control block uint32_t cb_size; ///< size of provided memory for control block void *mq_mem; ///< memory for data storage - uint32_t mq_size; ///< size of provided memory for data storage + uint32_t mq_size; ///< size of provided memory for data storage } osMessageQueueAttr_t; - - + + // ==== Kernel Management Functions ==== - + /// Initialize the RTOS Kernel. /// \return status code that indicates the execution status of the function. osStatus_t osKernelInitialize (void); - + /// Get RTOS Kernel Information. /// \param[out] version pointer to buffer for retrieving version information. /// \param[out] id_buf pointer to buffer for retrieving kernel identification string. /// \param[in] id_size size of buffer for kernel identification string. /// \return status code that indicates the execution status of the function. osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size); - + /// Get the current RTOS Kernel state. /// \return current RTOS Kernel state. osKernelState_t osKernelGetState (void); - + /// Start the RTOS Kernel scheduler. /// \return status code that indicates the execution status of the function. osStatus_t osKernelStart (void); - + /// Lock the RTOS Kernel scheduler. /// \return previous lock state (1 - locked, 0 - not locked, error code if negative). int32_t osKernelLock (void); - + /// Unlock the RTOS Kernel scheduler. /// \return previous lock state (1 - locked, 0 - not locked, error code if negative). int32_t osKernelUnlock (void); - + /// Restore the RTOS Kernel scheduler lock state. /// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock. /// \return new lock state (1 - locked, 0 - not locked, error code if negative). int32_t osKernelRestoreLock (int32_t lock); - + /// Suspend the RTOS Kernel scheduler. /// \return time in ticks, for how long the system can sleep or power-down. uint32_t osKernelSuspend (void); - + /// Resume the RTOS Kernel scheduler. /// \param[in] sleep_ticks time in ticks for how long the system was in sleep or power-down mode. void osKernelResume (uint32_t sleep_ticks); - + /// Get the RTOS kernel tick count. /// \return RTOS kernel current tick count. uint32_t osKernelGetTickCount (void); - + /// Get the RTOS kernel tick frequency. /// \return frequency of the kernel tick in hertz, i.e. kernel ticks per second. uint32_t osKernelGetTickFreq (void); - -/// Get the RTOS kernel system timer count. -/// \return RTOS kernel current system timer count as 32-bit value. -uint32_t osKernelGetSysTimerCount (void); - + /// Get the RTOS kernel system timer frequency. /// \return frequency of the system timer in hertz, i.e. timer ticks per second. uint32_t osKernelGetSysTimerFreq (void); - - -// ==== Thread Management Functions ==== - -/// Create a thread and add it to Active Threads. -/// \param[in] func thread function. -/// \param[in] argument pointer that is passed to the thread function as start argument. -/// \param[in] attr thread attributes; NULL: default values. -/// \return thread ID for reference by other functions or NULL in case of error. -osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); - -/// Get name of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return name as null-terminated string. -const char *osThreadGetName (osThreadId_t thread_id); - -/// Return the thread ID of the current running thread. -/// \return thread ID for reference by other functions or NULL in case of error. -osThreadId_t osThreadGetId (void); - -/// Get current thread state of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return current thread state of the specified thread. -osThreadState_t osThreadGetState (osThreadId_t thread_id); - -/// Get stack size of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return stack size in bytes. -uint32_t osThreadGetStackSize (osThreadId_t thread_id); - -/// Get available stack space of a thread based on stack watermark recording during execution. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return remaining stack space in bytes. -uint32_t osThreadGetStackSpace (osThreadId_t thread_id); - -/// Change priority of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \param[in] priority new priority value for the thread function. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadSetPriority (osThreadId_t thread_id, osPriority_t priority); - -/// Get current priority of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return current priority value of the specified thread. -osPriority_t osThreadGetPriority (osThreadId_t thread_id); - -/// Pass control to next thread that is in state \b READY. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadYield (void); - -/// Suspend execution of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadSuspend (osThreadId_t thread_id); - -/// Resume execution of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadResume (osThreadId_t thread_id); - -/// Detach a thread (thread storage can be reclaimed when thread terminates). -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadDetach (osThreadId_t thread_id); - -/// Wait for specified thread to terminate. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadJoin (osThreadId_t thread_id); - -/// Terminate execution of current running thread. -__NO_RETURN void osThreadExit (void); - -/// Terminate execution of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \return status code that indicates the execution status of the function. -osStatus_t osThreadTerminate (osThreadId_t thread_id); - -/// Get number of active threads. -/// \return number of active threads. -uint32_t osThreadGetCount (void); - -/// Enumerate active threads. -/// \param[out] thread_array pointer to array for retrieving thread IDs. -/// \param[in] array_items maximum number of items in array for retrieving thread IDs. -/// \return number of enumerated threads. -uint32_t osThreadEnumerate (osThreadId_t *thread_array, uint32_t array_items); - - -// ==== Thread Flags Functions ==== - -/// Set the specified Thread Flags of a thread. -/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. -/// \param[in] flags specifies the flags of the thread that shall be set. -/// \return thread flags after setting or error code if highest bit set. -uint32_t osThreadFlagsSet (osThreadId_t thread_id, uint32_t flags); - -/// Clear the specified Thread Flags of current running thread. -/// \param[in] flags specifies the flags of the thread that shall be cleared. -/// \return thread flags before clearing or error code if highest bit set. -uint32_t osThreadFlagsClear (uint32_t flags); - -/// Get the current Thread Flags of current running thread. -/// \return current thread flags. -uint32_t osThreadFlagsGet (void); - -/// Wait for one or more Thread Flags of the current running thread to become signaled. -/// \param[in] flags specifies the flags to wait for. -/// \param[in] options specifies flags options (osFlagsXxxx). -/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. -/// \return thread flags before clearing or error code if highest bit set. -uint32_t osThreadFlagsWait (uint32_t flags, uint32_t options, uint32_t timeout); - - + // ==== Generic Wait Functions ==== - + /// Wait for Timeout (Time Delay). /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value /// \return status code that indicates the execution status of the function. osStatus_t osDelay (uint32_t ticks); - + /// Wait until specified time. /// \param[in] ticks absolute time in ticks /// \return status code that indicates the execution status of the function. osStatus_t osDelayUntil (uint32_t ticks); - - + + // ==== Timer Management Functions ==== - + /// Create and Initialize a timer. /// \param[in] func function pointer to callback function. /// \param[in] type \ref osTimerOnce for one-shot or \ref osTimerPeriodic for periodic behavior. @@ -495,213 +207,47 @@ osStatus_t osDelayUntil (uint32_t ticks); /// \param[in] attr timer attributes; NULL: default values. /// \return timer ID for reference by other functions or NULL in case of error. osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr); - + /// Get name of a timer. /// \param[in] timer_id timer ID obtained by \ref osTimerNew. /// \return name as null-terminated string. const char *osTimerGetName (osTimerId_t timer_id); - + /// Start or restart a timer. /// \param[in] timer_id timer ID obtained by \ref osTimerNew. /// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer. /// \return status code that indicates the execution status of the function. osStatus_t osTimerStart (osTimerId_t timer_id, uint32_t ticks); - + /// Stop a timer. /// \param[in] timer_id timer ID obtained by \ref osTimerNew. /// \return status code that indicates the execution status of the function. osStatus_t osTimerStop (osTimerId_t timer_id); - + /// Check if a timer is running. /// \param[in] timer_id timer ID obtained by \ref osTimerNew. /// \return 0 not running, 1 running. uint32_t osTimerIsRunning (osTimerId_t timer_id); - + /// Delete a timer. /// \param[in] timer_id timer ID obtained by \ref osTimerNew. /// \return status code that indicates the execution status of the function. osStatus_t osTimerDelete (osTimerId_t timer_id); - - -// ==== Event Flags Management Functions ==== - -/// Create and Initialize an Event Flags object. -/// \param[in] attr event flags attributes; NULL: default values. -/// \return event flags ID for reference by other functions or NULL in case of error. -osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr); - -/// Get name of an Event Flags object. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \return name as null-terminated string. -const char *osEventFlagsGetName (osEventFlagsId_t ef_id); - -/// Set the specified Event Flags. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \param[in] flags specifies the flags that shall be set. -/// \return event flags after setting or error code if highest bit set. -uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags); - -/// Clear the specified Event Flags. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \param[in] flags specifies the flags that shall be cleared. -/// \return event flags before clearing or error code if highest bit set. -uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags); - -/// Get the current Event Flags. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \return current event flags. -uint32_t osEventFlagsGet (osEventFlagsId_t ef_id); - -/// Wait for one or more Event Flags to become signaled. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \param[in] flags specifies the flags to wait for. -/// \param[in] options specifies flags options (osFlagsXxxx). -/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. -/// \return event flags before clearing or error code if highest bit set. -uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout); - -/// Delete an Event Flags object. -/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id); - - -// ==== Mutex Management Functions ==== - -/// Create and Initialize a Mutex object. -/// \param[in] attr mutex attributes; NULL: default values. -/// \return mutex ID for reference by other functions or NULL in case of error. -osMutexId_t osMutexNew (const osMutexAttr_t *attr); - -/// Get name of a Mutex object. -/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. -/// \return name as null-terminated string. -const char *osMutexGetName (osMutexId_t mutex_id); - -/// Acquire a Mutex or timeout if it is locked. -/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. -/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. -/// \return status code that indicates the execution status of the function. -osStatus_t osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout); - -/// Release a Mutex that was acquired by \ref osMutexAcquire. -/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osMutexRelease (osMutexId_t mutex_id); - -/// Get Thread which owns a Mutex object. -/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. -/// \return thread ID of owner thread or NULL when mutex was not acquired. -osThreadId_t osMutexGetOwner (osMutexId_t mutex_id); - -/// Delete a Mutex object. -/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osMutexDelete (osMutexId_t mutex_id); - - -// ==== Semaphore Management Functions ==== - -/// Create and Initialize a Semaphore object. -/// \param[in] max_count maximum number of available tokens. -/// \param[in] initial_count initial number of available tokens. -/// \param[in] attr semaphore attributes; NULL: default values. -/// \return semaphore ID for reference by other functions or NULL in case of error. -osSemaphoreId_t osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr); - -/// Get name of a Semaphore object. -/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. -/// \return name as null-terminated string. -const char *osSemaphoreGetName (osSemaphoreId_t semaphore_id); - -/// Acquire a Semaphore token or timeout if no tokens are available. -/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. -/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. -/// \return status code that indicates the execution status of the function. -osStatus_t osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout); - -/// Release a Semaphore token up to the initial maximum count. -/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osSemaphoreRelease (osSemaphoreId_t semaphore_id); - -/// Get current Semaphore token count. -/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. -/// \return number of tokens available. -uint32_t osSemaphoreGetCount (osSemaphoreId_t semaphore_id); - -/// Delete a Semaphore object. -/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osSemaphoreDelete (osSemaphoreId_t semaphore_id); - - -// ==== Memory Pool Management Functions ==== - -/// Create and Initialize a Memory Pool object. -/// \param[in] block_count maximum number of memory blocks in memory pool. -/// \param[in] block_size memory block size in bytes. -/// \param[in] attr memory pool attributes; NULL: default values. -/// \return memory pool ID for reference by other functions or NULL in case of error. -osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr); - -/// Get name of a Memory Pool object. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return name as null-terminated string. -const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id); - -/// Allocate a memory block from a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. -/// \return address of the allocated memory block or NULL in case of no memory is available. -void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout); - -/// Return an allocated memory block back to a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \param[in] block address of the allocated memory block to be returned to the memory pool. -/// \return status code that indicates the execution status of the function. -osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block); - -/// Get maximum number of memory blocks in a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return maximum number of memory blocks. -uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id); - -/// Get memory block size in a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return memory block size in bytes. -uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id); - -/// Get number of memory blocks used in a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return number of memory blocks used. -uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id); - -/// Get number of memory blocks available in a Memory Pool. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return number of memory blocks available. -uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id); - -/// Delete a Memory Pool object. -/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. -/// \return status code that indicates the execution status of the function. -osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id); - - + // ==== Message Queue Management Functions ==== - + /// Create and Initialize a Message Queue object. /// \param[in] msg_count maximum number of messages in queue. /// \param[in] msg_size maximum message size in bytes. /// \param[in] attr message queue attributes; NULL: default values. /// \return message queue ID for reference by other functions or NULL in case of error. osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); - + /// Get name of a Message Queue object. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return name as null-terminated string. const char *osMessageQueueGetName (osMessageQueueId_t mq_id); - + /// Put a Message into a Queue or timeout if Queue is full. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \param[in] msg_ptr pointer to buffer with message to put into a queue. @@ -709,7 +255,7 @@ const char *osMessageQueueGetName (osMessageQueueId_t mq_id); /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. /// \return status code that indicates the execution status of the function. osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout); - + /// Get a Message from a Queue or timeout if Queue is empty. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \param[out] msg_ptr pointer to buffer for message to get from a queue. @@ -717,40 +263,40 @@ osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uin /// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. /// \return status code that indicates the execution status of the function. osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout); - + /// Get maximum number of messages in a Message Queue. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return maximum number of messages. uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id); - + /// Get maximum message size in a Message Queue. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return maximum message size in bytes. uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id); - + /// Get number of queued messages in a Message Queue. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return number of queued messages. uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id); - + /// Get number of available slots for messages in a Message Queue. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return number of available slots for messages. uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id); - + /// Reset a Message Queue to initial empty state. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return status code that indicates the execution status of the function. osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id); - + /// Delete a Message Queue object. /// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. /// \return status code that indicates the execution status of the function. osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id); - - + + #ifdef __cplusplus } #endif - + #endif // CMSIS_OS2_H_ diff --git a/lib/FreeRTOS-glue/freertos_mpool.h b/lib/FreeRTOS-glue/freertos_mpool.h deleted file mode 100644 index cea5017e..00000000 --- a/lib/FreeRTOS-glue/freertos_mpool.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -------------------------------------------------------------------------- - * Copyright (c) 2013-2020 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Name: freertos_mpool.h - * Purpose: CMSIS RTOS2 wrapper for FreeRTOS - * - *---------------------------------------------------------------------------*/ - -#ifndef FREERTOS_MPOOL_H_ -#define FREERTOS_MPOOL_H_ - -#include -#include "FreeRTOS.h" -#include "semphr.h" - -/* Memory Pool implementation definitions */ -#define MPOOL_STATUS 0x5EED0000U - -/* Memory Block header */ -typedef struct { - void *next; /* Pointer to next block */ -} MemPoolBlock_t; - -/* Memory Pool control block */ -typedef struct MemPoolDef_t { - MemPoolBlock_t *head; /* Pointer to head block */ - SemaphoreHandle_t sem; /* Pool semaphore handle */ - uint8_t *mem_arr; /* Pool memory array */ - uint32_t mem_sz; /* Pool memory array size */ - const char *name; /* Pointer to name string */ - uint32_t bl_sz; /* Size of a single block */ - uint32_t bl_cnt; /* Number of blocks */ - uint32_t n; /* Block allocation index */ - volatile uint32_t status; /* Object status flags */ -#if (configSUPPORT_STATIC_ALLOCATION == 1) - StaticSemaphore_t mem_sem; /* Semaphore object memory */ -#endif -} MemPool_t; - -/* No need to hide static object type, just align to coding style */ -#define StaticMemPool_t MemPool_t - -/* Define memory pool control block size */ -#define MEMPOOL_CB_SIZE (sizeof(StaticMemPool_t)) - -/* Define size of the byte array required to create count of blocks of given size */ -#define MEMPOOL_ARR_SIZE(bl_count, bl_size) (((((bl_size) + (4 - 1)) / 4) * 4)*(bl_count)) - -#endif /* FREERTOS_MPOOL_H_ */ diff --git a/lib/FreeRTOS-glue/freertos_os2.h b/lib/FreeRTOS-glue/freertos_os2.h index f67d2ae9..1e70b3fc 100644 --- a/lib/FreeRTOS-glue/freertos_os2.h +++ b/lib/FreeRTOS-glue/freertos_os2.h @@ -75,7 +75,7 @@ #endif /* - Option to exclude CMSIS-RTOS2 function osThreadEnumerate from the application image. + Option to exclude CMSIS-RTOS2 function furi_thread_enumerate from the application image. */ #ifndef configUSE_OS2_THREAD_ENUMERATE #define configUSE_OS2_THREAD_ENUMERATE 1 @@ -153,7 +153,7 @@ #if (INCLUDE_xTaskGetCurrentTaskHandle == 0) /* CMSIS-RTOS2 API uses FreeRTOS function xTaskGetCurrentTaskHandle to implement - functions osThreadGetId, osThreadFlagsClear and osThreadFlagsGet. In case if these + functions osThreadGetId, furi_thread_flags_clear and furi_thread_flags_get. In case if these functions are not used in the application image, compiler will optimize them away. Set #define INCLUDE_xTaskGetCurrentTaskHandle 1 to fix this error. */ @@ -170,8 +170,8 @@ #endif #if (INCLUDE_uxTaskGetStackHighWaterMark == 0) /* - CMSIS-RTOS2 function osThreadGetStackSpace uses FreeRTOS function uxTaskGetStackHighWaterMark. - In case if osThreadGetStackSpace is not used in the application image, compiler will + CMSIS-RTOS2 function furi_thread_get_stack_space uses FreeRTOS function uxTaskGetStackHighWaterMark. + In case if furi_thread_get_stack_space is not used in the application image, compiler will optimize it away. Set #define INCLUDE_uxTaskGetStackHighWaterMark 1 to fix this error. */ @@ -294,16 +294,16 @@ #if (configUSE_TRACE_FACILITY == 0) /* - CMSIS-RTOS2 function osThreadEnumerate requires FreeRTOS function uxTaskGetSystemState + CMSIS-RTOS2 function furi_thread_enumerate requires FreeRTOS function uxTaskGetSystemState which is only enabled if configUSE_TRACE_FACILITY == 1. Set #define configUSE_TRACE_FACILITY 1 to fix this error. - Alternatively, if the application does not use osThreadEnumerate it can be + Alternatively, if the application does not use furi_thread_enumerate it can be excluded from the image code by setting: #define configUSE_OS2_THREAD_ENUMERATE 0 (in FreeRTOSConfig.h) */ #if (configUSE_OS2_THREAD_ENUMERATE == 1) - #error "Definition configUSE_TRACE_FACILITY must equal 1 to implement osThreadEnumerate." + #error "Definition configUSE_TRACE_FACILITY must equal 1 to implement furi_thread_enumerate." #endif #endif @@ -316,21 +316,4 @@ #error "Definition configUSE_16_BIT_TICKS must be zero to implement CMSIS-RTOS2 API." #endif -#if (configMAX_PRIORITIES != 56) - /* - CMSIS-RTOS2 defines 56 different priorities (see osPriority_t) and portable CMSIS-RTOS2 - implementation should implement the same number of priorities. - Set #define configMAX_PRIORITIES 56 to fix this error. - */ - #error "Definition configMAX_PRIORITIES must equal 56 to implement Thread Management API." -#endif -#if (configUSE_PORT_OPTIMISED_TASK_SELECTION != 0) - /* - CMSIS-RTOS2 requires handling of 56 different priorities (see osPriority_t) while FreeRTOS port - optimised selection for Cortex core only handles 32 different priorities. - Set #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 to fix this error. - */ - #error "Definition configUSE_PORT_OPTIMISED_TASK_SELECTION must be zero to implement Thread Management API." -#endif - #endif /* FREERTOS_OS2_H_ */ diff --git a/lib/FreeRTOS-glue/os_tick.h b/lib/FreeRTOS-glue/os_tick.h deleted file mode 100644 index 3cfd8954..00000000 --- a/lib/FreeRTOS-glue/os_tick.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************//** - * @file os_tick.h - * @brief CMSIS OS Tick header file - * @version V1.0.2 - * @date 19. March 2021 - ******************************************************************************/ -/* - * Copyright (c) 2017-2021 ARM Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OS_TICK_H -#define OS_TICK_H - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/// IRQ Handler. -#ifndef IRQHANDLER_T -#define IRQHANDLER_T -typedef void (*IRQHandler_t) (void); -#endif - -/// Setup OS Tick timer to generate periodic RTOS Kernel Ticks -/// \param[in] freq tick frequency in Hz -/// \param[in] handler tick IRQ handler -/// \return 0 on success, -1 on error. -int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler); - -/// Enable OS Tick timer interrupt -void OS_Tick_Enable (void); - -/// Disable OS Tick timer interrupt -void OS_Tick_Disable (void); - -/// Acknowledge execution of OS Tick timer interrupt -void OS_Tick_AcknowledgeIRQ (void); - -/// Get OS Tick timer IRQ number -/// \return OS Tick IRQ number -int32_t OS_Tick_GetIRQn (void); - -/// Get OS Tick timer clock frequency -/// \return OS Tick timer clock frequency in Hz -uint32_t OS_Tick_GetClock (void); - -/// Get OS Tick timer interval reload value -/// \return OS Tick timer interval reload value -uint32_t OS_Tick_GetInterval (void); - -/// Get OS Tick timer counter value -/// \return OS Tick timer counter value -uint32_t OS_Tick_GetCount (void); - -/// Get OS Tick timer overflow status -/// \return OS Tick overflow status (1 - overflow, 0 - no overflow). -uint32_t OS_Tick_GetOverflow (void); - -#ifdef __cplusplus -} -#endif - -#endif /* OS_TICK_H */ diff --git a/lib/SConscript b/lib/SConscript new file mode 100644 index 00000000..ee8b8356 --- /dev/null +++ b/lib/SConscript @@ -0,0 +1,78 @@ +Import("env") + +env.Append( + LINT_SOURCES=[ + "lib/app-scened-template", + "lib/digital_signal", + "lib/drivers", + "lib/flipper_format", + "lib/infrared", + "lib/nfc_protocols", + "lib/one_wire", + "lib/ST25RFAL002", + "lib/subghz", + "lib/toolbox", + "lib/u8g2", + "lib/update_util", + ] +) + +env.Append( + CPPPATH=[ + "#/", + "#/lib", # TODO: remove! + "#/lib/mlib", + # Ugly hack + "${BUILD_DIR}/assets/compiled", + ], + CPPDEFINES=[ + '"M_MEMORY_FULL(x)=abort()"', + ], +) + + +# drivers +# fatfs +# flipper_format +# infrared +# littlefs +# subghz +# toolbox +# misc +# digital_signal +# fnv1a-hash +# micro-ecc +# microtar +# nfc_protocols +# one_wire +# qrcode +# u8g2 +# update_util +# heatshrink +# nanopb +# apps +# app-scened-template +# callback-connector +# app-template + + +libs = env.BuildModules( + [ + "STM32CubeWB", + "freertos", + "microtar", + "toolbox", + "ST25RFAL002", + "libusb_stm32", + "drivers", + "fatfs", + "flipper_format", + "infrared", + "littlefs", + "subghz", + "appframe", + "misc", + ], +) + +Return("libs") diff --git a/lib/ST25RFAL002/SConscript b/lib/ST25RFAL002/SConscript new file mode 100644 index 00000000..d86d2d00 --- /dev/null +++ b/lib/ST25RFAL002/SConscript @@ -0,0 +1,19 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/ST25RFAL002", + "#/lib/ST25RFAL002/include", + "#/lib/ST25RFAL002/source/st25r3916", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="st25rfal002") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/ST25RFAL002/platform.c b/lib/ST25RFAL002/platform.c index 52ac843e..c688bd59 100644 --- a/lib/ST25RFAL002/platform.c +++ b/lib/ST25RFAL002/platform.c @@ -3,49 +3,58 @@ #include #include -static const osThreadAttr_t platform_irq_thread_attr = { - .name = "RfalIrqDriver", - .stack_size = 1024, - .priority = osPriorityRealtime, -}; +typedef struct { + FuriThread* thread; + volatile PlatformIrqCallback callback; +} RfalPlatform; -static volatile osThreadId_t platform_irq_thread_id = NULL; -static volatile PlatformIrqCallback platform_irq_callback = NULL; -static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; +static volatile RfalPlatform rfal_platform = { + .thread = NULL, + .callback = NULL, +}; void nfc_isr(void* _ctx) { UNUSED(_ctx); - if(platform_irq_callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { - osThreadFlagsSet(platform_irq_thread_id, 0x1); + if(rfal_platform.callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { + furi_thread_flags_set(furi_thread_get_id(rfal_platform.thread), 0x1); } } -void platformIrqThread() { +int32_t rfal_platform_irq_thread(void* context) { + UNUSED(context); + while(1) { - uint32_t flags = osThreadFlagsWait(0x1, osFlagsWaitAny, osWaitForever); + uint32_t flags = furi_thread_flags_wait(0x1, osFlagsWaitAny, osWaitForever); if(flags & 0x1) { - platform_irq_callback(); + rfal_platform.callback(); } } } void platformEnableIrqCallback() { - furi_hal_gpio_init(&pin, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow); - furi_hal_gpio_enable_int_callback(&pin); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow); + furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull); } void platformDisableIrqCallback() { - furi_hal_gpio_init(&pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_disable_int_callback(&pin); + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull); } void platformSetIrqCallback(PlatformIrqCallback callback) { - platform_irq_callback = callback; - platform_irq_thread_id = osThreadNew(platformIrqThread, NULL, &platform_irq_thread_attr); - furi_hal_gpio_add_int_callback(&pin, nfc_isr, NULL); + rfal_platform.callback = callback; + rfal_platform.thread = furi_thread_alloc(); + + furi_thread_set_name(rfal_platform.thread, "RfalIrqDriver"); + furi_thread_set_callback(rfal_platform.thread, rfal_platform_irq_thread); + furi_thread_set_stack_size(rfal_platform.thread, 1024); + furi_thread_set_priority(rfal_platform.thread, FuriThreadPriorityIsr); + furi_thread_start(rfal_platform.thread); + + furi_hal_gpio_add_int_callback(&gpio_nfc_irq_rfid_pull, nfc_isr, NULL); // Disable interrupt callback as the pin is shared between 2 apps // It is enabled in rfalLowPowerModeStop() - furi_hal_gpio_disable_int_callback(&pin); + furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull); } bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len) { diff --git a/lib/STM32CubeWB.scons b/lib/STM32CubeWB.scons new file mode 100644 index 00000000..02618ae7 --- /dev/null +++ b/lib/STM32CubeWB.scons @@ -0,0 +1,66 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/STM32CubeWB/Drivers/CMSIS/Device/ST", + "#/lib/STM32CubeWB/Drivers/CMSIS/Device/ST/STM32WBxx/Include", + "#/lib/STM32CubeWB/Drivers/CMSIS/Include", + "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc", + "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/Legacy", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/ble", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/template", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl", + "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/utilities", + ], + CPPDEFINES=[ + "STM32WB", + "STM32WB55xx", + "USE_FULL_ASSERT", + "USE_FULL_LL_DRIVER", + ], +) + +if env["RAM_EXEC"]: + env.Append( + CPPDEFINES=[ + "VECT_TAB_SRAM", + ], + ) + + +libenv = env.Clone(FW_LIB_NAME="stm32cubewb") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive( + "*_ll_*.c", "STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Src/", exclude="*usb.c" +) +sources += Glob( + "STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci/*.c", + source=True, +) +sources += Glob( + "STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/*_tl*.c", + source=True, +) +sources += [ + "STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/tl_mbox.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/svc/Src/svc_ctl.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gap_aci.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gatt_aci.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hal_aci.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hci_le.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_l2cap_aci.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core/template/osal.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/utilities/dbg_trace.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/utilities/otp.c", + "STM32CubeWB/Middlewares/ST/STM32_WPAN/utilities/stm_list.c", +] + + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/appframe.scons b/lib/appframe.scons new file mode 100644 index 00000000..935986d6 --- /dev/null +++ b/lib/appframe.scons @@ -0,0 +1,26 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/app-scened-template", + "#/lib/callback-connector", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="appframe") +libenv.ApplyLibFlags() + +sources = [] + +recurse_dirs = [ + "app-scened-template", + "callback-connector", +] + +for recurse_dir in recurse_dirs: + sources += libenv.GlobRecursive("*.c*", recurse_dir) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript new file mode 100644 index 00000000..3b7ee240 --- /dev/null +++ b/lib/drivers/SConscript @@ -0,0 +1,17 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/drivers", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="hwdrivers") +libenv.ApplyLibFlags() + +sources = Glob("*.c", source=True) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/fatfs/SConscript b/lib/fatfs/SConscript new file mode 100644 index 00000000..c20e2936 --- /dev/null +++ b/lib/fatfs/SConscript @@ -0,0 +1,13 @@ +Import("env") + + +libenv = env.Clone(FW_LIB_NAME="fatfs") +libenv.ApplyLibFlags() + + +sources = ["option/unicode.c"] +sources += Glob("*.c", source=True) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/flipper_format/SConscript b/lib/flipper_format/SConscript new file mode 100644 index 00000000..e5d61a07 --- /dev/null +++ b/lib/flipper_format/SConscript @@ -0,0 +1,25 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/flipper_format", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="flipperformat") +libenv.ApplyLibFlags() + +if libenv["RAM_EXEC"]: + libenv.Append( + CPPDEFINES=[ + "FLIPPER_STREAM_LITE", + ], + ) + + +sources = libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/freertos.scons b/lib/freertos.scons new file mode 100644 index 00000000..992c4f87 --- /dev/null +++ b/lib/freertos.scons @@ -0,0 +1,28 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/drivers", + "#/lib/FreeRTOS-Kernel/include", + "#/lib/FreeRTOS-Kernel/portable/GCC/ARM_CM4F", + "#/lib/FreeRTOS-glue", + ], + CPPDEFINES=[ + "HAVE_FREERTOS", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="freertos") +libenv.ApplyLibFlags() + + +sources = libenv.Glob("FreeRTOS-Kernel/*.c", source=True) +sources += [ + "FreeRTOS-Kernel/portable/GCC/ARM_CM4F/port.c", + "FreeRTOS-glue/cmsis_os2.c", +] + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/infrared/SConscript b/lib/infrared/SConscript new file mode 100644 index 00000000..35db75f8 --- /dev/null +++ b/lib/infrared/SConscript @@ -0,0 +1,18 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/infrared/encoder_decoder", + "#/lib/infrared/worker", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="infrared") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*.c") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 71126c86..b24b7480 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -92,8 +92,8 @@ static void infrared_worker_furi_hal_message_sent_isr_callback(void* context); static void infrared_worker_rx_timeout_callback(void* context) { InfraredWorker* instance = context; - uint32_t flags_set = osThreadFlagsSet( - furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED); + uint32_t flags_set = furi_thread_flags_set( + furi_thread_get_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED); furi_check(flags_set & INFRARED_WORKER_RX_TIMEOUT_RECEIVED); } @@ -110,7 +110,7 @@ static void infrared_worker_rx_callback(void* context, bool level, uint32_t dura INFRARED_WORKER_OVERRUN; portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - uint32_t flags_set = osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), events); + uint32_t flags_set = furi_thread_flags_set(furi_thread_get_id(instance->thread), events); furi_check(flags_set & events); } @@ -152,8 +152,8 @@ static void instance->signal.timings[instance->signal.timings_cnt] = duration; ++instance->signal.timings_cnt; } else { - uint32_t flags_set = osThreadFlagsSet( - furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_OVERRUN); + uint32_t flags_set = furi_thread_flags_set( + furi_thread_get_id(instance->thread), INFRARED_WORKER_OVERRUN); furi_check(flags_set & INFRARED_WORKER_OVERRUN); instance->rx.overrun = true; } @@ -167,7 +167,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { TickType_t last_blink_time = 0; while(1) { - events = osThreadFlagsWait(INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever); + events = furi_thread_flags_wait(INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever); furi_check(events & INFRARED_WORKER_ALL_RX_EVENTS); /* at least one caught */ if(events & INFRARED_WORKER_RX_RECEIVED) { @@ -282,7 +282,7 @@ void infrared_worker_rx_stop(InfraredWorker* instance) { furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL); furi_hal_infrared_async_rx_stop(); - osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT); + furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT); furi_thread_join(instance->thread); BaseType_t xReturn = xStreamBufferReset(instance->stream); @@ -342,8 +342,8 @@ void infrared_worker_tx_start(InfraredWorker* instance) { static void infrared_worker_furi_hal_message_sent_isr_callback(void* context) { InfraredWorker* instance = context; - uint32_t flags_set = osThreadFlagsSet( - furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT); + uint32_t flags_set = furi_thread_flags_set( + furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT); furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT); } @@ -369,8 +369,8 @@ static FuriHalInfraredTxGetDataState state = FuriHalInfraredTxGetDataStateDone; } - uint32_t flags_set = osThreadFlagsSet( - furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER); + uint32_t flags_set = furi_thread_flags_set( + furi_thread_get_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER); furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER); return state; @@ -498,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { furi_hal_infrared_async_tx_wait_termination(); instance->state = InfraredWorkerStateStartTx; - events = osThreadFlagsGet(); + events = furi_thread_flags_get(); if(events & INFRARED_WORKER_EXIT) { exit = true; break; @@ -506,7 +506,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { break; case InfraredWorkerStateRunTx: - events = osThreadFlagsWait(INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever); + events = furi_thread_flags_wait(INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever); furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */ if(events & INFRARED_WORKER_EXIT) { @@ -558,7 +558,7 @@ void infrared_worker_tx_stop(InfraredWorker* instance) { furi_assert(instance); furi_assert(instance->state != InfraredWorkerStateRunRx); - osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT); + furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT); furi_thread_join(instance->thread); furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL); furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL); diff --git a/lib/lib.mk b/lib/lib.mk deleted file mode 100644 index 43f4a1a2..00000000 --- a/lib/lib.mk +++ /dev/null @@ -1,138 +0,0 @@ -LIB_DIR = $(PROJECT_ROOT)/lib - -# TODO: some places use lib/header.h includes, is it ok? -CFLAGS += -I$(LIB_DIR) - -# Mlib containers -CFLAGS += -I$(LIB_DIR)/mlib -D'M_MEMORY_FULL(x)=abort()' - -# U8G2 display library -U8G2_DIR = $(LIB_DIR)/u8g2 -CFLAGS += -I$(U8G2_DIR) -C_SOURCES += $(U8G2_DIR)/u8g2_glue.c -C_SOURCES += $(U8G2_DIR)/u8g2_intersection.c -C_SOURCES += $(U8G2_DIR)/u8g2_setup.c -C_SOURCES += $(U8G2_DIR)/u8g2_d_memory.c -C_SOURCES += $(U8G2_DIR)/u8x8_cad.c -C_SOURCES += $(U8G2_DIR)/u8x8_byte.c -C_SOURCES += $(U8G2_DIR)/u8x8_gpio.c -C_SOURCES += $(U8G2_DIR)/u8x8_display.c -C_SOURCES += $(U8G2_DIR)/u8x8_setup.c -C_SOURCES += $(U8G2_DIR)/u8g2_hvline.c -C_SOURCES += $(U8G2_DIR)/u8g2_line.c -C_SOURCES += $(U8G2_DIR)/u8g2_ll_hvline.c -C_SOURCES += $(U8G2_DIR)/u8g2_circle.c -C_SOURCES += $(U8G2_DIR)/u8g2_box.c -C_SOURCES += $(U8G2_DIR)/u8g2_buffer.c -C_SOURCES += $(U8G2_DIR)/u8g2_font.c -C_SOURCES += $(U8G2_DIR)/u8g2_fonts.c -C_SOURCES += $(U8G2_DIR)/u8x8_8x8.c -C_SOURCES += $(U8G2_DIR)/u8g2_bitmap.c - -FATFS_DIR = $(LIB_DIR)/fatfs -C_SOURCES += $(FATFS_DIR)/ff.c -C_SOURCES += $(FATFS_DIR)/ff_gen_drv.c -C_SOURCES += $(FATFS_DIR)/diskio.c -C_SOURCES += $(FATFS_DIR)/option/unicode.c - -# Little FS -LITTLEFS_DIR = $(LIB_DIR)/littlefs -CFLAGS += -I$(LITTLEFS_DIR) -DLFS_CONFIG=lfs_config.h -C_SOURCES += $(LITTLEFS_DIR)/lfs.c -C_SOURCES += $(LITTLEFS_DIR)/lfs_util.c - -ST25RFAL002_DIR = $(LIB_DIR)/ST25RFAL002 -CFLAGS += -I$(ST25RFAL002_DIR) -CFLAGS += -I$(ST25RFAL002_DIR)/include -CFLAGS += -I$(ST25RFAL002_DIR)/source/st25r3916 -C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/*.c) -C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/source/*.c) -C_SOURCES += $(wildcard $(ST25RFAL002_DIR)/source/st25r3916/*.c) - -CFLAGS += -I$(LIB_DIR)/nfc_protocols -C_SOURCES += $(wildcard $(LIB_DIR)/nfc_protocols/*.c) - -# callback connector (C to CPP) library -CFLAGS += -I$(LIB_DIR)/callback-connector - -# app template library -CFLAGS += -I$(LIB_DIR)/app-template - -# add C scene template -CFLAGS += -I$(LIB_DIR)/app_scene_template - -# fnv1a hash library -CFLAGS += -I$(LIB_DIR)/fnv1a-hash -C_SOURCES += $(LIB_DIR)/fnv1a-hash/fnv1a-hash.c - -# common apps api -CFLAGS += -I$(LIB_DIR)/common-api - -# drivers -CFLAGS += -I$(LIB_DIR)/drivers -C_SOURCES += $(wildcard $(LIB_DIR)/drivers/*.c) - -# IR lib -CFLAGS += -I$(LIB_DIR)/infrared/encoder_decoder -CFLAGS += -I$(LIB_DIR)/infrared/worker -C_SOURCES += $(wildcard $(LIB_DIR)/infrared/encoder_decoder/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/infrared/encoder_decoder/*/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/infrared/worker/*.c) - -# SubGhz -C_SOURCES += $(wildcard $(LIB_DIR)/subghz/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/subghz/*/*.c) - -#scened app template lib -CFLAGS += -I$(LIB_DIR)/app-scened-template -C_SOURCES += $(wildcard $(LIB_DIR)/app-scened-template/*.c) -CPP_SOURCES += $(wildcard $(LIB_DIR)/app-scened-template/*.cpp) -CPP_SOURCES += $(wildcard $(LIB_DIR)/app-scened-template/*/*.cpp) - -# Toolbox -C_SOURCES += $(wildcard $(LIB_DIR)/toolbox/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/toolbox/*/*.c) -CPP_SOURCES += $(wildcard $(LIB_DIR)/toolbox/*.cpp) -CPP_SOURCES += $(wildcard $(LIB_DIR)/toolbox/*/*.cpp) - -# Digital signal -CFLAGS += -I$(LIB_DIR)/digital_signal -C_SOURCES += $(wildcard $(LIB_DIR)/digital_signal/*.c) - - -# USB Stack -CFLAGS += -I$(LIB_DIR)/libusb_stm32/inc -C_SOURCES += $(LIB_DIR)/libusb_stm32/src/usbd_stm32wb55_devfs.c -C_SOURCES += $(LIB_DIR)/libusb_stm32/src/usbd_core.c - -# protobuf -CFLAGS += -I$(LIB_DIR)/nanopb -C_SOURCES += $(wildcard $(LIB_DIR)/nanopb/*.c) - -# heatshrink -CFLAGS += -I$(LIB_DIR)/heatshrink -C_SOURCES += $(wildcard $(LIB_DIR)/heatshrink/*.c) - -# Toolbox -CFLAGS += -I$(LIB_DIR)/flipper_file -C_SOURCES += $(wildcard $(LIB_DIR)/flipper_file/*.c) - -# Flipper format -CFLAGS += -I$(LIB_DIR)/flipper_format -C_SOURCES += $(wildcard $(LIB_DIR)/flipper_format/*.c) - -# Micro-ECC -CFLAGS += -I$(LIB_DIR)/micro-ecc -C_SOURCES += $(wildcard $(LIB_DIR)/micro-ecc/*.c) - -# iButton and OneWire -C_SOURCES += $(wildcard $(LIB_DIR)/one_wire/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/one_wire/*/*.c) -C_SOURCES += $(wildcard $(LIB_DIR)/one_wire/*/*/*.c) - -# microtar -CFLAGS += -I$(LIB_DIR)/microtar/src -C_SOURCES += $(wildcard $(LIB_DIR)/microtar/src/*.c) - -# Update-related common code -C_SOURCES += $(wildcard $(LIB_DIR)/update_util/*.c) diff --git a/lib/libusb_stm32.scons b/lib/libusb_stm32.scons new file mode 100644 index 00000000..cb867fdb --- /dev/null +++ b/lib/libusb_stm32.scons @@ -0,0 +1,24 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/libusb_stm32/inc", + ], + CPPDEFINES=[ + ("USB_PMASIZE", "0x400"), + ], +) + + +libenv = env.Clone(FW_LIB_NAME="usb_stm32") +libenv.ApplyLibFlags() + + +sources = [ + "libusb_stm32/src/usbd_core.c", + "libusb_stm32/src/usbd_stm32wb55_devfs.c", +] + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/littlefs.scons b/lib/littlefs.scons new file mode 100644 index 00000000..792142c3 --- /dev/null +++ b/lib/littlefs.scons @@ -0,0 +1,20 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/littlefs", + ], + CPPDEFINES=[ + ("LFS_CONFIG", "lfs_config.h"), + ], +) + + +libenv = env.Clone(FW_LIB_NAME="littlefs") +libenv.ApplyLibFlags() + +sources = Glob("littlefs/*.c", source=True) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/microtar.scons b/lib/microtar.scons new file mode 100644 index 00000000..6ee36d40 --- /dev/null +++ b/lib/microtar.scons @@ -0,0 +1,21 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/microtar/src", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="microtar") +libenv.ApplyLibFlags() + +libenv.Append( + CPPDEFINES=["MICROTAR_DISABLE_API_CHECKS"], +) + +sources = libenv.GlobRecursive("*.c", "microtar/src") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/misc.scons b/lib/misc.scons new file mode 100644 index 00000000..91a11ff6 --- /dev/null +++ b/lib/misc.scons @@ -0,0 +1,46 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/digital_signal", + "#/lib/fnv1a_hash", + "#/lib/heatshrink", + "#/lib/micro-ecc", + "#/lib/nanopb", + "#/lib/nfc_protocols", + "#/lib/u8g2", + ], + CPPDEFINES=[ + "PB_ENABLE_MALLOC", + ], +) + + +libenv = env.Clone(FW_LIB_NAME="misc") +libenv.ApplyLibFlags() + +sources = [] + +libs_recurse = [ + "digital_signal", + "micro-ecc", + "nfc_protocols", + "one_wire", + "u8g2", + "update_util", +] + +for lib in libs_recurse: + sources += libenv.GlobRecursive("*.c*", lib) + +libs_plain = [ + "heatshrink", + "nanopb", +] + +for lib in libs_plain: + sources += Glob(lib + "/*.c*", source=True) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/nanopb b/lib/nanopb index c9124132..afc499f9 160000 --- a/lib/nanopb +++ b/lib/nanopb @@ -1 +1 @@ -Subproject commit c9124132a604047d0ef97a09c0e99cd9bed2c818 +Subproject commit afc499f9a410fc9bbf6c9c48cdd8d8b199d49eb4 diff --git a/lib/nfc_protocols/mifare_ultralight.c b/lib/nfc_protocols/mifare_ultralight.c index fb425ea7..21dbd9c4 100644 --- a/lib/nfc_protocols/mifare_ultralight.c +++ b/lib/nfc_protocols/mifare_ultralight.c @@ -12,13 +12,38 @@ bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { return false; } +static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) { + switch(type) { + case MfUltralightTypeUL11: + case MfUltralightTypeUL21: + return MfUltralightSupportFastRead | MfUltralightSupportCompatWrite | + MfUltralightSupportReadCounter | MfUltralightSupportIncrCounter | + MfUltralightSupportAuth | MfUltralightSupportSignature | + MfUltralightSupportTearingFlags | MfUltralightSupportVcsl; + case MfUltralightTypeNTAG213: + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + return MfUltralightSupportFastRead | MfUltralightSupportCompatWrite | + MfUltralightSupportReadCounter | MfUltralightSupportAuth | + MfUltralightSupportSignature | MfUltralightSupportSingleCounter | + MfUltralightSupportAsciiMirror; + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2C2K: + return MfUltralightSupportFastRead | MfUltralightSupportSectorSelect; + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + return MfUltralightSupportFastRead | MfUltralightSupportAuth | + MfUltralightSupportFastWrite | MfUltralightSupportSignature | + MfUltralightSupportSectorSelect; + default: + // Assumed original MFUL 512-bit + return MfUltralightSupportNone; + } +} + static void mf_ul_set_default_version(MfUltralightReader* reader, MfUltralightData* data) { data->type = MfUltralightTypeUnknown; reader->pages_to_read = 16; - reader->support_fast_read = false; - reader->support_tearing_flags = false; - reader->support_counters = false; - reader->support_signature = false; } bool mf_ultralight_read_version( @@ -44,31 +69,15 @@ bool mf_ultralight_read_version( if(version->storage_size == 0x0B || version->storage_size == 0x00) { data->type = MfUltralightTypeUL11; reader->pages_to_read = 20; - reader->support_fast_read = true; - reader->support_tearing_flags = true; - reader->support_counters = true; - reader->support_signature = true; } else if(version->storage_size == 0x0E) { data->type = MfUltralightTypeUL21; reader->pages_to_read = 41; - reader->support_fast_read = true; - reader->support_tearing_flags = true; - reader->support_counters = true; - reader->support_signature = true; } else if(version->storage_size == 0x0F) { data->type = MfUltralightTypeNTAG213; reader->pages_to_read = 45; - reader->support_fast_read = true; - reader->support_tearing_flags = false; - reader->support_counters = false; - reader->support_signature = true; } else if(version->storage_size == 0x11) { data->type = MfUltralightTypeNTAG215; reader->pages_to_read = 135; - reader->support_fast_read = true; - reader->support_tearing_flags = false; - reader->support_counters = false; - reader->support_signature = true; } else if(version->prod_subtype == 5 && version->prod_ver_major == 2) { // NTAG I2C bool known = false; @@ -76,42 +85,30 @@ bool mf_ultralight_read_version( if(version->storage_size == 0x13) { data->type = MfUltralightTypeNTAGI2C1K; reader->pages_to_read = 231; - reader->support_signature = false; known = true; } else if(version->storage_size == 0x15) { data->type = MfUltralightTypeNTAGI2C2K; reader->pages_to_read = 485; - reader->support_signature = false; known = true; } } else if(version->prod_ver_minor == 2) { if(version->storage_size == 0x13) { data->type = MfUltralightTypeNTAGI2CPlus1K; reader->pages_to_read = 236; - reader->support_signature = true; known = true; } else if(version->storage_size == 0x15) { data->type = MfUltralightTypeNTAGI2CPlus2K; reader->pages_to_read = 492; - reader->support_signature = true; known = true; } } - if(known) { - reader->support_fast_read = true; - reader->support_tearing_flags = false; - reader->support_counters = false; - } else { + if(!known) { mf_ul_set_default_version(reader, data); } } else if(version->storage_size == 0x13) { data->type = MfUltralightTypeNTAG216; reader->pages_to_read = 231; - reader->support_fast_read = true; - reader->support_tearing_flags = false; - reader->support_counters = false; - reader->support_signature = true; } else { mf_ul_set_default_version(reader, data); break; @@ -119,9 +116,14 @@ bool mf_ultralight_read_version( version_read = true; } while(false); + reader->supported_features = mf_ul_get_features(data->type); return version_read; } +static int16_t mf_ultralight_page_addr_to_tag_addr(uint8_t sector, uint8_t page) { + return sector * 256 + page; +} + static int16_t mf_ultralight_ntag_i2c_addr_lin_to_tag_1k( int16_t linear_address, uint8_t* sector, @@ -404,6 +406,41 @@ static int16_t mf_ultralight_ntag_i2c_addr_tag_to_lin( } } +static MfUltralightConfigPages* mf_ultralight_get_config_pages(MfUltralightData* data) { + if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) { + return (MfUltralightConfigPages*)&data->data[data->data_size - 4 * 4]; + } else if( + data->type >= MfUltralightTypeNTAGI2CPlus1K && + data->type <= MfUltralightTypeNTAGI2CPlus2K) { + return (MfUltralightConfigPages*)&data->data[0xe3 * 4]; + } else { + return NULL; + } +} + +static uint16_t mf_ultralight_calc_auth_count(MfUltralightData* data) { + if(mf_ul_get_features(data->type) & MfUltralightSupportAuth) { + MfUltralightConfigPages* config = mf_ultralight_get_config_pages(data); + uint16_t scaled_authlim = config->access.authlim; + // NTAG I2C Plus uses 2^AUTHLIM attempts rather than the direct number + if(scaled_authlim > 0 && data->type >= MfUltralightTypeNTAGI2CPlus1K && + data->type <= MfUltralightTypeNTAGI2CPlus2K) { + scaled_authlim = 1 << scaled_authlim; + } + return scaled_authlim; + } + + return 0; +} + +// NTAG21x will NAK if NFC_CNT_EN unset, so preempt +static bool mf_ultralight_should_read_counters(MfUltralightData* data) { + if(data->type < MfUltralightTypeNTAG213 || data->type > MfUltralightTypeNTAG216) return true; + + MfUltralightConfigPages* config = mf_ultralight_get_config_pages(data); + return config->access.nfc_cnt_en; +} + static bool mf_ultralight_sector_select(FuriHalNfcTxRxContext* tx_rx, uint8_t sector) { FURI_LOG_D(TAG, "Selecting sector %u", sector); tx_rx->tx_data[0] = MF_UL_SECTOR_SELECT; @@ -455,7 +492,7 @@ bool mf_ultralight_read_pages( tx_rx->tx_data[1] = tag_page; tx_rx->tx_bits = 16; tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; - if(!furi_hal_nfc_tx_rx(tx_rx, 50)) { + if(!furi_hal_nfc_tx_rx(tx_rx, 50) || tx_rx->rx_bits < 16 * 8) { FURI_LOG_D( TAG, "Failed to read pages %d - %d", @@ -540,9 +577,11 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* uint8_t counter_read = 0; FURI_LOG_D(TAG, "Reading counters"); - for(size_t i = 0; i < 3; i++) { + bool is_single_counter = (mf_ul_get_features(data->type) & MfUltralightSupportSingleCounter) != + 0; + for(size_t i = is_single_counter ? 2 : 0; i < 3; i++) { tx_rx->tx_data[0] = MF_UL_READ_CNT; - tx_rx->rx_data[1] = i; + tx_rx->tx_data[1] = i; tx_rx->tx_bits = 16; tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; if(!furi_hal_nfc_tx_rx(tx_rx, 50)) { @@ -554,7 +593,7 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* counter_read++; } - return counter_read == 2; + return counter_read == (is_single_counter ? 1 : 3); } bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { @@ -589,38 +628,26 @@ bool mf_ul_read_card( // Read Mifare Ultralight version if(mf_ultralight_read_version(tx_rx, reader, data)) { - if(reader->support_signature) { + if(reader->supported_features & MfUltralightSupportSignature) { // Read Signature mf_ultralight_read_signature(tx_rx, data); } } - if(reader->support_counters) { - mf_ultralight_read_counters(tx_rx, data); - } - if(reader->support_tearing_flags) { - mf_ultralight_read_tearing_flags(tx_rx, data); - } + card_read = mf_ultralight_read_pages(tx_rx, reader, data); - return card_read; -} - -// TODO rework -static void mf_ul_protect_auth_data_on_read_command( - uint8_t* tx_buff, - uint8_t start_page, - uint8_t end_page, - MfUltralightEmulator* emulator) { - if(emulator->data.type >= MfUltralightTypeNTAG213) { - uint8_t pwd_page = (emulator->data.data_size / 4) - 2; - uint8_t pack_page = pwd_page + 1; - if((start_page <= pwd_page) && (end_page >= pwd_page)) { - memset(&tx_buff[(pwd_page - start_page) * 4], 0, 4); + if(card_read) { + if(reader->supported_features & MfUltralightSupportReadCounter && + mf_ultralight_should_read_counters(data)) { + mf_ultralight_read_counters(tx_rx, data); } - if((start_page <= pack_page) && (end_page >= pack_page)) { - memset(&tx_buff[(pack_page - start_page) * 4], 0, 2); + if(reader->supported_features & MfUltralightSupportTearingFlags) { + mf_ultralight_read_tearing_flags(tx_rx, data); } + data->curr_authlim = 0; } + + return card_read; } static void mf_ul_protect_auth_data_on_read_command_i2c( @@ -639,9 +666,8 @@ static void mf_ul_protect_auth_data_on_read_command_i2c( // Handle AUTH0 for sector 0 if(!emulator->auth_success) { - uint8_t access = emulator->data.data[228 * 4]; - if(access & 0x80) { - uint8_t auth0 = emulator->data.data[227 * 4 + 3]; + if(emulator->config_cache.access.prot) { + uint8_t auth0 = emulator->config_cache.auth0; if(auth0 < end_page) { // start_page is always < auth0; otherwise is NAK'd already uint8_t page_offset = auth0 - start_page; @@ -704,16 +730,29 @@ static void mf_ul_ntag_i2c_fill_cross_area_read( } } +static bool mf_ul_check_auth(MfUltralightEmulator* emulator, uint8_t start_page, bool is_write) { + if(!emulator->auth_success) { + if(start_page >= emulator->config_cache.auth0 && + (emulator->config_cache.access.prot || is_write)) + return false; + } + + if(is_write && emulator->config_cache.access.cfglck) { + uint16_t config_start_page = emulator->page_num - 4; + if(start_page == config_start_page || start_page == config_start_page + 1) return false; + } + + return true; +} + static bool mf_ul_ntag_i2c_plus_check_auth( MfUltralightEmulator* emulator, uint8_t start_page, bool is_write) { if(!emulator->auth_success) { - uint8_t access = emulator->data.data[228 * 4]; // Check NFC_PROT - if(emulator->curr_sector == 0 && ((access & 0x80) || is_write)) { - uint8_t auth0 = emulator->data.data[227 * 4 + 3]; - if(start_page >= auth0) return false; + if(emulator->curr_sector == 0 && (emulator->config_cache.access.prot || is_write)) { + if(start_page >= emulator->config_cache.auth0) return false; } else if(emulator->curr_sector == 1) { // We don't have to specifically check for type because this is done // by address translator @@ -725,43 +764,288 @@ static bool mf_ul_ntag_i2c_plus_check_auth( if(emulator->curr_sector == 1) { // Check NFC_DIS_SEC1 - uint8_t access = emulator->data.data[228 * 4]; - if(access & 0x20) return false; + if(emulator->config_cache.access.nfc_dis_sec1) return false; } return true; } +static int16_t mf_ul_get_dynamic_lock_page_addr(MfUltralightData* data) { + switch(data->type) { + case MfUltralightTypeUL21: + case MfUltralightTypeNTAG213: + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + return data->data_size / 4 - 5; + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + return 0xe2; + case MfUltralightTypeNTAGI2C2K: + return 0x1e0; + default: + return -1; // No dynamic lock bytes + } +} + +// Returns true if page not locked +// write_page is tag address +static bool mf_ul_check_lock(MfUltralightEmulator* emulator, int16_t write_page) { + if(write_page < 2) return false; // Page 0-1 is always locked + if(write_page == 2) return true; // Page 2 does not have a lock flag + + // Check static lock bytes + if(write_page <= 15) { + uint16_t static_lock_bytes = emulator->data.data[10] | (emulator->data.data[11] << 8); + return (static_lock_bytes & (1 << write_page)) == 0; + } + + // Check dynamic lock bytes + + // Check max page + switch(emulator->data.type) { + case MfUltralightTypeUL21: + case MfUltralightTypeNTAG213: + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + if(write_page >= emulator->page_num - 5) return true; + break; + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2CPlus1K: + if(write_page > 225) return true; + break; + case MfUltralightTypeNTAGI2C2K: + if(write_page > 479) return true; + break; + case MfUltralightTypeNTAGI2CPlus2K: + if(write_page >= 226 && write_page <= 255) return true; + if(write_page >= 512) return true; + break; + default: + furi_assert(false); + return true; + } + + int16_t dynamic_lock_index = mf_ul_get_dynamic_lock_page_addr(&emulator->data); + if(dynamic_lock_index == -1) return true; + // Run address through converter because NTAG I2C 2K is special + uint16_t valid_pages; // unused + dynamic_lock_index = + mf_ultralight_ntag_i2c_addr_tag_to_lin( + &emulator->data, dynamic_lock_index & 0xff, dynamic_lock_index >> 8, &valid_pages) * + 4; + + uint16_t dynamic_lock_bytes = emulator->data.data[dynamic_lock_index] | + (emulator->data.data[dynamic_lock_index + 1] << 8); + uint8_t shift; + + switch(emulator->data.type) { + // low byte LSB range, MSB range + case MfUltralightTypeUL21: + case MfUltralightTypeNTAG213: + // 16-17, 30-31 + shift = (write_page - 16) / 2; + break; + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2CPlus1K: + // 16-31, 128-129 + // 16-31, 128-143 + shift = (write_page - 16) / 16; + break; + case MfUltralightTypeNTAGI2C2K: + // 16-47, 240-271 + shift = (write_page - 16) / 32; + break; + case MfUltralightTypeNTAGI2CPlus2K: + // 16-47, 256-271 + if(write_page >= 208 && write_page <= 225) + shift = 6; + else if(write_page >= 256 && write_page <= 271) + shift = 7; + else + shift = (write_page - 16) / 32; + break; + default: + furi_assert(false); + shift = 0; + break; + } + + return (dynamic_lock_bytes & (1 << shift)) == 0; +} + +static void mf_ul_make_ascii_mirror(MfUltralightEmulator* emulator, string_t str) { + // Locals to improve readability + uint8_t mirror_page = emulator->config->mirror_page; + uint8_t mirror_byte = emulator->config->mirror.mirror_byte; + MfUltralightMirrorConf mirror_conf = emulator->config_cache.mirror.mirror_conf; + uint16_t last_user_page_index = emulator->page_num - 6; + bool uid_printed = false; + + if(mirror_conf == MfUltralightMirrorUid || mirror_conf == MfUltralightMirrorUidCounter) { + // UID range check + if(mirror_page < 4 || mirror_page > last_user_page_index - 3 || + (mirror_page == last_user_page_index - 3 && mirror_byte > 2)) { + if(mirror_conf == MfUltralightMirrorUid) return; + // NTAG21x has the peculiar behavior when UID+counter selected, if UID does not fit but + // counter will fit, it will actually mirror the counter + string_cat_str(str, " "); + } else { + for(int i = 0; i < 3; ++i) { + string_cat_printf(str, "%02X", emulator->data.data[i]); + } + // Skip BCC0 + for(int i = 4; i < 8; ++i) { + string_cat_printf(str, "%02X", emulator->data.data[i]); + } + uid_printed = true; + } + + uint16_t next_byte_offset = mirror_page * 4 + mirror_byte + 14; + if(mirror_conf == MfUltralightMirrorUidCounter) ++next_byte_offset; + mirror_page = next_byte_offset / 4; + mirror_byte = next_byte_offset % 4; + } + + if(mirror_conf == MfUltralightMirrorCounter || mirror_conf == MfUltralightMirrorUidCounter) { + // Counter is only printed if counter enabled + if(emulator->config_cache.access.nfc_cnt_en) { + // Counter protection check + if(emulator->config_cache.access.nfc_cnt_pwd_prot && !emulator->auth_success) return; + // Counter range check + if(mirror_page < 4) return; + if(mirror_page > last_user_page_index - 1) return; + if(mirror_page == last_user_page_index - 1 && mirror_byte > 2) return; + + if(mirror_conf == MfUltralightMirrorUidCounter) + string_cat_str(str, uid_printed ? "x" : " "); + + string_cat_printf(str, "%06X", emulator->data.counter[2]); + } + } +} + +static void mf_ul_increment_single_counter(MfUltralightEmulator* emulator) { + if(!emulator->read_counter_incremented && emulator->config_cache.access.nfc_cnt_en) { + if(emulator->data.counter[2] < 0xFFFFFF) { + ++emulator->data.counter[2]; + emulator->data_changed = true; + } + emulator->read_counter_incremented = true; + } +} + +static void mf_ul_emulate_write( + MfUltralightEmulator* emulator, + int16_t tag_addr, + int16_t write_page, + uint8_t* page_buff) { + // Assumption: all access checks have been completed + + if(tag_addr == 2) { + // Handle static locks + uint16_t orig_static_locks = emulator->data.data[write_page * 4 + 2] | + (emulator->data.data[write_page * 4 + 3] << 8); + uint16_t new_static_locks = page_buff[2] | (page_buff[3] << 8); + if(orig_static_locks & 1) new_static_locks &= ~0x08; + if(orig_static_locks & 2) new_static_locks &= ~0xF0; + if(orig_static_locks & 4) new_static_locks &= 0xFF; + new_static_locks |= orig_static_locks; + page_buff[0] = emulator->data.data[write_page * 4]; + page_buff[1] = emulator->data.data[write_page * 4 + 1]; + page_buff[2] = new_static_locks & 0xff; + page_buff[3] = new_static_locks >> 8; + } else if(tag_addr == 3) { + // Handle OTP/capability container + *(uint32_t*)page_buff |= *(uint32_t*)&emulator->data.data[write_page * 4]; + } else if(tag_addr == mf_ul_get_dynamic_lock_page_addr(&emulator->data)) { + // Handle dynamic locks + uint16_t orig_locks = emulator->data.data[write_page * 4] | + (emulator->data.data[write_page * 4 + 1] << 8); + uint8_t orig_block_locks = emulator->data.data[write_page * 4 + 2]; + uint16_t new_locks = page_buff[0] | (page_buff[1] << 8); + uint8_t new_block_locks = page_buff[2]; + + int block_lock_count; + switch(emulator->data.type) { + case MfUltralightTypeUL21: + block_lock_count = 5; + break; + case MfUltralightTypeNTAG213: + block_lock_count = 6; + break; + case MfUltralightTypeNTAG215: + block_lock_count = 4; + break; + case MfUltralightTypeNTAG216: + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2CPlus1K: + block_lock_count = 7; + break; + case MfUltralightTypeNTAGI2C2K: + case MfUltralightTypeNTAGI2CPlus2K: + block_lock_count = 8; + break; + default: + furi_assert(false); + block_lock_count = 0; + break; + } + + for(int i = 0; i < block_lock_count; ++i) { + if(orig_block_locks & (1 << i)) new_locks &= ~(3 << (2 * i)); + } + + new_locks |= orig_locks; + new_block_locks |= orig_block_locks; + + page_buff[0] = new_locks & 0xff; + page_buff[1] = new_locks >> 8; + page_buff[2] = new_block_locks; + if(emulator->data.type >= MfUltralightTypeUL21 && + emulator->data.type <= MfUltralightTypeNTAG216) + page_buff[3] = MF_UL_TEARING_FLAG_DEFAULT; + else + page_buff[3] = 0; + } + + memcpy(&emulator->data.data[write_page * 4], page_buff, 4); + emulator->data_changed = true; +} + +void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle) { + emulator->curr_sector = 0; + emulator->ntag_i2c_plus_sector3_lockout = false; + emulator->auth_success = false; + if(is_power_cycle) { + if(emulator->config != NULL) emulator->config_cache = *emulator->config; + + if(emulator->supported_features & MfUltralightSupportSingleCounter) { + emulator->read_counter_incremented = false; + } + } else { + if(emulator->config != NULL) { + // ACCESS (less CFGLCK) and AUTH0 are updated when reactivated + // MIRROR_CONF is not; don't know about STRG_MOD_EN, but we're not using that anyway + emulator->config_cache.access.value = (emulator->config->access.value & 0xBF) | + (emulator->config_cache.access.value & 0x40); + emulator->config_cache.auth0 = emulator->config->auth0; + } + } +} + void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data) { FURI_LOG_D(TAG, "Prepare emulation"); emulator->data = *data; - emulator->auth_data = NULL; + emulator->supported_features = mf_ul_get_features(data->type); + emulator->config = mf_ultralight_get_config_pages(&emulator->data); + emulator->page_num = emulator->data.data_size / 4; emulator->data_changed = false; emulator->comp_write_cmd_started = false; emulator->sector_select_cmd_started = false; - emulator->ntag_i2c_plus_sector3_lockout = false; - if(data->type == MfUltralightTypeUnknown) { - emulator->support_fast_read = false; - } else if(data->type == MfUltralightTypeUL11) { - emulator->support_fast_read = true; - } else if(data->type == MfUltralightTypeUL21) { - emulator->support_fast_read = true; - } else if(data->type == MfUltralightTypeNTAG213) { - emulator->support_fast_read = true; - } else if(data->type == MfUltralightTypeNTAG215) { - emulator->support_fast_read = true; - } else if(data->type == MfUltralightTypeNTAG216) { - emulator->support_fast_read = true; - } else if(data->type >= MfUltralightTypeNTAGI2C1K) { - emulator->support_fast_read = true; - } - - if(data->type >= MfUltralightTypeNTAG213 && data->type < MfUltralightTypeNTAGI2C1K) { - uint16_t pwd_page = (data->data_size / 4) - 2; - emulator->auth_data = (MfUltralightAuth*)&data->data[pwd_page * 4]; - } else if(data->type >= MfUltralightTypeNTAGI2CPlus1K) { - emulator->auth_data = (MfUltralightAuth*)&data->data[229 * 4]; - } + mf_ul_reset_emulation(emulator, true); } bool mf_ul_prepare_emulation_response( @@ -773,13 +1057,12 @@ bool mf_ul_prepare_emulation_response( void* context) { furi_assert(context); MfUltralightEmulator* emulator = context; - uint8_t cmd = buff_rx[0]; - uint16_t page_num = emulator->data.data_size / 4; uint16_t tx_bytes = 0; uint16_t tx_bits = 0; bool command_parsed = false; bool send_ack = false; bool respond_nothing = false; + bool reset_idle = false; #ifdef FURI_DEBUG string_t debug_buf; @@ -795,118 +1078,138 @@ bool mf_ul_prepare_emulation_response( // Check composite commands if(emulator->comp_write_cmd_started) { // Compatibility write is the only one composit command - if(buff_rx_len == 16) { - memcpy(&emulator->data.data[emulator->comp_write_page_addr * 4], buff_rx, 4); - emulator->data_changed = true; - // Send ACK message - buff_tx[0] = 0x0A; - tx_bits = 4; - *data_type = FURI_HAL_NFC_TXRX_RAW; + if(buff_rx_len == 16 * 8) { + mf_ul_emulate_write( + emulator, emulator->comp_write_page_addr, emulator->comp_write_page_addr, buff_rx); + send_ack = true; command_parsed = true; } emulator->comp_write_cmd_started = false; } else if(emulator->sector_select_cmd_started) { - if(buff_rx[0] <= 0xFE) { - emulator->curr_sector = buff_rx[0] > 3 ? 0 : buff_rx[0]; - emulator->ntag_i2c_plus_sector3_lockout = false; - command_parsed = true; - respond_nothing = true; - FURI_LOG_D(TAG, "Changing sector to %d", emulator->curr_sector); + if(buff_rx_len == 4 * 8) { + if(buff_rx[0] <= 0xFE) { + emulator->curr_sector = buff_rx[0] > 3 ? 0 : buff_rx[0]; + emulator->ntag_i2c_plus_sector3_lockout = false; + command_parsed = true; + respond_nothing = true; + FURI_LOG_D(TAG, "Changing sector to %d", emulator->curr_sector); + } } emulator->sector_select_cmd_started = false; - } else if(cmd == MF_UL_GET_VERSION_CMD) { - if(emulator->data.type != MfUltralightTypeUnknown) { - tx_bytes = sizeof(emulator->data.version); - memcpy(buff_tx, &emulator->data.version, tx_bytes); - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } else if(cmd == MF_UL_READ_CMD) { - int16_t start_page = buff_rx[1]; - tx_bytes = 16; - if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - if(start_page < page_num) { - if(start_page + 4 > page_num) { - // Handle roll-over mechanism - uint8_t end_pages_num = page_num - start_page; - memcpy(buff_tx, &emulator->data.data[start_page * 4], end_pages_num * 4); - memcpy( - &buff_tx[end_pages_num * 4], emulator->data.data, (4 - end_pages_num) * 4); - } else { - memcpy(buff_tx, &emulator->data.data[start_page * 4], tx_bytes); - } - mf_ul_protect_auth_data_on_read_command( - buff_tx, start_page, (start_page + 4), emulator); - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } else { - uint16_t valid_pages; - start_page = mf_ultralight_ntag_i2c_addr_tag_to_lin( - &emulator->data, start_page, emulator->curr_sector, &valid_pages); - if(start_page != -1) { - if(emulator->data.type < MfUltralightTypeNTAGI2CPlus1K || - mf_ul_ntag_i2c_plus_check_auth(emulator, buff_rx[1], false)) { - if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K && - emulator->curr_sector == 3 && valid_pages == 1) { - // Rewind back a sector to match behavior on a real tag - --start_page; - ++valid_pages; - } - - uint16_t copy_count = (valid_pages > 4 ? 4 : valid_pages) * 4; - FURI_LOG_D( - TAG, - "NTAG I2C Emu: page valid, %02x:%02x -> %d, %d", - emulator->curr_sector, - buff_rx[1], - start_page, - valid_pages); - memcpy(buff_tx, &emulator->data.data[start_page * 4], copy_count); - // For NTAG I2C, there's no roll-over; remainder is filled by null bytes - if(copy_count < tx_bytes) - memset(&buff_tx[copy_count], 0, tx_bytes - copy_count); - // Special case: NTAG I2C Plus sector 0 page 233 read crosses into page 236 - if(start_page == 233) - memcpy(&buff_tx[12], &emulator->data.data[(start_page + 1) * 4], 4); - mf_ul_protect_auth_data_on_read_command_i2c( - buff_tx, start_page, start_page + copy_count / 4 - 1, emulator); + } else if(buff_rx_len >= 8) { + uint8_t cmd = buff_rx[0]; + if(cmd == MF_UL_GET_VERSION_CMD) { + if(emulator->data.type != MfUltralightTypeUnknown) { + if(buff_rx_len == 1 * 8) { + tx_bytes = sizeof(emulator->data.version); + memcpy(buff_tx, &emulator->data.version, tx_bytes); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } - } else { - FURI_LOG_D( - TAG, - "NTAG I2C Emu: page invalid, %02x:%02x", - emulator->curr_sector, - buff_rx[1]); - if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K && - emulator->curr_sector == 3 && !emulator->ntag_i2c_plus_sector3_lockout) { - // NTAG I2C Plus has a weird behavior where if you read sector 3 - // at an invalid address, it responds with zeroes then locks - // the read out, while if you read the mirrored session registers, - // it returns both session registers on either pages - memset(buff_tx, 0, tx_bytes); - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - emulator->ntag_i2c_plus_sector3_lockout = true; - } } - } - if(!command_parsed) tx_bytes = 0; - } else if(cmd == MF_UL_FAST_READ_CMD) { - if(emulator->support_fast_read) { - int16_t start_page = buff_rx[1]; - uint8_t end_page = buff_rx[2]; - if(start_page <= end_page) { - tx_bytes = ((end_page + 1) - start_page) * 4; + } else if(cmd == MF_UL_READ_CMD) { + if(buff_rx_len == (1 + 1) * 8) { + int16_t start_page = buff_rx[1]; + tx_bytes = 16; if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - if((start_page < page_num) && (end_page < page_num)) { - memcpy(buff_tx, &emulator->data.data[start_page * 4], tx_bytes); - mf_ul_protect_auth_data_on_read_command( - buff_tx, start_page, end_page, emulator); - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; + if(start_page < emulator->page_num) { + do { + uint8_t copied_pages = 0; + uint8_t src_page = start_page; + uint8_t last_page_plus_one = start_page + 4; + uint8_t pwd_page = emulator->page_num - 2; + string_t ascii_mirror; + size_t ascii_mirror_len = 0; + const char* ascii_mirror_cptr = NULL; + uint8_t ascii_mirror_curr_page = 0; + uint8_t ascii_mirror_curr_byte = 0; + if(last_page_plus_one > emulator->page_num) + last_page_plus_one = emulator->page_num; + if(emulator->supported_features & MfUltralightSupportAuth) { + if(!mf_ul_check_auth(emulator, start_page, false)) break; + if(!emulator->auth_success && emulator->config_cache.access.prot && + emulator->config_cache.auth0 < last_page_plus_one) + last_page_plus_one = emulator->config_cache.auth0; + } + if(emulator->supported_features & MfUltralightSupportSingleCounter) + mf_ul_increment_single_counter(emulator); + if(emulator->supported_features & MfUltralightSupportAsciiMirror && + emulator->config_cache.mirror.mirror_conf != + MfUltralightMirrorNone) { + ascii_mirror_curr_byte = emulator->config->mirror.mirror_byte; + ascii_mirror_curr_page = emulator->config->mirror_page; + // Try to avoid wasting time making mirror if we won't copy it + // Conservatively check with UID+counter mirror size + if(last_page_plus_one > ascii_mirror_curr_page && + start_page + 3 >= ascii_mirror_curr_page && + start_page <= ascii_mirror_curr_page + 6) { + string_init(ascii_mirror); + mf_ul_make_ascii_mirror(emulator, ascii_mirror); + ascii_mirror_len = string_length_u(ascii_mirror); + ascii_mirror_cptr = string_get_cstr(ascii_mirror); + // Move pointer to where it should be to start copying + if(ascii_mirror_len > 0 && + ascii_mirror_curr_page < start_page && + ascii_mirror_curr_byte != 0) { + uint8_t diff = 4 - ascii_mirror_curr_byte; + ascii_mirror_len -= diff; + ascii_mirror_cptr += diff; + ascii_mirror_curr_byte = 0; + ++ascii_mirror_curr_page; + } + while(ascii_mirror_len > 0 && + ascii_mirror_curr_page < start_page) { + uint8_t diff = ascii_mirror_len > 4 ? 4 : ascii_mirror_len; + ascii_mirror_len -= diff; + ascii_mirror_cptr += diff; + ++ascii_mirror_curr_page; + } + } + } + + uint8_t* dest_ptr = buff_tx; + while(copied_pages < 4) { + // Copy page + memcpy(dest_ptr, &emulator->data.data[src_page * 4], 4); + + // Note: don't have to worry about roll-over with ASCII mirror because + // lowest valid page for it is 4, while roll-over will at best read + // pages 0-2 + if(ascii_mirror_len > 0 && src_page == ascii_mirror_curr_page) { + // Copy ASCII mirror + size_t copy_len = 4 - ascii_mirror_curr_byte; + if(copy_len > ascii_mirror_len) copy_len = ascii_mirror_len; + for(size_t i = 0; i < copy_len; ++i) { + if(*ascii_mirror_cptr != ' ') + dest_ptr[ascii_mirror_curr_byte] = + (uint8_t)*ascii_mirror_cptr; + ++ascii_mirror_curr_byte; + ++ascii_mirror_cptr; + } + ascii_mirror_len -= copy_len; + // Don't care if this is inaccurate after ascii_mirror_len = 0 + ascii_mirror_curr_byte = 0; + ++ascii_mirror_curr_page; + } + + if(emulator->supported_features & MfUltralightSupportAuth) { + if(src_page == pwd_page || src_page == pwd_page + 1) { + // Blank out PWD and PACK pages + memset(dest_ptr, 0, 4); + } + } + + dest_ptr += 4; + ++copied_pages; + ++src_page; + if(src_page >= last_page_plus_one) src_page = 0; + } + if(ascii_mirror_cptr != NULL) { + string_clear(ascii_mirror); + } + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } while(false); } } else { uint16_t valid_pages; @@ -915,151 +1218,401 @@ bool mf_ul_prepare_emulation_response( if(start_page != -1) { if(emulator->data.type < MfUltralightTypeNTAGI2CPlus1K || mf_ul_ntag_i2c_plus_check_auth(emulator, buff_rx[1], false)) { + if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K && + emulator->curr_sector == 3 && valid_pages == 1) { + // Rewind back a sector to match behavior on a real tag + --start_page; + ++valid_pages; + } + uint16_t copy_count = (valid_pages > 4 ? 4 : valid_pages) * 4; + FURI_LOG_D( + TAG, + "NTAG I2C Emu: page valid, %02x:%02x -> %d, %d", + emulator->curr_sector, + buff_rx[1], + start_page, + valid_pages); memcpy(buff_tx, &emulator->data.data[start_page * 4], copy_count); + // For NTAG I2C, there's no roll-over; remainder is filled by null bytes if(copy_count < tx_bytes) memset(&buff_tx[copy_count], 0, tx_bytes - copy_count); - mf_ul_ntag_i2c_fill_cross_area_read( - buff_tx, buff_rx[1], buff_rx[2], emulator); + // Special case: NTAG I2C Plus sector 0 page 233 read crosses into page 236 + if(start_page == 233) + memcpy( + &buff_tx[12], &emulator->data.data[(start_page + 1) * 4], 4); mf_ul_protect_auth_data_on_read_command_i2c( buff_tx, start_page, start_page + copy_count / 4 - 1, emulator); *data_type = FURI_HAL_NFC_TXRX_DEFAULT; command_parsed = true; } + } else { + FURI_LOG_D( + TAG, + "NTAG I2C Emu: page invalid, %02x:%02x", + emulator->curr_sector, + buff_rx[1]); + if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K && + emulator->curr_sector == 3 && + !emulator->ntag_i2c_plus_sector3_lockout) { + // NTAG I2C Plus has a weird behavior where if you read sector 3 + // at an invalid address, it responds with zeroes then locks + // the read out, while if you read the mirrored session registers, + // it returns both session registers on either pages + memset(buff_tx, 0, tx_bytes); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + emulator->ntag_i2c_plus_sector3_lockout = true; + } } } if(!command_parsed) tx_bytes = 0; } - } - } else if(cmd == MF_UL_WRITE) { - int16_t write_page = buff_rx[1]; - if(write_page > 1) { - uint16_t valid_pages; - write_page = mf_ultralight_ntag_i2c_addr_tag_to_lin( - &emulator->data, write_page, emulator->curr_sector, &valid_pages); - if(write_page != -1 && - (emulator->data.type >= MfUltralightTypeNTAGI2C1K || (write_page < page_num - 2))) { - if(emulator->data.type < MfUltralightTypeNTAGI2CPlus1K || - mf_ul_ntag_i2c_plus_check_auth(emulator, buff_rx[1], true)) { - memcpy(&emulator->data.data[write_page * 4], &buff_rx[2], 4); - emulator->data_changed = true; + } else if(cmd == MF_UL_FAST_READ_CMD) { + if(emulator->supported_features & MfUltralightSupportFastRead) { + if(buff_rx_len == (1 + 2) * 8) { + int16_t start_page = buff_rx[1]; + uint8_t end_page = buff_rx[2]; + if(start_page <= end_page) { + tx_bytes = ((end_page + 1) - start_page) * 4; + if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { + if((start_page < emulator->page_num) && + (end_page < emulator->page_num)) { + do { + if(emulator->supported_features & MfUltralightSupportAuth) { + // NAK if not authenticated and requested pages cross over AUTH0 + if(!emulator->auth_success && + emulator->config_cache.access.prot && + (start_page >= emulator->config_cache.auth0 || + end_page >= emulator->config_cache.auth0)) + break; + } + if(emulator->supported_features & + MfUltralightSupportSingleCounter) + mf_ul_increment_single_counter(emulator); + + // Copy requested pages + memcpy( + buff_tx, &emulator->data.data[start_page * 4], tx_bytes); + + if(emulator->supported_features & + MfUltralightSupportAsciiMirror && + emulator->config_cache.mirror.mirror_conf != + MfUltralightMirrorNone) { + // Copy ASCII mirror + // Less stringent check here, because expecting FAST_READ to + // only be issued once rather than repeatedly + string_t ascii_mirror; + string_init(ascii_mirror); + mf_ul_make_ascii_mirror(emulator, ascii_mirror); + size_t ascii_mirror_len = string_length_u(ascii_mirror); + const char* ascii_mirror_cptr = + string_get_cstr(ascii_mirror); + int16_t mirror_start_offset = + (emulator->config->mirror_page - start_page) * 4 + + emulator->config->mirror.mirror_byte; + if(mirror_start_offset < 0) { + if(mirror_start_offset < -(int16_t)ascii_mirror_len) { + // Past ASCII mirror, don't copy + ascii_mirror_len = 0; + } else { + ascii_mirror_cptr += -mirror_start_offset; + ascii_mirror_len -= -mirror_start_offset; + mirror_start_offset = 0; + } + } + if(ascii_mirror_len > 0) { + int16_t mirror_end_offset = + mirror_start_offset + ascii_mirror_len; + if(mirror_end_offset > (end_page + 1) * 4) { + mirror_end_offset = (end_page + 1) * 4; + ascii_mirror_len = + mirror_end_offset - mirror_start_offset; + } + for(size_t i = 0; i < ascii_mirror_len; ++i) { + if(*ascii_mirror_cptr != ' ') + buff_tx[mirror_start_offset] = + (uint8_t)*ascii_mirror_cptr; + ++mirror_start_offset; + ++ascii_mirror_cptr; + } + } + string_clear(ascii_mirror); + } + + if(emulator->supported_features & MfUltralightSupportAuth) { + // Clear PWD and PACK pages + uint8_t pwd_page = emulator->page_num - 2; + int16_t pwd_page_offset = pwd_page - start_page; + // PWD page + if(pwd_page_offset >= 0 && pwd_page <= end_page) { + memset(&buff_tx[pwd_page_offset * 4], 0, 4); + // PACK page + if(pwd_page + 1 <= end_page) + memset(&buff_tx[(pwd_page_offset + 1) * 4], 0, 4); + } + } + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } while(false); + } + } else { + uint16_t valid_pages; + start_page = mf_ultralight_ntag_i2c_addr_tag_to_lin( + &emulator->data, start_page, emulator->curr_sector, &valid_pages); + if(start_page != -1) { + if(emulator->data.type < MfUltralightTypeNTAGI2CPlus1K || + mf_ul_ntag_i2c_plus_check_auth(emulator, buff_rx[1], false)) { + uint16_t copy_count = tx_bytes; + if(copy_count > valid_pages * 4) copy_count = valid_pages * 4; + memcpy( + buff_tx, &emulator->data.data[start_page * 4], copy_count); + if(copy_count < tx_bytes) + memset(&buff_tx[copy_count], 0, tx_bytes - copy_count); + mf_ul_ntag_i2c_fill_cross_area_read( + buff_tx, buff_rx[1], buff_rx[2], emulator); + mf_ul_protect_auth_data_on_read_command_i2c( + buff_tx, + start_page, + start_page + copy_count / 4 - 1, + emulator); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } + } + } + if(!command_parsed) tx_bytes = 0; + } + } + } + } else if(cmd == MF_UL_WRITE) { + if(buff_rx_len == (1 + 5) * 8) { + do { + uint8_t orig_write_page = buff_rx[1]; + int16_t write_page = orig_write_page; + uint16_t valid_pages; // unused + write_page = mf_ultralight_ntag_i2c_addr_tag_to_lin( + &emulator->data, write_page, emulator->curr_sector, &valid_pages); + if(write_page == -1) // NTAG I2C range check + break; + else if(write_page < 2 || write_page >= emulator->page_num) // Other MFUL/NTAG range check + break; + + if(emulator->supported_features & MfUltralightSupportAuth) { + if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K) { + if(!mf_ul_ntag_i2c_plus_check_auth(emulator, orig_write_page, true)) + break; + } else { + if(!mf_ul_check_auth(emulator, orig_write_page, true)) break; + } + } + int16_t tag_addr = mf_ultralight_page_addr_to_tag_addr( + emulator->curr_sector, orig_write_page); + if(!mf_ul_check_lock(emulator, tag_addr)) break; + mf_ul_emulate_write(emulator, tag_addr, write_page, &buff_rx[2]); + send_ack = true; + command_parsed = true; + } while(false); + } + } else if(cmd == MF_UL_FAST_WRITE) { + if(emulator->supported_features & MfUltralightSupportFastWrite) { + if(buff_rx_len == (1 + 66) * 8) { + if(buff_rx[1] == 0xF0 && buff_rx[2] == 0xFF) { + // TODO: update when SRAM emulation implemented + send_ack = true; + command_parsed = true; + } + } + } + } else if(cmd == MF_UL_COMP_WRITE) { + if(emulator->supported_features & MfUltralightSupportCompatWrite) { + if(buff_rx_len == (1 + 1) * 8) { + uint8_t write_page = buff_rx[1]; + do { + if(write_page < 2 || write_page >= emulator->page_num) break; + if(emulator->supported_features & MfUltralightSupportAuth && + !mf_ul_check_auth(emulator, write_page, true)) + break; + // Note we don't convert to tag addr here because there's only one sector + if(!mf_ul_check_lock(emulator, write_page)) break; + + emulator->comp_write_cmd_started = true; + emulator->comp_write_page_addr = write_page; + send_ack = true; + command_parsed = true; + } while(false); + } + } + } else if(cmd == MF_UL_READ_CNT) { + if(emulator->supported_features & MfUltralightSupportReadCounter) { + if(buff_rx_len == (1 + 1) * 8) { + do { + uint8_t cnt_num = buff_rx[1]; + + // NTAG21x checks + if(emulator->supported_features & MfUltralightSupportSingleCounter) { + if(cnt_num != 2) break; // Only counter 2 is available + if(!emulator->config_cache.access.nfc_cnt_en) + break; // NAK if counter not enabled + if(emulator->config_cache.access.nfc_cnt_pwd_prot && + !emulator->auth_success) + break; + } + + if(cnt_num < 3) { + buff_tx[0] = emulator->data.counter[cnt_num] & 0xFF; + buff_tx[1] = (emulator->data.counter[cnt_num] >> 8) & 0xFF; + buff_tx[2] = (emulator->data.counter[cnt_num] >> 16) & 0xFF; + tx_bytes = 3; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } + } while(false); + } + } + } else if(cmd == MF_UL_INC_CNT) { + if(emulator->supported_features & MfUltralightSupportIncrCounter) { + if(buff_rx_len == (1 + 5) * 8) { + uint8_t cnt_num = buff_rx[1]; + uint32_t inc = (buff_rx[2] | (buff_rx[3] << 8) | (buff_rx[4] << 16)); + // TODO: can you increment by 0 when counter is at 0xffffff? + if((cnt_num < 3) && (emulator->data.counter[cnt_num] != 0x00FFFFFF) && + (emulator->data.counter[cnt_num] + inc <= 0x00FFFFFF)) { + emulator->data.counter[cnt_num] += inc; + // We're RAM-backed, so tearing never happens + emulator->data.tearing[cnt_num] = MF_UL_TEARING_FLAG_DEFAULT; + emulator->data_changed = true; + send_ack = true; + command_parsed = true; + } + } + } + } else if(cmd == MF_UL_AUTH) { + if(emulator->supported_features & MfUltralightSupportAuth) { + if(buff_rx_len == (1 + 4) * 8) { + uint16_t scaled_authlim = mf_ultralight_calc_auth_count(&emulator->data); + if(scaled_authlim != 0 && emulator->data.curr_authlim >= scaled_authlim) { + if(emulator->data.curr_authlim != UINT16_MAX) { + // Handle case where AUTHLIM has been lowered or changed from 0 + emulator->data.curr_authlim = UINT16_MAX; + emulator->data_changed = true; + } + // AUTHLIM reached, always fail + buff_tx[0] = MF_UL_NAK_AUTHLIM_REACHED; + tx_bits = 4; + *data_type = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; + mf_ul_reset_emulation(emulator, false); + command_parsed = true; + } else { + if(memcmp(&buff_rx[1], emulator->config->auth_data.pwd.raw, 4) == 0) { + // Correct password + buff_tx[0] = emulator->config->auth_data.pack.raw[0]; + buff_tx[1] = emulator->config->auth_data.pack.raw[1]; + tx_bytes = 2; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + emulator->auth_success = true; + command_parsed = true; + if(emulator->data.curr_authlim != 0) { + // Reset current AUTHLIM + emulator->data.curr_authlim = 0; + emulator->data_changed = true; + } + } else if(!emulator->config->auth_data.pwd.value) { + // Unknown password, pretend to be an Amiibo + buff_tx[0] = 0x80; + buff_tx[1] = 0x80; + tx_bytes = 2; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + emulator->auth_success = true; + command_parsed = true; + } else { + // Wrong password, increase negative verification count + if(emulator->data.curr_authlim < UINT16_MAX) { + ++emulator->data.curr_authlim; + emulator->data_changed = true; + } + if(scaled_authlim != 0 && + emulator->data.curr_authlim >= scaled_authlim) { + emulator->data.curr_authlim = UINT16_MAX; + buff_tx[0] = MF_UL_NAK_AUTHLIM_REACHED; + tx_bits = 4; + *data_type = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; + mf_ul_reset_emulation(emulator, false); + command_parsed = true; + } else { + // Should delay here to slow brute forcing + } + } + } + } + } + } else if(cmd == MF_UL_READ_SIG) { + if(emulator->supported_features & MfUltralightSupportSignature) { + // Check 2nd byte = 0x00 - RFU + if(buff_rx_len == (1 + 1) * 8 && buff_rx[1] == 0x00) { + tx_bytes = sizeof(emulator->data.signature); + memcpy(buff_tx, emulator->data.signature, tx_bytes); + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } + } + } else if(cmd == MF_UL_CHECK_TEARING) { + if(emulator->supported_features & MfUltralightSupportTearingFlags) { + if(buff_rx_len == (1 + 1) * 8) { + uint8_t cnt_num = buff_rx[1]; + if(cnt_num < 3) { + buff_tx[0] = emulator->data.tearing[cnt_num]; + tx_bytes = 1; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } + } + } + } else if(cmd == MF_UL_HALT_START) { + reset_idle = true; + FURI_LOG_D(TAG, "Received HLTA"); + } else if(cmd == MF_UL_SECTOR_SELECT) { + if(emulator->supported_features & MfUltralightSupportSectorSelect) { + if(buff_rx_len == (1 + 1) * 8 && buff_rx[1] == 0xFF) { + // Send ACK + emulator->sector_select_cmd_started = true; send_ack = true; command_parsed = true; } } - } - } else if(cmd == MF_UL_FAST_WRITE) { - if(emulator->data.type >= MfUltralightTypeNTAGI2CPlus1K) { - if(buff_rx[1] == 0xF0 && buff_rx[2] == 0xFF) { - // TODO: update when SRAM emulation implemented - send_ack = true; - command_parsed = true; + } else if(cmd == MF_UL_READ_VCSL) { + if(emulator->supported_features & MfUltralightSupportVcsl) { + if(buff_rx_len == (1 + 20) * 8) { + buff_tx[0] = emulator->config_cache.vctid; + tx_bytes = 1; + *data_type = FURI_HAL_NFC_TXRX_DEFAULT; + command_parsed = true; + } } + } else { + reset_idle = true; + FURI_LOG_D(TAG, "Received invalid command"); } - } else if(cmd == MF_UL_COMP_WRITE) { - if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - uint8_t write_page = buff_rx[1]; - if((write_page > 1) && (write_page < page_num - 2)) { - emulator->comp_write_cmd_started = true; - emulator->comp_write_page_addr = write_page; - // ACK - buff_tx[0] = 0x0A; - tx_bits = 4; - *data_type = FURI_HAL_NFC_TXRX_RAW; - command_parsed = true; - } - } - } else if(cmd == MF_UL_READ_CNT) { - if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - uint8_t cnt_num = buff_rx[1]; - if(cnt_num < 3) { - buff_tx[0] = emulator->data.counter[cnt_num] >> 16; - buff_tx[1] = emulator->data.counter[cnt_num] >> 8; - buff_tx[2] = emulator->data.counter[cnt_num]; - tx_bytes = 3; - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } - } else if(cmd == MF_UL_INC_CNT) { - if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - uint8_t cnt_num = buff_rx[1]; - uint32_t inc = (buff_rx[2] | (buff_rx[3] << 8) | (buff_rx[4] << 16)); - if((cnt_num < 3) && (emulator->data.counter[cnt_num] + inc < 0x00FFFFFF)) { - emulator->data.counter[cnt_num] += inc; - emulator->data_changed = true; - // ACK - buff_tx[0] = 0x0A; - tx_bits = 4; - *data_type = FURI_HAL_NFC_TXRX_RAW; - command_parsed = true; - } - } - } else if(cmd == MF_UL_AUTH) { - if(emulator->data.type >= MfUltralightTypeNTAG213 && - emulator->data.type != MfUltralightTypeNTAGI2C1K && - emulator->data.type != MfUltralightTypeNTAGI2C2K) { - if(memcmp(&buff_rx[1], emulator->auth_data->pwd, 4) == 0) { - buff_tx[0] = emulator->auth_data->pack.raw[0]; - buff_tx[1] = emulator->auth_data->pack.raw[1]; - tx_bytes = 2; - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - emulator->auth_success = true; - command_parsed = true; - } else if(!emulator->auth_data->pack.value) { - buff_tx[0] = 0x80; - buff_tx[1] = 0x80; - tx_bytes = 2; - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } - } else if(cmd == MF_UL_READ_SIG) { - if(emulator->data.type != MfUltralightTypeNTAGI2C1K && - emulator->data.type != MfUltralightTypeNTAGI2C2K) { - // Check 2nd byte = 0x00 - RFU - if(buff_rx[1] == 0x00) { - tx_bytes = sizeof(emulator->data.signature); - memcpy(buff_tx, emulator->data.signature, tx_bytes); - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } - } else if(cmd == MF_UL_CHECK_TEARING) { - if(emulator->data.type < MfUltralightTypeNTAGI2C1K) { - uint8_t cnt_num = buff_rx[1]; - if(cnt_num < 3) { - buff_tx[0] = emulator->data.tearing[cnt_num]; - tx_bytes = 1; - *data_type = FURI_HAL_NFC_TXRX_DEFAULT; - command_parsed = true; - } - } - } else if(cmd == MF_UL_HALT_START) { + } else { + reset_idle = true; + FURI_LOG_D(TAG, "Received invalid buffer less than 8 bits in length"); + } + + if(reset_idle) { + mf_ul_reset_emulation(emulator, false); tx_bits = 0; - emulator->curr_sector = 0; - emulator->ntag_i2c_plus_sector3_lockout = false; - emulator->auth_success = false; command_parsed = true; - FURI_LOG_D(TAG, "Received HLTA"); - } else if(cmd == MF_UL_SECTOR_SELECT) { - if(emulator->data.type >= MfUltralightTypeNTAGI2C1K) { - if(buff_rx[1] == 0xFF) { - // Send ACK - emulator->sector_select_cmd_started = true; - send_ack = true; - command_parsed = true; - } - } } if(!command_parsed) { // Send NACK - buff_tx[0] = 0x00; + buff_tx[0] = MF_UL_NAK_INVALID_ARGUMENT; tx_bits = 4; *data_type = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; + // Every NAK should cause reset to IDLE + mf_ul_reset_emulation(emulator, false); } else if(send_ack) { - buff_tx[0] = 0x0A; + buff_tx[0] = MF_UL_ACK; tx_bits = 4; *data_type = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; } diff --git a/lib/nfc_protocols/mifare_ultralight.h b/lib/nfc_protocols/mifare_ultralight.h index 76dc2edb..36b81fdf 100644 --- a/lib/nfc_protocols/mifare_ultralight.h +++ b/lib/nfc_protocols/mifare_ultralight.h @@ -22,6 +22,10 @@ #define MF_UL_READ_VCSL (0x4B) #define MF_UL_SECTOR_SELECT (0xC2) +#define MF_UL_ACK (0xa) +#define MF_UL_NAK_INVALID_ARGUMENT (0x0) +#define MF_UL_NAK_AUTHLIM_REACHED (0x4) + typedef enum { MfUltralightTypeUnknown, MfUltralightTypeUL11, @@ -38,6 +42,31 @@ typedef enum { MfUltralightTypeNum, } MfUltralightType; +typedef enum { + MfUltralightSupportNone = 0, + MfUltralightSupportFastRead = 1 << 0, + MfUltralightSupportTearingFlags = 1 << 1, + MfUltralightSupportReadCounter = 1 << 2, + MfUltralightSupportIncrCounter = 1 << 3, + MfUltralightSupportSignature = 1 << 4, + MfUltralightSupportFastWrite = 1 << 5, + MfUltralightSupportCompatWrite = 1 << 6, + MfUltralightSupportAuth = 1 << 7, + MfUltralightSupportVcsl = 1 << 8, + MfUltralightSupportSectorSelect = 1 << 9, + // NTAG21x only has counter 2 + MfUltralightSupportSingleCounter = 1 << 10, + // ASCII mirror is not a command, but handy to have as a flag + MfUltralightSupportAsciiMirror = 1 << 11, +} MfUltralightFeatures; + +typedef enum { + MfUltralightMirrorNone, + MfUltralightMirrorUid, + MfUltralightMirrorCounter, + MfUltralightMirrorUidCounter, +} MfUltralightMirrorConf; + typedef struct { uint8_t header; uint8_t vendor_id; @@ -65,38 +94,76 @@ typedef struct { uint8_t signature[32]; uint32_t counter[3]; uint8_t tearing[3]; + uint16_t curr_authlim; uint16_t data_size; uint8_t data[MF_UL_MAX_DUMP_SIZE]; } MfUltralightData; -typedef struct { - uint8_t pwd[4]; +typedef struct __attribute__((packed)) { + union { + uint8_t raw[4]; + uint32_t value; + } pwd; union { uint8_t raw[2]; uint16_t value; } pack; } MfUltralightAuth; +// Common configuration pages for MFUL EV1, NTAG21x, and NTAG I2C Plus +typedef struct __attribute__((packed)) { + union { + uint8_t value; + struct { + uint8_t rfui1 : 2; + bool strg_mod_en : 1; + bool rfui2 : 1; + uint8_t mirror_byte : 2; + MfUltralightMirrorConf mirror_conf : 2; + }; + } mirror; + uint8_t rfui1; + uint8_t mirror_page; + uint8_t auth0; + union { + uint8_t value; + struct { + uint8_t authlim : 3; + bool nfc_cnt_pwd_prot : 1; + bool nfc_cnt_en : 1; + bool nfc_dis_sec1 : 1; // NTAG I2C Plus only + bool cfglck : 1; + bool prot : 1; + }; + } access; + uint8_t vctid; + uint8_t rfui2[2]; + MfUltralightAuth auth_data; + uint8_t rfui3[2]; +} MfUltralightConfigPages; + typedef struct { uint16_t pages_to_read; int16_t pages_read; - bool support_fast_read; - bool support_tearing_flags; - bool support_counters; - bool support_signature; + MfUltralightFeatures supported_features; } MfUltralightReader; typedef struct { MfUltralightData data; - bool support_fast_read; + MfUltralightConfigPages* config; + // Most config values don't apply until power cycle, so cache config pages + // for correct behavior + MfUltralightConfigPages config_cache; + MfUltralightFeatures supported_features; + uint16_t page_num; bool data_changed; bool comp_write_cmd_started; uint8_t comp_write_page_addr; - MfUltralightAuth* auth_data; bool auth_success; uint8_t curr_sector; bool sector_select_cmd_started; bool ntag_i2c_plus_sector3_lockout; + bool read_counter_incremented; } MfUltralightEmulator; bool mf_ul_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); @@ -127,6 +194,8 @@ bool mf_ul_read_card( MfUltralightReader* reader, MfUltralightData* data); +void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle); + void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data); bool mf_ul_prepare_emulation_response( diff --git a/lib/one_wire/ibutton/ibutton_worker_i.h b/lib/one_wire/ibutton/ibutton_worker_i.h index 93755481..48d03595 100644 --- a/lib/one_wire/ibutton/ibutton_worker_i.h +++ b/lib/one_wire/ibutton/ibutton_worker_i.h @@ -27,9 +27,9 @@ typedef enum { typedef struct { const uint32_t quant; - void (*const start) (iButtonWorker* worker); - void (*const tick) (iButtonWorker* worker); - void (*const stop) (iButtonWorker* worker); + void (*const start)(iButtonWorker* worker); + void (*const tick)(iButtonWorker* worker); + void (*const stop)(iButtonWorker* worker); } iButtonWorkerModeType; typedef enum { diff --git a/lib/one_wire/one_wire_slave.c b/lib/one_wire/one_wire_slave.c index 3c9a796d..1f389623 100644 --- a/lib/one_wire/one_wire_slave.c +++ b/lib/one_wire/one_wire_slave.c @@ -212,7 +212,8 @@ static void exti_cb(void* context) { static uint32_t pulse_start = 0; if(input_state) { - uint32_t pulse_length = (DWT->CYCCNT - pulse_start) / furi_hal_delay_instructions_per_microsecond(); + uint32_t pulse_length = + (DWT->CYCCNT - pulse_start) / furi_hal_delay_instructions_per_microsecond(); if(pulse_length >= OWS_RESET_MIN) { if(pulse_length <= OWS_RESET_MAX) { // reset cycle ok diff --git a/lib/scons b/lib/scons new file mode 160000 index 00000000..c2d1f09f --- /dev/null +++ b/lib/scons @@ -0,0 +1 @@ +Subproject commit c2d1f09f615a9ef3fb5497a7e8e5ee2c900d21a7 diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript new file mode 100644 index 00000000..3c6728af --- /dev/null +++ b/lib/subghz/SConscript @@ -0,0 +1,16 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/subghz", + ], +) + +libenv = env.Clone(FW_LIB_NAME="subghz") +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*.c*") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c new file mode 100644 index 00000000..0dc81f2a --- /dev/null +++ b/lib/subghz/protocols/power_smart.c @@ -0,0 +1,380 @@ +#include "power_smart.h" +#include +#include +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +#define TAG "SubGhzProtocolPowerSmart" +#define POWER_SMART_PACKET_HEADER 0xFD000000AA000000 +#define POWER_SMART_PACKET_HEADER_MASK 0xFF000000FF000000 + +#define CHANNEL_PATTERN "%c%c%c%c%c%c" +#define CNT_TO_CHANNEL(dip) \ + (dip & 0x0001 ? '*' : '-'), (dip & 0x0002 ? '*' : '-'), (dip & 0x0004 ? '*' : '-'), \ + (dip & 0x0008 ? '*' : '-'), (dip & 0x0010 ? '*' : '-'), (dip & 0x0020 ? '*' : '-') + +static const SubGhzBlockConst subghz_protocol_power_smart_const = { + .te_short = 225, + .te_long = 450, + .te_delta = 100, + .min_count_bit_for_found = 64, +}; + +struct SubGhzProtocolDecoderPowerSmart { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + ManchesterState manchester_saved_state; + uint16_t header_count; +}; + +struct SubGhzProtocolEncoderPowerSmart { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + PowerSmartDecoderStepReset = 0, + PowerSmartDecoderFoundHeader, + PowerSmartDecoderStepDecoderData, +} PowerSmartDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_power_smart_decoder = { + .alloc = subghz_protocol_decoder_power_smart_alloc, + .free = subghz_protocol_decoder_power_smart_free, + + .feed = subghz_protocol_decoder_power_smart_feed, + .reset = subghz_protocol_decoder_power_smart_reset, + + .get_hash_data = subghz_protocol_decoder_power_smart_get_hash_data, + .serialize = subghz_protocol_decoder_power_smart_serialize, + .deserialize = subghz_protocol_decoder_power_smart_deserialize, + .get_string = subghz_protocol_decoder_power_smart_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_power_smart_encoder = { + .alloc = subghz_protocol_encoder_power_smart_alloc, + .free = subghz_protocol_encoder_power_smart_free, + + .deserialize = subghz_protocol_encoder_power_smart_deserialize, + .stop = subghz_protocol_encoder_power_smart_stop, + .yield = subghz_protocol_encoder_power_smart_yield, +}; + +const SubGhzProtocol subghz_protocol_power_smart = { + .name = SUBGHZ_PROTOCOL_POWER_SMART_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_power_smart_decoder, + .encoder = &subghz_protocol_power_smart_encoder, +}; + +void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderPowerSmart* instance = malloc(sizeof(SubGhzProtocolEncoderPowerSmart)); + + instance->base.protocol = &subghz_protocol_power_smart; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 1024; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_power_smart_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderPowerSmart* instance = context; + free(instance->encoder.upload); + free(instance); +} + +static LevelDuration + subghz_protocol_encoder_power_smart_add_duration_to_upload(ManchesterEncoderResult result) { + LevelDuration data = {.duration = 0, .level = 0}; + switch(result) { + case ManchesterEncoderResultShortLow: + data.duration = subghz_protocol_power_smart_const.te_short; + data.level = false; + break; + case ManchesterEncoderResultLongLow: + data.duration = subghz_protocol_power_smart_const.te_long; + data.level = false; + break; + case ManchesterEncoderResultLongHigh: + data.duration = subghz_protocol_power_smart_const.te_long; + data.level = true; + break; + case ManchesterEncoderResultShortHigh: + data.duration = subghz_protocol_power_smart_const.te_short; + data.level = true; + break; + + default: + furi_crash("SubGhz: ManchesterEncoderResult is incorrect."); + break; + } + return level_duration_make(data.level, data.duration); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderPowerSmart instance + */ +static void + subghz_protocol_encoder_power_smart_get_upload(SubGhzProtocolEncoderPowerSmart* instance) { + furi_assert(instance); + size_t index = 0; + + ManchesterEncoderState enc_state; + manchester_encoder_reset(&enc_state); + ManchesterEncoderResult result; + + for(int i = 8; i > 0; i--) { + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(!manchester_encoder_advance( + &enc_state, !bit_read(instance->generic.data, i - 1), &result)) { + instance->encoder.upload[index++] = + subghz_protocol_encoder_power_smart_add_duration_to_upload(result); + manchester_encoder_advance( + &enc_state, !bit_read(instance->generic.data, i - 1), &result); + } + instance->encoder.upload[index++] = + subghz_protocol_encoder_power_smart_add_duration_to_upload(result); + } + } + instance->encoder.upload[index] = subghz_protocol_encoder_power_smart_add_duration_to_upload( + manchester_encoder_finish(&enc_state)); + if(level_duration_get_level(instance->encoder.upload[index])) { + index++; + } + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_power_smart_const.te_long * 1111); + instance->encoder.size_upload = index; +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_power_smart_remote_controller(SubGhzBlockGeneric* instance) { + /* + * Protocol: Manchester encoding, symbol rate ~2222. + * Packet Format: + * 0xFDXXXXYYAAZZZZWW where 0xFD and 0xAA sync word + * XXXX = ~ZZZZ, YY=(~WW)-1 + * Example: + * SYNC1 K1 CHANNEL DATA1 K2 DATA2 SYNC2 ~K1 ~CHANNEL ~DATA2 ~K2 (~DATA2)-1 + * 0xFD2137ACAADEC852 => 11111101 0 010000 10011011 1 10101100 10101010 1 1011110 1100100 0 01010010 + * 0xFDA137ACAA5EC852 => 11111101 1 010000 10011011 1 10101100 10101010 0 1011110 1100100 0 01010010 + * 0xFDA136ACAA5EC952 => 11111101 1 010000 10011011 0 10101100 10101010 0 1011110 1100100 1 01010010 + * + * Key: + * K1K2 + * 0 0 - key_unknown + * 0 1 - key_down + * 1 0 - key_up + * 1 1 - key_stop + * + */ + + instance->btn = ((instance->data >> 54) & 0x02) | ((instance->data >> 40) & 0x1); + instance->serial = ((instance->data >> 33) & 0x3FFF00) | ((instance->data >> 32) & 0xFF); + instance->cnt = ((instance->data >> 49) & 0x3F); +} + +bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderPowerSmart* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_power_smart_remote_controller(&instance->generic); + subghz_protocol_encoder_power_smart_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_power_smart_stop(void* context) { + SubGhzProtocolEncoderPowerSmart* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_power_smart_yield(void* context) { + SubGhzProtocolEncoderPowerSmart* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_power_smart_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderPowerSmart* instance = malloc(sizeof(SubGhzProtocolDecoderPowerSmart)); + instance->base.protocol = &subghz_protocol_power_smart; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_power_smart_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + free(instance); +} + +void subghz_protocol_decoder_power_smart_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); +} + +bool subghz_protocol_power_smart_chek_valid(uint64_t packet) { + uint32_t data_1 = (uint32_t)((packet >> 40) & 0xFFFF); + uint32_t data_2 = (uint32_t)((~packet >> 8) & 0xFFFF); + uint8_t data_3 = (uint8_t)(packet >> 32) & 0xFF; + uint8_t data_4 = (uint8_t)(((~packet) & 0xFF) - 1); + return (data_1 == data_2) && (data_3 == data_4); +} + +void subghz_protocol_decoder_power_smart_feed( + void* context, + bool level, + volatile uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + ManchesterEvent event = ManchesterEventReset; + if(!level) { + if(DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_short) < + subghz_protocol_power_smart_const.te_delta) { + event = ManchesterEventShortLow; + } else if( + DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_long) < + subghz_protocol_power_smart_const.te_delta * 2) { + event = ManchesterEventLongLow; + } + } else { + if(DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_short) < + subghz_protocol_power_smart_const.te_delta) { + event = ManchesterEventShortHigh; + } else if( + DURATION_DIFF(duration, subghz_protocol_power_smart_const.te_long) < + subghz_protocol_power_smart_const.te_delta * 2) { + event = ManchesterEventLongHigh; + } + } + if(event != ManchesterEventReset) { + bool data; + bool data_ok = manchester_advance( + instance->manchester_saved_state, event, &instance->manchester_saved_state, &data); + + if(data_ok) { + instance->decoder.decode_data = (instance->decoder.decode_data << 1) | !data; + } + if((instance->decoder.decode_data & POWER_SMART_PACKET_HEADER_MASK) == + POWER_SMART_PACKET_HEADER) { + if(subghz_protocol_power_smart_chek_valid(instance->decoder.decode_data)) { + instance->decoder.decode_data = instance->decoder.decode_data; + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = + subghz_protocol_power_smart_const.min_count_bit_for_found; + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + } + } + } else { + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + manchester_advance( + instance->manchester_saved_state, + ManchesterEventReset, + &instance->manchester_saved_state, + NULL); + } +} + +static const char* subghz_protocol_power_smart_get_name_button(uint8_t btn) { + btn &= 0x3; + const char* name_btn[0x4] = {"Unknown", "Down", "Up", "Stop"}; + return name_btn[btn]; +} + +uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_power_smart_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderPowerSmart* instance = context; + subghz_protocol_power_smart_remote_controller(&instance->generic); + + string_cat_printf( + output, + "%s %db\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:0x%07lX \r\n" + "Btn:%s\r\n" + "Channel:" CHANNEL_PATTERN "\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data >> 32), + (uint32_t)(instance->generic.data & 0xFFFFFFFF), + instance->generic.serial, + subghz_protocol_power_smart_get_name_button(instance->generic.btn), + CNT_TO_CHANNEL(instance->generic.cnt)); +} diff --git a/lib/subghz/protocols/power_smart.h b/lib/subghz/protocols/power_smart.h new file mode 100644 index 00000000..346fe537 --- /dev/null +++ b/lib/subghz/protocols/power_smart.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_POWER_SMART_NAME "Power Smart" + +typedef struct SubGhzProtocolDecoderPowerSmart SubGhzProtocolDecoderPowerSmart; +typedef struct SubGhzProtocolEncoderPowerSmart SubGhzProtocolEncoderPowerSmart; + +extern const SubGhzProtocolDecoder subghz_protocol_power_smart_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_power_smart_encoder; +extern const SubGhzProtocol subghz_protocol_power_smart; + +/** + * Allocate SubGhzProtocolEncoderPowerSmart. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderPowerSmart* pointer to a SubGhzProtocolEncoderPowerSmart instance + */ +void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderPowerSmart. + * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance + */ +void subghz_protocol_encoder_power_smart_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance + */ +void subghz_protocol_encoder_power_smart_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_power_smart_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderPowerSmart. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderPowerSmart* pointer to a SubGhzProtocolDecoderPowerSmart instance + */ +void* subghz_protocol_decoder_power_smart_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderPowerSmart. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + */ +void subghz_protocol_decoder_power_smart_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderPowerSmart. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + */ +void subghz_protocol_decoder_power_smart_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_power_smart_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderPowerSmart. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_power_smart_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderPowerSmart. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance + * @param output Resulting text + */ +void subghz_protocol_decoder_power_smart_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index 668e6ad5..5a09ee8c 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -1,15 +1,15 @@ #include "registry.h" const SubGhzProtocol* subghz_protocol_registry[] = { - &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, - &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, - &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, - &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, - &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, - &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, - &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, - &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, - &subghz_protocol_chamb_code, + &subghz_protocol_gate_tx, &subghz_protocol_keeloq, &subghz_protocol_star_line, + &subghz_protocol_nice_flo, &subghz_protocol_came, &subghz_protocol_faac_slh, + &subghz_protocol_nice_flor_s, &subghz_protocol_came_twee, &subghz_protocol_came_atomo, + &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, + &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, + &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_princeton, + &subghz_protocol_raw, &subghz_protocol_linear, &subghz_protocol_secplus_v2, + &subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek, + &subghz_protocol_chamb_code, &subghz_protocol_power_smart, }; diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index 39322380..d64b0cdd 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -27,6 +27,7 @@ #include "megacode.h" #include "holtek.h" #include "chamberlain_code.h" +#include "power_smart.h" /** * Registration by name SubGhzProtocol. diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index a9a7c040..233b9564 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -233,7 +233,7 @@ static void subghz_protocol_scher_khan_check_remote_controller( // break; default: - instance->protocol_name = "Unknown"; + *protocol_name = "Unknown"; instance->serial = 0; instance->btn = 0; instance->cnt = 0; diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index 83cf90b7..0ec4c861 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -216,8 +216,9 @@ bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const c xStreamBufferReset(instance->stream); string_set(instance->file_path, file_path); instance->worker_running = true; - bool res = furi_thread_start(instance->thread); - return res; + furi_thread_start(instance->thread); + + return true; } void subghz_file_encoder_worker_stop(SubGhzFileEncoderWorker* instance) { diff --git a/lib/toolbox/.gitignore b/lib/toolbox/.gitignore new file mode 100644 index 00000000..912c1405 --- /dev/null +++ b/lib/toolbox/.gitignore @@ -0,0 +1 @@ +version.inc.h diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript new file mode 100644 index 00000000..26c233d9 --- /dev/null +++ b/lib/toolbox/SConscript @@ -0,0 +1,47 @@ +Import("env") + +from fbt.version import get_fast_git_version_id + + +env.Append( + CPPPATH=[ + "#/lib/toolbox", + ], +) + + +libenv = env.Clone(tools=["fbt_version"], FW_LIB_NAME="toolbox") +libenv.ApplyLibFlags() + + +# Git Version management +version_depends = [] +version_id_data = get_fast_git_version_id() +if version_id_data: + version_depends = Value(version_id_data) + +# Only invoke version generator if preliminary check target (version_depends) has changed +build_version = libenv.VersionBuilder( + Dir("."), + version_depends, +) + +fw_version_json = libenv.InstallAs( + "${BUILD_DIR}/${FIRMWARE_BUILD_CFG}.json", "version.json" +) +env.Append(FW_VERSION_JSON=fw_version_json) + +# Default(fw_version_json) + + +if not version_depends: + libenv.Precious(build_version) + libenv.AlwaysBuild(build_version) + +sources = libenv.GlobRecursive("*.c") + +libenv.Append(CPPPATH=["."]) + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/toolbox/path.c b/lib/toolbox/path.c index c6add856..607671fb 100644 --- a/lib/toolbox/path.c +++ b/lib/toolbox/path.c @@ -83,3 +83,32 @@ void path_concat(const char* path, const char* suffix, string_t out_path) { string_set(out_path, path); path_append(out_path, suffix); } + +bool path_contains_only_ascii(const char* path) { + const char* name_pos = strrchr(path, '/'); + if(name_pos == NULL) { + name_pos = path; + } else { + name_pos++; + } + + while(*name_pos != '\0') { + if((*name_pos >= '0') && (*name_pos <= '9')) { + name_pos++; + continue; + } else if((*name_pos >= 'A') && (*name_pos <= 'Z')) { + name_pos++; + continue; + } else if((*name_pos >= 'a') && (*name_pos <= 'z')) { + name_pos++; + continue; + } else if(strchr(".!#\\$%&'()-@^_`{}~", *name_pos) != NULL) { + name_pos++; + continue; + } + + return false; + } + + return true; +} \ No newline at end of file diff --git a/lib/toolbox/path.h b/lib/toolbox/path.h index 5c91e3fc..d46b210f 100644 --- a/lib/toolbox/path.h +++ b/lib/toolbox/path.h @@ -65,6 +65,15 @@ void path_append(string_t path, const char* suffix); */ void path_concat(const char* path, const char* suffix, string_t out_path); +/** + * @brief Check that path contains only ascii characters + * + * @param path + * @return true + * @return false + */ +bool path_contains_only_ascii(const char* path); + #ifdef __cplusplus } #endif diff --git a/lib/toolbox/version.c b/lib/toolbox/version.c index 40c48370..c6c10b41 100644 --- a/lib/toolbox/version.c +++ b/lib/toolbox/version.c @@ -1,5 +1,8 @@ #include "version.h" +/* This header is autogenerated by build system */ +#include "version.inc.h" + struct Version { const char* git_hash; const char* git_branch; diff --git a/lib/update_util/update_manifest.c b/lib/update_util/update_manifest.c index 2fe0a1ef..d1ac0d7d 100644 --- a/lib/update_util/update_manifest.c +++ b/lib/update_util/update_manifest.c @@ -17,6 +17,7 @@ #define MANIFEST_KEY_OB_REFERENCE "OB reference" #define MANIFEST_KEY_OB_MASK "OB mask" #define MANIFEST_KEY_OB_WRITE_MASK "OB write mask" +#define MANIFEST_KEY_SPLASH_FILE "Splashscreen" UpdateManifest* update_manifest_alloc() { UpdateManifest* update_manifest = malloc(sizeof(UpdateManifest)); @@ -25,6 +26,7 @@ UpdateManifest* update_manifest_alloc() { string_init(update_manifest->radio_image); string_init(update_manifest->staged_loader_file); string_init(update_manifest->resource_bundle); + string_init(update_manifest->splash_file); update_manifest->target = 0; update_manifest->manifest_version = 0; memset(update_manifest->ob_reference.bytes, 0, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); @@ -41,6 +43,7 @@ void update_manifest_free(UpdateManifest* update_manifest) { string_clear(update_manifest->radio_image); string_clear(update_manifest->staged_loader_file); string_clear(update_manifest->resource_bundle); + string_clear(update_manifest->splash_file); free(update_manifest); } @@ -107,6 +110,9 @@ static bool update_manifest->ob_write_mask.bytes, FURI_HAL_FLASH_OB_RAW_SIZE_BYTES); + flipper_format_read_string( + flipper_file, MANIFEST_KEY_SPLASH_FILE, update_manifest->splash_file); + update_manifest->valid = (!string_empty_p(update_manifest->firmware_dfu_image) || !string_empty_p(update_manifest->radio_image) || diff --git a/lib/update_util/update_manifest.h b/lib/update_util/update_manifest.h index 2b1e6857..2b0c9179 100644 --- a/lib/update_util/update_manifest.h +++ b/lib/update_util/update_manifest.h @@ -42,6 +42,7 @@ typedef struct { FuriHalFlashRawOptionByteData ob_reference; FuriHalFlashRawOptionByteData ob_compare_mask; FuriHalFlashRawOptionByteData ob_write_mask; + string_t splash_file; bool valid; } UpdateManifest; diff --git a/make/base.mk b/make/base.mk deleted file mode 100644 index 281419e9..00000000 --- a/make/base.mk +++ /dev/null @@ -1,11 +0,0 @@ -OBJ_DIR = .obj -ASM_SOURCES = -C_SOURCES = -CPP_SOURCES = -ASSETS = -OPENOCD_OPTS = - -CFLAGS = -CPPFLAGS = -LDFLAGS = -SVD_FILE = diff --git a/make/defaults.mk b/make/defaults.mk deleted file mode 100644 index ade34a6b..00000000 --- a/make/defaults.mk +++ /dev/null @@ -1,2 +0,0 @@ -TARGET ?= f7 -export TARGET diff --git a/make/freertos-heap.mk b/make/freertos-heap.mk deleted file mode 100644 index 93992900..00000000 --- a/make/freertos-heap.mk +++ /dev/null @@ -1 +0,0 @@ -LDFLAGS += -Wl,--wrap,_malloc_r -Wl,--wrap,_free_r -Wl,--wrap,_calloc_r -Wl,--wrap,_realloc_r diff --git a/make/git.mk b/make/git.mk deleted file mode 100644 index e58876a8..00000000 --- a/make/git.mk +++ /dev/null @@ -1,32 +0,0 @@ -GIT_COMMIT := $(shell git rev-parse --short HEAD || echo 'unknown') -GIT_BRANCH := $(shell echo $${WORKFLOW_BRANCH_OR_TAG-$$(git rev-parse --abbrev-ref HEAD || echo 'unknown')}) -GIT_BRANCH_NUM := $(shell git rev-list --count HEAD || echo 'nan') -BUILD_DATE := $(shell date '+%d-%m-%Y' || echo 'unknown') -BUILD_TIME := $(shell date '+%H:%M:%S' || echo 'unknown') -VERSION := $(shell git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo 'unknown') -GIT_DIRTY_BUILD := $(shell git diff --quiet ; echo $$?) - -GIT_DIRTY_SUFFIX := -ifeq ($(GIT_DIRTY_BUILD), 1) - GIT_DIRTY_SUFFIX := -dirty -endif - -CFLAGS += \ - -DGIT_COMMIT=\"$(GIT_COMMIT)\" \ - -DGIT_BRANCH=\"$(GIT_BRANCH)\" \ - -DGIT_BRANCH_NUM=\"$(GIT_BRANCH_NUM)\" \ - -DBUILD_DATE=\"$(BUILD_DATE)\" \ - -DVERSION=\"$(VERSION)\" \ - -DTARGET=$(HARDWARE_TARGET) \ - -DBUILD_DIRTY=$(GIT_DIRTY_BUILD) - -# if suffix is set in environment (by Github), use it -ifeq (${DIST_SUFFIX},) - DIST_SUFFIX := local-$(GIT_COMMIT)$(GIT_DIRTY_SUFFIX) -else - DIST_SUFFIX := ${DIST_SUFFIX}$(GIT_DIRTY_SUFFIX) -endif - -#VERSION_STRING := $(VERSION) ($(GIT_BRANCH) @ $(GIT_COMMIT)), built $(BUILD_DATE) $(BUILD_TIME) -VERSION_STRING := $(DIST_SUFFIX), $(GIT_BRANCH) - diff --git a/make/rules.mk b/make/rules.mk deleted file mode 100644 index bdf8a4af..00000000 --- a/make/rules.mk +++ /dev/null @@ -1,185 +0,0 @@ -OBJ_DIR := $(OBJ_DIR)/$(TARGET)-$(PROJECT) - -# Include source folder paths to virtual paths -C_SOURCES := $(abspath ${C_SOURCES}) -ASM_SOURCES := $(abspath ${ASM_SOURCES}) -CPP_SOURCES := $(abspath ${CPP_SOURCES}) - -# Gather object -OBJECTS = $(addprefix $(OBJ_DIR)/, $(C_SOURCES:.c=.o)) -OBJECTS += $(addprefix $(OBJ_DIR)/, $(ASM_SOURCES:.s=.o)) -OBJECTS += $(addprefix $(OBJ_DIR)/, $(CPP_SOURCES:.cpp=.o)) - -OBJECT_DIRS = $(sort $(dir $(OBJECTS))) - -# Generate dependencies -DEPS = $(OBJECTS:.o=.d) - -ifdef DFU_SERIAL - DFU_OPTIONS += -S $(DFU_SERIAL) -endif - -$(foreach dir, $(OBJECT_DIRS),$(shell mkdir -p $(dir))) - -BUILD_FLAGS_SHELL=\ - echo $(OBJ_DIR) ;\ - echo "$(CFLAGS)" > $(OBJ_DIR)/BUILD_FLAGS.tmp; \ - diff -u $(OBJ_DIR)/BUILD_FLAGS $(OBJ_DIR)/BUILD_FLAGS.tmp 2>&1 > /dev/null \ - && ( echo "CFLAGS ok"; rm $(OBJ_DIR)/BUILD_FLAGS.tmp) \ - || ( echo "CFLAGS has been changed"; mv $(OBJ_DIR)/BUILD_FLAGS.tmp $(OBJ_DIR)/BUILD_FLAGS ) -$(info $(shell $(BUILD_FLAGS_SHELL))) - -CHECK_AND_REINIT_SUBMODULES_SHELL=\ - if git submodule status | egrep -q '^[-]|^[+]' ; then \ - echo "INFO: Need to reinitialize git submodules"; \ - git submodule sync; \ - git submodule update --init; \ - fi -$(info $(shell $(CHECK_AND_REINIT_SUBMODULES_SHELL))) - - -all: $(OBJ_DIR)/$(PROJECT).elf $(OBJ_DIR)/$(PROJECT).hex $(OBJ_DIR)/$(PROJECT).bin $(OBJ_DIR)/$(PROJECT).dfu $(OBJ_DIR)/$(PROJECT).json - @: - -$(OBJ_DIR)/$(PROJECT).elf: $(OBJECTS) - @echo "\tLD\t" $@ - @$(LD) $(LDFLAGS) $(OBJECTS) -o $@ - @$(SZ) $@ - -$(OBJ_DIR)/$(PROJECT).hex: $(OBJ_DIR)/$(PROJECT).elf - @echo "\tHEX\t" $@ - @$(HEX) $< $@ - -$(OBJ_DIR)/$(PROJECT).bin: $(OBJ_DIR)/$(PROJECT).elf - @echo "\tBIN\t" $@ - @$(BIN) $< $@ - -$(OBJ_DIR)/$(PROJECT).dfu: $(OBJ_DIR)/$(PROJECT).bin - @echo "\tDFU\t" $@ - @../scripts/bin2dfu.py \ - -i $(OBJ_DIR)/$(PROJECT).bin \ - -o $(OBJ_DIR)/$(PROJECT).dfu \ - -a $(FLASH_ADDRESS) \ - -l "Flipper Zero $(shell echo $(TARGET) | tr a-z A-Z)" > /dev/null - -$(OBJ_DIR)/$(PROJECT).json: $(OBJ_DIR)/$(PROJECT).dfu - @echo "\tJSON\t" $@ - @$(PROJECT_ROOT)/scripts/meta.py generate -p $(PROJECT) $(CFLAGS) > $(OBJ_DIR)/$(PROJECT).json - -$(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS - @echo "\tCC\t" $(subst $(PROJECT_ROOT)/, , $<) - @$(CC) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS - @echo "\tASM\t" $(subst $(PROJECT_ROOT)/, , $<) - @$(AS) $(CFLAGS) -c $< -o $@ - -$(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS - @echo "\tCPP\t" $(subst $(PROJECT_ROOT)/, , $<) - @$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ - -$(OBJ_DIR)/flash: $(OBJ_DIR)/$(PROJECT).bin - openocd $(OPENOCD_OPTS) -c "program $(OBJ_DIR)/$(PROJECT).bin reset exit $(FLASH_ADDRESS)" - touch $@ - -$(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin - dfu-util -d 0483:df11 -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) $(DFU_OPTIONS) - touch $@ - -.PHONY: flash -flash: $(OBJ_DIR)/flash - -.PHONY: upload -upload: $(OBJ_DIR)/upload - -.PHONY: debug -debug: flash - $(GDB) \ - -ex 'target extended-remote | openocd -c "gdb_port pipe" $(OPENOCD_OPTS)' \ - -ex "set confirm off" \ - -ex "source ../debug/FreeRTOS/FreeRTOS.py" \ - -ex "source ../debug/PyCortexMDebug/PyCortexMDebug.py" \ - -ex "svd_load $(SVD_FILE)" \ - -ex "compare-sections" \ - $(OBJ_DIR)/$(PROJECT).elf; \ - -.PHONY: debug_other -debug_other: - $(GDB) \ - -ex 'target extended-remote | openocd -c "gdb_port pipe" $(OPENOCD_OPTS)' \ - -ex "set confirm off" \ - -ex "source ../debug/PyCortexMDebug/PyCortexMDebug.py" \ - -ex "svd_load $(SVD_FILE)" \ - -.PHONY: blackmagic -blackmagic: - $(GDB) \ - -ex 'target extended-remote $(BLACKMAGIC)' \ - -ex 'monitor swdp_scan' \ - -ex 'monitor debug_bmp enable' \ - -ex 'attach 1' \ - -ex 'set confirm off' \ - -ex 'set mem inaccessible-by-default off' \ - -ex "source ../debug/FreeRTOS/FreeRTOS.py" \ - -ex "source ../debug/PyCortexMDebug/PyCortexMDebug.py" \ - -ex "svd_load $(SVD_FILE)" \ - -ex "compare-sections" \ - $(OBJ_DIR)/$(PROJECT).elf; \ - -.PHONY: openocd -openocd: - openocd $(OPENOCD_OPTS) - -.PHONY: clean -clean: - @echo "\tCLEAN\t" - @$(RM) -rf $(OBJ_DIR) - -.PHONY: z -z: clean - $(MAKE) all - -.PHONY: zz -zz: clean - $(MAKE) flash - -.PHONY: zzz -zzz: clean - $(MAKE) debug - -.PHONY: generate_cscope_db -generate_cscope_db: - @echo "$(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/source.list.p - @cat ~/headers.list >> $(OBJ_DIR)/source.list.p - @cat $(OBJ_DIR)/source.list.p | sed -e "s|^[^//]|$$PWD/&|g" > $(OBJ_DIR)/source.list - @cscope -b -k -i $(OBJ_DIR)/source.list -f $(OBJ_DIR)/cscope.out - @rm -rf $(OBJ_DIR)/source.list $(OBJ_DIR)/source.list.p - -.PHONY: generate_compile_db -generate_compile_db: - @echo "$(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/db.asm_source.list - @echo "$(C_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/db.c_source.list - @echo "$(CPP_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/db.cpp_source.list - @echo "$(AS)$(CFLAGS)" | tr ' ' '\n' > $(OBJ_DIR)/db.asm_flags.list - @echo "$(CC)$(CFLAGS)" | tr ' ' '\n' > $(OBJ_DIR)/db.c_flags.list - @echo "$(CPP)$(CFLAGS)$(CPPFLAGS)" | tr ' ' '\n' > $(OBJ_DIR)/db.cpp_flags.list - @$(PROJECT_ROOT)/scripts/compile_db.py generate -p $(OBJ_DIR) - @rm $(OBJ_DIR)/db.asm_source.list - @rm $(OBJ_DIR)/db.c_source.list - @rm $(OBJ_DIR)/db.cpp_source.list - @rm $(OBJ_DIR)/db.asm_flags.list - @rm $(OBJ_DIR)/db.c_flags.list - @rm $(OBJ_DIR)/db.cpp_flags.list - -# Prevent make from searching targets for real files -%.d: ; - -%.c: ; - -%.cpp: ; - -%.s: ; - -$(OBJ_DIR)/BUILD_FLAGS: ; - --include $(DEPS) diff --git a/make/toolchain.mk b/make/toolchain.mk deleted file mode 100644 index f161d3d1..00000000 --- a/make/toolchain.mk +++ /dev/null @@ -1,41 +0,0 @@ -OS := $(shell uname -s) - -# Compiller -ifeq ($(TOOLCHAIN), arm) -PREFIX = arm-none-eabi- -ifdef GCC_PATH -PREFIX := $(GCC_PATH)/$(PREFIX) -endif -endif - -CCACHE := $(shell which ccache) - -CC = $(CCACHE) $(PREFIX)gcc -std=gnu17 -CPP = $(CCACHE) $(PREFIX)g++ -std=gnu++17 -LD = $(PREFIX)g++ -AS = $(PREFIX)gcc -x assembler-with-cpp -CP = $(PREFIX)objcopy -SZ = $(PREFIX)size -HEX = $(CP) -O ihex -BIN = $(CP) -O binary -S - - -ifeq ($(OS), Darwin) -GDB = gdb -else -GDB = $(PREFIX)gdb-py -endif - -DEBUG ?= 1 -COMPACT ?= 0 -ifeq ($(DEBUG), 1) -CFLAGS += -DFURI_DEBUG -DNDEBUG -Og -g -else ifeq ($(COMPACT), 1) -CFLAGS += -DFURI_NDEBUG -DNDEBUG -Os -g -else -CFLAGS += -DFURI_NDEBUG -DNDEBUG -Og -g -endif - -CFLAGS += -fdata-sections -ffunction-sections -fno-math-errno -fstack-usage -MMD -MP -MF "$(@:%.o=%.d)" -CPPFLAGS += -fno-threadsafe-statics -fno-use-cxa-atexit -fno-exceptions -fno-rtti -LDFLAGS += -Wl,-Map=$(OBJ_DIR)/$(PROJECT).map,--cref -Wl,--gc-sections -Wl,--undefined=uxTopUsedPriority -n diff --git a/scripts/assets.py b/scripts/assets.py index 1363900f..b27b29ef 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from flipper.app import App +from flipper.assets.icon import file2image import logging import argparse @@ -90,31 +91,8 @@ class Main(App): self.parser_dolphin.set_defaults(func=self.dolphin) def _icon2header(self, file): - output = subprocess.check_output(["convert", file, "xbm:-"]) - assert output - f = io.StringIO(output.decode().strip()) - width = int(f.readline().strip().split(" ")[2]) - height = int(f.readline().strip().split(" ")[2]) - data = f.read().strip().replace("\n", "").replace(" ", "").split("=")[1][:-1] - data_bin_str = data[1:-1].replace(",", " ").replace("0x", "") - data_bin = bytearray.fromhex(data_bin_str) - # Encode icon data with LZSS - data_encoded_str = subprocess.check_output( - ["heatshrink", "-e", "-w8", "-l4"], input=data_bin - ) - assert data_encoded_str - data_enc = bytearray(data_encoded_str) - data_enc = bytearray([len(data_enc) & 0xFF, len(data_enc) >> 8]) + data_enc - # Use encoded data only if its lenght less than original, including header - if len(data_enc) < len(data_bin) + 1: - data = ( - "{0x01,0x00," - + "".join("0x{:02x},".format(byte) for byte in data_enc) - + "}" - ) - else: - data = "{0x00," + data[1:] - return width, height, data + image = file2image(file) + return image.width, image.height, image.data_as_carray() def _iconIsSupported(self, filename): extension = filename.lower().split(".")[-1] @@ -122,7 +100,11 @@ class Main(App): def icons(self): self.logger.debug(f"Converting icons") - icons_c = open(os.path.join(self.args.output_directory, "assets_icons.c"), "w") + icons_c = open( + os.path.join(self.args.output_directory, "assets_icons.c"), + "w", + newline="\n", + ) icons_c.write(ICONS_TEMPLATE_C_HEADER) icons = [] # Traverse icons tree, append image data to source file @@ -204,12 +186,19 @@ class Main(App): ) ) icons_c.write("\n") + icons_c.close() + # Create Public Header self.logger.debug(f"Creating header") - icons_h = open(os.path.join(self.args.output_directory, "assets_icons.h"), "w") + icons_h = open( + os.path.join(self.args.output_directory, "assets_icons.h"), + "w", + newline="\n", + ) icons_h.write(ICONS_TEMPLATE_H_HEADER) for name, width, height, frame_rate, frame_count in icons: icons_h.write(ICONS_TEMPLATE_H_ICON_NAME.format(name=name)) + icons_h.close() self.logger.debug(f"Done") return 0 diff --git a/scripts/bin2dfu.py b/scripts/bin2dfu.py index 62554f69..7484738f 100755 --- a/scripts/bin2dfu.py +++ b/scripts/bin2dfu.py @@ -38,9 +38,9 @@ class Main(App): return 1 with open(self.args.input, mode="rb") as file: - bin = file.read() + bindata = file.read() - data = struct.pack(" 0: - h.update(data) - else: - break + with open(path, "rb") as fd: + while True: + data = fd.read(block_size) + if len(data) > 0: + h.update(data) + else: + break return h.hexdigest() diff --git a/scripts/flipper/utils/fff.py b/scripts/flipper/utils/fff.py index b7f89321..fa689b01 100644 --- a/scripts/flipper/utils/fff.py +++ b/scripts/flipper/utils/fff.py @@ -99,5 +99,5 @@ class FlipperFormatFile: self.lines = file.readlines() def save(self, filename: str): - with open(filename, "w") as file: + with open(filename, "w", newline="\n") as file: file.write("\n".join(self.lines)) diff --git a/scripts/lint.py b/scripts/lint.py index bf1f5e68..b3c3e7da 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -117,6 +117,7 @@ class Main(App): if dry_run: if len(bad) > 0: self.logger.error(f"Found {len(bad)} incorrectly named files") + self.logger.info(bad) return False else: # Replace occurances in text files diff --git a/scripts/ob.py b/scripts/ob.py index 17de08fd..722549d6 100755 --- a/scripts/ob.py +++ b/scripts/ob.py @@ -40,10 +40,10 @@ class Main(App): def before(self): self.logger.info(f"Loading Option Bytes data") file_path = os.path.join(os.path.dirname(sys.argv[0]), "ob.data") - file = open(file_path, "r") - for line in file.readlines(): - k, v, o = line.split(":") - self.ob[k.strip()] = v.strip(), o.strip() + with open(file_path, "r") as file: + for line in file.readlines(): + k, v, o = line.split(":") + self.ob[k.strip()] = v.strip(), o.strip() def check(self): self.logger.info(f"Checking Option Bytes") diff --git a/scripts/otp.py b/scripts/otp.py index 54714961..7b2378d1 100755 --- a/scripts/otp.py +++ b/scripts/otp.py @@ -149,8 +149,10 @@ class Main(App): self.logger.info(f"Generating OTP") self._processFirstArgs() self._processSecondArgs() - open(f"{self.args.file}_first.bin", "wb").write(self._packFirst()) - open(f"{self.args.file}_second.bin", "wb").write(self._packSecond()) + with open(f"{self.args.file}_first.bin", "wb") as file: + file.write(self._packFirst()) + with open(f"{self.args.file}_second.bin", "wb") as file: + file.write(self._packSecond()) self.logger.info( f"Generated files: {self.args.file}_first.bin and {self.args.file}_second.bin" ) @@ -166,9 +168,9 @@ class Main(App): try: self.logger.info(f"Packing binary data") - file = open(filename, "wb") - file.write(self._packFirst()) - file.close() + with open(filename, "wb") as file: + file.write(self._packFirst()) + self.logger.info(f"Flashing OTP") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x1FFF7000", filename) @@ -190,9 +192,9 @@ class Main(App): try: self.logger.info(f"Packing binary data") - file = open(filename, "wb") - file.write(self._packSecond()) - file.close() + with open(filename, "wb") as file: + file.write(self._packSecond()) + self.logger.info(f"Flashing OTP") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x1FFF7010", filename) @@ -215,10 +217,10 @@ class Main(App): try: self.logger.info(f"Packing binary data") - file = open(filename, "wb") - file.write(self._packFirst()) - file.write(self._packSecond()) - file.close() + with open(filename, "wb") as file: + file.write(self._packFirst()) + file.write(self._packSecond()) + self.logger.info(f"Flashing OTP") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x1FFF7000", filename) diff --git a/scripts/requirements.txt b/scripts/requirements.txt new file mode 100644 index 00000000..4c4b7279 --- /dev/null +++ b/scripts/requirements.txt @@ -0,0 +1,7 @@ +pyserial==3.5 +heatshrink2==0.11.0 +Pillow==9.1.1 +grpcio==1.47.0 +grpcio-tools==1.47.0 +protobuf==3.20.1 +python3-protobuf==2.5.0 diff --git a/scripts/dist.py b/scripts/sconsdist.py old mode 100755 new mode 100644 similarity index 55% rename from scripts/dist.py rename to scripts/sconsdist.py index ccede12b..1e95ee2f --- a/scripts/dist.py +++ b/scripts/sconsdist.py @@ -7,6 +7,15 @@ from update import Main as UpdateMain import shutil +class ProjectDir: + def __init__(self, project_dir): + self.dir = project_dir + parts = project_dir.split("-") + self.target = parts[0] + self.project = parts[1] + self.flavor = parts[2] if len(parts) > 2 else "" + + class Main(App): def init(self): self.subparsers = self.parser.add_subparsers(help="sub-command help") @@ -15,8 +24,7 @@ class Main(App): "copy", help="Copy firmware binaries & metadata" ) - self.parser_copy.add_argument("-t", dest="target", required=True) - self.parser_copy.add_argument("-p", dest="projects", nargs="+", required=True) + self.parser_copy.add_argument("-p", dest="project", nargs="+", required=True) self.parser_copy.add_argument("-s", dest="suffix", required=True) self.parser_copy.add_argument("-r", dest="resources", required=False) self.parser_copy.add_argument( @@ -36,40 +44,67 @@ class Main(App): def get_project_filename(self, project, filetype): # Temporary fix - if project == "firmware" and filetype != "elf": - project = "full" - return f"flipper-z-{self.args.target}-{project}-{self.args.suffix}.{filetype}" + project_name = project.project + if project_name == "firmware" and filetype != "elf": + project_name = "full" + return f"flipper-z-{self.target}-{project_name}-{self.args.suffix}.{filetype}" def get_dist_filepath(self, filename): return join(self.output_dir_path, filename) def copy_single_project(self, project): - target_project = f"{self.args.target}-{project}" - obj_directory = join("firmware", ".obj", target_project) + obj_directory = join("build", project.dir) for filetype in ("elf", "bin", "dfu", "json"): shutil.copyfile( - join(obj_directory, f"{project}.{filetype}"), + join(obj_directory, f"{project.project}.{filetype}"), self.get_dist_filepath(self.get_project_filename(project, filetype)), ) def copy(self): - self.output_dir_path = join("dist", self.args.target) + self.projects = dict( + map( + lambda pd: (pd.project, pd), + map(ProjectDir, self.args.project), + ) + ) + + project_targets = set(map(lambda p: p.target, self.projects.values())) + if len(project_targets) != 1: + self.logger.error(f"Cannot mix targets {project_targets}!") + return 1 + self.target = project_targets.pop() + + project_flavors = set(map(lambda p: p.flavor, self.projects.values())) + if len(project_flavors) != 1: + self.logger.error(f"Cannot mix flavors {project_flavors}!") + return 2 + self.flavor = project_flavors.pop() + + dist_dir_components = [self.target] + if self.flavor: + dist_dir_components.append(self.flavor) + + self.output_dir_path = join("dist", "-".join(dist_dir_components)) if exists(self.output_dir_path) and not self.args.noclean: - shutil.rmtree(self.output_dir_path) + try: + shutil.rmtree(self.output_dir_path) + except Exception as ex: + pass if not exists(self.output_dir_path): makedirs(self.output_dir_path) - for project in self.args.projects: + for project in self.projects.values(): self.copy_single_project(project) self.logger.info( f"Firmware binaries can be found at:\n\t{self.output_dir_path}" ) + if self.args.version: bundle_dir = join( - self.output_dir_path, f"{self.args.target}-update-{self.args.suffix}" + self.output_dir_path, f"{self.target}-update-{self.args.suffix}" ) bundle_args = [ "generate", @@ -78,11 +113,15 @@ class Main(App): "-v", self.args.version, "-t", - self.args.target, + self.target, "--dfu", - self.get_dist_filepath(self.get_project_filename("firmware", "dfu")), + self.get_dist_filepath( + self.get_project_filename(self.projects["firmware"], "dfu") + ), "--stage", - self.get_dist_filepath(self.get_project_filename("updater", "bin")), + self.get_dist_filepath( + self.get_project_filename(self.projects["updater"], "bin") + ), ] if self.args.resources: bundle_args.extend( diff --git a/scripts/selfupdate.py b/scripts/selfupdate.py new file mode 100644 index 00000000..538ecdb9 --- /dev/null +++ b/scripts/selfupdate.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +from flipper.storage import FlipperStorage + +import logging +import argparse +import os +import sys +import pathlib +import serial.tools.list_ports as list_ports + + +class Main: + def __init__(self): + # command args + self.parser = argparse.ArgumentParser() + self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") + self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") + self.parser.add_argument( + "-b", + "--baud", + help="Port Baud rate", + required=False, + default=115200 * 4, + type=int, + ) + + self.subparsers = self.parser.add_subparsers(help="sub-command help") + + self.parser_install = self.subparsers.add_parser( + "install", help="Install OTA package" + ) + self.parser_install.add_argument("manifest_path", help="Manifest path") + self.parser_install.add_argument( + "--pkg_dir_name", help="Update dir name", default="pcbundle", required=False + ) + self.parser_install.set_defaults(func=self.install) + + # logging + self.logger = logging.getLogger() + + def __call__(self): + self.args = self.parser.parse_args() + if "func" not in self.args: + self.parser.error("Choose something to do") + # configure log output + self.log_level = logging.DEBUG if self.args.debug else logging.INFO + self.logger.setLevel(self.log_level) + self.handler = logging.StreamHandler(sys.stdout) + self.handler.setLevel(self.log_level) + self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") + self.handler.setFormatter(self.formatter) + self.logger.addHandler(self.handler) + # execute requested function + self.args.func() + + # make directory with exist check + def mkdir_on_storage(self, storage, flipper_dir_path): + if not storage.exist_dir(flipper_dir_path): + self.logger.debug(f'"{flipper_dir_path}" does not exist, creating') + if not storage.mkdir(flipper_dir_path): + self.logger.error(f"Error: {storage.last_error}") + return False + else: + self.logger.debug(f'"{flipper_dir_path}" already exists') + return True + + # send file with exist check and hash check + def send_file_to_storage(self, storage, flipper_file_path, local_file_path, force): + exists = storage.exist_file(flipper_file_path) + do_upload = not exists + if exists: + hash_local = storage.hash_local(local_file_path) + hash_flipper = storage.hash_flipper(flipper_file_path) + self.logger.debug(f"hash check: local {hash_local}, flipper {hash_flipper}") + do_upload = force or (hash_local != hash_flipper) + + if do_upload: + self.logger.info(f'Sending "{local_file_path}" to "{flipper_file_path}"') + if not storage.send_file(local_file_path, flipper_file_path): + self.logger.error(f"Error: {storage.last_error}") + return False + return True + + def _get_port(self): + if self.args.port != "auto": + return self.args.port + # Try guessing + flippers = list(list_ports.grep("flip")) + if len(flippers) == 1: + flipper = flippers[0] + self.logger.info(f"Using {flipper.serial_number} on {flipper.device}") + return flipper.device + elif len(flippers) == 0: + self.logger.error("Failed to find connected Flipper") + elif len(flippers) > 1: + self.logger.error("More than one Flipper is attached") + self.logger.error("Failed to guess which port to use. Specify --port") + + def install(self): + if not (port := self._get_port()): + return 1 + + storage = FlipperStorage(port, self.args.baud) + storage.start() + + if not os.path.isfile(self.args.manifest_path): + self.logger.error("Error: manifest not found") + return 2 + + manifest_path = pathlib.Path(os.path.abspath(self.args.manifest_path)) + manifest_name, pkg_name = manifest_path.parts[-1], manifest_path.parts[-2] + + pkg_dir_name = self.args.pkg_dir_name or pkg_name + flipper_update_path = f"/ext/update/{pkg_dir_name}" + + self.logger.info(f'Installing "{pkg_name}" from {flipper_update_path}') + # if not os.path.exists(self.args.manifest_path): + # self.logger.error("Error: package not found") + if not self.mkdir_on_storage(storage, flipper_update_path): + self.logger.error(f"Error: cannot create {storage.last_error}") + return -2 + + for dirpath, dirnames, filenames in os.walk(manifest_path.parents[0]): + for fname in filenames: + self.logger.debug(f"Uploading {fname}") + local_file_path = os.path.join(dirpath, fname) + flipper_file_path = f"{flipper_update_path}/{fname}" + if not self.send_file_to_storage( + storage, flipper_file_path, local_file_path, False + ): + self.logger.error(f"Error: {storage.last_error}") + return -3 + + storage.send_and_wait_eol( + f"update install {flipper_update_path}/{manifest_name}\r" + ) + break + storage.stop() + + +if __name__ == "__main__": + Main()() diff --git a/scripts/slideshow.py b/scripts/slideshow.py new file mode 100644 index 00000000..7626a6ac --- /dev/null +++ b/scripts/slideshow.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +import os +import struct + +from flipper.app import App +from flipper.assets.icon import file2image + + +class Main(App): + MAGIC = 0x72676468 + VERSION = 1 + + def init(self): + self.parser.add_argument("-i", "--input", help="input folder", required=True) + self.parser.add_argument("-o", "--output", help="output file", required=True) + + self.parser.set_defaults(func=self.pack) + + def pack(self): + if not os.path.exists(self.args.input): + self.logger.error(f'"{self.args.input}" does not exist') + return 1 + + file_idx = 0 + images = [] + while True: + frame_filename = os.path.join(self.args.input, f"frame_{file_idx:02}.png") + if not os.path.exists(frame_filename): + break + + self.logger.debug(f"working on {frame_filename}") + try: + images.append(file2image(frame_filename)) + self.logger.debug(f"Processed frame #{file_idx}") + file_idx += 1 + except Exception as e: + self.logger.error(e) + break + + widths = set(img.width for img in images) + heights = set(img.height for img in images) + if len(widths) != 1 or len(heights) != 1: + self.logger.error("All images must have same dimensions!") + return 2 + + data = struct.pack( + ""] + for apptype in self.APP_TYPE_MAP: + contents.extend( + map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) + ) + entry_type, entry_block = self.APP_TYPE_MAP[apptype] + contents.append(f"const {entry_type} {entry_block}[] = {{") + contents.append( + ",\n".join( + map(self.get_app_descr, self.buildset.get_apps_of_type(apptype)) + ) + ) + contents.append("};") + contents.append( + f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});" + ) + + archive_app = self.buildset.get_apps_of_type(FlipperAppType.ARCHIVE) + if archive_app: + contents.extend( + [ + self.get_app_ep_forward(archive_app[0]), + f"const FlipperApplication FLIPPER_ARCHIVE = {self.get_app_descr(archive_app[0])};", + ] + ) + + return "\n".join(contents) diff --git a/site_scons/fbt/util.py b/site_scons/fbt/util.py new file mode 100644 index 00000000..9de24a9a --- /dev/null +++ b/site_scons/fbt/util.py @@ -0,0 +1,19 @@ +import SCons +from SCons.Subst import quote_spaces + +import re + + +WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)") + + +def tempfile_arg_esc_func(arg): + arg = quote_spaces(arg) + if SCons.Platform.platform_default() != "win32": + return arg + # GCC requires double Windows slashes, let's use UNIX separator + return WINPATHSEP_RE.sub(r"/\1", arg) + + +def wrap_tempfile(env, command): + env[command] = '${TEMPFILE("' + env[command] + '","$' + command + 'STR")}' diff --git a/site_scons/fbt/version.py b/site_scons/fbt/version.py new file mode 100644 index 00000000..4745c700 --- /dev/null +++ b/site_scons/fbt/version.py @@ -0,0 +1,23 @@ +import subprocess +import datetime + + +def get_fast_git_version_id(): + try: + version = ( + subprocess.check_output( + [ + "git", + "describe", + "--always", + "--dirty", + "--all", + "--long", + ] + ) + .strip() + .decode() + ) + return (version, datetime.date.today()) + except Exception as e: + print("Failed to check for git changes", e) diff --git a/site_scons/firmwareopts.scons b/site_scons/firmwareopts.scons new file mode 100644 index 00000000..f04b55cd --- /dev/null +++ b/site_scons/firmwareopts.scons @@ -0,0 +1,50 @@ +Import("ENV") + + +if ENV["DEBUG"]: + ENV.Append( + CPPDEFINES=[ + "FURI_DEBUG", + "NDEBUG", + ], + CCFLAGS=[ + "-Og", + ], + ) +elif ENV["COMPACT"]: + ENV.Append( + CPPDEFINES=[ + "FURI_NDEBUG", + "NDEBUG", + ], + CCFLAGS=[ + "-Os", + ], + ) +else: + ENV.Append( + CPPDEFINES=[ + "FURI_NDEBUG", + "NDEBUG", + ], + CCFLAGS=[ + "-Og", + ], + ) + +ENV.Append( + LINKFLAGS=[ + "-Tfirmware/targets/f${TARGET_HW}/${LINKER_SCRIPT}.ld", + ], +) + +if ENV["FIRMWARE_BUILD_CFG"] == "updater": + ENV.Append( + IMAGE_BASE_ADDRESS="0x20000000", + LINKER_SCRIPT="stm32wb55xx_ram_fw", + ) +else: + ENV.Append( + IMAGE_BASE_ADDRESS="0x8000000", + LINKER_SCRIPT="stm32wb55xx_flash", + ) diff --git a/site_scons/site_init.py b/site_scons/site_init.py new file mode 100644 index 00000000..817269e2 --- /dev/null +++ b/site_scons/site_init.py @@ -0,0 +1,40 @@ +from SCons.Script import GetBuildFailures + +import sys +import os +import atexit + +sys.path.insert(0, os.path.join(os.getcwd(), "scripts")) + + +def bf_to_str(bf): + """Convert an element of GetBuildFailures() to a string + in a useful way.""" + import SCons.Errors + + if bf is None: # unknown targets product None in list + return "(unknown tgt)" + elif isinstance(bf, SCons.Errors.StopError): + return str(bf) + elif bf.node: + return str(bf.node) + ": " + bf.errstr + elif bf.filename: + return bf.filename + ": " + bf.errstr + return "unknown failure: " + bf.errstr + + +def display_build_status(): + """Display the build status. Called by atexit. + Here you could do all kinds of complicated things.""" + bf = GetBuildFailures() + if bf: + # bf is normally a list of build failures; if an element is None, + # it's because of a target that scons doesn't know anything about. + failures_message = "\n".join( + ["Failed building %s" % bf_to_str(x) for x in bf if x is not None] + ) + print("*" * 10, "ERRORS", "*" * 10) + print(failures_message) + + +atexit.register(display_build_status) diff --git a/site_scons/site_tools/ccache.py b/site_scons/site_tools/ccache.py new file mode 100644 index 00000000..e88886ad --- /dev/null +++ b/site_scons/site_tools/ccache.py @@ -0,0 +1,14 @@ +def exists(): + return True + + +def generate(env): + if ccache := env.WhereIs("ccache"): + env["CCACHE"] = "ccache" + env["CC_NOCACHE"] = env["CC"] + env["CC"] = "$CCACHE $CC_NOCACHE" + # Tricky place: linking is done with CXX + # Using ccache breaks it + env["LINK"] = env["CXX"] + env["CXX_NOCACHE"] = env["CXX"] + env["CXX"] = "$CCACHE $CXX_NOCACHE" diff --git a/site_scons/site_tools/crosscc.py b/site_scons/site_tools/crosscc.py new file mode 100644 index 00000000..8d6b4a61 --- /dev/null +++ b/site_scons/site_tools/crosscc.py @@ -0,0 +1,74 @@ +from SCons.Tool import asm +from SCons.Tool import gcc +from SCons.Tool import gxx +from SCons.Tool import ar +from SCons.Tool import gnulink +import strip +import gdb +import objdump +import size + +from SCons.Action import _subproc +import subprocess + + +def prefix_commands(env, command_prefix, cmd_list): + for command in cmd_list: + if command in env: + env[command] = command_prefix + env[command] + + +def _get_tool_version(env, tool): + verstr = "version unknown" + proc = _subproc( + env, + env.subst("${%s} --version" % tool), + stdout=subprocess.PIPE, + stderr="devnull", + stdin="devnull", + universal_newlines=True, + error="raise", + shell=True, + ) + if proc: + verstr = proc.stdout.readline() + proc.communicate() + return verstr + + +def generate(env, **kw): + for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump, size): + orig_tool.generate(env) + env.SetDefault( + TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"), + ) + prefix_commands( + env, + env.subst("$TOOLCHAIN_PREFIX"), + [ + "AR", + "AS", + "CC", + "CXX", + "OBJCOPY", + "RANLIB", + "STRIP", + "GDB", + "GDBPY", + "OBJDUMP", + "SIZE", + ], + ) + # Call CC to check version + if whitelisted_versions := kw.get("versions", ()): + cc_version = _get_tool_version(env, "CC") + # print("CC version =", cc_version) + # print(list(filter(lambda v: v in cc_version, whitelisted_versions))) + if not any(filter(lambda v: v in cc_version, whitelisted_versions)): + raise Exception( + f"Toolchain version is not supported. Allowed: {whitelisted_versions}, toolchain: {cc_version} " + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_apps.py b/site_scons/site_tools/fbt_apps.py new file mode 100644 index 00000000..cbeae2d0 --- /dev/null +++ b/site_scons/site_tools/fbt_apps.py @@ -0,0 +1,61 @@ +from SCons.Builder import Builder +from SCons.Action import Action + +import SCons +from fbt.appmanifest import FlipperAppType, AppManager, ApplicationsCGenerator + +# Adding objects for application management to env +# AppManager env["APPMGR"] - loads all manifests; manages list of known apps +# AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config + + +def LoadApplicationManifests(env): + appmgr = env["APPMGR"] = AppManager() + for entry in env.Glob("#/applications/*"): + if isinstance(entry, SCons.Node.FS.Dir) and not str(entry).startswith("."): + appmgr.load_manifest(entry.File("application.fam").abspath, entry.name) + + +def PrepareApplicationsBuild(env): + env["APPBUILD"] = env["APPMGR"].filter_apps(env["APPS"]) + env["APPBUILD_DUMP"] = env.Action( + DumpApplicationConfig, + "\tINFO\t", + ) + + +def DumpApplicationConfig(target, source, env): + print(f"Loaded {len(env['APPMGR'].known_apps)} app definitions.") + print("Firmware modules configuration:") + for apptype in FlipperAppType: + app_sublist = env["APPBUILD"].get_apps_of_type(apptype) + if app_sublist: + print( + f"{apptype.value}:\n\t", + ", ".join(app.appid for app in app_sublist), + ) + + +def build_apps_c(target, source, env): + target_file_name = target[0].path + + gen = ApplicationsCGenerator(env["APPBUILD"]) + with open(target_file_name, "w") as file: + file.write(gen.generate()) + + +def generate(env): + env.AddMethod(LoadApplicationManifests) + env.AddMethod(PrepareApplicationsBuild) + + env.Append( + BUILDERS={ + "ApplicationsC": Builder( + action=Action(build_apps_c, "${APPSCOMSTR}"), + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_assets.py b/site_scons/site_tools/fbt_assets.py new file mode 100644 index 00000000..0c2ce6f7 --- /dev/null +++ b/site_scons/site_tools/fbt_assets.py @@ -0,0 +1,151 @@ +import SCons + +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Node.FS import File + +import os +import subprocess + + +def icons_emitter(target, source, env): + target = [ + "compiled/assets_icons.c", + "compiled/assets_icons.h", + ] + return target, source + + +def proto_emitter(target, source, env): + out_path = target[0].path + target = [] + for src in source: + basename = os.path.splitext(src.name)[0] + target.append(env.File(f"compiled/{basename}.pb.c")) + target.append(env.File(f"compiled/{basename}.pb.h")) + return target, source + + +def dolphin_emitter(target, source, env): + res_root_dir = source[0].Dir(env["DOLPHIN_RES_TYPE"]) + source = [res_root_dir] + source.extend( + env.GlobRecursive("*.*", res_root_dir), + ) + + target_base_dir = target[0] + env.Replace(_DOLPHIN_OUT_DIR=target[0]) + + if env["DOLPHIN_RES_TYPE"] == "external": + target = [] + target.extend( + map( + lambda node: target_base_dir.File( + res_root_dir.rel_path(node).replace(".png", ".bm") + ), + filter(lambda node: isinstance(node, SCons.Node.FS.File), source), + ) + ) + else: + asset_basename = f"assets_dolphin_{env['DOLPHIN_RES_TYPE']}" + target = [ + target_base_dir.File(asset_basename + ".c"), + target_base_dir.File(asset_basename + ".h"), + ] + + return target, source + + +def _invoke_git(args, source_dir): + cmd = ["git"] + cmd.extend(args) + return ( + subprocess.check_output(cmd, cwd=source_dir, stderr=subprocess.STDOUT) + .strip() + .decode() + ) + + +def proto_ver_generator(target, source, env): + target_file = target[0] + src_dir = source[0].dir.abspath + try: + git_fetch = _invoke_git( + ["fetch", "--tags"], + source_dir=src_dir, + ) + except (subprocess.CalledProcessError, EnvironmentError) as e: + # Not great, not terrible + print("Git: fetch failed") + + try: + git_describe = _invoke_git( + ["describe", "--tags", "--abbrev=0"], + source_dir=src_dir, + ) + except (subprocess.CalledProcessError, EnvironmentError) as e: + print("Git: describe failed") + Exit("git error") + + # print("describe=", git_describe) + git_major, git_minor = git_describe.split(".") + version_file_data = ( + "#pragma once", + f"#define PROTOBUF_MAJOR_VERSION {git_major}", + f"#define PROTOBUF_MINOR_VERSION {git_minor}", + "", + ) + with open(str(target_file), "wt") as file: + file.write("\n".join(version_file_data)) + + +def generate(env): + env.SetDefault( + ASSETS_COMPILER="${ROOT_DIR.abspath}/scripts/assets.py", + NANOPB_COMPILER="${ROOT_DIR.abspath}/lib/nanopb/generator/nanopb_generator.py", + ) + + env.Append( + BUILDERS={ + "IconBuilder": Builder( + action=Action( + "${PYTHON3} ${ASSETS_COMPILER} icons ${SOURCE.posix} ${TARGET.dir.posix}", + "${ICONSCOMSTR}", + ), + emitter=icons_emitter, + ), + "ProtoBuilder": Builder( + action=Action( + "${PYTHON3} ${NANOPB_COMPILER} -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}", + "${PROTOCOMSTR}", + ), + emitter=proto_emitter, + suffix=".pb.c", + src_suffix=".proto", + ), + "DolphinSymBuilder": Builder( + action=Action( + '${PYTHON3} ${ASSETS_COMPILER} dolphin -s dolphin_${DOLPHIN_RES_TYPE} "${SOURCE}" "${_DOLPHIN_OUT_DIR}"', + "${DOLPHINCOMSTR}", + ), + emitter=dolphin_emitter, + ), + "DolphinExtBuilder": Builder( + action=Action( + '${PYTHON3} ${ASSETS_COMPILER} dolphin "${SOURCE}" "${_DOLPHIN_OUT_DIR}"', + "${DOLPHINCOMSTR}", + ), + emitter=dolphin_emitter, + ), + "ProtoVerBuilder": Builder( + action=Action( + proto_ver_generator, + "${PBVERCOMSTR}", + ), + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_dist.py b/site_scons/site_tools/fbt_dist.py new file mode 100644 index 00000000..8bfb4068 --- /dev/null +++ b/site_scons/site_tools/fbt_dist.py @@ -0,0 +1,113 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Script import Mkdir +from SCons.Defaults import Touch + + +def get_variant_dirname(env, project=None): + parts = [f"f{env['TARGET_HW']}"] + if project: + parts.append(project) + + suffix = "" + if env["DEBUG"]: + suffix += "D" + if env["COMPACT"]: + suffix += "C" + if suffix: + parts.append(suffix) + + return "-".join(parts) + + +def create_fw_build_targets(env, configuration_name): + flavor = get_variant_dirname(env, configuration_name) + build_dir = env.Dir("build").Dir(flavor).abspath + return env.SConscript( + "firmware.scons", + variant_dir=build_dir, + duplicate=0, + exports={ + "ENV": env, + "fw_build_meta": { + "type": configuration_name, + "flavor": flavor, + "build_dir": build_dir, + }, + }, + ) + + +def AddFwProject(env, base_env, fw_type, fw_env_key): + project_env = env[fw_env_key] = create_fw_build_targets(base_env, fw_type) + env.Append( + DIST_PROJECTS=[ + project_env["FW_FLAVOR"], + ], + DIST_DEPENDS=[ + project_env["FW_ARTIFACTS"], + ], + ) + env.Replace(DIST_DIR=get_variant_dirname(env)) + return project_env + + +def AddDebugTarget(env, targetenv, force_flash=True): + pseudo_name = f"debug.{targetenv.subst('$FIRMWARE_BUILD_CFG')}.pseudo" + debug_target = env.GDBPy( + pseudo_name, + targetenv["FW_ELF"], + GDBPYOPTS='-ex "source debug/FreeRTOS/FreeRTOS.py" ' + '-ex "source debug/PyCortexMDebug/PyCortexMDebug.py" ' + '-ex "svd_load ${SVD_FILE}" ' + '-ex "compare-sections"', + ) + if force_flash: + env.Depends(debug_target, targetenv["FW_FLASH"]) + env.Pseudo(pseudo_name) + env.AlwaysBuild(debug_target) + return debug_target + + +def generate(env): + env.AddMethod(AddFwProject) + env.AddMethod(AddDebugTarget) + env.SetDefault( + COPRO_MCU_FAMILY="STM32WB5x", + ) + env.Append( + BUILDERS={ + "DistBuilder": Builder( + action=Action( + '@${PYTHON3} ${ROOT_DIR.abspath}/scripts/sconsdist.py copy -p ${DIST_PROJECTS} -s "${DIST_SUFFIX}" ${DIST_EXTRA}', + ), + ), + "UsbInstall": Builder( + action=[ + Action( + "${PYTHON3} ${ROOT_DIR.abspath}/scripts/selfupdate.py install dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}/update.fuf" + ), + Touch("${TARGET}"), + ] + ), + "CoproBuilder": Builder( + action=Action( + [ + Mkdir("$TARGET"), + "${PYTHON3} ${ROOT_DIR.abspath}/scripts/assets.py " + "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} ", + ], + "", + ) + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_extapps.py b/site_scons/site_tools/fbt_extapps.py new file mode 100644 index 00000000..17c4bf6c --- /dev/null +++ b/site_scons/site_tools/fbt_extapps.py @@ -0,0 +1,30 @@ +import os + + +def BuildAppElf(env, app): + work_dir = env.subst("$EXT_APPS_WORK_DIR") + app_target_name = os.path.join(work_dir, app.appid) + app_alias = f"{env['FIRMWARE_BUILD_CFG']}_{app.appid}" + app_elf = env.Program( + app_target_name, + env.GlobRecursive("*.c*", os.path.join(work_dir, app._appdir)), + APP_ENTRY=app.entry_point, + ) + app_elf_dump = env.ObjDump(app_target_name) + env.Alias(f"{app_alias}_list", app_elf_dump) + + app_stripped_elf = env.ELFStripper( + os.path.join(env.subst("$PLUGIN_ELF_DIR"), app.appid), app_elf + ) + env.Alias(app_alias, app_stripped_elf) + return app_stripped_elf + + +def generate(env, **kw): + env.SetDefault(EXT_APPS_WORK_DIR=kw.get("EXT_APPS_WORK_DIR", ".extapps")) + env.VariantDir(env.subst("$EXT_APPS_WORK_DIR"), ".", duplicate=False) + env.AddMethod(BuildAppElf) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fbt_version.py b/site_scons/site_tools/fbt_version.py new file mode 100644 index 00000000..5073c55d --- /dev/null +++ b/site_scons/site_tools/fbt_version.py @@ -0,0 +1,29 @@ +from SCons.Builder import Builder +from SCons.Action import Action + + +def version_emitter(target, source, env): + target_dir = target[0] + target = [ + target_dir.File("version.inc.h"), + target_dir.File("version.json"), + ] + return target, source + + +def generate(env): + env.Append( + BUILDERS={ + "VersionBuilder": Builder( + action=Action( + "${PYTHON3} ${ROOT_DIR.abspath}/scripts/version.py generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir ${ROOT_DIR}", + "${VERSIONCOMSTR}", + ), + emitter=version_emitter, + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/fwbin.py b/site_scons/site_tools/fwbin.py new file mode 100644 index 00000000..848571e3 --- /dev/null +++ b/site_scons/site_tools/fwbin.py @@ -0,0 +1,52 @@ +from SCons.Builder import Builder +from SCons.Action import Action +import SCons + +__OBJCOPY_ARM_BIN = "arm-none-eabi-objcopy" + + +def generate(env): + env.SetDefault( + BIN2DFU="${ROOT_DIR.abspath}/scripts/bin2dfu.py", + OBJCOPY=__OBJCOPY_ARM_BIN, # FIXME + ) + env.Append( + BUILDERS={ + "HEXBuilder": Builder( + action=Action( + '${OBJCOPY} -O ihex "${SOURCE}" "${TARGET}"', + "${HEXCOMSTR}", + ), + suffix=".hex", + src_suffix=".elf", + ), + "BINBuilder": Builder( + action=Action( + '${OBJCOPY} -O binary -S "${SOURCE}" "${TARGET}"', + "${BINCOMSTR}", + ), + suffix=".bin", + src_suffix=".elf", + ), + "DFUBuilder": Builder( + action=Action( + '${PYTHON3} ${BIN2DFU} -i "${SOURCE}" -o "${TARGET}" -a ${IMAGE_BASE_ADDRESS} -l "Flipper Zero F${TARGET_HW}"', + "${DFUCOMSTR}", + ), + suffix=".dfu", + src_suffix=".bin", + ), + } + ) + + +def exists(env): + try: + return env["OBJCOPY"] + except KeyError: + pass + + if objcopy := env.WhereIs(__OBJCOPY_ARM_BIN): + return objcopy + + raise SCons.Errors.StopError("Could not detect objcopy for arm") diff --git a/site_scons/site_tools/gdb.py b/site_scons/site_tools/gdb.py new file mode 100644 index 00000000..e7b6bdd6 --- /dev/null +++ b/site_scons/site_tools/gdb.py @@ -0,0 +1,33 @@ +from SCons.Builder import Builder +from SCons.Action import Action + + +def generate(env): + env.SetDefault( + GDB="gdb", + GDBPY="gdb-py", + GDBOPTS="", + GDBPYOPTS="", + GDBCOM="$GDB $GDBOPTS $SOURCES", # no $TARGET + GDBPYCOM="$GDBPY $GDBOPTS $GDBPYOPTS $SOURCES", # no $TARGET + ) + env.Append( + BUILDERS={ + "GDB": Builder( + action=Action( + "${GDBCOM}", + "${GDBCOMSTR}", + ), + ), + "GDBPy": Builder( + action=Action( + "${GDBPYCOM}", + "${GDBPYCOMSTR}", + ), + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/objdump.py b/site_scons/site_tools/objdump.py new file mode 100644 index 00000000..f5fa938a --- /dev/null +++ b/site_scons/site_tools/objdump.py @@ -0,0 +1,26 @@ +from SCons.Builder import Builder +from SCons.Action import Action + + +def generate(env): + env.SetDefault( + OBJDUMP="objdump", + OBJDUMPFLAGS=[], + OBJDUMPCOM="$OBJDUMP $OBJDUMPFLAGS -S $SOURCES > $TARGET", + ) + env.Append( + BUILDERS={ + "ObjDump": Builder( + action=Action( + "${OBJDUMPCOM}", + "${OBJDUMPCOMSTR}", + ), + suffix=".lst", + src_suffix=".elf", + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/openocd.py b/site_scons/site_tools/openocd.py new file mode 100644 index 00000000..135e1100 --- /dev/null +++ b/site_scons/site_tools/openocd.py @@ -0,0 +1,48 @@ +from SCons.Builder import Builder +from SCons.Action import Action +from SCons.Defaults import Touch +import SCons + +__OPENOCD_BIN = "openocd" + +_oocd_action = Action( + "${OPENOCD} ${OPENOCD_OPTS} ${OPENOCD_COMMAND}", + "${OOCDCOMSTR}", +) + + +def generate(env): + env.SetDefault( + OPENOCD=__OPENOCD_BIN, + OPENOCD_OPTS="", + OPENOCD_COMMAND="", + OOCDCOMSTR="", + ) + + env.Append( + BUILDERS={ + "OOCDFlashCommand": Builder( + action=[ + _oocd_action, + Touch("${TARGET}"), + ], + suffix=".flash", + src_suffix=".bin", + ), + "OOCDCommand": Builder( + action=_oocd_action, + ), + } + ) + + +def exists(env): + try: + return env["OPENOCD"] + except KeyError: + pass + + if openocd := env.WhereIs(__OPENOCD_BIN): + return openocd + + raise SCons.Errors.StopError("Could not detect openocd") diff --git a/site_scons/site_tools/python3.py b/site_scons/site_tools/python3.py new file mode 100644 index 00000000..8ac5490d --- /dev/null +++ b/site_scons/site_tools/python3.py @@ -0,0 +1,13 @@ +def generate(env): + py_name = "python3" + if env["PLATFORM"] == "win32": + # On Windows, Python 3 executable is usually just "python" + py_name = "python" + + env.SetDefault( + PYTHON3=py_name, + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/sconsmodular.py b/site_scons/site_tools/sconsmodular.py new file mode 100644 index 00000000..eeb90022 --- /dev/null +++ b/site_scons/site_tools/sconsmodular.py @@ -0,0 +1,38 @@ +import posixpath +import os + + +def BuildModule(env, module): + src_dir = str(env.Dir(".").srcdir or os.getcwd()) + module_sconscript = posixpath.join(src_dir, module, "SConscript") + if not os.path.exists(module_sconscript): + module_sconscript = posixpath.join(src_dir, f"{module}.scons") + if not os.path.exists(module_sconscript): + print(f"Cannot build module {module}: scons file not found") + Exit(2) + + return env.SConscript( + module_sconscript, + variant_dir=posixpath.join(env.subst("$BUILD_DIR"), module), + duplicate=0, + ) + + +def BuildModules(env, modules): + result = [] + for module in modules: + build_res = env.BuildModule(module) + # print("module ", module, build_res) + if build_res is None: + continue + result.append(build_res) + return result + + +def generate(env): + env.AddMethod(BuildModule) + env.AddMethod(BuildModules) + + +def exists(env): + return True diff --git a/site_scons/site_tools/sconsrecursiveglob.py b/site_scons/site_tools/sconsrecursiveglob.py new file mode 100644 index 00000000..32ff55ea --- /dev/null +++ b/site_scons/site_tools/sconsrecursiveglob.py @@ -0,0 +1,25 @@ +import SCons + + +def GlobRecursive(env, pattern, node=".", exclude=None): + results = [] + if isinstance(node, str): + node = env.Dir(node) + for f in node.glob("*", source=True, exclude=exclude): + if isinstance(f, SCons.Node.FS.Dir): + results += env.GlobRecursive(pattern, f, exclude) + results += node.glob( + pattern, + source=True, + exclude=exclude, + ) + # print(f"Glob for {pattern} from {node}: {results}") + return results + + +def generate(env): + env.AddMethod(GlobRecursive) + + +def exists(env): + return True diff --git a/site_scons/site_tools/size.py b/site_scons/site_tools/size.py new file mode 100644 index 00000000..56d4f3c9 --- /dev/null +++ b/site_scons/site_tools/size.py @@ -0,0 +1,24 @@ +from SCons.Builder import Builder +from SCons.Action import Action + + +def generate(env): + env.SetDefault( + SIZE="size", + SIZEFLAGS=[], + SIZECOM="$SIZE $SIZEFLAGS $TARGETS", + ) + env.Append( + BUILDERS={ + "ELFSize": Builder( + action=Action( + "${SIZECOM}", + "${SIZECOMSTR}", + ), + ), + } + ) + + +def exists(env): + return True diff --git a/site_scons/site_tools/strip.py b/site_scons/site_tools/strip.py new file mode 100644 index 00000000..053956f2 --- /dev/null +++ b/site_scons/site_tools/strip.py @@ -0,0 +1,26 @@ +from SCons.Builder import Builder +from SCons.Action import Action + + +def generate(env): + env.SetDefault( + STRIP="strip", + STRIPFLAGS=[], + STRIPCOM="$STRIP $STRIPFLAGS $SOURCES -o $TARGET", + ) + env.Append( + BUILDERS={ + "ELFStripper": Builder( + action=Action( + "${STRIPCOM}", + "${STRIPCOMSTR}", + ), + suffix=".elf", + src_suffix=".elf", + ), + } + ) + + +def exists(env): + return True