diff --git a/.github/workflow_data/hotfix.py b/.github/workflow_data/hotfix.py index fd04d7151..0a5c6793d 100644 --- a/.github/workflow_data/hotfix.py +++ b/.github/workflow_data/hotfix.py @@ -12,37 +12,37 @@ if __name__ == "__main__": event = json.load(f) release = requests.get( - event["repository"]["releases_url"].rsplit("{/")[0] + "latest", + event["repository"]["releases_url"].rsplit("{/")[0] + "/latest", headers={ "Accept": "application/vnd.github.v3+json", "Authorization": f"token {os.environ['GITHUB_TOKEN']}" } ).json() - artifacts = ( - os.environ['ARTIFACT_TGZ'], - os.environ['ARTIFACT_ZIP'] - ) + artifacts = { + os.environ['ARTIFACT_TGZ']: "application/gzip", + os.environ['ARTIFACT_ZIP']: "application/zip" + } for asset in release["assets"]: - if asset["name"] in artifacts: - req = requests.delete( - asset["url"], - headers={ - "Accept": "application/vnd.github.v3+json", - "Authorization": f"token {os.environ['GITHUB_TOKEN']}" - } - ) - if not req.ok: - print(f"{req.url = }\n{req.status_code = }\n{req.content = }") - sys.exit(1) + req = requests.delete( + asset["url"], + headers={ + "Accept": "application/vnd.github.v3+json", + "Authorization": f"token {os.environ['GITHUB_TOKEN']}" + } + ) + if not req.ok: + print(f"{req.url = }\n{req.status_code = }\n{req.content = }") + sys.exit(1) - for artifact in artifacts: + for artifact, mediatype in artifacts.items(): req = requests.post( release["upload_url"].rsplit("{?", 1)[0], headers={ "Accept": "application/vnd.github.v3+json", - "Authorization": f"token {os.environ['GITHUB_TOKEN']}" + "Authorization": f"token {os.environ['GITHUB_TOKEN']}", + "Content-Type": mediatype }, params={ "name": artifact @@ -59,14 +59,19 @@ if __name__ == "__main__": body = release["body"] body = re.sub( - r"(https://lab\.flipper\.net/\?url=).*?(&channel=XFW-Updater&version=" + os.environ['VERSION_TAG'] + r")", - r"\1" + os.environ['ARTIFACT_WEB'] + r"\2", + r"(https://lab\.flipper\.net/\?url=).*?(&channel=XFW-Updater&version=)[A-Za-z0-9_-]+", + r"\1" + os.environ['ARTIFACT_WEB'] + r"\2" + os.environ['VERSION_TAG'], + body + ) + body = re.sub( + r"(https://github\.com/ClaraCrazy/Flipper-Xtreme/releases/download/[A-Za-z0-9_-]+?/)[A-Za-z0-9_-]+", + r"\1" + os.environ['VERSION_TAG'], body ) body = body.replace("", "") insert = body.find("\n [//]: \n") - body = body[:insert] + hotfix + body[:insert] + body = body[:insert] + hotfix + body[insert:] req = requests.patch( release["url"], diff --git a/.github/workflow_data/webupdater.py b/.github/workflow_data/webupdater.py index eecbf2282..52005151a 100644 --- a/.github/workflow_data/webupdater.py +++ b/.github/workflow_data/webupdater.py @@ -5,7 +5,7 @@ if __name__ == "__main__": client = nextcloud_client.Client(os.environ["NC_HOST"]) client.login(os.environ["NC_USER"], os.environ["NC_PASS"]) file = os.environ["NC_FILE"] - path = os.environ["NC_PATH"] + file + path = os.environ["NC_PATH"] + "/" + file try: client.delete(path) except Exception: diff --git a/.github/workflows/hotfix.yml b/.github/workflows/hotfix.yml index 505f9c676..85bf00171 100644 --- a/.github/workflows/hotfix.yml +++ b/.github/workflows/hotfix.yml @@ -55,6 +55,8 @@ jobs: - name: "Upload hotfix" run: python .github/workflow_data/hotfix.py + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - name: "Merge pull request" uses: "pascalgn/automerge-action@v0.15.6" diff --git a/.gitignore b/.gitignore index d6a2dc470..48b5ed8b0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.swp *.swo *.gdb_history +*.old # LSP diff --git a/.gitmodules b/.gitmodules index 3a15177bd..671e7e2c4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ [submodule "lib/mlib"] path = lib/mlib url = https://github.com/P-p-H-d/mlib.git -[submodule "lib/STM32CubeWB"] - path = lib/STM32CubeWB - url = https://github.com/Flipper-Zero/STM32CubeWB.git [submodule "lib/littlefs"] path = lib/littlefs url = https://github.com/littlefs-project/littlefs.git @@ -34,3 +31,12 @@ [submodule "lib/heatshrink"] path = lib/heatshrink url = https://github.com/flipperdevices/heatshrink.git +[submodule "lib/st_cmsis_device_wb"] + path = lib/stm32wb_cmsis + url = https://github.com/STMicroelectronics/cmsis_device_wb +[submodule "lib/stm32wbxx_hal_driver"] + path = lib/stm32wb_hal + url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver +[submodule "lib/stm32wb_copro"] + path = lib/stm32wb_copro + url = https://github.com/flipperdevices/stm32wb_copro.git diff --git a/.pvsoptions b/.pvsoptions index ecb333dec..2b3946087 100644 --- a/.pvsoptions +++ b/.pvsoptions @@ -1 +1 @@ ---ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/xtreme -e lib/nanopb -e */arm-none-eabi/* -e applications/external/dap_link/lib/free-dap +--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/xtreme -e lib/nanopb -e */arm-none-eabi/* -e applications/external/dap_link/lib/free-dap diff --git a/.vscode/example/launch.json b/.vscode/example/launch.json index f7a9f8269..f4b7c6e48 100644 --- a/.vscode/example/launch.json +++ b/.vscode/example/launch.json @@ -11,11 +11,10 @@ "args": { "useSingleResult": true, "env": { - "PATH": "${workspaceFolder};${env:PATH}", - "FBT_QUIET": 1 + "PATH": "${workspaceFolder}${command:extension.commandvariable.envListSep}${env:PATH}" }, - "command": "fbt get_blackmagic", - "description": "Get Blackmagic device", + "command": "fbt -s get_blackmagic", + "description": "Get Blackmagic device" } } ], @@ -28,20 +27,21 @@ "type": "cortex-debug", "servertype": "openocd", "device": "stlink", - "svdFile": "./debug/STM32WB55_CM4.svd", + "svdFile": "./scripts/debug/STM32WB55_CM4.svd", // If you're debugging early in the boot process, before OS scheduler is running, // you have to comment out the following line. "rtos": "FreeRTOS", "configFiles": [ "interface/stlink.cfg", - "./debug/stm32wbx.cfg", + "./scripts/debug/stm32wbx.cfg", ], "postAttachCommands": [ + "source scripts/debug/flipperversion.py", + "fw-version", // "compare-sections", - "source debug/flipperapps.py", + "source scripts/debug/flipperapps.py", "fap-set-debug-elf-root build/latest/.extapps", - // "source debug/FreeRTOS/FreeRTOS.py", - // "svd_load debug/STM32WB55_CM4.svd" + // "source scripts/debug/FreeRTOS/FreeRTOS.py", ] // "showDevDebugOutput": "raw", }, @@ -53,14 +53,16 @@ "type": "cortex-debug", "servertype": "external", "gdbTarget": "${input:BLACKMAGIC}", - "svdFile": "./debug/STM32WB55_CM4.svd", + "svdFile": "./scripts/debug/STM32WB55_CM4.svd", "rtos": "FreeRTOS", "postAttachCommands": [ "monitor swdp_scan", "attach 1", "set confirm off", "set mem inaccessible-by-default off", - "source debug/flipperapps.py", + "source scripts/debug/flipperversion.py", + "fw-version", + "source scripts/debug/flipperapps.py", "fap-set-debug-elf-root build/latest/.extapps", // "compare-sections", ] @@ -75,10 +77,12 @@ "servertype": "jlink", "interface": "swd", "device": "STM32WB55RG", - "svdFile": "./debug/STM32WB55_CM4.svd", + "svdFile": "./scripts/debug/STM32WB55_CM4.svd", "rtos": "FreeRTOS", "postAttachCommands": [ - "source debug/flipperapps.py", + "source scripts/debug/flipperversion.py", + "fw-version", + "source scripts/debug/flipperapps.py", "fap-set-debug-elf-root build/latest/.extapps", ] // "showDevDebugOutput": "raw", @@ -91,27 +95,20 @@ "type": "cortex-debug", "servertype": "openocd", "device": "cmsis-dap", - "svdFile": "./debug/STM32WB55_CM4.svd", + "svdFile": "./scripts/debug/STM32WB55_CM4.svd", "rtos": "FreeRTOS", "configFiles": [ "interface/cmsis-dap.cfg", - "./debug/stm32wbx.cfg", + "./scripts/debug/stm32wbx.cfg", ], "postAttachCommands": [ - "source debug/flipperapps.py", + "source scripts/debug/flipperversion.py", + "fw-version", + "source scripts/debug/flipperapps.py", "fap-set-debug-elf-root build/latest/.extapps", ], // "showDevDebugOutput": "raw", }, - { - "name": "fbt debug", - "type": "python", - "request": "launch", - "program": "./lib/scons/scripts/scons.py", - "args": [ - "plugin_dist" - ] - }, { "name": "python debug", "type": "python", diff --git a/.vscode/extensions.json b/.vscode/extensions.json index b5791a91e..ead935b08 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -8,11 +8,12 @@ "amiralizadeh9480.cpp-helper", "marus25.cortex-debug", "zxh404.vscode-proto3", - "augustocdias.tasks-shell-input" + "augustocdias.tasks-shell-input", + "rioj7.command-variable" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [ "twxs.cmake", "ms-vscode.cmake-tools" ] -} +} \ No newline at end of file diff --git a/SConstruct b/SConstruct index 609b36af4..85e0241c6 100644 --- a/SConstruct +++ b/SConstruct @@ -239,19 +239,31 @@ distenv.PhonyTarget( ) # Debug alien elf +debug_other_opts = [ + "-ex", + "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py", + # "-ex", + # "source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py", + "-ex", + "source ${FBT_DEBUG_DIR}/flipperversion.py", + "-ex", + "fw-version", +] + distenv.PhonyTarget( "debug_other", "${GDBPYCOM}", GDBOPTS="${GDBOPTS_BASE}", GDBREMOTE="${OPENOCD_GDB_PIPE}", - GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ', + GDBPYOPTS=debug_other_opts, ) distenv.PhonyTarget( "debug_other_blackmagic", "${GDBPYCOM}", GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", - GDBREMOTE="$${BLACKMAGIC_ADDR}", + GDBREMOTE="${BLACKMAGIC_ADDR}", + GDBPYOPTS=debug_other_opts, ) @@ -335,3 +347,9 @@ vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*")) distenv.Precious(vscode_dist) distenv.NoClean(vscode_dist) distenv.Alias("vscode_dist", vscode_dist) + +# Configure shell with build tools +distenv.PhonyTarget( + "env", + "@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)", +) diff --git a/applications/debug/accessor/accessor_app.cpp b/applications/debug/accessor/accessor_app.cpp index 2e40b3c35..05a248efa 100644 --- a/applications/debug/accessor/accessor_app.cpp +++ b/applications/debug/accessor/accessor_app.cpp @@ -23,7 +23,7 @@ void AccessorApp::run(void) { exit = switch_to_previous_scene(); } } - }; + } scenes[current_scene]->on_exit(this); diff --git a/applications/debug/battery_test_app/views/battery_info.c b/applications/debug/battery_test_app/views/battery_info.c index 5353a2e2a..e32d1b461 100644 --- a/applications/debug/battery_test_app/views/battery_info.c +++ b/applications/debug/battery_test_app/views/battery_info.c @@ -17,7 +17,7 @@ static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) canvas_draw_box(canvas, x - 4, y + 16, 24, 6); canvas_set_color(canvas, ColorBlack); canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); -}; +} static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { char emote[20] = {}; @@ -85,7 +85,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header); canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value); -}; +} static void battery_info_draw_callback(Canvas* canvas, void* context) { furi_assert(context); diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index 54bdd5909..3b3a44431 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -1,10 +1,12 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -179,6 +181,153 @@ MU_TEST(nfc_digital_signal_test) { "NFC long digital signal test failed\r\n"); } +static bool nfc_test_pulse_reader_toggle( + uint32_t usec_low, + uint32_t usec_high, + uint32_t period_count, + uint32_t tolerance) { + furi_assert(nfc_test); + + bool success = false; + uint32_t pulses = 0; + const GpioPin* gpio_in = &gpio_ext_pa6; + const GpioPin* gpio_out = &gpio_ext_pa7; + PulseReader* reader = NULL; + + do { + reader = pulse_reader_alloc(gpio_in, 512); + + if(!reader) { + FURI_LOG_E(TAG, "failed to allocate pulse reader"); + break; + } + + /* use TIM1 to create a specific number of pulses with defined duty cycle + but first set the IO to high, so the low/high pulse can get detected */ + furi_hal_gpio_init(gpio_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + furi_hal_gpio_write(gpio_out, true); + + LL_TIM_DeInit(TIM1); + + LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP); + LL_TIM_SetRepetitionCounter(TIM1, 0); + LL_TIM_SetClockDivision(TIM1, LL_TIM_CLOCKDIVISION_DIV1); + LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL); + LL_TIM_DisableARRPreload(TIM1); + + LL_TIM_OC_DisablePreload(TIM1, LL_TIM_CHANNEL_CH1); + LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_PWM2); + LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH); + LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1); + LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1N); + + LL_TIM_EnableAllOutputs(TIM1); + + /* now calculate the TIM1 period and compare values */ + uint32_t freq_div = 64 * (usec_low + usec_high); + uint32_t prescaler = freq_div / 0x10000LU; + uint32_t period = freq_div / (prescaler + 1); + uint32_t compare = 64 * usec_low / (prescaler + 1); + + LL_TIM_SetPrescaler(TIM1, prescaler); + LL_TIM_SetAutoReload(TIM1, period - 1); + LL_TIM_SetCounter(TIM1, period - 1); + LL_TIM_OC_SetCompareCH1(TIM1, compare); + + /* timer is ready to launch, now start the pulse reader */ + pulse_reader_set_timebase(reader, PulseReaderUnitMicrosecond); + pulse_reader_start(reader); + + /* and quickly enable and switch over the GPIO to the generated signal */ + LL_TIM_EnableCounter(TIM1); + furi_hal_gpio_init_ex( + gpio_out, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn1TIM1); + + /* now it's time to parse the pulses received by the reader */ + uint32_t timer_pulses = period_count; + uint32_t prev_cnt = 0; + + while(timer_pulses > 0) { + /* whenever the counter gets reset, we went through a full period */ + uint32_t cur_cnt = LL_TIM_GetCounter(TIM1); + if(cur_cnt < prev_cnt) { + timer_pulses--; + } + prev_cnt = cur_cnt; + } + /* quickly halt the counter to keep a static signal */ + LL_TIM_DisableCounter(TIM1); + + do { + /* as all edges were sampled asynchronously, the timeout can be zero */ + uint32_t length = pulse_reader_receive(reader, 0); + + /* in the last pulse, we expect a "no edge" return value. if seen that, test succeeded. */ + if(pulses > period_count * 2) { + if(length != PULSE_READER_NO_EDGE) { + FURI_LOG_E( + TAG, + "last pulse expected to be PULSE_READER_NO_EDGE, but was %lu.", + length); + break; + } + success = true; + break; + } + + /* else we shall never see "no edge" or "lost edge" */ + if(length == PULSE_READER_NO_EDGE) { + FURI_LOG_E(TAG, "%lu. pulse not expected to be PULSE_READER_NO_EDGE", pulses); + break; + } + if(length == PULSE_READER_LOST_EDGE) { + FURI_LOG_E(TAG, "%lu. pulse not expected to be PULSE_READER_LOST_EDGE", pulses); + break; + } + + if(pulses > 0) { + /* throw away the first pulse, which is the 1->0 from the first start and will be irrelevant for our test */ + bool phase = ((pulses - 1) % 2) == 1; + uint32_t expected = phase ? usec_high : usec_low; + uint32_t deviation = abs((int32_t)length - (int32_t)expected); + + if(deviation > tolerance) { + FURI_LOG_E( + TAG, + "%lu. pulse expected %lu, but pulse was %lu.", + pulses, + expected, + length); + break; + } + } + pulses++; + } while(true); + } while(false); + + if(reader != NULL) { + pulse_reader_stop(reader); + pulse_reader_free(reader); + } + + LL_TIM_DeInit(TIM1); + furi_hal_gpio_init_simple(gpio_in, GpioModeAnalog); + furi_hal_gpio_init_simple(gpio_out, GpioModeAnalog); + + return success; +} + +MU_TEST(nfc_pulse_reader_test) { + mu_assert(nfc_test_pulse_reader_toggle(1500, 2500, 50, 10), "1 ms signal failed\r\n"); + mu_assert(nfc_test_pulse_reader_toggle(10000, 10000, 10, 10), "10 ms signal failed\r\n"); + mu_assert(nfc_test_pulse_reader_toggle(100000, 100000, 5, 50), "100 ms signal failed\r\n"); + mu_assert(nfc_test_pulse_reader_toggle(100, 900, 50, 10), "1 ms asymmetric signal failed\r\n"); + mu_assert( + nfc_test_pulse_reader_toggle(3333, 6666, 10, 10), "10 ms asymmetric signal failed\r\n"); + mu_assert( + nfc_test_pulse_reader_toggle(25000, 75000, 5, 10), "100 ms asymmetric signal failed\r\n"); +} + MU_TEST(mf_classic_dict_test) { MfClassicDict* instance = NULL; uint64_t key = 0; @@ -513,6 +662,7 @@ MU_TEST(mf_classic_4k_7b_file_test) { MU_TEST_SUITE(nfc) { nfc_test_alloc(); + MU_RUN_TEST(nfc_pulse_reader_test); MU_RUN_TEST(nfca_file_test); MU_RUN_TEST(mf_mini_file_test); MU_RUN_TEST(mf_classic_1k_4b_file_test); diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index c7e9c96f1..f1ab92653 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -407,7 +407,7 @@ MU_TEST(subghz_decoder_ido_test) { "Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n"); } -MU_TEST(subghz_decoder_keelog_test) { +MU_TEST(subghz_decoder_keeloq_test) { mu_assert( subghz_decoder_test( EXT_PATH("unit_tests/subghz/doorhan_raw.sub"), SUBGHZ_PROTOCOL_KEELOQ_NAME), @@ -676,7 +676,7 @@ MU_TEST(subghz_encoder_nice_flo_test) { "Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n"); } -MU_TEST(subghz_encoder_keelog_test) { +MU_TEST(subghz_encoder_keeloq_test) { mu_assert( subghz_encoder_test(EXT_PATH("unit_tests/subghz/doorhan.sub")), "Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n"); @@ -813,7 +813,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_gate_tx_test); MU_RUN_TEST(subghz_decoder_hormann_hsm_test); MU_RUN_TEST(subghz_decoder_ido_test); - MU_RUN_TEST(subghz_decoder_keelog_test); + MU_RUN_TEST(subghz_decoder_keeloq_test); MU_RUN_TEST(subghz_decoder_kia_seed_test); MU_RUN_TEST(subghz_decoder_nero_radio_test); MU_RUN_TEST(subghz_decoder_nero_sketch_test); @@ -852,7 +852,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_came_twee_test); MU_RUN_TEST(subghz_encoder_gate_tx_test); MU_RUN_TEST(subghz_encoder_nice_flo_test); - MU_RUN_TEST(subghz_encoder_keelog_test); + MU_RUN_TEST(subghz_encoder_keeloq_test); MU_RUN_TEST(subghz_encoder_linear_test); MU_RUN_TEST(subghz_encoder_linear_delta3_test); MU_RUN_TEST(subghz_encoder_megacode_test); diff --git a/applications/external/airmouse/tracking/util/matrix_4x4.h b/applications/external/airmouse/tracking/util/matrix_4x4.h index 9934f6be0..83f151fc4 100644 --- a/applications/external/airmouse/tracking/util/matrix_4x4.h +++ b/applications/external/airmouse/tracking/util/matrix_4x4.h @@ -34,4 +34,4 @@ private: } // namespace cardboard -#endif // CARDBOARD_SDK_UTIL_MATRIX4X4_H_ +#endif // CARDBOARD_SDK_UTIL_MATRIX_4X4_H_ diff --git a/applications/external/asteroids/application.fam b/applications/external/asteroids/application.fam index 5f70a0e1c..5eb43a6e5 100644 --- a/applications/external/asteroids/application.fam +++ b/applications/external/asteroids/application.fam @@ -8,8 +8,8 @@ App( stack_size=8 * 1024, order=50, fap_icon="appicon.png", - fap_icon_assets="assets", # Image assets to compile for this application fap_category="Games", + fap_icon_assets="assets", # Image assets to compile for this application fap_description="An implementation of the classic arcade game Asteroids", fap_author="antirez, SimplyMinimal", fap_weburl="https://github.com/SimplyMinimal/FlipperZero-Asteroids", diff --git a/applications/external/avr_isp_programmer/helpers/avr_isp.c b/applications/external/avr_isp_programmer/helpers/avr_isp.c index 283c17bfd..1b9e2fd1f 100644 --- a/applications/external/avr_isp_programmer/helpers/avr_isp.c +++ b/applications/external/avr_isp_programmer/helpers/avr_isp.c @@ -174,7 +174,7 @@ static void avr_isp_commit(AvrIsp* instance, uint16_t addr, uint8_t data) { while((furi_get_tick() - starttime) < 30) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { break; - }; + } } } } @@ -357,7 +357,7 @@ uint8_t avr_isp_read_lock_byte(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == data) { break; - }; + } data = 0x00; } return data; @@ -377,7 +377,7 @@ bool avr_isp_write_lock_byte(AvrIsp* instance, uint8_t lock) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_LOCK_BYTE) == lock) { ret = true; break; - }; + } } } return ret; @@ -392,7 +392,7 @@ uint8_t avr_isp_read_fuse_low(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == data) { break; - }; + } data = 0x00; } return data; @@ -412,7 +412,7 @@ bool avr_isp_write_fuse_low(AvrIsp* instance, uint8_t lfuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_LOW) == lfuse) { ret = true; break; - }; + } } } return ret; @@ -427,7 +427,7 @@ uint8_t avr_isp_read_fuse_high(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == data) { break; - }; + } data = 0x00; } return data; @@ -447,7 +447,7 @@ bool avr_isp_write_fuse_high(AvrIsp* instance, uint8_t hfuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_HIGH) == hfuse) { ret = true; break; - }; + } } } return ret; @@ -462,7 +462,7 @@ uint8_t avr_isp_read_fuse_extended(AvrIsp* instance) { data = avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED); if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == data) { break; - }; + } data = 0x00; } return data; @@ -482,7 +482,7 @@ bool avr_isp_write_fuse_extended(AvrIsp* instance, uint8_t efuse) { if(avr_isp_spi_transaction(instance, AVR_ISP_READ_FUSE_EXTENDED) == efuse) { ret = true; break; - }; + } } } return ret; diff --git a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c index 0f46872dd..051d97e9c 100644 --- a/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c +++ b/applications/external/avr_isp_programmer/lib/driver/avr_isp_prog.c @@ -111,7 +111,7 @@ static uint8_t avr_isp_prog_getch(AvrIspProg* instance) { uint8_t data[1] = {0}; while(furi_stream_buffer_receive(instance->stream_rx, &data, sizeof(int8_t), 30) == 0) { if(instance->exit) break; - }; + } return data[0]; } @@ -348,7 +348,7 @@ static void avr_isp_prog_commit(AvrIspProg* instance, uint16_t addr, uint8_t dat while((furi_get_tick() - starttime) < 30) { if(avr_isp_prog_spi_transaction(instance, AVR_ISP_READ_FLASH_HI(addr)) != 0xFF) { break; - }; + } } } } diff --git a/applications/external/barcode_gen/barcode_utils.c b/applications/external/barcode_gen/barcode_utils.c index 0a4770045..502014d85 100644 --- a/applications/external/barcode_gen/barcode_utils.c +++ b/applications/external/barcode_gen/barcode_utils.c @@ -98,7 +98,7 @@ const char* get_error_code_name(ErrorCode error_code) { return "OK"; default: return "Unknown Code"; - }; + } } const char* get_error_code_message(ErrorCode error_code) { @@ -121,5 +121,5 @@ const char* get_error_code_message(ErrorCode error_code) { return "OK"; default: return "Could not read barcode data"; - }; + } } \ No newline at end of file diff --git a/applications/external/bomberduck/LICENSE b/applications/external/bomberduck/LICENSE new file mode 100644 index 000000000..4624b249c --- /dev/null +++ b/applications/external/bomberduck/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2023 лень + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/applications/external/bomberduck/application.fam b/applications/external/bomberduck/application.fam new file mode 100644 index 000000000..d2ee5564b --- /dev/null +++ b/applications/external/bomberduck/application.fam @@ -0,0 +1,14 @@ +App( + appid="bomberduck", + name="Bomberduck", + apptype=FlipperAppType.EXTERNAL, + entry_point="bomberduck_app", + requires=[ + "gui", + ], + stack_size=1 * 1024, + order=90, + fap_icon="bomb.png", + fap_category="Games", + fap_icon_assets="assets", +) diff --git a/applications/external/bomberduck/assets/bomb0.png b/applications/external/bomberduck/assets/bomb0.png new file mode 100644 index 000000000..3fdc3a3c1 Binary files /dev/null and b/applications/external/bomberduck/assets/bomb0.png differ diff --git a/applications/external/bomberduck/assets/bomb1.png b/applications/external/bomberduck/assets/bomb1.png new file mode 100644 index 000000000..11d05b9b7 Binary files /dev/null and b/applications/external/bomberduck/assets/bomb1.png differ diff --git a/applications/external/bomberduck/assets/bomb2.png b/applications/external/bomberduck/assets/bomb2.png new file mode 100644 index 000000000..38ce7c732 Binary files /dev/null and b/applications/external/bomberduck/assets/bomb2.png differ diff --git a/applications/external/bomberduck/assets/box.png b/applications/external/bomberduck/assets/box.png new file mode 100644 index 000000000..bbd352b6f Binary files /dev/null and b/applications/external/bomberduck/assets/box.png differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_1.png b/applications/external/bomberduck/assets/end.png similarity index 61% rename from assets/dolphin/external/L3_Sunflower_128x64/frame_1.png rename to applications/external/bomberduck/assets/end.png index 999e5af17..d634933b7 100644 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_1.png and b/applications/external/bomberduck/assets/end.png differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_2.png b/applications/external/bomberduck/assets/enemy1.png similarity index 59% rename from assets/dolphin/external/L3_Sunflower_128x64/frame_2.png rename to applications/external/bomberduck/assets/enemy1.png index fa2782f2d..7ee7cb27f 100644 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_2.png and b/applications/external/bomberduck/assets/enemy1.png differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_5.png b/applications/external/bomberduck/assets/enemyleft.png similarity index 57% rename from assets/dolphin/external/L3_Sunflower_128x64/frame_5.png rename to applications/external/bomberduck/assets/enemyleft.png index e8303b575..bb85dfbb2 100644 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_5.png and b/applications/external/bomberduck/assets/enemyleft.png differ diff --git a/applications/external/bomberduck/assets/enemyright.png b/applications/external/bomberduck/assets/enemyright.png new file mode 100644 index 000000000..45e6a861a Binary files /dev/null and b/applications/external/bomberduck/assets/enemyright.png differ diff --git a/applications/external/bomberduck/assets/explore.png b/applications/external/bomberduck/assets/explore.png new file mode 100644 index 000000000..5eb50b669 Binary files /dev/null and b/applications/external/bomberduck/assets/explore.png differ diff --git a/applications/external/bomberduck/assets/playerleft.png b/applications/external/bomberduck/assets/playerleft.png new file mode 100644 index 000000000..86997a985 Binary files /dev/null and b/applications/external/bomberduck/assets/playerleft.png differ diff --git a/applications/external/bomberduck/assets/playerright.png b/applications/external/bomberduck/assets/playerright.png new file mode 100644 index 000000000..1a6283d9c Binary files /dev/null and b/applications/external/bomberduck/assets/playerright.png differ diff --git a/applications/external/bomberduck/assets/unbreakbox.png b/applications/external/bomberduck/assets/unbreakbox.png new file mode 100644 index 000000000..5e65912d5 Binary files /dev/null and b/applications/external/bomberduck/assets/unbreakbox.png differ diff --git a/applications/external/bomberduck/bomb.png b/applications/external/bomberduck/bomb.png new file mode 100644 index 000000000..44b9bfdea Binary files /dev/null and b/applications/external/bomberduck/bomb.png differ diff --git a/applications/external/bomberduck/bomberduck.c b/applications/external/bomberduck/bomberduck.c new file mode 100644 index 000000000..8c38b1a9c --- /dev/null +++ b/applications/external/bomberduck/bomberduck.c @@ -0,0 +1,643 @@ +#include +#include + +#include +#include +#include +#include +#include +#include "bomberduck_icons.h" + +int max(int a, int b) { + return (a > b) ? a : b; +} + +int min(int a, int b) { + return (a < b) ? a : b; +} + +#define WorldSizeX 12 +#define WorldSizeY 6 +#define BombRange 1 + +typedef struct { + FuriMutex* mutex; +} BomberState; + +typedef struct { + int row; + int col; +} Cell; + +typedef struct { + Cell cells[WorldSizeY * WorldSizeX]; + int front; + int rear; +} Queue; + +void enqueue(Queue* q, Cell c) { + q->cells[q->rear] = c; + q->rear++; +} + +Cell dequeue(Queue* q) { + Cell c = q->cells[q->front]; + q->front++; + + return c; +} + +bool is_empty(Queue* q) { + return q->front == q->rear; +} + +typedef struct { + int x; + int y; + int planted; +} Bomb; + +typedef struct { + int x; + int y; + bool side; +} Player; + +typedef struct { + int x; + int y; + int last; + bool side; + int level; +} Enemy; + +typedef struct { + int matrix[WorldSizeY][WorldSizeX]; + Player* player; + bool running; + int level; + + Enemy enemies[10]; + int enemies_count; + + Bomb bombs[100]; + int bombs_count; + + int endx; + int endy; +} World; + +Player player = {0, 0, 1}; +World world = {{{0}}, &player, 1, 0, {}, 0, {}, 0, 0, 0}; +bool vibration = false; + +void init() { + player.x = 1; + player.y = 1; + + world.endx = 4 + rand() % 8; + world.endy = rand() % 6; + for(int i = 0; i < WorldSizeY; i++) { + for(int j = 0; j < WorldSizeX; j++) { + world.matrix[i][j] = rand() % 3; + } + } + world.running = 1; + world.bombs_count = 0; + vibration = false; + for(int j = max(0, player.y - BombRange); j < min(WorldSizeY, player.y + BombRange + 1); j++) { + world.matrix[j][player.x] = 0; + } + + for(int j = max(0, player.x - BombRange); j < min(WorldSizeX, player.x + BombRange + 1); j++) { + world.matrix[player.y][j] = 0; + } + + world.enemies_count = 0; + for(int j = 0; j < rand() % 4 + world.level / 5; j++) { + Enemy enemy; + enemy.x = 4 + rand() % 7; + enemy.y = rand() % 6; + enemy.last = 0; + enemy.side = 1; + enemy.level = 0; + + world.enemies[j] = enemy; + world.enemies_count++; + + for(int m = max(0, world.enemies[j].y - BombRange); + m < min(WorldSizeY, world.enemies[j].y + BombRange + 1); + m++) { + world.matrix[m][world.enemies[j].x] = 0; + } + + for(int m = max(0, world.enemies[j].x - BombRange); + m < min(WorldSizeX, world.enemies[j].x + BombRange + 1); + m++) { + world.matrix[world.enemies[j].y][m] = 0; + } + } + world.matrix[world.endy][world.endx] = 1; +} + +const NotificationSequence end = { + &message_vibro_on, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_note_ds4, + &message_delay_10, + &message_sound_off, + &message_delay_10, + + &message_vibro_off, + NULL, +}; + +static const NotificationSequence bomb2 = { + &message_vibro_on, + &message_delay_25, + &message_vibro_off, + NULL, +}; + +static const NotificationSequence bomb_explore = { + &message_vibro_on, + &message_delay_50, + &message_vibro_off, + NULL, +}; + +static const NotificationSequence vibr1 = { + &message_vibro_on, + &message_delay_10, + &message_vibro_off, + &message_delay_10, + &message_vibro_on, + &message_delay_10, + &message_vibro_off, + &message_delay_10, + + NULL, +}; + +void intToStr(int num, char* str) { + int i = 0, sign = 0; + + if(num < 0) { + num = -num; + sign = 1; + } + + do { + str[i++] = num % 10 + '0'; + num /= 10; + } while(num > 0); + + if(sign) { + str[i++] = '-'; + } + + str[i] = '\0'; + + // Reverse the string + int j, len = i; + char temp; + for(j = 0; j < len / 2; j++) { + temp = str[j]; + str[j] = str[len - j - 1]; + str[len - j - 1] = temp; + } +} + +bool BFS() { + // Initialize visited array and queue + int visited[WorldSizeY][WorldSizeX] = {0}; + Queue q = {.front = 0, .rear = 0}; + // Mark the starting cell as visited and enqueue it + visited[world.player->y][world.player->x] = 1; + Cell startCell = {.row = world.player->y, .col = world.player->x}; + enqueue(&q, startCell); + // Traverse the field + while(!is_empty(&q)) { + // Dequeue a cell from the queue + Cell currentCell = dequeue(&q); + // Check if the current cell is the destination cell + if(currentCell.row == world.endy && currentCell.col == world.endx) { + return true; + } + // Check the neighboring cells + for(int rowOffset = -1; rowOffset <= 1; rowOffset++) { + for(int colOffset = -1; colOffset <= 1; colOffset++) { + // Skip diagonals and the current cell + if(rowOffset == 0 && colOffset == 0) { + continue; + } + if(rowOffset != 0 && colOffset != 0) { + continue; + } + // Calculate the row and column of the neighboring cell + int neighborRow = currentCell.row + rowOffset; + int neighborCol = currentCell.col + colOffset; + // Skip out-of-bounds cells and already visited cells + if(neighborRow < 0 || neighborRow >= WorldSizeY || neighborCol < 0 || + neighborCol >= WorldSizeX) { + continue; + } + if(visited[neighborRow][neighborCol]) { + continue; + } + // Mark the neighboring cell as visited and enqueue it + if(world.matrix[neighborRow][neighborCol] != 2) { + visited[neighborRow][neighborCol] = 1; + Cell neighborCell = {.row = neighborRow, .col = neighborCol}; + enqueue(&q, neighborCell); + } + } + } + } + return false; +} + +static void draw_callback(Canvas* canvas, void* ctx) { + furi_assert(ctx); + const BomberState* bomber_state = ctx; + + furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); + if(!BFS()) { + init(); + } + canvas_clear(canvas); + + canvas_draw_icon(canvas, world.endx * 10 + 4, world.endy * 10 + 2, &I_end); + + if(world.running) { + for(size_t i = 0; i < WorldSizeY; i++) { + for(size_t j = 0; j < WorldSizeX; j++) { + switch(world.matrix[i][j]) { + case 0: + break; + case 1: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_box); + break; + case 2: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_unbreakbox); + break; + case 3: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb0); + break; + case 4: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb1); + break; + case 5: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_bomb2); + break; + case 6: + canvas_draw_icon(canvas, j * 10 + 4, i * 10 + 2, &I_explore); + world.matrix[i][j] = 0; + break; + } + } + } + + if(world.player->side) { + canvas_draw_icon( + canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerright); + } else { + canvas_draw_icon( + canvas, world.player->x * 10 + 4, world.player->y * 10 + 2, &I_playerleft); + } + + for(int i = 0; i < world.enemies_count; i++) { + if(world.enemies[i].level > 0) { + canvas_draw_icon( + canvas, world.enemies[i].x * 10 + 4, world.enemies[i].y * 10 + 2, &I_enemy1); + } else { + if(world.enemies[i].side) { + canvas_draw_icon( + canvas, + world.enemies[i].x * 10 + 4, + world.enemies[i].y * 10 + 2, + &I_enemyright); + } else { + canvas_draw_icon( + canvas, + world.enemies[i].x * 10 + 4, + world.enemies[i].y * 10 + 2, + &I_enemyleft); + } + } + } + } else { + canvas_set_font(canvas, FontPrimary); + if(world.player->x == world.endx && world.player->y == world.endy) { + if(world.level == 20) { + canvas_draw_str(canvas, 30, 35, "You win!"); + } else { + canvas_draw_str(canvas, 30, 35, "Next level!"); + char str[20]; + intToStr(world.level, str); + canvas_draw_str(canvas, 90, 35, str); + } + + } else { + canvas_draw_str(canvas, 30, 35, "You died :("); + } + } + + furi_mutex_release(bomber_state->mutex); +} + +static void input_callback(InputEvent* input_event, void* ctx) { + // Проверяем, что контекст не нулевой + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + + furi_message_queue_put(event_queue, input_event, FuriWaitForever); +} + +int32_t bomberduck_app(void* p) { + UNUSED(p); + + // Текущее событие типа InputEvent + InputEvent event; + // Очередь событий на 8 элементов размера InputEvent + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); + + BomberState* bomber_state = malloc(sizeof(BomberState)); + + bomber_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); // Alloc Mutex + if(!bomber_state->mutex) { + FURI_LOG_E("BomberDuck", "cannot create mutex\r\n"); + furi_message_queue_free(event_queue); + free(bomber_state); + return 255; + } + + // Создаем новый view port + ViewPort* view_port = view_port_alloc(); + // Создаем callback отрисовки, без контекста + view_port_draw_callback_set(view_port, draw_callback, bomber_state); + // Создаем callback нажатий на клавиши, в качестве контекста передаем + // нашу очередь сообщений, чтоб запихивать в неё эти события + view_port_input_callback_set(view_port, input_callback, event_queue); + + // Создаем GUI приложения + Gui* gui = furi_record_open(RECORD_GUI); + // Подключаем view port к GUI в полноэкранном режиме + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message_block(notification, &sequence_display_backlight_enforce_on); + + init(); + + // Бесконечный цикл обработки очереди событий + while(1) { + if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) { + furi_mutex_acquire(bomber_state->mutex, FuriWaitForever); + // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения + + if(event.type == InputTypePress) { + if(event.key == InputKeyOk) { + if(world.running) { + if(world.matrix[world.player->y][world.player->x] == 0 && + world.bombs_count < 2) { + notification_message(notification, &bomb2); + world.matrix[world.player->y][world.player->x] = 3; + Bomb bomb = {world.player->x, world.player->y, furi_get_tick()}; + world.bombs[world.bombs_count] = bomb; + world.bombs_count++; + } + } else { + init(); + } + } + if(world.running) { + if(event.key == InputKeyUp) { + if(world.player->y > 0 && + world.matrix[world.player->y - 1][world.player->x] == 0) + world.player->y--; + } + if(event.key == InputKeyDown) { + if(world.player->y < WorldSizeY - 1 && + world.matrix[world.player->y + 1][world.player->x] == 0) + world.player->y++; + } + if(event.key == InputKeyLeft) { + world.player->side = 0; + if(world.player->x > 0 && + world.matrix[world.player->y][world.player->x - 1] == 0) + world.player->x--; + } + if(event.key == InputKeyRight) { + world.player->side = 1; + if(world.player->x < WorldSizeX - 1 && + world.matrix[world.player->y][world.player->x + 1] == 0) + world.player->x++; + } + } + } else if(event.type == InputTypeLong) { + if(event.key == InputKeyBack) { + break; + } + } + } + if(world.running) { + if(world.player->x == world.endx && world.player->y == world.endy) { + notification_message(notification, &end); + world.running = 0; + world.level += 1; + } + for(int i = 0; i < world.bombs_count; i++) { + if(furi_get_tick() - world.bombs[i].planted > + (unsigned long)max((3000 - world.level * 150), 1000)) { + vibration = false; + world.matrix[world.bombs[i].y][world.bombs[i].x] = 6; + notification_message(notification, &bomb_explore); + + for(int j = max(0, world.bombs[i].y - BombRange); + j < min(WorldSizeY, world.bombs[i].y + BombRange + 1); + j++) { + if(world.matrix[j][world.bombs[i].x] != 2) { + world.matrix[j][world.bombs[i].x] = 6; + if(j == world.player->y && world.bombs[i].x == world.player->x) { + notification_message(notification, &end); + world.running = 0; + } + for(int e = 0; e < world.enemies_count; e++) { + if(j == world.enemies[e].y && + world.bombs[i].x == world.enemies[e].x) { + if(world.enemies[e].level > 0) { + world.enemies[e].level--; + } else { + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + } + } + + for(int j = max(0, world.bombs[i].x - BombRange); + j < min(WorldSizeX, world.bombs[i].x + BombRange + 1); + j++) { + if(world.matrix[world.bombs[i].y][j] != 2) { + world.matrix[world.bombs[i].y][j] = 6; + if(world.bombs[i].y == world.player->y && j == world.player->x) { + notification_message(notification, &end); + world.running = 0; + } + for(int e = 0; e < world.enemies_count; e++) { + if(world.bombs[i].y == world.enemies[e].y && + j == world.enemies[e].x) { + if(world.enemies[e].level > 0) { + world.enemies[e].level--; + } else { + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + } + } + + for(int j = i; j < world.bombs_count - 1; j++) { + world.bombs[j] = world.bombs[j + 1]; + } + world.bombs_count--; + } else if( + furi_get_tick() - world.bombs[i].planted > + (unsigned long)max((3000 - world.level * 150) * 2 / 3, 666) && + world.matrix[world.bombs[i].y][world.bombs[i].x] != 5) { + world.matrix[world.bombs[i].y][world.bombs[i].x] = 5; + vibration = true; + + } else if( + furi_get_tick() - world.bombs[i].planted > + (unsigned long)max((3000 - world.level * 150) / 3, 333) && + world.matrix[world.bombs[i].y][world.bombs[i].x] != 4) { + world.matrix[world.bombs[i].y][world.bombs[i].x] = 4; + } + } + for(int e = 0; e < world.enemies_count; e++) { + if(world.player->y == world.enemies[e].y && + world.player->x == world.enemies[e].x) { + notification_message(notification, &end); + world.running = 0; + } + } + + for(int e = 0; e < world.enemies_count; e++) { + if(world.enemies[e].level > 0) { + if(furi_get_tick() - world.enemies[e].last > + (unsigned long)max((2000 - world.level * 100), 1000)) { + world.enemies[e].last = furi_get_tick(); + int move = rand() % 4; + switch(move) { + case 0: + if(world.enemies[e].y > 0 && + world.matrix[world.enemies[e].y - 1][world.enemies[e].x] != 2) + world.enemies[e].y--; + break; + case 1: + if(world.enemies[e].y < WorldSizeY - 1 && + world.matrix[world.enemies[e].y + 1][world.enemies[e].x] != 2) + world.enemies[e].y++; + break; + case 2: + world.enemies[e].side = 0; + if(world.enemies[e].x > 0 && + world.matrix[world.enemies[e].y][world.enemies[e].x - 1] != 2) + world.enemies[e].x--; + break; + case 3: + world.enemies[e].side = 1; + if(world.enemies[e].x < WorldSizeX - 1 && + world.matrix[world.enemies[e].y][world.enemies[e].x + 1] != 2) + world.enemies[e].x++; + default: + break; + } + } + } else { + if(furi_get_tick() - world.enemies[e].last > + (unsigned long)max((1000 - world.level * 50), 500)) { + world.enemies[e].last = furi_get_tick(); + int move = rand() % 4; + switch(move) { + case 0: + if(world.enemies[e].y > 0 && + world.matrix[world.enemies[e].y - 1][world.enemies[e].x] == 0) + world.enemies[e].y--; + break; + case 1: + if(world.enemies[e].y < WorldSizeY - 1 && + world.matrix[world.enemies[e].y + 1][world.enemies[e].x] == 0) + world.enemies[e].y++; + break; + case 2: + world.enemies[e].side = 0; + if(world.enemies[e].x > 0 && + world.matrix[world.enemies[e].y][world.enemies[e].x - 1] == 0) + world.enemies[e].x--; + break; + case 3: + world.enemies[e].side = 1; + if(world.enemies[e].x < WorldSizeX - 1 && + world.matrix[world.enemies[e].y][world.enemies[e].x + 1] == 0) + world.enemies[e].x++; + default: + break; + } + } + } + } + for(int e = 0; e < world.enemies_count; e++) { + for(int h = e + 1; h < world.enemies_count; h++) { + if(world.enemies[e].y == world.enemies[h].y && + world.enemies[e].x == world.enemies[h].x) { + world.enemies[h].level++; + for(int l = e; l < world.enemies_count - 1; l++) { + world.enemies[l] = world.enemies[l + 1]; + } + world.enemies_count--; + } + } + } + if(vibration) { + notification_message(notification, &vibr1); + } + } + + view_port_update(view_port); + furi_mutex_release(bomber_state->mutex); + } + + // Return to normal backlight settings + notification_message_block(notification, &sequence_display_backlight_enforce_auto); + furi_record_close(RECORD_NOTIFICATION); + // Специальная очистка памяти, занимаемой очередью + furi_message_queue_free(event_queue); + + // Чистим созданные объекты, связанные с интерфейсом + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + + furi_mutex_free(bomber_state->mutex); + furi_record_close(RECORD_GUI); + free(bomber_state); + + return 0; +} diff --git a/applications/external/bpmtapper/img/screenshot.png b/applications/external/bpmtapper/img/screenshot.png deleted file mode 100644 index fbba2aad9..000000000 Binary files a/applications/external/bpmtapper/img/screenshot.png and /dev/null differ diff --git a/applications/external/brainfuck/icons/DolphinCommon_56x48.png b/applications/external/brainfuck/icons/DolphinCommon_56x48.png deleted file mode 100644 index 089aaed83..000000000 Binary files a/applications/external/brainfuck/icons/DolphinCommon_56x48.png and /dev/null differ diff --git a/applications/external/brainfuck/icons/Text_10x10.png b/applications/external/brainfuck/icons/Text_10x10.png deleted file mode 100644 index 8e8a6183d..000000000 Binary files a/applications/external/brainfuck/icons/Text_10x10.png and /dev/null differ diff --git a/applications/external/brainfuck/worker.c b/applications/external/brainfuck/worker.c index 584bb9fb8..8fed94b40 100644 --- a/applications/external/brainfuck/worker.c +++ b/applications/external/brainfuck/worker.c @@ -111,7 +111,7 @@ void rShift() { memset((tmp + stackSize) - BF_STACK_STEP_SIZE, 0x00, BF_STACK_STEP_SIZE); bfStack = (uint8_t*)tmp; - }; + } if(stackPtr > stackSizeReal) { stackSizeReal = stackPtr; } diff --git a/applications/external/calculator/calculator.c b/applications/external/calculator/calculator.c index 1ca1d3a86..cc12cb7d1 100644 --- a/applications/external/calculator/calculator.c +++ b/applications/external/calculator/calculator.c @@ -199,7 +199,7 @@ void generate_calculator_layout(Canvas* canvas) { canvas_draw_str(canvas, 19, 118, " 0"); canvas_draw_str(canvas, 35, 118, " ."); canvas_draw_str(canvas, 51, 118, " ="); -}; +} void calculator_draw_callback(Canvas* canvas, void* ctx) { furi_assert(ctx); diff --git a/applications/external/cli_bridge/cli_control.c b/applications/external/cli_bridge/cli_control.c index e159d7424..80a0fd490 100644 --- a/applications/external/cli_bridge/cli_control.c +++ b/applications/external/cli_bridge/cli_control.c @@ -72,12 +72,7 @@ void latch_tx_handler() { session.is_connected = &session_connected; cli_session_close(global_cli); cli_session_open(global_cli, &session); - // Unlock loader-lock - Loader* loader = furi_record_open(RECORD_LOADER); - Loader_internal* loader_i = (Loader_internal*)loader; - loader_i->lock_count = 0; furi_record_close(RECORD_CLI); - furi_record_close(RECORD_LOADER); } void unlatch_tx_handler(bool persist) { Cli* global_cli = furi_record_open(RECORD_CLI); @@ -106,4 +101,4 @@ void unlatch_tx_handler(bool persist) { // At this point, all cli_vcp functions should be back. furi_stream_buffer_free(rx_stream); furi_stream_buffer_free(tx_stream); -} \ No newline at end of file +} diff --git a/applications/external/cli_bridge/cligui_main.c b/applications/external/cli_bridge/cligui_main.c index 6b6ec2797..ef53203f0 100644 --- a/applications/external/cli_bridge/cligui_main.c +++ b/applications/external/cli_bridge/cligui_main.c @@ -65,7 +65,13 @@ static void input_callback_wrapper(InputEvent* event, void* context) { int32_t cligui_main(void* p) { UNUSED(p); - loader_unlock(furi_record_open(RECORD_LOADER)); + + // Unlock loader-lock and save app thread + FuriThread* temp_save_appthr; + Loader* loader = furi_record_open(RECORD_LOADER); + Loader_internal* loader_i = (Loader_internal*)loader; + temp_save_appthr = loader_i->app.thread; + loader_unlock(loader); furi_record_close(RECORD_LOADER); CliguiApp* cligui = malloc(sizeof(CliguiApp)); @@ -132,5 +138,12 @@ int32_t cligui_main(void* p) { free(cligui->data); free(cligui); + // Don't touch system loader!!! We restoring previous app thread here, we love kostily and velosipedy, bydlo kod forever! + + Loader* loader1 = furi_record_open(RECORD_LOADER); + Loader_internal* loader_ii = (Loader_internal*)loader1; + loader_ii->app.thread = temp_save_appthr; + furi_record_close(RECORD_LOADER); + return 0; } diff --git a/applications/external/cli_bridge/internal_defs.h b/applications/external/cli_bridge/internal_defs.h index 9840d008b..9758b9aae 100644 --- a/applications/external/cli_bridge/internal_defs.h +++ b/applications/external/cli_bridge/internal_defs.h @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include +#include typedef struct { FuriThreadStdoutWriteCallback write_callback; @@ -68,24 +72,32 @@ typedef struct { } ViewPort_internal; typedef struct { - FuriThreadId loader_thread; + Gui* gui; + ViewDispatcher* view_dispatcher; + Menu* primary_menu; + Submenu* settings_menu; - const void* application; - FuriThread* application_thread; - char* application_arguments; + void (*closed_callback)(void*); + void* closed_callback_context; - void* cli; - void* gui; + void (*click_callback)(const char*, void*); + void* click_callback_context; - void* view_dispatcher; - void* primary_menu; - void* plugins_menu; - void* debug_menu; - void* settings_menu; + FuriThread* thread; +} LoaderMenu_internal; - volatile uint8_t lock_count; +typedef struct { + char* args; + char* name; + FuriThread* thread; + bool insomniac; +} LoaderAppData_internal; - void* pubsub; +typedef struct { + FuriPubSub* pubsub; + FuriMessageQueue* queue; + LoaderMenu_internal* loader_menu; + LoaderAppData_internal app; } Loader_internal; typedef struct { diff --git a/applications/external/doom/assets/screenshot1.png b/applications/external/doom/assets/screenshot1.png deleted file mode 100644 index 1ecb073a6..000000000 Binary files a/applications/external/doom/assets/screenshot1.png and /dev/null differ diff --git a/applications/external/doom/assets/screenshot2.png b/applications/external/doom/assets/screenshot2.png deleted file mode 100644 index 216b699de..000000000 Binary files a/applications/external/doom/assets/screenshot2.png and /dev/null differ diff --git a/applications/external/doom/assets/screenshot3.png b/applications/external/doom/assets/screenshot3.png deleted file mode 100644 index b5aec03fd..000000000 Binary files a/applications/external/doom/assets/screenshot3.png and /dev/null differ diff --git a/applications/external/doom/doom_music_player_worker.c b/applications/external/doom/doom_music_player_worker.c index e81549625..c8b9bb9db 100644 --- a/applications/external/doom/doom_music_player_worker.c +++ b/applications/external/doom/doom_music_player_worker.c @@ -393,7 +393,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { FURI_LOG_E(TAG, "Unable to open file"); break; - }; + } uint16_t ret = 0; do { diff --git a/applications/external/flipfrid/flipfrid.c b/applications/external/flipfrid/flipfrid.c index 25bdac024..172a98ef3 100644 --- a/applications/external/flipfrid/flipfrid.c +++ b/applications/external/flipfrid/flipfrid.c @@ -121,9 +121,6 @@ void flipfrid_free(FlipFridState* flipfrid) { furi_string_free(flipfrid->main_menu_proto_items[i]); } - free(flipfrid->data); - free(flipfrid->payload); - // The rest free(flipfrid); } diff --git a/applications/external/flipfrid/scene/flipfrid_scene_run_attack.c b/applications/external/flipfrid/scene/flipfrid_scene_run_attack.c index 6c726832a..225752559 100644 --- a/applications/external/flipfrid/scene/flipfrid_scene_run_attack.c +++ b/applications/external/flipfrid/scene/flipfrid_scene_run_attack.c @@ -356,7 +356,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) { stream_rewind(context->uids_stream); end_of_list = true; break; - }; + } if(furi_string_get_char(context->data_str, 0) == '#') continue; if(furi_string_size(context->data_str) != 11) break; break; @@ -370,7 +370,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) { notification_message(context->notify, &sequence_blink_stop); notification_message(context->notify, &sequence_error); break; - }; + } // string is valid, parse it in context->payload for(uint8_t i = 0; i < 5; i++) { @@ -394,7 +394,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) { stream_rewind(context->uids_stream); end_of_list = true; break; - }; + } if(furi_string_get_char(context->data_str, 0) == '#') continue; if(furi_string_size(context->data_str) != 9) break; break; @@ -408,7 +408,7 @@ void flipfrid_scene_run_attack_on_tick(FlipFridState* context) { notification_message(context->notify, &sequence_blink_stop); notification_message(context->notify, &sequence_error); break; - }; + } // string is valid, parse it in context->payload for(uint8_t i = 0; i < 4; i++) { diff --git a/applications/external/geiger/flipper_geiger.c b/applications/external/geiger/flipper_geiger.c index a5503eb90..9c3d0d3fc 100644 --- a/applications/external/geiger/flipper_geiger.c +++ b/applications/external/geiger/flipper_geiger.c @@ -39,33 +39,53 @@ typedef struct { static void draw_callback(Canvas* canvas, void* ctx) { furi_assert(ctx); - mutexStruct displayStruct; - mutexStruct* geigerMutex = ctx; - furi_mutex_acquire(geigerMutex->mutex, FuriWaitForever); - memcpy(&displayStruct, geigerMutex, sizeof(mutexStruct)); - furi_mutex_release(geigerMutex->mutex); + mutexStruct* mutexVal = ctx; + mutexStruct mutexDraw; + furi_mutex_acquire(mutexVal->mutex, FuriWaitForever); + memcpy(&mutexDraw, mutexVal, sizeof(mutexStruct)); + furi_mutex_release(mutexVal->mutex); char buffer[32]; - if(displayStruct.data == 0) - snprintf( - buffer, sizeof(buffer), "%ld cps - %ld cpm", displayStruct.cps, displayStruct.cpm); - else if(displayStruct.data == 1) + if(mutexDraw.data == 0) + snprintf(buffer, sizeof(buffer), "%ld cps - %ld cpm", mutexDraw.cps, mutexDraw.cpm); + else if(mutexDraw.data == 1) snprintf( buffer, sizeof(buffer), "%ld cps - %.2f uSv/h", - displayStruct.cps, - ((double)displayStruct.cpm * (double)CONVERSION_FACTOR)); - else + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR)); + else if(mutexDraw.data == 2) snprintf( buffer, sizeof(buffer), "%ld cps - %.2f mSv/y", - displayStruct.cps, - (((double)displayStruct.cpm * (double)CONVERSION_FACTOR)) * (double)8.76); + mutexDraw.cps, + (((double)mutexDraw.cpm * (double)CONVERSION_FACTOR)) * (double)8.76); + else if(mutexDraw.data == 3) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.4f Rad/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) / (double)10000); + else if(mutexDraw.data == 4) + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f mR/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) / (double)10); + else + snprintf( + buffer, + sizeof(buffer), + "%ld cps - %.2f uR/h", + mutexDraw.cps, + ((double)mutexDraw.cpm * (double)CONVERSION_FACTOR) * (double)100); for(int i = 0; i < SCREEN_SIZE_X; i += 2) { - float Y = SCREEN_SIZE_Y - (displayStruct.line[i / 2] * displayStruct.coef); + float Y = SCREEN_SIZE_Y - (mutexDraw.line[i / 2] * mutexDraw.coef); canvas_draw_line(canvas, i, Y, i, SCREEN_SIZE_Y); canvas_draw_line(canvas, i + 1, Y, i + 1, SCREEN_SIZE_Y); @@ -103,8 +123,7 @@ static void gpiocallback(void* ctx) { furi_message_queue_put(queue, &event, 0); } -int32_t flipper_geiger_app(void* p) { - UNUSED(p); +int32_t flipper_geiger_app() { EventApp event; FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp)); @@ -127,7 +146,7 @@ int32_t flipper_geiger_app(void* p) { } ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, &mutexVal); + view_port_draw_callback_set(view_port, draw_callback, &mutexVal.mutex); view_port_input_callback_set(view_port, input_callback, event_queue); furi_hal_gpio_add_int_callback(&gpio_ext_pa7, gpiocallback, event_queue); @@ -167,7 +186,7 @@ int32_t flipper_geiger_app(void* p) { if(mutexVal.data != 0) mutexVal.data--; else - mutexVal.data = 2; + mutexVal.data = 5; screenRefresh = 1; furi_mutex_release(mutexVal.mutex); @@ -175,7 +194,7 @@ int32_t flipper_geiger_app(void* p) { event.input.type == InputTypeShort)) { furi_mutex_acquire(mutexVal.mutex, FuriWaitForever); - if(mutexVal.data != 2) + if(mutexVal.data != 5) mutexVal.data++; else mutexVal.data = 0; diff --git a/applications/external/gpio_reader_a/GPIO_reader.c b/applications/external/gpioreader_a/GPIO_reader.c similarity index 100% rename from applications/external/gpio_reader_a/GPIO_reader.c rename to applications/external/gpioreader_a/GPIO_reader.c diff --git a/applications/external/gpio_reader_a/GPIO_reader_item.c b/applications/external/gpioreader_a/GPIO_reader_item.c similarity index 100% rename from applications/external/gpio_reader_a/GPIO_reader_item.c rename to applications/external/gpioreader_a/GPIO_reader_item.c diff --git a/applications/external/gpio_reader_a/GPIO_reader_item.h b/applications/external/gpioreader_a/GPIO_reader_item.h similarity index 100% rename from applications/external/gpio_reader_a/GPIO_reader_item.h rename to applications/external/gpioreader_a/GPIO_reader_item.h diff --git a/applications/external/gpio_reader_a/application.fam b/applications/external/gpioreader_a/application.fam similarity index 100% rename from applications/external/gpio_reader_a/application.fam rename to applications/external/gpioreader_a/application.fam diff --git a/applications/external/gpio_reader_a/icon.png b/applications/external/gpioreader_a/icon.png similarity index 100% rename from applications/external/gpio_reader_a/icon.png rename to applications/external/gpioreader_a/icon.png diff --git a/applications/external/gpio_reader_b/LICENSE b/applications/external/gpioreader_b/LICENSE similarity index 100% rename from applications/external/gpio_reader_b/LICENSE rename to applications/external/gpioreader_b/LICENSE diff --git a/applications/external/gpio_reader_b/application.fam b/applications/external/gpioreader_b/application.fam similarity index 100% rename from applications/external/gpio_reader_b/application.fam rename to applications/external/gpioreader_b/application.fam diff --git a/applications/external/gpio_reader_b/gpio_app.c b/applications/external/gpioreader_b/gpio_app.c similarity index 100% rename from applications/external/gpio_reader_b/gpio_app.c rename to applications/external/gpioreader_b/gpio_app.c diff --git a/applications/external/gpio_reader_b/gpio_app.h b/applications/external/gpioreader_b/gpio_app.h similarity index 100% rename from applications/external/gpio_reader_b/gpio_app.h rename to applications/external/gpioreader_b/gpio_app.h diff --git a/applications/external/gpio_reader_b/gpio_app_i.h b/applications/external/gpioreader_b/gpio_app_i.h similarity index 100% rename from applications/external/gpio_reader_b/gpio_app_i.h rename to applications/external/gpioreader_b/gpio_app_i.h diff --git a/applications/external/gpio_reader_b/gpio_custom_event.h b/applications/external/gpioreader_b/gpio_custom_event.h similarity index 100% rename from applications/external/gpio_reader_b/gpio_custom_event.h rename to applications/external/gpioreader_b/gpio_custom_event.h diff --git a/applications/external/gpio_reader_b/gpio_item.c b/applications/external/gpioreader_b/gpio_item.c similarity index 100% rename from applications/external/gpio_reader_b/gpio_item.c rename to applications/external/gpioreader_b/gpio_item.c diff --git a/applications/external/gpio_reader_b/gpio_item.h b/applications/external/gpioreader_b/gpio_item.h similarity index 100% rename from applications/external/gpio_reader_b/gpio_item.h rename to applications/external/gpioreader_b/gpio_item.h diff --git a/applications/external/gpio_reader_b/icon.png b/applications/external/gpioreader_b/icon.png similarity index 100% rename from applications/external/gpio_reader_b/icon.png rename to applications/external/gpioreader_b/icon.png diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene.c b/applications/external/gpioreader_b/scenes/gpio_scene.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene.c rename to applications/external/gpioreader_b/scenes/gpio_scene.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene.h b/applications/external/gpioreader_b/scenes/gpio_scene.h similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene.h rename to applications/external/gpioreader_b/scenes/gpio_scene.h diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_config.h b/applications/external/gpioreader_b/scenes/gpio_scene_config.h similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_config.h rename to applications/external/gpioreader_b/scenes/gpio_scene_config.h diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_reader.c b/applications/external/gpioreader_b/scenes/gpio_scene_reader.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_reader.c rename to applications/external/gpioreader_b/scenes/gpio_scene_reader.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_start.c b/applications/external/gpioreader_b/scenes/gpio_scene_start.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_start.c rename to applications/external/gpioreader_b/scenes/gpio_scene_start.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_test.c b/applications/external/gpioreader_b/scenes/gpio_scene_test.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_test.c rename to applications/external/gpioreader_b/scenes/gpio_scene_test.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart.c b/applications/external/gpioreader_b/scenes/gpio_scene_usb_uart.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart.c rename to applications/external/gpioreader_b/scenes/gpio_scene_usb_uart.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart_close_rpc.c b/applications/external/gpioreader_b/scenes/gpio_scene_usb_uart_close_rpc.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart_close_rpc.c rename to applications/external/gpioreader_b/scenes/gpio_scene_usb_uart_close_rpc.c diff --git a/applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart_config.c b/applications/external/gpioreader_b/scenes/gpio_scene_usb_uart_config.c similarity index 100% rename from applications/external/gpio_reader_b/scenes/gpio_scene_usb_uart_config.c rename to applications/external/gpioreader_b/scenes/gpio_scene_usb_uart_config.c diff --git a/applications/external/gpio_reader_b/usb_uart_bridge.c b/applications/external/gpioreader_b/usb_uart_bridge.c similarity index 100% rename from applications/external/gpio_reader_b/usb_uart_bridge.c rename to applications/external/gpioreader_b/usb_uart_bridge.c diff --git a/applications/external/gpio_reader_b/usb_uart_bridge.h b/applications/external/gpioreader_b/usb_uart_bridge.h similarity index 100% rename from applications/external/gpio_reader_b/usb_uart_bridge.h rename to applications/external/gpioreader_b/usb_uart_bridge.h diff --git a/applications/external/gpio_reader_b/views/gpio_reader.c b/applications/external/gpioreader_b/views/gpio_reader.c similarity index 100% rename from applications/external/gpio_reader_b/views/gpio_reader.c rename to applications/external/gpioreader_b/views/gpio_reader.c diff --git a/applications/external/gpio_reader_b/views/gpio_reader.h b/applications/external/gpioreader_b/views/gpio_reader.h similarity index 100% rename from applications/external/gpio_reader_b/views/gpio_reader.h rename to applications/external/gpioreader_b/views/gpio_reader.h diff --git a/applications/external/gpio_reader_b/views/gpio_test.c b/applications/external/gpioreader_b/views/gpio_test.c similarity index 100% rename from applications/external/gpio_reader_b/views/gpio_test.c rename to applications/external/gpioreader_b/views/gpio_test.c diff --git a/applications/external/gpio_reader_b/views/gpio_test.h b/applications/external/gpioreader_b/views/gpio_test.h similarity index 100% rename from applications/external/gpio_reader_b/views/gpio_test.h rename to applications/external/gpioreader_b/views/gpio_test.h diff --git a/applications/external/gpio_reader_b/views/gpio_usb_uart.c b/applications/external/gpioreader_b/views/gpio_usb_uart.c similarity index 98% rename from applications/external/gpio_reader_b/views/gpio_usb_uart.c rename to applications/external/gpioreader_b/views/gpio_usb_uart.c index f71dcccab..14f8c12fe 100644 --- a/applications/external/gpio_reader_b/views/gpio_usb_uart.c +++ b/applications/external/gpioreader_b/views/gpio_usb_uart.c @@ -82,7 +82,7 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) { if(model->rx_active) canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpFilled_14x15, IconRotation180); else - canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpFilled_14x15, IconRotation180); + canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpEmpty_14x15, IconRotation180); } static bool gpio_usb_uart_input_callback(InputEvent* event, void* context) { diff --git a/applications/external/gpio_reader_b/views/gpio_usb_uart.h b/applications/external/gpioreader_b/views/gpio_usb_uart.h similarity index 100% rename from applications/external/gpio_reader_b/views/gpio_usb_uart.h rename to applications/external/gpioreader_b/views/gpio_usb_uart.h diff --git a/applications/external/hex_viewer/hex_viewer.c b/applications/external/hex_viewer/hex_viewer.c index 50c34d634..bd4afa1a8 100644 --- a/applications/external/hex_viewer/hex_viewer.c +++ b/applications/external/hex_viewer/hex_viewer.c @@ -163,7 +163,7 @@ static bool hex_viewer_open_file(HexViewer* hex_viewer, const char* file_path) { FURI_LOG_E(TAG, "Unable to open stream: %s", file_path); isOk = false; break; - }; + } hex_viewer->model->file_size = stream_size(hex_viewer->model->stream); } while(false); diff --git a/applications/external/hid_app/hid.c b/applications/external/hid_app/hid.c index f29a3b22a..da0cb7857 100644 --- a/applications/external/hid_app/hid.c +++ b/applications/external/hid_app/hid.c @@ -9,10 +9,12 @@ enum HidDebugSubmenuIndex { HidSubmenuIndexKeynote, HidSubmenuIndexKeynoteVertical, HidSubmenuIndexKeyboard, + HidSubmenuIndexNumpad, HidSubmenuIndexMedia, HidSubmenuIndexTikTok, HidSubmenuIndexYTShorts, HidSubmenuIndexMouse, + HidSubmenuIndexMouseClicker, HidSubmenuIndexMouseJiggler, }; @@ -28,6 +30,9 @@ static void hid_submenu_callback(void* context, uint32_t index) { } else if(index == HidSubmenuIndexKeyboard) { app->view_id = HidViewKeyboard; view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeyboard); + } else if(index == HidSubmenuIndexNumpad) { + app->view_id = HidViewNumpad; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewNumpad); } else if(index == HidSubmenuIndexMedia) { app->view_id = HidViewMedia; view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMedia); @@ -40,6 +45,9 @@ static void hid_submenu_callback(void* context, uint32_t index) { } else if(index == HidSubmenuIndexYTShorts) { app->view_id = BtHidViewYTShorts; view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewYTShorts); + } else if(index == HidSubmenuIndexMouseClicker) { + app->view_id = HidViewMouseClicker; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseClicker); } else if(index == HidSubmenuIndexMouseJiggler) { app->view_id = HidViewMouseJiggler; view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler); @@ -60,8 +68,10 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con hid_keynote_set_connected_status(hid->hid_keynote, connected); hid_keynote_vertical_set_connected_status(hid->hid_keynote_vertical, connected); hid_keyboard_set_connected_status(hid->hid_keyboard, connected); + hid_numpad_set_connected_status(hid->hid_numpad, connected); hid_media_set_connected_status(hid->hid_media, connected); hid_mouse_set_connected_status(hid->hid_mouse, connected); + hid_mouse_clicker_set_connected_status(hid->hid_mouse_clicker, connected); hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected); hid_tiktok_set_connected_status(hid->hid_tiktok, connected); hid_ytshorts_set_connected_status(hid->hid_ytshorts, connected); @@ -118,6 +128,8 @@ Hid* hid_alloc(HidTransport transport) { app); submenu_add_item( app->device_type_submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_submenu_callback, app); + submenu_add_item( + app->device_type_submenu, "Numpad", HidSubmenuIndexNumpad, hid_submenu_callback, app); submenu_add_item( app->device_type_submenu, "Media", HidSubmenuIndexMedia, hid_submenu_callback, app); submenu_add_item( @@ -136,6 +148,12 @@ Hid* hid_alloc(HidTransport transport) { hid_submenu_callback, app); } + submenu_add_item( + app->device_type_submenu, + "Mouse Clicker", + HidSubmenuIndexMouseClicker, + hid_submenu_callback, + app); submenu_add_item( app->device_type_submenu, "Mouse Jiggler", @@ -185,6 +203,12 @@ Hid* hid_app_alloc_view(void* context) { view_dispatcher_add_view( app->view_dispatcher, HidViewKeyboard, hid_keyboard_get_view(app->hid_keyboard)); + //Numpad keyboard view + app->hid_numpad = hid_numpad_alloc(app); + view_set_previous_callback(hid_numpad_get_view(app->hid_numpad), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, HidViewNumpad, hid_numpad_get_view(app->hid_numpad)); + // Media view app->hid_media = hid_media_alloc(app); view_set_previous_callback(hid_media_get_view(app->hid_media), hid_exit_confirm_view); @@ -209,6 +233,15 @@ Hid* hid_app_alloc_view(void* context) { view_dispatcher_add_view( app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse)); + // Mouse clicker view + app->hid_mouse_clicker = hid_mouse_clicker_alloc(app); + view_set_previous_callback( + hid_mouse_clicker_get_view(app->hid_mouse_clicker), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, + HidViewMouseClicker, + hid_mouse_clicker_get_view(app->hid_mouse_clicker)); + // Mouse jiggler view app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app); view_set_previous_callback( @@ -240,10 +273,14 @@ void hid_free(Hid* app) { hid_keynote_vertical_free(app->hid_keynote_vertical); view_dispatcher_remove_view(app->view_dispatcher, HidViewKeyboard); hid_keyboard_free(app->hid_keyboard); + view_dispatcher_remove_view(app->view_dispatcher, HidViewNumpad); + hid_numpad_free(app->hid_numpad); view_dispatcher_remove_view(app->view_dispatcher, HidViewMedia); hid_media_free(app->hid_media); view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse); hid_mouse_free(app->hid_mouse); + view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseClicker); + hid_mouse_clicker_free(app->hid_mouse_clicker); view_dispatcher_remove_view(app->view_dispatcher, HidViewMouseJiggler); hid_mouse_jiggler_free(app->hid_mouse_jiggler); view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok); diff --git a/applications/external/hid_app/hid.h b/applications/external/hid_app/hid.h index be9176a28..472200683 100644 --- a/applications/external/hid_app/hid.h +++ b/applications/external/hid_app/hid.h @@ -19,13 +19,15 @@ #include "views/hid_keynote.h" #include "views/hid_keynote_vertical.h" #include "views/hid_keyboard.h" +#include "views/hid_numpad.h" #include "views/hid_media.h" #include "views/hid_mouse.h" #include "views/hid_mouse_jiggler.h" #include "views/hid_tiktok.h" #include "views/hid_ytshorts.h" +#include "views/hid_mouse_clicker.h" -#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" +#include "hid_path.h" typedef enum { HidTransportUsb, @@ -44,8 +46,10 @@ struct Hid { HidKeynote* hid_keynote; HidKeynoteVertical* hid_keynote_vertical; HidKeyboard* hid_keyboard; + HidNumpad* hid_numpad; HidMedia* hid_media; HidMouse* hid_mouse; + HidMouseClicker* hid_mouse_clicker; HidMouseJiggler* hid_mouse_jiggler; HidTikTok* hid_tiktok; HidYTShorts* hid_ytshorts; diff --git a/applications/external/hid_app/hid_path.h b/applications/external/hid_app/hid_path.h new file mode 100644 index 000000000..ed4ec45ff --- /dev/null +++ b/applications/external/hid_app/hid_path.h @@ -0,0 +1,3 @@ +#pragma once + +#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" diff --git a/applications/external/hid_app/views.h b/applications/external/hid_app/views.h index 81e8d6dbe..2ec17bb33 100644 --- a/applications/external/hid_app/views.h +++ b/applications/external/hid_app/views.h @@ -3,8 +3,10 @@ typedef enum { HidViewKeynote, HidViewKeynoteVertical, HidViewKeyboard, + HidViewNumpad, HidViewMedia, HidViewMouse, + HidViewMouseClicker, HidViewMouseJiggler, BtHidViewTikTok, BtHidViewYTShorts, diff --git a/applications/external/hid_app/views/hid_mouse_clicker.c b/applications/external/hid_app/views/hid_mouse_clicker.c new file mode 100644 index 000000000..d85affc43 --- /dev/null +++ b/applications/external/hid_app/views/hid_mouse_clicker.c @@ -0,0 +1,214 @@ +#include "hid_mouse_clicker.h" +#include +#include "../hid.h" + +#include "hid_icons.h" + +#define TAG "HidMouseClicker" +#define DEFAULT_CLICK_RATE 1 +#define MAXIMUM_CLICK_RATE 60 + +struct HidMouseClicker { + View* view; + Hid* hid; + FuriTimer* timer; +}; + +typedef struct { + bool connected; + bool running; + int rate; + HidTransport transport; +} HidMouseClickerModel; + +static void hid_mouse_clicker_start_or_restart_timer(void* context) { + furi_assert(context); + HidMouseClicker* hid_mouse_clicker = context; + + if(furi_timer_is_running(hid_mouse_clicker->timer)) { + furi_timer_stop(hid_mouse_clicker->timer); + } + + with_view_model( + hid_mouse_clicker->view, + HidMouseClickerModel * model, + { + furi_timer_start( + hid_mouse_clicker->timer, furi_kernel_get_tick_frequency() / model->rate); + }, + true); +} + +static void hid_mouse_clicker_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + HidMouseClickerModel* model = context; + + // Header + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } + } + + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Clicker"); + + // Ok + canvas_draw_icon(canvas, 63, 25, &I_Space_65x18); + if(model->running) { + canvas_set_font(canvas, FontPrimary); + + FuriString* rate_label = furi_string_alloc(); + furi_string_printf(rate_label, "%d clicks/s\n\nUp / Down", model->rate); + elements_multiline_text(canvas, AlignLeft, 35, furi_string_get_cstr(rate_label)); + canvas_set_font(canvas, FontSecondary); + furi_string_free(rate_label); + + elements_slightly_rounded_box(canvas, 66, 27, 60, 13); + canvas_set_color(canvas, ColorWhite); + } else { + canvas_set_font(canvas, FontPrimary); + elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto start\nclicking"); + canvas_set_font(canvas, FontSecondary); + } + canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9); + if(model->running) { + elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop"); + } else { + elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start"); + } + canvas_set_color(canvas, ColorBlack); + + // Back + canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8); + elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit"); +} + +static void hid_mouse_clicker_timer_callback(void* context) { + furi_assert(context); + HidMouseClicker* hid_mouse_clicker = context; + with_view_model( + hid_mouse_clicker->view, + HidMouseClickerModel * model, + { + if(model->running) { + hid_hal_mouse_press(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT); + hid_hal_mouse_release(hid_mouse_clicker->hid, HID_MOUSE_BTN_LEFT); + } + }, + false); +} + +static void hid_mouse_clicker_enter_callback(void* context) { + hid_mouse_clicker_start_or_restart_timer(context); +} + +static void hid_mouse_clicker_exit_callback(void* context) { + furi_assert(context); + HidMouseClicker* hid_mouse_clicker = context; + furi_timer_stop(hid_mouse_clicker->timer); +} + +static bool hid_mouse_clicker_input_callback(InputEvent* event, void* context) { + furi_assert(context); + HidMouseClicker* hid_mouse_clicker = context; + + bool consumed = false; + bool rate_changed = false; + + if(event->type != InputTypeShort && event->type != InputTypeRepeat) { + return false; + } + + with_view_model( + hid_mouse_clicker->view, + HidMouseClickerModel * model, + { + switch(event->key) { + case InputKeyOk: + model->running = !model->running; + consumed = true; + break; + case InputKeyUp: + if(model->rate < MAXIMUM_CLICK_RATE) { + model->rate++; + } + rate_changed = true; + consumed = true; + break; + case InputKeyDown: + if(model->rate > 1) { + model->rate--; + } + rate_changed = true; + consumed = true; + break; + default: + consumed = true; + break; + } + }, + true); + + if(rate_changed) { + hid_mouse_clicker_start_or_restart_timer(context); + } + + return consumed; +} + +HidMouseClicker* hid_mouse_clicker_alloc(Hid* hid) { + HidMouseClicker* hid_mouse_clicker = malloc(sizeof(HidMouseClicker)); + + hid_mouse_clicker->view = view_alloc(); + view_set_context(hid_mouse_clicker->view, hid_mouse_clicker); + view_allocate_model( + hid_mouse_clicker->view, ViewModelTypeLocking, sizeof(HidMouseClickerModel)); + view_set_draw_callback(hid_mouse_clicker->view, hid_mouse_clicker_draw_callback); + view_set_input_callback(hid_mouse_clicker->view, hid_mouse_clicker_input_callback); + view_set_enter_callback(hid_mouse_clicker->view, hid_mouse_clicker_enter_callback); + view_set_exit_callback(hid_mouse_clicker->view, hid_mouse_clicker_exit_callback); + + hid_mouse_clicker->hid = hid; + + hid_mouse_clicker->timer = furi_timer_alloc( + hid_mouse_clicker_timer_callback, FuriTimerTypePeriodic, hid_mouse_clicker); + + with_view_model( + hid_mouse_clicker->view, + HidMouseClickerModel * model, + { + model->transport = hid->transport; + model->rate = DEFAULT_CLICK_RATE; + }, + true); + + return hid_mouse_clicker; +} + +void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker) { + furi_assert(hid_mouse_clicker); + + furi_timer_stop(hid_mouse_clicker->timer); + furi_timer_free(hid_mouse_clicker->timer); + + view_free(hid_mouse_clicker->view); + + free(hid_mouse_clicker); +} + +View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker) { + furi_assert(hid_mouse_clicker); + return hid_mouse_clicker->view; +} + +void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected) { + furi_assert(hid_mouse_clicker); + with_view_model( + hid_mouse_clicker->view, + HidMouseClickerModel * model, + { model->connected = connected; }, + true); +} diff --git a/applications/external/hid_app/views/hid_mouse_clicker.h b/applications/external/hid_app/views/hid_mouse_clicker.h new file mode 100644 index 000000000..d72847baa --- /dev/null +++ b/applications/external/hid_app/views/hid_mouse_clicker.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidMouseClicker HidMouseClicker; + +HidMouseClicker* hid_mouse_clicker_alloc(Hid* bt_hid); + +void hid_mouse_clicker_free(HidMouseClicker* hid_mouse_clicker); + +View* hid_mouse_clicker_get_view(HidMouseClicker* hid_mouse_clicker); + +void hid_mouse_clicker_set_connected_status(HidMouseClicker* hid_mouse_clicker, bool connected); diff --git a/applications/external/hid_app/views/hid_mouse_jiggler.c b/applications/external/hid_app/views/hid_mouse_jiggler.c index 120d5bc34..09c14c668 100644 --- a/applications/external/hid_app/views/hid_mouse_jiggler.c +++ b/applications/external/hid_app/views/hid_mouse_jiggler.c @@ -6,8 +6,6 @@ #define TAG "HidMouseJiggler" -#define LENGTH(x) (int)(sizeof(x) / sizeof((x)[0])) - struct HidMouseJiggler { View* view; Hid* hid; @@ -44,7 +42,7 @@ static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) { elements_multiline_text(canvas, AlignLeft, 26, "Interval (ms):"); canvas_set_font(canvas, FontSecondary); if(model->interval_idx != 0) canvas_draw_icon(canvas, 74, 19, &I_ButtonLeft_4x7); - if(model->interval_idx != LENGTH(intervals) - 1) + if(model->interval_idx != (int)COUNT_OF(intervals) - 1) canvas_draw_icon(canvas, 80, 19, &I_ButtonRight_4x7); FuriString* interval_str = furi_string_alloc_printf("%d", intervals[model->interval_idx]); elements_multiline_text(canvas, 91, 26, furi_string_get_cstr(interval_str)); @@ -116,7 +114,7 @@ static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) { consumed = true; } if(event->type == InputTypePress && event->key == InputKeyRight && !model->running && - model->interval_idx < LENGTH(intervals) - 1) { + model->interval_idx < (int)COUNT_OF(intervals) - 1) { model->interval_idx++; consumed = true; } diff --git a/applications/external/hid_app/views/hid_numpad.c b/applications/external/hid_app/views/hid_numpad.c new file mode 100644 index 000000000..d3b488801 --- /dev/null +++ b/applications/external/hid_app/views/hid_numpad.c @@ -0,0 +1,302 @@ +#include "hid_numpad.h" +#include +#include +#include +#include "../hid.h" +#include "hid_icons.h" + +#define TAG "HidNumpad" + +struct HidNumpad { + View* view; + Hid* hid; +}; + +typedef struct { + uint8_t last_x; + uint8_t last_y; + uint8_t x; + uint8_t y; + uint8_t last_key_code; + uint16_t modifier_code; + bool ok_pressed; + bool back_pressed; + bool connected; + char key_string[5]; + HidTransport transport; +} HidNumpadModel; + +typedef struct { + uint8_t width; + char* key; + uint8_t height; + const Icon* icon; + uint8_t value; +} HidNumpadKey; + +typedef struct { + int8_t x; + int8_t y; +} HidNumpadPoint; + +#define MARGIN_TOP 0 +#define MARGIN_LEFT 24 +#define KEY_WIDTH 20 +#define KEY_HEIGHT 15 +#define KEY_PADDING 1 +#define ROW_COUNT 5 +#define COLUMN_COUNT 4 + +const HidNumpadKey hid_numpad_keyset[ROW_COUNT][COLUMN_COUNT] = { + { + {.width = 1, .height = 1, .icon = NULL, .key = "NL", .value = HID_KEYPAD_NUMLOCK}, + {.width = 1, .height = 1, .icon = NULL, .key = "/", .value = HID_KEYPAD_SLASH}, + {.width = 1, .height = 1, .icon = NULL, .key = "*", .value = HID_KEYPAD_ASTERISK}, + {.width = 1, .height = 1, .icon = NULL, .key = "-", .value = HID_KEYPAD_MINUS}, + }, + { + {.width = 1, .height = 1, .icon = NULL, .key = "7", .value = HID_KEYPAD_7}, + {.width = 1, .height = 1, .icon = NULL, .key = "8", .value = HID_KEYBOARD_8}, + {.width = 1, .height = 1, .icon = NULL, .key = "9", .value = HID_KEYBOARD_9}, + {.width = 1, .height = 2, .icon = NULL, .key = "+", .value = HID_KEYPAD_PLUS}, + }, + { + {.width = 1, .height = 1, .icon = NULL, .key = "4", .value = HID_KEYPAD_4}, + {.width = 1, .height = 1, .icon = NULL, .key = "5", .value = HID_KEYPAD_5}, + {.width = 1, .height = 1, .icon = NULL, .key = "6", .value = HID_KEYPAD_6}, + }, + { + {.width = 1, .height = 1, .icon = NULL, .key = "1", .value = HID_KEYPAD_1}, + {.width = 1, .height = 1, .icon = NULL, .key = "2", .value = HID_KEYPAD_2}, + {.width = 1, .height = 1, .icon = NULL, .key = "3", .value = HID_KEYPAD_3}, + {.width = 1, .height = 2, .icon = NULL, .key = "En", .value = HID_KEYPAD_ENTER}, + }, + { + {.width = 2, .height = 1, .icon = NULL, .key = "0", .value = HID_KEYBOARD_0}, + {.width = 0, .height = 0, .icon = NULL, .key = "0", .value = HID_KEYBOARD_0}, + {.width = 1, .height = 1, .icon = NULL, .key = ".", .value = HID_KEYPAD_DOT}, + }, +}; + +static void hid_numpad_draw_key( + Canvas* canvas, + HidNumpadModel* model, + uint8_t x, + uint8_t y, + HidNumpadKey key, + bool selected) { + if(!key.width || !key.height) return; + + canvas_set_color(canvas, ColorBlack); + uint8_t keyWidth = KEY_WIDTH * key.width + KEY_PADDING * (key.width - 1); + uint8_t keyHeight = KEY_HEIGHT * key.height + KEY_PADDING * (key.height - 1); + if(selected) { + elements_slightly_rounded_box( + canvas, + MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), + MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), + keyWidth, + keyHeight); + canvas_set_color(canvas, ColorWhite); + } else { + elements_slightly_rounded_frame( + canvas, + MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING), + MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING), + keyWidth, + keyHeight); + } + if(key.icon != NULL) { + canvas_draw_icon( + canvas, + MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 - key.icon->width / 2, + MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + keyHeight / 2 - key.icon->height / 2, + key.icon); + } else { + strcpy(model->key_string, key.key); + canvas_draw_str_aligned( + canvas, + MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 + 1, + MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + keyHeight / 2 + 1, + AlignCenter, + AlignCenter, + model->key_string); + } +} + +static void hid_numpad_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + HidNumpadModel* model = context; + + if((!model->connected) && (model->transport == HidTransportBle)) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + canvas_set_font(canvas, FontPrimary); + elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Numpad"); + + canvas_draw_icon(canvas, 68, 3, &I_Pin_back_arrow_10x8); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned(canvas, 127, 4, AlignRight, AlignTop, "Hold to exit"); + + elements_multiline_text_aligned( + canvas, 4, 60, AlignLeft, AlignBottom, "Waiting for Connection..."); + return; + } + + canvas_set_font(canvas, FontKeyboard); + uint8_t initY = model->y == 0 ? 0 : 1; + + if(model->y > 5) { + initY = model->y - 4; + } + + for(uint8_t y = initY; y < ROW_COUNT; y++) { + const HidNumpadKey* numpadKeyRow = hid_numpad_keyset[y]; + uint8_t x = 0; + for(uint8_t i = 0; i < COLUMN_COUNT; i++) { + HidNumpadKey key = numpadKeyRow[i]; + bool keySelected = (x <= model->x && model->x < (x + key.width)) && y == model->y; + bool backSelected = model->back_pressed && key.value == HID_KEYBOARD_DELETE; + hid_numpad_draw_key( + canvas, + model, + x, + y - initY, + key, + (!model->ok_pressed && keySelected) || backSelected); + x += key.width; + } + } +} + +static uint8_t hid_numpad_get_selected_key(HidNumpadModel* model) { + HidNumpadKey key = hid_numpad_keyset[model->y][model->x]; + return key.value; +} + +static void hid_numpad_get_select_key(HidNumpadModel* model, HidNumpadPoint delta) { + do { + const int delta_sum = model->y + delta.y; + model->y = delta_sum < 0 ? ROW_COUNT - 1 : delta_sum % ROW_COUNT; + } while(delta.y != 0 && hid_numpad_keyset[model->y][model->x].value == 0); + + do { + const int delta_sum = model->x + delta.x; + model->x = delta_sum < 0 ? COLUMN_COUNT - 1 : delta_sum % COLUMN_COUNT; + } while(delta.x != 0 && hid_numpad_keyset[model->y][model->x].width == 0); +} + +static void hid_numpad_process(HidNumpad* hid_numpad, InputEvent* event) { + with_view_model( + hid_numpad->view, + HidNumpadModel * model, + { + if(event->key == InputKeyOk) { + if(event->type == InputTypePress) { + model->ok_pressed = true; + } else if(event->type == InputTypeLong || event->type == InputTypeShort) { + model->last_key_code = hid_numpad_get_selected_key(model); + hid_hal_keyboard_press( + hid_numpad->hid, model->modifier_code | model->last_key_code); + } else if(event->type == InputTypeRelease) { + hid_hal_keyboard_release( + hid_numpad->hid, model->modifier_code | model->last_key_code); + model->ok_pressed = false; + } + } else if(event->key == InputKeyBack) { + if(event->type == InputTypePress) { + model->back_pressed = true; + } else if(event->type == InputTypeShort) { + hid_hal_keyboard_press(hid_numpad->hid, HID_KEYBOARD_DELETE); + hid_hal_keyboard_release(hid_numpad->hid, HID_KEYBOARD_DELETE); + } else if(event->type == InputTypeRelease) { + model->back_pressed = false; + } + } else if(event->type == InputTypePress || event->type == InputTypeRepeat) { + if(event->key == InputKeyUp) { + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 0, .y = -1}); + } else if(event->key == InputKeyDown) { + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 0, .y = 1}); + } else if(event->key == InputKeyLeft) { + if(model->last_x == 2 && model->last_y == 2 && model->y == 1 && + model->x == 3) { + model->x = model->last_x; + model->y = model->last_y; + } else if( + model->last_x == 2 && model->last_y == 4 && model->y == 3 && + model->x == 3) { + model->x = model->last_x; + model->y = model->last_y; + } else + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = -1, .y = 0}); + model->last_x = 0; + model->last_y = 0; + } else if(event->key == InputKeyRight) { + if(model->x == 2 && model->y == 2) { + model->last_x = model->x; + model->last_y = model->y; + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = -1}); + } else if(model->x == 2 && model->y == 4) { + model->last_x = model->x; + model->last_y = model->y; + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = -1}); + } else { + hid_numpad_get_select_key(model, (HidNumpadPoint){.x = 1, .y = 0}); + } + } + } + }, + true); +} + +static bool hid_numpad_input_callback(InputEvent* event, void* context) { + furi_assert(context); + HidNumpad* hid_numpad = context; + bool consumed = false; + + if(event->type == InputTypeLong && event->key == InputKeyBack) { + hid_hal_keyboard_release_all(hid_numpad->hid); + } else { + hid_numpad_process(hid_numpad, event); + consumed = true; + } + + return consumed; +} + +HidNumpad* hid_numpad_alloc(Hid* bt_hid) { + HidNumpad* hid_numpad = malloc(sizeof(HidNumpad)); + hid_numpad->view = view_alloc(); + hid_numpad->hid = bt_hid; + view_set_context(hid_numpad->view, hid_numpad); + view_allocate_model(hid_numpad->view, ViewModelTypeLocking, sizeof(HidNumpadModel)); + view_set_draw_callback(hid_numpad->view, hid_numpad_draw_callback); + view_set_input_callback(hid_numpad->view, hid_numpad_input_callback); + + with_view_model( + hid_numpad->view, + HidNumpadModel * model, + { + model->transport = bt_hid->transport; + model->y = 0; + }, + true); + + return hid_numpad; +} + +void hid_numpad_free(HidNumpad* hid_numpad) { + furi_assert(hid_numpad); + view_free(hid_numpad->view); + free(hid_numpad); +} + +View* hid_numpad_get_view(HidNumpad* hid_numpad) { + furi_assert(hid_numpad); + return hid_numpad->view; +} + +void hid_numpad_set_connected_status(HidNumpad* hid_numpad, bool connected) { + furi_assert(hid_numpad); + with_view_model( + hid_numpad->view, HidNumpadModel * model, { model->connected = connected; }, true); +} diff --git a/applications/external/hid_app/views/hid_numpad.h b/applications/external/hid_app/views/hid_numpad.h new file mode 100644 index 000000000..d9bf54df9 --- /dev/null +++ b/applications/external/hid_app/views/hid_numpad.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidNumpad HidNumpad; + +HidNumpad* hid_numpad_alloc(Hid* bt_hid); + +void hid_numpad_free(HidNumpad* hid_numpad); + +View* hid_numpad_get_view(HidNumpad* hid_numpad); + +void hid_numpad_set_connected_status(HidNumpad* hid_numpad, bool connected); diff --git a/applications/external/ibtn_fuzzer/ibtnfuzzer.c b/applications/external/ibtn_fuzzer/ibtnfuzzer.c index 880d3983b..9e6239b69 100644 --- a/applications/external/ibtn_fuzzer/ibtnfuzzer.c +++ b/applications/external/ibtn_fuzzer/ibtnfuzzer.c @@ -121,9 +121,6 @@ void ibtnfuzzer_free(iBtnFuzzerState* ibtnfuzzer) { furi_string_free(ibtnfuzzer->main_menu_proto_items[i]); } - free(ibtnfuzzer->data); - free(ibtnfuzzer->payload); - // The rest free(ibtnfuzzer); } diff --git a/applications/external/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c b/applications/external/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c index 13ec6e6be..53f2f694f 100644 --- a/applications/external/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c +++ b/applications/external/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c @@ -242,7 +242,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { stream_rewind(context->uids_stream); end_of_list = true; break; - }; + } if(furi_string_get_char(context->data_str, 0) == '#') continue; if(furi_string_size(context->data_str) != 17) break; break; @@ -256,7 +256,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { notification_message(context->notify, &sequence_blink_stop); notification_message(context->notify, &sequence_error); break; - }; + } // string is valid, parse it in context->payload for(uint8_t i = 0; i < 8; i++) { @@ -280,7 +280,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { stream_rewind(context->uids_stream); end_of_list = true; break; - }; + } if(furi_string_get_char(context->data_str, 0) == '#') continue; if(furi_string_size(context->data_str) != 5) break; break; @@ -294,7 +294,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { notification_message(context->notify, &sequence_blink_stop); notification_message(context->notify, &sequence_error); break; - }; + } // string is valid, parse it in context->payload for(uint8_t i = 0; i < 2; i++) { @@ -318,7 +318,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { stream_rewind(context->uids_stream); end_of_list = true; break; - }; + } if(furi_string_get_char(context->data_str, 0) == '#') continue; if(furi_string_size(context->data_str) != 9) break; break; @@ -332,7 +332,7 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { notification_message(context->notify, &sequence_blink_stop); notification_message(context->notify, &sequence_error); break; - }; + } // string is valid, parse it in context->payload for(uint8_t i = 0; i < 4; i++) { diff --git a/applications/external/ifttt/ifttt_virtual_button.c b/applications/external/ifttt/ifttt_virtual_button.c index e23b8715d..1d2d06416 100644 --- a/applications/external/ifttt/ifttt_virtual_button.c +++ b/applications/external/ifttt/ifttt_virtual_button.c @@ -38,6 +38,11 @@ void save_settings_file(FlipperFormat* file, Settings* settings) { Settings* load_settings() { Settings* settings = malloc(sizeof(Settings)); + settings->save_ssid = ""; + settings->save_password = ""; + settings->save_key = ""; + settings->save_event = ""; + Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -53,29 +58,14 @@ Settings* load_settings() { text_event_value = furi_string_alloc(); if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) != FSE_OK) { - if(!flipper_format_file_open_new(file, CONFIG_FILE_PATH)) { - flipper_format_file_close(file); - } else { - settings->save_ssid = malloc(1); - settings->save_password = malloc(1); - settings->save_key = malloc(1); - settings->save_event = malloc(1); - - settings->save_ssid[0] = '\0'; - settings->save_password[0] = '\0'; - settings->save_key[0] = '\0'; - settings->save_event[0] = '\0'; - + if(flipper_format_file_open_new(file, CONFIG_FILE_PATH)) { save_settings_file(file, settings); - flipper_format_file_close(file); } + flipper_format_file_close(file); } else { - if(!flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) { - flipper_format_file_close(file); - } else { + if(flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) { uint32_t value; - if(!flipper_format_read_header(file, string_value, &value)) { - } else { + if(flipper_format_read_header(file, string_value, &value)) { if(flipper_format_read_string(file, CONF_SSID, text_ssid_value)) { settings->save_ssid = malloc(furi_string_size(text_ssid_value) + 1); strcpy(settings->save_ssid, furi_string_get_cstr(text_ssid_value)); @@ -93,8 +83,8 @@ Settings* load_settings() { strcpy(settings->save_event, furi_string_get_cstr(text_event_value)); } } - flipper_format_file_close(file); } + flipper_format_file_close(file); } furi_string_free(text_ssid_value); @@ -139,7 +129,7 @@ void send_serial_command_config(ESerialCommand command, Settings* settings) { break; default: return; - }; + } furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); } @@ -248,4 +238,4 @@ int32_t ifttt_virtual_button_app(void* p) { view_dispatcher_run(app->view_dispatcher); ifttt_virtual_button_app_free(app); return 0; -} \ No newline at end of file +} diff --git a/applications/external/ifttt/views/send_view.c b/applications/external/ifttt/views/send_view.c index 6046c39e3..e1638e7a7 100644 --- a/applications/external/ifttt/views/send_view.c +++ b/applications/external/ifttt/views/send_view.c @@ -38,7 +38,7 @@ void send_serial_command_send(ESerialCommand command) { break; default: return; - }; + } furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1); } diff --git a/applications/external/metronome/img/screenshot.png b/applications/external/metronome/img/screenshot.png deleted file mode 100644 index 7b6916e81..000000000 Binary files a/applications/external/metronome/img/screenshot.png and /dev/null differ diff --git a/applications/external/metronome/metronome.c b/applications/external/metronome/metronome.c index a01f4418d..46231d66d 100644 --- a/applications/external/metronome/metronome.c +++ b/applications/external/metronome/metronome.c @@ -178,7 +178,7 @@ static void timer_callback(void* ctx) { case Silent: break; } - }; + } // this is a bit of a kludge... if we are on vibro and unpronounced, stop vibro after half the usual duration switch(metronome_state->output_mode) { diff --git a/applications/external/mfkey32/application.fam b/applications/external/mfkey32/application.fam index 47ae9c084..eb11aec2c 100644 --- a/applications/external/mfkey32/application.fam +++ b/applications/external/mfkey32/application.fam @@ -2,6 +2,7 @@ App( appid="mfkey32", name="Mfkey32", apptype=FlipperAppType.EXTERNAL, + targets=["f7"], entry_point="mfkey32_main", requires=[ "gui", diff --git a/applications/external/mfkey32/mfkey32.c b/applications/external/mfkey32/mfkey32.c index 48d6aa64f..d4b2d3e4a 100644 --- a/applications/external/mfkey32/mfkey32.c +++ b/applications/external/mfkey32/mfkey32.c @@ -1,8 +1,9 @@ #pragma GCC optimize("O3") #pragma GCC optimize("-funroll-all-loops") -// TODO: Handle back button correctly // TODO: Add keys to top of the user dictionary, not the bottom +// TODO: More efficient dictionary bruteforce by scanning through hardcoded very common keys and previously found dictionary keys first? +// (a cache for napi_key_already_found_for_nonce) #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc") #define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc") @@ -29,9 +31,7 @@ #define TAG "Mfkey32" #define NFC_MF_CLASSIC_KEY_LEN (13) -// MSB_LIMIT: Chunk size (out of 256) -#define MSB_LIMIT 16 -#define MIN_RAM 114500 +#define MIN_RAM 115632 #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) #define CONST_M1_1 (LF_POLY_EVEN << 1 | 1) @@ -40,9 +40,15 @@ #define CONST_M2_2 (LF_POLY_EVEN << 1 | 1) #define BIT(x, n) ((x) >> (n)&1) #define BEBIT(x, n) BIT(x, (n) ^ 24) -#define SWAPENDIAN(x) (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) +#define SWAPENDIAN(x) \ + ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) //#define SIZEOF(arr) sizeof(arr) / sizeof(*arr) +static int eta_round_time = 56; +static int eta_total_time = 900; +// MSB_LIMIT: Chunk size (out of 256) +static int MSB_LIMIT = 16; + struct Crypto1State { uint32_t odd, even; }; @@ -68,7 +74,6 @@ typedef struct { typedef enum { MissingNonces, ZeroNonces, - OutOfMemory, } MfkeyError; typedef enum { @@ -81,15 +86,20 @@ typedef enum { Help, } MfkeyState; +// TODO: Can we eliminate any of the members of this struct? typedef struct { FuriMutex* mutex; MfkeyError err; MfkeyState mfkey_state; int cracked; int unique_cracked; + int num_completed; int total; int dict_count; int search; + int eta_timestamp; + int eta_total; + int eta_round; bool is_thread_running; bool close_thread_please; FuriThread* mfkeythread; @@ -194,7 +204,7 @@ static inline uint32_t crypt_word(struct Crypto1State* s) { uint32_t res_ret = 0; uint32_t feedin, t; for(int i = 0; i <= 31; i++) { - res_ret |= (filter(s->odd) << (24 ^ i)); + res_ret |= (filter(s->odd) << (24 ^ i)); //-V629 feedin = LF_POLY_EVEN & s->even; feedin ^= LF_POLY_ODD & s->odd; s->even = s->even << 1 | (evenparity32(feedin)); @@ -431,6 +441,17 @@ int old_recover( return s; } +static inline int sync_state(ProgramState* program_state) { + int ts = furi_hal_rtc_get_timestamp(); + program_state->eta_round = program_state->eta_round - (ts - program_state->eta_timestamp); + program_state->eta_total = program_state->eta_total - (ts - program_state->eta_timestamp); + program_state->eta_timestamp = ts; + if(program_state->close_thread_please) { + return 1; + } + return 0; +} + int calculate_msb_tables( int oks, int eks, @@ -440,7 +461,8 @@ int calculate_msb_tables( struct Msb* odd_msbs, struct Msb* even_msbs, unsigned int* temp_states_odd, - unsigned int* temp_states_even) { + unsigned int* temp_states_even, + ProgramState* program_state) { //FURI_LOG_I(TAG, "MSB GO %i", msb_iter); // DEBUG unsigned int msb_head = (MSB_LIMIT * msb_round); // msb_iter ranges from 0 to (256/MSB_LIMIT)-1 unsigned int msb_tail = (MSB_LIMIT * (msb_round + 1)); @@ -452,10 +474,13 @@ int calculate_msb_tables( memset(even_msbs, 0, MSB_LIMIT * sizeof(struct Msb)); for(semi_state = 1 << 20; semi_state >= 0; semi_state--) { - //if (main_iter % 2048 == 0) { - // FURI_LOG_I(TAG, "On main_iter %i", main_iter); // DEBUG - //} - if(filter(semi_state) == (oks & 1)) { + if(semi_state % 32768 == 0) { + if(sync_state(program_state) == 1) { + return 0; + } + } + + if(filter(semi_state) == (oks & 1)) { //-V547 states_buffer[0] = semi_state; states_tail = state_loop(states_buffer, oks, CONST_M1_1, CONST_M2_1); @@ -478,7 +503,7 @@ int calculate_msb_tables( } } - if(filter(semi_state) == (eks & 1)) { + if(filter(semi_state) == (eks & 1)) { //-V547 states_buffer[0] = semi_state; states_tail = state_loop(states_buffer, eks, CONST_M1_2, CONST_M2_2); @@ -507,6 +532,12 @@ int calculate_msb_tables( eks >>= 12; for(i = 0; i < MSB_LIMIT; i++) { + if(sync_state(program_state) == 1) { + return 0; + } + // TODO: Why is this necessary? + memset(temp_states_even, 0, sizeof(unsigned int) * (1280)); + memset(temp_states_odd, 0, sizeof(unsigned int) * (1280)); memcpy(temp_states_odd, odd_msbs[i].states, odd_msbs[i].tail * sizeof(unsigned int)); memcpy(temp_states_even, even_msbs[i].states, even_msbs[i].tail * sizeof(unsigned int)); int res = old_recover( @@ -532,7 +563,8 @@ int calculate_msb_tables( return 0; } -int recover(struct Crypto1Params* p, int ks2, ProgramState* const program_state) { +bool recover(struct Crypto1Params* p, int ks2, ProgramState* program_state) { + bool found = false; unsigned int* states_buffer = malloc(sizeof(unsigned int) * (2 << 9)); struct Msb* odd_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb)); struct Msb* even_msbs = (struct Msb*)malloc(MSB_LIMIT * sizeof(struct Msb)); @@ -547,9 +579,12 @@ int recover(struct Crypto1Params* p, int ks2, ProgramState* const program_state) eks = eks << 1 | BEBIT(ks2, i); } int bench_start = furi_hal_rtc_get_timestamp(); + program_state->eta_total = eta_total_time; + program_state->eta_timestamp = bench_start; for(msb = 0; msb <= ((256 / MSB_LIMIT) - 1); msb++) { - //printf("MSB: %i\n", msb); program_state->search = msb; + program_state->eta_round = eta_round_time; + program_state->eta_total = eta_total_time - (eta_round_time * msb); if(calculate_msb_tables( oks, eks, @@ -559,18 +594,23 @@ int recover(struct Crypto1Params* p, int ks2, ProgramState* const program_state) odd_msbs, even_msbs, temp_states_odd, - temp_states_even)) { + temp_states_even, + program_state)) { int bench_stop = furi_hal_rtc_get_timestamp(); FURI_LOG_I(TAG, "Cracked in %i seconds", bench_stop - bench_start); - free(states_buffer); - free(odd_msbs); - free(even_msbs); - free(temp_states_odd); - free(temp_states_even); - return 1; + found = true; + break; + } + if(program_state->close_thread_please) { + break; } } - return 0; + free(states_buffer); + free(odd_msbs); + free(even_msbs); + free(temp_states_odd); + free(temp_states_even); + return found; } bool napi_mf_classic_dict_check_presence(MfClassicDictType dict_type) { @@ -820,8 +860,7 @@ MfClassicNonceArray* napi_mf_classic_nonce_array_alloc( MfClassicDict* system_dict, bool system_dict_exists, MfClassicDict* user_dict, - bool user_dict_exists, - ProgramState* const program_state) { + ProgramState* program_state) { MfClassicNonceArray* nonce_array = malloc(sizeof(MfClassicNonceArray)); MfClassicNonce* remaining_nonce_array_init = malloc(sizeof(MfClassicNonce) * 1); nonce_array->remaining_nonce_array = remaining_nonce_array_init; @@ -853,7 +892,7 @@ MfClassicNonceArray* napi_mf_classic_nonce_array_alloc( // Read total amount of nonces FuriString* next_line; next_line = furi_string_alloc(); - while(true) { + while(!(program_state->close_thread_please)) { if(!stream_read_line(nonce_array->stream, next_line)) { FURI_LOG_T(TAG, "No nonces left"); break; @@ -866,56 +905,59 @@ MfClassicNonceArray* napi_mf_classic_nonce_array_alloc( if(!furi_string_start_with_str(next_line, "Sec")) continue; const char* next_line_cstr = furi_string_get_cstr(next_line); MfClassicNonce res = {0}; - char token[20]; int i = 0; - const char* ptr = next_line_cstr; - while(sscanf(ptr, "%s", token) == 1) { + char* endptr; + for(i = 0; i <= 17; i++) { + if(i != 0) { + next_line_cstr = strchr(next_line_cstr, ' '); + if(next_line_cstr) { + next_line_cstr++; + } else { + break; + } + } + unsigned long value = strtoul(next_line_cstr, &endptr, 16); switch(i) { case 5: - sscanf(token, "%lx", &res.uid); + res.uid = value; break; case 7: - sscanf(token, "%lx", &res.nt0); + res.nt0 = value; break; case 9: - sscanf(token, "%lx", &res.nr0_enc); + res.nr0_enc = value; break; case 11: - sscanf(token, "%lx", &res.ar0_enc); + res.ar0_enc = value; break; case 13: - sscanf(token, "%lx", &res.nt1); + res.nt1 = value; break; case 15: - sscanf(token, "%lx", &res.nr1_enc); + res.nr1_enc = value; break; case 17: - sscanf(token, "%lx", &res.ar1_enc); + res.ar1_enc = value; break; default: break; // Do nothing } - i++; - ptr = strchr(ptr, ' '); - if(!ptr) { - break; - } - ptr++; + next_line_cstr = endptr; } (program_state->total)++; uint32_t p64b = prng_successor(res.nt1, 64); if((system_dict_exists && napi_key_already_found_for_nonce( system_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc)) || - (user_dict_exists && - napi_key_already_found_for_nonce( - user_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc))) { + (napi_key_already_found_for_nonce( + user_dict, res.uid ^ res.nt1, res.nr1_enc, p64b, res.ar1_enc))) { (program_state->cracked)++; + (program_state->num_completed)++; continue; } - FURI_LOG_I(TAG, "No key found for %lx %lx", res.uid, res.ar1_enc); + FURI_LOG_I(TAG, "No key found for %8lx %8lx", res.uid, res.ar1_enc); // TODO: Refactor - nonce_array->remaining_nonce_array = realloc( + nonce_array->remaining_nonce_array = realloc( //-V701 nonce_array->remaining_nonce_array, sizeof(MfClassicNonce) * ((nonce_array->remaining_nonces) + 1)); nonce_array->remaining_nonces++; @@ -923,14 +965,13 @@ MfClassicNonceArray* napi_mf_classic_nonce_array_alloc( nonce_array->total_nonces++; } furi_string_free(next_line); - stream_rewind(nonce_array->stream); + buffered_file_stream_close(nonce_array->stream); array_loaded = true; FURI_LOG_I(TAG, "Loaded %lu nonces", nonce_array->total_nonces); } while(false); if(!array_loaded) { - buffered_file_stream_close(nonce_array->stream); free(nonce_array); nonce_array = NULL; } @@ -948,26 +989,23 @@ void napi_mf_classic_nonce_array_free(MfClassicNonceArray* nonce_array) { } static void finished_beep() { - // Beep to indicate completion if the speaker is available - if(furi_hal_speaker_acquire(1000)) { // Wait up to a second for the speaker - float freq = 3000; - float volume = 1.0f; // 100% volume - furi_hal_speaker_start(freq, volume); - furi_delay_ms(75); - furi_hal_speaker_stop(); - furi_hal_speaker_release(); - } + // Beep to indicate completion + NotificationApp* notification = furi_record_open("notification"); + notification_message(notification, &sequence_audiovisual_alert); + notification_message(notification, &sequence_display_backlight_on); + furi_record_close("notification"); } -void mfkey32(ProgramState* const program_state) { +void mfkey32(ProgramState* program_state) { uint64_t found_key; // recovered key size_t keyarray_size = 0; uint64_t* keyarray = malloc(sizeof(uint64_t) * 1); - uint32_t i = 0; + uint32_t i = 0, j = 0; // Check for nonces if(!napi_mf_classic_nonces_check_presence()) { program_state->err = MissingNonces; program_state->mfkey_state = Error; + free(keyarray); return; } // Read dictionaries (optional) @@ -990,7 +1028,7 @@ void mfkey32(ProgramState* const program_state) { // Read nonces MfClassicNonceArray* nonce_arr; nonce_arr = napi_mf_classic_nonce_array_alloc( - system_dict, system_dict_exists, user_dict, user_dict_exists, program_state); + system_dict, system_dict_exists, user_dict, program_state); if(system_dict_exists) { napi_mf_classic_dict_free(system_dict); } @@ -1004,15 +1042,13 @@ void mfkey32(ProgramState* const program_state) { return; } if(memmgr_get_free_heap() < MIN_RAM) { - // Insufficient RAM - program_state->err = OutOfMemory; - program_state->mfkey_state = Error; - napi_mf_classic_nonce_array_free(nonce_arr); - napi_mf_classic_dict_free(user_dict); - free(keyarray); - return; + // System has less than the guaranteed amount of RAM (140 KB) - adjust some parameters to run anyway at half speed + eta_round_time *= 2; + eta_total_time *= 2; + MSB_LIMIT /= 2; } program_state->mfkey_state = MfkeyAttack; + // TODO: Work backwards on this array and free memory for(i = 0; i < nonce_arr->total_nonces; i++) { MfClassicNonce next_nonce = nonce_arr->remaining_nonce_array[i]; uint32_t p64 = prng_successor(next_nonce.nt0, 64); @@ -1026,9 +1062,10 @@ void mfkey32(ProgramState* const program_state) { next_nonce.ar1_enc)) { nonce_arr->remaining_nonces--; (program_state->cracked)++; + (program_state->num_completed)++; continue; } - FURI_LOG_I(TAG, "Cracking %lx %lx", next_nonce.uid, next_nonce.ar1_enc); + FURI_LOG_I(TAG, "Cracking %8lx %8lx", next_nonce.uid, next_nonce.ar1_enc); struct Crypto1Params p = { 0, next_nonce.nr0_enc, @@ -1037,24 +1074,29 @@ void mfkey32(ProgramState* const program_state) { next_nonce.nr1_enc, p64b, next_nonce.ar1_enc}; - if(recover(&p, next_nonce.ar0_enc ^ p64, program_state) == 0) { + if(!recover(&p, next_nonce.ar0_enc ^ p64, program_state)) { + if(program_state->close_thread_please) { + break; + } // No key found in recover() + (program_state->num_completed)++; continue; } + (program_state->cracked)++; + (program_state->num_completed)++; found_key = p.key; bool already_found = false; - for(i = 0; i < keyarray_size; i++) { - if(keyarray[i] == found_key) { + for(j = 0; j < keyarray_size; j++) { + if(keyarray[j] == found_key) { already_found = true; break; } } if(already_found == false) { // New key - keyarray = realloc(keyarray, sizeof(uint64_t) * (keyarray_size + 1)); + keyarray = realloc(keyarray, sizeof(uint64_t) * (keyarray_size + 1)); //-V701 keyarray_size += 1; keyarray[keyarray_size - 1] = found_key; - (program_state->cracked)++; (program_state->unique_cracked)++; } } @@ -1068,23 +1110,28 @@ void mfkey32(ProgramState* const program_state) { napi_mf_classic_dict_add_key_str(user_dict, temp_key); furi_string_free(temp_key); } - napi_mf_classic_nonce_array_free(nonce_arr); - if(user_dict_exists) { - napi_mf_classic_dict_free(user_dict); + if(keyarray_size > 0) { + // TODO: Should we use DolphinDeedNfcMfcAdd? + DOLPHIN_DEED(DolphinDeedNfcMfcAdd); } + napi_mf_classic_nonce_array_free(nonce_arr); + napi_mf_classic_dict_free(user_dict); free(keyarray); //FURI_LOG_I(TAG, "mfkey32 function completed normally"); // DEBUG program_state->mfkey_state = Complete; - finished_beep(); + // No need to alert the user if they asked it to stop + if(!(program_state->close_thread_please)) { + finished_beep(); + } return; } // Screen is 128x64 px static void render_callback(Canvas* const canvas, void* ctx) { furi_assert(ctx); - const ProgramState* program_state = ctx; + ProgramState* program_state = ctx; furi_mutex_acquire(program_state->mutex, FuriWaitForever); - char draw_str[32] = {}; + char draw_str[44] = {}; canvas_clear(canvas); canvas_draw_frame(canvas, 0, 0, 128, 64); canvas_draw_frame(canvas, 0, 15, 128, 64); @@ -1092,27 +1139,44 @@ static void render_callback(Canvas* const canvas, void* ctx) { canvas_draw_str_aligned(canvas, 5, 4, AlignLeft, AlignTop, "Mfkey32"); canvas_draw_icon(canvas, 114, 4, &I_mfkey); if(program_state->is_thread_running && program_state->mfkey_state == MfkeyAttack) { - float progress = (float)program_state->cracked / (float)program_state->total; - elements_progress_bar_with_text(canvas, 5, 18, 118, progress, draw_str); + float eta_round = (float)1 - ((float)program_state->eta_round / (float)eta_round_time); + float eta_total = (float)1 - ((float)program_state->eta_total / (float)eta_total_time); + float progress = (float)program_state->num_completed / (float)program_state->total; + if(eta_round < 0) { + // Round ETA miscalculated + eta_round = 1; + program_state->eta_round = 0; + } + if(eta_total < 0) { + // Total ETA miscalculated + eta_total = 1; + program_state->eta_total = 0; + } canvas_set_font(canvas, FontSecondary); snprintf( draw_str, sizeof(draw_str), - "Keys found: %d/%d (in prog.)", - program_state->cracked, + "Cracking: %d/%d - in prog.", + program_state->num_completed, program_state->total); - canvas_draw_str_aligned(canvas, 5, 31, AlignLeft, AlignTop, draw_str); + elements_progress_bar_with_text(canvas, 5, 18, 118, progress, draw_str); snprintf( - draw_str, sizeof(draw_str), "Search: %d/%d", program_state->search, 256 / MSB_LIMIT); - canvas_draw_str_aligned(canvas, 26, 41, AlignLeft, AlignTop, draw_str); + draw_str, + sizeof(draw_str), + "Round: %d/%d - ETA %02d Sec", + (program_state->search) + 1, // Zero indexed + 256 / MSB_LIMIT, + program_state->eta_round); + elements_progress_bar_with_text(canvas, 5, 31, 118, eta_round, draw_str); + snprintf(draw_str, sizeof(draw_str), "Total ETA %03d Sec", program_state->eta_total); + elements_progress_bar_with_text(canvas, 5, 44, 118, eta_total, draw_str); } else if(program_state->is_thread_running && program_state->mfkey_state == DictionaryAttack) { - elements_progress_bar_with_text(canvas, 5, 18, 118, 0, draw_str); canvas_set_font(canvas, FontSecondary); snprintf( draw_str, sizeof(draw_str), "Dict solves: %d (in progress)", program_state->cracked); - canvas_draw_str_aligned(canvas, 10, 31, AlignLeft, AlignTop, draw_str); + canvas_draw_str_aligned(canvas, 10, 18, AlignLeft, AlignTop, draw_str); snprintf(draw_str, sizeof(draw_str), "Keys in dict: %d", program_state->dict_count); - canvas_draw_str_aligned(canvas, 26, 41, AlignLeft, AlignTop, draw_str); + canvas_draw_str_aligned(canvas, 26, 28, AlignLeft, AlignTop, draw_str); } else if(program_state->mfkey_state == Complete) { // TODO: Scrollable list view to see cracked keys if user presses down elements_progress_bar_with_text(canvas, 5, 18, 118, 1, draw_str); @@ -1142,9 +1206,7 @@ static void render_callback(Canvas* const canvas, void* ctx) { if(program_state->err == MissingNonces) { canvas_draw_str_aligned(canvas, 25, 36, AlignLeft, AlignTop, "No nonces found"); } else if(program_state->err == ZeroNonces) { - canvas_draw_str_aligned(canvas, 25, 36, AlignLeft, AlignTop, "No nonces to crack"); - } else if(program_state->err == OutOfMemory) { - canvas_draw_str_aligned(canvas, 25, 36, AlignLeft, AlignTop, "Insufficient memory"); + canvas_draw_str_aligned(canvas, 15, 36, AlignLeft, AlignTop, "Nonces already cracked"); } else { // Unhandled error } @@ -1161,11 +1223,12 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu furi_message_queue_put(event_queue, &event, FuriWaitForever); } -static void mfkey32_state_init(ProgramState* const program_state) { +static void mfkey32_state_init(ProgramState* program_state) { program_state->is_thread_running = false; program_state->mfkey_state = Ready; program_state->cracked = 0; program_state->unique_cracked = 0; + program_state->num_completed = 0; program_state->total = 0; program_state->dict_count = 0; } @@ -1190,7 +1253,6 @@ void start_mfkey32_thread(ProgramState* program_state) { int32_t mfkey32_main() { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - DOLPHIN_DEED(DolphinDeedPluginStart); ProgramState* program_state = malloc(sizeof(ProgramState)); mfkey32_state_init(program_state); diff --git a/applications/external/minesweeper/img/screenshot.png b/applications/external/minesweeper/img/screenshot.png deleted file mode 100644 index 65b307c55..000000000 Binary files a/applications/external/minesweeper/img/screenshot.png and /dev/null differ diff --git a/applications/external/music_beeper/music_beeper_worker.c b/applications/external/music_beeper/music_beeper_worker.c index e06e77447..c95fe8d3a 100644 --- a/applications/external/music_beeper/music_beeper_worker.c +++ b/applications/external/music_beeper/music_beeper_worker.c @@ -399,7 +399,7 @@ bool music_beeper_worker_load_rtttl_from_file(MusicBeeperWorker* instance, const if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { FURI_LOG_E(TAG, "Unable to open file"); break; - }; + } uint16_t ret = 0; do { diff --git a/applications/external/music_player/music_player_worker.c b/applications/external/music_player/music_player_worker.c index ee350ee80..6a712d3e3 100644 --- a/applications/external/music_player/music_player_worker.c +++ b/applications/external/music_player/music_player_worker.c @@ -397,7 +397,7 @@ bool music_player_worker_load_rtttl_from_file(MusicPlayerWorker* instance, const if(!storage_file_open(file, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { FURI_LOG_E(TAG, "Unable to open file"); break; - }; + } uint16_t ret = 0; do { diff --git a/applications/external/musictracker/application.fam b/applications/external/music_tracker/application.fam similarity index 100% rename from applications/external/musictracker/application.fam rename to applications/external/music_tracker/application.fam diff --git a/applications/external/musictracker/tracker_engine/speaker_hal.c b/applications/external/music_tracker/tracker_engine/speaker_hal.c similarity index 99% rename from applications/external/musictracker/tracker_engine/speaker_hal.c rename to applications/external/music_tracker/tracker_engine/speaker_hal.c index 94489f1b6..0a506a424 100644 --- a/applications/external/musictracker/tracker_engine/speaker_hal.c +++ b/applications/external/music_tracker/tracker_engine/speaker_hal.c @@ -104,4 +104,4 @@ void tracker_debug_set(bool value) { void tracker_debug_deinit() { furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); -} \ No newline at end of file +} diff --git a/applications/external/musictracker/tracker_engine/speaker_hal.h b/applications/external/music_tracker/tracker_engine/speaker_hal.h similarity index 100% rename from applications/external/musictracker/tracker_engine/speaker_hal.h rename to applications/external/music_tracker/tracker_engine/speaker_hal.h diff --git a/applications/external/musictracker/tracker_engine/tracker.c b/applications/external/music_tracker/tracker_engine/tracker.c similarity index 100% rename from applications/external/musictracker/tracker_engine/tracker.c rename to applications/external/music_tracker/tracker_engine/tracker.c diff --git a/applications/external/musictracker/tracker_engine/tracker.h b/applications/external/music_tracker/tracker_engine/tracker.h similarity index 100% rename from applications/external/musictracker/tracker_engine/tracker.h rename to applications/external/music_tracker/tracker_engine/tracker.h diff --git a/applications/external/musictracker/tracker_engine/tracker_notes.h b/applications/external/music_tracker/tracker_engine/tracker_notes.h similarity index 100% rename from applications/external/musictracker/tracker_engine/tracker_notes.h rename to applications/external/music_tracker/tracker_engine/tracker_notes.h diff --git a/applications/external/musictracker/tracker_engine/tracker_song.h b/applications/external/music_tracker/tracker_engine/tracker_song.h similarity index 100% rename from applications/external/musictracker/tracker_engine/tracker_song.h rename to applications/external/music_tracker/tracker_engine/tracker_song.h diff --git a/applications/external/musictracker/view/tracker_view.c b/applications/external/music_tracker/view/tracker_view.c similarity index 100% rename from applications/external/musictracker/view/tracker_view.c rename to applications/external/music_tracker/view/tracker_view.c diff --git a/applications/external/musictracker/view/tracker_view.h b/applications/external/music_tracker/view/tracker_view.h similarity index 100% rename from applications/external/musictracker/view/tracker_view.h rename to applications/external/music_tracker/view/tracker_view.h diff --git a/applications/external/musictracker/zero_tracker.c b/applications/external/music_tracker/zero_tracker.c similarity index 100% rename from applications/external/musictracker/zero_tracker.c rename to applications/external/music_tracker/zero_tracker.c diff --git a/applications/external/musictracker/zero_tracker.h b/applications/external/music_tracker/zero_tracker.h similarity index 100% rename from applications/external/musictracker/zero_tracker.h rename to applications/external/music_tracker/zero_tracker.h diff --git a/applications/external/musictracker/zero_tracker.png b/applications/external/music_tracker/zero_tracker.png similarity index 100% rename from applications/external/musictracker/zero_tracker.png rename to applications/external/music_tracker/zero_tracker.png diff --git a/applications/external/nightstand_clock/application.fam b/applications/external/nightstand/application.fam similarity index 100% rename from applications/external/nightstand_clock/application.fam rename to applications/external/nightstand/application.fam diff --git a/applications/external/nightstand_clock/clock.png b/applications/external/nightstand/clock.png similarity index 100% rename from applications/external/nightstand_clock/clock.png rename to applications/external/nightstand/clock.png diff --git a/applications/external/nightstand_clock/clock_app.c b/applications/external/nightstand/clock_app.c similarity index 100% rename from applications/external/nightstand_clock/clock_app.c rename to applications/external/nightstand/clock_app.c diff --git a/applications/external/nightstand_clock/clock_app.h b/applications/external/nightstand/clock_app.h similarity index 100% rename from applications/external/nightstand_clock/clock_app.h rename to applications/external/nightstand/clock_app.h diff --git a/applications/external/picopass/rfal_picopass.c b/applications/external/picopass/rfal_picopass.c index ac66cb92d..e8ca64403 100644 --- a/applications/external/picopass/rfal_picopass.c +++ b/applications/external/picopass/rfal_picopass.c @@ -48,7 +48,7 @@ FuriHalNfcReturn rfalPicoPassPollerInitialize(void) { FuriHalNfcModePollPicopass, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48); if(ret != FuriHalNfcReturnOk) { return ret; - }; + } furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_PICOPASS); diff --git a/applications/external/pocsag_pager/pocsag_pager_app_i.c b/applications/external/pocsag_pager/pocsag_pager_app_i.c index ff73ab50e..85e2a4bcf 100644 --- a/applications/external/pocsag_pager/pocsag_pager_app_i.c +++ b/applications/external/pocsag_pager/pocsag_pager_app_i.c @@ -131,7 +131,7 @@ void pcsg_hopper_update(POCSAGPagerApp* app) { if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); - }; + } if(app->txrx->txrx_state == PCSGTxRxStateIDLE) { subghz_receiver_reset(app->txrx->receiver); app->txrx->preset->frequency = diff --git a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c index 658b70fea..60dca01c9 100644 --- a/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/scenes/pocsag_pager_receiver.c @@ -133,7 +133,7 @@ void pocsag_pager_scene_receiver_on_enter(void* context) { if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); - }; + } if((app->txrx->txrx_state == PCSGTxRxStateIDLE) || (app->txrx->txrx_state == PCSGTxRxStateSleep)) { pcsg_begin( @@ -158,7 +158,7 @@ bool pocsag_pager_scene_receiver_on_event(void* context, SceneManagerEvent event if(app->txrx->txrx_state == PCSGTxRxStateRx) { pcsg_rx_end(app); pcsg_sleep(app); - }; + } app->txrx->hopper_state = PCSGHopperStateOFF; app->txrx->idx_menu_chosen = 0; subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); diff --git a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c index 532f41984..64939a956 100644 --- a/applications/external/pocsag_pager/views/pocsag_pager_receiver.c +++ b/applications/external/pocsag_pager/views/pocsag_pager_receiver.c @@ -12,7 +12,7 @@ #define MENU_ITEMS 4u #define UNLOCK_CNT 3 -#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f +#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f typedef struct { FuriString* item_str; @@ -69,10 +69,10 @@ void pcsg_receiver_rssi(PCSGReceiver* instance, float rssi) { instance->view, PCSGReceiverModel * model, { - if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) { + if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { model->u_rssi = 0; } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN); + model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); } }, true); diff --git a/applications/external/pomodoro/flipp_pomodoro_app.c b/applications/external/pomodoro/flipp_pomodoro_app.c index 5adca1edb..3ee3b0277 100644 --- a/applications/external/pomodoro/flipp_pomodoro_app.c +++ b/applications/external/pomodoro/flipp_pomodoro_app.c @@ -9,14 +9,14 @@ static bool flipp_pomodoro_app_back_event_callback(void* ctx) { furi_assert(ctx); FlippPomodoroApp* app = ctx; return scene_manager_handle_back_event(app->scene_manager); -}; +} static void flipp_pomodoro_app_tick_event_callback(void* ctx) { furi_assert(ctx); FlippPomodoroApp* app = ctx; scene_manager_handle_custom_event(app->scene_manager, FlippPomodoroAppCustomEventTimerTick); -}; +} static bool flipp_pomodoro_app_custom_event_callback(void* ctx, uint32_t event) { furi_assert(ctx); @@ -40,7 +40,7 @@ static bool flipp_pomodoro_app_custom_event_callback(void* ctx, uint32_t event) break; } return scene_manager_handle_custom_event(app->scene_manager, event); -}; +} FlippPomodoroApp* flipp_pomodoro_app_alloc() { FlippPomodoroApp* app = malloc(sizeof(FlippPomodoroApp)); @@ -71,17 +71,18 @@ FlippPomodoroApp* flipp_pomodoro_app_alloc() { scene_manager_next_scene(app->scene_manager, FlippPomodoroSceneTimer); return app; -}; +} void flipp_pomodoro_app_free(FlippPomodoroApp* app) { view_dispatcher_remove_view(app->view_dispatcher, FlippPomodoroAppViewTimer); view_dispatcher_free(app->view_dispatcher); scene_manager_free(app->scene_manager); flipp_pomodoro_view_timer_free(app->timer_view); + flipp_pomodoro__destroy(app->state); free(app); furi_record_close(RECORD_GUI); furi_record_close(RECORD_NOTIFICATION); -}; +} int32_t flipp_pomodoro_app(void* p) { UNUSED(p); @@ -92,4 +93,4 @@ int32_t flipp_pomodoro_app(void* p) { flipp_pomodoro_app_free(app); return 0; -}; +} diff --git a/applications/external/pomodoro/helpers/time.c b/applications/external/pomodoro/helpers/time.c index 7fb0d13c2..02540a939 100644 --- a/applications/external/pomodoro/helpers/time.c +++ b/applications/external/pomodoro/helpers/time.c @@ -7,7 +7,7 @@ const int TIME_MINUTES_IN_HOUR = 60; uint32_t time_now() { return furi_hal_rtc_get_timestamp(); -}; +} TimeDifference time_difference_seconds(uint32_t begin, uint32_t end) { const uint32_t duration_seconds = end - begin; @@ -17,4 +17,4 @@ TimeDifference time_difference_seconds(uint32_t begin, uint32_t end) { return ( TimeDifference){.total_seconds = duration_seconds, .minutes = minutes, .seconds = seconds}; -}; +} diff --git a/applications/external/pomodoro/modules/flipp_pomodoro.c b/applications/external/pomodoro/modules/flipp_pomodoro.c index 161e862f8..cd417f791 100644 --- a/applications/external/pomodoro/modules/flipp_pomodoro.c +++ b/applications/external/pomodoro/modules/flipp_pomodoro.c @@ -38,21 +38,26 @@ void flipp_pomodoro__toggle_stage(FlippPomodoroState* state) { furi_assert(state); state->current_stage_index = state->current_stage_index + 1; state->started_at_timestamp = time_now(); -}; +} PomodoroStage flipp_pomodoro__get_stage(FlippPomodoroState* state) { furi_assert(state); return flipp_pomodoro__stage_by_index(state->current_stage_index); -}; +} char* flipp_pomodoro__current_stage_label(FlippPomodoroState* state) { furi_assert(state); return current_stage_label[flipp_pomodoro__get_stage(state)]; -}; +} char* flipp_pomodoro__next_stage_label(FlippPomodoroState* state) { furi_assert(state); return next_stage_label[flipp_pomodoro__stage_by_index(state->current_stage_index + 1)]; +} + +void flipp_pomodoro__destroy(FlippPomodoroState* state) { + furi_assert(state); + free(state); }; uint32_t flipp_pomodoro__current_stage_total_duration(FlippPomodoroState* state) { @@ -63,22 +68,22 @@ uint32_t flipp_pomodoro__current_stage_total_duration(FlippPomodoroState* state) }; return stage_duration_seconds_map[flipp_pomodoro__get_stage(state)]; -}; +} uint32_t flipp_pomodoro__stage_expires_timestamp(FlippPomodoroState* state) { return state->started_at_timestamp + flipp_pomodoro__current_stage_total_duration(state); -}; +} TimeDifference flipp_pomodoro__stage_remaining_duration(FlippPomodoroState* state) { const uint32_t stage_ends_at = flipp_pomodoro__stage_expires_timestamp(state); return time_difference_seconds(time_now(), stage_ends_at); -}; +} bool flipp_pomodoro__is_stage_expired(FlippPomodoroState* state) { const uint32_t expired_by = flipp_pomodoro__stage_expires_timestamp(state); const uint8_t seamless_change_span_seconds = 1; return (time_now() - seamless_change_span_seconds) >= expired_by; -}; +} FlippPomodoroState* flipp_pomodoro__new() { FlippPomodoroState* state = malloc(sizeof(FlippPomodoroState)); @@ -86,4 +91,4 @@ FlippPomodoroState* flipp_pomodoro__new() { state->started_at_timestamp = now; state->current_stage_index = 0; return state; -}; \ No newline at end of file +} \ No newline at end of file diff --git a/applications/external/pomodoro/scenes/flipp_pomodoro_scene_timer.c b/applications/external/pomodoro/scenes/flipp_pomodoro_scene_timer.c index 2190dbdb7..8ed5dd5e7 100644 --- a/applications/external/pomodoro/scenes/flipp_pomodoro_scene_timer.c +++ b/applications/external/pomodoro/scenes/flipp_pomodoro_scene_timer.c @@ -15,7 +15,7 @@ void flipp_pomodoro_scene_timer_sync_view_state(void* ctx) { flipp_pomodoro_view_timer_set_state( flipp_pomodoro_view_timer_get_view(app->timer_view), app->state); -}; +} void flipp_pomodoro_scene_timer_on_next_stage(void* ctx) { furi_assert(ctx); @@ -23,7 +23,7 @@ void flipp_pomodoro_scene_timer_on_next_stage(void* ctx) { FlippPomodoroApp* app = ctx; view_dispatcher_send_custom_event(app->view_dispatcher, FlippPomodoroAppCustomEventStageSkip); -}; +} void flipp_pomodoro_scene_timer_on_enter(void* ctx) { furi_assert(ctx); @@ -34,7 +34,7 @@ void flipp_pomodoro_scene_timer_on_enter(void* ctx) { flipp_pomodoro_scene_timer_sync_view_state(app); flipp_pomodoro_view_timer_set_on_right_cb( app->timer_view, flipp_pomodoro_scene_timer_on_next_stage, app); -}; +} void flipp_pomodoro_scene_timer_handle_custom_event( FlippPomodoroApp* app, @@ -48,7 +48,7 @@ void flipp_pomodoro_scene_timer_handle_custom_event( if(custom_event == FlippPomodoroAppCustomEventStateUpdated) { flipp_pomodoro_scene_timer_sync_view_state(app); } -}; +} bool flipp_pomodoro_scene_timer_on_event(void* ctx, SceneManagerEvent event) { furi_assert(ctx); @@ -62,10 +62,10 @@ bool flipp_pomodoro_scene_timer_on_event(void* ctx, SceneManagerEvent event) { return ExitSignal; default: break; - }; + } return SceneEventNotConusmed; -}; +} void flipp_pomodoro_scene_timer_on_exit(void* ctx) { UNUSED(ctx); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/applications/external/pomodoro/views/flipp_pomodoro_timer_view.c b/applications/external/pomodoro/views/flipp_pomodoro_timer_view.c index e8e0383b7..302380ddd 100644 --- a/applications/external/pomodoro/views/flipp_pomodoro_timer_view.c +++ b/applications/external/pomodoro/views/flipp_pomodoro_timer_view.c @@ -58,7 +58,7 @@ static void remaining_stage_time_string); furi_string_free(timer_string); -}; +} static void draw_str_with_drop_shadow( Canvas* canvas, @@ -92,7 +92,7 @@ static void static void flipp_pomodoro_view_timer_draw_callback(Canvas* canvas, void* _model) { if(!_model) { return; - }; + } FlippPomodoroTimerViewModel* model = _model; @@ -109,7 +109,7 @@ static void flipp_pomodoro_view_timer_draw_callback(Canvas* canvas, void* _model canvas_set_font(canvas, FontSecondary); elements_button_right(canvas, flipp_pomodoro__next_stage_label(model->state)); -}; +} bool flipp_pomodoro_view_timer_input_callback(InputEvent* event, void* ctx) { furi_assert(ctx); @@ -125,15 +125,15 @@ bool flipp_pomodoro_view_timer_input_callback(InputEvent* event, void* ctx) { furi_assert(timer->right_cb_ctx); timer->right_cb(timer->right_cb_ctx); return ViewInputConsumed; - }; + } return ViewInputNotConusmed; -}; +} View* flipp_pomodoro_view_timer_get_view(FlippPomodoroTimerView* timer) { furi_assert(timer); return timer->view; -}; +} void flipp_pomodoro_view_timer_assign_animation(View* view) { with_view_model( @@ -162,7 +162,7 @@ FlippPomodoroTimerView* flipp_pomodoro_view_timer_alloc() { view_set_input_callback(timer->view, flipp_pomodoro_view_timer_input_callback); return timer; -}; +} void flipp_pomodoro_view_timer_set_on_right_cb( FlippPomodoroTimerView* timer, @@ -172,7 +172,7 @@ void flipp_pomodoro_view_timer_set_on_right_cb( furi_assert(right_cb_ctx); timer->right_cb = right_cb; timer->right_cb_ctx = right_cb_ctx; -}; +} void flipp_pomodoro_view_timer_set_state(View* view, FlippPomodoroState* state) { furi_assert(view); @@ -180,7 +180,7 @@ void flipp_pomodoro_view_timer_set_state(View* view, FlippPomodoroState* state) with_view_model( view, FlippPomodoroTimerViewModel * model, { model->state = state; }, false); flipp_pomodoro_view_timer_assign_animation(view); -}; +} void flipp_pomodoro_view_timer_free(FlippPomodoroTimerView* timer) { furi_assert(timer); @@ -192,4 +192,4 @@ void flipp_pomodoro_view_timer_free(FlippPomodoroTimerView* timer) { view_free(timer->view); free(timer); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/applications/external/pong/flipper_pong.c b/applications/external/pong/flipper_pong.c index 55b371ad5..53c6a7e27 100644 --- a/applications/external/pong/flipper_pong.c +++ b/applications/external/pong/flipper_pong.c @@ -15,8 +15,7 @@ #define PAD_SIZE_X 3 #define PAD_SIZE_Y 8 -#define PLAYER1_PAD_SPEED 4 - +#define PLAYER1_PAD_SPEED 2 #define PLAYER2_PAD_SPEED 2 #define BALL_SIZE 4 @@ -39,29 +38,22 @@ typedef struct Players { static void draw_callback(Canvas* canvas, void* ctx) { furi_assert(ctx); - Players* playersMutex = ctx; - furi_mutex_acquire(playersMutex->mutex, FuriWaitForever); + Players* players = ctx; + furi_mutex_acquire(players->mutex, FuriWaitForever); canvas_draw_frame(canvas, 0, 0, 128, 64); - canvas_draw_box( - canvas, playersMutex->player1_X, playersMutex->player1_Y, PAD_SIZE_X, PAD_SIZE_Y); - canvas_draw_box( - canvas, playersMutex->player2_X, playersMutex->player2_Y, PAD_SIZE_X, PAD_SIZE_Y); - canvas_draw_box(canvas, playersMutex->ball_X, playersMutex->ball_Y, BALL_SIZE, BALL_SIZE); + canvas_draw_box(canvas, players->player1_X, players->player1_Y, PAD_SIZE_X, PAD_SIZE_Y); + canvas_draw_box(canvas, players->player2_X, players->player2_Y, PAD_SIZE_X, PAD_SIZE_Y); + canvas_draw_box(canvas, players->ball_X, players->ball_Y, BALL_SIZE, BALL_SIZE); canvas_set_font(canvas, FontPrimary); canvas_set_font_direction(canvas, CanvasDirectionBottomToTop); char buffer[16]; - snprintf( - buffer, - sizeof(buffer), - "%u - %u", - playersMutex->player1_score, - playersMutex->player2_score); + snprintf(buffer, sizeof(buffer), "%u - %u", players->player1_score, players->player2_score); canvas_draw_str_aligned( canvas, SCREEN_SIZE_X / 2 + 15, SCREEN_SIZE_Y / 2 + 2, AlignCenter, AlignTop, buffer); - furi_mutex_release(playersMutex->mutex); + furi_mutex_release(players->mutex); } static void input_callback(InputEvent* input_event, void* ctx) { @@ -101,8 +93,7 @@ uint8_t changeDirection() { return randomuint8[0]; } -int32_t flipper_pong_app(void* p) { - UNUSED(p); +int32_t flipper_pong_app() { EventApp event; FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp)); @@ -129,7 +120,7 @@ int32_t flipper_pong_app(void* p) { } ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, draw_callback, &players); + view_port_draw_callback_set(view_port, draw_callback, &players.mutex); view_port_input_callback_set(view_port, input_callback, event_queue); Gui* gui = furi_record_open(RECORD_GUI); @@ -152,7 +143,6 @@ int32_t flipper_pong_app(void* p) { if(event.type == EventTypeInput) { if(event.input.key == InputKeyBack) { furi_mutex_release(players.mutex); - notification_message(notification, &sequence_set_only_green_255); break; } else if(event.input.key == InputKeyUp) { if(players.player1_Y >= 1 + PLAYER1_PAD_SPEED) diff --git a/applications/external/rc2014_coleco/coleco.c b/applications/external/rc2014_coleco/coleco.c index 311b0ceac..f0a4c6188 100644 --- a/applications/external/rc2014_coleco/coleco.c +++ b/applications/external/rc2014_coleco/coleco.c @@ -40,15 +40,14 @@ typedef struct { } PluginEvent; typedef struct { - FuriMutex* mutex; bool dpad; int row; int column; + FuriMutex* mutex; } Coleco; static void render_callback(Canvas* const canvas, void* context) { - furi_assert(context); - Coleco* coleco = context; + Coleco* coleco = (Coleco*)context; furi_mutex_acquire(coleco->mutex, FuriWaitForever); if(coleco->dpad) { @@ -175,12 +174,20 @@ static Coleco* coleco_alloc() { coleco->row = 0; coleco->column = 1; + coleco->mutex = furi_mutex_alloc(FuriMutexTypeNormal); + if(!coleco->mutex) { + FURI_LOG_E("Coleco", "cannot create mutex\r\n"); + free(coleco); + return NULL; + } + return coleco; } static void coleco_free(Coleco* coleco) { furi_assert(coleco); + furi_mutex_free(coleco->mutex); free(coleco); } @@ -190,11 +197,7 @@ int32_t coleco_app(void* p) { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); Coleco* coleco = coleco_alloc(); - - coleco->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!coleco->mutex) { - FURI_LOG_E("Coleco", "cannot create mutex\r\n"); - coleco_free(coleco); + if(coleco == NULL) { return 255; } @@ -346,6 +349,8 @@ int32_t coleco_app(void* p) { view_port_update(view_port); } + } else { + FURI_LOG_D("Coleco", "FuriMessageQueue: event timeout"); } furi_mutex_release(coleco->mutex); @@ -358,7 +363,6 @@ int32_t coleco_app(void* p) { furi_record_close("gui"); view_port_free(view_port); furi_message_queue_free(event_queue); - furi_mutex_free(coleco->mutex); coleco_free(coleco); return 0; } diff --git a/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c b/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c index 4c845b883..c4ceae4ab 100644 --- a/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c +++ b/applications/external/rubiks_cube_scrambler/rubiks_cube_scrambler.c @@ -8,11 +8,11 @@ #include "scrambler.h" #include "furi_hal_random.h" -int scrambleStarted = 0; +bool scrambleStarted = false; char scramble_str[100] = {0}; char scramble_start[100] = {0}; char scramble_end[100] = {0}; -int notifications_enabled = 0; +bool notifications_enabled = false; static void success_vibration() { furi_hal_vibro_on(false); @@ -22,12 +22,12 @@ static void success_vibration() { return; } void split_array(char original[], int size, char first[], char second[]) { - int mid = size / 2; + int32_t mid = size / 2; if(size % 2 != 0) { mid++; } - int first_index = 0, second_index = 0; - for(int i = 0; i < size; i++) { + int32_t first_index = 0, second_index = 0; + for(int32_t i = 0; i < size; i++) { if(i < mid) { first[first_index++] = original[i]; } else { @@ -40,30 +40,24 @@ void split_array(char original[], int size, char first[], char second[]) { first[first_index] = '\0'; second[second_index] = '\0'; } +void genScramble() { + scrambleReplace(); + strcpy(scramble_str, printData()); + split_array(scramble_str, strlen(scramble_str), scramble_start, scramble_end); +} static void draw_callback(Canvas* canvas, void* ctx) { UNUSED(ctx); canvas_clear(canvas); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 4, 13, "Rubik's Cube Scrambler"); - - if(scrambleStarted) { - genScramble(); - scrambleReplace(); - strcpy(scramble_str, printData()); - if(notifications_enabled) { - success_vibration(); - } - split_array(scramble_str, strlen(scramble_str), scramble_start, scramble_end); - scrambleStarted = 0; - } canvas_set_font(canvas, FontSecondary); canvas_draw_str_aligned(canvas, 64, 28, AlignCenter, AlignCenter, scramble_start); canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, scramble_end); elements_button_center(canvas, "New"); elements_button_left(canvas, notifications_enabled ? "On" : "Off"); -}; +} static void input_callback(InputEvent* input_event, void* ctx) { furi_assert(ctx); @@ -90,13 +84,16 @@ int32_t rubiks_cube_scrambler_main(void* p) { furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk); if(event.key == InputKeyOk && event.type == InputTypeShort) { - scrambleStarted = 1; + genScramble(); + if(notifications_enabled) { + success_vibration(); + } } if(event.key == InputKeyLeft && event.type == InputTypeShort) { if(notifications_enabled) { - notifications_enabled = 0; + notifications_enabled = false; } else { - notifications_enabled = 1; + notifications_enabled = true; success_vibration(); } } diff --git a/applications/external/rubiks_cube_scrambler/scrambler.c b/applications/external/rubiks_cube_scrambler/scrambler.c index ea5291940..b97a67400 100644 --- a/applications/external/rubiks_cube_scrambler/scrambler.c +++ b/applications/external/rubiks_cube_scrambler/scrambler.c @@ -12,66 +12,37 @@ Authors: Tanish Bhongade and RaZe // 6 moves along with direction char moves[6] = {'R', 'U', 'F', 'B', 'L', 'D'}; -char dir[4] = {' ', '\'', '2'}; -const int SLEN = 20; +char dir[4] = {'\'', '2'}; +const int32_t SLEN = 20; #define RESULT_SIZE 100 -// Structure which holds main scramble + struct GetScramble { char mainScramble[25][3]; }; -struct GetScramble a; // Its object - -// Function prototypes to avoid bugs -void scrambleReplace(); -void genScramble(); -void valid(); -int getRand(int upr, int lwr); -char* printData(); -void writeToFile(); - -// Main function -/* int main(){ - genScramble ();//Calling genScramble - scrambleReplace();//Calling scrambleReplace - valid();//Calling valid to validate the scramble - printData ();//Printing the final scramble - //writeToFile();//If you want to write to a file, please uncomment this - - return 0; -} */ - -void genScramble() { - // Stage 1 - for(int i = 0; i < SLEN; i++) { - strcpy(a.mainScramble[i], "00"); - } - // This makes array like this 00 00 00....... -} +struct GetScramble a; void scrambleReplace() { - // Stage 2 - // Actual process begins here - // Initialize the mainScramble array with all the possible moves - for(int i = 0; i < SLEN; i++) { + for(int32_t i = 0; i < SLEN; i++) { a.mainScramble[i][0] = moves[furi_hal_random_get() % 6]; a.mainScramble[i][1] = dir[furi_hal_random_get() % 3]; } - // Perform the Fisher-Yates shuffle - for(int i = 6 - 1; i > 0; i--) { - int j = rand() % (i + 1); + /* // Perform the Fisher-Yates shuffle + for (int32_t i = 6 - 1; i > 0; i--) + { + int32_t j = rand() % (i + 1); char temp[3]; strcpy(temp, a.mainScramble[i]); strcpy(a.mainScramble[i], a.mainScramble[j]); strcpy(a.mainScramble[j], temp); - } + } */ - // Select the first 10 elements as the scramble, using only the first three elements of the dir array - for(int i = 0; i < SLEN; i++) { + // Select the first 10 elements as the scramble, using only the first two elements of the dir array + for(int32_t i = 0; i < SLEN; i++) { a.mainScramble[i][1] = dir[furi_hal_random_get() % 3]; } - for(int i = 1; i < SLEN; i++) { + for(int32_t i = 1; i < SLEN; i++) { while(a.mainScramble[i][0] == a.mainScramble[i - 2][0] || a.mainScramble[i][0] == a.mainScramble[i - 1][0]) { a.mainScramble[i][0] = moves[furi_hal_random_get() % 5]; @@ -79,24 +50,11 @@ void scrambleReplace() { } } -// Let this function be here for now till I find out what is causing the extra space bug in the scrambles -void remove_double_spaces(char* str) { - int i, j; - int len = strlen(str); - for(i = 0, j = 0; i < len; i++, j++) { - if(str[i] == ' ' && str[i + 1] == ' ') { - i++; - } - str[j] = str[i]; - } - str[j] = '\0'; -} char* printData() { static char result[RESULT_SIZE]; - int offset = 0; - for(int loop = 0; loop < SLEN; loop++) { + int32_t offset = 0; + for(int32_t loop = 0; loop < SLEN; loop++) { offset += snprintf(result + offset, RESULT_SIZE - offset, "%s ", a.mainScramble[loop]); } - remove_double_spaces(result); return result; -} +} \ No newline at end of file diff --git a/applications/external/rubiks_cube_scrambler/scrambler.h b/applications/external/rubiks_cube_scrambler/scrambler.h index 4b56c565d..557ef20ae 100644 --- a/applications/external/rubiks_cube_scrambler/scrambler.h +++ b/applications/external/rubiks_cube_scrambler/scrambler.h @@ -1,3 +1,2 @@ void scrambleReplace(); -void genScramble(); char* printData(); diff --git a/applications/external/sam/stm32_sam.cpp b/applications/external/sam/stm32_sam.cpp index 16f6fcaab..1ab73a66d 100644 --- a/applications/external/sam/stm32_sam.cpp +++ b/applications/external/sam/stm32_sam.cpp @@ -3945,7 +3945,7 @@ void STM32SAM::Code41240() { Insert(pos + 1, index + 1, phonemeLengthTable[index + 1], stress[pos]); Insert(pos + 2, index + 2, phonemeLengthTable[index + 2], stress[pos]); pos += 3; - }; + } } // Rewrites the phonemes using the following rules: diff --git a/applications/external/swd_probe/swd_probe_app.c b/applications/external/swd_probe/swd_probe_app.c index beaa871dc..ae835fe61 100644 --- a/applications/external/swd_probe/swd_probe_app.c +++ b/applications/external/swd_probe/swd_probe_app.c @@ -3164,6 +3164,11 @@ int32_t swd_probe_app_main(void* p) { furi_message_queue_free(app->event_queue); furi_mutex_free(app->gui_mutex); furi_mutex_free(app->swd_mutex); + + // Reset GPIO pins to default state + for(int io = 0; io < 8; io++) { + furi_hal_gpio_init(gpios[io], GpioModeAnalog, GpioPullNo, GpioSpeedLow); + } free(app); furi_record_close(RECORD_GUI); diff --git a/applications/external/text_viewer/text_viewer.c b/applications/external/text_viewer/text_viewer.c index 59923adb9..b5ccb6ef3 100644 --- a/applications/external/text_viewer/text_viewer.c +++ b/applications/external/text_viewer/text_viewer.c @@ -157,7 +157,7 @@ static bool text_viewer_open_file(TextViewer* text_viewer, const char* file_path FURI_LOG_E(TAG, "Unable to open stream: %s", file_path); isOk = false; break; - }; + } text_viewer->model->file_size = stream_size(text_viewer->model->stream); } while(false); diff --git a/applications/external/timelapse/icons/ButtonDownHollow_7x4.png b/applications/external/timelapse/icons/ButtonDownHollow_7x4.png new file mode 100644 index 000000000..2b87c4364 Binary files /dev/null and b/applications/external/timelapse/icons/ButtonDownHollow_7x4.png differ diff --git a/applications/external/timelapse/icons/ButtonLeftHollow_4x7.png b/applications/external/timelapse/icons/ButtonLeftHollow_4x7.png new file mode 100644 index 000000000..374dc7d1a Binary files /dev/null and b/applications/external/timelapse/icons/ButtonLeftHollow_4x7.png differ diff --git a/applications/external/timelapse/icons/ButtonRightHollow_4x7.png b/applications/external/timelapse/icons/ButtonRightHollow_4x7.png new file mode 100644 index 000000000..acbb08592 Binary files /dev/null and b/applications/external/timelapse/icons/ButtonRightHollow_4x7.png differ diff --git a/applications/external/timelapse/icons/ButtonUpHollow_7x4.png b/applications/external/timelapse/icons/ButtonUpHollow_7x4.png new file mode 100644 index 000000000..e88ee3322 Binary files /dev/null and b/applications/external/timelapse/icons/ButtonUpHollow_7x4.png differ diff --git a/applications/external/timelapse/zeitraffer.c b/applications/external/timelapse/zeitraffer.c index cbae4fa44..73ea4424a 100644 --- a/applications/external/timelapse/zeitraffer.c +++ b/applications/external/timelapse/zeitraffer.c @@ -69,16 +69,18 @@ static void draw_callback(Canvas* canvas, void* ctx) { canvas_draw_str(canvas, 13, 55, "AUTO"); } - //canvas_draw_icon(canvas, 90, 17, &I_ButtonUp_7x4); - //canvas_draw_icon(canvas, 100, 17, &I_ButtonDown_7x4); - //canvas_draw_icon(canvas, 27, 17, &I_ButtonLeftSmall_3x5); - //canvas_draw_icon(canvas, 37, 17, &I_ButtonRightSmall_3x5); - //canvas_draw_icon(canvas, 3, 48, &I_Pin_star_7x7); + if(Work) { + canvas_draw_icon(canvas, 85, 41, &I_ButtonUpHollow_7x4); + canvas_draw_icon(canvas, 85, 57, &I_ButtonDownHollow_7x4); + canvas_draw_icon(canvas, 59, 48, &I_ButtonLeftHollow_4x7); + canvas_draw_icon(canvas, 72, 48, &I_ButtonRightHollow_4x7); + } else { + canvas_draw_icon(canvas, 85, 41, &I_ButtonUp_7x4); + canvas_draw_icon(canvas, 85, 57, &I_ButtonDown_7x4); + canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7); + canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7); + } - canvas_draw_icon(canvas, 85, 41, &I_ButtonUp_7x4); - canvas_draw_icon(canvas, 85, 57, &I_ButtonDown_7x4); - canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7); - canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7); canvas_draw_icon(canvas, 3, 48, &I_Pin_star_7x7); canvas_set_font(canvas, FontPrimary); @@ -87,8 +89,8 @@ static void draw_callback(Canvas* canvas, void* ctx) { canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 85, 55, "S"); - canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7); - canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7); + //canvas_draw_icon(canvas, 59, 48, &I_ButtonLeft_4x7); + //canvas_draw_icon(canvas, 72, 48, &I_ButtonRight_4x7); if(Work) { canvas_draw_icon(canvas, 106, 46, &I_loading_10px); @@ -151,6 +153,10 @@ int32_t zeitraffer_app(void* p) { FlipperFormat* load = flipper_format_file_alloc(storage); do { + if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { + notification_message(notifications, &sequence_error); + break; + } if(!flipper_format_file_open_existing(load, CONFIG_FILE_PATH)) { notification_message(notifications, &sequence_error); break; @@ -247,6 +253,8 @@ int32_t zeitraffer_app(void* p) { if(WorkTime == 0) WorkTime = Delay; + if(Count == 1) WorkTime = Time; + if(Count == 0) { InfiniteShot = true; WorkCount = 1; @@ -390,7 +398,7 @@ int32_t zeitraffer_app(void* p) { } if(!flipper_format_write_comment_cstr( save, - "Zeitraffer app settings: n of frames, interval time, backlight type, Delay")) { + "Zeitraffer app settings: № of frames, interval time, backlight type, Delay")) { notification_message(notifications, &sequence_error); break; } diff --git a/applications/external/totp/lib/roll_value/roll_value.c b/applications/external/totp/lib/roll_value/roll_value.c index 326c7846a..563429d0d 100644 --- a/applications/external/totp/lib/roll_value/roll_value.c +++ b/applications/external/totp/lib/roll_value/roll_value.c @@ -25,4 +25,4 @@ TOTP_ROLL_VALUE_FN(int8_t, int8_t) TOTP_ROLL_VALUE_FN(uint8_t, int8_t) -TOTP_ROLL_VALUE_FN(size_t, int16_t); \ No newline at end of file +TOTP_ROLL_VALUE_FN(size_t, int16_t) \ No newline at end of file diff --git a/applications/external/totp/workers/type_code_common.c b/applications/external/totp/workers/type_code_common.c index 696df3b1f..bf5818ab2 100644 --- a/applications/external/totp/workers/type_code_common.c +++ b/applications/external/totp/workers/type_code_common.c @@ -30,7 +30,7 @@ static uint32_t get_keypress_delay(TokenAutomationFeature features) { } static void totp_type_code_worker_press_key( - uint8_t key, + uint16_t key, TOTP_AUTOMATION_KEY_HANDLER key_press_fn, TOTP_AUTOMATION_KEY_HANDLER key_release_fn, TokenAutomationFeature features) { @@ -47,8 +47,6 @@ void totp_type_code_worker_execute_automation( TokenAutomationFeature features) { furi_delay_ms(500); uint8_t i = 0; - totp_type_code_worker_press_key( - HID_KEYBOARD_CAPS_LOCK, key_press_fn, key_release_fn, features); while(i < code_buffer_size && code_buffer[i] != 0) { uint8_t char_index = CONVERT_CHAR_TO_DIGIT(code_buffer[i]); @@ -58,7 +56,11 @@ void totp_type_code_worker_execute_automation( if(char_index > 35) break; - uint8_t hid_kb_key = hid_number_keys[char_index]; + uint16_t hid_kb_key = hid_number_keys[char_index]; + if(char_index > 9) { + hid_kb_key |= KEY_MOD_LEFT_SHIFT; + } + totp_type_code_worker_press_key(hid_kb_key, key_press_fn, key_release_fn, features); furi_delay_ms(get_keystroke_delay(features)); i++; @@ -74,7 +76,4 @@ void totp_type_code_worker_execute_automation( furi_delay_ms(get_keystroke_delay(features)); totp_type_code_worker_press_key(HID_KEYBOARD_TAB, key_press_fn, key_release_fn, features); } - - totp_type_code_worker_press_key( - HID_KEYBOARD_CAPS_LOCK, key_press_fn, key_release_fn, features); } \ No newline at end of file diff --git a/applications/external/usb_hid_autofire/CHANGELOG.md b/applications/external/usb_hid_autofire/CHANGELOG.md deleted file mode 100644 index d0924edd3..000000000 --- a/applications/external/usb_hid_autofire/CHANGELOG.md +++ /dev/null @@ -1,13 +0,0 @@ -# Changelog - -## 0.4 -- Show active/inactive state in primary font (bold) - -## 0.3 -- Add a delay between key-presses (with left/right buttons) - -## 0.2 -- Update icon - -## 0.1 -- Initial release of the USB HID Autofire application diff --git a/applications/external/usb_hid_autofire/LICENSE b/applications/external/usb_hid_autofire/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/applications/external/usb_hid_autofire/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/applications/external/usb_hid_autofire/application.fam b/applications/external/usb_hid_autofire/application.fam deleted file mode 100644 index 9e7b9378c..000000000 --- a/applications/external/usb_hid_autofire/application.fam +++ /dev/null @@ -1,13 +0,0 @@ -App( - appid="usb_hid_autofire", - name="USB HID Autofire", - apptype=FlipperAppType.EXTERNAL, - entry_point="usb_hid_autofire_app", - cdefines=["APP_USB_HID_AUTOFIRE"], - requires=[ - "gui", - ], - stack_size=1 * 1024, - fap_icon="usb_hid_autofire.png", - fap_category="Misc", -) diff --git a/applications/external/usb_hid_autofire/tools.c b/applications/external/usb_hid_autofire/tools.c deleted file mode 100644 index 566d00564..000000000 --- a/applications/external/usb_hid_autofire/tools.c +++ /dev/null @@ -1,50 +0,0 @@ -// -// Tools for USB HID Autofire -// - -void strrev(char* arr, int start, int end) { - char temp; - - if(start >= end) return; - - temp = *(arr + start); - *(arr + start) = *(arr + end); - *(arr + end) = temp; - - start++; - end--; - strrev(arr, start, end); -} - -char* itoa(int number, char* arr, int base) { - int i = 0, r, negative = 0; - - if(number == 0) { - arr[i] = '0'; - arr[i + 1] = '\0'; - return arr; - } - - if(number < 0 && base == 10) { - number *= -1; - negative = 1; - } - - while(number != 0) { - r = number % base; - arr[i] = (r > 9) ? (r - 10) + 'a' : r + '0'; - i++; - number /= base; - } - - if(negative) { - arr[i] = '-'; - i++; - } - - strrev(arr, 0, i - 1); - - arr[i] = '\0'; - - return arr; -} diff --git a/applications/external/usb_hid_autofire/tools.h b/applications/external/usb_hid_autofire/tools.h deleted file mode 100644 index 7e5226514..000000000 --- a/applications/external/usb_hid_autofire/tools.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef FLIPPERZERO_FIRMWARE_TOOLS_H -#define FLIPPERZERO_FIRMWARE_TOOLS_H - -void strrev(char* arr, int start, int end); -char* itoa(int number, char* arr, int base); - -#endif //FLIPPERZERO_FIRMWARE_TOOLS_H diff --git a/applications/external/usb_hid_autofire/usb_hid_autofire.c b/applications/external/usb_hid_autofire/usb_hid_autofire.c deleted file mode 100644 index cf8077ae7..000000000 --- a/applications/external/usb_hid_autofire/usb_hid_autofire.c +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include -#include -#include -#include "version.h" -#include "tools.h" - -// Uncomment to be able to make a screenshot -//#define USB_HID_AUTOFIRE_SCREENSHOT - -typedef enum { - EventTypeInput, -} EventType; - -typedef struct { - union { - InputEvent input; - }; - EventType type; -} UsbMouseEvent; - -bool btn_left_autofire = false; -uint32_t autofire_delay = 10; - -static void usb_hid_autofire_render_callback(Canvas* canvas, void* ctx) { - UNUSED(ctx); - char autofire_delay_str[12]; - //std::string pi = "pi is " + std::to_string(3.1415926); - itoa(autofire_delay, autofire_delay_str, 10); - //sprintf(autofire_delay_str, "%lu", autofire_delay); - - canvas_clear(canvas); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 0, 10, "USB HID Autofire"); - canvas_draw_str(canvas, 0, 34, btn_left_autofire ? "" : ""); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 90, 10, "v"); - canvas_draw_str(canvas, 96, 10, VERSION); - canvas_draw_str(canvas, 0, 22, "Press [ok] for auto left clicking"); - canvas_draw_str(canvas, 0, 46, "delay [ms]:"); - canvas_draw_str(canvas, 50, 46, autofire_delay_str); - canvas_draw_str(canvas, 0, 63, "Press [back] to exit"); -} - -static void usb_hid_autofire_input_callback(InputEvent* input_event, void* ctx) { - FuriMessageQueue* event_queue = ctx; - - UsbMouseEvent event; - event.type = EventTypeInput; - event.input = *input_event; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -int32_t usb_hid_autofire_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(UsbMouseEvent)); - furi_check(event_queue); - ViewPort* view_port = view_port_alloc(); - - FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); -#ifndef USB_HID_AUTOFIRE_SCREENSHOT - furi_hal_usb_unlock(); - furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true); -#endif - - view_port_draw_callback_set(view_port, usb_hid_autofire_render_callback, NULL); - view_port_input_callback_set(view_port, usb_hid_autofire_input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - UsbMouseEvent event; - while(1) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 50); - - if(event_status == FuriStatusOk) { - if(event.type == EventTypeInput) { - if(event.input.key == InputKeyBack) { - break; - } - - if(event.input.type != InputTypeRelease) { - continue; - } - - switch(event.input.key) { - case InputKeyOk: - btn_left_autofire = !btn_left_autofire; - break; - case InputKeyLeft: - if(autofire_delay > 0) { - autofire_delay -= 10; - } - break; - case InputKeyRight: - autofire_delay += 10; - break; - default: - break; - } - } - } - - if(btn_left_autofire) { - furi_hal_hid_mouse_press(HID_MOUSE_BTN_LEFT); - // TODO: Don't wait, but use the timer directly to just don't send the release event (see furi_hal_cortex_delay_us) - furi_delay_us(autofire_delay * 500); - furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT); - furi_delay_us(autofire_delay * 500); - } - - view_port_update(view_port); - } - - furi_hal_usb_set_config(usb_mode_prev, NULL); - - // remove & free all stuff created by app - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - furi_message_queue_free(event_queue); - - return 0; -} diff --git a/applications/external/usb_hid_autofire/usb_hid_autofire.kra b/applications/external/usb_hid_autofire/usb_hid_autofire.kra deleted file mode 100644 index 21d416548..000000000 Binary files a/applications/external/usb_hid_autofire/usb_hid_autofire.kra and /dev/null differ diff --git a/applications/external/usb_hid_autofire/usb_hid_autofire.png b/applications/external/usb_hid_autofire/usb_hid_autofire.png deleted file mode 100644 index 369bff022..000000000 Binary files a/applications/external/usb_hid_autofire/usb_hid_autofire.png and /dev/null differ diff --git a/applications/external/usb_hid_autofire/usb_hid_autofire.svg b/applications/external/usb_hid_autofire/usb_hid_autofire.svg deleted file mode 100644 index ed66f3cfd..000000000 --- a/applications/external/usb_hid_autofire/usb_hid_autofire.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - A - - diff --git a/applications/external/usb_hid_autofire/version.h b/applications/external/usb_hid_autofire/version.h deleted file mode 100644 index ac1f5d0fa..000000000 --- a/applications/external/usb_hid_autofire/version.h +++ /dev/null @@ -1 +0,0 @@ -#define VERSION "0.4" diff --git a/applications/external/wav_player/wav_parser.c b/applications/external/wav_player/wav_parser.c index 1f534bacb..8c1f22b19 100644 --- a/applications/external/wav_player/wav_parser.c +++ b/applications/external/wav_player/wav_parser.c @@ -11,7 +11,7 @@ const char* format_text(FormatTag tag) { default: return "Unknown"; } -}; +} struct WavParser { WavHeaderChunk header; diff --git a/applications/external/weather_station/protocols/wendox_w6726.c b/applications/external/weather_station/protocols/wendox_w6726.c index 265c77f70..2fbe961f7 100644 --- a/applications/external/weather_station/protocols/wendox_w6726.c +++ b/applications/external/weather_station/protocols/wendox_w6726.c @@ -5,7 +5,7 @@ /* * Wendox W6726 * - * Temperature -50 to +70 + * Temperature -50C to +70C * _ _ _ __ _ * _| |___| |___| |___ ... | |_| |__...._______________ * preamble data guard time @@ -22,7 +22,7 @@ * * I: identification; * Z: temperature sign; - * T: temperature sign dependent +12 Ѱ; + * T: temperature sign dependent +12C; * B: battery low; flag to indicate low battery voltage; * C: CRC4 (polynomial = 0x9, start_data = 0xD); * u: unknown; diff --git a/applications/external/weather_station/scenes/weather_station_receiver.c b/applications/external/weather_station/scenes/weather_station_receiver.c index e76810430..79d01f13d 100644 --- a/applications/external/weather_station/scenes/weather_station_receiver.c +++ b/applications/external/weather_station/scenes/weather_station_receiver.c @@ -133,7 +133,7 @@ void weather_station_scene_receiver_on_enter(void* context) { if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); - }; + } if((app->txrx->txrx_state == WSTxRxStateIDLE) || (app->txrx->txrx_state == WSTxRxStateSleep)) { ws_begin( app, @@ -157,7 +157,7 @@ bool weather_station_scene_receiver_on_event(void* context, SceneManagerEvent ev if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); ws_sleep(app); - }; + } app->txrx->hopper_state = WSHopperStateOFF; app->txrx->idx_menu_chosen = 0; subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, app); diff --git a/applications/external/weather_station/views/weather_station_receiver.c b/applications/external/weather_station/views/weather_station_receiver.c index 62f1adad0..e994e7830 100644 --- a/applications/external/weather_station/views/weather_station_receiver.c +++ b/applications/external/weather_station/views/weather_station_receiver.c @@ -12,7 +12,7 @@ #define MENU_ITEMS 4u #define UNLOCK_CNT 3 -#define SUBGHZ_RAW_TRESHOLD_MIN -90.0f +#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f typedef struct { FuriString* item_str; uint8_t type; @@ -69,10 +69,10 @@ void ws_view_receiver_set_rssi(WSReceiver* instance, float rssi) { instance->view, WSReceiverModel * model, { - if(rssi < SUBGHZ_RAW_TRESHOLD_MIN) { + if(rssi < SUBGHZ_RAW_THRESHOLD_MIN) { model->u_rssi = 0; } else { - model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_TRESHOLD_MIN); + model->u_rssi = (uint8_t)(rssi - SUBGHZ_RAW_THRESHOLD_MIN); } }, true); diff --git a/applications/external/weather_station/weather_station_app_i.c b/applications/external/weather_station/weather_station_app_i.c index 7236b6625..2e83a6e30 100644 --- a/applications/external/weather_station/weather_station_app_i.c +++ b/applications/external/weather_station/weather_station_app_i.c @@ -146,7 +146,7 @@ void ws_hopper_update(WeatherStationApp* app) { if(app->txrx->txrx_state == WSTxRxStateRx) { ws_rx_end(app); - }; + } if(app->txrx->txrx_state == WSTxRxStateIDLE) { subghz_receiver_reset(app->txrx->receiver); app->txrx->preset->frequency = diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index 89a06f904..2f8b2f9a6 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.3.3" +#define WIFI_MARAUDER_APP_VERSION "v0.3.4" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c b/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c index d9eee83c9..e17e5aaee 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c +++ b/applications/external/wifi_marauder_companion/wifi_marauder_text_input.c @@ -168,31 +168,22 @@ static char char_to_uppercase(const char letter) { switch(letter) { case '_': return 0x20; - break; case '(': return 0x29; - break; case '{': return 0x7d; - break; case '[': return 0x5d; - break; case '/': return 0x5c; - break; case ';': return 0x3a; - break; case '.': return 0x2c; - break; case '!': return 0x3f; - break; case '<': return 0x3e; - break; } if(char_is_lowercase(letter)) { return (letter - 0x20); diff --git a/applications/external/wii_ec_anal/LICENSE b/applications/external/wiiec/LICENSE similarity index 100% rename from applications/external/wii_ec_anal/LICENSE rename to applications/external/wiiec/LICENSE diff --git a/applications/external/wii_ec_anal/WiiEC.png b/applications/external/wiiec/WiiEC.png similarity index 100% rename from applications/external/wii_ec_anal/WiiEC.png rename to applications/external/wiiec/WiiEC.png diff --git a/applications/external/wii_ec_anal/_image_tool/LICENSE b/applications/external/wiiec/_image_tool/LICENSE similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/LICENSE rename to applications/external/wiiec/_image_tool/LICENSE diff --git a/applications/external/wii_ec_anal/_image_tool/README b/applications/external/wiiec/_image_tool/README similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/README rename to applications/external/wiiec/_image_tool/README diff --git a/applications/external/wii_ec_anal/_image_tool/_convert.c b/applications/external/wiiec/_image_tool/_convert.c similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/_convert.c rename to applications/external/wiiec/_image_tool/_convert.c diff --git a/applications/external/wii_ec_anal/_image_tool/_convert.sh b/applications/external/wiiec/_image_tool/_convert.sh similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/_convert.sh rename to applications/external/wiiec/_image_tool/_convert.sh diff --git a/applications/external/wii_ec_anal/_image_tool/_convert_images.c b/applications/external/wiiec/_image_tool/_convert_images.c similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/_convert_images.c rename to applications/external/wiiec/_image_tool/_convert_images.c diff --git a/applications/external/wii_ec_anal/_image_tool/_convert_images.h b/applications/external/wiiec/_image_tool/_convert_images.h similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/_convert_images.h rename to applications/external/wiiec/_image_tool/_convert_images.h diff --git a/applications/external/wii_ec_anal/_image_tool/_convert_test.c b/applications/external/wiiec/_image_tool/_convert_test.c similarity index 100% rename from applications/external/wii_ec_anal/_image_tool/_convert_test.c rename to applications/external/wiiec/_image_tool/_convert_test.c diff --git a/applications/external/wii_ec_anal/application.fam b/applications/external/wiiec/application.fam similarity index 100% rename from applications/external/wii_ec_anal/application.fam rename to applications/external/wiiec/application.fam diff --git a/applications/external/wii_ec_anal/bc_logging.h b/applications/external/wiiec/bc_logging.h similarity index 100% rename from applications/external/wii_ec_anal/bc_logging.h rename to applications/external/wiiec/bc_logging.h diff --git a/applications/external/wii_ec_anal/err.h b/applications/external/wiiec/err.h similarity index 100% rename from applications/external/wii_ec_anal/err.h rename to applications/external/wiiec/err.h diff --git a/applications/external/wii_ec_anal/gfx/images.c b/applications/external/wiiec/gfx/images.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/images.c rename to applications/external/wiiec/gfx/images.c diff --git a/applications/external/wii_ec_anal/gfx/images.h b/applications/external/wiiec/gfx/images.h similarity index 100% rename from applications/external/wii_ec_anal/gfx/images.h rename to applications/external/wiiec/gfx/images.h diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_0.c b/applications/external/wiiec/gfx/img_3x5_0.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_0.c rename to applications/external/wiiec/gfx/img_3x5_0.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_1.c b/applications/external/wiiec/gfx/img_3x5_1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_1.c rename to applications/external/wiiec/gfx/img_3x5_1.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_2.c b/applications/external/wiiec/gfx/img_3x5_2.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_2.c rename to applications/external/wiiec/gfx/img_3x5_2.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_3.c b/applications/external/wiiec/gfx/img_3x5_3.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_3.c rename to applications/external/wiiec/gfx/img_3x5_3.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_4.c b/applications/external/wiiec/gfx/img_3x5_4.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_4.c rename to applications/external/wiiec/gfx/img_3x5_4.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_5.c b/applications/external/wiiec/gfx/img_3x5_5.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_5.c rename to applications/external/wiiec/gfx/img_3x5_5.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_6.c b/applications/external/wiiec/gfx/img_3x5_6.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_6.c rename to applications/external/wiiec/gfx/img_3x5_6.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_7.c b/applications/external/wiiec/gfx/img_3x5_7.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_7.c rename to applications/external/wiiec/gfx/img_3x5_7.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_8.c b/applications/external/wiiec/gfx/img_3x5_8.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_8.c rename to applications/external/wiiec/gfx/img_3x5_8.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_9.c b/applications/external/wiiec/gfx/img_3x5_9.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_9.c rename to applications/external/wiiec/gfx/img_3x5_9.c diff --git a/applications/external/wii_ec_anal/gfx/img_3x5_v.c b/applications/external/wiiec/gfx/img_3x5_v.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_3x5_v.c rename to applications/external/wiiec/gfx/img_3x5_v.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_0.c b/applications/external/wiiec/gfx/img_5x7_0.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_0.c rename to applications/external/wiiec/gfx/img_5x7_0.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_1.c b/applications/external/wiiec/gfx/img_5x7_1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_1.c rename to applications/external/wiiec/gfx/img_5x7_1.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_2.c b/applications/external/wiiec/gfx/img_5x7_2.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_2.c rename to applications/external/wiiec/gfx/img_5x7_2.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_3.c b/applications/external/wiiec/gfx/img_5x7_3.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_3.c rename to applications/external/wiiec/gfx/img_5x7_3.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_4.c b/applications/external/wiiec/gfx/img_5x7_4.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_4.c rename to applications/external/wiiec/gfx/img_5x7_4.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_5.c b/applications/external/wiiec/gfx/img_5x7_5.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_5.c rename to applications/external/wiiec/gfx/img_5x7_5.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_6.c b/applications/external/wiiec/gfx/img_5x7_6.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_6.c rename to applications/external/wiiec/gfx/img_5x7_6.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_7.c b/applications/external/wiiec/gfx/img_5x7_7.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_7.c rename to applications/external/wiiec/gfx/img_5x7_7.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_8.c b/applications/external/wiiec/gfx/img_5x7_8.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_8.c rename to applications/external/wiiec/gfx/img_5x7_8.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_9.c b/applications/external/wiiec/gfx/img_5x7_9.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_9.c rename to applications/external/wiiec/gfx/img_5x7_9.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_A.c b/applications/external/wiiec/gfx/img_5x7_A.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_A.c rename to applications/external/wiiec/gfx/img_5x7_A.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_B.c b/applications/external/wiiec/gfx/img_5x7_B.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_B.c rename to applications/external/wiiec/gfx/img_5x7_B.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_C.c b/applications/external/wiiec/gfx/img_5x7_C.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_C.c rename to applications/external/wiiec/gfx/img_5x7_C.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_D.c b/applications/external/wiiec/gfx/img_5x7_D.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_D.c rename to applications/external/wiiec/gfx/img_5x7_D.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_E.c b/applications/external/wiiec/gfx/img_5x7_E.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_E.c rename to applications/external/wiiec/gfx/img_5x7_E.c diff --git a/applications/external/wii_ec_anal/gfx/img_5x7_F.c b/applications/external/wiiec/gfx/img_5x7_F.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_5x7_F.c rename to applications/external/wiiec/gfx/img_5x7_F.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_0.c b/applications/external/wiiec/gfx/img_6x8_0.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_0.c rename to applications/external/wiiec/gfx/img_6x8_0.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_1.c b/applications/external/wiiec/gfx/img_6x8_1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_1.c rename to applications/external/wiiec/gfx/img_6x8_1.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_2.c b/applications/external/wiiec/gfx/img_6x8_2.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_2.c rename to applications/external/wiiec/gfx/img_6x8_2.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_3.c b/applications/external/wiiec/gfx/img_6x8_3.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_3.c rename to applications/external/wiiec/gfx/img_6x8_3.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_4.c b/applications/external/wiiec/gfx/img_6x8_4.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_4.c rename to applications/external/wiiec/gfx/img_6x8_4.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_5.c b/applications/external/wiiec/gfx/img_6x8_5.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_5.c rename to applications/external/wiiec/gfx/img_6x8_5.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_6.c b/applications/external/wiiec/gfx/img_6x8_6.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_6.c rename to applications/external/wiiec/gfx/img_6x8_6.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_7.c b/applications/external/wiiec/gfx/img_6x8_7.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_7.c rename to applications/external/wiiec/gfx/img_6x8_7.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_8.c b/applications/external/wiiec/gfx/img_6x8_8.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_8.c rename to applications/external/wiiec/gfx/img_6x8_8.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_9.c b/applications/external/wiiec/gfx/img_6x8_9.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_9.c rename to applications/external/wiiec/gfx/img_6x8_9.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_A.c b/applications/external/wiiec/gfx/img_6x8_A.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_A.c rename to applications/external/wiiec/gfx/img_6x8_A.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_B.c b/applications/external/wiiec/gfx/img_6x8_B.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_B.c rename to applications/external/wiiec/gfx/img_6x8_B.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_C.c b/applications/external/wiiec/gfx/img_6x8_C.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_C.c rename to applications/external/wiiec/gfx/img_6x8_C.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_D.c b/applications/external/wiiec/gfx/img_6x8_D.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_D.c rename to applications/external/wiiec/gfx/img_6x8_D.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_E.c b/applications/external/wiiec/gfx/img_6x8_E.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_E.c rename to applications/external/wiiec/gfx/img_6x8_E.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_F.c b/applications/external/wiiec/gfx/img_6x8_F.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_F.c rename to applications/external/wiiec/gfx/img_6x8_F.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_G.c b/applications/external/wiiec/gfx/img_6x8_G.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_G.c rename to applications/external/wiiec/gfx/img_6x8_G.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_X.c b/applications/external/wiiec/gfx/img_6x8_X.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_X.c rename to applications/external/wiiec/gfx/img_6x8_X.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_Y.c b/applications/external/wiiec/gfx/img_6x8_Y.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_Y.c rename to applications/external/wiiec/gfx/img_6x8_Y.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_Z.c b/applications/external/wiiec/gfx/img_6x8_Z.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_Z.c rename to applications/external/wiiec/gfx/img_6x8_Z.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_d_.c b/applications/external/wiiec/gfx/img_6x8_d_.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_d_.c rename to applications/external/wiiec/gfx/img_6x8_d_.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_n_.c b/applications/external/wiiec/gfx/img_6x8_n_.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_n_.c rename to applications/external/wiiec/gfx/img_6x8_n_.c diff --git a/applications/external/wii_ec_anal/gfx/img_6x8_v_.c b/applications/external/wiiec/gfx/img_6x8_v_.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_6x8_v_.c rename to applications/external/wiiec/gfx/img_6x8_v_.c diff --git a/applications/external/wii_ec_anal/gfx/img_RIP.c b/applications/external/wiiec/gfx/img_RIP.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_RIP.c rename to applications/external/wiiec/gfx/img_RIP.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_Cable.c b/applications/external/wiiec/gfx/img_cc_Cable.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_Cable.c rename to applications/external/wiiec/gfx/img_cc_Cable.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_Joy.c b/applications/external/wiiec/gfx/img_cc_Joy.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_Joy.c rename to applications/external/wiiec/gfx/img_cc_Joy.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_Main.c b/applications/external/wiiec/gfx/img_cc_Main.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_Main.c rename to applications/external/wiiec/gfx/img_cc_Main.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_btn_A1.c b/applications/external/wiiec/gfx/img_cc_btn_A1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_btn_A1.c rename to applications/external/wiiec/gfx/img_cc_btn_A1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_btn_B1.c b/applications/external/wiiec/gfx/img_cc_btn_B1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_btn_B1.c rename to applications/external/wiiec/gfx/img_cc_btn_B1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_btn_X1.c b/applications/external/wiiec/gfx/img_cc_btn_X1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_btn_X1.c rename to applications/external/wiiec/gfx/img_cc_btn_X1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_btn_Y1.c b/applications/external/wiiec/gfx/img_cc_btn_Y1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_btn_Y1.c rename to applications/external/wiiec/gfx/img_cc_btn_Y1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_pad_LR1.c b/applications/external/wiiec/gfx/img_cc_pad_LR1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_pad_LR1.c rename to applications/external/wiiec/gfx/img_cc_pad_LR1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_pad_UD1.c b/applications/external/wiiec/gfx/img_cc_pad_UD1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_pad_UD1.c rename to applications/external/wiiec/gfx/img_cc_pad_UD1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_L1.c b/applications/external/wiiec/gfx/img_cc_trg_L1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_L1.c rename to applications/external/wiiec/gfx/img_cc_trg_L1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_L2.c b/applications/external/wiiec/gfx/img_cc_trg_L2.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_L2.c rename to applications/external/wiiec/gfx/img_cc_trg_L2.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_L3.c b/applications/external/wiiec/gfx/img_cc_trg_L3.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_L3.c rename to applications/external/wiiec/gfx/img_cc_trg_L3.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_L4.c b/applications/external/wiiec/gfx/img_cc_trg_L4.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_L4.c rename to applications/external/wiiec/gfx/img_cc_trg_L4.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_R1.c b/applications/external/wiiec/gfx/img_cc_trg_R1.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_R1.c rename to applications/external/wiiec/gfx/img_cc_trg_R1.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_R2.c b/applications/external/wiiec/gfx/img_cc_trg_R2.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_R2.c rename to applications/external/wiiec/gfx/img_cc_trg_R2.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_R3.c b/applications/external/wiiec/gfx/img_cc_trg_R3.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_R3.c rename to applications/external/wiiec/gfx/img_cc_trg_R3.c diff --git a/applications/external/wii_ec_anal/gfx/img_cc_trg_R4.c b/applications/external/wiiec/gfx/img_cc_trg_R4.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_cc_trg_R4.c rename to applications/external/wiiec/gfx/img_cc_trg_R4.c diff --git a/applications/external/wii_ec_anal/gfx/img_csLogo_FULL.c b/applications/external/wiiec/gfx/img_csLogo_FULL.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_csLogo_FULL.c rename to applications/external/wiiec/gfx/img_csLogo_FULL.c diff --git a/applications/external/wii_ec_anal/gfx/img_csLogo_Small.c b/applications/external/wiiec/gfx/img_csLogo_Small.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_csLogo_Small.c rename to applications/external/wiiec/gfx/img_csLogo_Small.c diff --git a/applications/external/wii_ec_anal/gfx/img_ecp_SCL.c b/applications/external/wiiec/gfx/img_ecp_SCL.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_ecp_SCL.c rename to applications/external/wiiec/gfx/img_ecp_SCL.c diff --git a/applications/external/wii_ec_anal/gfx/img_ecp_SDA.c b/applications/external/wiiec/gfx/img_ecp_SDA.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_ecp_SDA.c rename to applications/external/wiiec/gfx/img_ecp_SDA.c diff --git a/applications/external/wii_ec_anal/gfx/img_ecp_port.c b/applications/external/wiiec/gfx/img_ecp_port.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_ecp_port.c rename to applications/external/wiiec/gfx/img_ecp_port.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_Back.c b/applications/external/wiiec/gfx/img_key_Back.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_Back.c rename to applications/external/wiiec/gfx/img_key_Back.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_D.c b/applications/external/wiiec/gfx/img_key_D.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_D.c rename to applications/external/wiiec/gfx/img_key_D.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_L.c b/applications/external/wiiec/gfx/img_key_L.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_L.c rename to applications/external/wiiec/gfx/img_key_L.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_OK.c b/applications/external/wiiec/gfx/img_key_OK.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_OK.c rename to applications/external/wiiec/gfx/img_key_OK.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_OKi.c b/applications/external/wiiec/gfx/img_key_OKi.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_OKi.c rename to applications/external/wiiec/gfx/img_key_OKi.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_R.c b/applications/external/wiiec/gfx/img_key_R.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_R.c rename to applications/external/wiiec/gfx/img_key_R.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_U.c b/applications/external/wiiec/gfx/img_key_U.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_U.c rename to applications/external/wiiec/gfx/img_key_U.c diff --git a/applications/external/wii_ec_anal/gfx/img_key_Ui.c b/applications/external/wiiec/gfx/img_key_Ui.c similarity index 100% rename from applications/external/wii_ec_anal/gfx/img_key_Ui.c rename to applications/external/wiiec/gfx/img_key_Ui.c diff --git a/applications/external/wii_ec_anal/i2c_workaround.h b/applications/external/wiiec/i2c_workaround.h similarity index 100% rename from applications/external/wii_ec_anal/i2c_workaround.h rename to applications/external/wiiec/i2c_workaround.h diff --git a/applications/external/wii_ec_anal/info.sh b/applications/external/wiiec/info.sh similarity index 100% rename from applications/external/wii_ec_anal/info.sh rename to applications/external/wiiec/info.sh diff --git a/applications/external/wii_ec_anal/wii_anal.c b/applications/external/wiiec/wii_anal.c similarity index 95% rename from applications/external/wii_ec_anal/wii_anal.c rename to applications/external/wiiec/wii_anal.c index 34b4f318b..5882dd60b 100644 --- a/applications/external/wii_ec_anal/wii_anal.c +++ b/applications/external/wiiec/wii_anal.c @@ -80,6 +80,8 @@ static void showVer(Canvas* const canvas) { show(canvas, 4, 59, VER_MAJ, SHOW_SET_BLK); canvas_draw_frame(canvas, 8, 62, 2, 2); show(canvas, 11, 59, VER_MIN, SHOW_SET_BLK); + canvas_draw_frame(canvas, 15, 62, 2, 2); + show(canvas, 18, 59, VER_SUB, SHOW_SET_BLK); } //+============================================================================ @@ -94,9 +96,10 @@ static void cbDraw(Canvas* const canvas, void* ctx) { furi_assert(canvas); furi_assert(ctx); - // Try to acquire the mutex for the plugin state variables, timeout = 25mS state_t* state = ctx; - furi_mutex_acquire(state->mutex, FuriWaitForever); + + // Try to acquire the mutex for the plugin state variables, timeout = 25mS + if(furi_mutex_acquire(state->mutex, 25) != FuriStatusOk) return; switch(state->scene) { //--------------------------------------------------------------------- @@ -344,8 +347,7 @@ int32_t wii_ec_anal(void) { goto bail; } // 5. Create a mutex for (reading/writing) the plugin state variables - state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!state->mutex) { + if(!(state->mutex = furi_mutex_alloc(FuriMutexTypeNormal))) { ERROR(wii_errs[(error = ERR_NO_MUTEX)]); goto bail; } @@ -434,7 +436,10 @@ int32_t wii_ec_anal(void) { // Read successful // *** Try to lock the plugin state variables *** - furi_mutex_acquire(state->mutex, FuriWaitForever); + if(furi_mutex_acquire(state->mutex, FuriWaitForever) != FuriStatusOk) { + ERROR(wii_errs[(error = ERR_MUTEX_BLOCK)]); + goto bail; + } // *** Handle events *** switch(msg.id) { @@ -472,7 +477,10 @@ int32_t wii_ec_anal(void) { if(redraw) view_port_update(vpp); // *** Try to release the plugin state variables *** - furi_mutex_release(state->mutex); + if(furi_mutex_release(state->mutex) != FuriStatusOk) { + ERROR(wii_errs[(error = ERR_MUTEX_RELEASE)]); + goto bail; + } } while(state->run); // ===== Game Over ===== @@ -480,13 +488,13 @@ int32_t wii_ec_anal(void) { bail: // 10. Release system notification queue - if(state->notify) { + if(state && state->notify) { furi_record_close(RECORD_NOTIFICATION); state->notify = NULL; } // 9. Stop the timer - if(state->timer) { + if(state && state->timer) { (void)furi_timer_stop(state->timer); furi_timer_free(state->timer); state->timer = NULL; @@ -507,7 +515,10 @@ bail: } // 5. Free the mutex - furi_mutex_free(state->mutex); + if(state && state->mutex) { + furi_mutex_free(state->mutex); + state->mutex = NULL; + } // 4. Free up state pointer(s) // none diff --git a/applications/external/wii_ec_anal/wii_anal.h b/applications/external/wiiec/wii_anal.h similarity index 98% rename from applications/external/wii_ec_anal/wii_anal.h rename to applications/external/wiiec/wii_anal.h index d8997b030..3be398a54 100644 --- a/applications/external/wii_ec_anal/wii_anal.h +++ b/applications/external/wiiec/wii_anal.h @@ -56,7 +56,8 @@ typedef struct eventMsg { // Access to this memory is controlled by mutex // typedef struct state { - FuriMutex* mutex; + FuriMutex* mutex; // mutex for using this struct + bool run; // true : plugin is running bool timerEn; // controller scanning enabled diff --git a/applications/external/wii_ec_anal/wii_anal_ec.c b/applications/external/wiiec/wii_anal_ec.c similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_ec.c rename to applications/external/wiiec/wii_anal_ec.c diff --git a/applications/external/wii_ec_anal/wii_anal_ec.h b/applications/external/wiiec/wii_anal_ec.h similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_ec.h rename to applications/external/wiiec/wii_anal_ec.h diff --git a/applications/external/wii_ec_anal/wii_anal_keys.c b/applications/external/wiiec/wii_anal_keys.c similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_keys.c rename to applications/external/wiiec/wii_anal_keys.c diff --git a/applications/external/wii_ec_anal/wii_anal_keys.h b/applications/external/wiiec/wii_anal_keys.h similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_keys.h rename to applications/external/wiiec/wii_anal_keys.h diff --git a/applications/external/wii_ec_anal/wii_anal_lcd.c b/applications/external/wiiec/wii_anal_lcd.c similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_lcd.c rename to applications/external/wiiec/wii_anal_lcd.c diff --git a/applications/external/wii_ec_anal/wii_anal_lcd.h b/applications/external/wiiec/wii_anal_lcd.h similarity index 100% rename from applications/external/wii_ec_anal/wii_anal_lcd.h rename to applications/external/wiiec/wii_anal_lcd.h diff --git a/applications/external/wii_ec_anal/wii_anal_ver.h b/applications/external/wiiec/wii_anal_ver.h similarity index 85% rename from applications/external/wii_ec_anal/wii_anal_ver.h rename to applications/external/wiiec/wii_anal_ver.h index 3f2c8c0e6..df2659d57 100644 --- a/applications/external/wii_ec_anal/wii_anal_ver.h +++ b/applications/external/wiiec/wii_anal_ver.h @@ -5,5 +5,6 @@ #define VER_MAJ &img_3x5_1 #define VER_MIN &img_3x5_0 +#define VER_SUB &img_3x5_1 #endif //WII_ANAL_VER_H_ diff --git a/applications/external/wii_ec_anal/wii_ec.c b/applications/external/wiiec/wii_ec.c similarity index 100% rename from applications/external/wii_ec_anal/wii_ec.c rename to applications/external/wiiec/wii_ec.c diff --git a/applications/external/wii_ec_anal/wii_ec.h b/applications/external/wiiec/wii_ec.h similarity index 100% rename from applications/external/wii_ec_anal/wii_ec.h rename to applications/external/wiiec/wii_ec.h diff --git a/applications/external/wii_ec_anal/wii_ec_classic.c b/applications/external/wiiec/wii_ec_classic.c similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_classic.c rename to applications/external/wiiec/wii_ec_classic.c diff --git a/applications/external/wii_ec_anal/wii_ec_classic.h b/applications/external/wiiec/wii_ec_classic.h similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_classic.h rename to applications/external/wiiec/wii_ec_classic.h diff --git a/applications/external/wii_ec_anal/wii_ec_macros.h b/applications/external/wiiec/wii_ec_macros.h similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_macros.h rename to applications/external/wiiec/wii_ec_macros.h diff --git a/applications/external/wii_ec_anal/wii_ec_nunchuck.c b/applications/external/wiiec/wii_ec_nunchuck.c similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_nunchuck.c rename to applications/external/wiiec/wii_ec_nunchuck.c diff --git a/applications/external/wii_ec_anal/wii_ec_nunchuck.h b/applications/external/wiiec/wii_ec_nunchuck.h similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_nunchuck.h rename to applications/external/wiiec/wii_ec_nunchuck.h diff --git a/applications/external/wii_ec_anal/wii_ec_udraw.c b/applications/external/wiiec/wii_ec_udraw.c similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_udraw.c rename to applications/external/wiiec/wii_ec_udraw.c diff --git a/applications/external/wii_ec_anal/wii_ec_udraw.h b/applications/external/wiiec/wii_ec_udraw.h similarity index 100% rename from applications/external/wii_ec_anal/wii_ec_udraw.h rename to applications/external/wiiec/wii_ec_udraw.h diff --git a/applications/external/wii_ec_anal/wii_i2c.c b/applications/external/wiiec/wii_i2c.c similarity index 100% rename from applications/external/wii_ec_anal/wii_i2c.c rename to applications/external/wiiec/wii_i2c.c diff --git a/applications/external/wii_ec_anal/wii_i2c.h b/applications/external/wiiec/wii_i2c.h similarity index 100% rename from applications/external/wii_ec_anal/wii_i2c.h rename to applications/external/wiiec/wii_i2c.h diff --git a/applications/main/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c index 9d4b963f5..9f3039041 100644 --- a/applications/main/archive/helpers/archive_favorites.c +++ b/applications/main/archive/helpers/archive_favorites.c @@ -140,13 +140,6 @@ bool archive_favorites_read(void* context) { bool result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); - if(!result) { - storage_file_close(file); - storage_common_copy(storage, ARCHIVE_FAV_OLD_PATH, ARCHIVE_FAV_PATH); - storage_common_remove(storage, ARCHIVE_FAV_OLD_PATH); - result = storage_file_open(file, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); - } - if(result) { while(1) { if(!archive_favorites_read_line(file, buffer)) { diff --git a/applications/main/archive/helpers/favorite_timeout.c b/applications/main/archive/helpers/favorite_timeout.c new file mode 100644 index 000000000..7643ebfc8 --- /dev/null +++ b/applications/main/archive/helpers/favorite_timeout.c @@ -0,0 +1,32 @@ +#include "favorite_timeout.h" +#include + +bool process_favorite_launch(char** args) { + if(*args && strlen(*args) > 4 && strncmp(*args, "fav/", 4) == 0) { + *args += 3; + return true; + } + return false; +} + +void favorite_timeout_callback(void* _ctx) { + FavoriteTImeoutCtx* ctx = _ctx; + while(scene_manager_previous_scene(ctx->scene_manager)) + ; + view_dispatcher_stop(ctx->view_dispatcher); +} + +void favorite_timeout_run(ViewDispatcher* view_dispatcher, SceneManager* scene_manager) { + int32_t timeout = XTREME_SETTINGS()->favorite_timeout; + if(timeout == 0) { + view_dispatcher_run(view_dispatcher); + return; + } + + FavoriteTImeoutCtx ctx = {.view_dispatcher = view_dispatcher, .scene_manager = scene_manager}; + FuriTimer* timer = furi_timer_alloc(favorite_timeout_callback, FuriTimerTypeOnce, &ctx); + furi_timer_start(timer, timeout * furi_kernel_get_tick_frequency()); + view_dispatcher_run(view_dispatcher); + furi_timer_stop(timer); + furi_timer_free(timer); +} diff --git a/applications/main/archive/helpers/favorite_timeout.h b/applications/main/archive/helpers/favorite_timeout.h new file mode 100644 index 000000000..aded05708 --- /dev/null +++ b/applications/main/archive/helpers/favorite_timeout.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +bool process_favorite_launch(char** p); + +typedef struct { + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; +} FavoriteTImeoutCtx; + +void favorite_timeout_callback(void* _ctx); + +void favorite_timeout_run(ViewDispatcher* view_dispatcher, SceneManager* scene_manager); diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index 3154fbec6..f0884ab73 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -36,7 +36,8 @@ static void archive_loader_callback(const void* message, void* context) { } } -static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected) { +static void + archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selected, bool favorites) { UNUSED(browser); Loader* loader = furi_record_open(RECORD_LOADER); @@ -48,8 +49,14 @@ static void archive_run_in_app(ArchiveBrowserView* browser, ArchiveFile_t* selec } status = loader_start(loader, flipper_app_name[selected->type], param); } else { - status = loader_start( - loader, flipper_app_name[selected->type], furi_string_get_cstr(selected->path)); + const char* str = furi_string_get_cstr(selected->path); + if(favorites) { + char arg[strlen(str) + 4]; + snprintf(arg, sizeof(arg), "fav%s", str); + status = loader_start(loader, flipper_app_name[selected->type], arg); + } else { + status = loader_start(loader, flipper_app_name[selected->type], str); + } } if(status != LoaderStatusOk) { @@ -113,7 +120,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { archive_show_file_menu(browser, false); archive_enter_dir(browser, selected->path); } else if(archive_is_known_app(selected->type)) { - archive_run_in_app(browser, selected); + archive_run_in_app(browser, selected, favorites); archive_show_file_menu(browser, false); } consumed = true; diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index 6e42cb40b..cc2ed6263 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -324,7 +324,7 @@ static void archive_render_status_bar(Canvas* canvas, ArchiveBrowserViewModel* m const char* tab_name = ArchiveTabNames[model->tab_idx]; - canvas_draw_icon(canvas, 0, 0, &I_Background_128x11); + canvas_draw_icon(canvas, 0, 0, XTREME_ASSETS()->I_Background_128x11); canvas_set_color(canvas, ColorWhite); canvas_draw_box(canvas, 0, 0, 50, 13); diff --git a/applications/main/bad_kb/bad_kb_app.c b/applications/main/bad_kb/bad_kb_app.c index 94a74aa92..03b941cd3 100644 --- a/applications/main/bad_kb/bad_kb_app.c +++ b/applications/main/bad_kb/bad_kb_app.c @@ -1,23 +1,15 @@ #include "bad_kb_app.h" -#include "bad_kb_settings_filename.h" #include #include #include #include #include #include +#include #include #include -#define BAD_KB_SETTINGS_PATH BAD_KB_APP_BASE_FOLDER "/" BAD_KB_SETTINGS_FILE_NAME - -// this is the MAC address used when we do not forget paired device (BOUND STATE) -const uint8_t BAD_KB_BOUND_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN] = - {0x41, 0x4a, 0xef, 0xb6, 0xa9, 0xd4}; -const uint8_t BAD_KB_EMPTY_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN] = - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - static bool bad_kb_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); BadKbApp* app = context; @@ -110,9 +102,13 @@ int32_t bad_kb_config_switch_mode(BadKbApp* app) { XTREME_SETTINGS_SAVE(); bad_kb_reload_worker(app); if(app->is_bt) furi_hal_bt_start_advertising(); + bad_kb_config_refresh_menu(app); + return 0; +} + +void bad_kb_config_refresh_menu(BadKbApp* app) { scene_manager_next_scene(app->scene_manager, BadKbSceneConfig); scene_manager_previous_scene(app->scene_manager); - return 0; } void bad_kb_config_switch_remember_mode(BadKbApp* app) { @@ -143,7 +139,7 @@ int32_t bad_kb_connection_init(BadKbApp* app) { bt_timeout = bt_hid_delays[LevelRssi39_0]; bt_disconnect(app->bt); - bt_keys_storage_set_storage_path(app->bt, BAD_KB_APP_PATH_BOUND_KEYS_FILE); + bt_keys_storage_set_storage_path(app->bt, BAD_KB_KEYS_PATH); if(strcmp(app->config.bt_name, "") != 0) { furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->config.bt_name); } @@ -204,6 +200,7 @@ BadKbApp* bad_kb_app_alloc(char* arg) { app->file_path = furi_string_alloc(); app->keyboard_layout = furi_string_alloc(); + process_favorite_launch(&arg); if(arg && strlen(arg)) { furi_string_set(app->file_path, arg); } @@ -336,8 +333,8 @@ void bad_kb_app_free(BadKbApp* app) { free(app); } -int32_t bad_kb_app(void* p) { - BadKbApp* bad_kb_app = bad_kb_app_alloc((char*)p); +int32_t bad_kb_app(char* p) { + BadKbApp* bad_kb_app = bad_kb_app_alloc(p); view_dispatcher_run(bad_kb_app->view_dispatcher); diff --git a/applications/main/bad_kb/bad_kb_app.h b/applications/main/bad_kb/bad_kb_app.h index 923ba7780..20bc87ce4 100644 --- a/applications/main/bad_kb/bad_kb_app.h +++ b/applications/main/bad_kb/bad_kb_app.h @@ -1,6 +1,7 @@ #pragma once #include "bad_kb_app.h" +#include "bad_kb_paths.h" #include "scenes/bad_kb_scene.h" #include "helpers/ducky_script.h" @@ -10,8 +11,6 @@ #include #include -#define BAD_KB_APP_BASE_FOLDER EXT_PATH("badkb") -#define BAD_KB_APP_PATH_LAYOUT_FOLDER BAD_KB_APP_BASE_FOLDER "/assets/layouts" #define BAD_KB_APP_SCRIPT_EXTENSION ".txt" #define BAD_KB_APP_LAYOUT_EXTENSION ".kl" diff --git a/applications/main/bad_kb/bad_kb_paths.h b/applications/main/bad_kb/bad_kb_paths.h new file mode 100644 index 000000000..72685b905 --- /dev/null +++ b/applications/main/bad_kb/bad_kb_paths.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +#define BAD_KB_APP_BASE_FOLDER EXT_PATH("badkb") +#define BAD_KB_KEYS_PATH BAD_KB_APP_BASE_FOLDER "/.badkb.keys" +#define BAD_KB_SETTINGS_PATH BAD_KB_APP_BASE_FOLDER "/.badkb.settings" +#define BAD_KB_APP_PATH_LAYOUT_FOLDER BAD_KB_APP_BASE_FOLDER "/assets/layouts" diff --git a/applications/main/bad_kb/bad_kb_settings_filename.h b/applications/main/bad_kb/bad_kb_settings_filename.h deleted file mode 100644 index 42de4878a..000000000 --- a/applications/main/bad_kb/bad_kb_settings_filename.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -#define BAD_KB_SETTINGS_FILE_NAME ".badkb.settings" -#define BAD_KB_APP_PATH_BOUND_KEYS_FOLDER EXT_PATH("badkb/.bt_keys") -#define BAD_KB_APP_PATH_BOUND_KEYS_FILE BAD_KB_APP_PATH_BOUND_KEYS_FOLDER "/.devices.keys" diff --git a/applications/main/bad_kb/helpers/ducky_script.c b/applications/main/bad_kb/helpers/ducky_script.c index 71c307cdf..99754c5fe 100644 --- a/applications/main/bad_kb/helpers/ducky_script.c +++ b/applications/main/bad_kb/helpers/ducky_script.c @@ -12,14 +12,17 @@ #include #include +const uint8_t BAD_KB_BOUND_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN] = + {0x41, 0x4a, 0xef, 0xb6, 0xa9, 0xd4}; +const uint8_t BAD_KB_EMPTY_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN] = + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + #define TAG "BadKB" #define WORKER_TAG TAG "Worker" #define BADKB_ASCII_TO_KEY(script, x) \ (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) -#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys") - /** * Delays for waiting between HID key press and key release */ @@ -383,8 +386,11 @@ static bool ducky_script_preload(BadKbScript* bad_kb, File* script_file) { bad_kb->app->switch_mode_thread = NULL; } // Looking for ID or BT_ID command at first line - bool reset_bt_id = !!bad_kb->bt; - if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { + bad_kb->set_usb_id = false; + bad_kb->set_bt_id = false; + bad_kb->has_usb_id = strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0; + bad_kb->has_bt_id = strncmp(line_tmp, ducky_cmd_bt_id, strlen(ducky_cmd_bt_id)) == 0; + if(bad_kb->has_usb_id) { if(bad_kb->bt) { bad_kb->app->is_bt = false; bad_kb->app->switch_mode_thread = furi_thread_alloc_ex( @@ -395,12 +401,8 @@ static bool ducky_script_preload(BadKbScript* bad_kb, File* script_file) { furi_thread_start(bad_kb->app->switch_mode_thread); return false; } - if(ducky_set_usb_id(bad_kb, &line_tmp[strlen(ducky_cmd_id) + 1])) { - furi_check(furi_hal_usb_set_config(&usb_hid, &bad_kb->hid_cfg)); - } else { - furi_check(furi_hal_usb_set_config(&usb_hid, NULL)); - } - } else if(strncmp(line_tmp, ducky_cmd_bt_id, strlen(ducky_cmd_bt_id)) == 0) { + bad_kb->set_usb_id = ducky_set_usb_id(bad_kb, &line_tmp[strlen(ducky_cmd_id) + 1]); + } else if(bad_kb->has_bt_id) { if(!bad_kb->bt) { bad_kb->app->is_bt = true; bad_kb->app->switch_mode_thread = furi_thread_alloc_ex( @@ -412,12 +414,40 @@ static bool ducky_script_preload(BadKbScript* bad_kb, File* script_file) { return false; } if(!bad_kb->app->bt_remember) { - reset_bt_id = !ducky_set_bt_id(bad_kb, &line_tmp[strlen(ducky_cmd_bt_id) + 1]); + bad_kb->set_bt_id = ducky_set_bt_id(bad_kb, &line_tmp[strlen(ducky_cmd_bt_id) + 1]); } } - if(reset_bt_id) { - furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, bad_kb->app->config.bt_name); - bt_set_profile_mac_address(bad_kb->bt, bad_kb->app->config.bt_mac); + bad_kb_config_refresh_menu(bad_kb->app); + + if(bad_kb->bt) { + if(!bad_kb->set_bt_id) { + const char* bt_name = bad_kb->app->config.bt_name; + const uint8_t* bt_mac = bad_kb->app->bt_remember ? + (uint8_t*)&BAD_KB_BOUND_MAC_ADDRESS : + bad_kb->app->config.bt_mac; + bool reset_name = strncmp( + bt_name, + furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), + BAD_KB_ADV_NAME_MAX_LEN); + bool reset_mac = memcmp( + bt_mac, + furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard), + BAD_KB_MAC_ADDRESS_LEN); + if(reset_name && reset_mac) { + furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, bt_name); + } else if(reset_name) { + bt_set_profile_adv_name(bad_kb->bt, bt_name); + } + if(reset_mac) { + bt_set_profile_mac_address(bad_kb->bt, bt_mac); + } + } + } else { + if(bad_kb->set_usb_id) { + furi_check(furi_hal_usb_set_config(&usb_hid, &bad_kb->hid_cfg)); + } else { + furi_check(furi_hal_usb_set_config(&usb_hid, NULL)); + } } storage_file_seek(script_file, 0, true); diff --git a/applications/main/bad_kb/helpers/ducky_script.h b/applications/main/bad_kb/helpers/ducky_script.h index 6a0386cf1..6c0098524 100644 --- a/applications/main/bad_kb/helpers/ducky_script.h +++ b/applications/main/bad_kb/helpers/ducky_script.h @@ -82,6 +82,11 @@ typedef struct { FuriString* string_print; size_t string_print_pos; + bool set_usb_id; + bool set_bt_id; + bool has_usb_id; + bool has_bt_id; + Bt* bt; BadKbApp* app; } BadKbScript; @@ -103,6 +108,10 @@ BadKbState* bad_kb_script_get_state(BadKbScript* bad_kb); #define BAD_KB_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH #define BAD_KB_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE +// this is the MAC address used when we do not forget paired device (BOUND STATE) +extern const uint8_t BAD_KB_BOUND_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN]; +extern const uint8_t BAD_KB_EMPTY_MAC_ADDRESS[BAD_KB_MAC_ADDRESS_LEN]; + typedef enum { BadKbAppErrorNoFiles, BadKbAppErrorCloseRpc, @@ -143,6 +152,8 @@ struct BadKbApp { int32_t bad_kb_config_switch_mode(BadKbApp* app); +void bad_kb_config_refresh_menu(BadKbApp* app); + #ifdef __cplusplus } #endif diff --git a/applications/main/bad_kb/helpers/ducky_script_commands.c b/applications/main/bad_kb/helpers/ducky_script_commands.c index f23ab2f8a..42ed1b9e8 100644 --- a/applications/main/bad_kb/helpers/ducky_script_commands.c +++ b/applications/main/bad_kb/helpers/ducky_script_commands.c @@ -171,6 +171,7 @@ static int32_t ducky_fnc_waitforbutton(BadKbScript* bad_kb, const char* line, in static const DuckyCmd ducky_commands[] = { {"REM", NULL, -1}, {"ID", NULL, -1}, + {"BT_ID", NULL, -1}, {"DELAY", ducky_fnc_delay, -1}, {"STRING", ducky_fnc_string, 0}, {"STRINGLN", ducky_fnc_string, 1}, diff --git a/applications/main/bad_kb/scenes/bad_kb_scene_config.c b/applications/main/bad_kb/scenes/bad_kb_scene_config.c index 3f16a4c48..e029d052e 100644 --- a/applications/main/bad_kb/scenes/bad_kb_scene_config.c +++ b/applications/main/bad_kb/scenes/bad_kb_scene_config.c @@ -45,28 +45,36 @@ void bad_kb_scene_config_on_enter(void* context) { var_item_list, "Connection", 2, bad_kb_scene_config_connection_callback, bad_kb); variable_item_set_current_value_index(item, bad_kb->is_bt); variable_item_set_current_value_text(item, bad_kb->is_bt ? "BT" : "USB"); - - item = variable_item_list_add( - var_item_list, "BT Remember", 2, bad_kb_scene_config_bt_remember_callback, bad_kb); - variable_item_set_current_value_index(item, bad_kb->bt_remember); - variable_item_set_current_value_text(item, bad_kb->bt_remember ? "ON" : "OFF"); - variable_item_set_locked(item, !bad_kb->is_bt, "Only in\nBT mode!"); - - item = variable_item_list_add(var_item_list, "BT Device Name", 0, NULL, bad_kb); - variable_item_set_locked(item, !bad_kb->is_bt, "Only in\nBT mode!"); - - item = variable_item_list_add(var_item_list, "BT MAC Address", 0, NULL, bad_kb); - if(!bad_kb->is_bt) { - variable_item_set_locked(item, true, "Only in\nBT mode!"); - } else if(bad_kb->bt_remember) { - variable_item_set_locked(item, true, "Remember\nmust be Off!"); + if(bad_kb->bad_kb_script->has_usb_id) { + variable_item_set_locked(item, true, "Script has\nID cmd!\nLocked to\nUSB Mode!"); + } else if(bad_kb->bad_kb_script->has_bt_id) { + variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nBT Mode!"); } - item = variable_item_list_add(var_item_list, "Randomize BT MAC", 0, NULL, bad_kb); - if(!bad_kb->is_bt) { - variable_item_set_locked(item, true, "Only in\nBT mode!"); - } else if(bad_kb->bt_remember) { - variable_item_set_locked(item, true, "Remember\nmust be Off!"); + if(bad_kb->is_bt) { + item = variable_item_list_add( + var_item_list, "BT Remember", 2, bad_kb_scene_config_bt_remember_callback, bad_kb); + variable_item_set_current_value_index(item, bad_kb->bt_remember); + variable_item_set_current_value_text(item, bad_kb->bt_remember ? "ON" : "OFF"); + + item = variable_item_list_add(var_item_list, "BT Device Name", 0, NULL, bad_kb); + if(bad_kb->bad_kb_script->set_bt_id) { + variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset Name!"); + } + + item = variable_item_list_add(var_item_list, "BT MAC Address", 0, NULL, bad_kb); + if(bad_kb->bt_remember) { + variable_item_set_locked(item, true, "Remember\nmust be Off!"); + } else if(bad_kb->bad_kb_script->set_bt_id) { + variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!"); + } + + item = variable_item_list_add(var_item_list, "Randomize BT MAC", 0, NULL, bad_kb); + if(bad_kb->bt_remember) { + variable_item_set_locked(item, true, "Remember\nmust be Off!"); + } else if(bad_kb->bad_kb_script->set_bt_id) { + variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!"); + } } variable_item_list_set_enter_callback( diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index b313d67ad..2a06e348c 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -12,6 +12,7 @@ #include #include #include +#include #define TAG "FapLoader" @@ -241,8 +242,9 @@ static void fap_loader_free(FapLoader* loader) { free(loader); } -int32_t fap_loader_app(void* p) { +int32_t fap_loader_app(char* p) { FapLoader* loader; + process_favorite_launch(&p); if(p) { loader = fap_loader_alloc((const char*)p); view_dispatcher_switch_to_view(loader->view_dispatcher, 0); @@ -256,7 +258,7 @@ int32_t fap_loader_app(void* p) { if(fap_loader_run_selected_app(loader, false)) { fap_loader_run_selected_app(loader, true); } - }; + } } fap_loader_free(loader); diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index 79999adb2..3fea2d2f6 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -2,6 +2,7 @@ #include #include +#include #define TAG "iButtonApp" @@ -258,13 +259,14 @@ void ibutton_widget_callback(GuiButtonType result, InputType type, void* context } } -int32_t ibutton_app(void* arg) { +int32_t ibutton_app(char* arg) { iButton* ibutton = ibutton_alloc(); ibutton_make_app_folder(ibutton); bool key_loaded = false; + bool is_favorite = process_favorite_launch(&arg); if((arg != NULL) && (strlen(arg) != 0)) { if(sscanf(arg, "RPC %lX", (uint32_t*)&ibutton->rpc) == 1) { FURI_LOG_D(TAG, "Running in RPC mode"); @@ -295,7 +297,11 @@ int32_t ibutton_app(void* arg) { } } - view_dispatcher_run(ibutton->view_dispatcher); + if(is_favorite) { + favorite_timeout_run(ibutton->view_dispatcher, ibutton->scene_manager); + } else { + view_dispatcher_run(ibutton->view_dispatcher); + } if(ibutton->rpc) { rpc_system_app_set_callback(ibutton->rpc, NULL, NULL); diff --git a/applications/main/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c index 54bc808b5..12da64fcc 100644 --- a/applications/main/ibutton/ibutton_cli.c +++ b/applications/main/ibutton/ibutton_cli.c @@ -31,7 +31,7 @@ static void ibutton_cli_print_usage() { printf("\tCyfral (2 bytes key_data)\r\n"); printf("\tMetakom (4 bytes key_data), must contain correct parity\r\n"); printf("\t are hex-formatted\r\n"); -}; +} static bool ibutton_cli_parse_key(iButtonProtocols* protocols, iButtonKey* key, FuriString* args) { bool result = false; @@ -124,7 +124,7 @@ static void ibutton_cli_read(Cli* cli) { ibutton_protocols_free(protocols); furi_event_flag_free(event); -}; +} typedef struct { FuriEventFlag* event; @@ -216,7 +216,7 @@ void ibutton_cli_emulate(Cli* cli, FuriString* args) { while(!cli_cmd_interrupt_received(cli)) { furi_delay_ms(100); - }; + } } while(false); @@ -226,7 +226,7 @@ void ibutton_cli_emulate(Cli* cli, FuriString* args) { ibutton_key_free(key); ibutton_worker_free(worker); ibutton_protocols_free(protocols); -}; +} void ibutton_cli(Cli* cli, FuriString* args, void* context) { UNUSED(cli); diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared.c index b8195941b..0d52cc3bf 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared.c @@ -2,6 +2,7 @@ #include #include +#include #define INFRARED_TX_MIN_INTERVAL_MS 50U @@ -246,6 +247,11 @@ static void infrared_free(Infrared* infrared) { furi_string_free(infrared->file_path); + // Disable 5v power if was enabled for external module + if(furi_hal_power_is_otg_enabled()) { + furi_hal_power_disable_otg(); + } + free(infrared); } @@ -435,7 +441,7 @@ void infrared_popup_closed_callback(void* context) { infrared->view_dispatcher, InfraredCustomEventTypePopupClosed); } -int32_t infrared_app(void* p) { +int32_t infrared_app(char* p) { Infrared* infrared = infrared_alloc(); infrared_make_app_folder(infrared); @@ -443,6 +449,7 @@ int32_t infrared_app(void* p) { bool is_remote_loaded = false; bool is_rpc_mode = false; + process_favorite_launch(&p); if(p && strlen(p)) { uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { @@ -478,8 +485,6 @@ int32_t infrared_app(void* p) { view_dispatcher_run(infrared->view_dispatcher); - furi_hal_power_disable_otg(); - infrared_free(infrared); return 0; } diff --git a/applications/main/infrared/scenes/infrared_scene_debug_settings.c b/applications/main/infrared/scenes/infrared_scene_debug_settings.c index 28ec7dfdc..bef666275 100644 --- a/applications/main/infrared/scenes/infrared_scene_debug_settings.c +++ b/applications/main/infrared/scenes/infrared_scene_debug_settings.c @@ -27,7 +27,9 @@ static void infrared_scene_debug_settings_power_changed(VariableItem* item) { furi_delay_ms(10); } } else { - furi_hal_power_disable_otg(); + if(furi_hal_power_is_otg_enabled()) { + furi_hal_power_disable_otg(); + } } variable_item_set_current_value_text(item, value ? "ON" : "OFF"); } diff --git a/applications/main/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c index a671c7592..422b7cce8 100644 --- a/applications/main/infrared/scenes/infrared_scene_start.c +++ b/applications/main/infrared/scenes/infrared_scene_start.c @@ -3,10 +3,10 @@ enum SubmenuIndex { SubmenuIndexUniversalRemotes, SubmenuIndexLearnNewRemote, - SubmenuIndexLearnNewRemoteRaw, SubmenuIndexSavedRemotes, - SubmenuIndexDebug, - SubmenuIndexDebugSettings + SubmenuIndexDebugSettings, + SubmenuIndexLearnNewRemoteRaw, + SubmenuIndexDebug }; static void infrared_scene_start_submenu_callback(void* context, uint32_t index) { @@ -37,6 +37,12 @@ void infrared_scene_start_on_enter(void* context) { SubmenuIndexSavedRemotes, infrared_scene_start_submenu_callback, infrared); + submenu_add_item( + submenu, + "GPIO Settings", + SubmenuIndexDebugSettings, + infrared_scene_start_submenu_callback, + infrared); submenu_add_lockable_item( submenu, @@ -54,14 +60,6 @@ void infrared_scene_start_on_enter(void* context) { infrared, !infrared->app_state.is_debug_enabled, "Enable\nDebug!"); - submenu_add_lockable_item( - submenu, - "Debug Settings", - SubmenuIndexDebugSettings, - infrared_scene_start_submenu_callback, - infrared, - !infrared->app_state.is_debug_enabled, - "Enable\nDebug!"); const uint32_t submenu_index = scene_manager_get_scene_state(scene_manager, InfraredSceneStart); diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index a2bcdcf52..eacb05614 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -1,5 +1,6 @@ #include "lfrfid_i.h" #include +#include static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -168,12 +169,12 @@ static void lfrfid_free(LfRfid* lfrfid) { free(lfrfid); } -int32_t lfrfid_app(void* p) { +int32_t lfrfid_app(char* args) { LfRfid* app = lfrfid_alloc(); - char* args = p; lfrfid_make_app_folder(app); + bool is_favorite = process_favorite_launch(&args); if(args && strlen(args)) { uint32_t rpc_ctx_ptr = 0; if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) { @@ -199,7 +200,11 @@ int32_t lfrfid_app(void* p) { scene_manager_next_scene(app->scene_manager, LfRfidSceneStart); } - view_dispatcher_run(app->view_dispatcher); + if(is_favorite) { + favorite_timeout_run(app->view_dispatcher, app->scene_manager); + } else { + view_dispatcher_run(app->view_dispatcher); + } lfrfid_free(app); diff --git a/applications/main/lfrfid/lfrfid_cli.c b/applications/main/lfrfid/lfrfid_cli.c index a57e40de9..cc1fa2bd7 100644 --- a/applications/main/lfrfid/lfrfid_cli.c +++ b/applications/main/lfrfid/lfrfid_cli.c @@ -30,7 +30,7 @@ static void lfrfid_cli_print_usage() { printf("rfid raw_read \r\n"); printf("rfid raw_emulate \r\n"); printf("rfid raw_analyze \r\n"); -}; +} typedef struct { ProtocolId protocol; diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index f68b7f2f2..9ff82eaa4 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -1,6 +1,7 @@ #include "nfc_i.h" #include #include +#include bool nfc_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -263,14 +264,14 @@ static bool nfc_is_hal_ready() { } } -int32_t nfc_app(void* p) { +int32_t nfc_app(char* p) { if(!nfc_is_hal_ready()) return 0; Nfc* nfc = nfc_alloc(); - char* args = p; // Check argument and run corresponding scene - if(args && strlen(args)) { + bool is_favorite = process_favorite_launch(&p); + if(p && strlen(p)) { nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); uint32_t rpc_ctx = 0; if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { @@ -311,7 +312,11 @@ int32_t nfc_app(void* p) { scene_manager_next_scene(nfc->scene_manager, NfcSceneStart); } - view_dispatcher_run(nfc->view_dispatcher); + if(is_favorite) { + favorite_timeout_run(nfc->view_dispatcher, nfc->scene_manager); + } else { + view_dispatcher_run(nfc->view_dispatcher); + } nfc_free(nfc); diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 6e14e371f..577b9adf1 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -46,7 +46,7 @@ static void nfc_cli_detect(Cli* cli, FuriString* args) { for(size_t i = 0; i < 8; i++) { printf("%02X", dev_data.uid[i]); } - printf("\r\nPMm:"); + printf(", PMm:"); for(size_t i = 0; i < 8; i++) { printf("%02X", dev_data.f_data.pmm[i]); } diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index c02e83787..deaaa4c21 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -20,6 +20,8 @@ ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput) ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock) ADD_SCENE(nfc, nfcv_emulate, NfcVEmulate) ADD_SCENE(nfc, nfcv_sniff, NfcVSniff) +ADD_SCENE(nfc, nfcf_read_success, NfcfReadSuccess) +ADD_SCENE(nfc, nfcf_menu, NfcfMenu) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) diff --git a/applications/main/nfc/scenes/nfc_scene_felica_info_select.c b/applications/main/nfc/scenes/nfc_scene_felica_info_select.c index 3b7c570d7..7a59521fa 100644 --- a/applications/main/nfc/scenes/nfc_scene_felica_info_select.c +++ b/applications/main/nfc/scenes/nfc_scene_felica_info_select.c @@ -19,24 +19,24 @@ void nfc_scene_felica_info_select_on_enter(void* context) { uint8_t i = 1; if(state->selected_system == NULL || state->selected_system->code == LITE_SYSTEM_CODE) { submenu_set_header(submenu, "Systems"); - FelicaSystemList_it_t it; - for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it); - FelicaSystemList_next(it)) { - FelicaSystem* current_system = *FelicaSystemList_ref(it); - FuriString* system_name = felica_get_system_name(current_system); - submenu_add_item( - submenu, - furi_string_get_cstr(system_name), - i++, - nfc_scene_felica_info_select_submenu_callback, - nfc); - furi_string_free(system_name); - } + for + M_EACH(current_system, data->systems, FelicaSystemArray_t) { + FuriString* system_name = felica_get_system_name(current_system); + submenu_add_item( + submenu, + furi_string_get_cstr(system_name), + i++, + nfc_scene_felica_info_select_submenu_callback, + nfc); + furi_string_free(system_name); + } } else { FelicaSystem* system = state->selected_system; FuriString* header = furi_string_alloc_printf("%04X/", system->code); - FelicaArea* area = &system->root_area; + FelicaNode* root = &system->root; + furi_assert(root->type == FelicaNodeTypeArea); + FelicaArea* area = root->area; if(FelicaAreaPath_size(state->selected_areas) > 0) { FelicaAreaPath_it_t it; for(FelicaAreaPath_it(it, state->selected_areas); !FelicaAreaPath_end_p(it); @@ -51,32 +51,30 @@ void nfc_scene_felica_info_select_on_enter(void* context) { submenu_set_header(submenu, furi_string_get_cstr(header)); furi_string_free(header); - FelicaNodeList_it_t it; - for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); - FelicaNodeList_next(it)) { - FelicaNode* node = *FelicaNodeList_ref(it); - FuriString* node_name = furi_string_alloc(); - if(node->type == FelicaNodeTypeArea) { - furi_string_printf(node_name, "Area %d", node->area->number); - submenu_add_item( - submenu, - furi_string_get_cstr(node_name), - i++, - nfc_scene_felica_info_select_submenu_callback, - nfc); - } else { - uint16_t service_code = node->service->number << 6; - furi_string_printf(node_name, "Service %04X", service_code); - submenu_add_item( - submenu, - furi_string_get_cstr(node_name), - i++, - nfc_scene_felica_info_select_submenu_callback, - nfc); - } + for + M_EACH(node, area->nodes, FelicaNodeArray_t) { + FuriString* node_name = furi_string_alloc(); + if(node->type == FelicaNodeTypeArea) { + furi_string_printf(node_name, "Area %d", node->area->number); + submenu_add_item( + submenu, + furi_string_get_cstr(node_name), + i++, + nfc_scene_felica_info_select_submenu_callback, + nfc); + } else { + uint16_t service_code = node->service->number << 6; + furi_string_printf(node_name, "Service %04X", service_code); + submenu_add_item( + submenu, + furi_string_get_cstr(node_name), + i++, + nfc_scene_felica_info_select_submenu_callback, + nfc); + } - furi_string_free(node_name); - } + furi_string_free(node_name); + } } state->selected_service = NULL; @@ -102,7 +100,7 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even index -= 1; if(state->selected_system == NULL) { - state->selected_system = *FelicaSystemList_get(data->systems, index); + state->selected_system = FelicaSystemArray_get(data->systems, index); if(state->selected_system->code == LITE_SYSTEM_CODE) { scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaServiceData); } else { @@ -111,12 +109,15 @@ bool nfc_scene_felica_info_select_on_event(void* context, SceneManagerEvent even consumed = true; } else { FelicaNode* selected_node = NULL; + + FelicaNode* root = &(state->selected_system->root); + furi_assert(root->type == FelicaNodeTypeArea); + if(FelicaAreaPath_size(state->selected_areas) == 0) { - selected_node = - *FelicaNodeList_get(state->selected_system->root_area.nodes, index); + selected_node = FelicaNodeArray_get(root->area->nodes, index); } else { FelicaArea* current_area = *FelicaAreaPath_back(state->selected_areas); - selected_node = *FelicaNodeList_get(current_area->nodes, index); + selected_node = FelicaNodeArray_get(current_area->nodes, index); } if(selected_node->type == FelicaNodeTypeArea) { diff --git a/applications/main/nfc/scenes/nfc_scene_felica_read_success.c b/applications/main/nfc/scenes/nfc_scene_felica_read_success.c index 52bba0ee3..79dd82297 100644 --- a/applications/main/nfc/scenes/nfc_scene_felica_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_felica_read_success.c @@ -29,21 +29,19 @@ void nfc_scene_felica_read_success_on_enter(void* context) { } else { temp_str = furi_string_alloc_printf("\e#%s", nfc_felica_type(felica_data->type)); - FelicaSystemList_it_t it; - for(FelicaSystemList_it(it, felica_data->systems); !FelicaSystemList_end_p(it); - FelicaSystemList_next(it)) { - FelicaSystem* current_system = *FelicaSystemList_ref(it); - furi_string_cat_printf( - temp_str, "\nSystem %04X (#%d):", current_system->code, current_system->number); - furi_string_cat_printf(temp_str, "\nIDm:\n "); - for(size_t i = 0; i < 8; i++) { - furi_string_cat_printf(temp_str, "%02X", current_system->idm[i]); + for + M_EACH(current_system, felica_data->systems, FelicaSystemArray_t) { + furi_string_cat_printf( + temp_str, "\nSystem %04X (#%d):", current_system->code, current_system->number); + furi_string_cat_printf(temp_str, "\nIDm:\n "); + for(size_t i = 0; i < 8; i++) { + furi_string_cat_printf(temp_str, "%02X", current_system->idm[i]); + } + furi_string_cat_printf(temp_str, "\nPMm:\n "); + for(size_t i = 0; i < 8; i++) { + furi_string_cat_printf(temp_str, "%02X", current_system->pmm[i]); + } } - furi_string_cat_printf(temp_str, "\nPMm:\n "); - for(size_t i = 0; i < 8; i++) { - furi_string_cat_printf(temp_str, "%02X", current_system->pmm[i]); - } - } } widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); diff --git a/applications/main/nfc/scenes/nfc_scene_mfkey_complete.c b/applications/main/nfc/scenes/nfc_scene_mfkey_complete.c index 3c4f9dba1..04515f24f 100644 --- a/applications/main/nfc/scenes/nfc_scene_mfkey_complete.c +++ b/applications/main/nfc/scenes/nfc_scene_mfkey_complete.c @@ -18,7 +18,7 @@ void nfc_scene_mfkey_complete_on_enter(void* context) { AlignCenter, AlignCenter, FontSecondary, - "Now use mfkey32v2\nto extract keys"); + "Now use Mfkey32\nto extract keys"); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_complete_callback, nfc); @@ -46,4 +46,4 @@ void nfc_scene_mfkey_complete_on_exit(void* context) { Nfc* nfc = context; widget_reset(nfc->widget); -} \ No newline at end of file +} diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c index 7f3a8907c..1a879d8a0 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType type, void* context) { Nfc* nfc = context; @@ -22,6 +23,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { Nfc* nfc = context; Widget* widget = nfc->widget; FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; + FuriHalNfcType type = nfc_data->type; NfcDeviceData* dev_data = &nfc->dev->dev_data; NfcProtocol protocol = dev_data->protocol; uint8_t text_scroll_height = 0; @@ -73,6 +75,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); break; } + } else if(protocol == NfcDeviceProtocolFelica) { + furi_string_cat_printf(temp_str, "\e#%s\n", nfc_felica_type(dev_data->felica_data.type)); } else { furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); } @@ -200,7 +204,63 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); break; } - } else { + // Set tag general data + } else if(type == FuriHalNfcTypeF) { + // Set NFC-F data + furi_string_cat_printf(temp_str, "ISO 18092 (NFC-F)\n"); + furi_string_cat_printf(temp_str, "CIN:"); + // NFC-F Card Identification Number (CIN) starts at "UID" byte 2. + for(size_t i = 2; i < nfc_data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + // The first 2 bytes of the "UID" are Manufacturer Code (MC) + furi_string_cat_printf( + temp_str, + "\nMC: %02X %02X ROM: %02X IC: %02X\n\n", + nfc_data->uid[0], + nfc_data->uid[1], + nfc_data->f_data.pmm[0], + nfc_data->f_data.pmm[1]); + + furi_string_cat_printf(temp_str, "MRT (1 node/blk):\n"); + furi_string_cat_printf( + temp_str, + "- ReqSvc: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_VARIABLE_MRT], 1)); + furi_string_cat_printf( + temp_str, + "- Fixed: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_FIXED_MRT], 0)); + furi_string_cat_printf( + temp_str, + "- Auth1: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 1)); + furi_string_cat_printf( + temp_str, + "- Auth2: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_MUTUAL_AUTH_MRT], 0)); + furi_string_cat_printf( + temp_str, + "- Read: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_READ_MRT], 1)); + furi_string_cat_printf( + temp_str, + "- Write: %" PRIuLEAST32 "us\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_WRITE_MRT], 1)); + furi_string_cat_printf( + temp_str, + "- Other: %" PRIuLEAST32 "us\n\n", + felica_estimate_timing_us(nfc_data->f_data.pmm[FELICA_PMM_OTHER_MRT], 0)); + + furi_string_cat_printf(temp_str, "IDm:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + furi_string_cat_printf(temp_str, "\nPMm:"); + for(size_t i = 0; i < sizeof(nfc_data->f_data.pmm); i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->f_data.pmm[i]); + } + } else { // FuriHalNfcTypeA char iso_type = FURI_BIT(nfc_data->a_data.sak, 5) ? '4' : '3'; furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); furi_string_cat_printf(temp_str, "UID:"); diff --git a/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c new file mode 100644 index 000000000..cae7055b1 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcf_menu.c @@ -0,0 +1,80 @@ +#include "../nfc_i.h" +#include + +enum SubmenuIndex { + /* + SubmenuIndexSave, + SubmenuIndexEmulate, + */ + SubmenuIndexInfo, +}; + +void nfc_scene_nfcf_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_nfcf_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + // FelicaData* data = &nfc->dev->dev_data.felica_data; + + /* + submenu_add_item( + submenu, "Save IDm", SubmenuIndexSave, nfc_scene_felica_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Emulate IDm", SubmenuIndexEmulate, nfc_scene_felica_menu_submenu_callback, nfc); + */ + submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfcf_menu_submenu_callback, nfc); + + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcfMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_nfcf_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + /* + if(event.event == SubmenuIndexSave) { + nfc->dev->format = NfcDeviceSaveFormatFelica; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaEmulate); + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) { + DOLPHIN_DEED(DolphinDeedNfcAddEmulate); + } else { + DOLPHIN_DEED(DolphinDeedNfcEmulate); + } + consumed = true; + } else if(event.event == SubmenuIndexUnlock) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaUnlockMenu); + consumed = true; + } else + */ + if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcfMenu, event.event); + + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_nfcf_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c b/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c new file mode 100644 index 000000000..da695ba83 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcf_read_success.c @@ -0,0 +1,88 @@ +#include "../nfc_i.h" +#include "nfc_device.h" + +void nfc_scene_nfcf_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_nfcf_read_success_on_enter(void* context) { + Nfc* nfc = context; + + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + NfcDeviceData* dev_data = &nfc->dev->dev_data; + + // Setup view + Widget* widget = nfc->widget; + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfcf_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_nfcf_read_success_widget_callback, nfc); + + FuriString* temp_str = furi_string_alloc(); + + if(dev_data->protocol == NfcDeviceProtocolFelica) { + furi_string_cat_printf(temp_str, "\e#%s", nfc_felica_type(dev_data->felica_data.type)); + } else { + furi_string_cat_printf(temp_str, "\e#Unknown ISO tag"); + } + + furi_string_cat_printf(temp_str, "\nISO 18092 (NFC-F)"); + + furi_string_cat_printf(temp_str, "\nCIN:"); + // NFC-F Card Identification Number (CIN) starts at "UID" byte 2. + for(size_t i = 2; i < data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); + } + + // The first 2 bytes of the "UID" are Manufacturer Code (MC) + furi_string_cat_printf( + temp_str, + "\nMC: %02X %02X ROM: %02X IC: %02X", + data->uid[0], + data->uid[1], + data->f_data.pmm[0], + data->f_data.pmm[1]); + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + notification_message_block(nfc->notifications, &sequence_set_green_255); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_nfcf_read_success_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcfMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_nfcf_read_success_on_exit(void* context) { + Nfc* nfc = context; + + notification_message_block(nfc->notifications, &sequence_reset_green); + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index c96562275..7327c88b4 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -57,7 +57,6 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if((event.event == NfcWorkerEventReadUidNfcB) || - (event.event == NfcWorkerEventReadUidNfcF) || (event.event == NfcWorkerEventReadUidNfcV)) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); @@ -102,6 +101,11 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); } consumed = true; + } else if(event.event == NfcWorkerEventReadUidNfcF) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcfReadSuccess); + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + consumed = true; } else if(event.event == NfcWorkerEventReadFelica) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneFelicaReadSuccess); diff --git a/applications/main/nfc/scenes/nfc_scene_read_card_type.c b/applications/main/nfc/scenes/nfc_scene_read_card_type.c index 865b3f54b..ed33515d4 100644 --- a/applications/main/nfc/scenes/nfc_scene_read_card_type.c +++ b/applications/main/nfc/scenes/nfc_scene_read_card_type.c @@ -8,6 +8,7 @@ enum SubmenuIndex { SubmenuIndexReadEMV, SubmenuIndexReadNFCA, SubmenuIndexReadFelica, + SubmenuIndexReadNFCF, }; void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) { @@ -56,6 +57,12 @@ void nfc_scene_read_card_type_on_enter(void* context) { SubmenuIndexReadFelica, nfc_scene_read_card_type_submenu_callback, nfc); + submenu_add_item( + submenu, + "Read NFC-F data", + SubmenuIndexReadNFCF, + nfc_scene_read_card_type_submenu_callback, + nfc); uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType); submenu_set_selected_item(submenu, state); @@ -97,6 +104,11 @@ bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); consumed = true; } + if(event.event == SubmenuIndexReadNFCF) { + nfc->dev->dev_data.read_mode = NfcReadModeNFCF; + scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); + consumed = true; + } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event); } return consumed; diff --git a/applications/main/onewire/onewire_cli.c b/applications/main/onewire/onewire_cli.c index 5f6cdc670..9a7ffe55c 100644 --- a/applications/main/onewire/onewire_cli.c +++ b/applications/main/onewire/onewire_cli.c @@ -21,7 +21,7 @@ void onewire_on_system_start() { static void onewire_cli_print_usage() { printf("Usage:\r\n"); printf("onewire search\r\n"); -}; +} static void onewire_cli_search(Cli* cli) { UNUSED(cli); diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index ad49bf09b..cd163a653 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -36,12 +36,12 @@ typedef enum { SubmenuIndexCAME24bit868, SubmenuIndexCAMETwee, SubmenuIndexCAMESpace, - SubmenuIndexPricenton, + SubmenuIndexPricenton433, SubmenuIndexPricenton315, SubmenuIndexBETT_433, SubmenuIndexLinear_300_00, - SubmenuIndexNeroSketch, - SubmenuIndexNeroRadio, + SubmenuIndexNeroSketch, //Deleted in OFW + SubmenuIndexNeroRadio, //Deleted in OFW SubmenuIndexGateTX, SubmenuIndexDoorHan_315_00, SubmenuIndexDoorHan_433_92, diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c index ab90547cb..6fec29565 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -278,7 +278,7 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc(void* cont furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread); SubGhz* subghz = context; - instance->setting = subghz->setting; + instance->setting = subghz_txrx_get_setting(subghz->txrx); instance->trigger_level = subghz->last_settings->frequency_analyzer_trigger; //instance->trigger_level = SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD; return instance; diff --git a/applications/main/subghz/helpers/subghz_threshold_rssi.c b/applications/main/subghz/helpers/subghz_threshold_rssi.c new file mode 100644 index 000000000..04a06bc17 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_threshold_rssi.c @@ -0,0 +1,60 @@ +#include "subghz_threshold_rssi.h" +#include +#include "../subghz_i.h" + +#define TAG "SubGhzThresholdRssi" +#define THRESHOLD_RSSI_LOW_COUNT 10 + +struct SubGhzThresholdRssi { + float threshold_rssi; + uint8_t threshold_rssi_low_count; +}; + +SubGhzThresholdRssi* subghz_threshold_rssi_alloc(void) { + SubGhzThresholdRssi* instance = malloc(sizeof(SubGhzThresholdRssi)); + instance->threshold_rssi = SUBGHZ_RAW_THRESHOLD_MIN; + instance->threshold_rssi_low_count = THRESHOLD_RSSI_LOW_COUNT; + return instance; +} + +void subghz_threshold_rssi_free(SubGhzThresholdRssi* instance) { + furi_assert(instance); + free(instance); +} + +void subghz_threshold_rssi_set(SubGhzThresholdRssi* instance, float rssi) { + furi_assert(instance); + instance->threshold_rssi = rssi; +} + +float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance) { + furi_assert(instance); + return instance->threshold_rssi; +} + +SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance) { + furi_assert(instance); + float rssi = furi_hal_subghz_get_rssi(); + SubGhzThresholdRssiData ret = {.rssi = rssi, .is_above = false}; + + if(float_is_equal(instance->threshold_rssi, SUBGHZ_RAW_THRESHOLD_MIN)) { + ret.is_above = true; + } else { + if(rssi < instance->threshold_rssi) { + instance->threshold_rssi_low_count++; + if(instance->threshold_rssi_low_count > THRESHOLD_RSSI_LOW_COUNT) { + instance->threshold_rssi_low_count = THRESHOLD_RSSI_LOW_COUNT; + } + ret.is_above = false; + } else { + instance->threshold_rssi_low_count = 0; + } + + if(instance->threshold_rssi_low_count == THRESHOLD_RSSI_LOW_COUNT) { + ret.is_above = false; + } else { + ret.is_above = true; + } + } + return ret; +} diff --git a/applications/main/subghz/helpers/subghz_threshold_rssi.h b/applications/main/subghz/helpers/subghz_threshold_rssi.h new file mode 100644 index 000000000..e28092acb --- /dev/null +++ b/applications/main/subghz/helpers/subghz_threshold_rssi.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +typedef struct { + float rssi; /**< Current RSSI */ + bool is_above; /**< Exceeded threshold level */ +} SubGhzThresholdRssiData; + +typedef struct SubGhzThresholdRssi SubGhzThresholdRssi; + +/** Allocate SubGhzThresholdRssi + * + * @return SubGhzThresholdRssi* + */ +SubGhzThresholdRssi* subghz_threshold_rssi_alloc(void); + +/** Free SubGhzThresholdRssi + * + * @param instance Pointer to a SubGhzThresholdRssi + */ +void subghz_threshold_rssi_free(SubGhzThresholdRssi* instance); + +/** Set threshold + * + * @param instance Pointer to a SubGhzThresholdRssi + * @param rssi RSSI threshold + */ +void subghz_threshold_rssi_set(SubGhzThresholdRssi* instance, float rssi); + +/** Get threshold + * + * @param instance Pointer to a SubGhzThresholdRssi + * @return float RSSI threshold + */ +float subghz_threshold_rssi_get(SubGhzThresholdRssi* instance); + +/** Check threshold + * + * @param instance Pointer to a SubGhzThresholdRssi + * @return SubGhzThresholdRssiData + */ +SubGhzThresholdRssiData subghz_threshold_get_rssi_data(SubGhzThresholdRssi* instance); diff --git a/applications/main/subghz/helpers/subghz_txrx.c b/applications/main/subghz/helpers/subghz_txrx.c new file mode 100644 index 000000000..c1f519ba0 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_txrx.c @@ -0,0 +1,563 @@ +#include "subghz_txrx_i.h" +#include + +#define TAG "SubGhz" + +SubGhzTxRx* subghz_txrx_alloc() { + SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); + instance->setting = subghz_setting_alloc(); + subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user")); + + instance->preset = malloc(sizeof(SubGhzRadioPreset)); + instance->preset->name = furi_string_alloc(); + subghz_txrx_set_preset( + instance, "AM650", subghz_setting_get_default_frequency(instance->setting), NULL, 0); + + instance->txrx_state = SubGhzTxRxStateSleep; + + subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF); + subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable); + subghz_txrx_set_debug_pin_state(instance, false); + + instance->worker = subghz_worker_alloc(); + instance->fff_data = flipper_format_string_alloc(); + + instance->environment = subghz_environment_alloc(); + instance->is_database_loaded = subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); + subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + subghz_environment_set_came_atomo_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/alutech_at_4n")); + subghz_environment_set_nice_flor_s_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/nice_flor_s")); + subghz_environment_set_protocol_registry( + instance->environment, (void*)&subghz_protocol_registry); + instance->receiver = subghz_receiver_alloc_init(instance->environment); + + subghz_worker_set_overrun_callback( + instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + subghz_worker_set_pair_callback( + instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); + subghz_worker_set_context(instance->worker, instance->receiver); + + return instance; +} + +void subghz_txrx_free(SubGhzTxRx* instance) { + furi_assert(instance); + + subghz_worker_free(instance->worker); + subghz_receiver_free(instance->receiver); + subghz_environment_free(instance->environment); + flipper_format_free(instance->fff_data); + furi_string_free(instance->preset->name); + subghz_setting_free(instance->setting); + free(instance->preset); + free(instance); +} + +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->is_database_loaded; +} + +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size) { + furi_assert(instance); + furi_string_set(instance->preset->name, preset_name); + SubGhzRadioPreset* preset = instance->preset; + preset->frequency = frequency; + preset->data = preset_data; + preset->data_size = preset_data_size; +} + +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) { + UNUSED(instance); + const char* preset_name = ""; + if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { + preset_name = "AM270"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { + preset_name = "AM650"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { + preset_name = "FM238"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { + preset_name = "FM476"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { + preset_name = "CUSTOM"; + } else { + FURI_LOG_E(TAG, "Unknown preset"); + } + return preset_name; +} + +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) { + furi_assert(instance); + return *instance->preset; +} + +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name) { + furi_assert(instance); + SubGhzRadioPreset* preset = instance->preset; + if(frequency != NULL) { + furi_string_printf( + frequency, + "%03ld.%02ld", + preset->frequency / 1000000 % 1000, + preset->frequency / 10000 % 100); + } + if(modulation != NULL) { + if(long_name) { + furi_string_printf(modulation, "%s", furi_string_get_cstr(preset->name)); + } else { + furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name)); + } + } +} + +static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { + furi_assert(instance); + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_custom_preset(preset_data); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect RX frequency."); + } + furi_assert( + instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); + + furi_hal_subghz_idle(); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_subghz_flush_rx(); + subghz_txrx_speaker_on(instance); + furi_hal_subghz_rx(); + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, instance->worker); + subghz_worker_start(instance->worker); + instance->txrx_state = SubGhzTxRxStateRx; + return value; +} + +static void subghz_txrx_idle(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static void subghz_txrx_rx_end(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateRx); + + if(subghz_worker_is_running(instance->worker)) { + subghz_worker_stop(instance->worker); + furi_hal_subghz_stop_async_rx(); + } + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +void subghz_txrx_sleep(SubGhzTxRx* instance) { + furi_assert(instance); + furi_hal_subghz_sleep(); + instance->txrx_state = SubGhzTxRxStateSleep; +} + +static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect TX frequency."); + } + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + bool ret = furi_hal_subghz_tx(); + if(ret) { + subghz_txrx_speaker_on(instance); + instance->txrx_state = SubGhzTxRxStateTx; + } + + return ret; +} + +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) { + furi_assert(instance); + furi_assert(flipper_format); + + subghz_txrx_stop(instance); + + SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers; + FuriString* temp_str = furi_string_alloc(); + uint32_t repeat = 200; + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + ret = SubGhzTxRxStartTxStateOk; + + SubGhzRadioPreset* preset = instance->preset; + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str)); + + if(instance->transmitter) { + if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) == + SubGhzProtocolStatusOk) { + if(strcmp(furi_string_get_cstr(preset->name), "") != 0) { + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + instance->setting, furi_string_get_cstr(preset->name))); + if(preset->frequency) { + if(!subghz_txrx_tx(instance, preset->frequency)) { + FURI_LOG_E(TAG, "Only Rx"); + ret = SubGhzTxRxStartTxStateErrorOnlyRx; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + } else { + FURI_LOG_E( + TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name)); + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + if(ret == SubGhzTxRxStartTxStateOk) { + //Start TX + furi_hal_subghz_start_async_tx( + subghz_transmitter_yield, instance->transmitter); + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + if(ret != SubGhzTxRxStartTxStateOk) { + subghz_transmitter_free(instance->transmitter); + if(instance->txrx_state != SubGhzTxRxStateIDLE) { + subghz_txrx_idle(instance); + } + } + + } while(false); + furi_string_free(temp_str); + return ret; +} + +void subghz_txrx_rx_start(SubGhzTxRx* instance) { + furi_assert(instance); + subghz_txrx_stop(instance); + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name))); + subghz_txrx_rx(instance, instance->preset->frequency); +} + +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context) { + furi_assert(instance); + instance->need_save_callback = callback; + instance->need_save_context = context; +} + +static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateTx); + //Stop TX + furi_hal_subghz_stop_async_tx(); + subghz_transmitter_stop(instance->transmitter); + subghz_transmitter_free(instance->transmitter); + + //if protocol dynamic then we save the last upload + if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + if(instance->need_save_callback) { + instance->need_save_callback(instance->need_save_context); + } + } + subghz_txrx_idle(instance); + subghz_txrx_speaker_off(instance); + //Todo: Show message + // notification_message(notifications, &sequence_reset_red); +} + +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->fff_data; +} + +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->setting; +} + +void subghz_txrx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->txrx_state) { + case SubGhzTxRxStateTx: + subghz_txrx_tx_stop(instance); + subghz_txrx_speaker_unmute(instance); + break; + case SubGhzTxRxStateRx: + subghz_txrx_rx_end(instance); + subghz_txrx_speaker_mute(instance); + break; + + default: + break; + } +} + +void subghz_txrx_hopper_update(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->hopper_state) { + case SubGhzHopperStateOFF: + case SubGhzHopperStatePause: + return; + case SubGhzHopperStateRSSITimeOut: + if(instance->hopper_timeout != 0) { + instance->hopper_timeout--; + return; + } + break; + default: + break; + } + float rssi = -127.0f; + if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { + // See RSSI Calculation timings in CC1101 17.3 RSSI + rssi = furi_hal_subghz_get_rssi(); + + // Stay if RSSI is high enough + if(rssi > -90.0f) { + instance->hopper_timeout = 10; + instance->hopper_state = SubGhzHopperStateRSSITimeOut; + return; + } + } else { + instance->hopper_state = SubGhzHopperStateRunning; + } + // Select next frequency + if(instance->hopper_idx_frequency < + subghz_setting_get_hopper_frequency_count(instance->setting) - 1) { + instance->hopper_idx_frequency++; + } else { + instance->hopper_idx_frequency = 0; + } + + if(instance->txrx_state == SubGhzTxRxStateRx) { + subghz_txrx_rx_end(instance); + }; + if(instance->txrx_state == SubGhzTxRxStateIDLE) { + subghz_receiver_reset(instance->receiver); + instance->preset->frequency = + subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency); + subghz_txrx_rx(instance, instance->preset->frequency); + } +} + +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->hopper_state; +} + +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) { + furi_assert(instance); + instance->hopper_state = state; +} + +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStatePause) { + instance->hopper_state = SubGhzHopperStateRunning; + } +} + +void subghz_txrx_hopper_pause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStateRunning) { + instance->hopper_state = SubGhzHopperStatePause; + } +} + +void subghz_txrx_speaker_on(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_acquire(30)) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } else { + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_off(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state != SubGhzSpeakerStateDisable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + furi_hal_speaker_release(); + if(instance->speaker_state == SubGhzSpeakerStateShutdown) + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + } + } +} + +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } + } +} + +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) { + furi_assert(instance); + instance->speaker_state = state; +} + +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->speaker_state; +} + +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) { + furi_assert(instance); + furi_assert(name_protocol); + bool res = false; + instance->decoder_result = + subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol); + if(instance->decoder_result) { + res = true; + } + return res; +} + +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->decoder_result; +} + +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) { + furi_assert(instance); + return ( + (instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == + SubGhzProtocolFlag_Save); +} + +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) { + furi_assert(instance); + const SubGhzProtocol* protocol = instance->decoder_result->protocol; + if(check_type) { + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic); + } + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize); +} + +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) { + furi_assert(instance); + subghz_receiver_set_filter(instance->receiver, filter); +} + +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context) { + subghz_receiver_set_rx_callback(instance->receiver, callback, context); +} + +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter), + callback, + context); +} + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { + furi_assert(instance); + instance->debug_pin_state = state; +} + +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->debug_pin_state; +} + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->receiver; +} \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_txrx.h b/applications/main/subghz/helpers/subghz_txrx.h new file mode 100644 index 000000000..fd7c024b8 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_txrx.h @@ -0,0 +1,296 @@ +#pragma once + +#include "subghz_types.h" + +#include +#include +#include +#include +#include + +typedef struct SubGhzTxRx SubGhzTxRx; + +typedef void (*SubGhzTxRxNeedSaveCallback)(void* context); + +typedef enum { + SubGhzTxRxStartTxStateOk, + SubGhzTxRxStartTxStateErrorOnlyRx, + SubGhzTxRxStartTxStateErrorParserOthers, +} SubGhzTxRxStartTxState; + +/** + * Allocate SubGhzTxRx + * + * @return SubGhzTxRx* pointer to SubGhzTxRx + */ +SubGhzTxRx* subghz_txrx_alloc(); + +/** + * Free SubGhzTxRx + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_free(SubGhzTxRx* instance); + +/** + * Check if the database is loaded + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if the database is loaded + */ +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance); + +/** + * Set preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param preset_data Data of preset + * @param preset_data_size Size of preset data + */ +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size); + +/** + * Get name of preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset String of preset + * @return const char* Name of preset + */ +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset); + +/** + * Get of preset + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzRadioPreset Preset + */ +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance); + +/** + * Get string frequency and modulation + * + * @param instance Pointer to a SubGhzTxRx + * @param frequency Pointer to a string frequency + * @param modulation Pointer to a string modulation + */ +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name); + +/** + * Start TX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + * @param flipper_format Pointer to a FlipperFormat + * @return SubGhzTxRxStartTxState + */ +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format); + +/** + * Start RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_rx_start(SubGhzTxRx* instance); + +/** + * Stop TX/RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_stop(SubGhzTxRx* instance); + +/** + * Set sleep mode CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_sleep(SubGhzTxRx* instance); + +/** + * Update frequency CC1101 in automatic mode (hopper) + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_update(SubGhzTxRx* instance); + +/** + * Get state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzHopperState + */ +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance); + +/** + * Set state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @param state State hopper + */ +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state); + +/** + * Unpause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance); + +/** + * Set pause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_pause(SubGhzTxRx* instance); + +/** + * Speaker on + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_on(SubGhzTxRx* instance); + +/** + * Speaker off + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_off(SubGhzTxRx* instance); + +/** + * Speaker mute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_mute(SubGhzTxRx* instance); + +/** + * Speaker unmute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance); + +/** + * Set state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @param state State speaker + */ +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state); + +/** + * Get state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSpeakerState + */ +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); + +/** + * load decoder by name protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_protocol Name protocol + * @return bool True if the decoder is loaded + */ +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol); + +/** + * Get decoder + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzProtocolDecoderBase* Pointer to a SubGhzProtocolDecoderBase + */ +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance); + +/** + * Set callback for save data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for save data + * @param context Context for callback + */ +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context); + +/** + * Get pointer to a load data key + * + * @param instance Pointer to a SubGhzTxRx + * @return FlipperFormat* + */ +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance); + +/** + * Get pointer to a SugGhzSetting + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSetting* + */ +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance); + +/** + * Is it possible to save this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to save this protocol + */ +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance); + +/** + * Is it possible to send this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to send this protocol + */ +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type); + +/** + * Set filter, what types of decoder to use + * + * @param instance Pointer to a SubGhzTxRx + * @param filter Filter + */ +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter); + +/** + * Set callback for receive data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for receive data + * @param context Context for callback + */ +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context); + +/** + * Set callback for Raw decoder, end of data transfer + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for Raw decoder, end of data transfer + * @param context Context for callback + */ +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context); + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance); // TODO use only in DecodeRaw diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c new file mode 100644 index 000000000..0631c7c15 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c @@ -0,0 +1,346 @@ +#include "subghz_txrx_i.h" +#include "subghz_txrx_create_protocol_key.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TAG "SubGhzCreateProtocolKey" + +bool subghz_txrx_gen_data_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + const char* protocol_name, + uint64_t key, + uint32_t bit) { + furi_assert(context); + SubGhzTxRx* instance = context; + + bool res = false; + + subghz_txrx_set_preset(instance, preset_name, frequency, NULL, 0); + instance->decoder_result = + subghz_receiver_search_decoder_base_by_name(instance->receiver, protocol_name); + + if(instance->decoder_result == NULL) { + //TODO: Error + // furi_string_set(error_str, "Protocol not\nfound!"); + // scene_manager_next_scene(scene_manager, SubGhzSceneShowErrorSub); + FURI_LOG_E(TAG, "Protocol not found!"); + return false; + } + + do { + Stream* fff_data_stream = flipper_format_get_raw_stream(instance->fff_data); + stream_clean(fff_data_stream); + if(subghz_protocol_decoder_base_serialize( + instance->decoder_result, instance->fff_data, instance->preset) != + SubGhzProtocolStatusOk) { + FURI_LOG_E(TAG, "Unable to serialize"); + break; + } + if(!flipper_format_update_uint32(instance->fff_data, "Bit", &bit, 1)) { + FURI_LOG_E(TAG, "Unable to update Bit"); + break; + } + + uint8_t key_data[sizeof(uint64_t)] = {0}; + for(size_t i = 0; i < sizeof(uint64_t); i++) { + key_data[sizeof(uint64_t) - i - 1] = (key >> (i * 8)) & 0xFF; + } + if(!flipper_format_update_hex(instance->fff_data, "Key", key_data, sizeof(uint64_t))) { + FURI_LOG_E(TAG, "Unable to update Key"); + break; + } + res = true; + } while(false); + return res; +} + +bool subghz_txrx_gen_data_protocol_and_te( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + const char* protocol_name, + uint64_t key, + uint32_t bit, + uint32_t te) { + furi_assert(instance); + bool ret = false; + if(subghz_txrx_gen_data_protocol(instance, preset_name, frequency, protocol_name, key, bit)) { + if(!flipper_format_update_uint32(instance->fff_data, "TE", (uint32_t*)&te, 1)) { + FURI_LOG_E(TAG, "Unable to update Te"); + } else { + ret = true; + } + } + return ret; +} + +bool subghz_txrx_gen_keeloq_protocol( //TODO lead to a general appearance + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + const char* manufacture_name) { + furi_assert(instance); + + bool res = false; + + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); + subghz_txrx_set_preset(instance, preset_name, frequency, NULL, 0); + + if(instance->transmitter && + subghz_protocol_keeloq_create_data( + subghz_transmitter_get_protocol_instance(instance->transmitter), + instance->fff_data, + serial, + btn, + cnt, + manufacture_name, + instance->preset)) { + flipper_format_write_string_cstr(instance->fff_data, "Manufacture", manufacture_name); + res = true; + } + subghz_transmitter_free(instance->transmitter); + return res; +} + +bool subghz_txrx_gen_keeloq_bft_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name) { + SubGhzTxRx* txrx = context; + + bool res = false; + + txrx->transmitter = + subghz_transmitter_alloc_init(txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); + subghz_txrx_set_preset(txrx, preset_name, frequency, NULL, 0); + + if(txrx->transmitter && subghz_protocol_keeloq_bft_create_data( + subghz_transmitter_get_protocol_instance(txrx->transmitter), + txrx->fff_data, + serial, + btn, + cnt, + seed, + manufacture_name, + txrx->preset)) { + res = true; + } + + if(res) { + uint8_t seed_data[sizeof(uint32_t)] = {0}; + for(size_t i = 0; i < sizeof(uint32_t); i++) { + seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF; + } + + flipper_format_write_hex(txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); + + flipper_format_write_string_cstr(txrx->fff_data, "Manufacture", "BFT"); + } + + subghz_transmitter_free(txrx->transmitter); + + return res; +} + +bool subghz_txrx_gen_nice_flor_s_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + bool nice_one) { + SubGhzTxRx* txrx = context; + + bool res = false; + + txrx->transmitter = + subghz_transmitter_alloc_init(txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME); + subghz_txrx_set_preset(txrx, preset_name, frequency, NULL, 0); + + if(txrx->transmitter && subghz_protocol_nice_flor_s_create_data( + subghz_transmitter_get_protocol_instance(txrx->transmitter), + txrx->fff_data, + serial, + btn, + cnt, + txrx->preset, + nice_one)) { + res = true; + } + + subghz_transmitter_free(txrx->transmitter); + + return res; +} + +bool subghz_txrx_gen_faac_slh_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name) { + SubGhzTxRx* txrx = context; + + bool res = false; + + txrx->transmitter = + subghz_transmitter_alloc_init(txrx->environment, SUBGHZ_PROTOCOL_FAAC_SLH_NAME); + subghz_txrx_set_preset(txrx, preset_name, frequency, NULL, 0); + + if(txrx->transmitter && subghz_protocol_faac_slh_create_data( + subghz_transmitter_get_protocol_instance(txrx->transmitter), + txrx->fff_data, + serial, + btn, + cnt, + seed, + manufacture_name, + txrx->preset)) { + res = true; + } + + if(res) { + uint8_t seed_data[sizeof(uint32_t)] = {0}; + for(size_t i = 0; i < sizeof(uint32_t); i++) { + seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF; + } + + flipper_format_write_hex(txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); + } + + subghz_transmitter_free(txrx->transmitter); + + return res; +} + +bool subghz_txrx_gen_alutech_at_4n_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt) { + SubGhzTxRx* txrx = context; + + bool res = false; + + txrx->transmitter = + subghz_transmitter_alloc_init(txrx->environment, SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME); + subghz_txrx_set_preset(txrx, preset_name, frequency, NULL, 0); + + if(txrx->transmitter && subghz_protocol_alutech_at_4n_create_data( + subghz_transmitter_get_protocol_instance(txrx->transmitter), + txrx->fff_data, + serial, + btn, + cnt, + txrx->preset)) { + res = true; + } + + subghz_transmitter_free(txrx->transmitter); + + return res; +} + +bool subghz_txrx_gen_somfy_telis_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt) { + SubGhzTxRx* txrx = context; + + bool res = false; + + txrx->transmitter = + subghz_transmitter_alloc_init(txrx->environment, SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME); + subghz_txrx_set_preset(txrx, preset_name, frequency, NULL, 0); + + if(txrx->transmitter && subghz_protocol_somfy_telis_create_data( + subghz_transmitter_get_protocol_instance(txrx->transmitter), + txrx->fff_data, + serial, + btn, + cnt, + txrx->preset)) { + res = true; + } + + subghz_transmitter_free(txrx->transmitter); + + return res; +} + +bool subghz_txrx_gen_secplus_v2_protocol( + SubGhzTxRx* instance, + const char* name_preset, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint32_t cnt) { + furi_assert(instance); + + bool ret = false; + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); + subghz_txrx_set_preset(instance, name_preset, frequency, NULL, 0); + if(instance->transmitter) { + subghz_protocol_secplus_v2_create_data( + subghz_transmitter_get_protocol_instance(instance->transmitter), + instance->fff_data, + serial, + btn, + cnt, + instance->preset); + ret = true; + } + return ret; +} + +bool subghz_txrx_gen_secplus_v1_protocol( + SubGhzTxRx* instance, + const char* name_preset, + uint32_t frequency) { + furi_assert(instance); + + bool ret = false; + uint32_t serial = (uint32_t)rand(); + while(!subghz_protocol_secplus_v1_check_fixed(serial)) { + serial = (uint32_t)rand(); + } + if(subghz_txrx_gen_data_protocol( + instance, + name_preset, + frequency, + SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, + (uint64_t)serial << 32 | 0xE6000000, + 42)) { + ret = true; + } + return ret; +} \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h new file mode 100644 index 000000000..a5fa2a802 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.h @@ -0,0 +1,141 @@ +#pragma once +#include "subghz_types.h" +#include "subghz_txrx.h" + +/** + * Generate data for protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param protocol_name Name of protocol + * @param key Key + * @param bit Bit + * @return bool True if success + */ +bool subghz_txrx_gen_data_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + const char* protocol_name, + uint64_t key, + uint32_t bit); + +/** + * Generate data for protocol and te + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param protocol_name Name of protocol + * @param key Key + * @param bit Bit + * @param te Te + * @return bool True if success + */ +bool subghz_txrx_gen_data_protocol_and_te( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + const char* protocol_name, + uint64_t key, + uint32_t bit, + uint32_t te); + +/** + * Generate data Keeloq protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param serial Serial number + * @param btn Button + * @param cnt Counter + * @param manufacture_name Name of Keeloq sysmem + * @return bool True if success + */ +bool subghz_txrx_gen_keeloq_protocol( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + const char* manufacture_name); + +bool subghz_txrx_gen_keeloq_bft_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name); + +bool subghz_txrx_gen_nice_flor_s_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + bool nice_one); + +bool subghz_txrx_gen_faac_slh_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + uint32_t seed, + const char* manufacture_name); + +bool subghz_txrx_gen_alutech_at_4n_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt); + +bool subghz_txrx_gen_somfy_telis_protocol( + void* context, + const char* preset_name, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint16_t cnt); + +/** + * Generate data SecPlus v2 protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_preset Name of preset + * @param frequency Frequency in Hz + * @param serial Serial number + * @param btn Button + * @param cnt Counter + * @return bool True if success + */ +bool subghz_txrx_gen_secplus_v2_protocol( + SubGhzTxRx* instance, + const char* name_preset, + uint32_t frequency, + uint32_t serial, + uint8_t btn, + uint32_t cnt); + +/** + * Generate data SecPlus v1 protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_preset Name of preset + * @param frequency Frequency in Hz + * @return bool True if success + */ +bool subghz_txrx_gen_secplus_v1_protocol( + SubGhzTxRx* instance, + const char* name_preset, + uint32_t frequency); \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_txrx_i.h b/applications/main/subghz/helpers/subghz_txrx_i.h new file mode 100644 index 000000000..680d27158 --- /dev/null +++ b/applications/main/subghz/helpers/subghz_txrx_i.h @@ -0,0 +1,29 @@ + +#pragma once +#include "subghz_txrx.h" + +struct SubGhzTxRx { + SubGhzWorker* worker; + + SubGhzEnvironment* environment; + SubGhzReceiver* receiver; + SubGhzTransmitter* transmitter; + SubGhzProtocolDecoderBase* decoder_result; + FlipperFormat* fff_data; + + SubGhzRadioPreset* preset; + SubGhzSetting* setting; + + uint8_t hopper_timeout; + uint8_t hopper_idx_frequency; + bool is_database_loaded; + SubGhzHopperState hopper_state; + + SubGhzTxRxState txrx_state; + SubGhzSpeakerState speaker_state; + + SubGhzTxRxNeedSaveCallback need_save_callback; + void* need_save_context; + + bool debug_pin_state; +}; \ No newline at end of file diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 3c5982427..700049237 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -80,6 +80,13 @@ typedef enum { SubGhzViewIdTestPacket, } SubGhzViewId; +/** SubGhz load type file */ +typedef enum { + SubGhzLoadTypeFileNoLoad, + SubGhzLoadTypeFileKey, + SubGhzLoadTypeFileRaw, +} SubGhzLoadTypeFile; + typedef enum { SubGhzViewReceiverModeLive, SubGhzViewReceiverModeFile, diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index 6fb183d60..269ec4c72 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -23,7 +23,7 @@ ADD_SCENE(subghz, set_fix, SetFix) ADD_SCENE(subghz, set_cnt, SetCnt) ADD_SCENE(subghz, set_seed, SetSeed) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) -ADD_SCENE(subghz, ext_module_settings, ExtModuleSettings) +ADD_SCENE(subghz, radio_settings, ExtModuleSettings) ADD_SCENE(subghz, read_raw, ReadRAW) ADD_SCENE(subghz, more_raw, MoreRAW) ADD_SCENE(subghz, decode_raw, DecodeRAW) diff --git a/applications/main/subghz/scenes/subghz_scene_decode_raw.c b/applications/main/subghz/scenes/subghz_scene_decode_raw.c index 5ac4fcccd..54c729cc3 100644 --- a/applications/main/subghz/scenes/subghz_scene_decode_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_decode_raw.c @@ -7,33 +7,15 @@ #define TAG "SubGhzDecodeRaw" #define SAMPLES_TO_READ_PER_TICK 400 -// TODO: -// [X] Remember RAW file after decoding -// [X] Decode in tick events instead of on_enter -// [X] Make "Config" label optional in subghz_view_receiver_draw (../views/receiver.c) -// [X] Make "Scanning..." label optional in subghz_view_receiver_draw (../views/receiver.c) -// [X] Add Decoding logo -// [ ] Design nicer Decoding logo -// [X] Check progress in stream_buffer, instead of raw stream -// [X] Blink led while decoding -// [X] Stop rx blink (blue, fast) on history item view -// [X] Don't reparse file on back -// [X] Fix: RX animation+LED returning from decoded detail view -// [X] Find good value for SAMPLES_TO_READ_PER_TICK -// [X] Fix: read errors (slow flash) after aborting decode read - static void subghz_scene_receiver_update_statusbar(void* context) { SubGhz* subghz = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; + FuriString* history_stat_str = furi_string_alloc(); + if(!subghz_history_get_text_space_left(subghz->history, history_stat_str)) { + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation( + subghz->txrx, frequency_str, modulation_str, false); subghz_view_receiver_add_data_statusbar( subghz->subghz_receiver, @@ -62,25 +44,24 @@ static void subghz_scene_add_to_history_callback( void* context) { furi_assert(context); SubGhz* subghz = context; - FuriString* item_name; - FuriString* item_time; - uint16_t idx = subghz_history_get_item(subghz->txrx->history); - item_name = furi_string_alloc(); - item_time = furi_string_alloc(); + FuriString* item_name = furi_string_alloc(); + FuriString* item_time = furi_string_alloc(); + uint16_t idx = subghz_history_get_item(subghz->history); + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); - if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) { + if(subghz_history_add_to_history(subghz->history, decoder_base, &preset)) { furi_string_reset(item_name); furi_string_reset(item_time); subghz->state_notifications = SubGhzNotificationStateRxDone; - subghz_history_get_text_item_menu(subghz->txrx->history, item_name, idx); - subghz_history_get_time_item_menu(subghz->txrx->history, item_time, idx); + subghz_history_get_text_item_menu(subghz->history, item_name, idx); + subghz_history_get_time_item_menu(subghz->history, item_time, idx); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, furi_string_get_cstr(item_name), furi_string_get_cstr(item_time), - subghz_history_get_type_protocol(subghz->txrx->history, idx)); + subghz_history_get_type_protocol(subghz->history, idx)); subghz_scene_receiver_update_statusbar(subghz); } @@ -90,16 +71,16 @@ static void subghz_scene_add_to_history_callback( } bool subghz_scene_decode_raw_start(SubGhz* subghz) { - FuriString* file_name; - file_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); bool success = false; do { - if(!flipper_format_rewind(subghz->txrx->fff_data)) { + if(!flipper_format_rewind(subghz_txrx_get_fff_data(subghz->txrx))) { FURI_LOG_E(TAG, "Rewind error"); break; } - if(!flipper_format_read_string(subghz->txrx->fff_data, "File_name", file_name)) { + if(!flipper_format_read_string( + subghz_txrx_get_fff_data(subghz->txrx), "File_name", file_name)) { FURI_LOG_E(TAG, "Missing File_name"); break; } @@ -130,14 +111,14 @@ bool subghz_scene_decode_raw_start(SubGhz* subghz) { bool subghz_scene_decode_raw_next(SubGhz* subghz) { LevelDuration level_duration; - + SubGhzReceiver* receiver = subghz_txrx_get_receiver(subghz->txrx); for(uint32_t read = SAMPLES_TO_READ_PER_TICK; read > 0; --read) { level_duration = subghz_file_encoder_worker_get_level_duration(subghz->decode_raw_file_worker_encoder); if(!level_duration_is_reset(level_duration)) { bool level = level_duration_get_level(level_duration); uint32_t duration = level_duration_get_duration(level_duration); - subghz_receiver_decode(subghz->txrx->receiver, level, duration); + subghz_receiver_decode(receiver, level, duration); } else { subghz->decode_raw_state = SubGhzDecodeRawStateLoaded; subghz->state_notifications = SubGhzNotificationStateIDLE; @@ -148,8 +129,7 @@ bool subghz_scene_decode_raw_next(SubGhz* subghz) { } // Update progress info - FuriString* progress_str; - progress_str = furi_string_alloc(); + FuriString* progress_str = furi_string_alloc(); subghz_file_encoder_worker_get_text_progress( subghz->decode_raw_file_worker_encoder, progress_str); @@ -164,24 +144,20 @@ bool subghz_scene_decode_raw_next(SubGhz* subghz) { void subghz_scene_decode_raw_on_enter(void* context) { SubGhz* subghz = context; - FuriString* item_name; - FuriString* item_time; - item_name = furi_string_alloc(); - item_time = furi_string_alloc(); + FuriString* item_name = furi_string_alloc(); + FuriString* item_time = furi_string_alloc(); - subghz_view_receiver_set_lock(subghz->subghz_receiver, subghz->lock); subghz_view_receiver_set_mode(subghz->subghz_receiver, SubGhzViewReceiverModeFile); subghz_view_receiver_set_callback( subghz->subghz_receiver, subghz_scene_decode_raw_callback, subghz); - subghz_receiver_set_rx_callback( - subghz->txrx->receiver, subghz_scene_add_to_history_callback, subghz); + subghz_txrx_set_rx_calback(subghz->txrx, subghz_scene_add_to_history_callback, subghz); - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_Decodable); + subghz_txrx_receiver_set_filter(subghz->txrx, SubGhzProtocolFlag_Decodable); if(subghz->decode_raw_state == SubGhzDecodeRawStateStart) { //Decode RAW to history - subghz_history_reset(subghz->txrx->history); + subghz_history_reset(subghz->history); if(subghz_scene_decode_raw_start(subghz)) { subghz->decode_raw_state = SubGhzDecodeRawStateLoading; subghz->state_notifications = SubGhzNotificationStateRx; @@ -189,20 +165,20 @@ void subghz_scene_decode_raw_on_enter(void* context) { } else { //Load history to receiver subghz_view_receiver_exit(subghz->subghz_receiver); - for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) { + for(uint8_t i = 0; i < subghz_history_get_item(subghz->history); i++) { furi_string_reset(item_name); furi_string_reset(item_time); - subghz_history_get_text_item_menu(subghz->txrx->history, item_name, i); - subghz_history_get_time_item_menu(subghz->txrx->history, item_time, i); + subghz_history_get_text_item_menu(subghz->history, item_name, i); + subghz_history_get_time_item_menu(subghz->history, item_time, i); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, furi_string_get_cstr(item_name), furi_string_get_cstr(item_time), - subghz_history_get_type_protocol(subghz->txrx->history, i)); + subghz_history_get_type_protocol(subghz->history, i)); } furi_string_free(item_name); furi_string_free(item_time); - subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); + subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->idx_menu_chosen); } subghz_scene_receiver_update_statusbar(subghz); @@ -217,11 +193,11 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case SubGhzCustomEventViewReceiverBack: subghz->decode_raw_state = SubGhzDecodeRawStateStart; - subghz->txrx->idx_menu_chosen = 0; + subghz->idx_menu_chosen = 0; subghz->in_decoder_scene = false; subghz->in_decoder_scene_skip = false; - subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); + subghz_txrx_set_rx_calback(subghz->txrx, NULL, subghz); if(subghz_file_encoder_worker_is_running(subghz->decode_raw_file_worker_encoder)) { subghz_file_encoder_worker_stop(subghz->decode_raw_file_worker_encoder); @@ -236,8 +212,7 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case SubGhzCustomEventViewReceiverOK: - subghz->txrx->idx_menu_chosen = - subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); subghz->state_notifications = SubGhzNotificationStateIDLE; subghz->in_decoder_scene = true; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); @@ -251,10 +226,6 @@ bool subghz_scene_decode_raw_on_event(void* context, SceneManagerEvent event) { notification_message(subghz->notifications, &sequence_display_backlight_off); consumed = true; break; - case SubGhzCustomEventViewReceiverUnlock: - subghz->lock = SubGhzLockOff; - consumed = true; - break; default: break; } diff --git a/applications/main/subghz/scenes/subghz_scene_delete.c b/applications/main/subghz/scenes/subghz_scene_delete.c index 94814b143..3fc4be069 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete.c +++ b/applications/main/subghz/scenes/subghz_scene_delete.c @@ -11,15 +11,11 @@ void subghz_scene_delete_callback(GuiButtonType result, InputType type, void* co void subghz_scene_delete_on_enter(void* context) { SubGhz* subghz = context; - FuriString* frequency_str; - FuriString* modulation_str; - FuriString* text; + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); + FuriString* text = furi_string_alloc(); - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - text = furi_string_alloc(); - - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, false); widget_add_string_element( subghz->widget, 78, @@ -37,7 +33,7 @@ void subghz_scene_delete_on_enter(void* context) { AlignTop, FontSecondary, furi_string_get_cstr(modulation_str)); - subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, text); + subghz_protocol_decoder_base_get_string(subghz_txrx_get_decoder(subghz->txrx), text); widget_add_string_multiline_element( subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text)); diff --git a/applications/main/subghz/scenes/subghz_scene_delete_raw.c b/applications/main/subghz/scenes/subghz_scene_delete_raw.c index fa4fc6f64..ada0f4c5c 100644 --- a/applications/main/subghz/scenes/subghz_scene_delete_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_delete_raw.c @@ -15,11 +15,8 @@ void subghz_scene_delete_raw_callback(GuiButtonType result, InputType type, void void subghz_scene_delete_raw_on_enter(void* context) { SubGhz* subghz = context; - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); char delete_str[SUBGHZ_MAX_LEN_NAME + 16]; FuriString* file_name; @@ -33,7 +30,7 @@ void subghz_scene_delete_raw_on_enter(void* context) { widget_add_string_element( subghz->widget, 38, 25, AlignLeft, AlignTop, FontSecondary, "RAW signal"); - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, false); widget_add_string_element( subghz->widget, 35, diff --git a/applications/main/subghz/scenes/subghz_scene_need_saving.c b/applications/main/subghz/scenes/subghz_scene_need_saving.c index 5c6b9cc39..8259b6e82 100644 --- a/applications/main/subghz/scenes/subghz_scene_need_saving.c +++ b/applications/main/subghz/scenes/subghz_scene_need_saving.c @@ -37,22 +37,24 @@ void subghz_scene_need_saving_on_enter(void* context) { bool subghz_scene_need_saving_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeBack) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack); scene_manager_previous_scene(subghz->scene_manager); return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneStay) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack); scene_manager_previous_scene(subghz->scene_manager); return true; } else if(event.event == SubGhzCustomEventSceneExit) { - if(subghz->txrx->rx_key_state == SubGhzRxKeyStateExit) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; - subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0); + SubGhzRxKeyState state = subghz_rx_key_state_get(subghz); + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); + + if(state == SubGhzRxKeyStateExit) { + subghz_txrx_set_preset( + subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0); scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); } else { - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; scene_manager_previous_scene(subghz->scene_manager); } diff --git a/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c b/applications/main/subghz/scenes/subghz_scene_radio_settings.c similarity index 73% rename from applications/main/subghz/scenes/subghz_scene_ext_module_settings.c rename to applications/main/subghz/scenes/subghz_scene_radio_settings.c index b6b9e18a7..7fea1de0a 100644 --- a/applications/main/subghz/scenes/subghz_scene_ext_module_settings.c +++ b/applications/main/subghz/scenes/subghz_scene_radio_settings.c @@ -1,12 +1,6 @@ #include "../subghz_i.h" #include "../helpers/subghz_custom_event.h" -static uint8_t value_index_exm; -static uint8_t value_index_dpin; -static uint8_t value_index_cnt; -static uint8_t value_index_pwr; -static uint8_t value_index_time; - #define EXT_MODULES_COUNT (sizeof(radio_modules_variables_text) / sizeof(char* const)) const char* const radio_modules_variables_text[] = { "Internal", @@ -31,19 +25,16 @@ const char* const debug_pin_text[DEBUG_P_COUNT] = { "17(1W)", }; -#define DEBUG_COUNTER_COUNT 6 +#define DEBUG_COUNTER_COUNT 3 const char* const debug_counter_text[DEBUG_COUNTER_COUNT] = { "+1", "+2", "+3", - "+4", - "+5", - "+10", }; static void subghz_scene_ext_module_changed(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); - value_index_exm = variable_item_get_current_value_index(item); + uint8_t value_index_exm = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, radio_modules_variables_text[value_index_exm]); @@ -62,7 +53,7 @@ static void subghz_scene_receiver_config_set_debug_pin(VariableItem* item) { variable_item_set_current_value_text(item, debug_pin_text[index]); - subghz->txrx->debug_pin_state = index == 1; + subghz_txrx_set_debug_pin_state(subghz->txrx, index == 1); } static void subghz_scene_receiver_config_set_debug_counter(VariableItem* item) { @@ -80,15 +71,6 @@ static void subghz_scene_receiver_config_set_debug_counter(VariableItem* item) { case 2: furi_hal_subghz_set_rolling_counter_mult(3); break; - case 3: - furi_hal_subghz_set_rolling_counter_mult(4); - break; - case 4: - furi_hal_subghz_set_rolling_counter_mult(5); - break; - case 5: - furi_hal_subghz_set_rolling_counter_mult(10); - break; default: break; } @@ -122,20 +104,21 @@ static void subghz_scene_receiver_config_set_timestamp_file_names(VariableItem* subghz_last_settings_save(subghz->last_settings); } -void subghz_scene_ext_module_settings_on_enter(void* context) { +void subghz_scene_radio_settings_on_enter(void* context) { SubGhz* subghz = context; VariableItemList* variable_item_list = subghz->variable_item_list; + uint8_t value_index; - value_index_exm = furi_hal_subghz.radio_type; + value_index = furi_hal_subghz.radio_type; VariableItem* item = variable_item_list_add( variable_item_list, "Module", EXT_MODULES_COUNT, subghz_scene_ext_module_changed, subghz); variable_item_list_set_enter_callback( variable_item_list, subghz_ext_module_start_var_list_enter_callback, subghz); - variable_item_set_current_value_index(item, value_index_exm); - variable_item_set_current_value_text(item, radio_modules_variables_text[value_index_exm]); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, radio_modules_variables_text[value_index]); item = variable_item_list_add( subghz->variable_item_list, @@ -143,9 +126,9 @@ void subghz_scene_ext_module_settings_on_enter(void* context) { EXT_MOD_POWER_COUNT, subghz_scene_receiver_config_set_ext_mod_power, subghz); - value_index_pwr = furi_hal_subghz_get_external_power_disable(); - variable_item_set_current_value_index(item, value_index_pwr); - variable_item_set_current_value_text(item, ext_mod_power_text[value_index_pwr]); + value_index = furi_hal_subghz_get_external_power_disable(); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, ext_mod_power_text[value_index]); item = variable_item_list_add( subghz->variable_item_list, @@ -153,21 +136,9 @@ void subghz_scene_ext_module_settings_on_enter(void* context) { TIMESTAMP_NAMES_COUNT, subghz_scene_receiver_config_set_timestamp_file_names, subghz); - value_index_time = furi_hal_subghz_get_timestamp_file_names(); - variable_item_set_current_value_index(item, value_index_time); - variable_item_set_current_value_text(item, timestamp_names_text[value_index_time]); - - item = variable_item_list_add( - subghz->variable_item_list, - "Debug Pin", - DEBUG_P_COUNT, - subghz_scene_receiver_config_set_debug_pin, - subghz); - value_index_dpin = subghz->txrx->debug_pin_state; - variable_item_set_current_value_index(item, value_index_dpin); - variable_item_set_current_value_text(item, debug_pin_text[value_index_dpin]); - variable_item_set_locked( - item, !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug), "Enable\nDebug!"); + value_index = furi_hal_subghz_get_timestamp_file_names(); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, timestamp_names_text[value_index]); item = variable_item_list_add( subghz->variable_item_list, @@ -177,48 +148,49 @@ void subghz_scene_ext_module_settings_on_enter(void* context) { subghz); switch(furi_hal_subghz_get_rolling_counter_mult()) { case 1: - value_index_cnt = 0; + value_index = 0; break; case 2: - value_index_cnt = 1; + value_index = 1; break; case 3: - value_index_cnt = 2; - break; - case 4: - value_index_cnt = 3; - break; - case 5: - value_index_cnt = 4; - break; - case 10: - value_index_cnt = 5; + value_index = 2; break; default: break; } - variable_item_set_current_value_index(item, value_index_cnt); - variable_item_set_current_value_text(item, debug_counter_text[value_index_cnt]); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, debug_counter_text[value_index]); + + item = variable_item_list_add( + subghz->variable_item_list, + "Debug Pin", + DEBUG_P_COUNT, + subghz_scene_receiver_config_set_debug_pin, + subghz); + value_index = subghz_txrx_get_debug_pin_state(subghz->txrx); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, debug_pin_text[value_index]); variable_item_set_locked( item, !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug), "Enable\nDebug!"); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdVariableItemList); } -bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent event) { +bool subghz_scene_radio_settings_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; UNUSED(subghz); UNUSED(event); // Set selected radio module - furi_hal_subghz_select_radio_type(value_index_exm); - furi_hal_subghz_init_radio_type(value_index_exm); + furi_hal_subghz_select_radio_type(subghz->last_settings->external_module_enabled); + furi_hal_subghz_init_radio_type(subghz->last_settings->external_module_enabled); furi_hal_subghz_enable_ext_power(); // Check if module is present, if no -> show error if(!furi_hal_subghz_check_radio()) { - value_index_exm = 0; + subghz->last_settings->external_module_enabled = false; furi_hal_subghz_select_radio_type(SubGhzRadioInternal); furi_hal_subghz_init_radio_type(SubGhzRadioInternal); furi_string_set(subghz->error_str, "Please connect\nexternal radio"); @@ -228,7 +200,7 @@ bool subghz_scene_ext_module_settings_on_event(void* context, SceneManagerEvent return false; } -void subghz_scene_ext_module_settings_on_exit(void* context) { +void subghz_scene_radio_settings_on_exit(void* context) { SubGhz* subghz = context; variable_item_list_reset(subghz->variable_item_list); } diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index 0c692e000..92fcfe125 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -7,20 +7,19 @@ #define RAW_FILE_NAME "RAW_" #define TAG "SubGhzSceneReadRAW" -#define RAW_THRESHOLD_RSSI_LOW_COUNT 10 bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { bool ret = false; //set the path to read the file - FuriString* temp_str; - temp_str = furi_string_alloc(); + FuriString* temp_str = furi_string_alloc(); do { - if(!flipper_format_rewind(subghz->txrx->fff_data)) { + FlipperFormat* fff_data = subghz_txrx_get_fff_data(subghz->txrx); + if(!flipper_format_rewind(fff_data)) { FURI_LOG_E(TAG, "Rewind error"); break; } - if(!flipper_format_read_string(subghz->txrx->fff_data, "File_name", temp_str)) { + if(!flipper_format_read_string(fff_data, "File_name", temp_str)) { FURI_LOG_E(TAG, "Missing File_name"); break; } @@ -38,17 +37,13 @@ static void subghz_scene_read_raw_update_statusbar(void* context) { furi_assert(context); SubGhz* subghz = context; - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); #ifdef SUBGHZ_EXT_PRESET_NAME - subghz_get_frequency_modulation(subghz, frequency_str, NULL); - furi_string_printf(modulation_str, "%s", furi_string_get_cstr(subghz->txrx->preset->name)); + subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, true); #else - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, modulation_str, false); #endif subghz_read_raw_add_data_statusbar( subghz->subghz_read_raw, @@ -74,13 +69,13 @@ void subghz_scene_read_raw_callback_end_tx(void* context) { void subghz_scene_read_raw_on_enter(void* context) { SubGhz* subghz = context; - FuriString* file_name; - file_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); - switch(subghz->txrx->rx_key_state) { + float threshold_rssi = subghz_threshold_rssi_get(subghz->threshold_rssi); + switch(subghz_rx_key_state_get(subghz)) { case SubGhzRxKeyStateBack: subghz_read_raw_set_status( - subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", subghz->txrx->raw_threshold_rssi); + subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", threshold_rssi); break; case SubGhzRxKeyStateRAWLoad: path_extract_filename(subghz->file_path, file_name, true); @@ -88,8 +83,7 @@ void subghz_scene_read_raw_on_enter(void* context) { subghz->subghz_read_raw, SubGhzReadRAWStatusLoadKeyTX, furi_string_get_cstr(file_name), - subghz->txrx->raw_threshold_rssi); - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + threshold_rssi); break; case SubGhzRxKeyStateRAWSave: path_extract_filename(subghz->file_path, file_name, true); @@ -97,69 +91,68 @@ void subghz_scene_read_raw_on_enter(void* context) { subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, furi_string_get_cstr(file_name), - subghz->txrx->raw_threshold_rssi); - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + threshold_rssi); break; default: subghz_read_raw_set_status( - subghz->subghz_read_raw, - SubGhzReadRAWStatusStart, - "", - subghz->txrx->raw_threshold_rssi); - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + subghz->subghz_read_raw, SubGhzReadRAWStatusStart, "", threshold_rssi); break; } + + if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); + } furi_string_free(file_name); subghz_scene_read_raw_update_statusbar(subghz); //set callback view raw subghz_read_raw_set_callback(subghz->subghz_read_raw, subghz_scene_read_raw_callback, subghz); - subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, SUBGHZ_PROTOCOL_RAW_NAME); - furi_assert(subghz->txrx->decoder_result); + furi_check(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_RAW_NAME)); //set filter RAW feed - subghz_receiver_set_filter(subghz->txrx->receiver, SubGhzProtocolFlag_RAW); + subghz_txrx_receiver_set_filter(subghz->txrx, SubGhzProtocolFlag_RAW); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReadRAW); + + // Start sending immediately with favorites + if(subghz->fav_timeout) { + with_view_model( + subghz->subghz_read_raw->view, + SubGhzReadRAWModel * model, + { + scene_manager_handle_custom_event( + subghz->scene_manager, SubGhzCustomEventViewReadRAWSendStart); + model->status = SubGhzReadRAWStatusTXRepeat; + }, + true); + } } bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; bool consumed = false; + SubGhzProtocolDecoderRAW* decoder_raw = + (SubGhzProtocolDecoderRAW*)subghz_txrx_get_decoder(subghz->txrx); if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case SubGhzCustomEventViewReadRAWBack: - //Stop TX - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - //Stop RX - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - }; + + subghz_txrx_stop(subghz->txrx); //Stop save file - subghz_protocol_raw_save_to_file_stop( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result); + subghz_protocol_raw_save_to_file_stop(decoder_raw); subghz->state_notifications = SubGhzNotificationStateIDLE; //needed save? - if((subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) || - (subghz->txrx->rx_key_state == SubGhzRxKeyStateBack)) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateExit; + if((subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey) || + (subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateBack)) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateExit); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { //Restore default setting if(subghz->raw_send_only) { - subghz_preset_init( - subghz, - "AM650", - subghz_setting_get_default_frequency(subghz->setting), - NULL, - 0); + subghz_set_default_preset(subghz); } else { - subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0); + subghz_txrx_set_preset( + subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0); } if(!scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneSaved)) { @@ -174,16 +167,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { break; case SubGhzCustomEventViewReadRAWTXRXStop: - //Stop TX - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } - //Stop RX - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - }; + subghz_txrx_stop(subghz->txrx); subghz->state_notifications = SubGhzNotificationStateIDLE; consumed = true; break; @@ -196,13 +180,13 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { break; case SubGhzCustomEventViewReadRAWErase: - if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) { + if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey) { if(subghz_scene_read_raw_update_filename(subghz)) { furi_string_set(subghz->file_path_tmp, subghz->file_path); subghz_delete_file(subghz); } } - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); notification_message(subghz->notifications, &sequence_reset_rgb); consumed = true; break; @@ -212,7 +196,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { if(subghz_scene_read_raw_update_filename(subghz)) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet); - subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW); consumed = true; } else { @@ -232,33 +216,22 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { if(subghz_file_available(subghz) && subghz_scene_read_raw_update_filename(subghz)) { //start send subghz->state_notifications = SubGhzNotificationStateIDLE; - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - } - if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || - (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - if(!subghz_tx_start(subghz, subghz->txrx->fff_data)) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; - subghz_read_raw_set_status( - subghz->subghz_read_raw, - SubGhzReadRAWStatusIDLE, - "", - subghz->txrx->raw_threshold_rssi); - } else { - if(scene_manager_has_previous_scene( - subghz->scene_manager, SubGhzSceneSaved) || - !scene_manager_has_previous_scene( - subghz->scene_manager, SubGhzSceneStart)) { - DOLPHIN_DEED(DolphinDeedSubGhzSend); - } - // set callback end tx - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( - subghz->txrx->transmitter), - subghz_scene_read_raw_callback_end_tx, - subghz); - subghz->state_notifications = SubGhzNotificationStateTx; + if(!subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx))) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack); + subghz_read_raw_set_status( + subghz->subghz_read_raw, + SubGhzReadRAWStatusIDLE, + "", + subghz_threshold_rssi_get(subghz->threshold_rssi)); + } else { + if(scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneSaved) || + !scene_manager_has_previous_scene(subghz->scene_manager, SubGhzSceneStart)) { + DOLPHIN_DEED(DolphinDeedSubGhzSend); } + // set callback end tx + subghz_txrx_set_raw_file_encoder_worker_callback_end( + subghz->txrx, subghz_scene_read_raw_callback_end_tx, subghz); + subghz->state_notifications = SubGhzNotificationStateTx; } } else { if(!scene_manager_search_and_switch_to_previous_scene( @@ -272,33 +245,29 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { case SubGhzCustomEventViewReadRAWSendStop: subghz->state_notifications = SubGhzNotificationStateIDLE; - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_speaker_unmute(subghz); - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } + subghz_txrx_stop(subghz->txrx); subghz_read_raw_stop_send(subghz->subghz_read_raw); + + // Exit / stop with favorites + if(subghz->fav_timeout) { + while(scene_manager_handle_back_event(subghz->scene_manager)) + ; + view_dispatcher_stop(subghz->view_dispatcher); + } consumed = true; break; case SubGhzCustomEventViewReadRAWIDLE: - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - }; + subghz_txrx_stop(subghz->txrx); + size_t spl_count = subghz_protocol_raw_get_sample_write(decoder_raw); - size_t spl_count = subghz_protocol_raw_get_sample_write( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result); + subghz_protocol_raw_save_to_file_stop(decoder_raw); - subghz_protocol_raw_save_to_file_stop( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result); - - FuriString* temp_str; - temp_str = furi_string_alloc(); + FuriString* temp_str = furi_string_alloc(); furi_string_printf( temp_str, "%s/%s%s", SUBGHZ_RAW_FOLDER, RAW_FILE_NAME, SUBGHZ_APP_EXTENSION); subghz_protocol_raw_gen_fff_data( - subghz->txrx->fff_data, furi_string_get_cstr(temp_str)); + subghz_txrx_get_fff_data(subghz->txrx), furi_string_get_cstr(temp_str)); furi_string_free(temp_str); if(spl_count > 0) { @@ -308,32 +277,21 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { } subghz->state_notifications = SubGhzNotificationStateIDLE; - subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); consumed = true; break; case SubGhzCustomEventViewReadRAWREC: - if(subghz->txrx->rx_key_state != SubGhzRxKeyStateIDLE) { + if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateIDLE) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { - subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT; - if(subghz_protocol_raw_save_to_file_init( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, - RAW_FILE_NAME, - subghz->txrx->preset)) { + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + if(subghz_protocol_raw_save_to_file_init(decoder_raw, RAW_FILE_NAME, &preset)) { DOLPHIN_DEED(DolphinDeedSubGhzRawRec); - if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || - (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - subghz_begin( - subghz, - subghz_setting_get_preset_data_by_name( - subghz->setting, - furi_string_get_cstr(subghz->txrx->preset->name))); - subghz_rx(subghz, subghz->txrx->preset->frequency); - } + subghz_txrx_rx_start(subghz->txrx); subghz->state_notifications = SubGhzNotificationStateRx; - subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } else { furi_string_set(subghz->error_str, "Function requires\nan SD card."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); @@ -346,7 +304,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { if(subghz_file_available(subghz) && subghz_scene_read_raw_update_filename(subghz)) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSetRAW); - subghz->txrx->rx_key_state = SubGhzRxKeyStateBack; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateBack); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); } else { if(!scene_manager_search_and_switch_to_previous_scene( @@ -365,41 +323,15 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { switch(subghz->state_notifications) { case SubGhzNotificationStateRx: notification_message(subghz->notifications, &sequence_blink_cyan_10); + subghz_read_raw_update_sample_write( - subghz->subghz_read_raw, - subghz_protocol_raw_get_sample_write( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result)); - - float rssi = furi_hal_subghz_get_rssi(); - - if(float_is_equal(subghz->txrx->raw_threshold_rssi, SUBGHZ_RAW_THRESHOLD_MIN)) { - subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true); - subghz_protocol_raw_save_to_file_pause( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false); - } else { - if(rssi < subghz->txrx->raw_threshold_rssi) { - subghz->txrx->raw_threshold_rssi_low_count++; - if(subghz->txrx->raw_threshold_rssi_low_count > RAW_THRESHOLD_RSSI_LOW_COUNT) { - subghz->txrx->raw_threshold_rssi_low_count = RAW_THRESHOLD_RSSI_LOW_COUNT; - } - subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false); - } else { - subghz->txrx->raw_threshold_rssi_low_count = 0; - } - - if(subghz->txrx->raw_threshold_rssi_low_count == RAW_THRESHOLD_RSSI_LOW_COUNT) { - subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, false); - subghz_protocol_raw_save_to_file_pause( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, true); - subghz_speaker_mute(subghz); - } else { - subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true); - subghz_protocol_raw_save_to_file_pause( - (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false); - subghz_speaker_unmute(subghz); - } - } + subghz->subghz_read_raw, subghz_protocol_raw_get_sample_write(decoder_raw)); + SubGhzThresholdRssiData ret_rssi = + subghz_threshold_get_rssi_data(subghz->threshold_rssi); + subghz_read_raw_add_data_rssi( + subghz->subghz_read_raw, ret_rssi.rssi, ret_rssi.is_above); + subghz_protocol_raw_save_to_file_pause(decoder_raw, !ret_rssi.is_above); break; case SubGhzNotificationStateTx: notification_message(subghz->notifications, &sequence_blink_magenta_10); @@ -416,13 +348,10 @@ void subghz_scene_read_raw_on_exit(void* context) { SubGhz* subghz = context; //Stop CC1101 - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - }; + subghz_txrx_stop(subghz->txrx); subghz->state_notifications = SubGhzNotificationStateIDLE; notification_message(subghz->notifications, &sequence_reset_rgb); //filter restoration - subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); + subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index b17a0700b..9987449cd 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -39,28 +39,29 @@ const NotificationSequence subghz_sequence_rx_locked = { static void subghz_scene_receiver_update_statusbar(void* context) { SubGhz* subghz = context; - FuriString* history_stat_str; - history_stat_str = furi_string_alloc(); - if(!subghz_history_get_text_space_left(subghz->txrx->history, history_stat_str)) { - FuriString* frequency_str; - FuriString* modulation_str; - - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); + FuriString* history_stat_str = furi_string_alloc(); + if(!subghz_history_get_text_space_left(subghz->history, history_stat_str)) { + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); #ifdef SUBGHZ_EXT_PRESET_NAME - if(subghz_history_get_last_index(subghz->txrx->history) > 0) { - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + if(subghz_history_get_last_index(subghz->history) > 0) { + subghz_txrx_get_frequency_and_modulation( + subghz->txrx, frequency_str, modulation_str, false); } else { - subghz_get_frequency_modulation(subghz, frequency_str, NULL); + FuriString* temp_str = furi_string_alloc(); + + subghz_txrx_get_frequency_and_modulation(subghz->txrx, frequency_str, temp_str, true); furi_string_printf( modulation_str, "%s Mod: %s", furi_hal_subghz_get_radio_type() ? "Ext" : "Int", - furi_string_get_cstr(subghz->txrx->preset->name)); + furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); } #else - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation( + subghz->txrx, frequency_str, modulation_str, false); #endif subghz_view_receiver_add_data_statusbar( @@ -91,128 +92,104 @@ static void subghz_scene_add_to_history_callback( void* context) { furi_assert(context); SubGhz* subghz = context; - FuriString* item_name; - FuriString* item_time; - uint16_t idx = subghz_history_get_item(subghz->txrx->history); - item_name = furi_string_alloc(); - item_time = furi_string_alloc(); + SubGhzHistory* history = subghz->history; + FuriString* item_name = furi_string_alloc(); + FuriString* item_time = furi_string_alloc(); + uint16_t idx = subghz_history_get_item(history); - if(subghz_history_add_to_history(subghz->txrx->history, decoder_base, subghz->txrx->preset)) { + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + if(subghz_history_add_to_history(history, decoder_base, &preset)) { furi_string_reset(item_name); furi_string_reset(item_time); subghz->state_notifications = SubGhzNotificationStateRxDone; - subghz_history_get_text_item_menu(subghz->txrx->history, item_name, idx); - subghz_history_get_time_item_menu(subghz->txrx->history, item_time, idx); + subghz_history_get_text_item_menu(history, item_name, idx); + subghz_history_get_time_item_menu(history, item_time, idx); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, furi_string_get_cstr(item_name), furi_string_get_cstr(item_time), - subghz_history_get_type_protocol(subghz->txrx->history, idx)); + subghz_history_get_type_protocol(history, idx)); subghz_scene_receiver_update_statusbar(subghz); } subghz_receiver_reset(receiver); furi_string_free(item_name); furi_string_free(item_time); - subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } void subghz_scene_receiver_on_enter(void* context) { SubGhz* subghz = context; + SubGhzHistory* history = subghz->history; - FuriString* item_name; - FuriString* item_time; - item_name = furi_string_alloc(); - item_time = furi_string_alloc(); + FuriString* item_name = furi_string_alloc(); + FuriString* item_time = furi_string_alloc(); - if(subghz->txrx->rx_key_state == SubGhzRxKeyStateIDLE) { - subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0); - subghz_history_reset(subghz->txrx->history); - subghz->txrx->rx_key_state = SubGhzRxKeyStateStart; + if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateIDLE) { + subghz_txrx_set_preset(subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0); + subghz_history_reset(history); + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateStart); } - subghz_view_receiver_set_lock(subghz->subghz_receiver, subghz->lock); + subghz_view_receiver_set_lock(subghz->subghz_receiver, subghz_is_locked(subghz)); subghz_view_receiver_set_mode(subghz->subghz_receiver, SubGhzViewReceiverModeLive); //Load history to receiver subghz_view_receiver_exit(subghz->subghz_receiver); - for(uint8_t i = 0; i < subghz_history_get_item(subghz->txrx->history); i++) { + for(uint8_t i = 0; i < subghz_history_get_item(history); i++) { furi_string_reset(item_name); furi_string_reset(item_time); - subghz_history_get_text_item_menu(subghz->txrx->history, item_name, i); - subghz_history_get_time_item_menu(subghz->txrx->history, item_time, i); + subghz_history_get_text_item_menu(history, item_name, i); + subghz_history_get_time_item_menu(history, item_time, i); subghz_view_receiver_add_item_to_menu( subghz->subghz_receiver, furi_string_get_cstr(item_name), furi_string_get_cstr(item_time), - subghz_history_get_type_protocol(subghz->txrx->history, i)); - subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; + subghz_history_get_type_protocol(history, i)); + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } furi_string_free(item_name); furi_string_free(item_time); subghz_scene_receiver_update_statusbar(subghz); subghz_view_receiver_set_callback( subghz->subghz_receiver, subghz_scene_receiver_callback, subghz); - subghz_receiver_set_rx_callback( - subghz->txrx->receiver, subghz_scene_add_to_history_callback, subghz); + subghz_txrx_set_rx_calback(subghz->txrx, subghz_scene_add_to_history_callback, subghz); // TODO: Replace with proper solution based on protocol flags, remove kostily and velosipedy from here // Needs to be done after subghz refactoring merge!!! - if(subghz->txrx->ignore_starline == true) { - SubGhzProtocolDecoderBase* protocoldecoderbase = NULL; - protocoldecoderbase = - subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Star Line"); - if(protocoldecoderbase) { + if(subghz->ignore_starline == true) { + if(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, "Star Line")) { subghz_protocol_decoder_base_set_decoder_callback( - protocoldecoderbase, NULL, subghz->txrx->receiver); + subghz_txrx_get_decoder(subghz->txrx), NULL, NULL); } } - if(subghz->txrx->ignore_auto_alarms == true) { - SubGhzProtocolDecoderBase* protocoldecoderbase = NULL; - protocoldecoderbase = - subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "KIA Seed"); - if(protocoldecoderbase) { + if(subghz->ignore_auto_alarms == true) { + if(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, "KIA Seed")) { subghz_protocol_decoder_base_set_decoder_callback( - protocoldecoderbase, NULL, subghz->txrx->receiver); + subghz_txrx_get_decoder(subghz->txrx), NULL, NULL); } - protocoldecoderbase = NULL; - protocoldecoderbase = - subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Scher-Khan"); - if(protocoldecoderbase) { + + if(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, "Scher-Khan")) { subghz_protocol_decoder_base_set_decoder_callback( - protocoldecoderbase, NULL, subghz->txrx->receiver); + subghz_txrx_get_decoder(subghz->txrx), NULL, NULL); } } - if(subghz->txrx->ignore_magellan == true) { - SubGhzProtocolDecoderBase* protocoldecoderbase = NULL; - protocoldecoderbase = - subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, "Magellan"); - if(protocoldecoderbase) { + if(subghz->ignore_magellan == true) { + if(subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, "Magellan")) { subghz_protocol_decoder_base_set_decoder_callback( - protocoldecoderbase, NULL, subghz->txrx->receiver); + subghz_txrx_get_decoder(subghz->txrx), NULL, NULL); } } subghz->state_notifications = SubGhzNotificationStateRx; - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - } - if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || - (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - subghz_begin( - subghz, - subghz_setting_get_preset_data_by_name( - subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); - subghz_rx(subghz, subghz->txrx->preset->frequency); - } - subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->txrx->idx_menu_chosen); + subghz_txrx_rx_start(subghz->txrx); + subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->idx_menu_chosen); //to use a universal decoder, we are looking for a link to it - subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, SUBGHZ_PROTOCOL_BIN_RAW_NAME); - furi_assert(subghz->txrx->decoder_result); + furi_check( + subghz_txrx_load_decoder_by_name_protocol(subghz->txrx, SUBGHZ_PROTOCOL_BIN_RAW_NAME)); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver); } @@ -225,20 +202,18 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { case SubGhzCustomEventViewReceiverBack: // Stop CC1101 Rx subghz->state_notifications = SubGhzNotificationStateIDLE; - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - } - subghz->txrx->hopper_state = SubGhzHopperStateOFF; - subghz->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); + subghz_txrx_stop(subghz->txrx); + subghz_txrx_hopper_set_state(subghz->txrx, SubGhzHopperStateOFF); + subghz->idx_menu_chosen = 0; + subghz_txrx_set_rx_calback(subghz->txrx, NULL, subghz); - if(subghz->txrx->rx_key_state == SubGhzRxKeyStateAddKey) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateExit; + if(subghz_rx_key_state_get(subghz) == SubGhzRxKeyStateAddKey) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateExit); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNeedSaving); } else { - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; - subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0); + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); + subghz_txrx_set_preset( + subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0); scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); } @@ -246,17 +221,15 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { break; case SubGhzCustomEventViewReceiverOK: // Show file info, scene: receiver_info - subghz->txrx->idx_menu_chosen = - subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverInfo); DOLPHIN_DEED(DolphinDeedSubGhzReceiverInfo); consumed = true; break; case SubGhzCustomEventViewReceiverDeleteItem: - subghz->txrx->idx_menu_chosen = - subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); - subghz_history_delete_item(subghz->txrx->history, subghz->txrx->idx_menu_chosen); + subghz_history_delete_item(subghz->history, subghz->idx_menu_chosen); subghz_view_receiver_delete_element_callback(subghz->subghz_receiver); subghz_scene_receiver_update_statusbar(subghz); @@ -264,8 +237,7 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { break; case SubGhzCustomEventViewReceiverConfig: subghz->state_notifications = SubGhzNotificationStateIDLE; - subghz->txrx->idx_menu_chosen = - subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + subghz->idx_menu_chosen = subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); scene_manager_set_scene_state( subghz->scene_manager, SubGhzViewIdReceiver, SubGhzCustomEventManagerSet); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiverConfig); @@ -276,30 +248,31 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case SubGhzCustomEventViewReceiverUnlock: - subghz->lock = SubGhzLockOff; + subghz_unlock(subghz); consumed = true; break; default: break; } } else if(event.type == SceneManagerEventTypeTick) { - if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { - subghz_hopper_update(subghz); + if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) { + subghz_txrx_hopper_update(subghz->txrx); subghz_scene_receiver_update_statusbar(subghz); } //get RSSI - float rssi = furi_hal_subghz_get_rssi(); - subghz_receiver_rssi(subghz->subghz_receiver, rssi); + SubGhzThresholdRssiData ret_rssi = subghz_threshold_get_rssi_data(subghz->threshold_rssi); + + subghz_receiver_rssi(subghz->subghz_receiver, ret_rssi.rssi); subghz_protocol_decoder_bin_raw_data_input_rssi( - (SubGhzProtocolDecoderBinRAW*)subghz->txrx->decoder_result, rssi); + (SubGhzProtocolDecoderBinRAW*)subghz_txrx_get_decoder(subghz->txrx), ret_rssi.rssi); switch(subghz->state_notifications) { case SubGhzNotificationStateRx: notification_message(subghz->notifications, &sequence_blink_cyan_10); break; case SubGhzNotificationStateRxDone: - if(subghz->lock != SubGhzLockOn) { + if(!subghz_is_locked(subghz)) { notification_message(subghz->notifications, &subghz_sequence_rx); } else { notification_message(subghz->notifications, &subghz_sequence_rx_locked); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 68c5b4b7a..29d55c03a 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -92,13 +92,15 @@ const char* const magellan_text[MAGELLAN_COUNT] = { uint8_t subghz_scene_receiver_config_next_frequency(const uint32_t value, void* context) { furi_assert(context); SubGhz* subghz = context; + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); + uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_frequency_count(subghz->setting); i++) { - if(value == subghz_setting_get_frequency(subghz->setting, i)) { + for(uint8_t i = 0; i < subghz_setting_get_frequency_count(setting); i++) { + if(value == subghz_setting_get_frequency(setting, i)) { index = i; break; } else { - index = subghz_setting_get_frequency_default_index(subghz->setting); + index = subghz_setting_get_frequency_default_index(setting); } } return index; @@ -108,12 +110,14 @@ uint8_t subghz_scene_receiver_config_next_preset(const char* preset_name, void* furi_assert(context); SubGhz* subghz = context; uint8_t index = 0; - for(uint8_t i = 0; i < subghz_setting_get_preset_count(subghz->setting); i++) { - if(!strcmp(subghz_setting_get_preset_name(subghz->setting, i), preset_name)) { + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); + + for(uint8_t i = 0; i < subghz_setting_get_preset_count(setting); i++) { + if(!strcmp(subghz_setting_get_preset_name(setting, i), preset_name)) { index = i; break; } else { - // index = subghz_setting_get_frequency_default_index(subghz->setting); + // index = subghz_setting_get_frequency_default_index(setting); } } return index; @@ -142,74 +146,90 @@ uint8_t subghz_scene_receiver_config_hopper_value_index( static void subghz_scene_receiver_config_set_frequency(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); - if(subghz->txrx->hopper_state == SubGhzHopperStateOFF) { + if(subghz_txrx_hopper_get_state(subghz->txrx) == SubGhzHopperStateOFF) { char text_buf[10] = {0}; + uint32_t frequency = subghz_setting_get_frequency(setting, index); + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + snprintf( text_buf, sizeof(text_buf), "%lu.%02lu", - subghz_setting_get_frequency(subghz->setting, index) / 1000000, - (subghz_setting_get_frequency(subghz->setting, index) % 1000000) / 10000); + frequency / 1000000, + (frequency % 1000000) / 10000); variable_item_set_current_value_text(item, text_buf); - subghz->txrx->preset->frequency = subghz_setting_get_frequency(subghz->setting, index); - subghz->last_settings->frequency = subghz->txrx->preset->frequency; - subghz_setting_set_default_frequency(subghz->setting, subghz->txrx->preset->frequency); + subghz_txrx_set_preset( + subghz->txrx, + furi_string_get_cstr(preset.name), + frequency, + preset.data, + preset.data_size); + + preset = subghz_txrx_get_preset(subghz->txrx); + + subghz->last_settings->frequency = preset.frequency; + subghz_setting_set_default_frequency(setting, preset.frequency); } else { variable_item_set_current_value_index( - item, subghz_setting_get_frequency_default_index(subghz->setting)); + item, subghz_setting_get_frequency_default_index(setting)); } } static void subghz_scene_receiver_config_set_preset(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); - const char* preset_name = subghz_setting_get_preset_name(subghz->setting, index); + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); + + const char* preset_name = subghz_setting_get_preset_name(setting, index); variable_item_set_current_value_text(item, preset_name); //subghz->last_settings->preset = index; - - subghz_preset_init( - subghz, + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + subghz_txrx_set_preset( + subghz->txrx, preset_name, - subghz->txrx->preset->frequency, - subghz_setting_get_preset_data(subghz->setting, index), - subghz_setting_get_preset_data_size(subghz->setting, index)); + preset.frequency, + subghz_setting_get_preset_data(setting, index), + subghz_setting_get_preset_data_size(setting, index)); } static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); + VariableItem* frequency_item = (VariableItem*)scene_manager_get_scene_state( + subghz->scene_manager, SubGhzSceneReceiverConfig); variable_item_set_current_value_text(item, hopping_text[index]); if(hopping_value[index] == SubGhzHopperStateOFF) { char text_buf[10] = {0}; + uint32_t frequency = subghz_setting_get_default_frequency(setting); + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + snprintf( text_buf, sizeof(text_buf), "%lu.%02lu", - subghz_setting_get_default_frequency(subghz->setting) / 1000000, - (subghz_setting_get_default_frequency(subghz->setting) % 1000000) / 10000); - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - subghz->scene_manager, SubGhzSceneReceiverConfig), - text_buf); - subghz->txrx->preset->frequency = subghz_setting_get_default_frequency(subghz->setting); + frequency / 1000000, + (frequency % 1000000) / 10000); + variable_item_set_current_value_text(frequency_item, text_buf); + + subghz_txrx_set_preset( + subghz->txrx, + furi_string_get_cstr(preset.name), + frequency, + preset.data, + preset.data_size); variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - subghz->scene_manager, SubGhzSceneReceiverConfig), - subghz_setting_get_frequency_default_index(subghz->setting)); + frequency_item, subghz_setting_get_frequency_default_index(setting)); } else { - variable_item_set_current_value_text( - (VariableItem*)scene_manager_get_scene_state( - subghz->scene_manager, SubGhzSceneReceiverConfig), - " -----"); + variable_item_set_current_value_text(frequency_item, " -----"); variable_item_set_current_value_index( - (VariableItem*)scene_manager_get_scene_state( - subghz->scene_manager, SubGhzSceneReceiverConfig), - subghz_setting_get_frequency_default_index(subghz->setting)); + frequency_item, subghz_setting_get_frequency_default_index(setting)); } - subghz->txrx->hopper_state = hopping_value[index]; + subghz_txrx_hopper_set_state(subghz->txrx, hopping_value[index]); } static void subghz_scene_receiver_config_set_speaker(VariableItem* item) { @@ -217,7 +237,7 @@ static void subghz_scene_receiver_config_set_speaker(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, speaker_text[index]); - subghz->txrx->speaker_state = speaker_value[index]; + subghz_txrx_speaker_set_state(subghz->txrx, speaker_value[index]); } static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) { @@ -225,8 +245,8 @@ static void subghz_scene_receiver_config_set_bin_raw(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, bin_raw_text[index]); - subghz->txrx->filter = bin_raw_value[index]; - subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); + subghz->filter = bin_raw_value[index]; + subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); } static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* item) { @@ -234,7 +254,7 @@ static void subghz_scene_receiver_config_set_raw_threshold_rssi(VariableItem* it uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, raw_threshold_rssi_text[index]); - subghz->txrx->raw_threshold_rssi = raw_threshold_rssi_value[index]; + subghz_threshold_rssi_set(subghz->threshold_rssi, raw_threshold_rssi_value[index]); } static void subghz_scene_receiver_config_set_starline(VariableItem* item) { @@ -242,7 +262,7 @@ static void subghz_scene_receiver_config_set_starline(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, starline_text[index]); - subghz->txrx->ignore_starline = (index == 1); + subghz->ignore_starline = (index == 1); } static void subghz_scene_receiver_config_set_auto_alarms(VariableItem* item) { @@ -250,7 +270,7 @@ static void subghz_scene_receiver_config_set_auto_alarms(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, auto_alarms_text[index]); - subghz->txrx->ignore_auto_alarms = (index == 1); + subghz->ignore_auto_alarms = (index == 1); } static void subghz_scene_receiver_config_set_magellan(VariableItem* item) { @@ -258,7 +278,7 @@ static void subghz_scene_receiver_config_set_magellan(VariableItem* item) { uint8_t index = variable_item_get_current_value_index(item); variable_item_set_current_value_text(item, magellan_text[index]); - subghz->txrx->ignore_magellan = (index == 1); + subghz->ignore_magellan = (index == 1); } static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { @@ -274,38 +294,40 @@ void subghz_scene_receiver_config_on_enter(void* context) { SubGhz* subghz = context; VariableItem* item; uint8_t value_index; + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); + SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); item = variable_item_list_add( subghz->variable_item_list, "Frequency:", - subghz_setting_get_frequency_count(subghz->setting), + subghz_setting_get_frequency_count(setting), subghz_scene_receiver_config_set_frequency, subghz); - value_index = - subghz_scene_receiver_config_next_frequency(subghz->txrx->preset->frequency, subghz); + value_index = subghz_scene_receiver_config_next_frequency(preset.frequency, subghz); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReceiverConfig, (uint32_t)item); variable_item_set_current_value_index(item, value_index); char text_buf[10] = {0}; + uint32_t frequency = subghz_setting_get_frequency(setting, value_index); snprintf( text_buf, sizeof(text_buf), "%lu.%02lu", - subghz_setting_get_frequency(subghz->setting, value_index) / 1000000, - (subghz_setting_get_frequency(subghz->setting, value_index) % 1000000) / 10000); + frequency / 1000000, + (frequency % 1000000) / 10000); variable_item_set_current_value_text(item, text_buf); item = variable_item_list_add( subghz->variable_item_list, "Modulation:", - subghz_setting_get_preset_count(subghz->setting), + subghz_setting_get_preset_count(setting), subghz_scene_receiver_config_set_preset, subghz); - value_index = subghz_scene_receiver_config_next_preset( - furi_string_get_cstr(subghz->txrx->preset->name), subghz); + value_index = + subghz_scene_receiver_config_next_preset(furi_string_get_cstr(preset.name), subghz); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text( - item, subghz_setting_get_preset_name(subghz->setting, value_index)); + item, subghz_setting_get_preset_name(setting, value_index)); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerSet) { @@ -317,7 +339,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_hopping_running, subghz); value_index = subghz_scene_receiver_config_hopper_value_index( - subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); + subghz_txrx_hopper_get_state(subghz->txrx), hopping_value, HOPPING_COUNT, subghz); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, hopping_text[value_index]); } @@ -330,7 +352,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { BIN_RAW_COUNT, subghz_scene_receiver_config_set_bin_raw, subghz); - value_index = value_index_uint32(subghz->txrx->filter, bin_raw_value, BIN_RAW_COUNT); + value_index = value_index_uint32(subghz->filter, bin_raw_value, BIN_RAW_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, bin_raw_text[value_index]); } @@ -344,7 +366,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_starline, subghz); - value_index = subghz->txrx->ignore_starline; + value_index = subghz->ignore_starline; variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, starline_text[value_index]); @@ -355,7 +377,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_auto_alarms, subghz); - value_index = subghz->txrx->ignore_auto_alarms; + value_index = subghz->ignore_auto_alarms; variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, auto_alarms_text[value_index]); @@ -366,7 +388,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_magellan, subghz); - value_index = subghz->txrx->ignore_magellan; + value_index = subghz->ignore_magellan; variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, magellan_text[value_index]); } @@ -378,7 +400,8 @@ void subghz_scene_receiver_config_on_enter(void* context) { SPEAKER_COUNT, subghz_scene_receiver_config_set_speaker, subghz); - value_index = value_index_uint32(subghz->txrx->speaker_state, speaker_value, SPEAKER_COUNT); + value_index = value_index_uint32( + subghz_txrx_speaker_get_state(subghz->txrx), speaker_value, SPEAKER_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, speaker_text[value_index]); @@ -400,7 +423,9 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz_scene_receiver_config_set_raw_threshold_rssi, subghz); value_index = value_index_float( - subghz->txrx->raw_threshold_rssi, raw_threshold_rssi_value, RAW_THRESHOLD_RSSI_COUNT); + subghz_threshold_rssi_get(subghz->threshold_rssi), + raw_threshold_rssi_value, + RAW_THRESHOLD_RSSI_COUNT); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, raw_threshold_rssi_text[value_index]); } @@ -413,7 +438,7 @@ bool subghz_scene_receiver_config_on_event(void* context, SceneManagerEvent even if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneSettingLock) { - subghz->lock = SubGhzLockOn; + subghz_lock(subghz); scene_manager_previous_scene(subghz->scene_manager); consumed = true; } diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index 58e428785..370638931 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -23,20 +23,19 @@ void subghz_scene_receiver_info_callback(GuiButtonType result, InputType type, v static bool subghz_scene_receiver_info_update_parser(void* context) { SubGhz* subghz = context; - subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, - subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); - if(subghz->txrx->decoder_result) { - //todo we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal + if(subghz_txrx_load_decoder_by_name_protocol( + subghz->txrx, + subghz_history_get_protocol_name(subghz->history, subghz->idx_menu_chosen))) { + //todo we are trying to deserialize without checking for errors, since it is assumed that we just received this signal subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, - subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); + subghz_txrx_get_decoder(subghz->txrx), + subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen)); SubGhzRadioPreset* preset = - subghz_history_get_radio_preset(subghz->txrx->history, subghz->txrx->idx_menu_chosen); - subghz_preset_init( - subghz, + subghz_history_get_radio_preset(subghz->history, subghz->idx_menu_chosen); + subghz_txrx_set_preset( + subghz->txrx, furi_string_get_cstr(preset->name), preset->frequency, preset->data, @@ -49,15 +48,12 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) { if(subghz_scene_receiver_info_update_parser(subghz)) { - FuriString* frequency_str; - FuriString* modulation_str; - FuriString* text; + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); + FuriString* text = furi_string_alloc(); - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - text = furi_string_alloc(); - - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation( + subghz->txrx, frequency_str, modulation_str, false); widget_add_string_element( subghz->widget, 78, @@ -75,7 +71,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) { AlignTop, FontSecondary, furi_string_get_cstr(modulation_str)); - subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, text); + subghz_protocol_decoder_base_get_string(subghz_txrx_get_decoder(subghz->txrx), text); widget_add_string_multiline_element( subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(text)); @@ -83,8 +79,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) { furi_string_free(modulation_str); furi_string_free(text); - if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == - SubGhzProtocolFlag_Save) { + if(subghz_txrx_protocol_is_serializable(subghz->txrx)) { widget_add_button_element( subghz->widget, GuiButtonTypeRight, @@ -93,9 +88,7 @@ void subghz_scene_receiver_info_draw_widget(SubGhz* subghz) { subghz); } // Removed static check - if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) == - SubGhzProtocolFlag_Send) && - subghz->txrx->decoder_result->protocol->encoder->deserialize) { + if(subghz_txrx_protocol_is_transmittable(subghz->txrx, false)) { widget_add_button_element( subghz->widget, GuiButtonTypeCenter, @@ -125,40 +118,19 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneReceiverInfoTxStart) { - //CC1101 Stop RX -> Start TX - if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { - subghz->txrx->hopper_state = SubGhzHopperStatePause; - } - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - } if(!subghz_scene_receiver_info_update_parser(subghz)) { return false; } - if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE || - subghz->txrx->txrx_state == SubGhzTxRxStateSleep) { - if(!subghz_tx_start( - subghz, - subghz_history_get_raw_data( - subghz->txrx->history, subghz->txrx->idx_menu_chosen))) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - } - if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) { - subghz_begin( - subghz, - subghz_setting_get_preset_data_by_name( - subghz->setting, - furi_string_get_cstr(subghz->txrx->preset->name))); - subghz_rx(subghz, subghz->txrx->preset->frequency); - } - if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { - subghz->txrx->hopper_state = SubGhzHopperStateRunning; - } - subghz->state_notifications = SubGhzNotificationStateRx; - } else { - subghz->state_notifications = SubGhzNotificationStateTx; - } + //CC1101 Stop RX -> Start TX + subghz_txrx_hopper_pause(subghz->txrx); + if(!subghz_tx_start( + subghz, + subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen))) { + subghz_txrx_rx_start(subghz->txrx); + subghz_txrx_hopper_unpause(subghz->txrx); + subghz->state_notifications = SubGhzNotificationStateRx; + } else { + subghz->state_notifications = SubGhzNotificationStateTx; } return true; } else if(event.event == SubGhzCustomEventSceneReceiverInfoTxStop) { @@ -168,37 +140,25 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) widget_reset(subghz->widget); subghz_scene_receiver_info_draw_widget(subghz); - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - } + subghz_txrx_stop(subghz->txrx); if(!subghz->in_decoder_scene) { - if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) { - subghz_begin( - subghz, - subghz_setting_get_preset_data_by_name( - subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); - subghz_rx(subghz, subghz->txrx->preset->frequency); - } - if(subghz->txrx->hopper_state == SubGhzHopperStatePause) { - subghz->txrx->hopper_state = SubGhzHopperStateRunning; - } + subghz_txrx_rx_start(subghz->txrx); + + subghz_txrx_hopper_unpause(subghz->txrx); subghz->state_notifications = SubGhzNotificationStateRx; } return true; } else if(event.event == SubGhzCustomEventSceneReceiverInfoSave) { //CC1101 Stop RX -> Save subghz->state_notifications = SubGhzNotificationStateIDLE; - subghz->txrx->hopper_state = SubGhzHopperStateOFF; - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - subghz_sleep(subghz); - } + subghz_txrx_hopper_set_state(subghz->txrx, SubGhzHopperStateOFF); + + subghz_txrx_stop(subghz->txrx); if(!subghz_scene_receiver_info_update_parser(subghz)) { return false; } - if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == - SubGhzProtocolFlag_Save) { + if(subghz_txrx_protocol_is_serializable(subghz->txrx)) { subghz_file_name_clear(subghz); if(subghz->in_decoder_scene) { @@ -209,8 +169,8 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) return true; } } else if(event.type == SceneManagerEventTypeTick) { - if(subghz->txrx->hopper_state != SubGhzHopperStateOFF) { - subghz_hopper_update(subghz); + if(subghz_txrx_hopper_get_state(subghz->txrx) != SubGhzHopperStateOFF) { + subghz_txrx_hopper_update(subghz->txrx); } switch(subghz->state_notifications) { case SubGhzNotificationStateTx: diff --git a/applications/main/subghz/scenes/subghz_scene_rpc.c b/applications/main/subghz/scenes/subghz_scene_rpc.c index 82ab184d1..8a52cf2a9 100644 --- a/applications/main/subghz/scenes/subghz_scene_rpc.c +++ b/applications/main/subghz/scenes/subghz_scene_rpc.c @@ -9,6 +9,7 @@ typedef enum { SubGhzRpcStateIdle, SubGhzRpcStateLoaded, + SubGhzRpcStateTx, } SubGhzRpcState; void subghz_scene_rpc_on_enter(void* context) { @@ -43,9 +44,9 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { view_dispatcher_stop(subghz->view_dispatcher); } else if(event.event == SubGhzCustomEventSceneRpcButtonPress) { bool result = false; - if((subghz->txrx->txrx_state == SubGhzTxRxStateSleep) && - (state == SubGhzRpcStateLoaded)) { - result = subghz_tx_start(subghz, subghz->txrx->fff_data); + if((state == SubGhzRpcStateLoaded)) { + result = subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx)); + state = SubGhzRpcStateTx; if(result) subghz_blink_start(subghz); } if(!result) { @@ -57,10 +58,10 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonPress, result); } else if(event.event == SubGhzCustomEventSceneRpcButtonRelease) { bool result = false; - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { + if(state == SubGhzRpcStateTx) { + subghz_txrx_stop(subghz->txrx); subghz_blink_stop(subghz); - subghz_tx_stop(subghz); - subghz_sleep(subghz); + state = SubGhzRpcStateIdle; result = true; } rpc_system_app_confirm(subghz->rpc_ctx, RpcAppEventButtonRelease, result); @@ -73,8 +74,7 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneRpc, SubGhzRpcStateLoaded); furi_string_set(subghz->file_path, arg); result = true; - FuriString* file_name; - file_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); path_extract_filename(subghz->file_path, file_name, true); snprintf( @@ -99,9 +99,9 @@ bool subghz_scene_rpc_on_event(void* context, SceneManagerEvent event) { void subghz_scene_rpc_on_exit(void* context) { SubGhz* subghz = context; - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); + SubGhzRpcState state = scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneRpc); + if(state != SubGhzRpcStateIdle) { + subghz_txrx_stop(subghz->txrx); subghz_blink_stop(subghz); } diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index d3f5474be..b0c3a1b12 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -51,23 +51,22 @@ void subghz_scene_save_name_on_enter(void* context) { TextInput* text_input = subghz->text_input; bool dev_name_empty = false; - FuriString* file_name; - FuriString* dir_name; - file_name = furi_string_alloc(); - dir_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); + FuriString* dir_name = furi_string_alloc(); if(!subghz_path_is_file(subghz->file_path)) { char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0}; if(furi_hal_subghz_get_timestamp_file_names()) { - if(subghz->txrx->decoder_result != 0x0) { - if(subghz->txrx->decoder_result != NULL) { - if(strlen(subghz->txrx->decoder_result->protocol->name) != 0) { + SubGhzProtocolDecoderBase* decoder_result = subghz_txrx_get_decoder(subghz->txrx); + if(decoder_result != 0x0) { + if(decoder_result != NULL) { + if(strlen(decoder_result->protocol->name) != 0) { if(scene_manager_has_previous_scene( subghz->scene_manager, SubGhzSceneSetType)) { subghz_scene_save_name_get_timefilename(file_name, "S", true); } else { subghz_scene_save_name_get_timefilename( - file_name, subghz->txrx->decoder_result->protocol->name, false); + file_name, decoder_result->protocol->name, false); } } else { @@ -109,7 +108,7 @@ void subghz_scene_save_name_on_enter(void* context) { subghz_scene_save_name_text_input_callback, subghz, subghz->file_name_tmp, - MAX_TEXT_INPUT_LEN, // buffer size + MAX_TEXT_INPUT_LEN, dev_name_empty); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( @@ -148,7 +147,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { SubGhzCustomEventManagerNoSet) { subghz_save_protocol_to_file( subghz, - subghz->txrx->fff_data, + subghz_txrx_get_fff_data(subghz->txrx), furi_string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, @@ -157,8 +156,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { } else { subghz_save_protocol_to_file( subghz, - subghz_history_get_raw_data( - subghz->txrx->history, subghz->txrx->idx_menu_chosen), + subghz_history_get_raw_data(subghz->history, subghz->idx_menu_chosen), furi_string_get_cstr(subghz->file_path)); } } @@ -166,7 +164,8 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { subghz_protocol_raw_gen_fff_data( - subghz->txrx->fff_data, furi_string_get_cstr(subghz->file_path)); + subghz_txrx_get_fff_data(subghz->txrx), + furi_string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); } else { diff --git a/applications/main/subghz/scenes/subghz_scene_save_success.c b/applications/main/subghz/scenes/subghz_scene_save_success.c index 107dc7b7d..9033f694b 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_success.c +++ b/applications/main/subghz/scenes/subghz_scene_save_success.c @@ -28,10 +28,10 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event) if(!subghz->in_decoder_scene) { if(!scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneReceiver)) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWSave; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWSave); if(!scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneReadRAW)) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); if(!scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneSaved)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved); @@ -40,8 +40,8 @@ bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent event) } } else { subghz->decode_raw_state = SubGhzDecodeRawStateStart; - subghz->txrx->idx_menu_chosen = 0; - subghz_receiver_set_rx_callback(subghz->txrx->receiver, NULL, subghz); + subghz->idx_menu_chosen = 0; + subghz_txrx_set_rx_calback(subghz->txrx, NULL, subghz); if(subghz_file_encoder_worker_is_running(subghz->decode_raw_file_worker_encoder)) { subghz_file_encoder_worker_stop(subghz->decode_raw_file_worker_encoder); diff --git a/applications/main/subghz/scenes/subghz_scene_saved.c b/applications/main/subghz/scenes/subghz_scene_saved.c index 62ade3508..8b198e339 100644 --- a/applications/main/subghz/scenes/subghz_scene_saved.c +++ b/applications/main/subghz/scenes/subghz_scene_saved.c @@ -4,8 +4,8 @@ void subghz_scene_saved_on_enter(void* context) { SubGhz* subghz = context; if(subghz_load_protocol_from_file(subghz)) { - if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { - subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; + if(subghz_get_load_type_file(subghz) == SubGhzLoadTypeFileRaw) { + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); } else { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); diff --git a/applications/main/subghz/scenes/subghz_scene_set_cnt.c b/applications/main/subghz/scenes/subghz_scene_set_cnt.c index 62ef581ff..4faff7bbb 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_cnt.c +++ b/applications/main/subghz/scenes/subghz_scene_set_cnt.c @@ -24,7 +24,7 @@ void subghz_scene_set_cnt_on_enter(void* context) { subghz_scene_set_cnt_byte_input_callback, NULL, subghz, - subghz->txrx->secure_data->cnt, + subghz->secure_data->cnt, 2); break; case SubmenuIndexFaacSLH_433: @@ -35,7 +35,7 @@ void subghz_scene_set_cnt_on_enter(void* context) { subghz_scene_set_cnt_byte_input_callback, NULL, subghz, - subghz->txrx->secure_data->cnt, + subghz->secure_data->cnt, 3); break; default: diff --git a/applications/main/subghz/scenes/subghz_scene_set_fix.c b/applications/main/subghz/scenes/subghz_scene_set_fix.c index 01431dac6..7564fb24d 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_fix.c +++ b/applications/main/subghz/scenes/subghz_scene_set_fix.c @@ -19,7 +19,7 @@ void subghz_scene_set_fix_on_enter(void* context) { subghz_scene_set_fix_byte_input_callback, NULL, subghz, - subghz->txrx->secure_data->fix, + subghz->secure_data->fix, 4); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } diff --git a/applications/main/subghz/scenes/subghz_scene_set_seed.c b/applications/main/subghz/scenes/subghz_scene_set_seed.c index aa2a270f3..e6850d1e3 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_seed.c +++ b/applications/main/subghz/scenes/subghz_scene_set_seed.c @@ -1,6 +1,5 @@ #include "../subghz_i.h" -#include -#include +#include "../helpers/subghz_txrx_create_protocol_key.h" #define TAG "SubGhzSetSeed" @@ -21,7 +20,7 @@ void subghz_scene_set_seed_on_enter(void* context) { subghz_scene_set_seed_byte_input_callback, NULL, subghz, - subghz->txrx->secure_data->seed, + subghz->secure_data->seed, 4); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdByteInput); } @@ -38,46 +37,23 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { switch(state) { case SubmenuIndexBFTClone: - fix_part = subghz->txrx->secure_data->fix[0] << 24 | - subghz->txrx->secure_data->fix[1] << 16 | - subghz->txrx->secure_data->fix[2] << 8 | - subghz->txrx->secure_data->fix[3]; + fix_part = subghz->secure_data->fix[0] << 24 | subghz->secure_data->fix[1] << 16 | + subghz->secure_data->fix[2] << 8 | subghz->secure_data->fix[3]; - cnt = subghz->txrx->secure_data->cnt[0] << 8 | subghz->txrx->secure_data->cnt[1]; + cnt = subghz->secure_data->cnt[0] << 8 | subghz->secure_data->cnt[1]; - seed = subghz->txrx->secure_data->seed[0] << 24 | - subghz->txrx->secure_data->seed[1] << 16 | - subghz->txrx->secure_data->seed[2] << 8 | - subghz->txrx->secure_data->seed[3]; + seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | + subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); - if(subghz->txrx->transmitter) { - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - subghz_protocol_keeloq_bft_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - fix_part & 0x0FFFFFFF, - fix_part >> 28, - cnt, - seed, - "BFT", - subghz->txrx->preset); - - uint8_t seed_data[sizeof(uint32_t)] = {0}; - for(size_t i = 0; i < sizeof(uint32_t); i++) { - seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF; - } - - flipper_format_write_hex( - subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); - - flipper_format_write_string_cstr(subghz->txrx->fff_data, "Manufacture", "BFT"); - - generated_protocol = true; - } - - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( + subghz->txrx, + "AM650", + 433920000, + fix_part & 0x0FFFFFFF, + fix_part >> 28, + cnt, + seed, + "BFT"); if(!generated_protocol) { furi_string_set( @@ -88,53 +64,37 @@ bool subghz_scene_set_seed_on_event(void* context, SceneManagerEvent event) { break; case SubmenuIndexFaacSLH_433: case SubmenuIndexFaacSLH_868: - fix_part = subghz->txrx->secure_data->fix[0] << 24 | - subghz->txrx->secure_data->fix[1] << 16 | - subghz->txrx->secure_data->fix[2] << 8 | - subghz->txrx->secure_data->fix[3]; + fix_part = subghz->secure_data->fix[0] << 24 | subghz->secure_data->fix[1] << 16 | + subghz->secure_data->fix[2] << 8 | subghz->secure_data->fix[3]; - cnt = subghz->txrx->secure_data->cnt[0] << 16 | - subghz->txrx->secure_data->cnt[1] << 8 | subghz->txrx->secure_data->cnt[2]; + cnt = subghz->secure_data->cnt[0] << 16 | subghz->secure_data->cnt[1] << 8 | + subghz->secure_data->cnt[2]; - seed = subghz->txrx->secure_data->seed[0] << 24 | - subghz->txrx->secure_data->seed[1] << 16 | - subghz->txrx->secure_data->seed[2] << 8 | - subghz->txrx->secure_data->seed[3]; + seed = subghz->secure_data->seed[0] << 24 | subghz->secure_data->seed[1] << 16 | + subghz->secure_data->seed[2] << 8 | subghz->secure_data->seed[3]; - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "Faac SLH"); - if(subghz->txrx->transmitter) { - SubGhzCustomEvent state = - scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType); - - if(state == SubmenuIndexFaacSLH_433) { - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - } else if(state == SubmenuIndexFaacSLH_868) { - subghz_preset_init(subghz, "AM650", 868350000, NULL, 0); - } - subghz_protocol_faac_slh_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, + if(state == SubmenuIndexFaacSLH_433) { + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + "AM650", + 433920000, fix_part >> 4, fix_part & 0xf, (cnt & 0xFFFFF), seed, - "FAAC_SLH", - subghz->txrx->preset); - // RogueMaster dont steal! - uint8_t seed_data[sizeof(uint32_t)] = {0}; - for(size_t i = 0; i < sizeof(uint32_t); i++) { - seed_data[sizeof(uint32_t) - i - 1] = (seed >> i * 8) & 0xFF; - } - - flipper_format_write_hex( - subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); - - generated_protocol = true; + "FAAC_SLH"); + } else if(state == SubmenuIndexFaacSLH_868) { + generated_protocol = subghz_txrx_gen_faac_slh_protocol( + subghz->txrx, + "AM650", + 868350000, + fix_part >> 4, + fix_part & 0xf, + (cnt & 0xFFFFF), + seed, + "FAAC_SLH"); } - subghz_transmitter_free(subghz->txrx->transmitter); - if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index e871a6439..ef53006da 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -1,102 +1,10 @@ #include "../subghz_i.h" -#include -#include -#include -#include -#include +#include "../helpers/subghz_txrx_create_protocol_key.h" #include -#include -#include #include #define TAG "SubGhzSetType" -bool subghz_scene_set_type_submenu_gen_data_protocol( - void* context, - const char* protocol_name, - uint64_t key, - uint32_t bit, - uint32_t frequency, - const char* preset_name) { - furi_assert(context); - SubGhz* subghz = context; - - bool res = false; - - subghz_preset_init(subghz, preset_name, frequency, NULL, 0); - subghz->txrx->decoder_result = - subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, protocol_name); - - if(subghz->txrx->decoder_result == NULL) { - furi_string_set(subghz->error_str, "Protocol not\nfound!"); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); - return false; - } - - do { - Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); - stream_clean(fff_data_stream); - if(subghz_protocol_decoder_base_serialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset) != - SubGhzProtocolStatusOk) { - FURI_LOG_E(TAG, "Unable to serialize"); - break; - } - if(!flipper_format_update_uint32(subghz->txrx->fff_data, "Bit", &bit, 1)) { - FURI_LOG_E(TAG, "Unable to update Bit"); - break; - } - - uint8_t key_data[sizeof(uint64_t)] = {0}; - for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (key >> (i * 8)) & 0xFF; - } - if(!flipper_format_update_hex(subghz->txrx->fff_data, "Key", key_data, sizeof(uint64_t))) { - FURI_LOG_E(TAG, "Unable to update Key"); - break; - } - res = true; - } while(false); - return res; -} - -bool subghz_scene_set_type_submenu_gen_data_keeloq( - void* context, - const char* preset_name, - uint32_t frequency, - uint32_t serial, - uint8_t btn, - uint16_t cnt, - const char* manufacture_name) { - SubGhz* subghz = context; - - bool res = false; - - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); - subghz_preset_init(subghz, preset_name, frequency, NULL, 0); - - if(subghz->txrx->transmitter && - subghz_protocol_keeloq_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - serial, - btn, - cnt, - manufacture_name, - subghz->txrx->preset)) { - flipper_format_write_string_cstr(subghz->txrx->fff_data, "Manufacture", manufacture_name); - res = true; - } - - subghz_transmitter_free(subghz->txrx->transmitter); - if(!res) { - furi_string_set(subghz->error_str, "Function requires\nan SD card with\nfresh databases."); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); - } - return res; -} - void subghz_scene_set_type_submenu_callback(void* context, uint32_t index) { SubGhz* subghz = context; view_dispatcher_send_custom_event(subghz->view_dispatcher, index); @@ -306,7 +214,7 @@ void subghz_scene_set_type_on_enter(void* context) { submenu_add_item( subghz->submenu, "Princeton 433MHz", - SubmenuIndexPricenton, + SubmenuIndexPricenton433, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( @@ -385,8 +293,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { bool generated_protocol = false; if(event.type == SceneManagerEventTypeCustom) { - //ToDo Fix - uint32_t key = subghz_random_serial(); + uint32_t key = (uint32_t)rand(); switch(event.event) { case SubmenuIndexFaacSLH_868: scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); @@ -397,258 +304,246 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexBFTClone: scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetFix); break; - case SubmenuIndexPricenton: + case SubmenuIndexPricenton433: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_PRINCETON_NAME, key, 24, 433920000, "AM650")) { - uint32_t te = 400; - flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol_and_te( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_PRINCETON_NAME, key, 24, 400); break; case SubmenuIndexPricenton315: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_PRINCETON_NAME, key, 24, 315000000, "AM650")) { - uint32_t te = 400; - flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol_and_te( + subghz->txrx, "AM650", 315000000, SUBGHZ_PROTOCOL_PRINCETON_NAME, key, 24, 400); break; case SubmenuIndexNiceFlo12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 12, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 12); break; case SubmenuIndexNiceFlo24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 24, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_NICE_FLO_NAME, key, 24); break; case SubmenuIndexCAME12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 12, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_CAME_NAME, key, 12); break; case SubmenuIndexCAME24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 24, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_CAME_NAME, key, 24); break; case SubmenuIndexCAME12bit868: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 12, 868350000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 868350000, SUBGHZ_PROTOCOL_CAME_NAME, key, 12); break; case SubmenuIndexCAME24bit868: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_CAME_NAME, key, 24, 868350000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 868350000, SUBGHZ_PROTOCOL_CAME_NAME, key, 24); break; case SubmenuIndexLinear_300_00: key = (key & 0x3FF); - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_LINEAR_NAME, key, 10, 300000000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 300000000, SUBGHZ_PROTOCOL_LINEAR_NAME, key, 10); break; case SubmenuIndexBETT_433: key = (key & 0x0000FFF0); - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_BETT_NAME, key, 18, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_BETT_NAME, key, 18); break; case SubmenuIndexCAMETwee: key = (key & 0x0FFFFFF0); key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE); - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_CAME_TWEE_NAME, key, 54, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_CAME_TWEE_NAME, key, 54); break; - // case SubmenuIndexNeroSketch: - // /* code */ - // break; - // case SubmenuIndexNeroRadio: - // /* code */ - // break; case SubmenuIndexGateTX: key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?) uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24); - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, SUBGHZ_PROTOCOL_GATE_TX_NAME, rev_key, 24, 433920000, "AM650")) { - generated_protocol = true; - } + generated_protocol = subghz_txrx_gen_data_protocol( + subghz->txrx, "AM650", 433920000, SUBGHZ_PROTOCOL_GATE_TX_NAME, rev_key, 24); break; case SubmenuIndexBeninca433: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 433920000, - (key & 0x000FFF00) | 0x00800080, - 0x1, - 0x0005, - "Beninca")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x000FFF00) | 0x00800080, + 0x1, + 0x0005, + "Beninca"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexBeninca868: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 868350000, - (key & 0x000FFF00) | 0x00800080, - 0x1, - 0x0005, - "Beninca")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 868350000, + (key & 0x000FFF00) | 0x00800080, + 0x1, + 0x0005, + "Beninca"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexAllmatic433: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 433920000, - (key & 0x00FFFF00) | 0x01000011, - 0xC, - 0x0005, - "Beninca")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x00FFFF00) | 0x01000011, + 0xC, + 0x0005, + "Beninca"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexAllmatic868: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 868350000, - (key & 0x00FFFF00) | 0x01000011, - 0xC, - 0x0005, - "Beninca")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 868350000, + (key & 0x00FFFF00) | 0x01000011, + 0xC, + 0x0005, + "Beninca"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexElmesElectronic: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 433920000, - (key & 0x00FFFFFF) | 0x02000000, - 0x2, - 0x0003, - "Elmes_Poland")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x00FFFFFF) | 0x02000000, + 0x2, + 0x0003, + "Elmes_Poland"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexANMotorsAT4: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 433920000, - (key & 0x000FFFFF) | 0x04700000, - 0x2, - 0x0021, - "AN-Motors")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x000FFFFF) | 0x04700000, + 0x2, + 0x0021, + "AN-Motors"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexAprimatic: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, - "AM650", - 433920000, - (key & 0x000FFFFF) | 0x00600000, - 0x4, - 0x0003, - "Aprimatic")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x000FFFFF) | 0x00600000, + 0x4, + 0x0003, + "Aprimatic"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexGibidi433: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "Gibidi")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "Gibidi"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexGSN: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x0FFFFFFF, 0x2, 0x0003, "GSN")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x0FFFFFFF, 0x2, 0x0003, "GSN"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexIronLogic: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x00FFFFF0, 0x4, 0x0005, "IronLogic")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x00FFFFF0, 0x4, 0x0005, "IronLogic"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexSommer_FM_434: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "FM476", 434420000, key & 0x0FFFFFFF, 0x4, 0x0003, "Sommer(fsk476)")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "FM476", 434420000, key & 0x0FFFFFFF, 0x4, 0x0003, "Sommer(fsk476)"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexSommer_FM_868: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "FM476", 868800000, key & 0x0FFFFFFF, 0x4, 0x0003, "Sommer(fsk476)")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "FM476", 868800000, key & 0x0FFFFFFF, 0x4, 0x0003, "Sommer(fsk476)"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexDTMNeo433: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x000FFFFF, 0x2, 0x0005, "DTM_Neo")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x000FFFFF, 0x2, 0x0005, "DTM_Neo"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexCAMESpace: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "Came_Space")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "Came_Space"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexBFTMitto: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_keeloq_bft_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key & 0x000FFFFF, - 0x2, - 0x0002, - key & 0x000FFFFF, - "BFT", - subghz->txrx->preset); - - uint8_t seed_data[sizeof(uint32_t)] = {0}; - for(size_t i = 0; i < sizeof(uint32_t); i++) { - seed_data[sizeof(uint32_t) - i - 1] = ((key & 0x000FFFFF) >> i * 8) & 0xFF; - } - - flipper_format_write_hex( - subghz->txrx->fff_data, "Seed", seed_data, sizeof(uint32_t)); - - flipper_format_write_string_cstr(subghz->txrx->fff_data, "Manufacture", "BFT"); - - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_keeloq_bft_protocol( + subghz->txrx, + "AM650", + 433920000, + key & 0x000FFFFF, + 0x2, + 0x0002, + key & 0x000FFFFF, + "BFT"); if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); @@ -656,22 +551,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexAlutechAT4N: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_ALUTECH_AT_4N_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_alutech_at_4n_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - (key & 0x000FFFFF) | 0x00100000, - 0x44, - 0x0003, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_alutech_at_4n_protocol( + subghz->txrx, "AM650", 433920000, (key & 0x000FFFFF) | 0x00100000, 0x44, 0x0003); if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); @@ -679,58 +560,30 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexSomfyTelis: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_somfy_telis_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key & 0x00FFFFFF, - 0x2, - 0x0003, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_somfy_telis_protocol( + subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003); + break; + case SubmenuIndexDoorHan_433_92: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x0FFFFFFF, 0x2, 0x0003, "DoorHan"); if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; - case SubmenuIndexDoorHan_433_92: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x0FFFFFFF, 0x2, 0x0003, "DoorHan")) { - generated_protocol = true; - } - break; case SubmenuIndexDoorHan_315_00: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 315000000, key & 0x0FFFFFFF, 0x2, 0x0003, "DoorHan")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 315000000, key & 0x0FFFFFFF, 0x2, 0x0003, "DoorHan"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexNiceFlorS_433_92: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_nice_flor_s_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key & 0x0FFFFFFF, - 0x1, - 0x0003, - subghz->txrx->preset, - false); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, "AM650", 433920000, key & 0x0FFFFFFF, 0x1, 0x0003, false); if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); @@ -738,23 +591,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexNiceOne_433_92: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_nice_flor_s_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key & 0x0FFFFFFF, - 0x1, - 0x0003, - subghz->txrx->preset, - true); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_nice_flor_s_protocol( + subghz->txrx, "AM650", 433920000, key & 0x0FFFFFFF, 0x1, 0x0003, true); if(!generated_protocol) { furi_string_set( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); @@ -762,124 +600,41 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexNiceSmilo_433_92: - if(subghz_scene_set_type_submenu_gen_data_keeloq( - subghz, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "NICE_Smilo")) { - generated_protocol = true; + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "NICE_Smilo"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; case SubmenuIndexLiftMaster_315_00: - while(!subghz_protocol_secplus_v1_check_fixed(key)) { - key = subghz_random_serial(); - } - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, - SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, - (uint64_t)key << 32 | 0xE6000000, - 42, - 315000000, - "AM650")) { - generated_protocol = true; - } + generated_protocol = + subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, "AM650", 315000000); break; case SubmenuIndexLiftMaster_390_00: - while(!subghz_protocol_secplus_v1_check_fixed(key)) { - key = subghz_random_serial(); - } - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, - SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, - (uint64_t)key << 32 | 0xE6000000, - 42, - 390000000, - "AM650")) { - generated_protocol = true; - } + generated_protocol = + subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, "AM650", 390000000); break; case SubmenuIndexLiftMaster_433_00: - while(!subghz_protocol_secplus_v1_check_fixed(key)) { - key = subghz_random_serial(); - } - if(subghz_scene_set_type_submenu_gen_data_protocol( - subghz, - SUBGHZ_PROTOCOL_SECPLUS_V1_NAME, - (uint64_t)key << 32 | 0xE6000000, - 42, - 433920000, - "AM650")) { - generated_protocol = true; - } + generated_protocol = + subghz_txrx_gen_secplus_v1_protocol(subghz->txrx, "AM650", 433920000); break; case SubmenuIndexSecPlus_v2_310_00: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); - subghz_preset_init(subghz, "AM650", 310000000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_secplus_v2_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key, - 0x68, - 0xE500000, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, "AM650", 310000000, key, 0x68, 0xE500000); break; case SubmenuIndexSecPlus_v2_315_00: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); - subghz_preset_init(subghz, "AM650", 315000000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_secplus_v2_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key, - 0x68, - 0xE500000, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, "AM650", 315000000, key, 0x68, 0xE500000); break; case SubmenuIndexSecPlus_v2_390_00: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); - subghz_preset_init(subghz, "AM650", 390000000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_secplus_v2_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key, - 0x68, - 0xE500000, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, "AM650", 390000000, key, 0x68, 0xE500000); break; case SubmenuIndexSecPlus_v2_433_00: - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, SUBGHZ_PROTOCOL_SECPLUS_V2_NAME); - subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); - if(subghz->txrx->transmitter) { - subghz_protocol_secplus_v2_create_data( - subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), - subghz->txrx->fff_data, - key, - 0x68, - 0xE500000, - subghz->txrx->preset); - generated_protocol = true; - } else { - generated_protocol = false; - } - subghz_transmitter_free(subghz->txrx->transmitter); + generated_protocol = subghz_txrx_gen_secplus_v2_protocol( + subghz->txrx, "AM650", 433920000, key, 0x68, 0xE500000); break; default: return false; diff --git a/applications/main/subghz/scenes/subghz_scene_show_error.c b/applications/main/subghz/scenes/subghz_scene_show_error.c index 107189cae..4544260ef 100644 --- a/applications/main/subghz/scenes/subghz_scene_show_error.c +++ b/applications/main/subghz/scenes/subghz_scene_show_error.c @@ -50,9 +50,10 @@ void subghz_scene_show_error_on_enter(void* context) { bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; + SubGhzCustomEvent scene_state = + scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowError); if(event.type == SceneManagerEventTypeBack) { - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowError) == - SubGhzCustomEventManagerSet) { + if(scene_state == SubGhzCustomEventManagerSet) { return false; } else { scene_manager_search_and_switch_to_previous_scene( @@ -61,14 +62,12 @@ bool subghz_scene_show_error_on_event(void* context, SceneManagerEvent event) { return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneShowErrorOk) { - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowError) == - SubGhzCustomEventManagerSet) { + if(scene_state == SubGhzCustomEventManagerSet) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); } return true; } else if(event.event == SubGhzCustomEventSceneShowErrorBack) { - if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneShowError) == - SubGhzCustomEventManagerSet) { + if(scene_state == SubGhzCustomEventManagerSet) { //exit app if(!scene_manager_previous_scene(subghz->scene_manager)) { scene_manager_stop(subghz->scene_manager); diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index e3c70aaf6..78b99c691 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -97,7 +97,7 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { } else if(event.event == SubmenuIndexReadRAW) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexReadRAW); - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); return true; } else if(event.event == SubmenuIndexRead) { diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index ab9155fb7..12f23cf11 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -1,6 +1,7 @@ #include "../subghz_i.h" #include "../views/transmitter.h" #include +#include #include #include @@ -15,32 +16,25 @@ void subghz_scene_transmitter_callback(SubGhzCustomEvent event, void* context) { bool subghz_scene_transmitter_update_data_show(void* context) { SubGhz* subghz = context; bool ret = false; - if(subghz->txrx->decoder_result) { - FuriString* key_str; - FuriString* frequency_str; - FuriString* modulation_str; + SubGhzProtocolDecoderBase* decoder = subghz_txrx_get_decoder(subghz->txrx); - key_str = furi_string_alloc(); - frequency_str = furi_string_alloc(); - modulation_str = furi_string_alloc(); - uint8_t show_button = 0; + if(decoder) { + FuriString* key_str = furi_string_alloc(); + FuriString* frequency_str = furi_string_alloc(); + FuriString* modulation_str = furi_string_alloc(); if(subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data) == SubGhzProtocolStatusOk) { - subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, key_str); + decoder, subghz_txrx_get_fff_data(subghz->txrx)) == SubGhzProtocolStatusOk) { + subghz_protocol_decoder_base_get_string(decoder, key_str); - if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) == - SubGhzProtocolFlag_Send) { - show_button = 1; - } - - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_txrx_get_frequency_and_modulation( + subghz->txrx, frequency_str, modulation_str, false); subghz_view_transmitter_add_data_to_show( subghz->subghz_transmitter, furi_string_get_cstr(key_str), furi_string_get_cstr(frequency_str), furi_string_get_cstr(modulation_str), - show_button); + subghz_txrx_protocol_is_transmittable(subghz->txrx, false)); ret = true; } furi_string_free(frequency_str); @@ -50,6 +44,12 @@ bool subghz_scene_transmitter_update_data_show(void* context) { return ret; } +void fav_timer_callback(void* context) { + SubGhz* subghz = context; + scene_manager_handle_custom_event( + subghz->scene_manager, SubGhzCustomEventViewTransmitterSendStop); +} + void subghz_scene_transmitter_on_enter(void* context) { SubGhz* subghz = context; @@ -66,6 +66,23 @@ void subghz_scene_transmitter_on_enter(void* context) { subghz->state_notifications = SubGhzNotificationStateIDLE; view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTransmitter); + + // Auto send and exit with favorites + if(subghz->fav_timeout) { + subghz_custom_btn_set(0); + scene_manager_handle_custom_event( + subghz->scene_manager, SubGhzCustomEventViewTransmitterSendStart); + with_view_model( + subghz->subghz_transmitter->view, + SubGhzViewTransmitterModel * model, + { model->show_button = false; }, + true); + subghz->fav_timer = furi_timer_alloc(fav_timer_callback, FuriTimerTypeOnce, subghz); + furi_timer_start( + subghz->fav_timer, + XTREME_SETTINGS()->favorite_timeout * furi_kernel_get_tick_frequency()); + subghz->state_notifications = SubGhzNotificationStateTx; + } } bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { @@ -73,42 +90,30 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventViewTransmitterSendStart) { subghz->state_notifications = SubGhzNotificationStateIDLE; - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - } - if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || - (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - if(subghz_tx_start(subghz, subghz->txrx->fff_data)) { - subghz->state_notifications = SubGhzNotificationStateTx; - subghz_scene_transmitter_update_data_show(subghz); - DOLPHIN_DEED(DolphinDeedSubGhzSend); - } + + if(subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx))) { + subghz->state_notifications = SubGhzNotificationStateTx; + subghz_scene_transmitter_update_data_show(subghz); + DOLPHIN_DEED(DolphinDeedSubGhzSend); } return true; } else if(event.event == SubGhzCustomEventViewTransmitterSendStop) { subghz->state_notifications = SubGhzNotificationStateIDLE; - if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { - subghz_tx_stop(subghz); - subghz_sleep(subghz); - } + subghz_txrx_stop(subghz->txrx); if(subghz_custom_btn_get() != 0) { subghz_custom_btn_set(0); uint8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); furi_hal_subghz_set_rolling_counter_mult(0); // Calling restore! - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - } - if((subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) || - (subghz->txrx->txrx_state == SubGhzTxRxStateSleep)) { - if(!subghz_tx_start(subghz, subghz->txrx->fff_data)) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); - } - } - subghz_tx_stop(subghz); - subghz_sleep(subghz); + subghz_tx_start(subghz, subghz_txrx_get_fff_data(subghz->txrx)); + subghz_txrx_stop(subghz->txrx); furi_hal_subghz_set_rolling_counter_mult(tmp_counter); } + if(subghz->fav_timeout) { + while(scene_manager_handle_back_event(subghz->scene_manager)) + ; + view_dispatcher_stop(subghz->view_dispatcher); + } return true; } else if(event.event == SubGhzCustomEventViewTransmitterBack) { subghz->state_notifications = SubGhzNotificationStateIDLE; diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 47da7ae40..7fdfc80fd 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -4,6 +4,8 @@ #include #include "subghz_i.h" #include +#include +#include #define TAG "SubGhzApp" @@ -51,16 +53,6 @@ static void subghz_rpc_command_callback(RpcAppSystemEvent event, void* context) } } -void subghz_blink_start(SubGhz* instance) { - furi_assert(instance); - notification_message(instance->notifications, &sequence_blink_start_magenta); -} - -void subghz_blink_stop(SubGhz* instance) { - furi_assert(instance); - notification_message(instance->notifications, &sequence_blink_stop); -} - SubGhz* subghz_alloc(bool alloc_for_tx_only) { SubGhz* subghz = malloc(sizeof(SubGhz)); @@ -180,10 +172,15 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { subghz_test_static_get_view(subghz->subghz_test_static)); #endif - //init setting - subghz->setting = subghz_setting_alloc(); + //init threshold rssi + subghz->threshold_rssi = subghz_threshold_rssi_alloc(); - subghz_setting_load(subghz->setting, EXT_PATH("subghz/assets/setting_user")); + //init TxRx & Protocol & History & KeyBoard + subghz_unlock(subghz); + + subghz->txrx = subghz_txrx_alloc(); + + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); // Custom Presets load without using config file if(!alloc_for_tx_only) { @@ -193,7 +190,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { (const char*)"Custom_preset_data", (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 83 10 67 15 24 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"FM95", temp_fm_preset); + subghz_setting_load_custom_preset(setting, (const char*)"FM95", temp_fm_preset); flipper_format_free(temp_fm_preset); @@ -204,7 +201,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { (const char*)"Custom_preset_data", (const char*)"02 0D 03 47 08 32 0B 06 15 32 14 00 13 00 12 00 11 32 10 A7 18 18 19 1D 1D 92 1C 00 1B 04 20 FB 22 17 21 B6 00 00 00 12 0E 34 60 C5 C1 C0"); flipper_format_rewind(temp_fm_preset2); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"FM15k", temp_fm_preset2); + subghz_setting_load_custom_preset(setting, (const char*)"FM15k", temp_fm_preset2); flipper_format_free(temp_fm_preset2); @@ -215,7 +212,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { (const char*)"Custom_preset_data", (const char*)"02 0D 07 04 08 32 0B 06 10 64 11 93 12 0C 13 02 14 00 15 15 18 18 19 16 1B 07 1C 00 1D 91 20 FB 21 56 22 10 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset3); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"Pagers", temp_fm_preset3); + subghz_setting_load_custom_preset(setting, (const char*)"Pagers", temp_fm_preset3); flipper_format_free(temp_fm_preset3); @@ -226,7 +223,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { (const char*)"Custom_preset_data", (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 04 11 36 10 69 15 32 18 18 19 16 1D 91 1C 00 1B 07 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset4); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_1", temp_fm_preset4); + subghz_setting_load_custom_preset(setting, (const char*)"HND_1", temp_fm_preset4); flipper_format_free(temp_fm_preset4); @@ -236,7 +233,7 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { (const char*)"Custom_preset_data", (const char*)"02 0D 0B 06 08 32 07 04 14 00 13 02 12 07 11 36 10 E9 15 32 18 18 19 16 1D 92 1C 40 1B 03 20 FB 22 10 21 56 00 00 C0 00 00 00 00 00 00 00"); flipper_format_rewind(temp_fm_preset5); - subghz_setting_load_custom_preset(subghz->setting, (const char*)"HND_2", temp_fm_preset5); + subghz_setting_load_custom_preset(setting, (const char*)"HND_2", temp_fm_preset5); flipper_format_free(temp_fm_preset5); } @@ -253,52 +250,24 @@ SubGhz* subghz_alloc(bool alloc_for_tx_only) { subghz->last_settings->frequency, subghz->last_settings->preset); #endif - subghz_setting_set_default_frequency(subghz->setting, subghz->last_settings->frequency); + subghz_setting_set_default_frequency(setting, subghz->last_settings->frequency); } - //init Worker & Protocol & History & KeyBoard - subghz->lock = SubGhzLockOff; - subghz->txrx = malloc(sizeof(SubGhzTxRx)); - subghz->txrx->preset = malloc(sizeof(SubGhzRadioPreset)); - subghz->txrx->preset->name = furi_string_alloc(); + if(!alloc_for_tx_only) { - subghz_preset_init(subghz, "AM650", subghz->last_settings->frequency, NULL, 0); - } else { - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_txrx_set_preset(subghz->txrx, "AM650", subghz->last_settings->frequency, NULL, 0); } - subghz->txrx->txrx_state = SubGhzTxRxStateSleep; - subghz->txrx->hopper_state = SubGhzHopperStateOFF; - subghz->txrx->speaker_state = SubGhzSpeakerStateDisable; - subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; - subghz->txrx->debug_pin_state = false; + + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE); + if(!alloc_for_tx_only) { - subghz->txrx->history = subghz_history_alloc(); + subghz->history = subghz_history_alloc(); } - subghz->txrx->raw_threshold_rssi = SUBGHZ_RAW_THRESHOLD_MIN; - subghz->txrx->worker = subghz_worker_alloc(); + subghz->secure_data = malloc(sizeof(SecureData)); - subghz->txrx->fff_data = flipper_format_string_alloc(); - subghz->txrx->secure_data = malloc(sizeof(SecureData)); - - subghz->txrx->environment = subghz_environment_alloc(); - subghz_environment_set_came_atomo_rainbow_table_file_name( - subghz->txrx->environment, EXT_PATH("subghz/assets/came_atomo")); - subghz_environment_set_alutech_at_4n_rainbow_table_file_name( - subghz->txrx->environment, EXT_PATH("subghz/assets/alutech_at_4n")); - subghz_environment_set_nice_flor_s_rainbow_table_file_name( - subghz->txrx->environment, EXT_PATH("subghz/assets/nice_flor_s")); - subghz_environment_set_protocol_registry( - subghz->txrx->environment, (void*)&subghz_protocol_registry); - subghz->txrx->receiver = subghz_receiver_alloc_init(subghz->txrx->environment); - subghz->txrx->filter = SubGhzProtocolFlag_Decodable; - subghz_receiver_set_filter(subghz->txrx->receiver, subghz->txrx->filter); - - subghz_worker_set_overrun_callback( - subghz->txrx->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); - subghz_worker_set_pair_callback( - subghz->txrx->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); - subghz_worker_set_context(subghz->txrx->worker, subghz->txrx->receiver); + subghz->filter = SubGhzProtocolFlag_Decodable; + subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); + subghz_txrx_set_need_save_callback(subghz->txrx, subghz_save_to_file, subghz); //Init Error_str subghz->error_str = furi_string_alloc(); @@ -316,7 +285,9 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { subghz->rpc_ctx = NULL; } - subghz_speaker_off(subghz); + subghz_txrx_speaker_off(subghz->txrx); + subghz_txrx_stop(subghz->txrx); + subghz_txrx_sleep(subghz->txrx); #if FURI_DEBUG // Packet Test @@ -386,27 +357,19 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { furi_record_close(RECORD_GUI); subghz->gui = NULL; - //setting - subghz_setting_free(subghz->setting); + subghz_last_settings_free(subghz->last_settings); + + // threshold rssi + subghz_threshold_rssi_free(subghz->threshold_rssi); + if(!alloc_for_tx_only) { - subghz_last_settings_free(subghz->last_settings); + subghz_history_free(subghz->history); } - //Worker & Protocol & History - subghz_receiver_free(subghz->txrx->receiver); + free(subghz->secure_data); - subghz_environment_free(subghz->txrx->environment); - - subghz_worker_free(subghz->txrx->worker); - - flipper_format_free(subghz->txrx->fff_data); - if(!alloc_for_tx_only) { - subghz_history_free(subghz->txrx->history); - } - furi_string_free(subghz->txrx->preset->name); - free(subghz->txrx->preset); - free(subghz->txrx->secure_data); - free(subghz->txrx); + //TxRx + subghz_txrx_free(subghz->txrx); //Error string furi_string_free(subghz->error_str); @@ -423,7 +386,7 @@ void subghz_free(SubGhz* subghz, bool alloc_for_tx_only) { free(subghz); } -int32_t subghz_app(void* p) { +int32_t subghz_app(char* p) { bool alloc_for_tx; if(p && strlen(p)) { alloc_for_tx = true; @@ -439,12 +402,6 @@ int32_t subghz_app(void* p) { subghz->raw_send_only = false; } - //Load database - bool load_database = subghz_environment_load_keystore( - subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); - subghz_environment_load_keystore( - subghz->txrx->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); - // Call enable power for external module furi_hal_subghz_enable_ext_power(); @@ -455,6 +412,7 @@ int32_t subghz_app(void* p) { furi_hal_subghz_init_radio_type(SubGhzRadioInternal); } // Check argument and run corresponding scene + bool is_favorite = process_favorite_launch(&p) && XTREME_SETTINGS()->favorite_timeout; if(p && strlen(p)) { uint32_t rpc_ctx = 0; @@ -471,9 +429,10 @@ int32_t subghz_app(void* p) { if(subghz_key_load(subghz, p, true)) { furi_string_set(subghz->file_path, (const char*)p); - if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { + subghz->fav_timeout = is_favorite; + if(subghz_get_load_type_file(subghz) == SubGhzLoadTypeFileRaw) { //Load Raw TX - subghz->txrx->rx_key_state = SubGhzRxKeyStateRAWLoad; + subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); } else { //Load transmitter TX @@ -489,7 +448,7 @@ int32_t subghz_app(void* p) { view_dispatcher_attach_to_gui( subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen); furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER); - if(load_database) { + if(subghz_txrx_is_database_loaded(subghz->txrx)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); } else { scene_manager_set_scene_state( @@ -505,6 +464,11 @@ int32_t subghz_app(void* p) { view_dispatcher_run(subghz->view_dispatcher); + if(subghz->fav_timer) { + furi_timer_stop(subghz->fav_timer); + furi_timer_free(subghz->fav_timer); + } + furi_hal_power_suppress_charge_exit(); // Disable power for External CC1101 if it was enabled and module is connected furi_hal_subghz_disable_ext_power(); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index be7143643..815857cc9 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -215,8 +215,7 @@ static void subghz_cli_command_rx_callback( SubGhzCliCommandRx* instance = context; instance->packet_count++; - FuriString* text; - text = furi_string_alloc(); + FuriString* text = furi_string_alloc(); subghz_protocol_decoder_base_get_string(decoder_base, text); subghz_receiver_reset(receiver); printf("%s", furi_string_get_cstr(text)); @@ -384,14 +383,12 @@ void subghz_cli_command_rx_raw(Cli* cli, FuriString* args, void* context) { } void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) { UNUSED(context); - FuriString* file_name; - file_name = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); furi_string_set(file_name, ANY_PATH("subghz/test.sub")); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - FuriString* temp_str; - temp_str = furi_string_alloc(); + FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; bool check_file = false; @@ -526,10 +523,8 @@ static void subghz_cli_command_encrypt_keeloq(Cli* cli, FuriString* args) { UNUSED(cli); uint8_t iv[16]; - FuriString* source; - FuriString* destination; - source = furi_string_alloc(); - destination = furi_string_alloc(); + FuriString* source = furi_string_alloc(); + FuriString* destination = furi_string_alloc(); SubGhzKeystore* keystore = subghz_keystore_alloc(); @@ -569,10 +564,8 @@ static void subghz_cli_command_encrypt_raw(Cli* cli, FuriString* args) { UNUSED(cli); uint8_t iv[16]; - FuriString* source; - FuriString* destination; - source = furi_string_alloc(); - destination = furi_string_alloc(); + FuriString* source = furi_string_alloc(); + FuriString* destination = furi_string_alloc(); do { if(!args_read_string_and_trim(args, source)) { @@ -646,14 +639,10 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { size_t message_max_len = 64; uint8_t message[64] = {0}; - FuriString* input; - input = furi_string_alloc(); - FuriString* name; - name = furi_string_alloc(); - FuriString* output; - output = furi_string_alloc(); - FuriString* sysmsg; - sysmsg = furi_string_alloc(); + FuriString* input = furi_string_alloc(); + FuriString* name = furi_string_alloc(); + FuriString* output = furi_string_alloc(); + FuriString* sysmsg = furi_string_alloc(); bool exit = false; SubGhzChatEvent chat_event; @@ -786,8 +775,7 @@ static void subghz_cli_command_chat(Cli* cli, FuriString* args, void* context) { } static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { - FuriString* cmd; - cmd = furi_string_alloc(); + FuriString* cmd = furi_string_alloc(); do { if(!args_read_string_and_trim(args, cmd)) { diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 3c018ec8b..396e28421 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -197,8 +197,7 @@ bool subghz_history_add_to_history( instance->code_last_hash_data = subghz_protocol_decoder_base_get_hash_data(decoder_base); instance->last_update_timestamp = furi_get_tick(); - FuriString* text; - text = furi_string_alloc(); + FuriString* text = furi_string_alloc(); SubGhzHistoryItem* item = SubGhzHistoryItemArray_push_raw(instance->history->data); item->preset = malloc(sizeof(SubGhzRadioPreset)); item->type = decoder_base->protocol->type; diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index dd0160213..70812ed11 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -18,215 +18,42 @@ #define TAG "SubGhz" -void subghz_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size) { - furi_assert(context); - SubGhz* subghz = context; - furi_string_set(subghz->txrx->preset->name, preset_name); - subghz->txrx->preset->frequency = frequency; - subghz->txrx->preset->data = preset_data; - subghz->txrx->preset->data_size = preset_data_size; -} - -bool subghz_set_preset(SubGhz* subghz, const char* preset) { - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - furi_string_set(subghz->txrx->preset->name, "AM270"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - furi_string_set(subghz->txrx->preset->name, "AM650"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - furi_string_set(subghz->txrx->preset->name, "FM238"); - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - furi_string_set(subghz->txrx->preset->name, "FM476"); - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - furi_string_set(subghz->txrx->preset->name, "CUSTOM"); - } else { - FURI_LOG_E(TAG, "Unknown preset"); - return false; - } - return true; -} - -void subghz_get_frequency_modulation(SubGhz* subghz, FuriString* frequency, FuriString* modulation) { +void subghz_set_default_preset(SubGhz* subghz) { furi_assert(subghz); - if(frequency != NULL) { - furi_string_printf( - frequency, - "%03ld.%02ld", - subghz->txrx->preset->frequency / 1000000 % 1000, - subghz->txrx->preset->frequency / 10000 % 100); - } - if(modulation != NULL) { - furi_string_printf(modulation, "%.2s", furi_string_get_cstr(subghz->txrx->preset->name)); - } + subghz_txrx_set_preset( + subghz->txrx, + "AM650", + subghz_setting_get_default_frequency(subghz_txrx_get_setting(subghz->txrx)), + NULL, + 0); } -void subghz_begin(SubGhz* subghz, uint8_t* preset_data) { +void subghz_blink_start(SubGhz* subghz) { furi_assert(subghz); - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(preset_data); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; + notification_message(subghz->notifications, &sequence_blink_stop); + notification_message(subghz->notifications, &sequence_blink_start_magenta); } -uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency) { +void subghz_blink_stop(SubGhz* subghz) { furi_assert(subghz); - if(!furi_hal_subghz_is_frequency_valid(frequency)) { - furi_crash("SubGhz: Incorrect RX frequency."); - } - furi_assert( - subghz->txrx->txrx_state != SubGhzTxRxStateRx && - subghz->txrx->txrx_state != SubGhzTxRxStateSleep); - - furi_hal_subghz_idle(); - uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - furi_hal_subghz_flush_rx(); - subghz_speaker_on(subghz); - furi_hal_subghz_rx(); - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->txrx->worker); - subghz_worker_start(subghz->txrx->worker); - subghz->txrx->txrx_state = SubGhzTxRxStateRx; - return value; -} - -static bool subghz_tx(SubGhz* subghz, uint32_t frequency) { - furi_assert(subghz); - if(!furi_hal_subghz_is_frequency_valid(frequency)) { - furi_crash("SubGhz: Incorrect TX frequency."); - } - furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); - furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - bool ret = furi_hal_subghz_tx(); - if(ret) { - subghz_speaker_on(subghz); - subghz->txrx->txrx_state = SubGhzTxRxStateTx; - } - return ret; -} - -void subghz_idle(SubGhz* subghz) { - furi_assert(subghz); - furi_assert(subghz->txrx->txrx_state != SubGhzTxRxStateSleep); - furi_hal_subghz_idle(); - subghz_speaker_off(subghz); - subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; -} - -void subghz_rx_end(SubGhz* subghz) { - furi_assert(subghz); - furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateRx); - - if(subghz_worker_is_running(subghz->txrx->worker)) { - subghz_worker_stop(subghz->txrx->worker); - furi_hal_subghz_stop_async_rx(); - } - furi_hal_subghz_idle(); - subghz_speaker_off(subghz); - subghz->txrx->txrx_state = SubGhzTxRxStateIDLE; -} - -void subghz_sleep(SubGhz* subghz) { - furi_assert(subghz); - furi_hal_subghz_sleep(); - subghz->txrx->txrx_state = SubGhzTxRxStateSleep; + notification_message(subghz->notifications, &sequence_blink_stop); } bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { - furi_assert(subghz); + switch(subghz_txrx_tx_start(subghz->txrx, flipper_format)) { + case SubGhzTxRxStartTxStateErrorParserOthers: + dialog_message_show_storage_error( + subghz->dialogs, "Error in protocol\nparameters\ndescription"); + break; + case SubGhzTxRxStartTxStateErrorOnlyRx: + subghz_dialog_message_show_only_rx(subghz); + break; - bool ret = false; - FuriString* temp_str; - temp_str = furi_string_alloc(); - uint32_t repeat = 200; - do { - if(!flipper_format_rewind(flipper_format)) { - FURI_LOG_E(TAG, "Rewind error"); - break; - } - if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - subghz->txrx->transmitter = subghz_transmitter_alloc_init( - subghz->txrx->environment, furi_string_get_cstr(temp_str)); - - if(subghz->txrx->transmitter) { - if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format) == - SubGhzProtocolStatusOk) { - if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "") != 0) { - subghz_begin( - subghz, - subghz_setting_get_preset_data_by_name( - subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name))); - } else { - FURI_LOG_E( - TAG, - "Unknown name preset \" %s \"", - furi_string_get_cstr(subghz->txrx->preset->name)); - subghz_begin( - subghz, subghz_setting_get_preset_data_by_name(subghz->setting, "AM650")); - } - if(subghz->txrx->preset->frequency) { - ret = subghz_tx(subghz, subghz->txrx->preset->frequency); - } else { - ret = subghz_tx(subghz, 433920000); - } - if(ret) { - //Start TX - furi_hal_subghz_start_async_tx( - subghz_transmitter_yield, subghz->txrx->transmitter); - } else { - subghz_dialog_message_show_only_rx(subghz); - } - } else { - dialog_message_show_storage_error( - subghz->dialogs, "Error in protocol\nparameters\ndescription"); - } - } - if(!ret) { - subghz_transmitter_free(subghz->txrx->transmitter); - if(subghz->txrx->txrx_state != SubGhzTxRxStateSleep) { - subghz_idle(subghz); - } - } - - } while(false); - furi_string_free(temp_str); - return ret; -} - -void subghz_tx_stop(SubGhz* subghz) { - furi_assert(subghz); - furi_assert(subghz->txrx->txrx_state == SubGhzTxRxStateTx); - //Stop TX - furi_hal_subghz_stop_async_tx(); - subghz_transmitter_stop(subghz->txrx->transmitter); - subghz_transmitter_free(subghz->txrx->transmitter); - - //if protocol dynamic then we save the last upload - if((subghz->txrx->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) && - (subghz_path_is_file(subghz->file_path))) { - subghz_save_protocol_to_file( - subghz, subghz->txrx->fff_data, furi_string_get_cstr(subghz->file_path)); + default: + return true; + break; } - subghz_idle(subghz); - subghz_speaker_off(subghz); - notification_message(subghz->notifications, &sequence_reset_red); + return false; } void subghz_dialog_message_show_only_rx(SubGhz* subghz) { @@ -251,11 +78,11 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); + Stream* fff_data_stream = + flipper_format_get_raw_stream(subghz_txrx_get_fff_data(subghz->txrx)); SubGhzLoadKeyState load_key_state = SubGhzLoadKeyStateParseErr; - FuriString* temp_str; - temp_str = furi_string_alloc(); + FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; do { @@ -278,6 +105,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { break; } + //Load frequency if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { FURI_LOG_E(TAG, "Missing Frequency"); break; @@ -293,58 +121,62 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { load_key_state = SubGhzLoadKeyStateOnlyRx; break; } - subghz->txrx->preset->frequency = temp_data32; + //Load preset if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { FURI_LOG_E(TAG, "Missing Preset"); break; } - if(!subghz_set_preset(subghz, furi_string_get_cstr(temp_str))) { + furi_string_set_str( + temp_str, subghz_txrx_get_preset_name(subghz->txrx, furi_string_get_cstr(temp_str))); + if(!strcmp(furi_string_get_cstr(temp_str), "")) { break; } + SubGhzSetting* setting = subghz_txrx_get_setting(subghz->txrx); - if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { + if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) { //Todo add Custom_preset_module //delete preset if it already exists - subghz_setting_delete_custom_preset( - subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name)); + subghz_setting_delete_custom_preset(setting, furi_string_get_cstr(temp_str)); //load custom preset from file if(!subghz_setting_load_custom_preset( - subghz->setting, - furi_string_get_cstr(subghz->txrx->preset->name), - fff_data_file)) { + setting, furi_string_get_cstr(temp_str), fff_data_file)) { FURI_LOG_E(TAG, "Missing Custom preset"); break; } } - size_t preset_index = subghz_setting_get_inx_preset_by_name( - subghz->setting, furi_string_get_cstr(subghz->txrx->preset->name)); - subghz_preset_init( - subghz, - furi_string_get_cstr(subghz->txrx->preset->name), - subghz->txrx->preset->frequency, - subghz_setting_get_preset_data(subghz->setting, preset_index), - subghz_setting_get_preset_data_size(subghz->setting, preset_index)); + size_t preset_index = + subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str)); + subghz_txrx_set_preset( + subghz->txrx, + furi_string_get_cstr(temp_str), + temp_data32, + subghz_setting_get_preset_data(setting, preset_index), + subghz_setting_get_preset_data_size(setting, preset_index)); + //Load protocol if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { FURI_LOG_E(TAG, "Missing Protocol"); break; } + + FlipperFormat* fff_data = subghz_txrx_get_fff_data(subghz->txrx); if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { //if RAW - subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, file_path); + subghz->load_type_file = SubGhzLoadTypeFileRaw; + subghz_protocol_raw_gen_fff_data(fff_data, file_path); } else { + subghz->load_type_file = SubGhzLoadTypeFileKey; stream_copy_full( flipper_format_get_raw_stream(fff_data_file), - flipper_format_get_raw_stream(subghz->txrx->fff_data)); + flipper_format_get_raw_stream(fff_data)); } - subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( - subghz->txrx->receiver, furi_string_get_cstr(temp_str)); - if(subghz->txrx->decoder_result) { + if(subghz_txrx_load_decoder_by_name_protocol( + subghz->txrx, furi_string_get_cstr(temp_str))) { SubGhzProtocolStatus status = subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data); + subghz_txrx_get_decoder(subghz->txrx), fff_data); if(status != SubGhzProtocolStatusOk) { load_key_state = SubGhzLoadKeyStateProtocolDescriptionErr; break; @@ -389,17 +221,18 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { } } +SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz) { + furi_assert(subghz); + return subghz->load_type_file; +} + bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { furi_assert(subghz); Storage* storage = furi_record_open(RECORD_STORAGE); - FuriString* temp_str; - FuriString* file_name; - FuriString* file_path; - - temp_str = furi_string_alloc(); - file_name = furi_string_alloc(); - file_path = furi_string_alloc(); + FuriString* temp_str = furi_string_alloc(); + FuriString* file_name = furi_string_alloc(); + FuriString* file_path = furi_string_alloc(); bool res = false; @@ -446,8 +279,7 @@ bool subghz_save_protocol_to_file( Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); bool saved = false; - FuriString* file_dir; - file_dir = furi_string_alloc(); + FuriString* file_dir = furi_string_alloc(); path_extract_dirname(dev_file_name, file_dir); do { @@ -475,11 +307,21 @@ bool subghz_save_protocol_to_file( return saved; } +void subghz_save_to_file(void* context) { + furi_assert(context); + SubGhz* subghz = context; + if(subghz_path_is_file(subghz->file_path)) { + subghz_save_protocol_to_file( + subghz, + subghz_txrx_get_fff_data(subghz->txrx), + furi_string_get_cstr(subghz->file_path)); + } +} + bool subghz_load_protocol_from_file(SubGhz* subghz) { furi_assert(subghz); - FuriString* file_path; - file_path = furi_string_alloc(); + FuriString* file_path = furi_string_alloc(); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); @@ -559,113 +401,27 @@ bool subghz_path_is_file(FuriString* path) { return furi_string_end_with(path, SUBGHZ_APP_EXTENSION); } -uint32_t subghz_random_serial(void) { - return (uint32_t)rand(); -} - -void subghz_hopper_update(SubGhz* subghz) { +void subghz_lock(SubGhz* subghz) { furi_assert(subghz); - - switch(subghz->txrx->hopper_state) { - case SubGhzHopperStateOFF: - case SubGhzHopperStatePause: - return; - case SubGhzHopperStateRSSITimeOut: - if(subghz->txrx->hopper_timeout != 0) { - subghz->txrx->hopper_timeout--; - return; - } - break; - default: - break; - } - float rssi = -127.0f; - if(subghz->txrx->hopper_state != SubGhzHopperStateRSSITimeOut) { - // See RSSI Calculation timings in CC1101 17.3 RSSI - rssi = furi_hal_subghz_get_rssi(); - - // Stay if RSSI is high enough - if(rssi > -90.0f) { - subghz->txrx->hopper_timeout = 10; - subghz->txrx->hopper_state = SubGhzHopperStateRSSITimeOut; - return; - } - } else { - subghz->txrx->hopper_state = SubGhzHopperStateRunning; - } - // Select next frequency - if(subghz->txrx->hopper_idx_frequency < - subghz_setting_get_hopper_frequency_count(subghz->setting) - 1) { - subghz->txrx->hopper_idx_frequency++; - } else { - subghz->txrx->hopper_idx_frequency = 0; - } - - if(subghz->txrx->txrx_state == SubGhzTxRxStateRx) { - subghz_rx_end(subghz); - }; - if(subghz->txrx->txrx_state == SubGhzTxRxStateIDLE) { - subghz_receiver_reset(subghz->txrx->receiver); - subghz->txrx->preset->frequency = subghz_setting_get_hopper_frequency( - subghz->setting, subghz->txrx->hopper_idx_frequency); - subghz_rx(subghz, subghz->txrx->preset->frequency); - } + subghz->lock = SubGhzLockOn; } -void subghz_speaker_on(SubGhz* subghz) { - if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); - } - - if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_acquire(30)) { - if(!subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); - } - } else { - subghz->txrx->speaker_state = SubGhzSpeakerStateDisable; - } - } +void subghz_unlock(SubGhz* subghz) { + furi_assert(subghz); + subghz->lock = SubGhzLockOff; } -void subghz_speaker_off(SubGhz* subghz) { - if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); - } - if(subghz->txrx->speaker_state != SubGhzSpeakerStateDisable) { - if(furi_hal_speaker_is_mine()) { - if(!subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); - } - furi_hal_speaker_release(); - if(subghz->txrx->speaker_state == SubGhzSpeakerStateShutdown) - subghz->txrx->speaker_state = SubGhzSpeakerStateDisable; - } - } +bool subghz_is_locked(SubGhz* subghz) { + furi_assert(subghz); + return (subghz->lock == SubGhzLockOn); } -void subghz_speaker_mute(SubGhz* subghz) { - if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); - } - if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_is_mine()) { - if(!subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(NULL); - } - } - } +void subghz_rx_key_state_set(SubGhz* subghz, SubGhzRxKeyState state) { + furi_assert(subghz); + subghz->rx_key_state = state; } -void subghz_speaker_unmute(SubGhz* subghz) { - if(subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); - } - if(subghz->txrx->speaker_state == SubGhzSpeakerStateEnable) { - if(furi_hal_speaker_is_mine()) { - if(!subghz->txrx->debug_pin_state) { - furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); - } - } - } +SubGhzRxKeyState subghz_rx_key_state_get(SubGhz* subghz) { + furi_assert(subghz); + return subghz->rx_key_state; } diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index faae35fa2..f1b063457 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -41,6 +41,10 @@ #include "rpc/rpc_app.h" +#include "helpers/subghz_threshold_rssi.h" + +#include "helpers/subghz_txrx.h" + #define SUBGHZ_MAX_LEN_NAME 64 #define SUBGHZ_EXT_PRESET_NAME true @@ -56,38 +60,6 @@ typedef enum { SubGhzDecodeRawStateLoaded, } SubGhzDecodeRawState; -struct SubGhzTxRx { - SubGhzWorker* worker; - - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzTransmitter* transmitter; - SubGhzProtocolFlag filter; - SubGhzProtocolDecoderBase* decoder_result; - FlipperFormat* fff_data; - SecureData* secure_data; - - SubGhzRadioPreset* preset; - SubGhzHistory* history; - uint16_t idx_menu_chosen; - SubGhzTxRxState txrx_state; - SubGhzHopperState hopper_state; - SubGhzSpeakerState speaker_state; - bool ignore_starline; - bool ignore_auto_alarms; - bool ignore_magellan; - uint8_t hopper_timeout; - uint8_t hopper_idx_frequency; - SubGhzRxKeyState rx_key_state; - - bool debug_pin_state; - - float raw_threshold_rssi; - uint8_t raw_threshold_rssi_low_count; -}; - -typedef struct SubGhzTxRx SubGhzTxRx; - struct SubGhz { Gui* gui; NotificationApp* notifications; @@ -120,57 +92,65 @@ struct SubGhz { SubGhzTestStatic* subghz_test_static; SubGhzTestPacket* subghz_test_packet; #endif - FuriString* error_str; - SubGhzSetting* setting; SubGhzLastSettings* last_settings; + + SubGhzProtocolFlag filter; + FuriString* error_str; SubGhzLock lock; bool in_decoder_scene; bool in_decoder_scene_skip; + bool ignore_starline; + bool ignore_auto_alarms; + bool ignore_magellan; + + SecureData* secure_data; + SubGhzDecodeRawState decode_raw_state; SubGhzFileEncoderWorker* decode_raw_file_worker_encoder; + SubGhzThresholdRssi* threshold_rssi; + SubGhzRxKeyState rx_key_state; + SubGhzHistory* history; + + uint16_t idx_menu_chosen; + SubGhzLoadTypeFile load_type_file; + + bool fav_timeout; + FuriTimer* fav_timer; + void* rpc_ctx; }; -void subghz_preset_init( - void* context, - const char* preset_name, - uint32_t frequency, - uint8_t* preset_data, - size_t preset_data_size); -bool subghz_set_preset(SubGhz* subghz, const char* preset); -void subghz_get_frequency_modulation(SubGhz* subghz, FuriString* frequency, FuriString* modulation); -void subghz_begin(SubGhz* subghz, uint8_t* preset_data); -uint32_t subghz_rx(SubGhz* subghz, uint32_t frequency); -void subghz_rx_end(SubGhz* subghz); -void subghz_sleep(SubGhz* subghz); - -void subghz_blink_start(SubGhz* instance); -void subghz_blink_stop(SubGhz* instance); +void subghz_set_default_preset(SubGhz* subghz); +void subghz_blink_start(SubGhz* subghz); +void subghz_blink_stop(SubGhz* subghz); bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format); -void subghz_tx_stop(SubGhz* subghz); void subghz_dialog_message_show_only_rx(SubGhz* subghz); + bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog); bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len); bool subghz_save_protocol_to_file( SubGhz* subghz, FlipperFormat* flipper_format, const char* dev_file_name); +void subghz_save_to_file(void* context); bool subghz_load_protocol_from_file(SubGhz* subghz); bool subghz_rename_file(SubGhz* subghz); bool subghz_file_available(SubGhz* subghz); bool subghz_delete_file(SubGhz* subghz); void subghz_file_name_clear(SubGhz* subghz); bool subghz_path_is_file(FuriString* path); -uint32_t subghz_random_serial(void); -void subghz_hopper_update(SubGhz* subghz); -void subghz_speaker_on(SubGhz* subghz); -void subghz_speaker_off(SubGhz* subghz); -void subghz_speaker_mute(SubGhz* subghz); -void subghz_speaker_unmute(SubGhz* subghz); +SubGhzLoadTypeFile subghz_get_load_type_file(SubGhz* subghz); + +void subghz_lock(SubGhz* subghz); +void subghz_unlock(SubGhz* subghz); +bool subghz_is_locked(SubGhz* subghz); + +void subghz_rx_key_state_set(SubGhz* subghz, SubGhzRxKeyState state); +SubGhzRxKeyState subghz_rx_key_state_get(SubGhz* subghz); extern const NotificationSequence subghz_sequence_rx; extern const NotificationSequence subghz_sequence_rx_locked; diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 0d38503da..20afe8c12 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -51,7 +51,7 @@ typedef enum { } SubGhzViewReceiverBarShow; struct SubGhzViewReceiver { - SubGhzLock lock; + bool lock; uint8_t lock_count; FuriTimer* timer; View* view; @@ -97,10 +97,10 @@ void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { true); } -void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock lock) { +void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, bool lock) { furi_assert(subghz_receiver); subghz_receiver->lock_count = 0; - if(lock == SubGhzLockOn) { + if(lock == true) { subghz_receiver->lock = lock; with_view_model( subghz_receiver->view, @@ -241,8 +241,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { } bool scrollbar = model->history_item > 4; - FuriString* str_buff; - str_buff = furi_string_alloc(); + FuriString* str_buff = furi_string_alloc(); SubGhzReceiverMenuItem* item_menu; @@ -400,7 +399,7 @@ static void subghz_view_receiver_timer_callback(void* context) { subghz_receiver->callback( SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context); } else { - subghz_receiver->lock = SubGhzLockOff; + subghz_receiver->lock = false; subghz_receiver->callback(SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context); } subghz_receiver->lock_count = 0; @@ -410,7 +409,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { furi_assert(context); SubGhzViewReceiver* subghz_receiver = context; - if(subghz_receiver->lock == SubGhzLockOn) { + if(subghz_receiver->lock == true) { with_view_model( subghz_receiver->view, SubGhzViewReceiverModel * model, @@ -430,7 +429,7 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { SubGhzViewReceiverModel * model, { model->bar_show = SubGhzViewReceiverBarShowUnlock; }, true); - //subghz_receiver->lock = SubGhzLockOff; + //subghz_receiver->lock = false; furi_timer_start(subghz_receiver->timer, pdMS_TO_TICKS(650)); } @@ -555,7 +554,7 @@ SubGhzViewReceiver* subghz_view_receiver_alloc() { // View allocation and configuration subghz_receiver->view = view_alloc(); - subghz_receiver->lock = SubGhzLockOff; + subghz_receiver->lock = false; subghz_receiver->lock_count = 0; view_allocate_model( subghz_receiver->view, ViewModelTypeLocking, sizeof(SubGhzViewReceiverModel)); diff --git a/applications/main/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h index f5ec86b4b..54c1b3e7d 100644 --- a/applications/main/subghz/views/receiver.h +++ b/applications/main/subghz/views/receiver.h @@ -14,7 +14,7 @@ void subghz_view_receiver_set_mode( void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi); -void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, SubGhzLock keyboard); +void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, bool keyboard); void subghz_view_receiver_set_callback( SubGhzViewReceiver* subghz_receiver, diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index fcc077efa..7676c527d 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -11,28 +11,6 @@ #define SUBGHZ_READ_RAW_RSSI_HISTORY_SIZE 100 #define TAG "SubGhzReadRAW" -struct SubGhzReadRAW { - View* view; - SubGhzReadRAWCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* sample_write; - FuriString* file_name; - uint8_t* rssi_history; - uint8_t rssi_current; - bool rssi_history_end; - uint8_t ind_write; - uint8_t ind_sin; - SubGhzReadRAWStatus status; - bool raw_send_only; - float raw_threshold_rssi; - bool not_showing_samples; -} SubGhzReadRAWModel; - void subghz_read_raw_set_callback( SubGhzReadRAW* subghz_read_raw, SubGhzReadRAWCallback callback, diff --git a/applications/main/subghz/views/subghz_read_raw.h b/applications/main/subghz/views/subghz_read_raw.h index 9d63870d5..f9a56ca04 100644 --- a/applications/main/subghz/views/subghz_read_raw.h +++ b/applications/main/subghz/views/subghz_read_raw.h @@ -5,10 +5,14 @@ #define SUBGHZ_RAW_THRESHOLD_MIN -90.0f -typedef struct SubGhzReadRAW SubGhzReadRAW; - typedef void (*SubGhzReadRAWCallback)(SubGhzCustomEvent event, void* context); +typedef struct { + View* view; + SubGhzReadRAWCallback callback; + void* context; +} SubGhzReadRAW; + typedef enum { SubGhzReadRAWStatusStart, SubGhzReadRAWStatusIDLE, @@ -22,6 +26,22 @@ typedef enum { SubGhzReadRAWStatusSaveKey, } SubGhzReadRAWStatus; +typedef struct { + FuriString* frequency_str; + FuriString* preset_str; + FuriString* sample_write; + FuriString* file_name; + uint8_t* rssi_history; + uint8_t rssi_current; + bool rssi_history_end; + uint8_t ind_write; + uint8_t ind_sin; + SubGhzReadRAWStatus status; + bool raw_send_only; + float raw_threshold_rssi; + bool not_showing_samples; +} SubGhzReadRAWModel; + void subghz_read_raw_set_callback( SubGhzReadRAW* subghz_read_raw, SubGhzReadRAWCallback callback, diff --git a/applications/main/subghz/views/transmitter.c b/applications/main/subghz/views/transmitter.c index 2bec77690..48184cf39 100644 --- a/applications/main/subghz/views/transmitter.c +++ b/applications/main/subghz/views/transmitter.c @@ -6,21 +6,6 @@ #include -struct SubGhzViewTransmitter { - View* view; - SubGhzViewTransmitterCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* key_str; - uint8_t show_button; - FuriString* temp_button_id; - bool draw_temp_button; -} SubGhzViewTransmitterModel; - void subghz_view_transmitter_set_callback( SubGhzViewTransmitter* subghz_transmitter, SubGhzViewTransmitterCallback callback, @@ -36,7 +21,7 @@ void subghz_view_transmitter_add_data_to_show( const char* key_str, const char* frequency_str, const char* preset_str, - uint8_t show_button) { + bool show_button) { furi_assert(subghz_transmitter); with_view_model( subghz_transmitter->view, @@ -119,7 +104,7 @@ bool subghz_view_transmitter_input(InputEvent* event, void* context) { furi_string_reset(model->preset_str); furi_string_reset(model->key_str); furi_string_reset(model->temp_button_id); - model->show_button = 0; + model->show_button = false; model->draw_temp_button = false; }, false); diff --git a/applications/main/subghz/views/transmitter.h b/applications/main/subghz/views/transmitter.h index 64bcbd1af..e121c8746 100644 --- a/applications/main/subghz/views/transmitter.h +++ b/applications/main/subghz/views/transmitter.h @@ -3,10 +3,23 @@ #include #include "../helpers/subghz_custom_event.h" -typedef struct SubGhzViewTransmitter SubGhzViewTransmitter; +typedef struct { + FuriString* frequency_str; + FuriString* preset_str; + FuriString* key_str; + bool show_button; + FuriString* temp_button_id; + bool draw_temp_button; +} SubGhzViewTransmitterModel; typedef void (*SubGhzViewTransmitterCallback)(SubGhzCustomEvent event, void* context); +typedef struct { + View* view; + SubGhzViewTransmitterCallback callback; + void* context; +} SubGhzViewTransmitter; + void subghz_view_transmitter_set_callback( SubGhzViewTransmitter* subghz_transmitter, SubGhzViewTransmitterCallback callback, @@ -23,4 +36,4 @@ void subghz_view_transmitter_add_data_to_show( const char* key_str, const char* frequency_str, const char* preset_str, - uint8_t show_button); + bool show_button); diff --git a/applications/main/u2f/u2f_app.c b/applications/main/u2f/u2f_app.c index 60500152a..db94a398c 100644 --- a/applications/main/u2f/u2f_app.c +++ b/applications/main/u2f/u2f_app.c @@ -28,11 +28,6 @@ U2fApp* u2f_app_alloc() { app->gui = furi_record_open(RECORD_GUI); app->notifications = furi_record_open(RECORD_NOTIFICATION); - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, U2F_CNT_OLD_FILE, U2F_CNT_FILE); - storage_common_copy(storage, U2F_KEY_OLD_FILE, U2F_KEY_FILE); - furi_record_close(RECORD_STORAGE); - app->view_dispatcher = view_dispatcher_alloc(); app->scene_manager = scene_manager_alloc(&u2f_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); diff --git a/applications/main/u2f/u2f_data.h b/applications/main/u2f/u2f_data.h index f3c62f89d..5c887ba1d 100644 --- a/applications/main/u2f/u2f_data.h +++ b/applications/main/u2f/u2f_data.h @@ -9,10 +9,10 @@ extern "C" { #define U2F_DATA_FOLDER EXT_PATH("u2f/") #define U2F_CERT_FILE U2F_DATA_FOLDER "assets/cert.der" #define U2F_CERT_KEY_FILE U2F_DATA_FOLDER "assets/cert_key.u2f" +#define U2F_CNT_OLD_FILE INT_PATH(".cnt.u2f") #define U2F_KEY_OLD_FILE U2F_DATA_FOLDER "key.u2f" -#define U2F_CNT_OLD_FILE U2F_DATA_FOLDER "cnt.u2f" +#define U2F_CNT_FILE U2F_DATA_FOLDER "cnt.u2f" #define U2F_KEY_FILE INT_PATH(".key.u2f") -#define U2F_CNT_FILE INT_PATH(".cnt.u2f") bool u2f_data_check(bool cert_only); diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_common.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_common.c index 259d8a260..54b0241d9 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_common.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_interface_common.c @@ -37,6 +37,16 @@ static void xtreme_app_scene_interface_common_left_handed_changed(VariableItem* } } +static void xtreme_app_scene_interface_common_favorite_timeout_changed(VariableItem* item) { + XtremeApp* app = variable_item_get_context(item); + uint32_t value = variable_item_get_current_value_index(item); + char text[6]; + snprintf(text, sizeof(text), "%lu S", value); + variable_item_set_current_value_text(item, value ? text : "OFF"); + XTREME_SETTINGS()->favorite_timeout = value; + app->save_settings = true; +} + void xtreme_app_scene_interface_common_on_enter(void* context) { XtremeApp* app = context; XtremeSettings* xtreme_settings = XTREME_SETTINGS(); @@ -67,6 +77,17 @@ void xtreme_app_scene_interface_common_on_enter(void* context) { variable_item_set_current_value_index(item, value); variable_item_set_current_value_text(item, value ? "ON" : "OFF"); + item = variable_item_list_add( + var_item_list, + "Favorite Timeout", + 61, + xtreme_app_scene_interface_common_favorite_timeout_changed, + app); + variable_item_set_current_value_index(item, xtreme_settings->favorite_timeout); + char text[4]; + snprintf(text, sizeof(text), "%lu S", xtreme_settings->favorite_timeout); + variable_item_set_current_value_text(item, xtreme_settings->favorite_timeout ? text : "OFF"); + variable_item_list_set_enter_callback( var_item_list, xtreme_app_scene_interface_common_var_item_list_callback, app); diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_rename.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_rename.c index 47a0fb607..dd01a60ca 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_rename.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_misc_rename.c @@ -42,7 +42,7 @@ void xtreme_app_scene_misc_rename_on_enter(void* context) { xtreme_app_scene_misc_rename_text_input_callback, app, app->device_name, - NAMECHANGER_TEXT_STORE_SIZE, + FURI_HAL_VERSION_ARRAY_NAME_LENGTH, true); view_dispatcher_switch_to_view(app->view_dispatcher, XtremeAppViewTextInput); diff --git a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols.c b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols.c index d8244d30d..28b97618e 100644 --- a/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols.c +++ b/applications/main/xtreme_app/scenes/xtreme_app_scene_protocols.c @@ -5,7 +5,6 @@ enum VarItemListIndex { VarItemListIndexBadbtRemember, VarItemListIndexSubghzFrequencies, VarItemListIndexSubghzExtend, - VarItemListIndexSubghzBypass, }; void xtreme_app_scene_protocols_var_item_list_callback(void* context, uint32_t index) { @@ -36,13 +35,6 @@ static void xtreme_app_scene_protocols_subghz_extend_changed(VariableItem* item) app->save_subghz = true; } -static void xtreme_app_scene_protocols_subghz_bypass_changed(VariableItem* item) { - XtremeApp* app = variable_item_get_context(item); - app->subghz_bypass = variable_item_get_current_value_index(item); - variable_item_set_current_value_text(item, app->subghz_bypass ? "ON" : "OFF"); - app->save_subghz = true; -} - void xtreme_app_scene_protocols_on_enter(void* context) { XtremeApp* app = context; XtremeSettings* xtreme_settings = XTREME_SETTINGS(); @@ -66,11 +58,6 @@ void xtreme_app_scene_protocols_on_enter(void* context) { variable_item_set_current_value_index(item, app->subghz_extend); variable_item_set_current_value_text(item, app->subghz_extend ? "ON" : "OFF"); - item = variable_item_list_add( - var_item_list, "SubGHz Bypass", 2, xtreme_app_scene_protocols_subghz_bypass_changed, app); - variable_item_set_current_value_index(item, app->subghz_bypass); - variable_item_set_current_value_text(item, app->subghz_bypass ? "ON" : "OFF"); - variable_item_list_set_enter_callback( var_item_list, xtreme_app_scene_protocols_var_item_list_callback, app); diff --git a/applications/main/xtreme_app/xtreme_app.c b/applications/main/xtreme_app/xtreme_app.c index 57706233e..623bbcdc9 100644 --- a/applications/main/xtreme_app/xtreme_app.c +++ b/applications/main/xtreme_app/xtreme_app.c @@ -64,33 +64,20 @@ bool xtreme_app_apply(XtremeApp* app) { } if(app->save_subghz) { - furi_hal_subghz_set_extend_settings(app->subghz_extend, app->subghz_bypass); + furi_hal_subghz_set_is_extended(app->subghz_extend); } if(app->save_name) { if(strcmp(app->device_name, "") == 0) { - storage_simply_remove(storage, NAMECHANGER_PATH); + storage_simply_remove(storage, NAMESPOOF_PATH); } else { FlipperFormat* file = flipper_format_file_alloc(storage); do { - if(!flipper_format_file_open_always(file, NAMECHANGER_PATH)) break; - - if(!flipper_format_write_header_cstr(file, NAMECHANGER_HEADER, 1)) break; - - if(!flipper_format_write_comment_cstr( - file, "Changing the value below will change your FlipperZero device name.")) + if(!flipper_format_file_open_always(file, NAMESPOOF_PATH)) break; + if(!flipper_format_write_header_cstr(file, NAMESPOOF_HEADER, NAMESPOOF_VERSION)) break; - if(!flipper_format_write_comment_cstr( - file, - "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) - break; - if(!flipper_format_write_comment_cstr( - file, "It cannot contain any other characters.")) - break; - if(!flipper_format_write_string_cstr(file, "Name", app->device_name)) break; - } while(0); flipper_format_free(file); @@ -260,9 +247,9 @@ XtremeApp* xtreme_app_alloc() { flipper_format_free(file); furi_record_close(RECORD_STORAGE); - furi_hal_subghz_get_extend_settings(&app->subghz_extend, &app->subghz_bypass); + app->subghz_extend = furi_hal_subghz_get_is_extended(); - strlcpy(app->device_name, furi_hal_version_get_name_ptr(), NAMECHANGER_TEXT_STORE_SIZE); + strlcpy(app->device_name, furi_hal_version_get_name_ptr(), FURI_HAL_VERSION_ARRAY_NAME_LENGTH); Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); diff --git a/applications/main/xtreme_app/xtreme_app.h b/applications/main/xtreme_app/xtreme_app.h index 15cd71ce9..dedb9630c 100644 --- a/applications/main/xtreme_app/xtreme_app.h +++ b/applications/main/xtreme_app/xtreme_app.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "scenes/xtreme_app_scene.h" #include "dolphin/helpers/dolphin_state.h" #include "dolphin/dolphin.h" @@ -21,8 +20,9 @@ #include #include #include -#include +#include #include +#include #include #define XTREME_SUBGHZ_FREQ_BUFFER_SIZE 6 @@ -51,8 +51,7 @@ typedef struct { uint8_t subghz_hopper_index; char subghz_freq_buffer[XTREME_SUBGHZ_FREQ_BUFFER_SIZE]; bool subghz_extend; - bool subghz_bypass; - char device_name[NAMECHANGER_TEXT_STORE_SIZE]; + char device_name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH]; int32_t xp_level; FuriString* version_tag; diff --git a/applications/services/application.fam b/applications/services/application.fam index af02ef1a1..aec49b231 100644 --- a/applications/services/application.fam +++ b/applications/services/application.fam @@ -9,7 +9,5 @@ App( "desktop", "loader", "power", - "rgb_backlight", - "namechangersrv", ], ) diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index b4a6b25a4..1781d03d7 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -126,10 +126,6 @@ Bt* bt_alloc() { bt_settings_save(&bt->bt_settings); } // Keys storage - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, BT_KEYS_STORAGE_OLD_PATH, BT_KEYS_STORAGE_PATH); - storage_common_remove(storage, BT_KEYS_STORAGE_OLD_PATH); - furi_record_close(RECORD_STORAGE); bt->keys_storage = bt_keys_storage_alloc(BT_KEYS_STORAGE_PATH); // Alloc queue bt->message_queue = furi_message_queue_alloc(8, sizeof(BtMessage)); diff --git a/applications/services/bt/bt_settings.c b/applications/services/bt/bt_settings.c index 92e6c7d5d..6a6c5f562 100644 --- a/applications/services/bt/bt_settings.c +++ b/applications/services/bt/bt_settings.c @@ -4,31 +4,14 @@ #include #include -#define BT_SETTINGS_OLD_PATH INT_PATH(".bt.settings") -#define BT_SETTINGS_PATH CFG_PATH("bt.settings") #define BT_SETTINGS_VERSION (0) #define BT_SETTINGS_MAGIC (0x19) bool bt_settings_load(BtSettings* bt_settings) { furi_assert(bt_settings); - bool ret = saved_struct_load( + return saved_struct_load( BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION); - - if(!ret) { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, BT_SETTINGS_OLD_PATH, BT_SETTINGS_PATH); - storage_common_remove(storage, BT_SETTINGS_OLD_PATH); - furi_record_close(RECORD_STORAGE); - ret = saved_struct_load( - BT_SETTINGS_PATH, - bt_settings, - sizeof(BtSettings), - BT_SETTINGS_MAGIC, - BT_SETTINGS_VERSION); - } - - return ret; } bool bt_settings_save(BtSettings* bt_settings) { diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h index 620a3f5a6..cd6be60c4 100644 --- a/applications/services/bt/bt_settings.h +++ b/applications/services/bt/bt_settings.h @@ -7,6 +7,9 @@ extern "C" { #endif +#define BT_SETTINGS_OLD_PATH INT_PATH(".bt.settings") +#define BT_SETTINGS_PATH CFG_PATH("bt.settings") + typedef struct { bool enabled; } BtSettings; diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index a8d1b7e67..fc71aa31f 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -79,7 +79,7 @@ void cli_command_help(Cli* cli, FuriString* args, void* context) { printf("%s", furi_string_get_cstr(*CliCommandTree_ref(it_right)->key_ptr)); CliCommandTree_next(it_right); } - }; + } if(furi_string_size(args) > 0) { cli_nl(); @@ -230,11 +230,9 @@ void cli_command_sysctl_debug(Cli* cli, FuriString* args, void* context) { UNUSED(context); if(!furi_string_cmp(args, "0")) { furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); - loader_update_menu(); printf("Debug disabled."); } else if(!furi_string_cmp(args, "1")) { furi_hal_rtc_set_flag(FuriHalRtcFlagDebug); - loader_update_menu(); printf("Debug enabled."); } else { cli_print_usage("sysctl debug", "<1|0>", furi_string_get_cstr(args)); diff --git a/applications/services/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c index d91b448ec..34aa34dd3 100644 --- a/applications/services/crypto/crypto_cli.c +++ b/applications/services/crypto/crypto_cli.c @@ -15,7 +15,7 @@ void crypto_cli_print_usage() { printf("\thas_key \t - Check if secure enclave has key in slot\r\n"); printf( "\tstore_key \t - Store key in secure enclave. !!! NON-REVERSIBLE OPERATION - READ MANUAL FIRST !!!\r\n"); -}; +} void crypto_cli_encrypt(Cli* cli, FuriString* args) { int key_slot = 0; diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 394ffee30..77884f2c1 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -217,25 +217,25 @@ static bool animation_manager_check_blocking(AnimationManager* animation_manager FS_Error sd_status = storage_sd_status(storage); if(sd_status == FSE_INTERNAL) { - blocking_animation = animation_storage_find_animation(BAD_SD_ANIMATION_NAME, false); + blocking_animation = animation_storage_find_animation(BAD_SD_ANIMATION_NAME); furi_assert(blocking_animation); } else if(sd_status == FSE_NOT_READY) { animation_manager->sd_shown_sd_ok = false; animation_manager->sd_shown_no_db = false; } else if(sd_status == FSE_OK) { if(!animation_manager->sd_shown_sd_ok) { - blocking_animation = animation_storage_find_animation(SD_OK_ANIMATION_NAME, false); + blocking_animation = animation_storage_find_animation(SD_OK_ANIMATION_NAME); furi_assert(blocking_animation); animation_manager->sd_shown_sd_ok = true; } else if(!animation_manager->sd_shown_no_db) { if(!storage_file_exists(storage, EXT_PATH("Manifest"))) { - blocking_animation = animation_storage_find_animation(NO_DB_ANIMATION_NAME, false); + blocking_animation = animation_storage_find_animation(NO_DB_ANIMATION_NAME); furi_assert(blocking_animation); animation_manager->sd_shown_no_db = true; animation_manager->sd_show_url = true; } } else if(animation_manager->sd_show_url) { - blocking_animation = animation_storage_find_animation(URL_ANIMATION_NAME, false); + blocking_animation = animation_storage_find_animation(URL_ANIMATION_NAME); furi_assert(blocking_animation); animation_manager->sd_show_url = false; } @@ -245,7 +245,7 @@ static bool animation_manager_check_blocking(AnimationManager* animation_manager DolphinStats stats = dolphin_stats(dolphin); furi_record_close(RECORD_DOLPHIN); if(!blocking_animation && stats.level_up_is_pending) { - blocking_animation = animation_storage_find_animation(NEW_MAIL_ANIMATION_NAME, false); + blocking_animation = animation_storage_find_animation(NEW_MAIL_ANIMATION_NAME); furi_check(blocking_animation); animation_manager->levelup_pending = true; } @@ -446,22 +446,12 @@ static StorageAnimation* /* cache animation, if failed - choose reliable animation */ if(selected == NULL) { FURI_LOG_E(TAG, "Can't find valid animation in manifest"); - selected = animation_storage_find_animation(HARDCODED_ANIMATION_NAME, false); + selected = animation_storage_find_animation(HARDCODED_ANIMATION_NAME); } else if(!animation_storage_get_bubble_animation(selected)) { const char* name = animation_storage_get_meta(selected)->name; FURI_LOG_E(TAG, "Can't upload animation described in manifest: \'%s\'", name); animation_storage_free_storage_animation(&selected); - selected = animation_storage_find_animation(HARDCODED_ANIMATION_NAME, false); - } else { - FuriHalRtcDateTime date; - furi_hal_rtc_get_datetime(&date); - if(date.month == 4 && date.day == 1 && furi_hal_random_get() % 2) { - animation_storage_free_storage_animation(&selected); - selected = animation_storage_find_animation("L3_Sunflower_128x64", true); - if(selected == NULL) { - selected = animation_storage_find_animation(HARDCODED_ANIMATION_NAME, false); - } - } + selected = animation_storage_find_animation(HARDCODED_ANIMATION_NAME); } furi_assert(selected); @@ -520,7 +510,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m if(animation_manager->state == AnimationManagerStateFreezedBlocked) { StorageAnimation* restore_animation = animation_storage_find_animation( - furi_string_get_cstr(animation_manager->freezed_animation_name), false); + furi_string_get_cstr(animation_manager->freezed_animation_name)); /* all blocked animations must be in flipper -> we can * always find blocking animation */ furi_assert(restore_animation); @@ -532,7 +522,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m if(!blocked) { /* if no blocking - try restore last one idle */ StorageAnimation* restore_animation = animation_storage_find_animation( - furi_string_get_cstr(animation_manager->freezed_animation_name), false); + furi_string_get_cstr(animation_manager->freezed_animation_name)); if(restore_animation) { Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); DolphinStats stats = dolphin_stats(dolphin); diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index 0905a6d43..b412d175b 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -30,11 +30,11 @@ static void animation_storage_free_frames(BubbleAnimation* animation); static void animation_storage_free_animation(BubbleAnimation** storage_animation); static BubbleAnimation* animation_storage_load_animation(const char* name); -void animation_handler_select_manifest(bool force_stock) { +void animation_handler_select_manifest() { XtremeSettings* xtreme_settings = XTREME_SETTINGS(); FuriString* anim_dir = furi_string_alloc(); FuriString* manifest = furi_string_alloc(); - bool use_asset_pack = !force_stock && xtreme_settings->asset_pack[0] != '\0'; + bool use_asset_pack = xtreme_settings->asset_pack[0] != '\0'; if(use_asset_pack) { furi_string_printf( anim_dir, "%s/%s/Anims", XTREME_ASSETS_PATH, xtreme_settings->asset_pack); @@ -61,10 +61,9 @@ void animation_handler_select_manifest(bool force_stock) { static bool animation_storage_load_single_manifest_info( StorageAnimationManifestInfo* manifest_info, - const char* name, - bool force_stock) { + const char* name) { furi_assert(manifest_info); - animation_handler_select_manifest(force_stock); + animation_handler_select_manifest(); bool result = false; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -120,7 +119,7 @@ static bool animation_storage_load_single_manifest_info( void animation_storage_fill_animation_list(StorageAnimationList_t* animation_list) { furi_assert(sizeof(StorageAnimationList_t) == sizeof(void*)); furi_assert(!StorageAnimationList_size(*animation_list)); - animation_handler_select_manifest(false); + animation_handler_select_manifest(); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -176,7 +175,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis furi_record_close(RECORD_STORAGE); } -StorageAnimation* animation_storage_find_animation(const char* name, bool force_stock) { +StorageAnimation* animation_storage_find_animation(const char* name) { furi_assert(name); furi_assert(strlen(name)); StorageAnimation* storage_animation = NULL; @@ -203,8 +202,8 @@ StorageAnimation* animation_storage_find_animation(const char* name, bool force_ storage_animation->external = true; bool result = false; - result = animation_storage_load_single_manifest_info( - &storage_animation->manifest_info, name, force_stock); + result = + animation_storage_load_single_manifest_info(&storage_animation->manifest_info, name); if(result) { storage_animation->animation = animation_storage_load_animation(name); result = !!storage_animation->animation; diff --git a/applications/services/desktop/animations/animation_storage.h b/applications/services/desktop/animations/animation_storage.h index 55512e008..16c0feab4 100644 --- a/applications/services/desktop/animations/animation_storage.h +++ b/applications/services/desktop/animations/animation_storage.h @@ -61,7 +61,7 @@ void animation_storage_cache_animation(StorageAnimation* storage_animation); * @name name of animation * @return found animation. NULL if nothing found. */ -StorageAnimation* animation_storage_find_animation(const char* name, bool force_stock); +StorageAnimation* animation_storage_find_animation(const char* name); /** * Get meta information of storage animation. diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 45435411a..c28566dca 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "animations/animation_manager.h" #include "desktop/scenes/desktop_scene.h" @@ -14,8 +16,7 @@ #include "desktop/views/desktop_view_pin_input.h" #include "desktop/views/desktop_view_pin_timeout.h" #include "desktop_i.h" -#include "helpers/pin_lock.h" -#include +#include "helpers/pin.h" #define TAG "Desktop" @@ -64,10 +65,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { return true; case DesktopGlobalAutoLock: if(!loader_is_locked(desktop->loader)) { - if(desktop->settings.auto_lock_with_pin && desktop->settings.pin_code.length > 0) { - desktop_pin_lock(&desktop->settings); - } - desktop_lock(desktop); + desktop_lock(desktop, desktop->settings.auto_lock_with_pin); } return true; } @@ -128,12 +126,22 @@ static void desktop_auto_lock_inhibit(Desktop* desktop) { } } -void desktop_lock(Desktop* desktop) { +void desktop_lock(Desktop* desktop, bool pin_lock) { + pin_lock = pin_lock && desktop->settings.pin_code.length > 0; + if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { + furi_hal_rtc_set_pin_fails(0); + } + if(pin_lock) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLock); + Cli* cli = furi_record_open(RECORD_CLI); + cli_session_close(cli); + furi_record_close(RECORD_CLI); + } + desktop_auto_lock_inhibit(desktop); scene_manager_set_scene_state( desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); - notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000); } void desktop_unlock(Desktop* desktop) { @@ -144,6 +152,13 @@ void desktop_unlock(Desktop* desktop) { desktop_view_locked_unlock(desktop->locked_view); scene_manager_search_and_switch_to_previous_scene(desktop->scene_manager, DesktopSceneMain); desktop_auto_lock_arm(desktop); + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { + furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); + Cli* cli = furi_record_open(RECORD_CLI); + cli_session_open(cli, &cli_vcp); + furi_record_close(RECORD_CLI); + } } void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled) { @@ -270,11 +285,14 @@ Desktop* desktop_alloc() { desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); + furi_record_create(RECORD_DESKTOP, desktop); + return desktop; } void desktop_free(Desktop* desktop) { furi_assert(desktop); + furi_check(furi_record_destroy(RECORD_DESKTOP)); furi_pubsub_unsubscribe( loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription); @@ -332,6 +350,16 @@ static bool desktop_check_file_flag(const char* flag_path) { return exists; } +bool desktop_api_is_locked(Desktop* instance) { + furi_assert(instance); + return furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); +} + +void desktop_api_unlock(Desktop* instance) { + furi_assert(instance); + view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked); +} + int32_t desktop_srv(void* p) { UNUSED(p); @@ -348,9 +376,6 @@ int32_t desktop_srv(void* p) { furi_hal_rtc_reset_flag(FuriHalRtcFlagResetPin); } - XTREME_SETTINGS_LOAD(); - XTREME_ASSETS_LOAD(); - Desktop* desktop = desktop_alloc(); bool loaded = DESKTOP_SETTINGS_LOAD(&desktop->settings); @@ -361,14 +386,12 @@ int32_t desktop_srv(void* p) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); - desktop_pin_lock_init(&desktop->settings); - - if(!desktop_pin_lock_is_locked()) { + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock)) { + desktop_lock(desktop, true); + } else { if(!loader_is_locked(desktop->loader)) { desktop_auto_lock_arm(desktop); } - } else { - desktop_lock(desktop); } if(desktop_check_file_flag(SLIDESHOW_FS_PATH)) { diff --git a/applications/services/desktop/desktop.h b/applications/services/desktop/desktop.h index f5608207d..5b12647b8 100644 --- a/applications/services/desktop/desktop.h +++ b/applications/services/desktop/desktop.h @@ -1,3 +1,9 @@ #pragma once typedef struct Desktop Desktop; + +#define RECORD_DESKTOP "desktop" + +bool desktop_api_is_locked(Desktop* instance); + +void desktop_api_unlock(Desktop* instance); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 988092f0e..a05e2062e 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -76,6 +76,6 @@ struct Desktop { Desktop* desktop_alloc(); void desktop_free(Desktop* desktop); -void desktop_lock(Desktop* desktop); +void desktop_lock(Desktop* desktop, bool pin_lock); void desktop_unlock(Desktop* desktop); void desktop_set_stealth_mode_state(Desktop* desktop, bool enabled); diff --git a/applications/services/desktop/desktop_settings.c b/applications/services/desktop/desktop_settings.c index 9c95e950f..d1df4a9a6 100644 --- a/applications/services/desktop/desktop_settings.c +++ b/applications/services/desktop/desktop_settings.c @@ -10,25 +10,10 @@ bool DESKTOP_SETTINGS_SAVE(DesktopSettings* x) { } bool DESKTOP_SETTINGS_LOAD(DesktopSettings* x) { - bool ret = saved_struct_load( + return saved_struct_load( DESKTOP_SETTINGS_PATH, x, sizeof(DesktopSettings), DESKTOP_SETTINGS_MAGIC, DESKTOP_SETTINGS_VER); - - if(!ret) { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, DESKTOP_SETTINGS_OLD_PATH, DESKTOP_SETTINGS_PATH); - storage_common_remove(storage, DESKTOP_SETTINGS_OLD_PATH); - furi_record_close(RECORD_STORAGE); - ret = saved_struct_load( - DESKTOP_SETTINGS_PATH, - x, - sizeof(DesktopSettings), - DESKTOP_SETTINGS_MAGIC, - DESKTOP_SETTINGS_VER); - } - - return ret; } diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 62d4e5aae..5896f0ed7 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -7,7 +7,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (7) +#define DESKTOP_SETTINGS_VER (8) #define DESKTOP_SETTINGS_OLD_PATH INT_PATH(".desktop.settings") #define DESKTOP_SETTINGS_PATH CFG_PATH("desktop.settings") @@ -34,7 +34,6 @@ typedef struct { FavoriteApp favorite_primary; FavoriteApp favorite_secondary; PinCode pin_code; - uint8_t is_locked; uint32_t auto_lock_delay_ms; bool auto_lock_with_pin; } DesktopSettings; diff --git a/applications/services/desktop/helpers/pin.c b/applications/services/desktop/helpers/pin.c new file mode 100644 index 000000000..d6ab48df2 --- /dev/null +++ b/applications/services/desktop/helpers/pin.c @@ -0,0 +1,55 @@ +#include "pin.h" + +#include +#include +#include +#include +#include +#include + +#include "../desktop_i.h" + +static const NotificationSequence sequence_pin_fail = { + &message_display_backlight_on, + + &message_red_255, + &message_vibro_on, + &message_delay_100, + &message_vibro_off, + &message_red_0, + + &message_delay_250, + + &message_red_255, + &message_vibro_on, + &message_delay_100, + &message_vibro_off, + &message_red_0, + NULL, +}; + +void desktop_pin_lock_error_notify() { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + notification_message(notification, &sequence_pin_fail); + furi_record_close(RECORD_NOTIFICATION); +} + +uint32_t desktop_pin_lock_get_fail_timeout() { + uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); + if(pin_fails < 3) { + return 0; + } + return 30 * pow(2, pin_fails - 3); +} + +bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2) { + furi_assert(pin_code1); + furi_assert(pin_code2); + bool result = false; + + if(pin_code1->length == pin_code2->length) { + result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length); + } + + return result; +} diff --git a/applications/services/desktop/helpers/pin.h b/applications/services/desktop/helpers/pin.h new file mode 100644 index 000000000..e5410723e --- /dev/null +++ b/applications/services/desktop/helpers/pin.h @@ -0,0 +1,11 @@ +#pragma once +#include +#include +#include "../desktop.h" +#include + +void desktop_pin_lock_error_notify(); + +uint32_t desktop_pin_lock_get_fail_timeout(); + +bool desktop_pin_compare(const PinCode* pin_code1, const PinCode* pin_code2); diff --git a/applications/services/desktop/helpers/pin_lock.c b/applications/services/desktop/helpers/pin_lock.c deleted file mode 100644 index 2439a4ebc..000000000 --- a/applications/services/desktop/helpers/pin_lock.c +++ /dev/null @@ -1,132 +0,0 @@ - -#include -#include -#include -#include -#include -#include - -#include "../helpers/pin_lock.h" -#include "../desktop_i.h" -#include -#include -#include - -static const NotificationSequence sequence_pin_fail = { - &message_display_backlight_on, - - &message_red_255, - &message_vibro_on, - &message_delay_100, - &message_vibro_off, - &message_red_0, - - &message_delay_250, - - &message_red_255, - &message_vibro_on, - &message_delay_100, - &message_vibro_off, - &message_red_0, - NULL, -}; - -void desktop_pin_lock_error_notify() { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - notification_message(notification, &sequence_pin_fail); - furi_record_close(RECORD_NOTIFICATION); -} - -uint32_t desktop_pin_lock_get_fail_timeout() { - uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); - if(pin_fails < 3) { - return 0; - } - return 30 * pow(2, pin_fails - 3); -} - -void desktop_pin_lock(DesktopSettings* settings) { - furi_assert(settings); - - furi_hal_rtc_set_pin_fails(0); - furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_close(cli); - furi_record_close(RECORD_CLI); - settings->is_locked = 1; - DESKTOP_SETTINGS_SAVE(settings); -} - -void desktop_pin_unlock(DesktopSettings* settings) { - furi_assert(settings); - - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_open(cli, &cli_vcp); - furi_record_close(RECORD_CLI); - settings->is_locked = 0; - DESKTOP_SETTINGS_SAVE(settings); -} - -void desktop_pin_lock_init(DesktopSettings* settings) { - furi_assert(settings); - - if(settings->pin_code.length > 0) { - if(settings->is_locked == 1) { - furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - } else { - if(desktop_pin_lock_is_locked()) { - settings->is_locked = 1; - DESKTOP_SETTINGS_SAVE(settings); - } - } - } else { - furi_hal_rtc_set_pin_fails(0); - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - } - - if(desktop_pin_lock_is_locked()) { - Cli* cli = furi_record_open(RECORD_CLI); - cli_session_close(cli); - furi_record_close(RECORD_CLI); - } -} - -bool desktop_pin_lock_verify(const PinCode* pin_set, const PinCode* pin_entered) { - bool result = false; - if(desktop_pins_are_equal(pin_set, pin_entered)) { - furi_hal_rtc_set_pin_fails(0); - result = true; - } else { - uint32_t pin_fails = furi_hal_rtc_get_pin_fails(); - if(pin_fails >= 9 && XTREME_SETTINGS()->bad_pins_format) { - furi_hal_rtc_set_pin_fails(0); - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_simply_remove(storage, INT_PATH(".cnt.u2f")); - storage_simply_remove(storage, INT_PATH(".key.u2f")); - storage_sd_format(storage); - furi_record_close(RECORD_STORAGE); - power_reboot(PowerBootModeNormal); - } - furi_hal_rtc_set_pin_fails(pin_fails + 1); - result = false; - } - return result; -} - -bool desktop_pin_lock_is_locked() { - return furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); -} - -bool desktop_pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2) { - furi_assert(pin_code1); - furi_assert(pin_code2); - bool result = false; - - if(pin_code1->length == pin_code2->length) { - result = !memcmp(pin_code1->data, pin_code2->data, pin_code1->length); - } - - return result; -} diff --git a/applications/services/desktop/helpers/pin_lock.h b/applications/services/desktop/helpers/pin_lock.h deleted file mode 100644 index 028ae6d22..000000000 --- a/applications/services/desktop/helpers/pin_lock.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include -#include -#include "../desktop.h" -#include - -void desktop_pin_lock_error_notify(); - -uint32_t desktop_pin_lock_get_fail_timeout(); - -void desktop_pin_lock(DesktopSettings* settings); - -void desktop_pin_unlock(DesktopSettings* settings); - -bool desktop_pin_lock_is_locked(); - -void desktop_pin_lock_init(DesktopSettings* settings); - -bool desktop_pin_lock_verify(const PinCode* pin_set, const PinCode* pin_entered); - -bool desktop_pins_are_equal(const PinCode* pin_code1, const PinCode* pin_code2); diff --git a/applications/services/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c index e68d28076..7ecda0ddf 100644 --- a/applications/services/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -12,7 +12,7 @@ #include "../views/desktop_view_lock_menu.h" #include "desktop_scene_i.h" #include "desktop_scene.h" -#include "../helpers/pin_lock.h" +#include "../helpers/pin.h" #include #define TAG "DesktopSceneLock" @@ -66,8 +66,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { if(desktop->settings.pin_code.length > 0) { desktop_lock_menu_set_pin_state(desktop->lock_menu, true); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); - desktop_pin_lock(&desktop->settings); - desktop_lock(desktop); + desktop_lock(desktop, true); if(check_pin_changed == 2) { Power* power = furi_record_open(RECORD_POWER); furi_delay_ms(500); @@ -80,20 +79,19 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case DesktopLockMenuEventSettings: desktop_scene_lock_menu_save_settings(desktop); - loader_show_settings(); + loader_show_settings(furi_record_open(RECORD_LOADER)); + furi_record_close(RECORD_LOADER); consumed = true; break; case DesktopLockMenuEventLock: desktop_scene_lock_menu_save_settings(desktop); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); - desktop_lock(desktop); + desktop_lock(desktop, false); consumed = true; break; case DesktopLockMenuEventLockPin: desktop_scene_lock_menu_save_settings(desktop); if(desktop->settings.pin_code.length > 0) { - desktop_pin_lock(&desktop->settings); - desktop_lock(desktop); + desktop_lock(desktop, true); } else { LoaderStatus status = loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); @@ -108,8 +106,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { case DesktopLockMenuEventLockPinOff: desktop_scene_lock_menu_save_settings(desktop); if(desktop->settings.pin_code.length > 0) { - desktop_pin_lock(&desktop->settings); - desktop_lock(desktop); + desktop_lock(desktop, true); Power* power = furi_record_open(RECORD_POWER); furi_delay_ms(500); power_off(power); diff --git a/applications/services/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c index eaa2b1e11..11dd7f222 100644 --- a/applications/services/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -7,7 +7,7 @@ #include "../desktop.h" #include "../desktop_i.h" -#include "../helpers/pin_lock.h" +#include "../helpers/pin.h" #include "../animations/animation_manager.h" #include "../views/desktop_events.h" #include "../views/desktop_view_pin_input.h" @@ -45,7 +45,7 @@ void desktop_scene_locked_on_enter(void* context) { bool switch_to_timeout_scene = false; uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked); if(state == SCENE_LOCKED_FIRST_ENTER) { - bool pin_locked = desktop_pin_lock_is_locked(); + bool pin_locked = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock); view_port_enabled_set(desktop->lock_icon_viewport, true); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, true); diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index 8be63bfe3..92a4eaf36 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -9,7 +9,6 @@ #include "../views/desktop_view_main.h" #include "desktop_scene.h" #include "desktop_scene_i.h" -#include "../helpers/pin_lock.h" #define TAG "DesktopSrv" @@ -90,10 +89,12 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case DesktopMainEventOpenMenu: - loader_show_menu(); + case DesktopMainEventOpenMenu: { + Loader* loader = furi_record_open(RECORD_LOADER); + loader_show_menu(loader); + furi_record_close(RECORD_LOADER); consumed = true; - break; + } break; case DesktopMainEventOpenLockMenu: scene_manager_next_scene(desktop->scene_manager, DesktopSceneLockMenu); @@ -106,11 +107,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; case DesktopMainEventLock: - if(desktop->settings.pin_code.length > 0) { - desktop_pin_lock(&desktop->settings); - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); - } - desktop_lock(desktop); + desktop_lock(desktop, true); consumed = true; break; diff --git a/applications/services/desktop/scenes/desktop_scene_pin_input.c b/applications/services/desktop/scenes/desktop_scene_pin_input.c index 9392309e6..d4068fa56 100644 --- a/applications/services/desktop/scenes/desktop_scene_pin_input.c +++ b/applications/services/desktop/scenes/desktop_scene_pin_input.c @@ -6,13 +6,14 @@ #include #include #include +#include #include "../desktop.h" #include "../desktop_i.h" #include "../animations/animation_manager.h" #include "../views/desktop_events.h" #include "../views/desktop_view_pin_input.h" -#include "../helpers/pin_lock.h" +#include "../helpers/pin.h" #include "desktop_scene.h" #include "desktop_scene_i.h" @@ -54,9 +55,19 @@ static void desktop_scene_pin_input_back_callback(void* context) { static void desktop_scene_pin_input_done_callback(const PinCode* pin_code, void* context) { Desktop* desktop = (Desktop*)context; - if(desktop_pin_lock_verify(&desktop->settings.pin_code, pin_code)) { + if(desktop_pin_compare(&desktop->settings.pin_code, pin_code)) { + furi_hal_rtc_set_pin_fails(0); view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopPinInputEventUnlocked); } else { + uint32_t pin_fails = furi_hal_rtc_get_pin_fails() + 1; + if(pin_fails >= 10 && XTREME_SETTINGS()->bad_pins_format) { + furi_hal_rtc_set_pin_fails(0); + furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); + storage_sd_format(furi_record_open(RECORD_STORAGE)); + furi_record_close(RECORD_STORAGE); + power_reboot(PowerBootModeNormal); + } + furi_hal_rtc_set_pin_fails(pin_fails); view_dispatcher_send_custom_event( desktop->view_dispatcher, DesktopPinInputEventUnlockFailed); } @@ -126,7 +137,6 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopPinInputEventUnlocked: - desktop_pin_unlock(&desktop->settings); desktop_unlock(desktop); consumed = true; break; diff --git a/applications/services/desktop/views/desktop_view_debug.c b/applications/services/desktop/views/desktop_view_debug.c index 8c72001b4..2b820e64e 100644 --- a/applications/services/desktop/views/desktop_view_debug.c +++ b/applications/services/desktop/views/desktop_view_debug.c @@ -37,13 +37,12 @@ void desktop_debug_render(Canvas* canvas, void* model) { snprintf( buffer, sizeof(buffer), - "%d.F%dB%dC%d %s:%s %s", + "%d.F%dB%dC%d %s %s", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name_otp(), - furi_hal_region_get_name(), my_name ? my_name : "Unknown"); canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer); @@ -65,13 +64,16 @@ void desktop_debug_render(Canvas* canvas, void* model) { version_get_builddate(ver)); canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer); + uint16_t api_major, api_minor; + furi_hal_info_get_api_version(&api_major, &api_minor); snprintf( buffer, sizeof(buffer), - "%s%s [%s] %s", + "%s%s [%d.%d] %s", version_get_dirty_flag(ver) ? "[!] " : "", version_get_githash(ver), - version_get_gitbranchnum(ver), + api_major, + api_minor, c2_ver ? c2_ver->StackTypeString : ""); canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer); diff --git a/applications/services/desktop/views/desktop_view_locked.c b/applications/services/desktop/views/desktop_view_locked.c index dc081e88d..d7cc7f236 100644 --- a/applications/services/desktop/views/desktop_view_locked.c +++ b/applications/services/desktop/views/desktop_view_locked.c @@ -309,5 +309,6 @@ bool desktop_view_locked_is_locked_hint_visible(DesktopViewLocked* locked_view) DesktopViewLockedModel* model = view_get_model(locked_view->view); const DesktopViewLockedState view_state = model->view_state; view_commit_model(locked_view->view, false); - return view_state == DesktopViewLockedStateLockedHintShown; + return view_state == DesktopViewLockedStateLockedHintShown || + view_state == DesktopViewLockedStateLocked; } diff --git a/applications/services/desktop/views/desktop_view_pin_setup_done.c b/applications/services/desktop/views/desktop_view_pin_setup_done.c deleted file mode 100644 index 561b12861..000000000 --- a/applications/services/desktop/views/desktop_view_pin_setup_done.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../desktop_i.h" -#include "desktop_view_pin_setup_done.h" - -struct DesktopViewPinSetupDone { - View* view; - DesktopViewPinSetupDoneDoneCallback callback; - void* context; -}; - -static void desktop_view_pin_done_draw(Canvas* canvas, void* model) { - furi_assert(canvas); - UNUSED(model); - - canvas_set_font(canvas, FontPrimary); - elements_multiline_text_aligned( - canvas, 64, 0, AlignCenter, AlignTop, "Prepare to use\narrows as\nPIN symbols"); - - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 58, 24, "Prepare to use\narrows as\nPIN symbols"); - - canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29); - elements_button_right(canvas, "Next"); -} - -static bool desktop_view_pin_done_input(InputEvent* event, void* context) { - furi_assert(event); - furi_assert(context); - - DesktopViewPinSetupDone* instance = context; - bool consumed = false; - - if((event->key == InputKeyRight) && (event->type == InputTypeShort)) { - instance->callback(instance->context); - consumed = true; - } - - return consumed; -} - -void desktop_view_pin_done_set_callback( - DesktopViewPinSetupDone* instance, - DesktopViewPinSetupDoneDoneCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} - -DesktopViewPinSetupDone* desktop_view_pin_done_alloc() { - DesktopViewPinSetupDone* view = malloc(sizeof(DesktopViewPinSetupDone)); - view->view = view_alloc(); - view_set_context(view->view, view); - view_set_draw_callback(view->view, desktop_view_pin_done_draw); - view_set_input_callback(view->view, desktop_view_pin_done_input); - - return view; -} - -void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance) { - furi_assert(instance); - - view_free(instance->view); - free(instance); -} - -View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance) { - furi_assert(instance); - return instance->view; -} diff --git a/applications/services/desktop/views/desktop_view_pin_setup_done.h b/applications/services/desktop/views/desktop_view_pin_setup_done.h deleted file mode 100644 index b55677dc5..000000000 --- a/applications/services/desktop/views/desktop_view_pin_setup_done.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -typedef struct DesktopViewPinSetupDone DesktopViewPinSetupDone; - -typedef void (*DesktopViewPinSetupDoneDoneCallback)(void*); - -void desktop_view_pin_done_set_callback( - DesktopViewPinSetupDone* instance, - DesktopViewPinSetupDoneDoneCallback callback, - void* context); -DesktopViewPinSetupDone* desktop_view_pin_done_alloc(); -void desktop_view_pin_done_free(DesktopViewPinSetupDone* instance); -View* desktop_view_pin_done_get_view(DesktopViewPinSetupDone* instance); diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index 190efa5ec..1a418ead2 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -10,8 +10,6 @@ #define TAG "DolphinState" -#define DOLPHIN_STATE_OLD_PATH INT_PATH(".dolphin.state") -#define DOLPHIN_STATE_PATH CFG_PATH("dolphin.state") #define DOLPHIN_STATE_HEADER_MAGIC 0xD0 #define DOLPHIN_STATE_HEADER_VERSION 0x01 @@ -61,19 +59,6 @@ bool dolphin_state_load(DolphinState* dolphin_state) { DOLPHIN_STATE_HEADER_MAGIC, DOLPHIN_STATE_HEADER_VERSION); - if(!success) { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, DOLPHIN_STATE_OLD_PATH, DOLPHIN_STATE_PATH); - storage_common_remove(storage, DOLPHIN_STATE_OLD_PATH); - furi_record_close(RECORD_STORAGE); - success = saved_struct_load( - DOLPHIN_STATE_PATH, - &dolphin_state->data, - sizeof(DolphinStoreData), - DOLPHIN_STATE_HEADER_MAGIC, - DOLPHIN_STATE_HEADER_VERSION); - } - if(success) { if((dolphin_state->data.butthurt > BUTTHURT_MAX) || (dolphin_state->data.butthurt < BUTTHURT_MIN)) { @@ -101,7 +86,7 @@ bool dolphin_state_is_levelup(int icounter) { if((icounter == DOLPHIN_LEVELS[i])) { return true; } - }; + } return false; } diff --git a/applications/services/dolphin/helpers/dolphin_state.h b/applications/services/dolphin/helpers/dolphin_state.h index 65cea35ac..e869775f7 100644 --- a/applications/services/dolphin/helpers/dolphin_state.h +++ b/applications/services/dolphin/helpers/dolphin_state.h @@ -9,6 +9,9 @@ extern "C" { #endif +#define DOLPHIN_STATE_OLD_PATH INT_PATH(".dolphin.state") +#define DOLPHIN_STATE_PATH CFG_PATH("dolphin.state") + #define DOLPHIN_LEVEL_COUNT 29 typedef struct DolphinState DolphinState; diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index e914e807f..dd3b4114e 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -1,6 +1,8 @@ #include #include "gui_i.h" #include +#include +#include #define TAG "GuiSrv" @@ -75,7 +77,7 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { canvas_draw_box(gui->canvas, 89, 3, 38, 6); canvas_set_color(gui->canvas, ColorBlack); canvas_set_bitmap_mode(gui->canvas, 1); - canvas_draw_icon(gui->canvas, 0, 0, &I_Background_128x11); + canvas_draw_icon(gui->canvas, 0, 0, XTREME_ASSETS()->I_Background_128x11); } else { canvas_set_color(gui->canvas, ColorBlack); } @@ -589,6 +591,10 @@ Gui* gui_alloc() { furi_check(gui->input_events); furi_pubsub_subscribe(gui->input_events, gui_input_events_callback, gui); + Storage* storage = furi_record_open(RECORD_STORAGE); + gui_add_view_port(gui, storage->sd_gui.view_port, GuiLayerStatusBarLeft); + furi_record_close(RECORD_STORAGE); + return gui; } diff --git a/applications/services/gui/modules/popup.c b/applications/services/gui/modules/popup.c index d75abb95f..ad26b2691 100644 --- a/applications/services/gui/modules/popup.c +++ b/applications/services/gui/modules/popup.c @@ -99,7 +99,7 @@ void popup_start_timer(void* context) { if(furi_timer_start(popup->timer, timer_period) != FuriStatusOk) { furi_assert(0); - }; + } } } diff --git a/applications/services/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c index 01ccdbf52..6dc558815 100644 --- a/applications/services/gui/modules/text_box.c +++ b/applications/services/gui/modules/text_box.c @@ -85,7 +85,7 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) { // Set text position to 5th line from the end for(uint8_t i = 0; i < line_num - 5; i++) { while(*model->text_pos++ != '\n') { - }; + } } model->scroll_num = line_num - 4; model->scroll_pos = line_num - 5; diff --git a/applications/services/gui/view.c b/applications/services/gui/view.c index 4d84cac50..07ae072a1 100644 --- a/applications/services/gui/view.c +++ b/applications/services/gui/view.c @@ -19,19 +19,16 @@ void view_tie_icon_animation(View* view, IconAnimation* icon_animation) { void view_set_draw_callback(View* view, ViewDrawCallback callback) { furi_assert(view); - furi_assert(view->draw_callback == NULL); view->draw_callback = callback; } void view_set_input_callback(View* view, ViewInputCallback callback) { furi_assert(view); - furi_assert(view->input_callback == NULL); view->input_callback = callback; } void view_set_custom_callback(View* view, ViewCustomCallback callback) { furi_assert(view); - furi_assert(callback); view->custom_callback = callback; } @@ -62,7 +59,6 @@ void view_set_update_callback_context(View* view, void* context) { void view_set_context(View* view, void* context) { furi_assert(view); - furi_assert(context); view->context = context; } diff --git a/applications/services/loader/application.fam b/applications/services/loader/application.fam index 49f3c4148..f4d006e07 100644 --- a/applications/services/loader/application.fam +++ b/applications/services/loader/application.fam @@ -5,6 +5,7 @@ App( entry_point="loader_srv", cdefines=["SRV_LOADER"], requires=["gui"], + provides=["loader_start"], stack_size=2 * 1024, order=90, sdk_headers=[ @@ -12,3 +13,11 @@ App( "firmware_api/firmware_api.h", ], ) + +App( + appid="loader_start", + apptype=FlipperAppType.STARTUP, + entry_point="loader_on_system_start", + requires=["loader"], + order=90, +) diff --git a/applications/services/loader/firmware_api/firmware_api.cpp b/applications/services/loader/firmware_api/firmware_api.cpp index 52e86efc2..6651bf112 100644 --- a/applications/services/loader/firmware_api/firmware_api.cpp +++ b/applications/services/loader/firmware_api/firmware_api.cpp @@ -6,6 +6,8 @@ /* Generated table */ #include +#include + static_assert(!has_hash_collisions(elf_api_table), "Detected API method hash collision!"); constexpr HashtableApiInterface elf_api_interface{ @@ -19,3 +21,8 @@ constexpr HashtableApiInterface elf_api_interface{ }; const ElfApiInterface* const firmware_api_interface = &elf_api_interface; + +extern "C" void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor) { + *major = elf_api_interface.api_version_major; + *minor = elf_api_interface.api_version_minor; +} \ No newline at end of file diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 7e40ae54e..12651eba7 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -1,395 +1,122 @@ -#include "applications.h" -#include -#include -#include "loader/loader.h" +#include "loader.h" #include "loader_i.h" -#include "applications/main/fap_loader/fap_loader_app.h" -#include -#include +#include "loader_menu.h" +#include +#include #include -#include -#include #include +#include +#include "applications/main/fap_loader/fap_loader_app.h" +#include -#define TAG "LoaderSrv" +#define TAG "Loader" +#define LOADER_MAGIC_THREAD_VALUE 0xDEADBEEF +// api -#define LOADER_THREAD_FLAG_SHOW_MENU (1 << 0) -#define LOADER_THREAD_FLAG_SHOW_SETTINGS (1 << 1) -#define LOADER_THREAD_FLAG_ALL (LOADER_THREAD_FLAG_SHOW_MENU | LOADER_THREAD_FLAG_SHOW_SETTINGS) +LoaderStatus loader_start(Loader* loader, const char* name, const char* args) { + LoaderMessage message; + LoaderMessageLoaderStatusResult result; -static Loader* loader_instance = NULL; - -static FlipperApplication const* loader_find_application_by_name_in_list( - const char* name, - const FlipperApplication* list, - const uint32_t n_apps) { - for(size_t i = 0; i < n_apps; i++) { - if(strcmp(name, list[i].name) == 0) { - return &list[i]; - } - } - return NULL; + message.type = LoaderMessageTypeStartByName; + message.start.name = name; + message.start.args = args; + message.api_lock = api_lock_alloc_locked(); + message.status_value = &result; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); + api_lock_wait_unlock_and_free(message.api_lock); + return result.value; } -static bool - loader_start_application(const FlipperApplication* application, const char* arguments) { - if(application->app == NULL) { - arguments = application->appid; - application = loader_find_application_by_name_in_list( - FAP_LOADER_APP_NAME, FLIPPER_APPS, FLIPPER_APPS_COUNT); - } - loader_instance->application = application; +bool loader_lock(Loader* loader) { + LoaderMessage message; + LoaderMessageBoolResult result; + message.type = LoaderMessageTypeLock; + message.api_lock = api_lock_alloc_locked(); + message.bool_value = &result; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); + api_lock_wait_unlock_and_free(message.api_lock); + return result.value; +} - furi_assert(loader_instance->application_arguments == NULL); - if(arguments && strlen(arguments) > 0) { - loader_instance->application_arguments = strdup(arguments); - } +void loader_unlock(Loader* loader) { + LoaderMessage message; + message.type = LoaderMessageTypeUnlock; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} - FURI_LOG_I(TAG, "Starting: %s", loader_instance->application->name); +bool loader_is_locked(Loader* loader) { + LoaderMessage message; + LoaderMessageBoolResult result; + message.type = LoaderMessageTypeIsLocked; + message.api_lock = api_lock_alloc_locked(); + message.bool_value = &result; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); + api_lock_wait_unlock_and_free(message.api_lock); + return result.value; +} - FuriHalRtcHeapTrackMode mode = furi_hal_rtc_get_heap_track_mode(); - if(mode > FuriHalRtcHeapTrackModeNone) { - furi_thread_enable_heap_trace(loader_instance->application_thread); +void loader_show_menu(Loader* loader) { + LoaderMessage message; + message.type = LoaderMessageTypeShowMenu; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} + +void loader_show_settings(Loader* loader) { + LoaderMessage message; + message.type = LoaderMessageTypeShowSettings; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} + +FuriPubSub* loader_get_pubsub(Loader* loader) { + furi_assert(loader); + // it's safe to return pubsub without locking + // because it's never freed and loader is never exited + // also the loader instance cannot be obtained until the pubsub is created + return loader->pubsub; +} + +// callbacks + +static void loader_menu_closed_callback(void* context) { + Loader* loader = context; + LoaderMessage message; + message.type = LoaderMessageTypeMenuClosed; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} + +static void loader_menu_click_callback(const char* name, bool external, void* context) { + Loader* loader = context; + if(external) { + loader_start(loader, FAP_LOADER_APP_NAME, name); } else { - furi_thread_disable_heap_trace(loader_instance->application_thread); + loader_start(loader, name, NULL); } - - furi_thread_set_name(loader_instance->application_thread, loader_instance->application->name); - furi_thread_set_appid( - loader_instance->application_thread, loader_instance->application->appid); - furi_thread_set_stack_size( - loader_instance->application_thread, loader_instance->application->stack_size); - furi_thread_set_context( - loader_instance->application_thread, loader_instance->application_arguments); - furi_thread_set_callback( - loader_instance->application_thread, loader_instance->application->app); - - furi_thread_start(loader_instance->application_thread); - - return true; -} - -const FlipperApplication* loader_find_application_by_name(const char* name) { - const FlipperApplication* application = NULL; - application = loader_find_application_by_name_in_list(name, FLIPPER_APPS, FLIPPER_APPS_COUNT); - if(!application) { - application = loader_find_application_by_name_in_list( - name, FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT); - } - if(!application) { - application = loader_find_application_by_name_in_list( - name, FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT); - } - - return application; -} - -static void loader_menu_callback(void* _ctx, uint32_t index) { - UNUSED(index); - const FlipperApplication* application = _ctx; - - furi_assert(application->app); - furi_assert(application->name); - - if(!loader_lock(loader_instance)) { - FURI_LOG_E(TAG, "Loader is locked"); - return; - } - - loader_start_application(application, NULL); -} - -static void loader_external_callback(void* _ctx, uint32_t index) { - UNUSED(index); - const char* path = _ctx; - const FlipperApplication* app = loader_find_application_by_name_in_list( - FAP_LOADER_APP_NAME, FLIPPER_APPS, FLIPPER_APPS_COUNT); - - furi_assert(path); - - if(!loader_lock(loader_instance)) { - FURI_LOG_E(TAG, "Loader is locked"); - return; - } - - loader_start_application(app, path); -} - -static void loader_submenu_callback(void* context, uint32_t index) { - UNUSED(index); - uint32_t view_id = (uint32_t)context; - view_dispatcher_switch_to_view(loader_instance->view_dispatcher, view_id); -} - -static void loader_cli_print_usage() { - printf("Usage:\r\n"); - printf("loader \r\n"); - printf("Cmd list:\r\n"); - printf("\tlist\t - List available applications\r\n"); - printf("\topen \t - Open application by name\r\n"); - printf("\tinfo\t - Show loader state\r\n"); -} - -static void loader_cli_open(Cli* cli, FuriString* args, Loader* instance) { - UNUSED(cli); - if(loader_is_locked(instance)) { - if(instance->application) { - furi_assert(instance->application->name); - printf("Can't start, %s application is running", instance->application->name); - } else { - printf("Can't start, furi application is running"); - } - return; - } - - FuriString* application_name; - application_name = furi_string_alloc(); - - do { - if(!args_read_probably_quoted_string_and_trim(args, application_name)) { - printf("No application provided\r\n"); - break; - } - - const FlipperApplication* application = - loader_find_application_by_name(furi_string_get_cstr(application_name)); - if(!application) { - printf("%s doesn't exists\r\n", furi_string_get_cstr(application_name)); - break; - } - - furi_string_trim(args); - if(!loader_start_application(application, furi_string_get_cstr(args))) { - printf("Can't start, furi application is running"); - return; - } else { - // We must to increment lock counter to keep balance - // TODO: rewrite whole thing, it's complex as hell - FURI_CRITICAL_ENTER(); - instance->lock_count++; - FURI_CRITICAL_EXIT(); - } - } while(false); - - furi_string_free(application_name); -} - -static void loader_cli_list(Cli* cli, FuriString* args, Loader* instance) { - UNUSED(cli); - UNUSED(args); - UNUSED(instance); - printf("Applications:\r\n"); - for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { - printf("\t%s\r\n", FLIPPER_APPS[i].name); - } -} - -static void loader_cli_info(Cli* cli, FuriString* args, Loader* instance) { - UNUSED(cli); - UNUSED(args); - if(!loader_is_locked(instance)) { - printf("No application is running\r\n"); - } else { - printf("Running application: "); - if(instance->application) { - furi_assert(instance->application->name); - printf("%s\r\n", instance->application->name); - } else { - printf("unknown\r\n"); - } - } -} - -static void loader_cli(Cli* cli, FuriString* args, void* _ctx) { - furi_assert(_ctx); - Loader* instance = _ctx; - - FuriString* cmd; - cmd = furi_string_alloc(); - - do { - if(!args_read_string_and_trim(args, cmd)) { - loader_cli_print_usage(); - break; - } - - if(furi_string_cmp_str(cmd, "list") == 0) { - loader_cli_list(cli, args, instance); - break; - } - - if(furi_string_cmp_str(cmd, "open") == 0) { - loader_cli_open(cli, args, instance); - break; - } - - if(furi_string_cmp_str(cmd, "info") == 0) { - loader_cli_info(cli, args, instance); - break; - } - - loader_cli_print_usage(); - } while(false); - - furi_string_free(cmd); -} - -LoaderStatus loader_start(Loader* instance, const char* name, const char* args) { - UNUSED(instance); - furi_assert(name); - - const FlipperApplication* application = loader_find_application_by_name(name); - - if(!application) { - FURI_LOG_E(TAG, "Can't find application with name %s", name); - return LoaderStatusErrorUnknownApp; - } - - if(!loader_lock(loader_instance)) { - FURI_LOG_E(TAG, "Loader is locked"); - return LoaderStatusErrorAppStarted; - } - - if(!loader_start_application(application, args)) { - return LoaderStatusErrorInternal; - } - - return LoaderStatusOk; -} - -bool loader_lock(Loader* instance) { - FURI_CRITICAL_ENTER(); - bool result = false; - if(instance->lock_count == 0) { - instance->lock_count++; - result = true; - } - FURI_CRITICAL_EXIT(); - return result; -} - -void loader_unlock(Loader* instance) { - FURI_CRITICAL_ENTER(); - if(instance->lock_count > 0) instance->lock_count--; - FURI_CRITICAL_EXIT(); -} - -bool loader_is_locked(const Loader* instance) { - return instance->lock_count > 0; } static void loader_thread_state_callback(FuriThreadState thread_state, void* context) { furi_assert(context); - Loader* instance = context; + Loader* loader = context; LoaderEvent event; if(thread_state == FuriThreadStateRunning) { event.type = LoaderEventTypeApplicationStarted; - furi_pubsub_publish(loader_instance->pubsub, &event); - - if(!(loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe)) { - furi_hal_power_insomnia_enter(); - } + furi_pubsub_publish(loader->pubsub, &event); } else if(thread_state == FuriThreadStateStopped) { - FURI_LOG_I(TAG, "Application stopped. Free heap: %zu", memmgr_get_free_heap()); - - if(loader_instance->application_arguments) { - free(loader_instance->application_arguments); - loader_instance->application_arguments = NULL; - } - - if(!(loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe)) { - furi_hal_power_insomnia_exit(); - } - loader_unlock(instance); + LoaderMessage message; + message.type = LoaderMessageTypeAppClosed; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); event.type = LoaderEventTypeApplicationStopped; - furi_pubsub_publish(loader_instance->pubsub, &event); + furi_pubsub_publish(loader->pubsub, &event); } } -static uint32_t loader_hide_menu(void* context) { - UNUSED(context); - return VIEW_NONE; -} - -static uint32_t loader_back_to_primary_menu(void* context) { - furi_assert(context); - Submenu* submenu = context; - submenu_set_selected_item(submenu, 0); - return LoaderMenuViewPrimary; -} - -static Loader* loader_alloc() { - Loader* instance = malloc(sizeof(Loader)); - - instance->application_thread = furi_thread_alloc(); - - furi_thread_set_state_context(instance->application_thread, instance); - furi_thread_set_state_callback(instance->application_thread, loader_thread_state_callback); - - instance->pubsub = furi_pubsub_alloc(); - -#ifdef SRV_CLI - instance->cli = furi_record_open(RECORD_CLI); - cli_add_command( - instance->cli, RECORD_LOADER, CliCommandFlagParallelSafe, loader_cli, instance); -#else - UNUSED(loader_cli); -#endif - - instance->loader_thread = furi_thread_get_current_id(); - - // Gui - instance->gui = furi_record_open(RECORD_GUI); - instance->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_attach_to_gui( - instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); - // Primary menu - instance->primary_menu = menu_alloc(); - view_set_previous_callback(menu_get_view(instance->primary_menu), loader_hide_menu); - view_dispatcher_add_view( - instance->view_dispatcher, LoaderMenuViewPrimary, menu_get_view(instance->primary_menu)); - // Settings menu - instance->settings_menu = submenu_alloc(); - view_set_context(submenu_get_view(instance->settings_menu), instance->settings_menu); - view_set_previous_callback( - submenu_get_view(instance->settings_menu), loader_back_to_primary_menu); - view_dispatcher_add_view( - instance->view_dispatcher, - LoaderMenuViewSettings, - submenu_get_view(instance->settings_menu)); - - view_dispatcher_enable_queue(instance->view_dispatcher); - - return instance; -} - -static void loader_free(Loader* instance) { - furi_assert(instance); - - if(instance->cli) { - furi_record_close(RECORD_CLI); - } - - furi_pubsub_free(instance->pubsub); - - furi_thread_free(instance->application_thread); - - menu_free(loader_instance->primary_menu); - view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewPrimary); - submenu_free(loader_instance->settings_menu); - view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewSettings); - view_dispatcher_free(loader_instance->view_dispatcher); - - furi_record_close(RECORD_GUI); - - free(instance); - instance = NULL; -} - -bool loader_load_fap_meta(Storage* storage, FuriString* path, FuriString* name, const Icon** icon) { +bool loader_menu_load_fap_meta( + Storage* storage, + FuriString* path, + FuriString* name, + const Icon** icon) { *icon = NULL; uint8_t* icon_buf = malloc(CUSTOM_ICON_MAX_SIZE); if(!fap_loader_load_name_and_icon(path, storage, &icon_buf, name)) { @@ -407,43 +134,35 @@ bool loader_load_fap_meta(Storage* storage, FuriString* path, FuriString* name, return true; } -static void loader_build_menu() { - FURI_LOG_I(TAG, "Building main menu"); - size_t i; - for(i = 0; i < FLIPPER_APPS_COUNT; i++) { - menu_add_item( - loader_instance->primary_menu, - FLIPPER_APPS[i].name, - FLIPPER_APPS[i].icon, - i, - loader_menu_callback, - (void*)&FLIPPER_APPS[i]); - } - menu_add_item( - loader_instance->primary_menu, - "Settings", - &A_Settings_14, - i++, - loader_submenu_callback, - (void*)LoaderMenuViewSettings); +// implementation + +static Loader* loader_alloc() { + Loader* loader = malloc(sizeof(Loader)); + loader->pubsub = furi_pubsub_alloc(); + loader->queue = furi_message_queue_alloc(1, sizeof(LoaderMessage)); + loader->loader_menu = NULL; + loader->app.args = NULL; + loader->app.name = NULL; + loader->app.thread = NULL; + loader->app.insomniac = false; Storage* storage = furi_record_open(RECORD_STORAGE); FuriString* path = furi_string_alloc(); FuriString* name = furi_string_alloc(); Stream* stream = file_stream_alloc(storage); + ExtMainAppList_init(loader->ext_main_apps); if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { while(stream_read_line(stream, path)) { furi_string_replace_all(path, "\r", ""); furi_string_replace_all(path, "\n", ""); const Icon* icon; - if(!loader_load_fap_meta(storage, path, name, &icon)) continue; - menu_add_item( - loader_instance->primary_menu, - strdup(furi_string_get_cstr(name)), - icon, - i++, - loader_external_callback, - (void*)strdup(furi_string_get_cstr(path))); + if(!loader_menu_load_fap_meta(storage, path, name, &icon)) continue; + ExtMainAppList_push_back( + loader->ext_main_apps, + (ExtMainApp){ + .name = strdup(furi_string_get_cstr(name)), + .path = strdup(furi_string_get_cstr(path)), + .icon = icon}); } } file_stream_close(stream); @@ -451,82 +170,207 @@ static void loader_build_menu() { furi_string_free(name); furi_string_free(path); furi_record_close(RECORD_STORAGE); + return loader; } -static void loader_build_submenu() { - FURI_LOG_I(TAG, "Building settings menu"); - for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { - submenu_add_item( - loader_instance->settings_menu, - FLIPPER_SETTINGS_APPS[i].name, - i, - loader_menu_callback, - (void*)&FLIPPER_SETTINGS_APPS[i]); +static FlipperApplication const* loader_find_application_by_name_in_list( + const char* name, + const FlipperApplication* list, + const uint32_t n_apps) { + for(size_t i = 0; i < n_apps; i++) { + if(strcmp(name, list[i].name) == 0) { + return &list[i]; + } + } + return NULL; +} + +static const FlipperApplication* loader_find_application_by_name(const char* name) { + const FlipperApplication* application = NULL; + application = loader_find_application_by_name_in_list(name, FLIPPER_APPS, FLIPPER_APPS_COUNT); + if(!application) { + application = loader_find_application_by_name_in_list( + name, FLIPPER_SETTINGS_APPS, FLIPPER_SETTINGS_APPS_COUNT); + } + if(!application) { + application = loader_find_application_by_name_in_list( + name, FLIPPER_SYSTEM_APPS, FLIPPER_SYSTEM_APPS_COUNT); + } + + return application; +} + +static void + loader_start_internal_app(Loader* loader, const FlipperApplication* app, const char* args) { + FURI_LOG_I(TAG, "Starting %s", app->name); + + if(app->app == NULL) { + args = app->appid; + app = loader_find_application_by_name_in_list( + FAP_LOADER_APP_NAME, FLIPPER_APPS, FLIPPER_APPS_COUNT); + } + + // store args + furi_assert(loader->app.args == NULL); + if(args && strlen(args) > 0) { + loader->app.args = strdup(args); + } + + // store name + furi_assert(loader->app.name == NULL); + loader->app.name = strdup(app->name); + + // setup app thread + loader->app.thread = + furi_thread_alloc_ex(app->name, app->stack_size, app->app, loader->app.args); + furi_thread_set_appid(loader->app.thread, app->appid); + + // setup heap trace + FuriHalRtcHeapTrackMode mode = furi_hal_rtc_get_heap_track_mode(); + if(mode > FuriHalRtcHeapTrackModeNone) { + furi_thread_enable_heap_trace(loader->app.thread); + } else { + furi_thread_disable_heap_trace(loader->app.thread); + } + + // setup insomnia + if(!(app->flags & FlipperApplicationFlagInsomniaSafe)) { + furi_hal_power_insomnia_enter(); + loader->app.insomniac = true; + } else { + loader->app.insomniac = false; + } + + // setup app thread callbacks + furi_thread_set_state_context(loader->app.thread, loader); + furi_thread_set_state_callback(loader->app.thread, loader_thread_state_callback); + + // start app thread + furi_thread_start(loader->app.thread); +} + +// process messages + +static void loader_do_menu_show(Loader* loader, bool settings) { + if(!loader->loader_menu) { + loader->loader_menu = loader_menu_alloc(); + loader_menu_set_closed_callback(loader->loader_menu, loader_menu_closed_callback, loader); + loader_menu_set_click_callback(loader->loader_menu, loader_menu_click_callback, loader); + loader_menu_start(loader->loader_menu, settings, &loader->ext_main_apps); } } -void loader_show_menu() { - furi_assert(loader_instance); - furi_thread_flags_set(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU); +static void loader_do_menu_closed(Loader* loader) { + if(loader->loader_menu) { + loader_menu_stop(loader->loader_menu); + loader_menu_free(loader->loader_menu); + loader->loader_menu = NULL; + } } -void loader_show_settings() { - furi_assert(loader_instance); - furi_thread_flags_set(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_SETTINGS); +static bool loader_do_is_locked(Loader* loader) { + return loader->app.thread != NULL; } -void loader_update_menu() { - menu_reset(loader_instance->primary_menu); - loader_build_menu(); +static LoaderStatus loader_do_start_by_name(Loader* loader, const char* name, const char* args) { + if(loader_do_is_locked(loader)) { + return LoaderStatusErrorAppStarted; + } + + const FlipperApplication* app = loader_find_application_by_name(name); + + if(!app) { + return LoaderStatusErrorUnknownApp; + } + + loader_start_internal_app(loader, app, args); + return LoaderStatusOk; } +static bool loader_do_lock(Loader* loader) { + if(loader->app.thread) { + return false; + } + + loader->app.thread = (FuriThread*)LOADER_MAGIC_THREAD_VALUE; + return true; +} + +static void loader_do_unlock(Loader* loader) { + furi_assert(loader->app.thread == (FuriThread*)LOADER_MAGIC_THREAD_VALUE); + loader->app.thread = NULL; +} + +static void loader_do_app_closed(Loader* loader) { + furi_assert(loader->app.thread); + FURI_LOG_I(TAG, "Application stopped. Free heap: %zu", memmgr_get_free_heap()); + if(loader->app.args) { + free(loader->app.args); + loader->app.args = NULL; + } + + if(loader->app.insomniac) { + furi_hal_power_insomnia_exit(); + } + + free(loader->app.name); + loader->app.name = NULL; + + furi_thread_join(loader->app.thread); + furi_thread_free(loader->app.thread); + loader->app.thread = NULL; +} + +// app + int32_t loader_srv(void* p) { UNUSED(p); + Loader* loader = loader_alloc(); + furi_record_create(RECORD_LOADER, loader); + FURI_LOG_I(TAG, "Executing system start hooks"); for(size_t i = 0; i < FLIPPER_ON_SYSTEM_START_COUNT; i++) { FLIPPER_ON_SYSTEM_START[i](); } - FURI_LOG_I(TAG, "Starting"); - loader_instance = loader_alloc(); - - loader_build_menu(); - loader_build_submenu(); - - FURI_LOG_I(TAG, "Started"); - - furi_record_create(RECORD_LOADER, loader_instance); - if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) { - loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL); + loader_do_start_by_name(loader, FLIPPER_AUTORUN_APP_NAME, NULL); } - while(1) { - uint32_t flags = - furi_thread_flags_wait(LOADER_THREAD_FLAG_ALL, FuriFlagWaitAny, FuriWaitForever); - if(flags & LOADER_THREAD_FLAG_SHOW_MENU) { - menu_set_selected_item(loader_instance->primary_menu, 0); - view_dispatcher_switch_to_view( - loader_instance->view_dispatcher, LoaderMenuViewPrimary); - view_dispatcher_run(loader_instance->view_dispatcher); - } else if(flags & LOADER_THREAD_FLAG_SHOW_SETTINGS) { - submenu_set_selected_item(loader_instance->settings_menu, 0); - view_set_previous_callback( - submenu_get_view(loader_instance->settings_menu), loader_hide_menu); - view_dispatcher_switch_to_view( - loader_instance->view_dispatcher, LoaderMenuViewSettings); - view_dispatcher_run(loader_instance->view_dispatcher); - view_set_previous_callback( - submenu_get_view(loader_instance->settings_menu), loader_back_to_primary_menu); + LoaderMessage message; + while(true) { + if(furi_message_queue_get(loader->queue, &message, FuriWaitForever) == FuriStatusOk) { + switch(message.type) { + case LoaderMessageTypeStartByName: + message.status_value->value = + loader_do_start_by_name(loader, message.start.name, message.start.args); + api_lock_unlock(message.api_lock); + break; + case LoaderMessageTypeShowMenu: + loader_do_menu_show(loader, false); + break; + case LoaderMessageTypeShowSettings: + loader_do_menu_show(loader, true); + break; + case LoaderMessageTypeMenuClosed: + loader_do_menu_closed(loader); + break; + case LoaderMessageTypeIsLocked: + message.bool_value->value = loader_do_is_locked(loader); + api_lock_unlock(message.api_lock); + break; + case LoaderMessageTypeAppClosed: + loader_do_app_closed(loader); + break; + case LoaderMessageTypeLock: + message.bool_value->value = loader_do_lock(loader); + api_lock_unlock(message.api_lock); + break; + case LoaderMessageTypeUnlock: + loader_do_unlock(loader); + } } } - furi_record_destroy(RECORD_LOADER); - loader_free(loader_instance); - return 0; } - -FuriPubSub* loader_get_pubsub(Loader* instance) { - return instance->pubsub; -} diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index 58516b339..b31bb1bdd 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -1,7 +1,6 @@ #pragma once - -#include -#include +#include +#include "loader_extmainapp.h" #ifdef __cplusplus extern "C" { @@ -45,16 +44,13 @@ bool loader_lock(Loader* instance); void loader_unlock(Loader* instance); /** Get loader lock status */ -bool loader_is_locked(const Loader* instance); +bool loader_is_locked(Loader* instance); /** Show primary loader */ -void loader_show_menu(); +void loader_show_menu(Loader* instance); /** Show settings menu */ -void loader_show_settings(); - -/** Show primary loader */ -void loader_update_menu(); +void loader_show_settings(Loader* loader); /** Show primary loader */ FuriPubSub* loader_get_pubsub(Loader* instance); diff --git a/applications/services/loader/loader_cli.c b/applications/services/loader/loader_cli.c new file mode 100644 index 000000000..2d4602215 --- /dev/null +++ b/applications/services/loader/loader_cli.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include "loader.h" + +static void loader_cli_print_usage() { + printf("Usage:\r\n"); + printf("loader \r\n"); + printf("Cmd list:\r\n"); + printf("\tlist\t - List available applications\r\n"); + printf("\topen \t - Open application by name\r\n"); + printf("\tinfo\t - Show loader state\r\n"); +} + +static void loader_cli_list() { + printf("Applications:\r\n"); + for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { + printf("\t%s\r\n", FLIPPER_APPS[i].name); + } + printf("Settings:\r\n"); + for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { + printf("\t%s\r\n", FLIPPER_SETTINGS_APPS[i].name); + } +} + +static void loader_cli_info(Loader* loader) { + if(!loader_is_locked(loader)) { + printf("No application is running\r\n"); + } else { + // TODO: print application name ??? + printf("Application is running\r\n"); + } +} + +static void loader_cli_open(FuriString* args, Loader* loader) { + FuriString* app_name = furi_string_alloc(); + + do { + if(!args_read_probably_quoted_string_and_trim(args, app_name)) { + printf("No application provided\r\n"); + break; + } + furi_string_trim(args); + + const char* args_str = furi_string_get_cstr(args); + if(strlen(args_str) == 0) { + args_str = NULL; + } + + const char* app_name_str = furi_string_get_cstr(app_name); + + LoaderStatus status = loader_start(loader, app_name_str, args_str); + + switch(status) { + case LoaderStatusOk: + break; + case LoaderStatusErrorAppStarted: + printf("Can't start, application is running"); + break; + case LoaderStatusErrorUnknownApp: + printf("%s doesn't exists\r\n", app_name_str); + break; + case LoaderStatusErrorInternal: + printf("Internal error\r\n"); + break; + } + } while(false); + + furi_string_free(app_name); +} + +static void loader_cli(Cli* cli, FuriString* args, void* context) { + UNUSED(cli); + UNUSED(context); + Loader* loader = furi_record_open(RECORD_LOADER); + + FuriString* cmd; + cmd = furi_string_alloc(); + + do { + if(!args_read_string_and_trim(args, cmd)) { + loader_cli_print_usage(); + break; + } + + if(furi_string_cmp_str(cmd, "list") == 0) { + loader_cli_list(); + break; + } + + if(furi_string_cmp_str(cmd, "open") == 0) { + loader_cli_open(args, loader); + break; + } + + if(furi_string_cmp_str(cmd, "info") == 0) { + loader_cli_info(loader); + break; + } + + loader_cli_print_usage(); + } while(false); + + furi_string_free(cmd); + furi_record_close(RECORD_LOADER); +} + +void loader_on_system_start() { +#ifdef SRV_CLI + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, RECORD_LOADER, CliCommandFlagParallelSafe, loader_cli, NULL); + furi_record_close(RECORD_CLI); +#else + UNUSED(loader_cli); +#endif +} \ No newline at end of file diff --git a/applications/services/loader/loader_extmainapp.h b/applications/services/loader/loader_extmainapp.h new file mode 100644 index 000000000..2e10b16a3 --- /dev/null +++ b/applications/services/loader/loader_extmainapp.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +typedef struct { + const char* name; + const char* path; + const Icon* icon; +} ExtMainApp; + +LIST_DEF(ExtMainAppList, ExtMainApp, M_POD_OPLIST) diff --git a/applications/services/loader/loader_i.h b/applications/services/loader/loader_i.h index 00028cd6b..6887b4b50 100644 --- a/applications/services/loader/loader_i.h +++ b/applications/services/loader/loader_i.h @@ -1,39 +1,58 @@ -#include "loader.h" - +#pragma once #include -#include -#include -#include -#include +#include +#include "loader.h" +#include "loader_menu.h" -#include - -#include -#include - -#include -#include +typedef struct { + char* args; + char* name; + FuriThread* thread; + bool insomniac; +} LoaderAppData; struct Loader { - FuriThreadId loader_thread; - - const FlipperApplication* application; - FuriThread* application_thread; - char* application_arguments; - - Cli* cli; - Gui* gui; - - ViewDispatcher* view_dispatcher; - Menu* primary_menu; - Submenu* settings_menu; - - volatile uint8_t lock_count; - FuriPubSub* pubsub; + FuriMessageQueue* queue; + LoaderMenu* loader_menu; + LoaderAppData app; + ExtMainAppList_t ext_main_apps; }; typedef enum { - LoaderMenuViewPrimary, - LoaderMenuViewSettings, -} LoaderMenuView; + LoaderMessageTypeStartByName, + LoaderMessageTypeAppClosed, + LoaderMessageTypeShowMenu, + LoaderMessageTypeMenuClosed, + LoaderMessageTypeLock, + LoaderMessageTypeUnlock, + LoaderMessageTypeIsLocked, + LoaderMessageTypeShowSettings, +} LoaderMessageType; + +typedef struct { + const char* name; + const char* args; +} LoaderMessageStartByName; + +typedef struct { + LoaderStatus value; +} LoaderMessageLoaderStatusResult; + +typedef struct { + bool value; +} LoaderMessageBoolResult; + +typedef struct { + FuriApiLock api_lock; + LoaderMessageType type; + + union { + LoaderMessageStartByName start; + }; + + union { + LoaderMessageLoaderStatusResult* status_value; + LoaderMessageBoolResult* bool_value; + }; +} LoaderMessage; diff --git a/applications/services/loader/loader_menu.c b/applications/services/loader/loader_menu.c new file mode 100644 index 000000000..c4e14038c --- /dev/null +++ b/applications/services/loader/loader_menu.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include + +#include "loader_menu.h" + +#define TAG "LoaderMenu" + +struct LoaderMenu { + Gui* gui; + ViewDispatcher* view_dispatcher; + Menu* primary_menu; + Submenu* settings_menu; + + bool settings; + ExtMainAppList_t* ext_main_apps; + + void (*closed_callback)(void*); + void* closed_callback_context; + + void (*click_callback)(const char*, bool, void*); + void* click_callback_context; + + FuriThread* thread; +}; + +typedef enum { + LoaderMenuViewPrimary, + LoaderMenuViewSettings, +} LoaderMenuView; + +static int32_t loader_menu_thread(void* p); + +LoaderMenu* loader_menu_alloc() { + LoaderMenu* loader_menu = malloc(sizeof(LoaderMenu)); + loader_menu->gui = furi_record_open(RECORD_GUI); + loader_menu->view_dispatcher = view_dispatcher_alloc(); + loader_menu->primary_menu = menu_alloc(); + loader_menu->settings_menu = submenu_alloc(); + loader_menu->thread = NULL; + return loader_menu; +} + +void loader_menu_free(LoaderMenu* loader_menu) { + furi_assert(loader_menu); + // check if thread is running + furi_assert(!loader_menu->thread); + + submenu_free(loader_menu->settings_menu); + menu_free(loader_menu->primary_menu); + view_dispatcher_free(loader_menu->view_dispatcher); + furi_record_close(RECORD_GUI); + free(loader_menu); +} + +void loader_menu_start(LoaderMenu* loader_menu, bool settings, ExtMainAppList_t* ext_main_apps) { + furi_assert(loader_menu); + furi_assert(!loader_menu->thread); + loader_menu->settings = settings; + loader_menu->ext_main_apps = ext_main_apps; + loader_menu->thread = furi_thread_alloc_ex(TAG, 1024, loader_menu_thread, loader_menu); + furi_thread_start(loader_menu->thread); +} + +void loader_menu_stop(LoaderMenu* loader_menu) { + furi_assert(loader_menu); + furi_assert(loader_menu->thread); + view_dispatcher_stop(loader_menu->view_dispatcher); + furi_thread_join(loader_menu->thread); + furi_thread_free(loader_menu->thread); + loader_menu->thread = NULL; +} + +void loader_menu_set_closed_callback( + LoaderMenu* loader_menu, + void (*callback)(void*), + void* context) { + loader_menu->closed_callback = callback; + loader_menu->closed_callback_context = context; +} + +void loader_menu_set_click_callback( + LoaderMenu* loader_menu, + void (*callback)(const char*, bool, void*), + void* context) { + loader_menu->click_callback = callback; + loader_menu->click_callback_context = context; +} + +static void loader_menu_callback(void* context, uint32_t index) { + LoaderMenu* loader_menu = context; + const char* name = FLIPPER_APPS[index].name; + if(loader_menu->click_callback) { + loader_menu->click_callback(name, false, loader_menu->click_callback_context); + } +} + +static void loader_menu_external_callback(void* context, uint32_t index) { + LoaderMenu* loader_menu = context; + const char* path = (const char*)index; + if(loader_menu->click_callback) { + loader_menu->click_callback(path, true, loader_menu->click_callback_context); + } +} + +static void loader_menu_settings_menu_callback(void* context, uint32_t index) { + LoaderMenu* loader_menu = context; + const char* name = FLIPPER_SETTINGS_APPS[index].name; + if(loader_menu->click_callback) { + loader_menu->click_callback(name, false, loader_menu->click_callback_context); + } +} + +static void loader_menu_switch_to_settings(void* context, uint32_t index) { + UNUSED(index); + LoaderMenu* loader_menu = context; + view_dispatcher_switch_to_view(loader_menu->view_dispatcher, LoaderMenuViewSettings); +} + +static uint32_t loader_menu_switch_to_primary(void* context) { + UNUSED(context); + return LoaderMenuViewPrimary; +} + +static uint32_t loader_menu_exit(void* context) { + UNUSED(context); + return VIEW_NONE; +} + +static void loader_menu_build_menu(LoaderMenu* loader_menu) { + size_t i; + for(i = 0; i < FLIPPER_APPS_COUNT; i++) { + menu_add_item( + loader_menu->primary_menu, + FLIPPER_APPS[i].name, + FLIPPER_APPS[i].icon, + i, + loader_menu_callback, + (void*)loader_menu); + } + menu_add_item( + loader_menu->primary_menu, + "Settings", + &A_Settings_14, + i++, + loader_menu_switch_to_settings, + loader_menu); + + for(i = 0; i < ExtMainAppList_size(*loader_menu->ext_main_apps); i++) { + const ExtMainApp* app = ExtMainAppList_get(*loader_menu->ext_main_apps, i); + menu_add_item( + loader_menu->primary_menu, + app->name, + app->icon, + (uint32_t)app->path, + loader_menu_external_callback, + (void*)loader_menu); + } +}; + +static void loader_menu_build_submenu(LoaderMenu* loader_menu) { + for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { + submenu_add_item( + loader_menu->settings_menu, + FLIPPER_SETTINGS_APPS[i].name, + i, + loader_menu_settings_menu_callback, + loader_menu); + } +} + +static int32_t loader_menu_thread(void* p) { + LoaderMenu* loader_menu = p; + furi_assert(loader_menu); + + if(!loader_menu->settings) loader_menu_build_menu(loader_menu); + loader_menu_build_submenu(loader_menu); + + view_dispatcher_attach_to_gui( + loader_menu->view_dispatcher, loader_menu->gui, ViewDispatcherTypeFullscreen); + + // Primary menu + if(!loader_menu->settings) { + View* primary_view = menu_get_view(loader_menu->primary_menu); + view_set_context(primary_view, loader_menu->primary_menu); + view_set_previous_callback(primary_view, loader_menu_exit); + view_dispatcher_add_view( + loader_menu->view_dispatcher, LoaderMenuViewPrimary, primary_view); + } + + // Settings menu + View* settings_view = submenu_get_view(loader_menu->settings_menu); + view_set_context(settings_view, loader_menu->settings_menu); + view_set_previous_callback( + settings_view, loader_menu->settings ? loader_menu_exit : loader_menu_switch_to_primary); + view_dispatcher_add_view(loader_menu->view_dispatcher, LoaderMenuViewSettings, settings_view); + + view_dispatcher_enable_queue(loader_menu->view_dispatcher); + view_dispatcher_switch_to_view( + loader_menu->view_dispatcher, + loader_menu->settings ? LoaderMenuViewSettings : LoaderMenuViewPrimary); + + // run view dispatcher + view_dispatcher_run(loader_menu->view_dispatcher); + + if(!loader_menu->settings) + view_dispatcher_remove_view(loader_menu->view_dispatcher, LoaderMenuViewPrimary); + view_dispatcher_remove_view(loader_menu->view_dispatcher, LoaderMenuViewSettings); + + if(loader_menu->closed_callback) { + loader_menu->closed_callback(loader_menu->closed_callback_context); + } + + return 0; +} diff --git a/applications/services/loader/loader_menu.h b/applications/services/loader/loader_menu.h new file mode 100644 index 000000000..f4188b733 --- /dev/null +++ b/applications/services/loader/loader_menu.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include "loader_extmainapp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct LoaderMenu LoaderMenu; + +LoaderMenu* loader_menu_alloc(); + +void loader_menu_free(LoaderMenu* loader_menu); + +void loader_menu_start(LoaderMenu* loader_menu, bool settings, ExtMainAppList_t* ext_main_apps); + +void loader_menu_stop(LoaderMenu* loader_menu); + +void loader_menu_set_closed_callback( + LoaderMenu* loader_menu, + void (*callback)(void*), + void* context); + +void loader_menu_set_click_callback( + LoaderMenu* loader_menu, + void (*callback)(const char*, bool, void*), + void* context); + +#ifdef __cplusplus +} +#endif diff --git a/applications/services/namechangersrv/application.fam b/applications/services/namechangersrv/application.fam deleted file mode 100644 index 3263a3708..000000000 --- a/applications/services/namechangersrv/application.fam +++ /dev/null @@ -1,7 +0,0 @@ -App( - appid="namechangersrv", - apptype=FlipperAppType.STARTUP, - entry_point="namechanger_on_system_start", - requires=["storage"], - order=1000, -) diff --git a/applications/services/namechangersrv/namechangersrv.c b/applications/services/namechangersrv/namechangersrv.c deleted file mode 100644 index 33aeb3fdd..000000000 --- a/applications/services/namechangersrv/namechangersrv.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "namechangersrv.h" -#include "m-string.h" -#include -#include - -void namechanger_on_system_start() { - if(!furi_hal_is_normal_boot()) { - FURI_LOG_W(TAG, "NameChangerSRV load skipped. Device is in special startup mode."); - } else { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* file = flipper_format_file_alloc(storage); - - FuriString* NAMEHEADER; - NAMEHEADER = furi_string_alloc_set("Flipper Name File"); - - bool result = false; - - FuriString* data; - data = furi_string_alloc(); - - do { - if(!flipper_format_file_open_existing(file, NAMECHANGER_PATH)) { - break; - } - - // header - uint32_t version; - - if(!flipper_format_read_header(file, data, &version)) { - break; - } - - if(furi_string_cmp_str(data, furi_string_get_cstr(NAMEHEADER)) != 0) { - break; - } - - if(version != 1) { - break; - } - - // get Name - if(!flipper_format_read_string(file, "Name", data)) { - break; - } - - result = true; - } while(false); - - flipper_format_free(file); - - if(!result) { - //file not good - write new one - FlipperFormat* file = flipper_format_file_alloc(storage); - - bool res = false; - - do { - // Open file for write - if(!flipper_format_file_open_always(file, NAMECHANGER_PATH)) { - break; - } - - // Write header - if(!flipper_format_write_header_cstr(file, furi_string_get_cstr(NAMEHEADER), 1)) { - break; - } - - // Write comments - if(!flipper_format_write_comment_cstr( - file, - "Changing the value below will change your FlipperZero device name.")) { - break; - } - - if(!flipper_format_write_comment_cstr( - file, - "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { - break; - } - - if(!flipper_format_write_comment_cstr( - file, "It can contain other characters but use at your own risk.")) { - break; - } - - //Write name - if(!flipper_format_write_string_cstr( - file, "Name", furi_hal_version_get_name_ptr())) { - break; - } - - res = true; - } while(false); - - flipper_format_free(file); - - if(!res) { - FURI_LOG_E(TAG, "Save failed."); - } - } else { - if(!furi_string_size(data)) { - //Empty file - get default name and write to file. - FlipperFormat* file = flipper_format_file_alloc(storage); - - bool res = false; - - do { - // Open file for write - if(!flipper_format_file_open_always(file, NAMECHANGER_PATH)) { - break; - } - - // Write header - if(!flipper_format_write_header_cstr( - file, furi_string_get_cstr(NAMEHEADER), 1)) { - break; - } - - // Write comments - if(!flipper_format_write_comment_cstr( - file, - "Changing the value below will change your FlipperZero device name.")) { - break; - } - - if(!flipper_format_write_comment_cstr( - file, - "Note: This is limited to 8 characters using the following: a-z, A-Z, 0-9, and _")) { - break; - } - - if(!flipper_format_write_comment_cstr( - file, "It cannot contain any other characters.")) { - break; - } - - //Write name - if(!flipper_format_write_string_cstr( - file, "Name", furi_hal_version_get_name_ptr())) { - break; - } - - res = true; - } while(false); - - flipper_format_free(file); - - if(!res) { - FURI_LOG_E(TAG, "Save failed."); - } - } else { - char newdata[9]; - snprintf(newdata, 9, "%s", furi_string_get_cstr(data)); - //set name from file - furi_hal_version_set_custom_name(newdata); - } - } - - furi_string_free(data); - - furi_record_close(RECORD_STORAGE); - } -} diff --git a/applications/services/namechangersrv/namechangersrv.h b/applications/services/namechangersrv/namechangersrv.h deleted file mode 100644 index d440b19bc..000000000 --- a/applications/services/namechangersrv/namechangersrv.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include - -#define NAMECHANGER_TEXT_STORE_SIZE 9 -#define NAMECHANGER_HEADER "Flipper Name File" -#define NAMECHANGER_PATH EXT_PATH("dolphin/name.txt") - -#define TAG "NameChangerSRV" diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c index a26d84ab3..409c51957 100644 --- a/applications/services/notification/notification_app.c +++ b/applications/services/notification/notification_app.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "notification.h" #include "notification_messages.h" @@ -36,7 +37,7 @@ void notification_message_save_settings(NotificationApp* app) { furi_event_flag_wait( m.back_event, NOTIFICATION_EVENT_COMPLETE, FuriFlagWaitAny, FuriWaitForever); furi_event_flag_free(m.back_event); -}; +} // internal layer void notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t layer_value) { @@ -336,7 +337,7 @@ void notification_process_notification_message( } notification_message_index++; notification_message = (*message->sequence)[notification_message_index]; - }; + } // send and do minimal delay if(led_active) { @@ -410,79 +411,23 @@ void notification_process_internal_message(NotificationApp* app, NotificationApp } } -static bool notification_load_settings(NotificationApp* app) { - NotificationSettings settings; - File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - const size_t settings_size = sizeof(NotificationSettings); - - FURI_LOG_I(TAG, "loading settings from \"%s\"", NOTIFICATION_SETTINGS_PATH); - bool fs_result = - storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING); - - if(fs_result) { - uint16_t bytes_count = storage_file_read(file, &settings, settings_size); - - if(bytes_count != settings_size) { - fs_result = false; - } - } - - if(fs_result) { - FURI_LOG_I(TAG, "load success"); - - if(settings.version != NOTIFICATION_SETTINGS_VERSION) { - FURI_LOG_E( - TAG, "version(%d != %d) mismatch", settings.version, NOTIFICATION_SETTINGS_VERSION); - } else { - furi_kernel_lock(); - memcpy(&app->settings, &settings, settings_size); - furi_kernel_unlock(); - } - } else { - FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file)); - } - - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - - return fs_result; -}; - static bool notification_save_settings(NotificationApp* app) { - NotificationSettings settings; - File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - const size_t settings_size = sizeof(NotificationSettings); + return saved_struct_save( + NOTIFICATION_SETTINGS_PATH, + &app->settings, + sizeof(NotificationSettings), + NOTIFICATION_SETTINGS_MAGIC, + NOTIFICATION_SETTINGS_VERSION); +} - FURI_LOG_I(TAG, "saving settings to \"%s\"", NOTIFICATION_SETTINGS_PATH); - - furi_kernel_lock(); - memcpy(&settings, &app->settings, settings_size); - furi_kernel_unlock(); - - bool fs_result = - storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS); - - if(fs_result) { - uint16_t bytes_count = storage_file_write(file, &settings, settings_size); - - if(bytes_count != settings_size) { - fs_result = false; - } - } - - if(fs_result) { - FURI_LOG_I(TAG, "save success"); - } else { - FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file)); - } - - storage_file_close(file); - storage_file_free(file); - furi_record_close(RECORD_STORAGE); - - return fs_result; -}; +static bool notification_load_settings(NotificationApp* app) { + return saved_struct_load( + NOTIFICATION_SETTINGS_PATH, + &app->settings, + sizeof(NotificationSettings), + NOTIFICATION_SETTINGS_MAGIC, + NOTIFICATION_SETTINGS_VERSION); +} static void input_event_callback(const void* value, void* context) { furi_assert(value); @@ -531,7 +476,7 @@ static NotificationApp* notification_app_alloc() { notification_message(app, &sequence_display_backlight_on); return app; -}; +} // App int32_t notification_srv(void* p) { diff --git a/applications/services/notification/notification_app.h b/applications/services/notification/notification_app.h index 88194bfbd..92a668ee9 100644 --- a/applications/services/notification/notification_app.h +++ b/applications/services/notification/notification_app.h @@ -2,7 +2,6 @@ #include #include "notification.h" #include "notification_messages.h" -#include "notification_settings_filename.h" #define NOTIFICATION_LED_COUNT 3 #define NOTIFICATION_EVENT_COMPLETE 0x00000001U @@ -33,7 +32,9 @@ typedef struct { } NotificationLedLayer; #define NOTIFICATION_SETTINGS_VERSION 0x01 -#define NOTIFICATION_SETTINGS_PATH INT_PATH(NOTIFICATION_SETTINGS_FILE_NAME) +#define NOTIFICATION_SETTINGS_MAGIC 0x16 +#define NOTIFICATION_SETTINGS_OLD_PATH INT_PATH(".notification.settings") +#define NOTIFICATION_SETTINGS_PATH CFG_PATH("notification.settings") typedef struct { uint8_t version; diff --git a/applications/services/notification/notification_app_api.c b/applications/services/notification/notification_app_api.c index 9bc06b013..9bcf5964f 100644 --- a/applications/services/notification/notification_app_api.c +++ b/applications/services/notification/notification_app_api.c @@ -8,13 +8,13 @@ void notification_message(NotificationApp* app, const NotificationSequence* sequ NotificationAppMessage m = { .type = NotificationLayerMessage, .sequence = sequence, .back_event = NULL}; furi_check(furi_message_queue_put(app->queue, &m, FuriWaitForever) == FuriStatusOk); -}; +} void notification_internal_message(NotificationApp* app, const NotificationSequence* sequence) { NotificationAppMessage m = { .type = InternalLayerMessage, .sequence = sequence, .back_event = NULL}; furi_check(furi_message_queue_put(app->queue, &m, FuriWaitForever) == FuriStatusOk); -}; +} void notification_message_block(NotificationApp* app, const NotificationSequence* sequence) { NotificationAppMessage m = { @@ -25,7 +25,7 @@ void notification_message_block(NotificationApp* app, const NotificationSequence furi_event_flag_wait( m.back_event, NOTIFICATION_EVENT_COMPLETE, FuriFlagWaitAny, FuriWaitForever); furi_event_flag_free(m.back_event); -}; +} void notification_internal_message_block( NotificationApp* app, @@ -36,4 +36,4 @@ void notification_internal_message_block( furi_event_flag_wait( m.back_event, NOTIFICATION_EVENT_COMPLETE, FuriFlagWaitAny, FuriWaitForever); furi_event_flag_free(m.back_event); -}; +} diff --git a/applications/services/notification/notification_settings_filename.h b/applications/services/notification/notification_settings_filename.h deleted file mode 100644 index d9ed596ec..000000000 --- a/applications/services/notification/notification_settings_filename.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define NOTIFICATION_SETTINGS_FILE_NAME ".notification.settings" diff --git a/applications/services/power/power_settings.c b/applications/services/power/power_settings.c index cd456a5a8..b98c382c0 100644 --- a/applications/services/power/power_settings.c +++ b/applications/services/power/power_settings.c @@ -6,17 +6,6 @@ bool SAVE_POWER_SETTINGS(uint32_t* x) { } bool LOAD_POWER_SETTINGS(uint32_t* x) { - bool ret = saved_struct_load( + return saved_struct_load( POWER_SETTINGS_PATH, x, sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER); - - if(!ret) { - Storage* storage = furi_record_open(RECORD_STORAGE); - storage_common_copy(storage, POWER_SETTINGS_OLD_PATH, POWER_SETTINGS_PATH); - storage_common_remove(storage, POWER_SETTINGS_OLD_PATH); - furi_record_close(RECORD_STORAGE); - ret = saved_struct_load( - POWER_SETTINGS_PATH, x, sizeof(uint32_t), POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER); - } - - return ret; } diff --git a/applications/services/rgb_backlight/application.fam b/applications/services/rgb_backlight/application.fam deleted file mode 100644 index 70fc0dc9a..000000000 --- a/applications/services/rgb_backlight/application.fam +++ /dev/null @@ -1,9 +0,0 @@ -App( - appid="rgb_backlight", - name="RGB Backlight", - apptype=FlipperAppType.SERVICE, - entry_point="rgb_backlight_srv", - sdk_headers=[ - "rgb_backlight.h", - ], -) diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index 62428d79d..3b8cd5f23 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -57,6 +57,10 @@ static RpcSystemCallbacks rpc_systems[] = { .alloc = rpc_system_property_alloc, .free = NULL, }, + { + .alloc = rpc_desktop_alloc, + .free = rpc_desktop_free, + }, }; struct RpcSession { @@ -326,31 +330,35 @@ static int32_t rpc_session_worker(void* context) { return 0; } -static void rpc_session_free_callback(FuriThreadState thread_state, void* context) { - furi_assert(context); - +static void rpc_session_thread_pending_callback(void* context, uint32_t arg) { + UNUSED(arg); RpcSession* session = (RpcSession*)context; + for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) { + if(rpc_systems[i].free) { + (rpc_systems[i].free)(session->system_contexts[i]); + } + } + free(session->system_contexts); + free(session->decoded_message); + RpcHandlerDict_clear(session->handlers); + furi_stream_buffer_free(session->stream); + + furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever); + if(session->terminated_callback) { + session->terminated_callback(session->context); + } + furi_mutex_release(session->callbacks_mutex); + + furi_mutex_free(session->callbacks_mutex); + furi_thread_join(session->thread); + furi_thread_free(session->thread); + free(session); +} + +static void rpc_session_thread_state_callback(FuriThreadState thread_state, void* context) { if(thread_state == FuriThreadStateStopped) { - for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) { - if(rpc_systems[i].free) { - rpc_systems[i].free(session->system_contexts[i]); - } - } - free(session->system_contexts); - free(session->decoded_message); - RpcHandlerDict_clear(session->handlers); - furi_stream_buffer_free(session->stream); - - furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever); - if(session->terminated_callback) { - session->terminated_callback(session->context); - } - furi_mutex_release(session->callbacks_mutex); - - furi_mutex_free(session->callbacks_mutex); - furi_thread_free(session->thread); - free(session); + furi_timer_pending_callback(rpc_session_thread_pending_callback, context, 0); } } @@ -385,7 +393,7 @@ RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) { session->thread = furi_thread_alloc_ex("RpcSessionWorker", 3072, rpc_session_worker, session); furi_thread_set_state_context(session->thread, session); - furi_thread_set_state_callback(session->thread, rpc_session_free_callback); + furi_thread_set_state_callback(session->thread, rpc_session_thread_state_callback); furi_thread_start(session->thread); diff --git a/applications/services/rpc/rpc_desktop.c b/applications/services/rpc/rpc_desktop.c new file mode 100644 index 000000000..dbf9796ec --- /dev/null +++ b/applications/services/rpc/rpc_desktop.c @@ -0,0 +1,73 @@ +#include "flipper.pb.h" +#include "rpc_i.h" +#include +#include "desktop.pb.h" + +#define TAG "RpcDesktop" + +typedef struct { + RpcSession* session; + Desktop* desktop; +} RpcDesktop; + +static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_is_locked_request_tag); + + FURI_LOG_D(TAG, "IsLockedRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + PB_CommandStatus ret = desktop_api_is_locked(rpc_desktop->desktop) ? PB_CommandStatus_OK : + PB_CommandStatus_ERROR; + + rpc_send_and_release_empty(session, request->command_id, ret); +} + +static void rpc_desktop_on_unlock_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_unlock_request_tag); + + FURI_LOG_D(TAG, "UnlockRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + desktop_api_unlock(rpc_desktop->desktop); + + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); +} + +void* rpc_desktop_alloc(RpcSession* session) { + furi_assert(session); + + RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop)); + rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP); + rpc_desktop->session = session; + + RpcHandler rpc_handler = { + .message_handler = NULL, + .decode_submessage = NULL, + .context = rpc_desktop, + }; + + rpc_handler.message_handler = rpc_desktop_on_is_locked_request; + rpc_add_handler(session, PB_Main_desktop_is_locked_request_tag, &rpc_handler); + + rpc_handler.message_handler = rpc_desktop_on_unlock_request; + rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler); + + return rpc_desktop; +} + +void rpc_desktop_free(void* context) { + furi_assert(context); + RpcDesktop* rpc_desktop = context; + + furi_assert(rpc_desktop->desktop); + furi_record_close(RECORD_DESKTOP); + + rpc_desktop->session = NULL; + free(rpc_desktop); +} \ No newline at end of file diff --git a/applications/services/rpc/rpc_i.h b/applications/services/rpc/rpc_i.h index 91a176da8..16e5e594d 100644 --- a/applications/services/rpc/rpc_i.h +++ b/applications/services/rpc/rpc_i.h @@ -36,6 +36,9 @@ void* rpc_system_gpio_alloc(RpcSession* session); void rpc_system_gpio_free(void* ctx); void* rpc_system_property_alloc(RpcSession* session); +void* rpc_desktop_alloc(RpcSession* session); +void rpc_desktop_free(void* ctx); + void rpc_debug_print_message(const PB_Main* message); void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size); diff --git a/applications/services/storage/application.fam b/applications/services/storage/application.fam index 7b106e00f..260609c5c 100644 --- a/applications/services/storage/application.fam +++ b/applications/services/storage/application.fam @@ -7,7 +7,7 @@ App( requires=["storage_settings"], provides=["storage_start"], stack_size=3 * 1024, - order=44, + order=10, sdk_headers=["storage.h"], ) diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index 1816bf921..f746196c2 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -54,10 +54,6 @@ Storage* storage_app_alloc() { view_port_draw_callback_set(app->sd_gui.view_port, storage_app_sd_icon_draw_callback, app); view_port_enabled_set(app->sd_gui.view_port, false); - Gui* gui = furi_record_open(RECORD_GUI); - gui_add_view_port(gui, app->sd_gui.view_port, GuiLayerStatusBarLeft); - furi_record_close(RECORD_GUI); - return app; } diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index 8e2dcdbbb..d720de9d1 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -33,7 +33,7 @@ static void storage_cli_print_usage() { printf("\tmd5\t - md5 hash of the file\r\n"); printf("\tstat\t - info about file or dir\r\n"); printf("\ttimestamp\t - last modification timestamp\r\n"); -}; +} static void storage_cli_print_error(FS_Error error) { printf("Storage error: %s\r\n", storage_error_get_desc(error)); @@ -86,7 +86,7 @@ static void storage_cli_info(Cli* cli, FuriString* path) { } furi_record_close(RECORD_STORAGE); -}; +} static void storage_cli_format(Cli* cli, FuriString* path) { if(furi_string_cmp_str(path, STORAGE_INT_PATH_PREFIX) == 0) { @@ -112,7 +112,7 @@ static void storage_cli_format(Cli* cli, FuriString* path) { } else { storage_cli_print_usage(); } -}; +} static void storage_cli_list(Cli* cli, FuriString* path) { UNUSED(cli); diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index ffc3da4bc..bf474bc9d 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -803,6 +803,7 @@ void storage_file_free(File* file) { } FuriPubSub* storage_get_pubsub(Storage* storage) { + furi_assert(storage); return storage->pubsub; } diff --git a/applications/services/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c index d802d6e9f..15a355dc2 100644 --- a/applications/services/storage/storages/storage_ext.c +++ b/applications/services/storage/storages/storage_ext.c @@ -337,6 +337,7 @@ static bool storage_ext_file_close(void* ctx, File* file) { file->internal_error_id = f_close(file_data); file->error_id = storage_ext_parse_error(file->internal_error_id); free(file_data); + storage_set_storage_file_data(file, NULL, storage); return (file->error_id == FSE_OK); } diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c index c1cf2c7de..8a2fef53b 100644 --- a/applications/services/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -160,7 +160,7 @@ static LFSData* storage_int_lfs_data_alloc() { lfs_data->config.lookahead_size = 16; return lfs_data; -}; +} // Returns true if fingerprint was invalid and LFS reformatting is needed static bool storage_int_check_and_set_fingerprint(LFSData* lfs_data) { @@ -194,41 +194,30 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { if(need_format) { // Backup U2F keys - lfs_file_t file; - uint8_t* cnt = NULL; - uint32_t cnt_size; - uint8_t* key = NULL; - uint32_t key_size; - if(lfs_mount(lfs, &lfs_data->config) == 0) { - FURI_LOG_I(TAG, "Factory reset: Mounted for backup"); + // lfs_file_t file; + // uint8_t* key = NULL; + // uint32_t key_size; + // if(lfs_mount(lfs, &lfs_data->config) == 0) { + // FURI_LOG_I(TAG, "Factory reset: Mounted for backup"); - if(lfs_file_open(lfs, &file, ".cnt.u2f", LFS_O_RDONLY) == 0) { - cnt_size = file.ctz.size; - cnt = malloc(cnt_size); - if(lfs_file_read(lfs, &file, cnt, cnt_size) != (int32_t)cnt_size) { - free(cnt); - cnt = NULL; - } - lfs_file_close(lfs, &file); - if(lfs_file_open(lfs, &file, ".key.u2f", LFS_O_RDONLY) == 0) { - key_size = file.ctz.size; - key = malloc(key_size); - if(lfs_file_read(lfs, &file, key, key_size) != (int32_t)key_size) { - free(key); - key = NULL; - } - lfs_file_close(lfs, &file); - } - } + // if(lfs_file_open(lfs, &file, ".key.u2f", LFS_O_RDONLY) == 0) { + // key_size = file.ctz.size; + // key = malloc(key_size); + // if(lfs_file_read(lfs, &file, key, key_size) != (int32_t)key_size) { + // free(key); + // key = NULL; + // } + // lfs_file_close(lfs, &file); + // } - if(lfs_unmount(lfs) == 0) { - FURI_LOG_E(TAG, "Factory reset: Unmounted after backup"); - } else { - FURI_LOG_E(TAG, "Factory reset: Unmount after backup failed"); - } - } else { - FURI_LOG_E(TAG, "Factory reset: Mount for backup failed"); - } + // if(lfs_unmount(lfs) == 0) { + // FURI_LOG_E(TAG, "Factory reset: Unmounted after backup"); + // } else { + // FURI_LOG_E(TAG, "Factory reset: Unmount after backup failed"); + // } + // } else { + // FURI_LOG_E(TAG, "Factory reset: Mount for backup failed"); + // } // Format storage if(lfs_format(lfs, &lfs_data->config) == 0) { @@ -239,19 +228,12 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { storage->status = StorageStatusOK; // Restore U2F keys - if(cnt != NULL && key != NULL) { - if(lfs_file_open(lfs, &file, ".cnt.u2f", LFS_O_WRONLY | LFS_O_CREAT) == 0) { - lfs_file_write(lfs, &file, cnt, cnt_size); - lfs_file_close(lfs, &file); - if(lfs_file_open(lfs, &file, ".key.u2f", LFS_O_WRONLY | LFS_O_CREAT) == - 0) { - lfs_file_write(lfs, &file, key, key_size); - lfs_file_close(lfs, &file); - } - } - } - if(cnt != NULL) free(cnt); - if(key != NULL) free(key); + // if(key != NULL) { + // if(lfs_file_open(lfs, &file, ".key.u2f", LFS_O_WRONLY | LFS_O_CREAT) == 0) { + // lfs_file_write(lfs, &file, key, key_size); + // lfs_file_close(lfs, &file); + // } + // } } else { FURI_LOG_E(TAG, "Factory reset: Mount after format failed"); storage->status = StorageStatusNotMounted; @@ -260,6 +242,7 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { FURI_LOG_E(TAG, "Factory reset: Format failed"); storage->status = StorageStatusNoFS; } + // if(key != NULL) free(key); } else { // Normal err = lfs_mount(lfs, &lfs_data->config); diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 20263e887..2d38d930a 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -7,6 +7,7 @@ #include #include #include +#include int screen_index; @@ -98,13 +99,12 @@ static DialogMessageButton hw_version_screen(DialogsApp* dialogs, DialogMessage* furi_string_cat_printf( buffer, - "%d.F%dB%dC%d %s:%s %s\n", + "%d.F%dB%dC%d %s %s\n", furi_hal_version_get_hw_version(), furi_hal_version_get_hw_target(), furi_hal_version_get_hw_body(), furi_hal_version_get_hw_connect(), furi_hal_version_get_hw_region_name_otp(), - furi_hal_region_get_name(), my_name ? my_name : "Unknown"); furi_string_cat_printf(buffer, "Serial Number:\n"); @@ -136,14 +136,17 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* if(!ver) { //-V1051 furi_string_cat_printf(buffer, "No info\n"); } else { + uint16_t api_major, api_minor; + furi_hal_info_get_api_version(&api_major, &api_minor); furi_string_cat_printf( buffer, - "%s [%s]\n%s%s [%s] %s\n[%d] %s", + "%s [%s]\n%s%s [%d.%d] %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), + api_major, + api_minor, c2_ver ? c2_ver->StackTypeString : "", version_get_target(ver), version_get_gitbranch(ver)); @@ -179,7 +182,7 @@ static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) canvas_draw_box(canvas, x - 4, y + 16, 24, 6); canvas_set_color(canvas, ColorBlack); canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); -}; +} static void draw_battery(Canvas* canvas, PowerInfo* info, int x, int y) { char header[20] = {}; @@ -212,7 +215,9 @@ static void draw_battery(Canvas* canvas, PowerInfo* info, int x, int y) { (uint32_t)(info->voltage_vbus), (uint32_t)(info->voltage_vbus * 10) % 10, current); - } else if(current < 0) { + } else if(current < -5) { + // Often gauge reports anything in the range 1~5ma as 5ma + // That brings confusion, so we'll treat it as Napping snprintf(header, sizeof(header), "%s", "Consumption is"); snprintf( value, @@ -245,7 +250,7 @@ static void draw_battery(Canvas* canvas, PowerInfo* info, int x, int y) { canvas_draw_str_aligned(canvas, x + 92, y + 9, AlignCenter, AlignCenter, header); canvas_draw_str_aligned(canvas, x + 92, y + 19, AlignCenter, AlignCenter, value); } -}; +} static void battery_info_draw_callback(Canvas* canvas, void* context) { furi_assert(context); diff --git a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c index 00ddca333..ff5989245 100644 --- a/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c +++ b/applications/settings/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c @@ -1,6 +1,7 @@ #include "../bt_settings_app.h" #include -#include +#include +#include void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) { furi_assert(context); @@ -30,11 +31,15 @@ bool bt_settings_scene_forget_dev_confirm_on_event(void* context, SceneManagerEv if(event.event == DialogExResultLeft) { consumed = scene_manager_previous_scene(app->scene_manager); } else if(event.event == DialogExResultRight) { - bt_forget_bonded_devices(app->bt); - // also removes keys of badkb bonded devices - bt_keys_storage_set_storage_path(app->bt, BAD_KB_APP_PATH_BOUND_KEYS_FILE); - bt_forget_bonded_devices(app->bt); bt_keys_storage_set_default_path(app->bt); + bt_forget_bonded_devices(app->bt); + + // also remove keys of badkb and bt remote + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_simply_remove(storage, BAD_KB_KEYS_PATH); + storage_simply_remove( + storage, EXT_PATH("apps_data/hid_ble/") HID_BT_KEYS_STORAGE_NAME); + furi_record_close(RECORD_STORAGE); scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevSuccess); consumed = true; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c index a5a76354c..f153aac7a 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include "../desktop_settings_app.h" #include #include @@ -18,7 +18,7 @@ static void pin_auth_done_callback(const PinCode* pin_code, void* context) { DesktopSettingsApp* app = context; app->pincode_buffer = *pin_code; - if(desktop_pins_are_equal(&app->settings.pin_code, pin_code)) { + if(desktop_pin_compare(&app->settings.pin_code, pin_code)) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); } else { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c index f813525e6..dbb69c1b9 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_error.c @@ -6,7 +6,7 @@ #include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include +#include #include "../desktop_settings_app.h" #define SCENE_EVENT_EXIT (0U) diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c index 6befe5f9d..1ea212fd9 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup.c @@ -7,7 +7,7 @@ #include #include "desktop_settings_scene.h" #include "desktop_settings_scene_i.h" -#include +#include #define SCENE_EVENT_EXIT (0U) #define SCENE_EVENT_1ST_PIN_ENTERED (1U) @@ -25,7 +25,7 @@ static void pin_setup_done_callback(const PinCode* pin_code, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_1ST_PIN_ENTERED); } else { app->pincode_buffer_filled = false; - if(desktop_pins_are_equal(&app->pincode_buffer, pin_code)) { + if(desktop_pin_compare(&app->pincode_buffer, pin_code)) { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_EQUAL); } else { view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_PINS_DIFFERENT); diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index 0956cae4f..9ffb0d22b 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -18,7 +18,7 @@ static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) canvas_draw_box(canvas, x - 4, y + 16, 24, 6); canvas_set_color(canvas, ColorBlack); canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val); -}; +} static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { char emote[20] = {}; @@ -53,7 +53,9 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { (uint32_t)(data->vbus_voltage), (uint32_t)(data->vbus_voltage * 10) % 10, current); - } else if(current < 0) { + } else if(current < -5) { + // Often gauge reports anything in the range 1~5ma as 5ma + // That brings confusion, so we'll treat it as Napping snprintf( emote, sizeof(emote), @@ -87,7 +89,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header); canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value); -}; +} static void battery_info_draw_callback(Canvas* canvas, void* context) { furi_assert(context); diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index 655541be5..68a895004 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -43,7 +43,6 @@ static void debug_changed(VariableItem* item) { } else { furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); } - loader_update_menu(); } const char* const heap_trace_mode_text[] = { diff --git a/applications/system/updater/application.fam b/applications/system/updater/application.fam index ae6914eb7..b3f6603da 100644 --- a/applications/system/updater/application.fam +++ b/applications/system/updater/application.fam @@ -6,12 +6,12 @@ App( requires=[ "gui", "storage", - "rgb_backlight", + "archive", ], conflicts=["desktop"], entry_point="updater_srv", stack_size=2 * 1024, - order=130, + order=120, ) App( @@ -23,6 +23,7 @@ App( "gui", "storage", "bt", + "archive", ], conflicts=["updater"], provides=["updater_start"], diff --git a/applications/system/updater/cli/updater_cli.c b/applications/system/updater/cli/updater_cli.c index 2bf6dab26..659c431f7 100644 --- a/applications/system/updater/cli/updater_cli.c +++ b/applications/system/updater/cli/updater_cli.c @@ -85,22 +85,10 @@ static void updater_cli_ep(Cli* cli, FuriString* args, void* context) { updater_cli_help(args); } -static int32_t updater_spawner_thread_worker(void* arg) { +static void updater_start_app(void* context, uint32_t arg) { + UNUSED(context); UNUSED(arg); - Loader* loader = furi_record_open(RECORD_LOADER); - loader_start(loader, "UpdaterApp", NULL); - furi_record_close(RECORD_LOADER); - return 0; -} -static void updater_spawner_thread_cleanup(FuriThreadState state, void* context) { - FuriThread* thread = context; - if(state == FuriThreadStateStopped) { - furi_thread_free(thread); - } -} - -static void updater_start_app() { FuriHalRtcBootMode mode = furi_hal_rtc_get_boot_mode(); if((mode != FuriHalRtcBootModePreUpdate) && (mode != FuriHalRtcBootModePostUpdate)) { return; @@ -110,11 +98,9 @@ static void updater_start_app() { * inside loader process, at startup. * So, accessing its record would cause a deadlock */ - FuriThread* thread = - furi_thread_alloc_ex("UpdateAppSpawner", 768, updater_spawner_thread_worker, NULL); - furi_thread_set_state_callback(thread, updater_spawner_thread_cleanup); - furi_thread_set_state_context(thread, thread); - furi_thread_start(thread); + Loader* loader = furi_record_open(RECORD_LOADER); + loader_start(loader, "UpdaterApp", NULL); + furi_record_close(RECORD_LOADER); } void updater_on_system_start() { @@ -126,7 +112,7 @@ void updater_on_system_start() { UNUSED(updater_cli_ep); #endif #ifndef FURI_RAM_EXEC - updater_start_app(); + furi_timer_pending_callback(updater_start_app, NULL, 0); #else UNUSED(updater_start_app); #endif diff --git a/applications/system/updater/updater.c b/applications/system/updater/updater.c index e749f3ce6..59af8a3b0 100644 --- a/applications/system/updater/updater.c +++ b/applications/system/updater/updater.c @@ -7,6 +7,7 @@ #include #include #include +#include static bool updater_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -32,8 +33,9 @@ static void updater_main_model_set_state(main_view, message, progress, failed); } -Updater* updater_alloc(const char* arg) { +Updater* updater_alloc(char* arg) { Updater* updater = malloc(sizeof(Updater)); + process_favorite_launch(&arg); if(arg && strlen(arg)) { updater->startup_arg = furi_string_alloc_set(arg); furi_string_replace(updater->startup_arg, ANY_PATH(""), EXT_PATH("")); @@ -118,10 +120,8 @@ void updater_free(Updater* updater) { free(updater); } -int32_t updater_srv(void* p) { - const char* cfgpath = p; - - Updater* updater = updater_alloc(cfgpath); +int32_t updater_srv(char* p) { + Updater* updater = updater_alloc(p); view_dispatcher_run(updater->view_dispatcher); updater_free(updater); diff --git a/applications/system/updater/updater_i.h b/applications/system/updater/updater_i.h index 4e3c704d2..4940eb60e 100644 --- a/applications/system/updater/updater_i.h +++ b/applications/system/updater/updater_i.h @@ -52,7 +52,7 @@ typedef struct { int32_t idle_ticks; } Updater; -Updater* updater_alloc(const char* arg); +Updater* updater_alloc(char* arg); void updater_free(Updater* updater); diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index 63024ced9..5d2477464 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -346,7 +346,11 @@ int32_t update_task_worker_flash_writer(void* context) { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePostUpdate); // Format LFS before restoring backup on next boot furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); - +#ifdef FURI_NDEBUG + // Production + furi_hal_rtc_set_log_level(FuriLogLevelDefault); + furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug); +#endif update_task_set_progress(update_task, UpdateTaskStageCompleted, 100); success = true; } while(false); diff --git a/assets/SConscript b/assets/SConscript index 21437aa30..9bd273626 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -1,7 +1,7 @@ -Import("env") - from fbt.version import get_git_commit_unix_timestamp +Import("env") + assetsenv = env.Clone( tools=["fbt_assets"], FW_LIB_NAME="assets", diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_0.png b/assets/dolphin/external/L3_Sunflower_128x64/frame_0.png deleted file mode 100644 index 023da26d5..000000000 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_0.png and /dev/null differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_3.png b/assets/dolphin/external/L3_Sunflower_128x64/frame_3.png deleted file mode 100644 index f86f35cec..000000000 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_3.png and /dev/null differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_4.png b/assets/dolphin/external/L3_Sunflower_128x64/frame_4.png deleted file mode 100644 index b86eba07d..000000000 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_4.png and /dev/null differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/frame_6.png b/assets/dolphin/external/L3_Sunflower_128x64/frame_6.png deleted file mode 100644 index aaaa2a5cd..000000000 Binary files a/assets/dolphin/external/L3_Sunflower_128x64/frame_6.png and /dev/null differ diff --git a/assets/dolphin/external/L3_Sunflower_128x64/meta.txt b/assets/dolphin/external/L3_Sunflower_128x64/meta.txt deleted file mode 100644 index f93fdaae7..000000000 --- a/assets/dolphin/external/L3_Sunflower_128x64/meta.txt +++ /dev/null @@ -1,14 +0,0 @@ -Filetype: Flipper Animation -Version: 1 - -Width: 128 -Height: 64 -Passive frames: 16 -Active frames: 0 -Frames order: 0 1 2 3 4 5 5 5 6 6 6 6 6 6 3 3 -Active cycles: 0 -Frame rate: 1 -Duration: 360 -Active cooldown: 0 - -Bubble slots: 0 diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 52cc88a7e..f9303a6ff 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -133,10 +133,3 @@ Max butthurt: 10 Min level: 27 Max level: 30 Weight: 3 - -Name: L3_Sunflower_128x64 -Min butthurt: 0 -Max butthurt: 14 -Min level: 1 -Max level: 30 -Weight: 0 diff --git a/assets/protobuf b/assets/protobuf index 1f6b4a08c..a13c5ddd0 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit 1f6b4a08c5d05c2b17926a3ba79f60109638932f +Subproject commit a13c5ddd0397511bd4c6de4afdd1031a5b6f5bca diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index 49a4acd20..777d5399c 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 14th Apr, 2023 -# Last Checked 25th Apr, 2023 +# Last Updated 2nd May, 2023 +# Last Checked 2nd May, 2023 # name: POWER type: raw @@ -1740,3 +1740,33 @@ type: parsed protocol: NEC address: 04 00 00 00 command: 00 00 00 00 +# +name: TEMP+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 443 457 418 451 424 445 420 449 416 453 422 25403 3487 1758 421 1325 416 445 420 452 423 446 419 1319 422 447 418 450 415 456 419 449 416 1323 418 454 421 1316 414 1326 415 462 424 1307 423 1315 415 1323 418 1322 419 1321 420 449 416 452 423 1316 414 455 420 448 417 453 422 447 418 452 423 448 417 451 424 443 422 450 415 452 423 445 420 450 415 456 419 450 415 452 423 447 418 450 415 456 419 1318 423 447 418 454 421 445 420 450 415 453 422 446 419 451 424 1315 415 1324 417 454 421 446 419 1321 420 1319 422 448 417 452 423 445 420 449 416 453 422 448 417 452 423 445 420 449 416 455 420 1319 422 1314 416 1325 416 1322 419 1322 419 1318 423 1317 424 447 418 1320 421 1317 424 1317 424 1315 415 455 420 449 416 452 423 447 418 451 414 454 421 448 417 453 422 448 417 452 423 444 421 449 416 452 423 447 418 453 422 445 420 450 415 456 419 448 417 453 422 446 419 450 415 455 420 450 415 453 422 448 417 452 423 444 421 448 417 454 421 446 419 452 423 445 420 450 415 453 422 447 418 451 424 446 419 449 416 454 421 447 418 452 423 446 419 452 423 1315 415 451 424 1316 414 456 419 451 414 453 422 1317 424 1316 425 444 421 447 418 452 423 448 417 450 415 455 420 456 419 449 416 446 419 451 414 455 420 1320 421 447 418 452 423 453 422 439 415 1324 417 459 416 446 419 451 424 446 419 1320 421 446 419 1319 422 +# +name: TEMP- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 444 455 420 449 416 454 421 448 417 451 424 25402 3487 1758 421 1317 424 445 420 452 423 443 422 1317 424 447 418 451 424 447 418 449 416 1324 417 452 423 1315 415 1324 417 452 423 1316 425 1315 415 1325 416 1323 418 1319 422 449 416 452 423 1318 423 445 420 448 417 453 422 447 418 452 423 446 419 449 416 455 420 447 418 453 422 446 419 452 423 446 419 451 424 444 421 447 418 451 424 445 420 1320 421 448 417 454 421 445 420 452 423 445 420 450 415 454 421 1316 414 1324 417 454 421 448 417 1321 420 1320 421 448 417 453 422 446 419 452 423 446 419 449 416 455 420 448 417 451 424 445 420 1321 420 1319 422 1316 414 1324 417 1324 417 1321 420 1320 421 449 416 1323 418 1323 418 1319 422 1317 424 446 419 453 422 445 420 450 415 453 422 448 417 452 423 447 418 450 415 455 420 448 417 454 421 445 420 451 414 455 420 449 416 454 421 448 417 452 423 446 419 449 416 454 421 447 418 452 423 445 420 450 415 454 421 450 415 454 421 447 418 452 423 444 421 451 424 442 423 449 416 451 424 445 420 450 415 455 420 448 417 454 421 447 418 450 415 457 418 1317 424 448 417 1320 421 448 417 453 422 449 416 1321 420 1320 421 448 417 452 423 449 416 451 424 446 419 448 417 454 421 449 416 452 423 447 418 452 423 1315 415 452 423 447 418 451 424 446 419 1319 422 448 417 451 424 446 419 449 416 1324 417 453 422 1316 414 +# SWING_HORIZONTAL +name: SWING +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 446 455 420 449 416 461 393 467 419 454 421 25402 3484 1759 419 1319 422 449 416 454 421 447 418 1322 419 449 416 454 421 449 416 452 423 1317 424 444 421 1321 420 1316 425 446 419 1329 422 1308 422 1318 422 1317 424 1314 416 453 422 447 418 1323 418 451 424 444 421 448 417 454 421 449 416 458 417 444 421 449 416 454 421 447 418 453 422 446 419 456 419 445 420 448 417 452 423 446 419 451 424 1316 414 453 422 447 418 453 422 446 419 451 414 455 420 449 416 1324 417 1321 420 452 423 444 421 1318 423 1317 423 445 420 450 415 455 420 447 418 455 420 447 418 451 424 445 420 456 419 444 421 1317 424 1316 424 1315 415 1323 417 452 423 1316 414 456 419 1318 423 448 417 452 423 444 421 450 415 456 419 448 417 453 422 447 418 450 415 454 421 448 417 454 421 446 419 452 423 446 419 449 416 455 420 448 417 452 423 448 417 451 424 451 424 445 420 444 421 447 418 460 415 446 419 451 424 446 419 450 415 454 421 449 416 1321 420 451 424 444 421 449 416 453 422 447 418 454 421 445 420 449 416 456 419 449 416 452 423 447 418 451 424 444 421 451 424 1314 416 453 422 1324 417 445 420 449 416 453 422 1319 422 1315 415 455 420 448 417 452 423 453 422 442 423 451 424 439 415 454 421 447 418 451 424 447 418 1322 418 451 424 442 423 448 417 451 424 1317 423 1315 415 454 421 449 416 460 415 446 419 1320 421 1319 422 +# OFF +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 445 455 421 449 416 453 422 447 418 451 424 25400 3494 1753 416 1322 419 450 415 456 420 449 416 1325 416 451 425 444 421 448 417 453 423 1318 423 444 421 1320 421 1316 414 457 419 1320 421 1318 423 1314 417 1322 419 1320 421 449 416 453 422 1317 424 445 420 450 415 456 419 447 418 451 414 456 420 449 416 452 424 448 417 453 422 445 420 450 415 456 419 448 417 452 423 447 418 449 416 453 423 448 417 453 423 446 419 449 416 453 423 447 418 1321 420 451 414 454 422 449 416 1322 419 1319 422 449 416 1322 419 451 424 445 420 449 416 455 421 445 420 449 416 455 420 448 417 452 424 446 419 1321 420 1317 424 1315 416 1324 417 1322 419 1320 421 1320 421 446 419 1319 422 1319 422 1318 423 1313 417 453 423 445 420 450 415 454 421 449 416 454 422 446 419 449 416 456 420 448 417 453 423 444 421 450 415 454 422 447 418 451 424 445 420 450 415 455 420 447 418 452 424 447 418 451 424 445 420 448 417 453 423 446 419 451 424 444 421 448 417 452 423 446 419 451 424 445 420 448 417 451 414 456 420 452 424 443 422 449 416 451 424 448 417 449 416 455 420 1318 423 446 419 1319 422 448 417 451 424 447 418 1320 421 1316 415 455 421 451 414 455 421 449 416 451 424 446 419 1319 422 448 417 454 422 446 419 451 414 1325 416 452 423 447 418 451 424 447 418 1318 423 446 419 449 416 1327 424 1312 419 449 416 455 421 449 416 +# OFF +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 645 17766 3059 8884 533 461 557 1427 560 435 584 433 534 458 534 458 534 458 588 404 587 405 586 1399 586 407 584 408 558 1429 555 1457 502 491 525 1460 528 1458 554 1431 554 1431 555 1431 554 438 555 438 554 439 553 440 553 464 528 464 528 464 529 465 528 465 526 467 526 467 527 465 553 439 554 439 554 438 554 439 554 439 553 439 554 439 553 439 553 439 554 440 552 464 528 464 528 465 528 466 527 466 501 492 525 468 526 466 527 466 553 439 554 439 553 440 552 1433 553 1433 553 2936 3024 8893 552 1458 527 465 528 465 527 467 526 467 500 493 524 468 526 467 526 467 552 1434 552 441 552 441 552 1435 550 465 528 1458 527 1458 528 1459 527 1485 501 1485 500 1486 501 491 527 466 528 465 528 465 527 465 528 465 527 465 528 465 528 465 527 465 528 465 527 466 527 466 527 492 500 492 501 492 500 493 500 493 500 492 526 466 527 465 527 465 527 465 527 466 527 466 527 466 527 465 527 466 526 466 527 466 526 467 526 493 499 493 474 518 499 494 500 493 526 2936 3025 8918 526 1459 527 466 527 466 527 466 526 466 527 466 526 467 526 467 525 467 526 1460 525 493 499 493 498 495 498 495 499 493 500 493 525 1460 527 1460 525 1460 526 1460 525 1460 526 1460 526 468 525 1487 499 1487 497 495 498 495 499 493 500 1486 525 1460 525 1460 525 467 525 467 526 467 525 467 526 468 524 1462 524 468 524 494 498 1488 497 1488 499 494 499 493 525 468 525 1461 524 468 525 468 524 468 525 468 525 468 524 468 525 469 524 494 498 494 499 1488 473 1514 524 diff --git a/assets/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index f6183ed86..ce6d0a7aa 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 14th Apr, 2023 -# Last Checked 25th Apr, 2023 +# Last Checked 2nd May, 2023 # name: POWER type: parsed diff --git a/assets/resources/infrared/assets/fans.ir b/assets/resources/infrared/assets/fans.ir index 6bef11b34..e422bdce4 100644 --- a/assets/resources/infrared/assets/fans.ir +++ b/assets/resources/infrared/assets/fans.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 14th Apr, 2023 -# Last Checked 25th Apr, 2023 +# Last Updated 2nd May, 2023 +# Last Checked 2nd May, 2023 # name: POWER type: raw @@ -1497,3 +1497,9 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3534 3439 954 2505 985 2535 955 798 954 2535 899 2591 899 2599 899 853 925 2566 924 2567 922 2596 894 2596 894 867 894 859 894 860 893 2597 894 859 894 859 894 867 894 2597 893 859 894 859 894 860 893 859 894 2605 894 40336 3531 3469 894 2597 893 2597 893 859 894 2597 893 2597 893 2605 893 860 893 2597 893 2597 893 2597 894 2597 893 868 893 860 893 860 893 2597 893 860 893 860 893 868 893 2597 893 860 893 860 893 860 893 860 893 2605 893 +# +name: POWER +type: parsed +protocol: NEC +address: 80 00 00 00 +command: 1A 00 00 00 diff --git a/assets/resources/infrared/assets/projectors.ir b/assets/resources/infrared/assets/projectors.ir index 00e331bd4..8e81a25bd 100644 --- a/assets/resources/infrared/assets/projectors.ir +++ b/assets/resources/infrared/assets/projectors.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 14th Apr, 2023 -# Last Checked 25th Apr, 2023 +# Last Updated 2nd May, 2023 +# Last Checked 2nd May, 2023 # # ON name: POWER @@ -886,3 +886,27 @@ type: parsed protocol: NECext address: 84 F4 00 00 command: 2F D0 00 00 +# +name: MUTE +type: parsed +protocol: NECext +address: 4F 50 00 00 +command: 0F F0 00 00 +# +name: POWER +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 12 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 06 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 00 00 00 00 diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index c55ad267d..8c781eea9 100644 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 07th Mar, 2023 -# Last Checked 25th Apr, 2023 +# Last Updated 2nd May, 2023 +# Last Checked 2nd May, 2023 # name: POWER type: parsed @@ -1899,3 +1899,77 @@ type: parsed protocol: SIRC20 address: 10 01 00 00 command: 33 00 00 00 +# +# Sharp TV +# +name: POWER +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 01 FE 00 00 +# +name: VOL+ +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 0C F3 00 00 +# +name: VOL- +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 10 EF 00 00 +# +name: CH+ +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 18 E7 00 00 +# +name: CH- +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 1C E3 00 00 +# +name: MUTE +type: parsed +protocol: NECext +address: 00 BD 00 00 +command: 04 FB 00 00 +# +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 278 1811 277 788 246 794 250 764 280 786 248 792 252 1813 275 1815 273 791 253 1812 276 789 255 785 249 791 253 1812 276 789 255 45322 280 1809 279 786 248 766 278 788 246 794 250 1815 273 792 252 788 246 1819 280 785 249 1817 271 1819 280 1810 278 787 247 1818 281 43217 274 1818 270 794 250 764 280 786 248 792 252 788 256 1809 279 1811 277 788 246 1819 280 785 249 766 278 762 272 1819 280 785 248 +# +name: MUTE +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 278 1812 276 762 282 758 276 765 279 761 273 1818 281 1809 279 1811 277 762 282 1809 279 760 274 766 278 762 282 1809 279 760 274 44279 276 1813 275 763 281 759 275 766 278 762 272 768 276 764 280 760 274 1817 271 768 276 1815 273 1817 271 1819 280 759 275 1816 272 44276 279 1812 276 763 281 758 276 765 279 761 273 1818 281 1810 278 1811 277 762 272 1819 279 760 274 766 278 762 282 1809 279 760 274 +# +name: VOL+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 272 1817 271 794 250 790 254 786 248 792 252 762 272 794 250 1815 273 792 252 1813 275 790 254 785 249 766 278 1813 275 789 255 46372 273 1817 271 794 250 763 281 785 248 792 252 1813 275 1814 274 791 253 1812 276 789 255 1810 278 1812 276 1813 275 790 254 1811 277 42170 277 1814 274 791 253 787 247 793 251 763 281 759 275 791 253 1812 276 789 255 1810 278 787 247 793 251 789 255 1810 278 787 247 +# +name: VOL- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 275 1814 274 791 253 787 247 793 251 789 255 1810 278 787 247 1818 281 785 249 1816 272 793 251 789 255 785 249 1816 272 766 278 45325 274 1815 273 792 252 762 272 794 250 790 254 786 247 1818 270 794 250 1815 273 792 252 1813 275 1815 273 1816 272 793 251 1814 274 43224 277 1814 274 764 280 786 248 792 252 788 246 1820 279 786 247 1817 271 768 276 1815 273 792 252 761 273 794 250 1815 273 791 253 +# +name: CH+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 272 1817 271 794 250 790 254 786 248 792 252 1813 275 790 254 759 275 792 252 1813 275 789 255 785 248 792 252 1813 275 789 255 46372 273 1817 271 793 251 763 281 759 275 791 253 787 247 1818 281 1810 278 1812 276 789 255 1809 279 1811 277 1813 275 790 254 1811 277 42169 277 1815 273 792 252 787 247 794 250 789 255 1810 278 787 247 794 250 789 255 1810 278 761 273 793 251 789 255 1810 278 787 247 +# +name: CH- +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 273 1816 272 767 277 789 255 785 249 791 253 787 246 1818 281 785 248 765 279 1812 276 789 255 759 275 791 253 1812 276 789 255 46372 281 1808 280 785 249 791 253 787 247 793 251 1814 274 791 253 1812 276 1814 274 791 253 1812 276 1814 274 1815 273 792 252 1813 275 42172 272 1819 280 785 249 765 279 761 273 768 276 764 280 1811 277 788 246 768 276 1815 273 792 252 788 246 794 250 1815 273 791 253 diff --git a/debug/PyCortexMDebug/README.md b/debug/PyCortexMDebug/README.md deleted file mode 100644 index 32c76e765..000000000 --- a/debug/PyCortexMDebug/README.md +++ /dev/null @@ -1,84 +0,0 @@ -PyCortexMDebug -============== - -*A set of GDB/Python-based utilities to make life debugging ARM Cortex-M processors a bit easier* - -It will consist of several modules which will hopefully become integrated as they evolve. Presently, there is only one: - -## SVD -ARM defines an SVD (System View Description) file format in its CMSIS -standard as a means for Cortex-M-based chip manufacturers to provide a -common description of peripherals, registers, and register fields. You -can download SVD files for different manufacturers -[here](http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php). - -My implementation so far has only tested STM32 chips but should hold for others. If others are like those from ST, -expect plenty of errors in the file. Like GPIOA having a register named GPIOB_OSPEEDR and lots of 16-bit registers -that are listed as 32! - -The implementation consists of two components -- An xml parser module (pysvd) and a GDB file (gdb_svd). -I haven't yet worked out a perfect workflow for this, though it's quite easy to use when -you already tend to have a GDB initialization file for starting up OpenOCD and the like. -However your workflow works, just make sure to, in GDB: - - source gdb_svd.py - svd_load [your_svd_file].svd - -These files can be huge so it might take a second or two. Anyways, after that, you can do - - svd - -to list available peripherals with descriptions. Or you can do - - svd [some_peripheral_name] - -to see all of the registers (with their values) for a given peripheral. For more details, run - - svd [some_peripheral_name] [some_register_name] - -to see all of the field values with descriptions. - -You can add format modifiers like: - -* `svd/x` will display values in hex -* `svd/o` will display values in octal -* `svd/t` or `svd/b` will display values in binary -* `svd/a` will display values in hex and try to resolve symbols from the values - -All field values are displayed at the correct lengths as provided by the SVD files. -Also, tab completion exists for nearly everything! When in doubt, run `svd help`. - -### TODO - -Enable writing to registers and individual fields - -### Bugs - -There are probably a few. All planning, writing, and testing of this was done in an afternoon. There may be -some oddities in working with non-STM32 parts. I'll play with this when I start working with other -controllers again. If something's giving you trouble, describe the problem and it shall be fixed. - -## DWT -The ARM Data Watchpoint and Trace Unit (DWT) offers data watchpoints and a series of gated cycle counters. For now, -I only support the raw cycle counter but facilities are in place to make use of others. As this is independent of the -specific device under test, commands are simple and you can configure a clock speed to get real time values from -counters. - - dwt configclk 48000000 - -will set the current core clock speed. Then - - dwt cyccnt reset - dwt cyccnt enable - -will reset and start the cycle counter. At any point - - dwt cycnt - -will then indicate the number of cycles and amount of time that has passed. - -## ITM/ETM support - -This is not implemented yet. I want to have more complete support for some of the nicer debug and trace features -on Cortex-M processors. Parts of this will probably be dependent on OpenOCD and possibly on specific interfaces. -I'll try to avoid this where possible but can't make any promises. diff --git a/debug/PyCortexMDebug/cmdebug/dwt_gdb.py b/debug/PyCortexMDebug/cmdebug/dwt_gdb.py deleted file mode 100755 index dd7ccd207..000000000 --- a/debug/PyCortexMDebug/cmdebug/dwt_gdb.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env python -""" -This file is part of PyCortexMDebug - -PyCortexMDebug is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -PyCortexMDebug is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with PyCortexMDebug. If not, see . -""" - -import gdb -import struct - -DWT_CTRL = 0xE0001000 -DWT_CYCCNT = 0xE0001004 -DWT_CPICNT = 0xE0001008 -DWT_EXTCNT = 0xE000100C -DWT_SLEEPCNT = 0xE0001010 -DWT_LSUCNT = 0xE0001014 -DWT_FOLDCNT = 0xE0001018 -DWT_PCSR = 0xE000101C - -prefix = "dwt : " - - -class DWT(gdb.Command): - clk = None - is_init = False - - def __init__(self): - gdb.Command.__init__(self, "dwt", gdb.COMMAND_DATA) - - @staticmethod - def read(address, bits=32): - """Read from memory (using print) and return an integer""" - value = gdb.selected_inferior().read_memory(address, bits / 8) - return struct.unpack_from(" 1: - if s[1][:2] == "en": - self.cyccnt_en() - elif s[1][0] == "r": - self.cyccnt_reset() - elif s[1][0] == "d": - self.cyccnt_dis() - gdb.write( - prefix - + "CYCCNT ({}): ".format("ON" if (self.read(DWT_CTRL) & 1) else "OFF") - + self.cycles_str(self.read(DWT_CYCCNT)) - ) - elif s[0] == "reset": - if len(s) > 1: - if s[1] == "cyccnt": - self.cyccnt_reset() - gdb.write(prefix + "CYCCNT reset\n") - if s[1] == "counters": - self.cyccnt_reset() - gdb.write(prefix + "CYCCNT reset\n") - else: - self.cyccnt_reset() - gdb.write(prefix + "CYCCNT reset\n") - else: - # Reset everything - self.cyccnt_reset() - gdb.write(prefix + "CYCCNT reset\n") - elif s[0] == "configclk": - if len(s) == 2: - try: - self.clk = float(s[1]) - except: - self.print_help() - else: - self.print_help() - else: - # Try to figure out what stupid went on here - gdb.write(args) - self.print_help() - - @staticmethod - def complete(text, word): - text = str(text).lower() - s = text.split(" ") - - commands = ["configclk", "reset", "cyccnt"] - reset_commands = ["counters", "cyccnt"] - cyccnt_commands = ["enable", "reset", "disable"] - - if len(s) == 1: - return filter(lambda x: x.startswith(s[0]), commands) - - if len(s) == 2: - if s[0] == "reset": - return filter(lambda x: x.startswith(s[1]), reset_commands) - if s[0] == "cyccnt": - return filter(lambda x: x.startswith(s[1]), cyccnt_commands) - - def cycles_str(self, cycles): - if self.clk: - return "%d cycles, %.3es\n" % (cycles, cycles * 1.0 / self.clk) - else: - return "%d cycles" - - def cyccnt_en(self): - self.write(DWT_CTRL, self.read(DWT_CTRL) | 1) - - def cyccnt_dis(self): - self.write(DWT_CTRL, self.read(DWT_CTRL) & 0xFFFFFFFE) - - def cyccnt_reset(self, value=0): - self.write(DWT_CYCCNT, value) - - def cpicnt_reset(self, value=0): - self.write(DWT_CPICNT, value & 0xFF) - - @staticmethod - def print_help(): - gdb.write("Usage:\n") - gdb.write("=========\n") - gdb.write("dwt:\n") - gdb.write("\tList available peripherals\n") - gdb.write("dwt configclk [Hz]:\n") - gdb.write("\tSet clock for rendering time values in seconds\n") - gdb.write("dwt reset:\n") - gdb.write("\tReset everything in DWT\n") - gdb.write("dwt reset counters:\n") - gdb.write("\tReset all DWT counters\n") - gdb.write("dwt cyccnt\n") - gdb.write("\tDisplay the cycle count\n") - gdb.write("\td(default):decimal, x: hex, o: octal, b: binary\n") - return - - -# Registers our class to GDB when sourced: -DWT() diff --git a/debug/PyCortexMDebug/cmdebug/x2d.py b/debug/PyCortexMDebug/cmdebug/x2d.py deleted file mode 100644 index fc3f185db..000000000 --- a/debug/PyCortexMDebug/cmdebug/x2d.py +++ /dev/null @@ -1,586 +0,0 @@ -#!/usr/bin/env python -"Makes working with XML feel like you are working with JSON" - -try: - from defusedexpat import pyexpat as expat -except ImportError: - from xml.parsers import expat - -from xml.sax.saxutils import XMLGenerator -from xml.sax.xmlreader import AttributesImpl - -try: # pragma no cover - from cStringIO import StringIO -except ImportError: # pragma no cover - try: - from StringIO import StringIO - except ImportError: - from io import StringIO - -from inspect import isgenerator - - -class ObjectDict(dict): - def __getattr__(self, name): - if name in self: - return self[name] - else: - raise AttributeError("No such attribute: " + name) - - -try: # pragma no cover - _basestring = basestring -except NameError: # pragma no cover - _basestring = str -try: # pragma no cover - _unicode = unicode -except NameError: # pragma no cover - _unicode = str - -__author__ = "Martin Blech" -__version__ = "0.12.0" -__license__ = "MIT" - - -class ParsingInterrupted(Exception): - pass - - -class _DictSAXHandler(object): - def __init__( - self, - item_depth=0, - item_callback=lambda *args: True, - xml_attribs=True, - attr_prefix="@", - cdata_key="#text", - force_cdata=False, - cdata_separator="", - postprocessor=None, - dict_constructor=ObjectDict, - strip_whitespace=True, - namespace_separator=":", - namespaces=None, - force_list=None, - comment_key="#comment", - ): - self.path = [] - self.stack = [] - self.data = [] - self.item = None - self.item_depth = item_depth - self.xml_attribs = xml_attribs - self.item_callback = item_callback - self.attr_prefix = attr_prefix - self.cdata_key = cdata_key - self.force_cdata = force_cdata - self.cdata_separator = cdata_separator - self.postprocessor = postprocessor - self.dict_constructor = dict_constructor - self.strip_whitespace = strip_whitespace - self.namespace_separator = namespace_separator - self.namespaces = namespaces - self.namespace_declarations = ObjectDict() - self.force_list = force_list - self.comment_key = comment_key - - def _build_name(self, full_name): - if self.namespaces is None: - return full_name - i = full_name.rfind(self.namespace_separator) - if i == -1: - return full_name - namespace, name = full_name[:i], full_name[i + 1 :] - try: - short_namespace = self.namespaces[namespace] - except KeyError: - short_namespace = namespace - if not short_namespace: - return name - else: - return self.namespace_separator.join((short_namespace, name)) - - def _attrs_to_dict(self, attrs): - if isinstance(attrs, dict): - return attrs - return self.dict_constructor(zip(attrs[0::2], attrs[1::2])) - - def startNamespaceDecl(self, prefix, uri): - self.namespace_declarations[prefix or ""] = uri - - def startElement(self, full_name, attrs): - name = self._build_name(full_name) - attrs = self._attrs_to_dict(attrs) - if attrs and self.namespace_declarations: - attrs["xmlns"] = self.namespace_declarations - self.namespace_declarations = ObjectDict() - self.path.append((name, attrs or None)) - if len(self.path) > self.item_depth: - self.stack.append((self.item, self.data)) - if self.xml_attribs: - attr_entries = [] - for key, value in attrs.items(): - key = self.attr_prefix + self._build_name(key) - if self.postprocessor: - entry = self.postprocessor(self.path, key, value) - else: - entry = (key, value) - if entry: - attr_entries.append(entry) - attrs = self.dict_constructor(attr_entries) - else: - attrs = None - self.item = attrs or None - self.data = [] - - def endElement(self, full_name): - name = self._build_name(full_name) - if len(self.path) == self.item_depth: - item = self.item - if item is None: - item = None if not self.data else self.cdata_separator.join(self.data) - - should_continue = self.item_callback(self.path, item) - if not should_continue: - raise ParsingInterrupted() - if len(self.stack): - data = None if not self.data else self.cdata_separator.join(self.data) - item = self.item - self.item, self.data = self.stack.pop() - if self.strip_whitespace and data: - data = data.strip() or None - if data and self.force_cdata and item is None: - item = self.dict_constructor() - if item is not None: - if data: - self.push_data(item, self.cdata_key, data) - self.item = self.push_data(self.item, name, item) - else: - self.item = self.push_data(self.item, name, data) - else: - self.item = None - self.data = [] - self.path.pop() - - def characters(self, data): - if not self.data: - self.data = [data] - else: - self.data.append(data) - - def comments(self, data): - if self.strip_whitespace: - data = data.strip() - self.item = self.push_data(self.item, self.comment_key, data) - - def push_data(self, item, key, data): - if self.postprocessor is not None: - result = self.postprocessor(self.path, key, data) - if result is None: - return item - key, data = result - if item is None: - item = self.dict_constructor() - try: - value = item[key] - if isinstance(value, list): - value.append(data) - else: - item[key] = [value, data] - except KeyError: - if self._should_force_list(key, data): - item[key] = [data] - else: - item[key] = data - return item - - def _should_force_list(self, key, value): - if not self.force_list: - return False - if isinstance(self.force_list, bool): - return self.force_list - try: - return key in self.force_list - except TypeError: - return self.force_list(self.path[:-1], key, value) - - -def parse( - xml_input, - encoding=None, - expat=expat, - process_namespaces=False, - namespace_separator=":", - disable_entities=True, - process_comments=False, - **kwargs -): - """Parse the given XML input and convert it into a dictionary. - - `xml_input` can either be a `string`, a file-like object, or a generator of strings. - - If `xml_attribs` is `True`, element attributes are put in the dictionary - among regular child elements, using `@` as a prefix to avoid collisions. If - set to `False`, they are just ignored. - - Simple example:: - - >>> import xmltodict - >>> doc = xmltodict.parse(\"\"\" - ... - ... 1 - ... 2 - ... - ... \"\"\") - >>> doc['a']['@prop'] - u'x' - >>> doc['a']['b'] - [u'1', u'2'] - - If `item_depth` is `0`, the function returns a dictionary for the root - element (default behavior). Otherwise, it calls `item_callback` every time - an item at the specified depth is found and returns `None` in the end - (streaming mode). - - The callback function receives two parameters: the `path` from the document - root to the item (name-attribs pairs), and the `item` (dict). If the - callback's return value is false-ish, parsing will be stopped with the - :class:`ParsingInterrupted` exception. - - Streaming example:: - - >>> def handle(path, item): - ... print('path:%s item:%s' % (path, item)) - ... return True - ... - >>> xmltodict.parse(\"\"\" - ... - ... 1 - ... 2 - ... \"\"\", item_depth=2, item_callback=handle) - path:[(u'a', {u'prop': u'x'}), (u'b', None)] item:1 - path:[(u'a', {u'prop': u'x'}), (u'b', None)] item:2 - - The optional argument `postprocessor` is a function that takes `path`, - `key` and `value` as positional arguments and returns a new `(key, value)` - pair where both `key` and `value` may have changed. Usage example:: - - >>> def postprocessor(path, key, value): - ... try: - ... return key + ':int', int(value) - ... except (ValueError, TypeError): - ... return key, value - >>> xmltodict.parse('12x', - ... postprocessor=postprocessor) - ObjectDict([(u'a', ObjectDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) - - You can pass an alternate version of `expat` (such as `defusedexpat`) by - using the `expat` parameter. E.g: - - >>> import defusedexpat - >>> xmltodict.parse('hello', expat=defusedexpat.pyexpat) - ObjectDict([(u'a', u'hello')]) - - You can use the force_list argument to force lists to be created even - when there is only a single child of a given level of hierarchy. The - force_list argument is a tuple of keys. If the key for a given level - of hierarchy is in the force_list argument, that level of hierarchy - will have a list as a child (even if there is only one sub-element). - The index_keys operation takes precedence over this. This is applied - after any user-supplied postprocessor has already run. - - For example, given this input: - - - host1 - Linux - - - em0 - 10.0.0.1 - - - - - - If called with force_list=('interface',), it will produce - this dictionary: - {'servers': - {'server': - {'name': 'host1', - 'os': 'Linux'}, - 'interfaces': - {'interface': - [ {'name': 'em0', 'ip_address': '10.0.0.1' } ] } } } - - `force_list` can also be a callable that receives `path`, `key` and - `value`. This is helpful in cases where the logic that decides whether - a list should be forced is more complex. - - - If `process_comment` is `True` then comment will be added with comment_key - (default=`'#comment'`) to then tag which contains comment - - For example, given this input: - - - - - - 1 - - 2 - - - - If called with process_comment=True, it will produce - this dictionary: - 'a': { - 'b': { - '#comment': 'b comment', - 'c': { - - '#comment': 'c comment', - '#text': '1', - }, - 'd': '2', - }, - } - """ - handler = _DictSAXHandler(namespace_separator=namespace_separator, **kwargs) - if isinstance(xml_input, _unicode): - if not encoding: - encoding = "utf-8" - xml_input = xml_input.encode(encoding) - if not process_namespaces: - namespace_separator = None - parser = expat.ParserCreate(encoding, namespace_separator) - try: - parser.ordered_attributes = True - except AttributeError: - # Jython's expat does not support ordered_attributes - pass - parser.StartNamespaceDeclHandler = handler.startNamespaceDecl - parser.StartElementHandler = handler.startElement - parser.EndElementHandler = handler.endElement - parser.CharacterDataHandler = handler.characters - if process_comments: - parser.CommentHandler = handler.comments - parser.buffer_text = True - if disable_entities: - try: - # Attempt to disable DTD in Jython's expat parser (Xerces-J). - feature = "http://apache.org/xml/features/disallow-doctype-decl" - parser._reader.setFeature(feature, True) - except AttributeError: - # For CPython / expat parser. - # Anything not handled ends up here and entities aren't expanded. - parser.DefaultHandler = lambda x: None - # Expects an integer return; zero means failure -> expat.ExpatError. - parser.ExternalEntityRefHandler = lambda *x: 1 - if hasattr(xml_input, "read"): - parser.ParseFile(xml_input) - elif isgenerator(xml_input): - for chunk in xml_input: - parser.Parse(chunk, False) - parser.Parse(b"", True) - else: - parser.Parse(xml_input, True) - return handler.item - - -def _process_namespace(name, namespaces, ns_sep=":", attr_prefix="@"): - if not namespaces: - return name - try: - ns, name = name.rsplit(ns_sep, 1) - except ValueError: - pass - else: - ns_res = namespaces.get(ns.strip(attr_prefix)) - name = ( - "{}{}{}{}".format( - attr_prefix if ns.startswith(attr_prefix) else "", ns_res, ns_sep, name - ) - if ns_res - else name - ) - return name - - -def _emit( - key, - value, - content_handler, - attr_prefix="@", - cdata_key="#text", - depth=0, - preprocessor=None, - pretty=False, - newl="\n", - indent="\t", - namespace_separator=":", - namespaces=None, - full_document=True, - expand_iter=None, -): - key = _process_namespace(key, namespaces, namespace_separator, attr_prefix) - if preprocessor is not None: - result = preprocessor(key, value) - if result is None: - return - key, value = result - if ( - not hasattr(value, "__iter__") - or isinstance(value, _basestring) - or isinstance(value, dict) - ): - value = [value] - for index, v in enumerate(value): - if full_document and depth == 0 and index > 0: - raise ValueError("document with multiple roots") - if v is None: - v = ObjectDict() - elif isinstance(v, bool): - if v: - v = _unicode("true") - else: - v = _unicode("false") - elif not isinstance(v, dict): - if ( - expand_iter - and hasattr(v, "__iter__") - and not isinstance(v, _basestring) - ): - v = ObjectDict(((expand_iter, v),)) - else: - v = _unicode(v) - if isinstance(v, _basestring): - v = ObjectDict(((cdata_key, v),)) - cdata = None - attrs = ObjectDict() - children = [] - for ik, iv in v.items(): - if ik == cdata_key: - cdata = iv - continue - if ik.startswith(attr_prefix): - ik = _process_namespace( - ik, namespaces, namespace_separator, attr_prefix - ) - if ik == "@xmlns" and isinstance(iv, dict): - for k, v in iv.items(): - attr = "xmlns{}".format(":{}".format(k) if k else "") - attrs[attr] = _unicode(v) - continue - if not isinstance(iv, _unicode): - iv = _unicode(iv) - attrs[ik[len(attr_prefix) :]] = iv - continue - children.append((ik, iv)) - if pretty: - content_handler.ignorableWhitespace(depth * indent) - content_handler.startElement(key, AttributesImpl(attrs)) - if pretty and children: - content_handler.ignorableWhitespace(newl) - for child_key, child_value in children: - _emit( - child_key, - child_value, - content_handler, - attr_prefix, - cdata_key, - depth + 1, - preprocessor, - pretty, - newl, - indent, - namespaces=namespaces, - namespace_separator=namespace_separator, - expand_iter=expand_iter, - ) - if cdata is not None: - content_handler.characters(cdata) - if pretty and children: - content_handler.ignorableWhitespace(depth * indent) - content_handler.endElement(key) - if pretty and depth: - content_handler.ignorableWhitespace(newl) - - -def unparse( - input_dict, - output=None, - encoding="utf-8", - full_document=True, - short_empty_elements=False, - **kwargs -): - """Emit an XML document for the given `input_dict` (reverse of `parse`). - - The resulting XML document is returned as a string, but if `output` (a - file-like object) is specified, it is written there instead. - - Dictionary keys prefixed with `attr_prefix` (default=`'@'`) are interpreted - as XML node attributes, whereas keys equal to `cdata_key` - (default=`'#text'`) are treated as character data. - - The `pretty` parameter (default=`False`) enables pretty-printing. In this - mode, lines are terminated with `'\n'` and indented with `'\t'`, but this - can be customized with the `newl` and `indent` parameters. - - """ - if full_document and len(input_dict) != 1: - raise ValueError("Document must have exactly one root.") - must_return = False - if output is None: - output = StringIO() - must_return = True - if short_empty_elements: - content_handler = XMLGenerator(output, encoding, True) - else: - content_handler = XMLGenerator(output, encoding) - if full_document: - content_handler.startDocument() - for key, value in input_dict.items(): - _emit(key, value, content_handler, full_document=full_document, **kwargs) - if full_document: - content_handler.endDocument() - if must_return: - value = output.getvalue() - try: # pragma no cover - value = value.decode(encoding) - except AttributeError: # pragma no cover - pass - return value - - -if __name__ == "__main__": # pragma: no cover - import sys - import marshal - - try: - stdin = sys.stdin.buffer - stdout = sys.stdout.buffer - except AttributeError: - stdin = sys.stdin - stdout = sys.stdout - - (item_depth,) = sys.argv[1:] - item_depth = int(item_depth) - - def handle_item(path, item): - marshal.dump((path, item), stdout) - return True - - try: - root = parse( - stdin, - item_depth=item_depth, - item_callback=handle_item, - dict_constructor=dict, - ) - if item_depth == 0: - handle_item([], root) - except KeyboardInterrupt: - pass diff --git a/fbt b/fbt index efe625f03..ef41cc056 100755 --- a/fbt +++ b/fbt @@ -5,6 +5,7 @@ set -eu; # private variables +N_GIT_THREADS="$(getconf _NPROCESSORS_ONLN)"; SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd -P)"; SCONS_DEFAULT_FLAGS="--warn=target-not-built"; SCONS_EP="python3 -m SCons"; @@ -28,7 +29,7 @@ if [ -z "$FBT_NO_SYNC" ]; then echo "\".git\" directory not found, please clone repo via \"git clone\""; exit 1; fi - git submodule update --init --depth 1; + git submodule update --init --depth 1 --jobs "$N_GIT_THREADS"; fi $SCONS_EP $SCONS_DEFAULT_FLAGS "$@" diff --git a/fbt.cmd b/fbt.cmd index 6e839c778..03e4ec3d0 100644 --- a/fbt.cmd +++ b/fbt.cmd @@ -5,7 +5,7 @@ set SCONS_EP=python -m SCons if [%FBT_NO_SYNC%] == [] ( if exist ".git" ( - git submodule update --init --depth 1 + git submodule update --init --depth 1 --jobs %NUMBER_OF_PROCESSORS% ) else ( echo Not in a git repo, please clone with "git clone" exit /b 1 diff --git a/fbt_options.py b/fbt_options.py index 0e87521a1..5ebe82977 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -14,15 +14,15 @@ DEBUG = 0 # Suffix to add to files when building distribution # If OS environment has DIST_SUFFIX set, it will be used instead -DIST_SUFFIX = "XFW-0044_09042023" +DIST_SUFFIX = "XFW-0046_06052023" # Coprocessor firmware COPRO_OB_DATA = "scripts/ob.data" -# Must match lib/STM32CubeWB version +# Must match lib/stm32wb_copro version COPRO_CUBE_VERSION = "1.13.3" -COPRO_CUBE_DIR = "lib/STM32CubeWB" +COPRO_CUBE_DIR = "lib/stm32wb_copro" # Default radio stack COPRO_STACK_BIN = "stm32wb5x_BLE_Stack_light_fw.bin" @@ -32,13 +32,8 @@ COPRO_STACK_TYPE = "ble_light" # Leave 0 to let scripts automatically calculate it COPRO_STACK_ADDR = "0x0" -# If you override COPRO_CUBE_DIR on command-line, override this as well -COPRO_STACK_BIN_DIR = posixpath.join( - COPRO_CUBE_DIR, - "Projects", - "STM32WB_Copro_Wireless_Binaries", - "STM32WB5x", -) +# If you override COPRO_CUBE_DIR on commandline, override this as well +COPRO_STACK_BIN_DIR = posixpath.join(COPRO_CUBE_DIR, "firmware") # Supported toolchain versions FBT_TOOLCHAIN_VERSIONS = (" 10.3.",) diff --git a/firmware.scons b/firmware.scons index c7fdc6392..c46996899 100644 --- a/firmware.scons +++ b/firmware.scons @@ -1,5 +1,3 @@ -Import("ENV", "fw_build_meta") - from SCons.Errors import UserError from SCons.Node import FS @@ -10,6 +8,8 @@ from fbt_extra.util import ( link_elf_dir_as_latest, ) +Import("ENV", "fw_build_meta") + # Building initial C environment for libs env = ENV.Clone( tools=[ diff --git a/firmware/SConscript b/firmware/SConscript index fa96b0adf..8d8789e72 100644 --- a/firmware/SConscript +++ b/firmware/SConscript @@ -7,7 +7,7 @@ env.Append( libenv = env.Clone(FW_LIB_NAME="flipper${TARGET_HW}") libenv.Append( CPPPATH=[ - "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl", + "#/lib/stm32wb_copro/wpan/interface/patterns/ble_thread/tl", ] ) libenv.ApplyLibFlags() diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 0852b9243..0681b773b 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,23.0,, +Version,+,26.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -36,6 +36,7 @@ Header,+,applications/services/notification/notification_messages.h,, Header,+,applications/services/power/power_service/power.h,, Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/storage/storage.h,, +Header,-,firmware/targets/f18/furi_hal/furi_hal_power_calibration.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,, Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,, @@ -77,33 +78,6 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_adc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_bus.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_comp.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_cortex.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crs.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dma.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dmamux.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_exti.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_gpio.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_hsem.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_i2c.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_ipcc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_iwdg.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lptim.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lpuart.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pka.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pwr.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rcc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rng.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rtc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_spi.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_system.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_tim.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_usart.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_utils.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, @@ -111,6 +85,7 @@ Header,+,lib/flipper_application/plugins/composite_resolver.h,, Header,+,lib/flipper_application/plugins/plugin_manager.h,, Header,+,lib/flipper_format/flipper_format.h,, Header,+,lib/flipper_format/flipper_format_i.h,, +Header,+,lib/flipper_format/flipper_format_stream.h,, Header,+,lib/libusb_stm32/inc/hid_usage_button.h,, Header,+,lib/libusb_stm32/inc/hid_usage_consumer.h,, Header,+,lib/libusb_stm32/inc/hid_usage_desktop.h,, @@ -154,6 +129,34 @@ Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_cortex.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_crc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_crs.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_dma.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_dmamux.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_exti.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_gpio.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_hsem.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_i2c.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_ipcc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_iwdg.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_lptim.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_lpuart.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_pka.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_pwr.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rcc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rng.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rtc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_spi.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_system.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_tim.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, +Header,+,lib/pulse_reader/pulse_reader.h,, Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, @@ -199,8 +202,8 @@ Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef* Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef* Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*" Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef* -Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef* -Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*" +Function,-,LL_I2C_DeInit,ErrorStatus,const I2C_TypeDef* +Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, const LL_I2C_InitTypeDef*" Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef* Function,-,LL_Init1msTick,void,uint32_t Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef* @@ -754,6 +757,11 @@ Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32 Function,+,flipper_format_rewind,_Bool,FlipperFormat* Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat* Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool" +Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool" +Function,+,flipper_format_stream_get_value_count,_Bool,"Stream*, const char*, uint32_t*, _Bool" +Function,+,flipper_format_stream_read_value_line,_Bool,"Stream*, const char*, FlipperStreamValue, void*, size_t, _Bool" +Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*" +Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*" Function,+,flipper_format_string_alloc,FlipperFormat*, Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" @@ -816,6 +824,7 @@ Function,+,furi_hal_bt_change_app,_Bool,"FuriHalBtProfile, GapEventCallback, voi Function,+,furi_hal_bt_clear_white_list,_Bool, Function,+,furi_hal_bt_dump_state,void,FuriString* Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode +Function,-,furi_hal_bt_get_hardfault_info,const FuriHalBtHardfaultInfo*, Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*" Function,+,furi_hal_bt_get_radio_stack,FuriHalBtStack, Function,+,furi_hal_bt_get_rssi,float, @@ -885,6 +894,8 @@ Function,+,furi_hal_console_puts,void,const char* Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*" Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t" Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t" +Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize" +Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp Function,+,furi_hal_cortex_delay_us,void,uint32_t Function,-,furi_hal_cortex_init_early,void, Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t, @@ -959,6 +970,7 @@ Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t" Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t" Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*" +Function,+,furi_hal_info_get_api_version,void,"uint16_t*, uint16_t*" Function,-,furi_hal_init,void, Function,-,furi_hal_init_early,void, Function,-,furi_hal_interrupt_init,void, @@ -1270,7 +1282,7 @@ Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority" Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t" Function,+,furi_thread_set_state_callback,void,"FuriThread*, FuriThreadStateCallback" Function,+,furi_thread_set_state_context,void,"FuriThread*, void*" -Function,+,furi_thread_set_stdout_callback,_Bool,FuriThreadStdoutWriteCallback +Function,+,furi_thread_set_stdout_callback,void,FuriThreadStdoutWriteCallback Function,+,furi_thread_start,void,FuriThread* Function,+,furi_thread_stdout_flush,int32_t, Function,+,furi_thread_stdout_write,size_t,"const char*, size_t" @@ -1279,6 +1291,7 @@ Function,+,furi_thread_yield,void, Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" Function,+,furi_timer_free,void,FuriTimer* Function,+,furi_timer_is_running,uint32_t,FuriTimer* +Function,+,furi_timer_pending_callback,void,"FuriTimerPendigCallback, void*, uint32_t" Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" Function,+,furi_timer_stop,FuriStatus,FuriTimer* Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" @@ -1368,12 +1381,11 @@ Function,-,ldiv,ldiv_t,"long, long" Function,-,llabs,long long,long long Function,-,lldiv,lldiv_t,"long long, long long" Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,const Loader* +Function,+,loader_is_locked,_Bool,Loader* Function,+,loader_lock,_Bool,Loader* -Function,+,loader_show_menu,void, +Function,+,loader_show_menu,void,Loader* Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_unlock,void,Loader* -Function,+,loader_update_menu,void, Function,+,loading_alloc,Loading*, Function,+,loading_free,void,Loading* Function,+,loading_get_view,View*,Loading* @@ -1565,6 +1577,15 @@ Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, FuriString*, siz Function,+,protocol_dict_render_data,void,"ProtocolDict*, FuriString*, size_t" Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" Function,-,pselect,int,"int, fd_set*, fd_set*, fd_set*, const timespec*, const sigset_t*" +Function,-,pulse_reader_alloc,PulseReader*,"const GpioPin*, uint32_t" +Function,-,pulse_reader_free,void,PulseReader* +Function,-,pulse_reader_receive,uint32_t,"PulseReader*, int" +Function,-,pulse_reader_samples,uint32_t,PulseReader* +Function,-,pulse_reader_set_bittime,void,"PulseReader*, uint32_t" +Function,-,pulse_reader_set_pull,void,"PulseReader*, GpioPull" +Function,-,pulse_reader_set_timebase,void,"PulseReader*, PulseReaderUnit" +Function,-,pulse_reader_start,void,PulseReader* +Function,-,pulse_reader_stop,void,PulseReader* Function,-,putc,int,"int, FILE*" Function,-,putc_unlocked,int,"int, FILE*" Function,-,putchar,int,int diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h new file mode 100644 index 000000000..e97e1657d --- /dev/null +++ b/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h @@ -0,0 +1,37 @@ +const ParamCEDV cedv = { + .cedv_conf.gauge_conf = + { + .CCT = 1, + .CSYNC = 0, + .EDV_CMP = 0, + .SC = 1, + .FIXED_EDV0 = 1, + .FCC_LIM = 1, + .FC_FOR_VDQ = 1, + .IGNORE_SD = 1, + .SME0 = 0, + }, + .full_charge_cap = 1300, + .design_cap = 1300, + .EDV0 = 3300, + .EDV1 = 3321, + .EDV2 = 3355, + .EMF = 3679, + .C0 = 430, + .C1 = 0, + .R1 = 408, + .R0 = 334, + .T0 = 4626, + .TC = 11, + .DOD0 = 4044, + .DOD10 = 3905, + .DOD20 = 3807, + .DOD30 = 3718, + .DOD40 = 3642, + .DOD50 = 3585, + .DOD60 = 3546, + .DOD70 = 3514, + .DOD80 = 3477, + .DOD90 = 3411, + .DOD100 = 3299, +}; diff --git a/firmware/targets/f18/target.json b/firmware/targets/f18/target.json index 0abb02019..6b150afbd 100644 --- a/firmware/targets/f18/target.json +++ b/firmware/targets/f18/target.json @@ -14,7 +14,7 @@ "flipper18", "furi", "freertos", - "stm32cubewb", + "stm32wb", "hwdrivers", "fatfs", "littlefs", @@ -54,4 +54,4 @@ "infrared", "st25rfal002" ] -} +} \ No newline at end of file diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index b78883d85..6a1b21773 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,23.0,, +Version,+,26.2,, Header,+,applications/main/fap_loader/fap_loader_app.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -37,7 +37,6 @@ Header,+,applications/services/locale/locale.h,, Header,+,applications/services/notification/notification.h,, Header,+,applications/services/notification/notification_messages.h,, Header,+,applications/services/power/power_service/power.h,, -Header,+,applications/services/rgb_backlight/rgb_backlight.h,, Header,+,applications/services/rpc/rpc_app.h,, Header,+,applications/services/storage/storage.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,, @@ -51,6 +50,7 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, +Header,-,firmware/targets/f7/furi_hal/furi_hal_power_calibration.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,, @@ -87,35 +87,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_adc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_bus.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_comp.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_cortex.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_crs.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dma.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_dmamux.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_exti.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_gpio.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_hsem.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_i2c.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_ipcc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_iwdg.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lptim.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_lpuart.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pka.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_pwr.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rcc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rng.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_rtc.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_spi.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_system.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_tim.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_usart.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_utils.h,, -Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,, -Header,-,lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h,, -Header,+,lib/STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h,, +Header,+,lib/drivers/rgb_backlight.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, @@ -123,6 +95,7 @@ Header,+,lib/flipper_application/plugins/composite_resolver.h,, Header,+,lib/flipper_application/plugins/plugin_manager.h,, Header,+,lib/flipper_format/flipper_format.h,, Header,+,lib/flipper_format/flipper_format_i.h,, +Header,+,lib/flipper_format/flipper_format_stream.h,, Header,+,lib/ibutton/ibutton_key.h,, Header,+,lib/ibutton/ibutton_protocols.h,, Header,+,lib/ibutton/ibutton_worker.h,, @@ -180,6 +153,33 @@ Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, Header,+,lib/pulse_reader/pulse_reader.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_cortex.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_crc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_crs.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_dma.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_dmamux.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_exti.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_gpio.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_hsem.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_i2c.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_ipcc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_iwdg.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_lptim.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_lpuart.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_pka.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_pwr.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rcc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rng.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_rtc.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_spi.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_system.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_tim.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, +Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/subghz/blocks/const.h,, Header,+,lib/subghz/blocks/decoder.h,, Header,+,lib/subghz/blocks/encoder.h,, @@ -218,17 +218,17 @@ Header,+,lib/toolbox/version.h,, Header,+,lib/u8g2/u8g2.h,, Header,+,lib/xtreme/xtreme.h,, Function,-,LL_ADC_CommonDeInit,ErrorStatus,ADC_Common_TypeDef* -Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, LL_ADC_CommonInitTypeDef*" +Function,-,LL_ADC_CommonInit,ErrorStatus,"ADC_Common_TypeDef*, const LL_ADC_CommonInitTypeDef*" Function,-,LL_ADC_CommonStructInit,void,LL_ADC_CommonInitTypeDef* Function,-,LL_ADC_DeInit,ErrorStatus,ADC_TypeDef* -Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_INJ_InitTypeDef*" +Function,-,LL_ADC_INJ_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_INJ_InitTypeDef*" Function,-,LL_ADC_INJ_StructInit,void,LL_ADC_INJ_InitTypeDef* -Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_InitTypeDef*" -Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, LL_ADC_REG_InitTypeDef*" +Function,-,LL_ADC_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_InitTypeDef*" +Function,-,LL_ADC_REG_Init,ErrorStatus,"ADC_TypeDef*, const LL_ADC_REG_InitTypeDef*" Function,-,LL_ADC_REG_StructInit,void,LL_ADC_REG_InitTypeDef* Function,-,LL_ADC_StructInit,void,LL_ADC_InitTypeDef* Function,-,LL_COMP_DeInit,ErrorStatus,COMP_TypeDef* -Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, LL_COMP_InitTypeDef*" +Function,+,LL_COMP_Init,ErrorStatus,"COMP_TypeDef*, const LL_COMP_InitTypeDef*" Function,-,LL_COMP_StructInit,void,LL_COMP_InitTypeDef* Function,-,LL_CRC_DeInit,ErrorStatus,CRC_TypeDef* Function,-,LL_CRS_DeInit,ErrorStatus, @@ -241,16 +241,16 @@ Function,-,LL_EXTI_StructInit,void,LL_EXTI_InitTypeDef* Function,-,LL_GPIO_DeInit,ErrorStatus,GPIO_TypeDef* Function,+,LL_GPIO_Init,ErrorStatus,"GPIO_TypeDef*, LL_GPIO_InitTypeDef*" Function,-,LL_GPIO_StructInit,void,LL_GPIO_InitTypeDef* -Function,-,LL_I2C_DeInit,ErrorStatus,I2C_TypeDef* -Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, LL_I2C_InitTypeDef*" +Function,-,LL_I2C_DeInit,ErrorStatus,const I2C_TypeDef* +Function,+,LL_I2C_Init,ErrorStatus,"I2C_TypeDef*, const LL_I2C_InitTypeDef*" Function,-,LL_I2C_StructInit,void,LL_I2C_InitTypeDef* Function,-,LL_Init1msTick,void,uint32_t Function,+,LL_LPTIM_DeInit,ErrorStatus,LPTIM_TypeDef* Function,-,LL_LPTIM_Disable,void,LPTIM_TypeDef* -Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, LL_LPTIM_InitTypeDef*" +Function,+,LL_LPTIM_Init,ErrorStatus,"LPTIM_TypeDef*, const LL_LPTIM_InitTypeDef*" Function,-,LL_LPTIM_StructInit,void,LL_LPTIM_InitTypeDef* -Function,-,LL_LPUART_DeInit,ErrorStatus,USART_TypeDef* -Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, LL_LPUART_InitTypeDef*" +Function,-,LL_LPUART_DeInit,ErrorStatus,const USART_TypeDef* +Function,+,LL_LPUART_Init,ErrorStatus,"USART_TypeDef*, const LL_LPUART_InitTypeDef*" Function,-,LL_LPUART_StructInit,void,LL_LPUART_InitTypeDef* Function,-,LL_PKA_DeInit,ErrorStatus,PKA_TypeDef* Function,-,LL_PKA_Init,ErrorStatus,"PKA_TypeDef*, LL_PKA_InitTypeDef*" @@ -295,23 +295,23 @@ Function,+,LL_SPI_Init,ErrorStatus,"SPI_TypeDef*, LL_SPI_InitTypeDef*" Function,-,LL_SPI_StructInit,void,LL_SPI_InitTypeDef* Function,-,LL_SetFlashLatency,ErrorStatus,uint32_t Function,+,LL_SetSystemCoreClock,void,uint32_t -Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_BDTR_InitTypeDef*" +Function,-,LL_TIM_BDTR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_BDTR_InitTypeDef*" Function,-,LL_TIM_BDTR_StructInit,void,LL_TIM_BDTR_InitTypeDef* Function,+,LL_TIM_DeInit,ErrorStatus,TIM_TypeDef* -Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_ENCODER_InitTypeDef*" +Function,-,LL_TIM_ENCODER_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_ENCODER_InitTypeDef*" Function,-,LL_TIM_ENCODER_StructInit,void,LL_TIM_ENCODER_InitTypeDef* -Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_HALLSENSOR_InitTypeDef*" +Function,-,LL_TIM_HALLSENSOR_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_HALLSENSOR_InitTypeDef*" Function,-,LL_TIM_HALLSENSOR_StructInit,void,LL_TIM_HALLSENSOR_InitTypeDef* -Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_IC_InitTypeDef*" +Function,-,LL_TIM_IC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_IC_InitTypeDef*" Function,-,LL_TIM_IC_StructInit,void,LL_TIM_IC_InitTypeDef* -Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, LL_TIM_InitTypeDef*" -Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, LL_TIM_OC_InitTypeDef*" +Function,+,LL_TIM_Init,ErrorStatus,"TIM_TypeDef*, const LL_TIM_InitTypeDef*" +Function,+,LL_TIM_OC_Init,ErrorStatus,"TIM_TypeDef*, uint32_t, const LL_TIM_OC_InitTypeDef*" Function,-,LL_TIM_OC_StructInit,void,LL_TIM_OC_InitTypeDef* Function,-,LL_TIM_StructInit,void,LL_TIM_InitTypeDef* -Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, LL_USART_ClockInitTypeDef*" +Function,-,LL_USART_ClockInit,ErrorStatus,"USART_TypeDef*, const LL_USART_ClockInitTypeDef*" Function,-,LL_USART_ClockStructInit,void,LL_USART_ClockInitTypeDef* -Function,-,LL_USART_DeInit,ErrorStatus,USART_TypeDef* -Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, LL_USART_InitTypeDef*" +Function,-,LL_USART_DeInit,ErrorStatus,const USART_TypeDef* +Function,+,LL_USART_Init,ErrorStatus,"USART_TypeDef*, const LL_USART_InitTypeDef*" Function,-,LL_USART_StructInit,void,LL_USART_InitTypeDef* Function,-,LL_mDelay,void,uint32_t Function,-,SK6805_get_led_count,uint8_t, @@ -896,18 +896,20 @@ Function,-,fdopen,FILE*,"int, const char*" Function,-,felica_check_ic_type,_Bool,uint8_t* Function,-,felica_clear,void,FelicaData* Function,-,felica_define_normal_block,void,"FelicaService*, uint16_t, uint8_t*" +Function,-,felica_estimate_timing_us,uint_least32_t,"uint_least8_t, uint_least8_t" Function,-,felica_get_ic_type,FelicaICType,uint8_t* Function,-,felica_get_service_name,FuriString*,FelicaService* Function,-,felica_get_system_name,FuriString*,FelicaSystem* Function,-,felica_lite_can_read_without_mac,_Bool,"uint8_t*, uint8_t" +Function,-,felica_lite_dump_data,_Bool,"FuriHalNfcTxRxContext*, FelicaReader*, FelicaData*, FelicaSystem*" Function,-,felica_lite_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, _Bool, const uint8_t*, uint8_t" Function,-,felica_lite_prepare_unencrypted_write,uint8_t,"uint8_t*, const FelicaReader*, const uint8_t*, uint8_t, const uint8_t*" Function,-,felica_parse_unencrypted_read,uint16_t,"uint8_t*, uint8_t, FelicaReader*, uint8_t*, uint16_t" Function,-,felica_parse_unencrypted_write,_Bool,"uint8_t*, uint8_t, FelicaReader*" Function,-,felica_prepare_unencrypted_read,uint8_t,"uint8_t*, const FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t" Function,-,felica_prepare_unencrypted_write,uint8_t,"uint8_t*, FelicaReader*, const uint16_t*, uint8_t, const uint32_t*, uint8_t, const uint8_t*" +Function,-,felica_push_normal_block,void,"FelicaService*, uint8_t*" Function,-,felica_read_card,_Bool,"FuriHalNfcTxRxContext*, FelicaData*, uint8_t*, uint8_t*" -Function,-,felica_read_lite_system,_Bool,"FuriHalNfcTxRxContext*, FelicaReader*, FelicaData*, FelicaSystem*" Function,-,feof,int,FILE* Function,-,feof_unlocked,int,FILE* Function,-,ferror,int,FILE* @@ -1003,6 +1005,11 @@ Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32 Function,+,flipper_format_rewind,_Bool,FlipperFormat* Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat* Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool" +Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool" +Function,+,flipper_format_stream_get_value_count,_Bool,"Stream*, const char*, uint32_t*, _Bool" +Function,+,flipper_format_stream_read_value_line,_Bool,"Stream*, const char*, FlipperStreamValue, void*, size_t, _Bool" +Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*" +Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*" Function,+,flipper_format_string_alloc,FlipperFormat*, Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t" Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t" @@ -1084,6 +1091,7 @@ Function,+,furi_hal_bt_clear_white_list,_Bool, Function,+,furi_hal_bt_dump_state,void,FuriString* Function,+,furi_hal_bt_ensure_c2_mode,_Bool,BleGlueC2Mode Function,+,furi_hal_bt_get_conn_rssi,uint32_t,uint8_t* +Function,-,furi_hal_bt_get_hardfault_info,const FuriHalBtHardfaultInfo*, Function,+,furi_hal_bt_get_key_storage_buff,void,"uint8_t**, uint16_t*" Function,+,furi_hal_bt_get_profile_adv_name,const char*,FuriHalBtProfile Function,+,furi_hal_bt_get_profile_mac_addr,const uint8_t*,FuriHalBtProfile @@ -1161,6 +1169,8 @@ Function,+,furi_hal_console_puts,void,const char* Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*" Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t" Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t" +Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize" +Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp Function,+,furi_hal_cortex_delay_us,void,uint32_t Function,-,furi_hal_cortex_init_early,void, Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t, @@ -1242,6 +1252,7 @@ Function,+,furi_hal_ibutton_pin_configure,void, Function,+,furi_hal_ibutton_pin_reset,void, Function,+,furi_hal_ibutton_pin_write,void,const _Bool Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*" +Function,+,furi_hal_info_get_api_version,void,"uint16_t*, uint16_t*" Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*" Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t Function,+,furi_hal_infrared_async_rx_set_timeout_isr_callback,void,"FuriHalInfraredRxTimeoutCallback, void*" @@ -1350,7 +1361,6 @@ Function,+,furi_hal_random_get,uint32_t, Function,+,furi_hal_region_get,const FuriHalRegion*, Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t Function,+,furi_hal_region_get_name,const char*, -Function,+,furi_hal_region_init,void, Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t Function,+,furi_hal_region_is_provisioned,_Bool, Function,+,furi_hal_region_set,void,FuriHalRegion* @@ -1442,8 +1452,8 @@ Function,-,furi_hal_subghz_dump_state,void, Function,+,furi_hal_subghz_enable_ext_power,_Bool, Function,+,furi_hal_subghz_flush_rx,void, Function,+,furi_hal_subghz_flush_tx,void, -Function,+,furi_hal_subghz_get_extend_settings,void,"_Bool*, _Bool*" Function,+,furi_hal_subghz_get_external_power_disable,_Bool, +Function,+,furi_hal_subghz_get_is_extended,_Bool, Function,+,furi_hal_subghz_get_lqi,uint8_t, Function,+,furi_hal_subghz_get_radio_type,SubGhzRadioType, Function,+,furi_hal_subghz_get_rolling_counter_mult,uint8_t, @@ -1467,10 +1477,10 @@ Function,+,furi_hal_subghz_rx,void, Function,+,furi_hal_subghz_rx_pipe_not_empty,_Bool, Function,+,furi_hal_subghz_select_radio_type,void,SubGhzRadioType Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin* -Function,+,furi_hal_subghz_set_extend_settings,void,"_Bool, _Bool" Function,+,furi_hal_subghz_set_external_power_disable,void,_Bool Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t +Function,+,furi_hal_subghz_set_is_extended,void,_Bool Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath Function,+,furi_hal_subghz_set_rolling_counter_mult,void,uint8_t Function,+,furi_hal_subghz_set_timestamp_file_names,void,_Bool @@ -1523,7 +1533,7 @@ Function,+,furi_hal_version_get_model_name,const char*, Function,+,furi_hal_version_get_name_ptr,const char*, Function,+,furi_hal_version_get_otp_version,FuriHalVersionOtpVersion, Function,-,furi_hal_version_init,void, -Function,+,furi_hal_version_set_custom_name,void,const char* +Function,-,furi_hal_version_set_name,void,const char* Function,+,furi_hal_version_uid,const uint8_t*, Function,+,furi_hal_version_uid_size,size_t, Function,-,furi_hal_vibro_init,void, @@ -1672,7 +1682,7 @@ Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority" Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t" Function,+,furi_thread_set_state_callback,void,"FuriThread*, FuriThreadStateCallback" Function,+,furi_thread_set_state_context,void,"FuriThread*, void*" -Function,+,furi_thread_set_stdout_callback,_Bool,FuriThreadStdoutWriteCallback +Function,+,furi_thread_set_stdout_callback,void,FuriThreadStdoutWriteCallback Function,+,furi_thread_start,void,FuriThread* Function,+,furi_thread_stdout_flush,int32_t, Function,+,furi_thread_stdout_write,size_t,"const char*, size_t" @@ -1681,6 +1691,7 @@ Function,+,furi_thread_yield,void, Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*" Function,+,furi_timer_free,void,FuriTimer* Function,+,furi_timer_is_running,uint32_t,FuriTimer* +Function,+,furi_timer_pending_callback,void,"FuriTimerPendigCallback, void*, uint32_t" Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" Function,+,furi_timer_stop,FuriStatus,FuriTimer* Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" @@ -1910,13 +1921,12 @@ Function,-,llround,long long int,double Function,-,llroundf,long long int,float Function,-,llroundl,long long int,long double Function,+,loader_get_pubsub,FuriPubSub*,Loader* -Function,+,loader_is_locked,_Bool,const Loader* +Function,+,loader_is_locked,_Bool,Loader* Function,+,loader_lock,_Bool,Loader* -Function,+,loader_show_menu,void, -Function,+,loader_show_settings,void, +Function,+,loader_show_menu,void,Loader* +Function,+,loader_show_settings,void,Loader* Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_unlock,void,Loader* -Function,+,loader_update_menu,void, Function,+,loading_alloc,Loading*, Function,+,loading_free,void,Loading* Function,+,loading_get_view,View*,Loading* @@ -4559,7 +4569,6 @@ Function,+,uECC_sign,int,"const uint8_t*, const uint8_t*, unsigned, uint8_t*, uE Function,-,uECC_sign_deterministic,int,"const uint8_t*, const uint8_t*, unsigned, const uECC_HashContext*, uint8_t*, uECC_Curve" Function,-,uECC_valid_public_key,int,"const uint8_t*, uECC_Curve" Function,-,uECC_verify,int,"const uint8_t*, const uint8_t*, unsigned, const uint8_t*, uECC_Curve" -Function,-,ucStreamBufferGetStreamBufferType,uint8_t,StreamBufferHandle_t Function,+,uint8_to_hex_chars,void,"const uint8_t*, uint8_t*, int" Function,-,ulTaskGenericNotifyTake,uint32_t,"UBaseType_t, BaseType_t, TickType_t" Function,-,ulTaskGenericNotifyValueClear,uint32_t,"TaskHandle_t, UBaseType_t, uint32_t" @@ -4571,7 +4580,6 @@ Function,-,usbd_poll,void,usbd_device* Function,-,utf8_show,void, Function,-,utoa,char*,"unsigned, char*, int" Function,-,uxListRemove,UBaseType_t,ListItem_t* -Function,-,uxStreamBufferGetStreamBufferNumber,UBaseType_t,StreamBufferHandle_t Function,-,uxTaskGetNumberOfTasks,UBaseType_t, Function,-,uxTaskGetStackHighWaterMark,UBaseType_t,TaskHandle_t Function,-,uxTaskGetStackHighWaterMark2,uint16_t,TaskHandle_t @@ -4596,8 +4604,6 @@ Function,-,vPortFree,void,void* Function,-,vPortGetHeapStats,void,HeapStats_t* Function,-,vPortInitialiseBlocks,void, Function,-,vPortSuppressTicksAndSleep,void,TickType_t -Function,+,vStreamBufferDelete,void,StreamBufferHandle_t -Function,-,vStreamBufferSetStreamBufferNumber,void,"StreamBufferHandle_t, UBaseType_t" Function,-,vTaskAllocateMPURegions,void,"TaskHandle_t, const MemoryRegion_t*" Function,-,vTaskDelay,void,const TickType_t Function,-,vTaskDelete,void,TaskHandle_t @@ -4662,6 +4668,7 @@ Function,+,version_get_gitbranchnum,const char*,const Version* Function,+,version_get_githash,const char*,const Version* Function,+,version_get_target,uint8_t,const Version* Function,+,version_get_version,const char*,const Version* +Function,-,version_set_custom_name,void,"Version*, const char*" Function,-,vfiprintf,int,"FILE*, const char*, __gnuc_va_list" Function,-,vfiscanf,int,"FILE*, const char*, __gnuc_va_list" Function,-,vfprintf,int,"FILE*, const char*, __gnuc_va_list" @@ -4743,21 +4750,6 @@ Function,+,widget_reset,void,Widget* Function,-,xPortGetFreeHeapSize,size_t, Function,-,xPortGetMinimumEverFreeHeapSize,size_t, Function,-,xPortStartScheduler,BaseType_t, -Function,-,xStreamBufferBytesAvailable,size_t,StreamBufferHandle_t -Function,+,xStreamBufferGenericCreate,StreamBufferHandle_t,"size_t, size_t, BaseType_t" -Function,-,xStreamBufferGenericCreateStatic,StreamBufferHandle_t,"size_t, size_t, BaseType_t, uint8_t*, StaticStreamBuffer_t*" -Function,-,xStreamBufferIsEmpty,BaseType_t,StreamBufferHandle_t -Function,-,xStreamBufferIsFull,BaseType_t,StreamBufferHandle_t -Function,-,xStreamBufferNextMessageLengthBytes,size_t,StreamBufferHandle_t -Function,+,xStreamBufferReceive,size_t,"StreamBufferHandle_t, void*, size_t, TickType_t" -Function,-,xStreamBufferReceiveCompletedFromISR,BaseType_t,"StreamBufferHandle_t, BaseType_t*" -Function,-,xStreamBufferReceiveFromISR,size_t,"StreamBufferHandle_t, void*, size_t, BaseType_t*" -Function,-,xStreamBufferReset,BaseType_t,StreamBufferHandle_t -Function,-,xStreamBufferSend,size_t,"StreamBufferHandle_t, const void*, size_t, TickType_t" -Function,-,xStreamBufferSendCompletedFromISR,BaseType_t,"StreamBufferHandle_t, BaseType_t*" -Function,+,xStreamBufferSendFromISR,size_t,"StreamBufferHandle_t, const void*, size_t, BaseType_t*" -Function,-,xStreamBufferSetTriggerLevel,BaseType_t,"StreamBufferHandle_t, size_t" -Function,-,xStreamBufferSpacesAvailable,size_t,StreamBufferHandle_t Function,-,xTaskAbortDelay,BaseType_t,TaskHandle_t Function,-,xTaskCallApplicationTaskHook,BaseType_t,"TaskHandle_t, void*" Function,-,xTaskCatchUpTicks,BaseType_t,TickType_t diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index c73bbd866..1cb5501d9 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -2,6 +2,7 @@ #include "app_common.h" #include "ble_app.h" #include +#include #include #include @@ -54,6 +55,40 @@ void ble_glue_set_key_storage_changed_callback( ble_glue->context = context; } +/////////////////////////////////////////////////////////////////////////////// + +/* TL hook to catch hardfaults */ + +int32_t ble_glue_TL_SYS_SendCmd(uint8_t* buffer, uint16_t size) { + if(furi_hal_bt_get_hardfault_info()) { + furi_crash("ST(R) Copro(R) HardFault"); + } + + return TL_SYS_SendCmd(buffer, size); +} + +void shci_register_io_bus(tSHciIO* fops) { + /* Register IO bus services */ + fops->Init = TL_SYS_Init; + fops->Send = ble_glue_TL_SYS_SendCmd; +} + +static int32_t ble_glue_TL_BLE_SendCmd(uint8_t* buffer, uint16_t size) { + if(furi_hal_bt_get_hardfault_info()) { + furi_crash("ST(R) Copro(R) HardFault"); + } + + return TL_BLE_SendCmd(buffer, size); +} + +void hci_register_io_bus(tHciIO* fops) { + /* Register IO bus services */ + fops->Init = TL_BLE_Init; + fops->Send = ble_glue_TL_BLE_SendCmd; +} + +/////////////////////////////////////////////////////////////////////////////// + void ble_glue_init() { ble_glue = malloc(sizeof(BleGlue)); ble_glue->status = BleGlueStatusStartup; diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index d60cfe755..a56f54484 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -19,6 +19,8 @@ /* Time, in ms, to wait for mode transition before crashing */ #define C2_MODE_SWITCH_TIMEOUT 10000 +#define FURI_HAL_BT_HARDFAULT_INFO_MAGIC 0x1170FD0F + FuriMutex* furi_hal_bt_core2_mtx = NULL; static FuriHalBtStack furi_hal_bt_stack = FuriHalBtStackUnknown; @@ -212,8 +214,12 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, config->adv_service_uuid |= furi_hal_version_get_hw_color(); } else if(profile == FuriHalBtProfileHidKeyboard) { // Change MAC address for HID profile - uint8_t default_mac[GAP_MAC_ADDR_SIZE] = FURI_HAL_BT_DEFAULT_MAC_ADDR; - if(memcmp(config->mac_address, default_mac, 6) == 0) { + uint8_t default_mac[sizeof(config->mac_address)] = FURI_HAL_BT_DEFAULT_MAC_ADDR; + const uint8_t* normal_mac = furi_hal_version_get_ble_mac(); + if(memcmp(config->mac_address, default_mac, sizeof(config->mac_address)) == 0) { + memcpy(config->mac_address, normal_mac, sizeof(config->mac_address)); + } + if(memcmp(config->mac_address, normal_mac, sizeof(config->mac_address)) == 0) { config->mac_address[2]++; } // Change name Flipper -> Control @@ -469,6 +475,15 @@ bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode) { return false; } +const FuriHalBtHardfaultInfo* furi_hal_bt_get_hardfault_info() { + /* AN5289, 4.8.2 */ + const FuriHalBtHardfaultInfo* info = (FuriHalBtHardfaultInfo*)(SRAM2A_BASE); + if(info->magic != FURI_HAL_BT_HARDFAULT_INFO_MAGIC) { + return NULL; + } + return info; +} + void furi_hal_bt_set_profile_adv_name( FuriHalBtProfile profile, const char name[FURI_HAL_BT_ADV_NAME_LENGTH]) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index a76fbfbca..6283efabc 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -76,6 +76,10 @@ void furi_hal_clock_init() { LL_RCC_LSI1_Enable(); while(!LS_CLOCK_IS_READY()) ; + + /* RF wakeup */ + LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE); + LL_EXTI_EnableIT_0_31( LL_EXTI_LINE_18); /* Why? Because that's why. See RM0434, Table 61. CPU1 vector table. */ LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_18); @@ -145,7 +149,7 @@ void furi_hal_clock_init() { LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLLSAI1); LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_PLLSAI1); LL_RCC_HSI_EnableInStopMode(); // Ensure that MR is capable of work in STOP0 - LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE); + LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI); LL_RCC_SetSMPSPrescaler(LL_RCC_SMPS_DIV_1); LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE); @@ -208,8 +212,8 @@ void furi_hal_clock_switch_to_hsi() { while(!LL_RCC_HSI_IsReady()) ; - LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI); LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + furi_assert(LL_RCC_GetSMPSClockSource() == LL_RCC_SMPS_CLKSOURCE_HSI); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) ; @@ -240,7 +244,6 @@ void furi_hal_clock_switch_to_pll() { ; LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); - LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE); while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) ; diff --git a/firmware/targets/f7/furi_hal/furi_hal_cortex.c b/firmware/targets/f7/furi_hal/furi_hal_cortex.c index d0bce5038..3fbe384e3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_cortex.c +++ b/firmware/targets/f7/furi_hal/furi_hal_cortex.c @@ -1,11 +1,12 @@ #include +#include #include #define FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND (SystemCoreClock / 1000000) void furi_hal_cortex_init_early() { - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + CoreDebug->DEMCR |= (CoreDebug_DEMCR_TRCENA_Msk | CoreDebug_DEMCR_MON_EN_Msk); DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; DWT->CYCCNT = 0U; @@ -38,4 +39,71 @@ bool furi_hal_cortex_timer_is_expired(FuriHalCortexTimer cortex_timer) { void furi_hal_cortex_timer_wait(FuriHalCortexTimer cortex_timer) { while(!furi_hal_cortex_timer_is_expired(cortex_timer)) ; -} \ No newline at end of file +} + +// Duck ST +#undef COMP0 +#undef COMP1 +#undef COMP2 +#undef COMP3 + +void furi_hal_cortex_comp_enable( + FuriHalCortexComp comp, + FuriHalCortexCompFunction function, + uint32_t value, + uint32_t mask, + FuriHalCortexCompSize size) { + uint32_t function_reg = (uint32_t)function | ((uint32_t)size << 10); + + switch(comp) { + case FuriHalCortexComp0: + (DWT->COMP0) = value; + (DWT->MASK0) = mask; + (DWT->FUNCTION0) = function_reg; + break; + case FuriHalCortexComp1: + (DWT->COMP1) = value; + (DWT->MASK1) = mask; + (DWT->FUNCTION1) = function_reg; + break; + case FuriHalCortexComp2: + (DWT->COMP2) = value; + (DWT->MASK2) = mask; + (DWT->FUNCTION2) = function_reg; + break; + case FuriHalCortexComp3: + (DWT->COMP3) = value; + (DWT->MASK3) = mask; + (DWT->FUNCTION3) = function_reg; + break; + default: + furi_crash("Invalid parameter"); + } +} + +void furi_hal_cortex_comp_reset(FuriHalCortexComp comp) { + switch(comp) { + case FuriHalCortexComp0: + (DWT->COMP0) = 0; + (DWT->MASK0) = 0; + (DWT->FUNCTION0) = 0; + break; + case FuriHalCortexComp1: + (DWT->COMP1) = 0; + (DWT->MASK1) = 0; + (DWT->FUNCTION1) = 0; + break; + case FuriHalCortexComp2: + (DWT->COMP2) = 0; + (DWT->MASK2) = 0; + (DWT->FUNCTION2) = 0; + break; + case FuriHalCortexComp3: + (DWT->COMP3) = 0; + (DWT->MASK3) = 0; + (DWT->FUNCTION3) = 0; + break; + default: + furi_crash("Invalid parameter"); + } +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index 464d88d95..94d269345 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -27,7 +27,7 @@ #define FURI_HAL_FLASH_OPT_KEY2 0x4C5D6E7F #define FURI_HAL_FLASH_OB_TOTAL_WORDS (0x80 / (sizeof(uint32_t) * 2)) -/* lib/STM32CubeWB/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_RfWithFlash/Core/Src/flash_driver.c +/* STM32CubeWB/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_RfWithFlash/Core/Src/flash_driver.c * ProcessSingleFlashOperation, quote: > In most BLE application, the flash should not be blocked by the CPU2 longer than FLASH_TIMEOUT_VALUE (1000ms) > However, it could be that for some marginal application, this time is longer. diff --git a/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h b/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h index 36b45755a..9f91db14e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h +++ b/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h @@ -3,7 +3,6 @@ #include #include #include -#include // Timer used for tickless idle #define FURI_HAL_IDLE_TIMER_MAX 0xFFFF diff --git a/firmware/targets/f7/furi_hal/furi_hal_info.c b/firmware/targets/f7/furi_hal/furi_hal_info.c index c984ef4d5..4c034ff35 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_info.c +++ b/firmware/targets/f7/furi_hal/furi_hal_info.c @@ -8,6 +8,11 @@ #include #include +FURI_WEAK void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor) { + *major = 0; + *minor = 0; +} + void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) { FuriString* key = furi_string_alloc(); FuriString* value = furi_string_alloc(); @@ -18,10 +23,10 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) { // Device Info version if(sep == '.') { property_value_out(&property_context, NULL, 2, "format", "major", "3"); - property_value_out(&property_context, NULL, 2, "format", "minor", "0"); + property_value_out(&property_context, NULL, 2, "format", "minor", "1"); } else { property_value_out(&property_context, NULL, 3, "device", "info", "major", "2"); - property_value_out(&property_context, NULL, 3, "device", "info", "minor", "0"); + property_value_out(&property_context, NULL, 3, "device", "info", "minor", "1"); } // Model name @@ -161,6 +166,13 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) { version_get_builddate(firmware_version)); property_value_out( &property_context, "%d", 2, "firmware", "target", version_get_target(firmware_version)); + + uint16_t api_version_major, api_version_minor; + furi_hal_info_get_api_version(&api_version_major, &api_version_minor); + property_value_out( + &property_context, "%d", 3, "firmware", "api", "major", api_version_major); + property_value_out( + &property_context, "%d", 3, "firmware", "api", "minor", api_version_minor); } if(furi_hal_bt_is_alive()) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c index 5ce624d1e..76b401d95 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_light.c +++ b/firmware/targets/f7/furi_hal/furi_hal_light.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #define LED_CURRENT_RED 50 #define LED_CURRENT_GREEN 50 diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index e380de7fa..ec405f108 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -46,43 +46,7 @@ static volatile FuriHalPower furi_hal_power = { .suppress_charge = 0, }; -const ParamCEDV cedv = { - .cedv_conf.gauge_conf = - { - .CCT = 1, - .CSYNC = 0, - .EDV_CMP = 0, - .SC = 1, - .FIXED_EDV0 = 1, - .FCC_LIM = 1, - .FC_FOR_VDQ = 1, - .IGNORE_SD = 1, - .SME0 = 0, - }, - .full_charge_cap = 2101, - .design_cap = 2101, - .EDV0 = 3300, - .EDV1 = 3321, - .EDV2 = 3355, - .EMF = 3679, - .C0 = 430, - .C1 = 0, - .R1 = 408, - .R0 = 334, - .T0 = 4626, - .TC = 11, - .DOD0 = 4044, - .DOD10 = 3905, - .DOD20 = 3807, - .DOD30 = 3718, - .DOD40 = 3642, - .DOD50 = 3585, - .DOD60 = 3546, - .DOD70 = 3514, - .DOD80 = 3477, - .DOD90 = 3411, - .DOD100 = 3299, -}; +#include void furi_hal_power_init() { #ifdef FURI_HAL_POWER_DEBUG diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h new file mode 100644 index 000000000..5eb0f938b --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h @@ -0,0 +1,37 @@ +const ParamCEDV cedv = { + .cedv_conf.gauge_conf = + { + .CCT = 1, + .CSYNC = 0, + .EDV_CMP = 0, + .SC = 1, + .FIXED_EDV0 = 1, + .FCC_LIM = 1, + .FC_FOR_VDQ = 1, + .IGNORE_SD = 1, + .SME0 = 0, + }, + .full_charge_cap = 2101, + .design_cap = 2101, + .EDV0 = 3300, + .EDV1 = 3321, + .EDV2 = 3355, + .EMF = 3679, + .C0 = 430, + .C1 = 0, + .R1 = 408, + .R0 = 334, + .T0 = 4626, + .TC = 11, + .DOD0 = 4044, + .DOD10 = 3905, + .DOD20 = 3807, + .DOD30 = 3718, + .DOD40 = 3642, + .DOD50 = 3585, + .DOD60 = 3546, + .DOD70 = 3514, + .DOD80 = 3477, + .DOD90 = 3411, + .DOD100 = 3299, +}; diff --git a/firmware/targets/f7/furi_hal/furi_hal_region.c b/firmware/targets/f7/furi_hal/furi_hal_region.c index 191ca3873..0f0cb855c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_region.c +++ b/firmware/targets/f7/furi_hal/furi_hal_region.c @@ -1,6 +1,5 @@ #include -#include -#include +#include const FuriHalRegion furi_hal_region_zero = { .country_code = "00", @@ -14,115 +13,18 @@ const FuriHalRegion furi_hal_region_zero = { }, }}; -const FuriHalRegion furi_hal_region_eu_ru = { - .country_code = "EU", - .bands_count = 2, - .bands = { - { - .start = 433050000, - .end = 434790000, - .power_limit = 12, - .duty_cycle = 50, - }, - { - .start = 868150000, - .end = 868550000, - .power_limit = 12, - .duty_cycle = 50, - }}}; - -const FuriHalRegion furi_hal_region_us_ca_au = { - .country_code = "US", - .bands_count = 3, - .bands = { - { - .start = 304100000, - .end = 321950000, - .power_limit = 12, - .duty_cycle = 50, - }, - { - .start = 433050000, - .end = 434790000, - .power_limit = 12, - .duty_cycle = 50, - }, - { - .start = 915000000, - .end = 928000000, - .power_limit = 12, - .duty_cycle = 50, - }}}; - -const FuriHalRegion furi_hal_region_jp = { - .country_code = "JP", - .bands_count = 2, - .bands = { - { - .start = 312000000, - .end = 315250000, - .power_limit = 12, - .duty_cycle = 50, - }, - { - .start = 920500000, - .end = 923500000, - .power_limit = 12, - .duty_cycle = 50, - }}}; - static const FuriHalRegion* furi_hal_region = NULL; -void furi_hal_region_init() { - FuriHalVersionRegion region = furi_hal_version_get_hw_region(); - - if(region == FuriHalVersionRegionUnknown) { - furi_hal_region = &furi_hal_region_zero; - } else if(region == FuriHalVersionRegionEuRu) { - furi_hal_region = &furi_hal_region_eu_ru; - } else if(region == FuriHalVersionRegionUsCaAu) { - furi_hal_region = &furi_hal_region_us_ca_au; - } else if(region == FuriHalVersionRegionJp) { - furi_hal_region = &furi_hal_region_jp; - } -} - const FuriHalRegion* furi_hal_region_get() { - return furi_hal_region; + return &furi_hal_region_zero; } void furi_hal_region_set(FuriHalRegion* region) { - furi_hal_region = region; -} - -bool furi_hal_region_is_provisioned() { - return furi_hal_region != NULL; -} - -const char* furi_hal_region_get_name() { - if(furi_hal_region) { - return furi_hal_region->country_code; - } else { - return "--"; - } -} - -bool furi_hal_region_is_frequency_allowed(uint32_t frequency) { - bool isAllowed = true; - if(!furi_hal_region) { - isAllowed = false; - } - const FuriHalRegionBand* band = furi_hal_region_get_band(frequency); - if(!band) { - isAllowed = false; - } - if(!isAllowed) { - isAllowed = furi_hal_subghz_is_tx_allowed(frequency); - } - return isAllowed; + UNUSED(region); } const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency) { + furi_hal_region = &furi_hal_region_zero; if(!furi_hal_region) { return NULL; } @@ -136,3 +38,16 @@ const FuriHalRegionBand* furi_hal_region_get_band(uint32_t frequency) { return NULL; } + +bool furi_hal_region_is_frequency_allowed(uint32_t frequency) { + UNUSED(frequency); + return true; +} + +bool furi_hal_region_is_provisioned() { + return true; +} + +const char* furi_hal_region_get_name() { + return "00"; +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 573c5b8ab..a7261cc42 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -1,6 +1,6 @@ #include #include -#include + #include #include #include @@ -448,22 +448,21 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { return value; } -void furi_hal_subghz_get_extend_settings(bool* extend, bool* bypass) { - *extend = false; - *bypass = false; +bool furi_hal_subghz_get_is_extended() { + bool is_extended = false; Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); if(flipper_format_file_open_existing(file, "/ext/subghz/assets/extend_range.txt")) { - flipper_format_read_bool(file, "use_ext_range_at_own_risk", extend, 1); - flipper_format_read_bool(file, "ignore_default_tx_region", bypass, 1); + flipper_format_read_bool(file, "use_ext_range_at_own_risk", &is_extended, 1); } flipper_format_free(file); furi_record_close(RECORD_STORAGE); + return is_extended; } -void furi_hal_subghz_set_extend_settings(bool extend, bool bypass) { +void furi_hal_subghz_set_is_extended(bool is_extended) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* file = flipper_format_file_alloc(storage); @@ -473,11 +472,7 @@ void furi_hal_subghz_set_extend_settings(bool extend, bool bypass) { if(!flipper_format_write_comment_cstr( file, "Whether to allow extended ranges that can break your flipper")) break; - if(!flipper_format_write_bool(file, "use_ext_range_at_own_risk", &extend, 1)) break; - if(!flipper_format_write_comment_cstr( - file, "Whether to ignore the default TX region settings")) - break; - if(!flipper_format_write_bool(file, "ignore_default_tx_region", &bypass, 1)) break; + if(!flipper_format_write_bool(file, "use_ext_range_at_own_risk", &is_extended, 1)) break; } while(0); flipper_format_free(file); @@ -485,63 +480,22 @@ void furi_hal_subghz_set_extend_settings(bool extend, bool bypass) { } bool furi_hal_subghz_is_tx_allowed(uint32_t value) { - bool is_extended; - bool is_allowed; - furi_hal_subghz_get_extend_settings(&is_extended, &is_allowed); + bool is_extended = furi_hal_subghz_get_is_extended(); - switch(furi_hal_version_get_hw_region_otp()) { - case FuriHalVersionRegionEuRu: - //433,05..434,79; 868,15..868,55 - if(!(value >= 433050000 && value <= 434790000) && - !(value >= 868150000 && value <= 868550000)) { - } else { - is_allowed = true; - } - break; - case FuriHalVersionRegionUsCaAu: - //304,10..321,95; 433,05..434,79; 915,00..928,00 - if(!(value >= 304100000 && value <= 321950000) && - !(value >= 433050000 && value <= 434790000) && - !(value >= 915000000 && value <= 928000000)) { - } else { - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(value <= 321950000 && - ((furi_hal_subghz.preset == FuriHalSubGhzPresetOok270Async) || - (furi_hal_subghz.preset == FuriHalSubGhzPresetOok650Async))) { - furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable_au); - } - } - is_allowed = true; - } - break; - case FuriHalVersionRegionJp: - //312,00..315,25; 920,50..923,50 - if(!(value >= 312000000 && value <= 315250000) && - !(value >= 920500000 && value <= 923500000)) { - } else { - is_allowed = true; - } - break; - - default: - is_allowed = true; - break; - } - // No flag - test original range, flag set, test extended range if(!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350 !(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75 !(value >= 778999847 && value <= 928000000) && !(is_extended)) { - FURI_LOG_I(TAG, "Frequency blocked - outside regional range"); - is_allowed = false; + FURI_LOG_I(TAG, "Frequency blocked - outside default range"); + return false; } else if( !(value >= 281000000 && value <= 361000000) && !(value >= 378000000 && value <= 481000000) && !(value >= 749000000 && value <= 962000000) && is_extended) { FURI_LOG_I(TAG, "Frequency blocked - outside extended range"); - is_allowed = false; + return false; } - return is_allowed; + return true; } uint32_t furi_hal_subghz_set_frequency(uint32_t value) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.h b/firmware/targets/f7/furi_hal/furi_hal_subghz.h index a292c642f..8383c27f2 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.h +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.h @@ -227,17 +227,15 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value); /** Read extend and bypass settings values into out params * - * @param extend pointer to bool for extend - * @param bypass pointer to bool for bypass + * @return is_extended bool */ -void furi_hal_subghz_get_extend_settings(bool* extend, bool* bypass); +bool furi_hal_subghz_get_is_extended(); /** Set extend and bypass settings values to file * - * @param extend bool for extend - * @param bypass bool for bypass + * @param is_extended bool for extend */ -void furi_hal_subghz_set_extend_settings(bool extend, bool bypass); +void furi_hal_subghz_set_is_extended(bool is_extended); /** Сheck if transmission is allowed on this frequency with your current config * diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h b/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h index 5ea17b6dd..b2b5760fd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h @@ -273,16 +273,6 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00, 0x00}; -static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = { - 0x00, - 0x37, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00}; - static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 0x00, diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index 607560460..32cf5386d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -90,26 +90,13 @@ typedef struct { static FuriHalVersion furi_hal_version = {0}; -void furi_hal_version_set_custom_name(const char* name) { - if((name != NULL) && ((strlen(name) >= 1) && (strlen(name) <= 8))) { +void furi_hal_version_set_name(const char* name) { + if(name != NULL && strlen(name)) { strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); snprintf( furi_hal_version.device_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH, - "x%s", // Someone tell me why that X is needed - name); - - furi_hal_version.device_name[0] = AD_TYPE_COMPLETE_LOCAL_NAME; - } -} - -static void furi_hal_version_set_name(const char* name) { - if(name != NULL) { - strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH); - snprintf( - furi_hal_version.device_name, - FURI_HAL_VERSION_DEVICE_NAME_LENGTH, - "x%s", // Someone tell me why that X is needed + "x%s", // Someone tell me why that X is needed - it's for BLE adv name type (6 lines below) furi_hal_version.name); } else { snprintf(furi_hal_version.device_name, FURI_HAL_VERSION_DEVICE_NAME_LENGTH, "xFlipper"); @@ -119,12 +106,16 @@ static void furi_hal_version_set_name(const char* name) { // BLE Mac address uint32_t udn = LL_FLASH_GetUDN(); - if(version_get_custom_name(NULL) != NULL) { - udn = *((uint32_t*)version_get_custom_name(NULL)); + if(name != NULL) { + udn = *((uint32_t*)name); } uint32_t company_id = LL_FLASH_GetSTCompanyID(); - uint32_t device_id = LL_FLASH_GetDeviceID(); + // uint32_t device_id = LL_FLASH_GetDeviceID(); + // Somehow some new flippers return 0x27 instead of 0x26 + // Mobile apps expects it to return 0x26 (and clearly STM too) + // Temporarely hardcoded until cause / fix is found + uint32_t device_id = 0x26; furi_hal_version.ble_mac[0] = (uint8_t)(udn & 0x000000FF); furi_hal_version.ble_mac[1] = (uint8_t)((udn & 0x0000FF00) >> 8); furi_hal_version.ble_mac[2] = (uint8_t)((udn & 0x00FF0000) >> 16); diff --git a/firmware/targets/f7/target.json b/firmware/targets/f7/target.json index 906ee23ad..c50364453 100644 --- a/firmware/targets/f7/target.json +++ b/firmware/targets/f7/target.json @@ -20,7 +20,7 @@ "flipper7", "furi", "freertos", - "stm32cubewb", + "stm32wb", "hwdrivers", "fatfs", "littlefs", @@ -28,6 +28,7 @@ "flipperformat", "toolbox", "nfc", + "pulse_reader", "microtar", "usb_stm32", "st25rfal002", @@ -40,8 +41,7 @@ "mbedtls", "lfrfid", "flipper_application", - "pulse_reader", "flipperformat", "toolbox" ] -} +} \ No newline at end of file diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index 24817b552..af8c74089 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -224,6 +224,19 @@ uint32_t furi_hal_bt_get_transmitted_packets(); */ bool furi_hal_bt_ensure_c2_mode(BleGlueC2Mode mode); +typedef struct { + uint32_t magic; + uint32_t source_pc; + uint32_t source_lr; + uint32_t source_sp; +} FuriHalBtHardfaultInfo; + +/** Get hardfault info + * + * @return hardfault info. NULL if no hardfault + */ +const FuriHalBtHardfaultInfo* furi_hal_bt_get_hardfault_info(); + /** Modify profile advertisement name and restart bluetooth * @param[in] profile profile type * @param[in] name new adv name diff --git a/firmware/targets/furi_hal_include/furi_hal_cortex.h b/firmware/targets/furi_hal_include/furi_hal_cortex.h index 91596ffe3..ebabbabfd 100644 --- a/firmware/targets/furi_hal_include/furi_hal_cortex.h +++ b/firmware/targets/furi_hal_include/furi_hal_cortex.h @@ -56,6 +56,53 @@ bool furi_hal_cortex_timer_is_expired(FuriHalCortexTimer cortex_timer); */ void furi_hal_cortex_timer_wait(FuriHalCortexTimer cortex_timer); +typedef enum { + FuriHalCortexComp0, + FuriHalCortexComp1, + FuriHalCortexComp2, + FuriHalCortexComp3, +} FuriHalCortexComp; + +typedef enum { + FuriHalCortexCompSizeWord = 0b10, + FuriHalCortexCompSizeHalfWord = 0b01, + FuriHalCortexCompSizeByte = 0b00, +} FuriHalCortexCompSize; + +typedef enum { + FuriHalCortexCompFunctionPC = 0b100, + FuriHalCortexCompFunctionRead = 0b101, + FuriHalCortexCompFunctionWrite = 0b110, + FuriHalCortexCompFunctionReadWrite = 0b110, +} FuriHalCortexCompFunction; + +/** Enable DWT comparator + * + * Allows to programmatically set instruction/data breakpoints. + * + * More details on how it works can be found in armv7m official documentation: + * https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/The-Data-Watchpoint-and-Trace-unit/The-DWT-comparators + * https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/The-Data-Watchpoint-and-Trace-unit/Comparator-Function-registers--DWT-FUNCTIONn + * + * @param[in] comp The Comparator + * @param[in] function The Comparator Function to use + * @param[in] value The value + * @param[in] mask The mask + * @param[in] size The size + */ +void furi_hal_cortex_comp_enable( + FuriHalCortexComp comp, + FuriHalCortexCompFunction function, + uint32_t value, + uint32_t mask, + FuriHalCortexCompSize size); + +/** Reset DWT comparator + * + * @param[in] comp The Comparator + */ +void furi_hal_cortex_comp_reset(FuriHalCortexComp comp); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/furi_hal_include/furi_hal_info.h b/firmware/targets/furi_hal_include/furi_hal_info.h index fa3267f5d..7e8b0e1fb 100644 --- a/firmware/targets/furi_hal_include/furi_hal_info.h +++ b/firmware/targets/furi_hal_include/furi_hal_info.h @@ -14,6 +14,8 @@ extern "C" { #endif +void furi_hal_info_get_api_version(uint16_t* major, uint16_t* minor); + /** Get device information * * @param[in] callback callback to provide with new data diff --git a/firmware/targets/furi_hal_include/furi_hal_region.h b/firmware/targets/furi_hal_include/furi_hal_region.h index ddc8a6a43..9586d51ed 100644 --- a/firmware/targets/furi_hal_include/furi_hal_region.h +++ b/firmware/targets/furi_hal_include/furi_hal_region.h @@ -21,9 +21,6 @@ typedef struct { FuriHalRegionBand bands[]; } FuriHalRegion; -/** Initialize region */ -void furi_hal_region_init(); - /** Get Region Data. * * Region data may be allocated in Flash or in RAM. diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/firmware/targets/furi_hal_include/furi_hal_version.h index 2ff6730f6..3c1755512 100644 --- a/firmware/targets/furi_hal_include/furi_hal_version.h +++ b/firmware/targets/furi_hal_include/furi_hal_version.h @@ -159,7 +159,7 @@ FuriHalVersionDisplay furi_hal_version_get_hw_display(); uint32_t furi_hal_version_get_hw_timestamp(); // Set custom name -void furi_hal_version_set_custom_name(const char* name); +void furi_hal_version_set_name(const char* name); /** Get pointer to target name * diff --git a/furi/core/check.c b/furi/core/check.c index f5390639d..478f3aacc 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -87,6 +88,20 @@ static void __furi_print_stack_info() { __furi_put_uint32_as_text(uxTaskGetStackHighWaterMark(NULL) * 4); } +static void __furi_print_bt_stack_info() { + const FuriHalBtHardfaultInfo* fault_info = furi_hal_bt_get_hardfault_info(); + if(fault_info == NULL) { + furi_hal_console_puts("\r\n\tcore2: not faulted"); + } else { + furi_hal_console_puts("\r\n\tcore2: hardfaulted.\r\n\tPC: "); + __furi_put_uint32_as_hex(fault_info->source_pc); + furi_hal_console_puts("\r\n\tLR: "); + __furi_put_uint32_as_hex(fault_info->source_lr); + furi_hal_console_puts("\r\n\tSP: "); + __furi_put_uint32_as_hex(fault_info->source_sp); + } +} + static void __furi_print_heap_info() { furi_hal_console_puts("\r\n\t heap total: "); __furi_put_uint32_as_text(xPortGetTotalHeapSize()); @@ -136,6 +151,7 @@ FURI_NORETURN void __furi_crash() { __furi_print_stack_info(); } __furi_print_heap_info(); + __furi_print_bt_stack_info(); #ifndef FURI_DEBUG // Check if debug enabled by DAP diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index 1ec847d45..d7bfaf207 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -15,6 +15,10 @@ extern "C" { #define FURI_WARN_UNUSED __attribute__((warn_unused_result)) #endif +#ifndef FURI_WEAK +#define FURI_WEAK __attribute__((weak)) +#endif + #ifndef FURI_IS_IRQ_MASKED #define FURI_IS_IRQ_MASKED() (__get_PRIMASK() != 0U) #endif diff --git a/furi/core/thread.c b/furi/core/thread.c index d78070d61..facbcb411 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -164,10 +164,13 @@ FuriThread* furi_thread_alloc_ex( void furi_thread_free(FuriThread* thread) { furi_assert(thread); - furi_assert(thread->state == FuriThreadStateStopped); - if(thread->name) free((void*)thread->name); - if(thread->appid) free((void*)thread->appid); + // Ensure that use join before free + furi_assert(thread->state == FuriThreadStateStopped); + furi_assert(thread->task_handle == NULL); + + if(thread->name) free(thread->name); + if(thread->appid) free(thread->appid); furi_string_free(thread->output.buffer); free(thread); @@ -176,14 +179,14 @@ void furi_thread_free(FuriThread* thread) { void furi_thread_set_name(FuriThread* thread, const char* name) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); - if(thread->name) free((void*)thread->name); + if(thread->name) free(thread->name); thread->name = name ? strdup(name) : NULL; } void furi_thread_set_appid(FuriThread* thread, const char* appid) { furi_assert(thread); furi_assert(thread->state == FuriThreadStateStopped); - if(thread->appid) free((void*)thread->appid); + if(thread->appid) free(thread->appid); thread->appid = appid ? strdup(appid) : NULL; } @@ -276,7 +279,7 @@ void furi_thread_cleanup_tcb_event(TaskHandle_t task) { if(thread) { // clear thread local storage vTaskSetThreadLocalStoragePointer(task, 0, NULL); - + furi_assert(thread->task_handle == task); thread->task_handle = NULL; } } @@ -332,7 +335,6 @@ FuriThreadId furi_thread_get_current_id() { FuriThread* furi_thread_get_current() { FuriThread* thread = pvTaskGetThreadLocalStoragePointer(NULL, 0); - furi_assert(thread != NULL); return thread; } @@ -579,24 +581,22 @@ static int32_t __furi_thread_stdout_flush(FuriThread* thread) { return 0; } -bool furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback) { +void furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback) { FuriThread* thread = furi_thread_get_current(); - + furi_assert(thread); __furi_thread_stdout_flush(thread); thread->output.write_callback = callback; - - return true; } FuriThreadStdoutWriteCallback furi_thread_get_stdout_callback() { FuriThread* thread = furi_thread_get_current(); - + furi_assert(thread); return thread->output.write_callback; } size_t furi_thread_stdout_write(const char* data, size_t size) { FuriThread* thread = furi_thread_get_current(); - + furi_assert(thread); if(size == 0 || data == NULL) { return __furi_thread_stdout_flush(thread); } else { @@ -619,7 +619,9 @@ size_t furi_thread_stdout_write(const char* data, size_t size) { } int32_t furi_thread_stdout_flush() { - return __furi_thread_stdout_flush(furi_thread_get_current()); + FuriThread* thread = furi_thread_get_current(); + furi_assert(thread); + return __furi_thread_stdout_flush(thread); } void furi_thread_suspend(FuriThreadId thread_id) { diff --git a/furi/core/thread.h b/furi/core/thread.h index b11a225b5..022894ee8 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -233,7 +233,7 @@ FuriThreadId furi_thread_get_current_id(); /** Get FuriThread instance for current thread * - * @return FuriThread* + * @return pointer to FuriThread or NULL if this thread doesn't belongs to Furi */ FuriThread* furi_thread_get_current(); @@ -288,12 +288,10 @@ uint32_t furi_thread_get_stack_space(FuriThreadId thread_id); FuriThreadStdoutWriteCallback furi_thread_get_stdout_callback(); /** Set STDOUT callback for thread - * + * * @param callback callback or NULL to clear - * - * @return true on success, otherwise fail */ -bool furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback); +void furi_thread_set_stdout_callback(FuriThreadStdoutWriteCallback callback); /** Write data to buffered STDOUT * diff --git a/furi/core/timer.c b/furi/core/timer.c index 4b6ccecba..7743ffe70 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -124,3 +124,13 @@ uint32_t furi_timer_is_running(FuriTimer* instance) { /* Return 0: not running, 1: running */ return (uint32_t)xTimerIsTimerActive(hTimer); } + +void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg) { + BaseType_t ret = pdFAIL; + if(furi_kernel_is_irq_or_masked()) { + ret = xTimerPendFunctionCallFromISR(callback, context, arg, NULL); + } else { + ret = xTimerPendFunctionCall(callback, context, arg, FuriWaitForever); + } + furi_check(ret == pdPASS); +} \ No newline at end of file diff --git a/furi/core/timer.h b/furi/core/timer.h index e79c1868d..3f43de5fd 100644 --- a/furi/core/timer.h +++ b/furi/core/timer.h @@ -56,6 +56,10 @@ FuriStatus furi_timer_stop(FuriTimer* instance); */ uint32_t furi_timer_is_running(FuriTimer* instance); +typedef void (*FuriTimerPendigCallback)(void* context, uint32_t arg); + +void furi_timer_pending_callback(FuriTimerPendigCallback callback, void* context, uint32_t arg); + #ifdef __cplusplus } #endif diff --git a/furi/flipper.c b/furi/flipper.c index 8806ce27f..4419877e9 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -4,6 +4,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define TAG "Flipper" @@ -27,23 +37,68 @@ static void flipper_print_version(const char* target, const Version* version) { } } +void flipper_migrate_files() { + if(!furi_hal_is_normal_boot()) return; + Storage* storage = furi_record_open(RECORD_STORAGE); + + // Revert cringe + storage_common_remove(storage, INT_PATH(".passport.settings")); + storage_common_remove(storage, INT_PATH(".region_data")); + + // Migrate files + storage_common_copy(storage, ARCHIVE_FAV_OLD_PATH, ARCHIVE_FAV_PATH); + storage_common_remove(storage, ARCHIVE_FAV_OLD_PATH); + storage_common_copy(storage, BT_SETTINGS_OLD_PATH, BT_SETTINGS_PATH); + storage_common_remove(storage, BT_SETTINGS_OLD_PATH); + storage_common_copy(storage, DOLPHIN_STATE_OLD_PATH, DOLPHIN_STATE_PATH); + storage_common_remove(storage, DOLPHIN_STATE_OLD_PATH); + storage_common_copy(storage, POWER_SETTINGS_OLD_PATH, POWER_SETTINGS_PATH); + storage_common_remove(storage, POWER_SETTINGS_OLD_PATH); + storage_common_copy(storage, BT_KEYS_STORAGE_OLD_PATH, BT_KEYS_STORAGE_PATH); + storage_common_remove(storage, BT_KEYS_STORAGE_OLD_PATH); + storage_common_copy(storage, DESKTOP_SETTINGS_OLD_PATH, DESKTOP_SETTINGS_PATH); + storage_common_remove(storage, DESKTOP_SETTINGS_OLD_PATH); + storage_common_copy(storage, NOTIFICATION_SETTINGS_OLD_PATH, NOTIFICATION_SETTINGS_PATH); + storage_common_remove(storage, NOTIFICATION_SETTINGS_OLD_PATH); + + // Special care for U2F + if(storage_common_exists(storage, U2F_CNT_OLD_FILE)) { // Is on Int + storage_common_remove(storage, U2F_CNT_FILE); // Remove outdated on Ext + storage_common_rename(storage, U2F_CNT_OLD_FILE, U2F_CNT_FILE); // Int -> Ext + } + storage_common_copy(storage, U2F_KEY_OLD_FILE, U2F_KEY_FILE); // Ext -> Int + + furi_record_close(RECORD_STORAGE); +} + +void flipper_start_service(const FlipperApplication* service) { + FURI_LOG_D(TAG, "Starting service %s", service->name); + + FuriThread* thread = + furi_thread_alloc_ex(service->name, service->stack_size, service->app, NULL); + furi_thread_mark_as_service(thread); + furi_thread_set_appid(thread, service->appid); + + furi_thread_start(thread); +} + void flipper_init() { flipper_print_version("Firmware", furi_hal_version_get_firmware_version()); FURI_LOG_I(TAG, "Boot mode %d, starting services", furi_hal_rtc_get_boot_mode()); - for(size_t i = 0; i < FLIPPER_SERVICES_COUNT; i++) { - FURI_LOG_D(TAG, "Starting service %s", FLIPPER_SERVICES[i].name); + // Start storage service first, thanks OFW :/ + flipper_start_service(&FLIPPER_SERVICES[0]); - FuriThread* thread = furi_thread_alloc_ex( - FLIPPER_SERVICES[i].name, - FLIPPER_SERVICES[i].stack_size, - FLIPPER_SERVICES[i].app, - NULL); - furi_thread_mark_as_service(thread); - furi_thread_set_appid(thread, FLIPPER_SERVICES[i].appid); + flipper_migrate_files(); - furi_thread_start(thread); + NAMESPOOF_INIT(); + XTREME_SETTINGS_LOAD(); + XTREME_ASSETS_LOAD(); + + // Everything else + for(size_t i = 1; i < FLIPPER_SERVICES_COUNT; i++) { + flipper_start_service(&FLIPPER_SERVICES[i]); } FURI_LOG_I(TAG, "Startup complete"); @@ -65,4 +120,4 @@ void vApplicationGetTimerTaskMemory( *tcb_ptr = memmgr_alloc_from_pool(sizeof(StaticTask_t)); *stack_ptr = memmgr_alloc_from_pool(sizeof(StackType_t) * configTIMER_TASK_STACK_DEPTH); *stack_size = configTIMER_TASK_STACK_DEPTH; -} \ No newline at end of file +} diff --git a/lib/ReadMe.md b/lib/ReadMe.md index 82dcb74c7..93236b267 100644 --- a/lib/ReadMe.md +++ b/lib/ReadMe.md @@ -1,25 +1,38 @@ # Structure -- `app-scened-template` - Scened template app library -- `app-template` - Template app library +- `FreeRTOS-Kernel` - FreeRTOS kernel source code +- `FreeRTOS-glue` - Extra glue to hold together FreeRTOS kernel and flipper firmware +- `ST25RFAL002` - ST25R3916 Driver and protocol stack +- `app-scened-template` - C++ app library - `callback-connector` - Callback connector library -- `drivers` - Drivers that we wrote -- `fatfs` - External storage file system +- `cmsis_core` - CMSIS Core package, contain cortex-m core headers +- `cxxheaderparser` - C++ headers parser, used by SDK bundler +- `digital_signal` - Digital signal library: used by NFC for software implemented protocols +- `drivers` - Various flipper drivers +- `fatfs` - FatFS file system driver +- `flipper_application` - Flipper application library, used for FAPs - `flipper_format` - Flipper File Format library -- `fnv1a-hash` - Fnv1a hash library -- `heatshrink` - Image compression library -- `infrared` - Infrared library -- `libusb_stm32` - STM32 USB library -- `littlefs` - Internal storage file system -- `micro-ecc` - Elliptic Curve Crytography library -- `microtar` - TAR archive support library -- `mlib` - Algorithms and containers -- `nanopb` - Nano Protobuf library -- `nfc` - Nfc library -- `one_wire` - One wire library -- `qrcode` - Qr code generator library -- `ST25RFAL002` - ST253916 driver and NFC hal -- `STM32CubeWB` - STM32WB series cube package -- `subghz` - SubGhz library -- `toolbox` - Toolbox of things that we are using but don't place in core -- `u8g2` - Graphics library that we use to draw GUI +- `fnv1a-hash` - FNV-1a hash library +- `heatshrink` - Heatshrink compression library +- `ibutton` - ibutton library, used by iButton application +- `infrared` - Infrared library, used by Infrared application +- `lfrfid` - LF-RFID library, used by LF RFID application +- `libusb_stm32` - LibUSB for STM32 series MCU +- `littlefs` - LittleFS file system driver, used by internal storage +- `mbedtls` - MbedTLS cryptography library +- `micro-ecc` - MicroECC cryptography library +- `microtar` - MicroTAR library +- `mlib` - M-Lib C containers library +- `nanopb` - NanoPB library, protobuf implementation for MCU +- `nfc` - NFC library, used by NFC application +- `one_wire` - OneWire library, used by iButton application +- `print` - Tiny printf implementation +- `pulse_reader` - Pulse Reader library used by NFC for software implemented protocols +- `qrcode` - QR-Code library +- `stm32wb_cmsis` - STM32WB series CMSIS headers, extends CMSIS Core +- `stm32wb_copro` - STM32WB Copro library: contains WPAN and radio co-processor firmware +- `stm32wb_hal` - STM32WB HAL library, extends STM32WB CMSIS and provides HAL +- `subghz` - Subghz library, used by SubGhz application +- `toolbox` - Toolbox library, contains various things that is used by flipper firmware +- `u8g2` - u8g2 graphics library, used by GUI subsystem +- `update_util` - update utilities library, used by updater \ No newline at end of file diff --git a/lib/SConscript b/lib/SConscript index 28a508471..b854017f6 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -80,7 +80,7 @@ env.Append( libs = env.BuildModules( [ - "STM32CubeWB", + "stm32wb", "freertos", "print", "microtar", diff --git a/lib/STM32CubeWB b/lib/STM32CubeWB deleted file mode 160000 index a9e29b431..000000000 --- a/lib/STM32CubeWB +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a9e29b431f6dac95b6fc860a717834f35b7f78e5 diff --git a/lib/STM32CubeWB.scons b/lib/STM32CubeWB.scons deleted file mode 100644 index a1b484ad1..000000000 --- a/lib/STM32CubeWB.scons +++ /dev/null @@ -1,78 +0,0 @@ -Import("env") - -env.Append( - CPPPATH=[ - "#/lib/STM32CubeWB/Drivers/CMSIS/Device/ST/STM32WBxx/Include", - "#/lib/STM32CubeWB/Drivers/CMSIS/Include", - "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc", - "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN", - ], - CPPDEFINES=[ - "STM32WB", - "STM32WB55xx", - "USE_FULL_ASSERT", - "USE_FULL_LL_DRIVER", - ], - SDK_HEADERS=[ - *env.GlobRecursive( - "*_ll_*.h", - "#/lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/", - exclude="*usb.h", - ), - File("STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h"), - File( - "STM32CubeWB/Middlewares/Third_Party/FreeRTOS/Source/include/stream_buffer.h" - ), - ], -) - -if env["RAM_EXEC"]: - env.Append( - CPPDEFINES=[ - "VECT_TAB_SRAM", - ], - ) - - -libenv = env.Clone(FW_LIB_NAME="stm32cubewb") -libenv.Append( - CPPPATH=[ - "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/ble", - "#/lib/STM32CubeWB/Middlewares/ST/STM32_WPAN/ble/core", - "#/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", - ] -) -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/cmsis_core/cmsis_armcc.h b/lib/cmsis_core/cmsis_armcc.h new file mode 100644 index 000000000..2edff5af5 --- /dev/null +++ b/lib/cmsis_core/cmsis_armcc.h @@ -0,0 +1,894 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.4.0 + * @date 20. January 2023 + ******************************************************************************/ +/* + * Copyright (c) 2009-2023 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 __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + /* __ARM_ARCH_8_1M_MAIN__ not applicable */ + +/* CMSIS compiler control DSP macros */ +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __ARM_FEATURE_DSP 1 +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(noreturn) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __memory_changed() +#endif +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"), zero_init)) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return result; +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; + __ISB(); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/lib/cmsis_core/cmsis_armclang.h b/lib/cmsis_core/cmsis_armclang.h new file mode 100644 index 000000000..139923dab --- /dev/null +++ b/lib/cmsis_core/cmsis_armclang.h @@ -0,0 +1,1510 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.5.0 + * @date 20. January 2023 + ******************************************************************************/ +/* + * Copyright (c) 2009-2023 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. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** @}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(fpscr) ((void)(fpscr)) +#endif + + +/** @} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/** @} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/lib/cmsis_core/cmsis_armclang_ltm.h b/lib/cmsis_core/cmsis_armclang_ltm.h new file mode 100644 index 000000000..477136e84 --- /dev/null +++ b/lib/cmsis_core/cmsis_armclang_ltm.h @@ -0,0 +1,1934 @@ +/**************************************************************************//** + * @file cmsis_armclang_ltm.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V1.6.0 + * @date 20. January 2023 + ******************************************************************************/ +/* + * Copyright (c) 2018-2023 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. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/lib/cmsis_core/cmsis_compiler.h b/lib/cmsis_core/cmsis_compiler.h new file mode 100644 index 000000000..192f9b7c9 --- /dev/null +++ b/lib/cmsis_core/cmsis_compiler.h @@ -0,0 +1,303 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.3.0 + * @date 04. April 2023 + ******************************************************************************/ +/* + * Copyright (c) 2009-2023 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 __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + +/* + * TI Arm Clang Compiler (tiarmclang) + */ +#elif defined (__ti__) + #include "cmsis_tiarmclang.h" + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler (armcl) + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + #ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) + #endif + #ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) + #endif + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + #ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) + #endif + #ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) + #endif + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + #ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) + #endif + #ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) + #endif + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/lib/cmsis_core/cmsis_gcc.h b/lib/cmsis_core/cmsis_gcc.h new file mode 100644 index 000000000..4f0762d6d --- /dev/null +++ b/lib/cmsis_core/cmsis_gcc.h @@ -0,0 +1,2217 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.4.2 + * @date 17. December 2022 + ******************************************************************************/ +/* + * Copyright (c) 2009-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 __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct __copy_table { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct __zero_table { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".vectors"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL __StackSeal +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi":::"memory") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe":::"memory") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1, ARG2) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + +#define __USAT16(ARG1, ARG2) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) ); + } else { + result = __SXTB16(__ROR(op1, rotate)) ; + } + return result; +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16_RORn(uint32_t op1, uint32_t op2, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtab16 %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1) , "r" (op2) , "i" (rotate)); + } else { + result = __SXTAB16(op1, __ROR(op2, rotate)); + } + return result; +} + + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +#define __PKHBT(ARG1,ARG2,ARG3) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ diff --git a/lib/cmsis_core/cmsis_iccarm.h b/lib/cmsis_core/cmsis_iccarm.h new file mode 100644 index 000000000..47d6a859e --- /dev/null +++ b/lib/cmsis_core/cmsis_iccarm.h @@ -0,0 +1,1008 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.4.0 + * @date 20. January 2023 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2021 IAR Systems +// Copyright (c) 2017-2023 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 +// http://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 __CMSIS_ICCARM_H__ +#define __CMSIS_ICCARM_H__ + +#ifndef __ICCARM__ + #error This file should only be compiled by ICCARM +#endif + +#pragma system_include + +#define __IAR_FT _Pragma("inline=forced") __intrinsic + +#if (__VER__ >= 8000000) + #define __ICCARM_V8 1 +#else + #define __ICCARM_V8 0 +#endif + +#ifndef __ALIGNED + #if __ICCARM_V8 + #define __ALIGNED(x) __attribute__((aligned(x))) + #elif (__VER__ >= 7080000) + /* Needs IAR language extensions */ + #define __ALIGNED(x) __attribute__((aligned(x))) + #else + #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. + #define __ALIGNED(x) + #endif +#endif + + +/* Define compiler macros for CPU architecture, used in CMSIS 5. + */ +#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ +/* Macros already defined */ +#else + #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' + #if __ARM_ARCH == 6 + #define __ARM_ARCH_6M__ 1 + #elif __ARM_ARCH == 7 + #if __ARM_FEATURE_DSP + #define __ARM_ARCH_7EM__ 1 + #else + #define __ARM_ARCH_7M__ 1 + #endif + #endif /* __ARM_ARCH */ + #endif /* __ARM_ARCH_PROFILE == 'M' */ +#endif + +/* Alternativ core deduction for older ICCARM's */ +#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ + !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) + #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) + #define __ARM_ARCH_6M__ 1 + #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) + #define __ARM_ARCH_7M__ 1 + #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) + #define __ARM_ARCH_7EM__ 1 + #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #else + #error "Unknown target." + #endif +#endif + + + +#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 + #define __IAR_M0_FAMILY 1 +#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 + #define __IAR_M0_FAMILY 1 +#else + #define __IAR_M0_FAMILY 0 +#endif + +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".noinit"))) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + +#ifndef __ASM + #define __ASM __asm +#endif + +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +#ifndef __INLINE + #define __INLINE inline +#endif + +#ifndef __NO_RETURN + #if __ICCARM_V8 + #define __NO_RETURN __attribute__((__noreturn__)) + #else + #define __NO_RETURN _Pragma("object_attribute=__noreturn") + #endif +#endif + +#ifndef __PACKED + #if __ICCARM_V8 + #define __PACKED __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED __packed + #endif +#endif + +#ifndef __PACKED_STRUCT + #if __ICCARM_V8 + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_STRUCT __packed struct + #endif +#endif + +#ifndef __PACKED_UNION + #if __ICCARM_V8 + #define __PACKED_UNION union __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_UNION __packed union + #endif +#endif + +#ifndef __RESTRICT + #if __ICCARM_V8 + #define __RESTRICT __restrict + #else + /* Needs IAR language extensions */ + #define __RESTRICT restrict + #endif +#endif + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif + +#ifndef __FORCEINLINE + #define __FORCEINLINE _Pragma("inline=forced") +#endif + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE +#endif + +#ifndef __UNALIGNED_UINT16_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint16_t __iar_uint16_read(void const *ptr) +{ + return *(__packed uint16_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) +#endif + + +#ifndef __UNALIGNED_UINT16_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) +{ + *(__packed uint16_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint32_t __iar_uint32_read(void const *ptr) +{ + return *(__packed uint32_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) +#endif + +#ifndef __UNALIGNED_UINT32_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) +{ + *(__packed uint32_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32 /* deprecated */ +#pragma language=save +#pragma language=extended +__packed struct __iar_u32 { uint32_t v; }; +#pragma language=restore +#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) +#endif + +#ifndef __USED + #if __ICCARM_V8 + #define __USED __attribute__((used)) + #else + #define __USED _Pragma("__root") + #endif +#endif + +#undef __WEAK /* undo the definition from DLib_Defaults.h */ +#ifndef __WEAK + #if __ICCARM_V8 + #define __WEAK __attribute__((weak)) + #else + #define __WEAK _Pragma("__weak") + #endif +#endif + +#ifndef __PROGRAM_START +#define __PROGRAM_START __iar_program_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP CSTACK$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT CSTACK$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __vector_table +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE @".intvec" +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL STACKSEAL$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + +#ifndef __ICCARM_INTRINSICS_VERSION__ + #define __ICCARM_INTRINSICS_VERSION__ 0 +#endif + +#if __ICCARM_INTRINSICS_VERSION__ == 2 + + #if defined(__CLZ) + #undef __CLZ + #endif + #if defined(__REVSH) + #undef __REVSH + #endif + #if defined(__RBIT) + #undef __RBIT + #endif + #if defined(__SSAT) + #undef __SSAT + #endif + #if defined(__USAT) + #undef __USAT + #endif + + #include "iccarm_builtin.h" + + #define __disable_fault_irq __iar_builtin_disable_fiq + #define __disable_irq __iar_builtin_disable_interrupt + #define __enable_fault_irq __iar_builtin_enable_fiq + #define __enable_irq __iar_builtin_enable_interrupt + #define __arm_rsr __iar_builtin_rsr + #define __arm_wsr __iar_builtin_wsr + + + #define __get_APSR() (__arm_rsr("APSR")) + #define __get_BASEPRI() (__arm_rsr("BASEPRI")) + #define __get_CONTROL() (__arm_rsr("CONTROL")) + #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) + + #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + #define __get_FPSCR() (__arm_rsr("FPSCR")) + #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) + #else + #define __get_FPSCR() ( 0 ) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #define __get_IPSR() (__arm_rsr("IPSR")) + #define __get_MSP() (__arm_rsr("MSP")) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __get_MSPLIM() (0U) + #else + #define __get_MSPLIM() (__arm_rsr("MSPLIM")) + #endif + #define __get_PRIMASK() (__arm_rsr("PRIMASK")) + #define __get_PSP() (__arm_rsr("PSP")) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __get_PSPLIM() (0U) + #else + #define __get_PSPLIM() (__arm_rsr("PSPLIM")) + #endif + + #define __get_xPSR() (__arm_rsr("xPSR")) + + #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) + #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) + +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __arm_wsr("CONTROL", control); + __iar_builtin_ISB(); +} + + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) + #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __set_MSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) + #endif + #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) + #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __set_PSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) + #endif + + #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) + +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __arm_wsr("CONTROL_NS", control); + __iar_builtin_ISB(); +} + + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) + #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) + #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) + #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) + #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) + #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) + #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) + #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) + #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) + #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) + #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) + #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __TZ_get_PSPLIM_NS() (0U) + #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) + #else + #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) + #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) + #endif + + #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) + #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) + + #define __NOP __iar_builtin_no_operation + + #define __CLZ __iar_builtin_CLZ + #define __CLREX __iar_builtin_CLREX + + #define __DMB __iar_builtin_DMB + #define __DSB __iar_builtin_DSB + #define __ISB __iar_builtin_ISB + + #define __LDREXB __iar_builtin_LDREXB + #define __LDREXH __iar_builtin_LDREXH + #define __LDREXW __iar_builtin_LDREX + + #define __RBIT __iar_builtin_RBIT + #define __REV __iar_builtin_REV + #define __REV16 __iar_builtin_REV16 + + __IAR_FT int16_t __REVSH(int16_t val) + { + return (int16_t) __iar_builtin_REVSH(val); + } + + #define __ROR __iar_builtin_ROR + #define __RRX __iar_builtin_RRX + + #define __SEV __iar_builtin_SEV + + #if !__IAR_M0_FAMILY + #define __SSAT __iar_builtin_SSAT + #endif + + #define __STREXB __iar_builtin_STREXB + #define __STREXH __iar_builtin_STREXH + #define __STREXW __iar_builtin_STREX + + #if !__IAR_M0_FAMILY + #define __USAT __iar_builtin_USAT + #endif + + #define __WFE __iar_builtin_WFE + #define __WFI __iar_builtin_WFI + + #if __ARM_MEDIA__ + #define __SADD8 __iar_builtin_SADD8 + #define __QADD8 __iar_builtin_QADD8 + #define __SHADD8 __iar_builtin_SHADD8 + #define __UADD8 __iar_builtin_UADD8 + #define __UQADD8 __iar_builtin_UQADD8 + #define __UHADD8 __iar_builtin_UHADD8 + #define __SSUB8 __iar_builtin_SSUB8 + #define __QSUB8 __iar_builtin_QSUB8 + #define __SHSUB8 __iar_builtin_SHSUB8 + #define __USUB8 __iar_builtin_USUB8 + #define __UQSUB8 __iar_builtin_UQSUB8 + #define __UHSUB8 __iar_builtin_UHSUB8 + #define __SADD16 __iar_builtin_SADD16 + #define __QADD16 __iar_builtin_QADD16 + #define __SHADD16 __iar_builtin_SHADD16 + #define __UADD16 __iar_builtin_UADD16 + #define __UQADD16 __iar_builtin_UQADD16 + #define __UHADD16 __iar_builtin_UHADD16 + #define __SSUB16 __iar_builtin_SSUB16 + #define __QSUB16 __iar_builtin_QSUB16 + #define __SHSUB16 __iar_builtin_SHSUB16 + #define __USUB16 __iar_builtin_USUB16 + #define __UQSUB16 __iar_builtin_UQSUB16 + #define __UHSUB16 __iar_builtin_UHSUB16 + #define __SASX __iar_builtin_SASX + #define __QASX __iar_builtin_QASX + #define __SHASX __iar_builtin_SHASX + #define __UASX __iar_builtin_UASX + #define __UQASX __iar_builtin_UQASX + #define __UHASX __iar_builtin_UHASX + #define __SSAX __iar_builtin_SSAX + #define __QSAX __iar_builtin_QSAX + #define __SHSAX __iar_builtin_SHSAX + #define __USAX __iar_builtin_USAX + #define __UQSAX __iar_builtin_UQSAX + #define __UHSAX __iar_builtin_UHSAX + #define __USAD8 __iar_builtin_USAD8 + #define __USADA8 __iar_builtin_USADA8 + #define __SSAT16 __iar_builtin_SSAT16 + #define __USAT16 __iar_builtin_USAT16 + #define __UXTB16 __iar_builtin_UXTB16 + #define __UXTAB16 __iar_builtin_UXTAB16 + #define __SXTB16 __iar_builtin_SXTB16 + #define __SXTAB16 __iar_builtin_SXTAB16 + #define __SMUAD __iar_builtin_SMUAD + #define __SMUADX __iar_builtin_SMUADX + #define __SMMLA __iar_builtin_SMMLA + #define __SMLAD __iar_builtin_SMLAD + #define __SMLADX __iar_builtin_SMLADX + #define __SMLALD __iar_builtin_SMLALD + #define __SMLALDX __iar_builtin_SMLALDX + #define __SMUSD __iar_builtin_SMUSD + #define __SMUSDX __iar_builtin_SMUSDX + #define __SMLSD __iar_builtin_SMLSD + #define __SMLSDX __iar_builtin_SMLSDX + #define __SMLSLD __iar_builtin_SMLSLD + #define __SMLSLDX __iar_builtin_SMLSLDX + #define __SEL __iar_builtin_SEL + #define __QADD __iar_builtin_QADD + #define __QSUB __iar_builtin_QSUB + #define __PKHBT __iar_builtin_PKHBT + #define __PKHTB __iar_builtin_PKHTB + #endif + +#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #define __CLZ __cmsis_iar_clz_not_active + #define __SSAT __cmsis_iar_ssat_not_active + #define __USAT __cmsis_iar_usat_not_active + #define __RBIT __cmsis_iar_rbit_not_active + #define __get_APSR __cmsis_iar_get_APSR_not_active + #endif + + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #define __get_FPSCR __cmsis_iar_get_FPSR_not_active + #define __set_FPSCR __cmsis_iar_set_FPSR_not_active + #endif + + #ifdef __INTRINSICS_INCLUDED + #error intrinsics.h is already included previously! + #endif + + #include + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #undef __CLZ + #undef __SSAT + #undef __USAT + #undef __RBIT + #undef __get_APSR + + __STATIC_INLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_INLINE uint32_t __RBIT(uint32_t v) + { + uint8_t sc = 31U; + uint32_t r = v; + for (v >>= 1U; v; v >>= 1U) + { + r <<= 1U; + r |= v & 1U; + sc--; + } + return (r << sc); + } + + __STATIC_INLINE uint32_t __get_APSR(void) + { + uint32_t res; + __asm("MRS %0,APSR" : "=r" (res)); + return res; + } + + #endif + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #undef __get_FPSCR + #undef __set_FPSCR + #define __get_FPSCR() (0) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #pragma diag_suppress=Pe940 + #pragma diag_suppress=Pe177 + + #define __enable_irq __enable_interrupt + #define __disable_irq __disable_interrupt + #define __NOP __no_operation + + #define __get_xPSR __get_PSR + + #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) + + __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) + { + return __LDREX((unsigned long *)ptr); + } + + __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) + { + return __STREX(value, (unsigned long *)ptr); + } + #endif + + + /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + #if (__CORTEX_M >= 0x03) + + __IAR_FT uint32_t __RRX(uint32_t value) + { + uint32_t result; + __ASM volatile("RRX %0, %1" : "=r"(result) : "r" (value)); + return(result); + } + + __IAR_FT void __set_BASEPRI_MAX(uint32_t value) + { + __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); + } + + + #define __enable_fault_irq __enable_fiq + #define __disable_fault_irq __disable_fiq + + + #endif /* (__CORTEX_M >= 0x03) */ + + __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) + { + return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); + } + + #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + __IAR_FT uint32_t __get_MSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,MSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_MSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR MSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __get_PSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_PSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) + { + __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + __iar_builtin_ISB(); + } + + __IAR_FT uint32_t __TZ_get_PSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PSP_NS(uint32_t value) + { + __asm volatile("MSR PSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_MSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSP_NS(uint32_t value) + { + __asm volatile("MSR MSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_SP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,SP_NS" : "=r" (res)); + return res; + } + __IAR_FT void __TZ_set_SP_NS(uint32_t value) + { + __asm volatile("MSR SP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) + { + __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) + { + __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) + { + __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) + { + __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); + } + + #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + +#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) + +#if __IAR_M0_FAMILY + __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + + __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) + { + uint32_t res; + __ASM volatile ("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) + { + uint32_t res; + __ASM volatile ("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) + { + uint32_t res; + __ASM volatile ("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return res; + } + + __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) + { + __ASM volatile ("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) + { + __ASM volatile ("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) + { + __ASM volatile ("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); + } + +#endif /* (__CORTEX_M >= 0x03) */ + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + + __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) + { + __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) + { + __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) + { + __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + +#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#undef __IAR_FT +#undef __IAR_M0_FAMILY +#undef __ICCARM_V8 + +#pragma diag_default=Pe940 +#pragma diag_default=Pe177 + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +#endif /* __CMSIS_ICCARM_H__ */ diff --git a/lib/cmsis_core/cmsis_tiarmclang.h b/lib/cmsis_core/cmsis_tiarmclang.h new file mode 100644 index 000000000..4d799c277 --- /dev/null +++ b/lib/cmsis_core/cmsis_tiarmclang.h @@ -0,0 +1,1510 @@ +/**************************************************************************//** + * @file cmsis_tiarmclang.h + * @brief CMSIS compiler tiarmclang header file + * @version V1.0.0 + * @date 04. April 2023 + ******************************************************************************/ +/* + * Copyright (c) 2023 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. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_TIARMCLANG_H +#define __CMSIS_TIARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif +#ifndef __NO_INIT + #define __NO_INIT __attribute__ ((section (".bss.noinit"))) +#endif +#ifndef __ALIAS + #define __ALIAS(x) __attribute__ ((alias(x))) +#endif + + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START _c_int00 +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __STACK_END +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __STACK_SIZE +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".intvecs"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** @}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(fpscr) ((void)(fpscr)) +#endif + + +/** @} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/** @} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_TIARMCLANG_H */ diff --git a/lib/cmsis_core/cmsis_version.h b/lib/cmsis_core/cmsis_version.h new file mode 100644 index 000000000..8b4765f18 --- /dev/null +++ b/lib/cmsis_core/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.5 + * @date 02. February 2022 + ******************************************************************************/ +/* + * Copyright (c) 2009-2022 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. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 6U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/lib/cmsis_core/core_cm4.h b/lib/cmsis_core/core_cm4.h new file mode 100644 index 000000000..711c11326 --- /dev/null +++ b/lib/cmsis_core/core_cm4.h @@ -0,0 +1,2170 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.2.0 + * @date 04. April 2023 + ******************************************************************************/ +/* + * Copyright (c) 2009-2023 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. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (4U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ti__) + #if defined (__ARM_FP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 1U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_BYTEACC_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_BYTEACC_Msk (1UL << ITM_LSR_BYTEACC_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_ACCESS_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_ACCESS_Msk (1UL << ITM_LSR_ACCESS_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_PRESENT_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_PRESENT_Msk (1UL /*<< ITM_LSR_PRESENT_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_register_aliases Backwards Compatibility Aliases + \brief Register alias definitions for backwards compatibility. + @{ + */ + +/* Capitalize ITM_TCR Register Definitions */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_TraceBusID_Pos (ITM_TCR_TRACEBUSID_Pos) /*!< \deprecated ITM_TCR_TraceBusID_Pos */ +#define ITM_TCR_TraceBusID_Msk (ITM_TCR_TRACEBUSID_Msk) /*!< \deprecated ITM_TCR_TraceBusID_Msk */ + +#define ITM_TCR_TSPrescale_Pos (ITM_TCR_TSPRESCALE_Pos) /*!< \deprecated ITM_TCR_TSPrescale_Pos */ +#define ITM_TCR_TSPrescale_Msk (ITM_TCR_TSPRESCALE_Msk) /*!< \deprecated ITM_TCR_TSPrescale_Msk */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos (ITM_LSR_BYTEACC_Pos) /*!< \deprecated ITM_LSR_ByteAcc_Pos */ +#define ITM_LSR_ByteAcc_Msk (ITM_LSR_BYTEACC_Msk) /*!< \deprecated ITM_LSR_ByteAcc_Msk */ + +#define ITM_LSR_Access_Pos (ITM_LSR_ACCESS_Pos) /*!< \deprecated ITM_LSR_Access_Pos */ +#define ITM_LSR_Access_Msk (ITM_LSR_ACCESS_Msk) /*!< \deprecated ITM_LSR_Access_Msk */ + +#define ITM_LSR_Present_Pos (ITM_LSR_PRESENT_Pos) /*!< \deprecated ITM_LSR_Present_Pos */ +#define ITM_LSR_Present_Msk (ITM_LSR_PRESENT_Msk) /*!< \deprecated ITM_LSR_Present_Msk */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M4 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/lib/cmsis_core/mpu_armv7.h b/lib/cmsis_core/mpu_armv7.h new file mode 100644 index 000000000..d9eedf81a --- /dev/null +++ b/lib/cmsis_core/mpu_armv7.h @@ -0,0 +1,275 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.2 + * @date 25. May 2020 + ******************************************************************************/ +/* + * Copyright (c) 2017-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. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + __DMB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; + __DSB(); + __ISB(); +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load(). +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/lib/digital_signal/digital_signal.c b/lib/digital_signal/digital_signal.c index 59278277c..51a87d22a 100644 --- a/lib/digital_signal/digital_signal.c +++ b/lib/digital_signal/digital_signal.c @@ -51,6 +51,16 @@ struct DigitalSignalInternals { #define T_TIM 1562 /* 15.625 ns *100 */ #define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */ +/* maximum entry count of the sequence dma ring buffer */ +#define SEQUENCE_DMA_RINGBUFFER_SIZE 32 +/* maximum number of DigitalSignals in a sequence */ +#define SEQUENCE_SIGNALS_SIZE 32 +/* + * if sequence size runs out from the initial value passed to digital_sequence_alloc + * the size will be increased by this amount and reallocated + */ +#define SEQUENCE_SIZE_REALLOCATE_INCREMENT 256 + DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) { DigitalSignal* signal = malloc(sizeof(DigitalSignal)); signal->start_level = true; @@ -90,10 +100,6 @@ DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) { void digital_signal_free(DigitalSignal* signal) { furi_assert(signal); - if(!signal) { - return; - } - free(signal->edge_timings); free(signal->reload_reg_buff); free(signal->internals); @@ -293,8 +299,6 @@ void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) { furi_hal_gpio_init( signal->internals->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - /* single signal, add a temporary, terminating edge at the end */ - signal->edge_timings[signal->edge_cnt++] = 10; digital_signal_prepare_arr(signal); digital_signal_setup_dma(signal); @@ -306,8 +310,6 @@ void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) { digital_signal_stop_timer(); digital_signal_stop_dma(); - - signal->edge_cnt--; } static void digital_sequence_alloc_signals(DigitalSequence* sequence, uint32_t size) { @@ -332,7 +334,7 @@ DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) { sequence->bake = false; sequence->dma_buffer = malloc(sizeof(struct ReloadBuffer)); - sequence->dma_buffer->size = 32; + sequence->dma_buffer->size = SEQUENCE_DMA_RINGBUFFER_SIZE; sequence->dma_buffer->buffer = malloc(sequence->dma_buffer->size * sizeof(uint32_t)); sequence->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; @@ -357,7 +359,7 @@ DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) { sequence->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; sequence->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH; - digital_sequence_alloc_signals(sequence, 32); + digital_sequence_alloc_signals(sequence, SEQUENCE_SIGNALS_SIZE); digital_sequence_alloc_sequence(sequence, size); return sequence; @@ -366,10 +368,6 @@ DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) { void digital_sequence_free(DigitalSequence* sequence) { furi_assert(sequence); - if(!sequence) { - return; - } - free(sequence->signals); free(sequence->sequence); free(sequence->dma_buffer->buffer); @@ -404,8 +402,9 @@ void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) { furi_assert(signal_index < sequence->signals_size); if(sequence->sequence_used >= sequence->sequence_size) { - sequence->sequence_size += 256; - sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); + sequence->sequence_size += SEQUENCE_SIZE_REALLOCATE_INCREMENT; + sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); //-V701 + furi_assert(sequence->sequence); } sequence->sequence[sequence->sequence_used++] = signal_index; @@ -479,7 +478,7 @@ static void digital_sequence_finish(DigitalSequence* sequence) { break; } - if(last_pos != dma_buffer->read_pos) { + if(last_pos != dma_buffer->read_pos) { //-V547 prev_timer = DWT->CYCCNT; } if(DWT->CYCCNT - prev_timer > wait_ticks) { @@ -513,7 +512,7 @@ static void digital_sequence_queue_pulse(DigitalSequence* sequence, uint32_t len break; } - if(last_pos != dma_buffer->read_pos) { + if(last_pos != dma_buffer->read_pos) { //-V547 prev_timer = DWT->CYCCNT; } if(DWT->CYCCNT - prev_timer > wait_ticks) { diff --git a/lib/digital_signal/digital_signal.h b/lib/digital_signal/digital_signal.h index 40afb1e41..404d02605 100644 --- a/lib/digital_signal/digital_signal.h +++ b/lib/digital_signal/digital_signal.h @@ -11,10 +11,10 @@ extern "C" { #endif /* helper for easier signal generation */ -#define DIGITAL_SIGNAL_MS(x) (x * 100000000UL) -#define DIGITAL_SIGNAL_US(x) (x * 100000UL) -#define DIGITAL_SIGNAL_NS(x) (x * 100UL) -#define DIGITAL_SIGNAL_PS(x) (x / 10UL) +#define DIGITAL_SIGNAL_MS(x) ((x)*100000000UL) +#define DIGITAL_SIGNAL_US(x) ((x)*100000UL) +#define DIGITAL_SIGNAL_NS(x) ((x)*100UL) +#define DIGITAL_SIGNAL_PS(x) ((x) / 10UL) /* using an anonymous type for the internals */ typedef struct DigitalSignalInternals DigitalSignalInternals; @@ -52,15 +52,22 @@ uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num); void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio); DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio); + void digital_sequence_free(DigitalSequence* sequence); + void digital_sequence_set_signal( DigitalSequence* sequence, uint8_t signal_index, DigitalSignal* signal); + void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time); + void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index); + bool digital_sequence_send(DigitalSequence* sequence); + void digital_sequence_clear(DigitalSequence* sequence); + void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor); #ifdef __cplusplus diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript index 3b7ee2401..7cbd42b37 100644 --- a/lib/drivers/SConscript +++ b/lib/drivers/SConscript @@ -4,6 +4,9 @@ env.Append( CPPPATH=[ "#/lib/drivers", ], + SDK_HEADERS=[ + File("rgb_backlight.h"), + ], ) diff --git a/applications/services/rgb_backlight/rgb_backlight.c b/lib/drivers/rgb_backlight.c similarity index 98% rename from applications/services/rgb_backlight/rgb_backlight.c rename to lib/drivers/rgb_backlight.c index 2dbfa7e8c..ec39efb0b 100644 --- a/applications/services/rgb_backlight/rgb_backlight.c +++ b/lib/drivers/rgb_backlight.c @@ -103,7 +103,7 @@ void rgb_backlight_load_settings(void) { storage_file_free(file); furi_record_close(RECORD_STORAGE); rgb_settings.settings_is_loaded = true; -}; +} void rgb_backlight_save_settings(void) { RGBBacklightSettings settings; @@ -134,7 +134,7 @@ void rgb_backlight_save_settings(void) { storage_file_close(file); storage_file_free(file); furi_record_close(RECORD_STORAGE); -}; +} RGBBacklightSettings* rgb_backlight_get_settings(void) { if(!rgb_settings.settings_is_loaded) { @@ -172,8 +172,3 @@ void rgb_backlight_update(uint8_t brightness) { SK6805_update(); } - -int32_t rgb_backlight_srv(void* p) { - UNUSED(p); - return 0; -} diff --git a/applications/services/rgb_backlight/rgb_backlight.h b/lib/drivers/rgb_backlight.h similarity index 100% rename from applications/services/rgb_backlight/rgb_backlight.h rename to lib/drivers/rgb_backlight.h diff --git a/lib/flipper_format/SConscript b/lib/flipper_format/SConscript index 353da8035..9c9e8b6f3 100644 --- a/lib/flipper_format/SConscript +++ b/lib/flipper_format/SConscript @@ -7,6 +7,7 @@ env.Append( SDK_HEADERS=[ File("flipper_format.h"), File("flipper_format_i.h"), + File("flipper_format_stream.h"), ], ) diff --git a/lib/freertos.scons b/lib/freertos.scons index 1c5a5bf54..cb0006e56 100644 --- a/lib/freertos.scons +++ b/lib/freertos.scons @@ -7,9 +7,6 @@ env.Append( "#/lib/FreeRTOS-Kernel/portable/GCC/ARM_CM4F", "#/lib/FreeRTOS-glue", ], - CPPDEFINES=[ - "HAVE_FREERTOS", - ], ) diff --git a/lib/libusb_stm32.scons b/lib/libusb_stm32.scons index 4838b7c50..ccc5de24f 100644 --- a/lib/libusb_stm32.scons +++ b/lib/libusb_stm32.scons @@ -4,9 +4,6 @@ env.Append( CPPPATH=[ "#/lib/libusb_stm32/inc", ], - CPPDEFINES=[ - ("USB_PMASIZE", "0x400"), - ], SDK_HEADERS=env.GlobRecursive( "*.h", Dir("libusb_stm32/inc"), @@ -16,6 +13,11 @@ env.Append( libenv = env.Clone(FW_LIB_NAME="usb_stm32") libenv.ApplyLibFlags() +libenv.Append( + CPPDEFINES=[ + ("USB_PMASIZE", "0x400"), + ], +) sources = [ diff --git a/lib/littlefs.scons b/lib/littlefs.scons index 792142c32..3d68e07ba 100644 --- a/lib/littlefs.scons +++ b/lib/littlefs.scons @@ -4,14 +4,16 @@ env.Append( CPPPATH=[ "#/lib/littlefs", ], - CPPDEFINES=[ - ("LFS_CONFIG", "lfs_config.h"), - ], ) libenv = env.Clone(FW_LIB_NAME="littlefs") libenv.ApplyLibFlags() +libenv.Append( + CPPDEFINES=[ + ("LFS_CONFIG", "lfs_config.h"), + ], +) sources = Glob("littlefs/*.c", source=True) diff --git a/lib/misc.scons b/lib/misc.scons index 63681f2f2..9ba518579 100644 --- a/lib/misc.scons +++ b/lib/misc.scons @@ -1,7 +1,7 @@ -Import("env") - from fbt.util import GLOB_FILE_EXCLUSION +Import("env") + env.Append( CPPPATH=[ "#/lib/digital_signal", diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 1d66ced68..793f733e4 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -66,6 +66,7 @@ typedef enum { NfcReadModeEMV, NfcReadModeNFCA, NfcReadModeFelica, + NfcReadModeNFCF, } NfcReadMode; typedef struct { diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index dee97c136..9314a4e53 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -756,6 +756,10 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) { break; } } + } else if(read_mode == NfcReadModeNFCF) { + nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; + event = NfcWorkerEventReadUidNfcF; + break; } } } else { diff --git a/lib/nfc/protocols/felica.c b/lib/nfc/protocols/felica.c index d9489cb50..827187564 100644 --- a/lib/nfc/protocols/felica.c +++ b/lib/nfc/protocols/felica.c @@ -8,13 +8,15 @@ #define TAG "FeliCa" bool felica_check_ic_type(uint8_t* PMm) { - uint8_t ic_type = PMm[0]; - uint8_t rom_type = PMm[1]; + uint8_t rom_type = PMm[0]; + uint8_t ic_type = PMm[1]; bool is_valid_ic = false; if(ic_type == 0xff) { // RC-S967 in nfc-dep is_valid_ic = true; - } else if(ic_type == 0xf0 || ic_type == 0xf2) { // Lite(S) + } else if(ic_type == 0xf2) { // RC-S732? + is_valid_ic = true; + } else if(ic_type == 0xf0 || ic_type == 0xf1) { // Lite(S) is_valid_ic = true; } else if(ic_type == 0xe1) { // RC-S967 in plug mode is_valid_ic = true; @@ -149,6 +151,55 @@ FelicaICType felica_get_ic_type(uint8_t* PMm) { return FelicaICType2K; } +/** Parse common FeliCa response headers. + * + * This parses and validates the most commonly occurring response header types. + * + * The header needs to match the (length, res, idm) format, and also (sf1, sf2) when always_succeed + * is set to false. + * + * @param buf RX buffer. + * @param len RX buffer length. + * @param reader The FeliCa reader context. + * @param expected_resp Expected response code. Must be an odd number. + * @param always_succeed When set to true, skip status flags (sf1 and sf2) parsing. + * @return The number of bytes parsed, or 0 when response is invalid or status flags are set. + */ +static uint8_t felica_consume_header( + uint8_t* buf, + uint8_t len, + FelicaReader* reader, + uint8_t expected_resp, + bool always_succeed) { + furi_assert(expected_resp & 1); + furi_assert(buf != NULL); + furi_assert(reader != NULL); + + uint8_t header_size = always_succeed ? 10 : 12; + if(len < header_size) { + FURI_LOG_E(TAG, "Malformed header: too short."); + return 0; + } + if(buf[1] != expected_resp) { + FURI_LOG_E(TAG, "Expecting %u, got %u.", expected_resp, buf[1]); + return 0; + } + if(memcmp(&buf[2], reader->current_idm, 8) != 0) { + FURI_LOG_E(TAG, "IDm mismatch."); + return 0; + } + if(always_succeed) { + reader->status_flags[0] = buf[10]; + reader->status_flags[1] = buf[11]; + if(reader->status_flags[0] != 0 || reader->status_flags[1] != 0) { + FURI_LOG_W( + TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]); + return 0; + } + } + return header_size; +} + uint8_t felica_prepare_unencrypted_read( uint8_t* dest, const FelicaReader* reader, @@ -210,32 +261,12 @@ uint16_t felica_parse_unencrypted_read( FelicaReader* reader, uint8_t* out, uint16_t out_len) { - if(len < 12) { - return false; - } - len--; - buf++; - - if(*buf != FELICA_UNENCRYPTED_READ_RES) { - return false; - } - len--; - buf++; - - if(memcmp(buf, reader->current_idm, 8) != 0) { - return false; - } - len -= 8; - buf += 8; - - reader->status_flags[0] = buf[0]; - reader->status_flags[1] = buf[1]; - len -= 2; - buf += 2; - if(reader->status_flags[0] != 0) { - FURI_LOG_W(TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]); + uint8_t consumed = felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_READ_RES, false); + if(!consumed) { return 0; } + len -= consumed; + buf += consumed; if(len < 1) { return 0; @@ -313,48 +344,77 @@ uint8_t felica_lite_prepare_unencrypted_write( } bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* reader) { - if(len < 12) { + uint8_t consumed = + felica_consume_header(buf, len, reader, FELICA_UNENCRYPTED_WRITE_RES, false); + if(!consumed) { return false; } + return true; +} + +uint8_t felica_prepare_request_system_code(uint8_t* dest, FelicaReader* reader) { + dest[0] = FELICA_REQUEST_SYSTEM_CODE_CMD; + memcpy(&dest[1], reader->current_idm, 8); + return 9; +} + +bool felica_parse_request_system_code( + uint8_t* buf, + uint8_t len, + FelicaReader* reader, + FelicaSystemArray_t* systems) { + uint8_t consumed = + felica_consume_header(buf, len, reader, FELICA_REQUEST_SYSTEM_CODE_RES, true); + if(consumed == 0) { + return false; + } + len -= consumed; + buf += consumed; + + uint8_t entries = *buf; len--; buf++; - if(*buf != FELICA_UNENCRYPTED_WRITE_RES) { + if(len < 2 * entries) { + FURI_LOG_E(TAG, "FELICA_REQUEST_SYSTEM_CODE_RES: Response too short"); return false; } - len--; - buf++; - if(memcmp(buf, reader->current_idm, 8) != 0) { - return false; - } - len -= 8; - buf += 8; + for(uint8_t idx = 0; idx < entries; idx++) { + FelicaSystem* system = FelicaSystemArray_push_new(*systems); + furi_assert(system != NULL); - reader->status_flags[0] = buf[0]; - reader->status_flags[1] = buf[1]; - len -= 2; - buf += 2; - if(reader->status_flags[0] != 0) { - FURI_LOG_W(TAG, "SF1: %02X SF2: %02X", reader->status_flags[0], reader->status_flags[1]); - return 0; + // Set system code + system->number = idx; + system->code = buf[2 * idx] | (buf[2 * idx + 1] << 8); + + FURI_LOG_D(TAG, "Found system code %04X", system->code); + + // Fill in IDm and PMm + memcpy(system->idm, reader->current_idm, 8); + memcpy(system->pmm, reader->current_pmm, 8); + + // Set system index field in IDm + system->idm[0] &= 0x0f; + system->idm[0] |= ((idx & 0xf) << 4); } return true; } -void felica_parse_system_info(FelicaSystem* system, uint8_t* IDm, uint8_t* PMm) { - memcpy(system->idm, IDm, 8); - memcpy(system->pmm, PMm, 8); - for(int i = 0; i < 6; i++) { - char MRT_byte = PMm[2 + i]; - FelicaMRTParts* mrt_data = &system->maximum_response_times[i]; - mrt_data->real_a = (MRT_byte & 7) + 1; - MRT_byte >>= 3; - mrt_data->real_b = (MRT_byte & 7) + 1; - MRT_byte >>= 3; - mrt_data->exponent = (MRT_byte & 3); - } +static FelicaSystem* felica_gen_monolithic_system_code( + FelicaReader* reader, + FelicaSystemArray_t* systems, + uint16_t system_code) { + FelicaSystem* system = FelicaSystemArray_push_new(*systems); + furi_assert(reader != NULL); + furi_assert(system != NULL); + + memcpy(system->idm, reader->current_idm, 8); + memcpy(system->pmm, reader->current_pmm, 8); + system->code = system_code; + + return system; } bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number) { @@ -366,12 +426,16 @@ bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number) } void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data) { - FelicaBlock* block = malloc(sizeof(FelicaBlock)); + FelicaBlock* block = FelicaBlockArray_safe_get(service->blocks, number); memcpy(block->data, data, FELICA_BLOCK_SIZE); - FelicaBlockList_set_at(service->blocks, number, block); } -bool felica_read_lite_system( +void felica_push_normal_block(FelicaService* service, uint8_t* data) { + FelicaBlock* block = FelicaBlockArray_push_new(service->blocks); + memcpy(block->data, data, FELICA_BLOCK_SIZE); +} + +bool felica_lite_dump_data( FuriHalNfcTxRxContext* tx_rx, FelicaReader* reader, FelicaData* data, @@ -423,8 +487,6 @@ bool felica_read_lite_system( return false; } - system->code = LITE_SYSTEM_CODE; - FelicaLiteInfo* lite_info = &system->lite_info; lite_info->card_key_1 = NULL; lite_info->card_key_2 = NULL; @@ -566,6 +628,22 @@ bool felica_read_lite_system( return true; } +bool felica_std_request_system_code( + FuriHalNfcTxRxContext* tx_rx, + FelicaReader* reader, + FelicaSystemArray_t* systems) { + tx_rx->tx_bits = 8 * felica_prepare_request_system_code(tx_rx->tx_data, reader); + if(!furi_hal_nfc_tx_rx_full(tx_rx)) { + FURI_LOG_E(TAG, "Bad exchange requesting system code"); + return false; + } + if(!felica_parse_request_system_code(tx_rx->rx_data, tx_rx->rx_bits / 8, reader, systems)) { + FURI_LOG_E(TAG, "Bad response to Request System Code command"); + return false; + } + return true; +} + bool felica_read_card( FuriHalNfcTxRxContext* tx_rx, FelicaData* data, @@ -581,31 +659,24 @@ bool felica_read_card( memcpy(reader.current_idm, polled_idm, 8); memcpy(reader.current_pmm, polled_pmm, 8); - FelicaSystem* current_system = malloc(sizeof(FelicaSystem)); - FelicaSystemList_init(data->systems); - FelicaSystemList_push_back(data->systems, current_system); - - felica_parse_system_info(current_system, polled_idm, polled_pmm); + FelicaSystemArray_init(data->systems); if(data->type == FelicaICTypeLite || data->type == FelicaICTypeLiteS) { FURI_LOG_I(TAG, "Reading Felica Lite system"); - felica_read_lite_system(tx_rx, &reader, data, current_system); + FelicaSystem* lite_system = + felica_gen_monolithic_system_code(&reader, &(data->systems), LITE_SYSTEM_CODE); + felica_lite_dump_data(tx_rx, &reader, data, lite_system); card_read = true; break; } + FURI_LOG_I(TAG, "Reading Felica Standard system"); } while(false); return card_read; } void felica_service_clear(FelicaService* service) { - FelicaBlockList_it_t it; - for(FelicaBlockList_it(it, service->blocks); !FelicaBlockList_end_p(it); - FelicaBlockList_next(it)) { - FelicaBlock* block = *FelicaBlockList_ref(it); - free(block); - } - FelicaBlockList_clear(service->blocks); + FelicaBlockArray_clear(service->blocks); } void felica_lite_clear(FelicaLiteInfo* lite_info) { @@ -628,31 +699,33 @@ void felica_lite_clear(FelicaLiteInfo* lite_info) { } } +void felica_node_clear(FelicaNode* node); + void felica_area_clear(FelicaArea* area) { - FelicaNodeList_it_t it; - for(FelicaNodeList_it(it, area->nodes); !FelicaNodeList_end_p(it); FelicaNodeList_next(it)) { - FelicaNode* node = *FelicaNodeList_ref(it); - if(node->type == FelicaNodeTypeArea) { - felica_area_clear(node->area); - } else if(node->type == FelicaNodeTypeService) { - felica_service_clear(node->service); + for + M_EACH(node, area->nodes, FelicaNodeArray_t) { + felica_node_clear(node); } - free(node); + FelicaNodeArray_clear(area->nodes); +} + +void felica_node_clear(FelicaNode* node) { + if(node->type == FelicaNodeTypeArea) { + felica_area_clear(node->area); + } else if(node->type == FelicaNodeTypeService) { + felica_service_clear(node->service); } - FelicaNodeList_clear(area->nodes); } void felica_clear(FelicaData* data) { - FelicaSystemList_it_t it; - for(FelicaSystemList_it(it, data->systems); !FelicaSystemList_end_p(it); - FelicaSystemList_next(it)) { - FelicaSystem* system = *FelicaSystemList_ref(it); - if(system->code == LITE_SYSTEM_CODE) { - felica_lite_clear(&system->lite_info); - ; - } else { - felica_area_clear(&system->root_area); + for + M_EACH(system, data->systems, FelicaSystemArray_t) { + if(system->code == LITE_SYSTEM_CODE) { + felica_lite_clear(&system->lite_info); + } else { + felica_node_clear(&system->root); + FelicaPublicServiceDict_clear(system->public_services); + } } - } - FelicaSystemList_clear(data->systems); + FelicaSystemArray_clear(data->systems); } \ No newline at end of file diff --git a/lib/nfc/protocols/felica.h b/lib/nfc/protocols/felica.h index fa81cba2f..f8e504102 100644 --- a/lib/nfc/protocols/felica.h +++ b/lib/nfc/protocols/felica.h @@ -10,6 +10,8 @@ #define MRT_T_SIG_x16 4833038.24 //ns, MRT_T_SIG * (4 ** 2) #define MRT_T_SIG_x64 19332152.96 //ns, MRT_T_SIG * (4 ** 2) +#define FELICA_PMM_MRT_BASE 2 + #define FELICA_VARIABLE_MRT 0 #define FELICA_FIXED_MRT 1 #define FELICA_MUTUAL_AUTH_MRT 2 @@ -17,6 +19,13 @@ #define FELICA_WRITE_MRT 4 #define FELICA_OTHER_MRT 5 +#define FELICA_PMM_VARIABLE_MRT (FELICA_PMM_MRT_BASE + FELICA_VARIABLE_MRT) +#define FELICA_PMM_FIXED_MRT (FELICA_PMM_MRT_BASE + FELICA_FIXED_MRT) +#define FELICA_PMM_MUTUAL_AUTH_MRT (FELICA_PMM_MRT_BASE + FELICA_MUTUAL_AUTH_MRT) +#define FELICA_PMM_READ_MRT (FELICA_PMM_MRT_BASE + FELICA_READ_MRT) +#define FELICA_PMM_WRITE_MRT (FELICA_PMM_MRT_BASE + FELICA_WRITE_MRT) +#define FELICA_PMM_OTHER_MRT (FELICA_PMM_MRT_BASE + FELICA_OTHER_MRT) + #define FELICA_BLOCK_SIZE 16 #define CYBERNET_SYSTEM_CODE 0x0003 @@ -55,9 +64,13 @@ #define FELICA_UNENCRYPTED_READ_CMD 0x06 #define FELICA_UNENCRYPTED_WRITE_CMD 0x08 +#define FELICA_SEARCH_SERVICE_CODE_CMD 0x0a +#define FELICA_REQUEST_SYSTEM_CODE_CMD 0x0c #define FELICA_UNENCRYPTED_READ_RES 0x07 #define FELICA_UNENCRYPTED_WRITE_RES 0x09 +#define FELICA_SEARCH_SERVICE_CODE_RES 0x0b +#define FELICA_REQUEST_SYSTEM_CODE_RES 0x0d typedef enum { FelicaICTypeRC_SA24_10K, // RC-SA24/1x @@ -88,13 +101,6 @@ typedef enum { FelicaICTypeSuica, // https://www.tuv-nederland.nl/assets/files/cerfiticaten/2019/07/cr-nscib-cc-10-30076-cr.pdf } FelicaICType; -typedef struct { - uint8_t exponent : 2; - // Incremented at read - uint8_t real_a : 4; - uint8_t real_b : 4; -} FelicaMRTParts; - typedef enum { FelicaServiceTypeRandom = (0b0010 << 2), FelicaServiceTypeCyclic = (0b0011 << 2), @@ -121,20 +127,20 @@ DICT_SET_DEF( FelicaServiceAttribute, M_ENUM_OPLIST(FelicaServiceAttribute, FelicaServiceAttributeAuthRW)) -typedef FelicaMRTParts FelicaMRTParameters[6]; - typedef struct { uint8_t data[FELICA_BLOCK_SIZE]; } FelicaBlock; -ARRAY_DEF(FelicaBlockList, FelicaBlock*, M_PTR_OPLIST) +ARRAY_DEF(FelicaBlockArray, FelicaBlock, M_POD_OPLIST) +#define M_OPL_FelicaBlockArray_t() ARRAY_OPLIST(FelicaBlockArray, M_POD_OPLIST) typedef struct { uint16_t number; FelicaServiceAttributeList_t access_control_list; // accounts for overlap services - bool is_extended_overlap; + bool is_extended_overlap; // We don't know much about this currently. will always be false union { - FelicaBlockList_t blocks; + // TODO change this to use FelicaBlockArray_t + FelicaBlockArray_t blocks; struct { uint16_t overlap_target; uint8_t block_start; @@ -149,23 +155,44 @@ typedef enum { } FelicaNodeType; struct _FelicaArea_t; -typedef struct { +typedef struct _FelicaArea_t FelicaArea; + +struct _FelicaNode_s; +typedef struct _FelicaNode_s FelicaNode; + +struct _FelicaNode_s { + /** Node type. */ FelicaNodeType type; + /** Borrowed pointer to its parent node. */ + FelicaNode* parent; union { - struct _FelicaArea_t* area; + /** (Area/dir type only) The area struct. */ + FelicaArea* area; + /** (Service/file type only) The service struct. */ FelicaService* service; }; -} FelicaNode; +}; -ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST) +// TODO properly remove this +//ARRAY_DEF(FelicaNodeList, FelicaNode*, M_PTR_OPLIST) +ARRAY_DEF(FelicaNodeArray, FelicaNode, M_POD_OPLIST) +#define M_OPL_FelicaNodeArray_t() ARRAY_OPLIST(FelicaNodeArray, M_POD_OPLIST) -typedef struct _FelicaArea_t { +ARRAY_DEF(FelicaNodeRefArray, FelicaNode*, M_PTR_OPLIST) +#define M_OPL_FelicaNodeRefArray_t() ARRAY_OPLIST(FelicaNodeRefArray, M_PTR_OPLIST) + +// { service_number: service_ptr_in_tree } +DICT_DEF2(FelicaPublicServiceDict, uint16_t, M_DEFAULT_OPLIST, FelicaService*, M_PTR_OPLIST) +#define M_OPL_FelicaPublicServiceDict_t() \ + DICT_OPLIST(FelicaPublicServiceDict, M_DEFAULT_OPLIST, M_PTR_OPLIST) + +struct _FelicaArea_t { uint16_t number; bool can_create_subareas; uint16_t end_service_code; - FelicaNodeList_t nodes; -} FelicaArea; + FelicaNodeArray_t nodes; +}; typedef struct { uint8_t* S_PAD[14]; @@ -186,24 +213,39 @@ typedef struct { } FelicaLiteInfo; typedef struct _FelicaSystem_t { + /** FeliCa system index. */ uint8_t number; + /** If the system belongs to a FeliCa Lite (and be its only system). */ + bool is_lite; + /** FeliCa system code. */ uint16_t code; + /** System IDm with system index bitfield properly set. */ uint8_t idm[8]; + /** Cached card PMm. */ uint8_t pmm[8]; - FelicaMRTParameters maximum_response_times; union { + /** (For FeliCa Lite only) Card content. */ FelicaLiteInfo lite_info; - FelicaArea root_area; + struct { + /** (For FeliCa Standard only) The root of the raw filesystem tree. */ + FelicaNode root; + /** (For FeliCa Standard only) Shortcut for all publicly accessible services for quick + * access by card parsers. */ + FelicaPublicServiceDict_t public_services; + }; }; } FelicaSystem; -ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST) +// TODO properly remove this +//ARRAY_DEF(FelicaSystemList, FelicaSystem*, M_PTR_OPLIST) +ARRAY_DEF(FelicaSystemArray, FelicaSystem, M_POD_OPLIST) +#define M_OPL_FelicaSystemArray_t() ARRAY_OPLIST(FelicaSystemArray, M_POD_OPLIST) typedef struct { FelicaICType type; uint8_t subtype; - FelicaSystemList_t systems; + FelicaSystemArray_t systems; } FelicaData; typedef struct { @@ -255,8 +297,17 @@ bool felica_parse_unencrypted_write(uint8_t* buf, uint8_t len, FelicaReader* rea bool felica_lite_can_read_without_mac(uint8_t* mc_r_restr, uint8_t block_number); void felica_define_normal_block(FelicaService* service, uint16_t number, uint8_t* data); +void felica_push_normal_block(FelicaService* service, uint8_t* data); -bool felica_read_lite_system( +/** Dump a FeliCa Lite or Lite-S tag. + * + * @param tx_rx NFC context. + * @param reader FeliCa reader context. + * @param data Output data object. + * @param system FeliCa system description. + * @return true if successful. + */ +bool felica_lite_dump_data( FuriHalNfcTxRxContext* tx_rx, FelicaReader* reader, FelicaData* data, diff --git a/lib/nfc/protocols/felica_util.c b/lib/nfc/protocols/felica_util.c index a5198aa09..481ea5ed7 100644 --- a/lib/nfc/protocols/felica_util.c +++ b/lib/nfc/protocols/felica_util.c @@ -1,6 +1,16 @@ #include "./felica.h" #include +static const uint32_t TIME_CONSTANT_US = 302; + +// TODO move this to felica.c +uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units) { + uint_least32_t base_cost_factor = 1 + (timing & 0x7); + uint_least32_t unit_cost_factor = 1 + ((timing >> 3) & 0x7); + uint_least32_t scale = 1 << ((timing >> 6) * 2); + return TIME_CONSTANT_US * scale * (base_cost_factor + unit_cost_factor * units); +} + FuriString* felica_get_system_name(FelicaSystem* system) { uint16_t code = system->code; diff --git a/lib/nfc/protocols/felica_util.h b/lib/nfc/protocols/felica_util.h index 4224668eb..e53d66805 100644 --- a/lib/nfc/protocols/felica_util.h +++ b/lib/nfc/protocols/felica_util.h @@ -1,4 +1,5 @@ #include "./felica.h" +uint_least32_t felica_estimate_timing_us(uint_least8_t timing, uint_least8_t units); FuriString* felica_get_system_name(FelicaSystem* system); FuriString* felica_get_service_name(FelicaService* service); \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index a8e846388..31c347021 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -896,25 +896,11 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ MfClassicSectorTrailer* sector_trailer = (MfClassicSectorTrailer*)emulator->data.block[sector_trailer_block].value; if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD) { - if(mf_classic_is_key_found( - &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyA)) { - key = nfc_util_bytes2num(sector_trailer->key_a, 6); - access_key = MfClassicKeyA; - } else { - FURI_LOG_D(TAG, "Key not known"); - command_processed = true; - break; - } + key = nfc_util_bytes2num(sector_trailer->key_a, 6); + access_key = MfClassicKeyA; } else { - if(mf_classic_is_key_found( - &emulator->data, mf_classic_get_sector_by_block(block), MfClassicKeyB)) { - key = nfc_util_bytes2num(sector_trailer->key_b, 6); - access_key = MfClassicKeyB; - } else { - FURI_LOG_D(TAG, "Key not known"); - command_processed = true; - break; - } + key = nfc_util_bytes2num(sector_trailer->key_b, 6); + access_key = MfClassicKeyB; } uint32_t nonce = prng_successor(DWT->CYCCNT, 32) ^ 0xAA; diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index 1cea2c392..e0a21a043 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -703,7 +703,7 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight FURI_LOG_D(TAG, "Reading tearing flags"); for(size_t i = 0; i < 3; i++) { tx_rx->tx_data[0] = MF_UL_CHECK_TEARING; - 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)) { diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index e3ab4103f..2e817a538 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -1315,13 +1315,13 @@ bool nfcv_emu_loop( float fc_1024 = (4.0f * duration) / (4 * (frame_pos * 4 + 1) + 1); /* it should be 1024/fc in 64MHz ticks */ float fact = fc_1024 / ((1000000.0f * 64.0f * 1024.0f) / NFCV_FC); - FURI_LOG_D(TAG, "1024/fc: %f -> %f %%", (double)fc_1024, (double)fact * 100); + FURI_LOG_D(TAG, "1024/fc: %f -> %f %%", (double)fc_1024, (double)(fact * 100)); #if 0 if(fact > 0.99f && fact < 1.01f) { static float avg_err = 0.0f; avg_err = (avg_err * 15.0f + (fact - 1.0f)) / 16.0f; - FURI_LOG_D(TAG, " ==> set %f %%", (1.0f + avg_err) * 100); + FURI_LOG_D(TAG, " ==> set %f %%", (double)((1.0f + avg_err) * 100)); digital_sequence_timebase_correction(nfcv_data->emu_air.nfcv_signal, 1.0f + avg_err); } #endif diff --git a/lib/pulse_reader/pulse_reader.c b/lib/pulse_reader/pulse_reader.c index c8d0e3ff7..74d99fe80 100644 --- a/lib/pulse_reader/pulse_reader.c +++ b/lib/pulse_reader/pulse_reader.c @@ -119,10 +119,6 @@ void pulse_reader_set_pull(PulseReader* signal, GpioPull pull) { void pulse_reader_free(PulseReader* signal) { furi_assert(signal); - if(!signal) { - return; - } - free(signal->timer_buffer); free(signal->gpio_buffer); free(signal); diff --git a/lib/pulse_reader/pulse_reader.h b/lib/pulse_reader/pulse_reader.h index 08056a0ac..62c5f2fa4 100644 --- a/lib/pulse_reader/pulse_reader.h +++ b/lib/pulse_reader/pulse_reader.h @@ -10,9 +10,9 @@ extern "C" { #endif -#define PULSE_READER_NO_EDGE 0xFFFFFFFFUL -#define PULSE_READER_LOST_EDGE 0xFFFFFFFEUL -#define F_TIM2 64000000UL +#define PULSE_READER_NO_EDGE (0xFFFFFFFFUL) +#define PULSE_READER_LOST_EDGE (0xFFFFFFFEUL) +#define F_TIM2 (64000000UL) /** * unit of the edge durations to return diff --git a/lib/stm32wb.scons b/lib/stm32wb.scons new file mode 100644 index 000000000..94a1c7075 --- /dev/null +++ b/lib/stm32wb.scons @@ -0,0 +1,74 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/cmsis_core", + "#/lib/stm32wb_cmsis/Include", + "#/lib/stm32wb_hal/Inc", + "#/lib/stm32wb_copro/wpan", + ], + CPPDEFINES=[ + "STM32WB", + "STM32WB55xx", + "USE_FULL_ASSERT", + "USE_FULL_LL_DRIVER", + ], + SDK_HEADERS=env.GlobRecursive( + "*_ll_*.h", + Dir("stm32wb_hal/Inc"), + exclude="*usb.h", + ), +) + +if env["RAM_EXEC"]: + env.Append( + CPPDEFINES=[ + "VECT_TAB_SRAM", + ], + ) + + +libenv = env.Clone(FW_LIB_NAME="stm32wb") +libenv.Append( + CPPPATH=[ + "#/lib/stm32wb_copro/wpan/ble", + "#/lib/stm32wb_copro/wpan/ble/core", + "#/lib/stm32wb_copro/wpan/interface/patterns/ble_thread", + "#/lib/stm32wb_copro/wpan/interface/patterns/ble_thread/shci", + "#/lib/stm32wb_copro/wpan/interface/patterns/ble_thread/tl", + "#/lib/stm32wb_copro/wpan/utilities", + ] +) +libenv.ApplyLibFlags() + +sources = libenv.GlobRecursive("*_ll_*.c", "stm32wb_hal/Src/", exclude="*usb.c") +sources += Glob( + "stm32wb_copro/wpan/interface/patterns/ble_thread/shci/*.c", + source=True, +) +sources += Glob( + "stm32wb_copro/wpan/interface/patterns/ble_thread/tl/*_tl*.c", + exclude=[ + "stm32wb_copro/wpan/interface/patterns/ble_thread/tl/hci_tl_if.c", + "stm32wb_copro/wpan/interface/patterns/ble_thread/tl/shci_tl_if.c", + ], + source=True, +) +sources += [ + "stm32wb_copro/wpan/interface/patterns/ble_thread/tl/tl_mbox.c", + "stm32wb_copro/wpan/ble/svc/Src/svc_ctl.c", + "stm32wb_copro/wpan/ble/core/auto/ble_gap_aci.c", + "stm32wb_copro/wpan/ble/core/auto/ble_gatt_aci.c", + "stm32wb_copro/wpan/ble/core/auto/ble_hal_aci.c", + "stm32wb_copro/wpan/ble/core/auto/ble_hci_le.c", + "stm32wb_copro/wpan/ble/core/auto/ble_l2cap_aci.c", + "stm32wb_copro/wpan/ble/core/template/osal.c", + "stm32wb_copro/wpan/utilities/dbg_trace.c", + "stm32wb_copro/wpan/utilities/otp.c", + "stm32wb_copro/wpan/utilities/stm_list.c", +] + + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/stm32wb_cmsis b/lib/stm32wb_cmsis new file mode 160000 index 000000000..d1b860584 --- /dev/null +++ b/lib/stm32wb_cmsis @@ -0,0 +1 @@ +Subproject commit d1b860584dfe24d40d455ae624ed14600dfa93c9 diff --git a/lib/stm32wb_copro b/lib/stm32wb_copro new file mode 160000 index 000000000..d685979c2 --- /dev/null +++ b/lib/stm32wb_copro @@ -0,0 +1 @@ +Subproject commit d685979c282c9f38d561dd1ea8e6fdbd735d7362 diff --git a/lib/stm32wb_hal b/lib/stm32wb_hal new file mode 160000 index 000000000..cfd0dd258 --- /dev/null +++ b/lib/stm32wb_hal @@ -0,0 +1 @@ +Subproject commit cfd0dd258cb031c95b2b2d6d04c19f9f625fe3e8 diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c index 20dae49c1..47cf37d6b 100644 --- a/lib/subghz/protocols/alutech_at_4n.c +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -429,10 +429,8 @@ static bool subghz_protocol_encoder_alutech_at_4n_get_upload( if((custom_btn_id == 0) && (original_btn_num != 0)) { btn = original_btn_num; } - //gen new key - if(subghz_protocol_alutech_at_4n_gen_data(instance, btn)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + // Gen new key + if(!subghz_protocol_alutech_at_4n_gen_data(instance, btn)) { return false; } diff --git a/lib/subghz/protocols/keeloq_common.c b/lib/subghz/protocols/keeloq_common.c index 1d2d04457..a9a2238dd 100644 --- a/lib/subghz/protocols/keeloq_common.c +++ b/lib/subghz/protocols/keeloq_common.c @@ -23,7 +23,7 @@ inline uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const } /** Simple Learning Decrypt - * @param data - keelog encrypt data + * @param data - keeloq encrypt data * @param key - manufacture (64bit) * @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter */ diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c index a9127d2b1..c5d21bcb0 100644 --- a/lib/subghz/protocols/kinggates_stylo_4k.c +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -197,9 +197,7 @@ static bool subghz_protocol_encoder_kinggates_stylo_4k_get_upload( furi_assert(instance); // Gen new key - if(subghz_protocol_kinggates_stylo_4k_gen_data(instance, btn)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + if(!subghz_protocol_kinggates_stylo_4k_gen_data(instance, btn)) { return false; } diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index dd860a61d..4074d757b 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -208,10 +208,8 @@ static bool subghz_protocol_encoder_somfy_keytis_get_upload( uint8_t btn) { furi_assert(instance); - //gen new key - if(subghz_protocol_somfy_keytis_gen_data(instance, btn)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + // Gen new key + if(!subghz_protocol_somfy_keytis_gen_data(instance, btn)) { return false; } diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 047efb688..57c6c510b 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -254,10 +254,8 @@ static bool subghz_protocol_encoder_somfy_telis_get_upload( uint8_t btn) { furi_assert(instance); - //gen new key - if(subghz_protocol_somfy_telis_gen_data(instance, btn, false)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + // Gen new key + if(!subghz_protocol_somfy_telis_gen_data(instance, btn, false)) { return false; } diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index 181dee643..cb9b26760 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -237,10 +237,8 @@ static bool subghz_protocol_encoder_star_line_get_upload( uint8_t btn) { furi_assert(instance); - //gen new key - if(subghz_protocol_star_line_gen_data(instance, btn)) { - //ToDo if you need to add a callback to automatically update the data on the display - } else { + // Gen new key + if(!subghz_protocol_star_line_gen_data(instance, btn)) { return false; } diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 9dce9d0f4..2d94336a9 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -1,8 +1,8 @@ -Import("env") - from fbt.version import get_fast_git_version_id +Import("env") + env.Append( CPPPATH=[ "#/lib/toolbox", diff --git a/lib/toolbox/version.c b/lib/toolbox/version.c index ae4ef2e3f..69c43b8bf 100644 --- a/lib/toolbox/version.c +++ b/lib/toolbox/version.c @@ -1,24 +1,35 @@ #include "version.h" - +#include /* This header is autogenerated by build system */ #include "version.inc.h" +#define VERSION_MAGIC (0xBE40u) +#define VERSION_MAJOR (0x1u) +#define VERSION_MINOR (0x0u) + struct Version { + // Header + const uint16_t magic; + const uint8_t major; + const uint8_t minor; + // Payload const char* git_hash; const char* git_branch; - const char* git_branch_num; const char* build_date; const char* custom_flipper_name; const char* version; + // Payload bits and pieces const uint8_t target; const bool build_is_dirty; }; /* version of current running firmware (bootloader/flipper) */ -static const Version version = { +static Version version = { + .magic = VERSION_MAGIC, + .major = VERSION_MAJOR, + .minor = VERSION_MINOR, .git_hash = GIT_COMMIT, .git_branch = GIT_BRANCH, - .git_branch_num = GIT_BRANCH_NUM, .build_date = BUILD_DATE, #ifdef FURI_CUSTOM_FLIPPER_NAME .custom_flipper_name = FURI_CUSTOM_FLIPPER_NAME, @@ -47,7 +58,8 @@ const char* version_get_gitbranch(const Version* v) { } const char* version_get_gitbranchnum(const Version* v) { - return v ? v->git_branch_num : version.git_branch_num; + UNUSED(v); + return "0"; } const char* version_get_builddate(const Version* v) { @@ -62,6 +74,12 @@ const char* version_get_custom_name(const Version* v) { return v ? v->custom_flipper_name : version.custom_flipper_name; } +void version_set_custom_name(Version* v, const char* name) { + Version* ver = v ? v : &version; + ver->custom_flipper_name = name; + return; +} + uint8_t version_get_target(const Version* v) { return v ? v->target : version.target; } diff --git a/lib/toolbox/version.h b/lib/toolbox/version.h index ed54631b3..43fe6a9d3 100644 --- a/lib/toolbox/version.h +++ b/lib/toolbox/version.h @@ -74,6 +74,14 @@ const char* version_get_version(const Version* v); */ const char* version_get_custom_name(const Version* v); +/** Get custom flipper name if set in ENV + * + * @param v pointer to Version data. NULL for currently running + * software. + * @param custom name or NULL + */ +void version_set_custom_name(Version* v, const char* name); + /** Get hardware target this firmware was built for * * @param v pointer to Version data. NULL for currently running diff --git a/lib/update_util/lfs_backup.c b/lib/update_util/lfs_backup.c index b299a9d32..a441ccabd 100644 --- a/lib/update_util/lfs_backup.c +++ b/lib/update_util/lfs_backup.c @@ -2,28 +2,8 @@ #include -#include - #define LFS_BACKUP_DEFAULT_LOCATION EXT_PATH(LFS_BACKUP_DEFAULT_FILENAME) -static void backup_name_converter(FuriString* filename) { - if(furi_string_empty(filename) || (furi_string_get_char(filename, 0) == '.')) { - return; - } - - /* Filenames are already prefixed with '.' */ - const char* const names[] = { - NOTIFICATION_SETTINGS_FILE_NAME, - }; - - for(size_t i = 0; i < COUNT_OF(names); i++) { - if(furi_string_equal(filename, &names[i][1])) { - furi_string_set(filename, names[i]); - return; - } - } -} - bool lfs_backup_create(Storage* storage, const char* destination) { const char* final_destination = destination && strlen(destination) ? destination : LFS_BACKUP_DEFAULT_LOCATION; @@ -37,5 +17,5 @@ bool lfs_backup_exists(Storage* storage, const char* source) { bool lfs_backup_unpack(Storage* storage, const char* source) { const char* final_source = source && strlen(source) ? source : LFS_BACKUP_DEFAULT_LOCATION; - return storage_int_restore(storage, final_source, backup_name_converter) == FSE_OK; + return storage_int_restore(storage, final_source, NULL) == FSE_OK; } diff --git a/lib/xtreme/assets.c b/lib/xtreme/assets.c index 3c27f838c..828369ad1 100644 --- a/lib/xtreme/assets.c +++ b/lib/xtreme/assets.c @@ -28,6 +28,7 @@ XtremeAssets xtreme_assets = { .I_RFIDDolphinSend_97x61 = &I_RFIDDolphinSend_97x61, .I_RFIDDolphinSuccess_108x57 = &I_RFIDDolphinSuccess_108x57, .I_Cry_dolph_55x52 = &I_Cry_dolph_55x52, + .I_Background_128x11 = &I_Background_128x11, .I_Fishing_123x52 = &I_Fishing_123x52, .I_Scanning_123x52 = &I_Scanning_123x52, .I_Auth_62x31 = &I_Auth_62x31, @@ -132,6 +133,7 @@ void swap(XtremeAssets* x, FuriString* p, File* f) { icon(&x->I_RFIDDolphinSend_97x61, "RFID/RFIDDolphinSend_97x61", p, f); icon(&x->I_RFIDDolphinSuccess_108x57, "RFID/RFIDDolphinSuccess_108x57", p, f); icon(&x->I_Cry_dolph_55x52, "Settings/Cry_dolph_55x52", p, f); + icon(&x->I_Background_128x11, "StatusBar/Background_128x11", p, f); icon(&x->I_Fishing_123x52, "SubGhz/Fishing_123x52", p, f); icon(&x->I_Scanning_123x52, "SubGhz/Scanning_123x52", p, f); icon(&x->I_Auth_62x31, "U2F/Auth_62x31", p, f); @@ -146,13 +148,6 @@ void XTREME_ASSETS_LOAD() { xtreme_assets.is_nsfw = strncmp(xtreme_settings->asset_pack, "NSFW", strlen("NSFW")) == 0; Storage* storage = furi_record_open(RECORD_STORAGE); - int32_t timeout = 5000; - while(timeout > 0) { - if(storage_sd_status(storage) == FSE_OK) break; - furi_delay_ms(250); - timeout -= 250; - } - FileInfo info; FuriString* path = furi_string_alloc(); furi_string_printf(path, XTREME_ASSETS_PATH "/%s", xtreme_settings->asset_pack); diff --git a/lib/xtreme/namespoof.c b/lib/xtreme/namespoof.c new file mode 100644 index 000000000..3a5918a38 --- /dev/null +++ b/lib/xtreme/namespoof.c @@ -0,0 +1,27 @@ +#include "namespoof.h" +#include +#include + +#define TAG "NameSpoof" + +void NAMESPOOF_INIT() { + FuriString* str = furi_string_alloc(); + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* file = flipper_format_file_alloc(storage); + + do { + uint32_t version; + if(!flipper_format_file_open_existing(file, NAMESPOOF_PATH)) break; + if(!flipper_format_read_header(file, str, &version)) break; + if(furi_string_cmp_str(str, NAMESPOOF_HEADER)) break; + if(version != NAMESPOOF_VERSION) break; + + if(!flipper_format_read_string(file, "Name", str)) break; + version_set_custom_name(NULL, strdup(furi_string_get_cstr(str))); + furi_hal_version_set_name(version_get_custom_name(NULL)); + } while(false); + + flipper_format_free(file); + furi_record_close(RECORD_STORAGE); + furi_string_free(str); +} diff --git a/lib/xtreme/namespoof.h b/lib/xtreme/namespoof.h new file mode 100644 index 000000000..5d7e91a1f --- /dev/null +++ b/lib/xtreme/namespoof.h @@ -0,0 +1,5 @@ +#pragma once + +#define NAMESPOOF_HEADER "Flipper Name File" +#define NAMESPOOF_VERSION 1 +#define NAMESPOOF_PATH EXT_PATH("dolphin/name.txt") diff --git a/lib/xtreme/private.h b/lib/xtreme/private.h index 8b220f586..2718b67af 100644 --- a/lib/xtreme/private.h +++ b/lib/xtreme/private.h @@ -1,4 +1,5 @@ #pragma once -void XTREME_ASSETS_LOAD(); +void NAMESPOOF_INIT(); void XTREME_SETTINGS_LOAD(); +void XTREME_ASSETS_LOAD(); diff --git a/lib/xtreme/settings.c b/lib/xtreme/settings.c index 1cafa6f59..f840f990d 100644 --- a/lib/xtreme/settings.c +++ b/lib/xtreme/settings.c @@ -24,9 +24,10 @@ XtremeSettings xtreme_settings = { .bar_background = false, // OFF .sort_dirs_first = true, // ON .dark_mode = false, // OFF + .favorite_timeout = 0, // OFF .bad_bt = false, // USB .bad_bt_remember = false, // OFF - .butthurt_timer = 43200, // 12 H + .butthurt_timer = 21600, // 6 H .rgb_backlight = false, // OFF }; @@ -75,6 +76,8 @@ void XTREME_SETTINGS_LOAD() { flipper_format_rewind(file); flipper_format_read_bool(file, "dark_mode", &x->dark_mode, 1); flipper_format_rewind(file); + flipper_format_read_uint32(file, "favorite_timeout", &x->favorite_timeout, 1); + flipper_format_rewind(file); flipper_format_read_bool(file, "bad_bt", &x->bad_bt, 1); flipper_format_rewind(file); flipper_format_read_bool(file, "bad_bt_remember", &x->bad_bt_remember, 1); @@ -112,6 +115,7 @@ void XTREME_SETTINGS_SAVE() { flipper_format_write_bool(file, "bar_background", &x->bar_background, 1); flipper_format_write_bool(file, "sort_dirs_first", &x->sort_dirs_first, 1); flipper_format_write_bool(file, "dark_mode", &x->dark_mode, 1); + flipper_format_write_uint32(file, "favorite_timeout", &x->favorite_timeout, 1); flipper_format_write_bool(file, "bad_bt", &x->bad_bt, 1); flipper_format_write_bool(file, "bad_bt_remember", &x->bad_bt_remember, 1); flipper_format_write_int32(file, "butthurt_timer", &x->butthurt_timer, 1); diff --git a/lib/xtreme/xtreme.h b/lib/xtreme/xtreme.h index 63f457c27..b84ba9691 100644 --- a/lib/xtreme/xtreme.h +++ b/lib/xtreme/xtreme.h @@ -31,14 +31,15 @@ typedef struct { bool bar_background; bool sort_dirs_first; bool dark_mode; + uint32_t favorite_timeout; bool bad_bt; bool bad_bt_remember; int32_t butthurt_timer; bool rgb_backlight; } XtremeSettings; -XtremeSettings* XTREME_SETTINGS(); void XTREME_SETTINGS_SAVE(); +XtremeSettings* XTREME_SETTINGS(); typedef struct { bool is_nsfw; @@ -61,6 +62,7 @@ typedef struct { const Icon* I_RFIDDolphinSend_97x61; const Icon* I_RFIDDolphinSuccess_108x57; const Icon* I_Cry_dolph_55x52; + const Icon* I_Background_128x11; const Icon* I_Fishing_123x52; const Icon* I_Scanning_123x52; const Icon* I_Auth_62x31; diff --git a/scripts/assets.py b/scripts/assets.py index 0520c9fb6..888425e84 100755 --- a/scripts/assets.py +++ b/scripts/assets.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import os +import pathlib + import asset_packer from flipper.app import App from flipper.assets.icon import file2image -import os -import pathlib - ICONS_SUPPORTED_FORMATS = ["png"] ICONS_TEMPLATE_H_HEADER = """#pragma once @@ -62,7 +62,6 @@ class Main(App): ) self.parser_copro.add_argument("cube_dir", help="Path to Cube folder") self.parser_copro.add_argument("output_dir", help="Path to output folder") - self.parser_copro.add_argument("mcu", help="MCU series as in copro folder") self.parser_copro.add_argument( "--cube_ver", dest="cube_ver", help="Cube version", required=True ) @@ -129,7 +128,7 @@ class Main(App): if not filenames: continue if "frame_rate" in filenames: - self.logger.debug(f"Folder contains animation") + self.logger.debug("Folder contains animation") icon_name = "A_" + os.path.split(dirpath)[1].replace("-", "_") width = height = None frame_count = 0 @@ -188,7 +187,7 @@ class Main(App): icons_c.write("\n") icons.append((icon_name, width, height, 0, 1)) # Create array of images: - self.logger.debug(f"Finalizing source file") + self.logger.debug("Finalizing source file") for name, width, height, frame_rate, frame_count in icons: icons_c.write( ICONS_TEMPLATE_C_ICONS.format( @@ -203,7 +202,7 @@ class Main(App): icons_c.close() # Create Public Header - self.logger.debug(f"Creating header") + self.logger.debug("Creating header") icons_h = open( os.path.join(self.args.output_directory, f"{self.args.filename}.h"), "w", @@ -213,7 +212,7 @@ class Main(App): 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") + self.logger.debug("Done") return 0 def manifest(self): @@ -234,7 +233,7 @@ class Main(App): new_manifest = Manifest(self.args.timestamp) new_manifest.create(directory_path) - self.logger.info(f"Comparing new manifest with existing") + self.logger.info("Comparing new manifest with existing") only_in_old, changed, only_in_new = Manifest.compare(old_manifest, new_manifest) for record in only_in_old: self.logger.info(f"Only in old: {record}") @@ -256,38 +255,42 @@ class Main(App): self.logger.info, ) - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 def copro(self): from flipper.assets.copro import Copro - self.logger.info(f"Bundling coprocessor binaries") - copro = Copro(self.args.mcu) - self.logger.info(f"Loading CUBE info") - copro.loadCubeInfo(self.args.cube_dir, self.args.cube_ver) - self.logger.info(f"Bundling") - copro.bundle( - self.args.output_dir, - self.args.stack_file, - self.args.stack_type, - self.args.stack_addr, - ) - self.logger.info(f"Complete") + self.logger.info("Bundling coprocessor binaries") + copro = Copro() + try: + self.logger.info("Loading CUBE info") + copro.loadCubeInfo(self.args.cube_dir, self.args.cube_ver) + self.logger.info("Bundling") + copro.bundle( + self.args.output_dir, + self.args.stack_file, + self.args.stack_type, + self.args.stack_addr, + ) + except Exception as e: + self.logger.error(f"Failed to bundle: {e}") + return 1 + self.logger.info("Complete") return 0 def dolphin(self): from flipper.assets.dolphin import Dolphin - self.logger.info(f"Processing Dolphin sources") + self.logger.info("Processing Dolphin sources") dolphin = Dolphin() - self.logger.info(f"Loading data") + self.logger.info("Loading data") dolphin.load(self.args.input_directory) - self.logger.info(f"Packing") + self.logger.info("Packing") dolphin.pack(self.args.output_directory, self.args.symbol_name) - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 diff --git a/debug/FreeRTOS/FreeRTOS.py b/scripts/debug/FreeRTOS/FreeRTOS.py similarity index 99% rename from debug/FreeRTOS/FreeRTOS.py rename to scripts/debug/FreeRTOS/FreeRTOS.py index 036e18f31..0eb7e5f8d 100644 --- a/debug/FreeRTOS/FreeRTOS.py +++ b/scripts/debug/FreeRTOS/FreeRTOS.py @@ -29,7 +29,6 @@ from FreeRTOSgdb.GDBCommands import ShowQueueInfo class Scheduler: def __init__(self): - self._blocked = ListInspector("xSuspendedTaskList") self._delayed1 = ListInspector("xDelayedTaskList1") self._delayed2 = ListInspector("xDelayedTaskList2") diff --git a/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py similarity index 100% rename from debug/FreeRTOS/FreeRTOSgdb/EventGroup.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/EventGroup.py diff --git a/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py similarity index 99% rename from debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py index ba811e3e1..5564502ec 100644 --- a/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py +++ b/scripts/debug/FreeRTOS/FreeRTOSgdb/GDBCommands.py @@ -61,7 +61,6 @@ class ShowQueueInfo(gdb.Command): if maxCount == 0: print(outputFmt % (q.GetName(), q.GetQueueMessagesWaiting(), "", "")) else: - for i in range(0, maxCount): txName = "" if i < len(sendList): diff --git a/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py similarity index 99% rename from debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py index 1682c9176..c13457017 100644 --- a/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py +++ b/scripts/debug/FreeRTOS/FreeRTOSgdb/HandleRegistry.py @@ -48,7 +48,6 @@ class HandleRegistry: print("%d: %3s %16s" % (i, h, name)) def FilterBy(self, qMode): - """Retrieve a List of Mutex Queue Handles""" resp = [] for i in range(self._minIndex, self._maxIndex): diff --git a/debug/FreeRTOS/FreeRTOSgdb/List.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/List.py similarity index 99% rename from debug/FreeRTOS/FreeRTOSgdb/List.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/List.py index 62aa9dc9a..575bdc525 100644 --- a/debug/FreeRTOS/FreeRTOSgdb/List.py +++ b/scripts/debug/FreeRTOS/FreeRTOSgdb/List.py @@ -56,7 +56,6 @@ class ListInspector: of some of the TCB Task lists. """ if self._list != None: - CastType = None if CastTypeStr != None: if type(CastTypeStr) == str: @@ -73,7 +72,6 @@ class ListInspector: index = self._list["pxIndex"] if numElems > 0 and numElems < 200: - if startElem == 0: curr = index else: diff --git a/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py similarity index 99% rename from debug/FreeRTOS/FreeRTOSgdb/QueueTools.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py index 49a780db3..a35f0894f 100644 --- a/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py +++ b/scripts/debug/FreeRTOS/FreeRTOSgdb/QueueTools.py @@ -47,7 +47,6 @@ QueueMode.Map = QueueMap class QueueInspector: - QueueType = gdb.lookup_type("Queue_t") def __init__(self, handle): diff --git a/debug/FreeRTOS/FreeRTOSgdb/Task.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/Task.py similarity index 99% rename from debug/FreeRTOS/FreeRTOSgdb/Task.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/Task.py index 04da3bbcd..d3078fdc9 100644 --- a/debug/FreeRTOS/FreeRTOSgdb/Task.py +++ b/scripts/debug/FreeRTOS/FreeRTOSgdb/Task.py @@ -11,7 +11,6 @@ import gdb class TaskInspector: - TCBType = gdb.lookup_type("TCB_t") def __init__(self, handle): diff --git a/debug/FreeRTOS/FreeRTOSgdb/Types.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/Types.py similarity index 100% rename from debug/FreeRTOS/FreeRTOSgdb/Types.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/Types.py diff --git a/debug/FreeRTOS/FreeRTOSgdb/__init__.py b/scripts/debug/FreeRTOS/FreeRTOSgdb/__init__.py similarity index 100% rename from debug/FreeRTOS/FreeRTOSgdb/__init__.py rename to scripts/debug/FreeRTOS/FreeRTOSgdb/__init__.py diff --git a/debug/FreeRTOS/LICENSE b/scripts/debug/FreeRTOS/LICENSE similarity index 100% rename from debug/FreeRTOS/LICENSE rename to scripts/debug/FreeRTOS/LICENSE diff --git a/debug/FreeRTOS/README.md b/scripts/debug/FreeRTOS/README.md similarity index 100% rename from debug/FreeRTOS/README.md rename to scripts/debug/FreeRTOS/README.md diff --git a/debug/PyCortexMDebug/LICENSE b/scripts/debug/PyCortexMDebug/LICENSE similarity index 100% rename from debug/PyCortexMDebug/LICENSE rename to scripts/debug/PyCortexMDebug/LICENSE diff --git a/debug/PyCortexMDebug/PyCortexMDebug.py b/scripts/debug/PyCortexMDebug/PyCortexMDebug.py similarity index 96% rename from debug/PyCortexMDebug/PyCortexMDebug.py rename to scripts/debug/PyCortexMDebug/PyCortexMDebug.py index 6533535c3..fd322b5a6 100644 --- a/debug/PyCortexMDebug/PyCortexMDebug.py +++ b/scripts/debug/PyCortexMDebug/PyCortexMDebug.py @@ -28,7 +28,5 @@ directory = path.abspath(directory) sys.path.append(directory) from cmdebug.svd_gdb import LoadSVD -from cmdebug.dwt_gdb import DWT -DWT() LoadSVD() diff --git a/scripts/debug/PyCortexMDebug/README.md b/scripts/debug/PyCortexMDebug/README.md new file mode 100644 index 000000000..0a5764b02 --- /dev/null +++ b/scripts/debug/PyCortexMDebug/README.md @@ -0,0 +1,35 @@ +PyCortexMDebug +============== + +## SVD + +ARM defines an SVD (System View Description) file format in its CMSIS standard as a means for Cortex-M-based chip manufacturers to provide a common description of peripherals, registers, and register fields. You can download SVD files for different manufacturers [here](http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php). + +The implementation consists of two components -- An lxml-based parser module (pysvd) and a GDB file (gdb_svd). I haven't yet worked out a perfect workflow for this, though it's quite easy to use when you already tend to have a GDB initialization file for starting up OpenOCD and the like. However your workflow works, just make sure to, in GDB: + + source gdb_svd.py + svd_load [your_svd_file].svd + +These files can be huge so it might take a second or two. Anyways, after that, you can do + + svd + +to list available peripherals with descriptions. Or you can do + + svd [some_peripheral_name] + +to see all of the registers (with their values) for a given peripheral. For more details, run + + svd [some_peripheral_name] [some_register_name] + +to see all of the field values with descriptions. + +You can add format modifiers like: + +* `svd/x` will display values in hex +* `svd/o` will display values in octal +* `svd/t` or `svd/b` will display values in binary +* `svd/a` will display values in hex and try to resolve symbols from the values + +All field values are displayed at the correct lengths as provided by the SVD files. +Also, tab completion exists for nearly everything! When in doubt, run `svd help`. diff --git a/debug/PyCortexMDebug/cmdebug/__init__.py b/scripts/debug/PyCortexMDebug/cmdebug/__init__.py similarity index 100% rename from debug/PyCortexMDebug/cmdebug/__init__.py rename to scripts/debug/PyCortexMDebug/cmdebug/__init__.py diff --git a/debug/PyCortexMDebug/cmdebug/svd.py b/scripts/debug/PyCortexMDebug/cmdebug/svd.py similarity index 89% rename from debug/PyCortexMDebug/cmdebug/svd.py rename to scripts/debug/PyCortexMDebug/cmdebug/svd.py index f4a884bb4..a25e69bfb 100755 --- a/debug/PyCortexMDebug/cmdebug/svd.py +++ b/scripts/debug/PyCortexMDebug/cmdebug/svd.py @@ -16,15 +16,14 @@ You should have received a copy of the GNU General Public License along with PyCortexMDebug. If not, see . """ -from collections import OrderedDict -from . import x2d - -import traceback -import warnings -import pickle +import lxml.objectify as objectify import sys +from collections import OrderedDict import os +import pickle +import traceback import re +import warnings class SmartDict: @@ -127,31 +126,26 @@ class SVDFile: def __init__(self, fname): """ + Args: fname: Filename for the SVD file """ + f = objectify.parse(os.path.expanduser(fname)) + root = f.getroot() + periph = root.peripherals.getchildren() self.peripherals = SmartDict() self.base_address = 0 - xml_file_name = os.path.expanduser(fname) - pickle_file_name = xml_file_name + ".pickle" - root = None - if os.path.exists(pickle_file_name): - print("Loading pickled SVD") - root = pickle.load(open(pickle_file_name, "rb")) - else: - print("Loading XML SVD and pickling it") - root = x2d.parse(open(xml_file_name, "rb")) - pickle.dump(root, open(pickle_file_name, "wb"), pickle.HIGHEST_PROTOCOL) - print("Processing SVD tree") # XML elements - for p in root["device"]["peripherals"]["peripheral"]: + for p in periph: try: - self.peripherals[p["name"]] = SVDPeripheral(p, self) + if p.tag == "peripheral": + self.peripherals[str(p.name)] = SVDPeripheral(p, self) + else: + # This is some other tag + pass except SVDNonFatalError as e: - # print(e) - pass - print("SVD Ready") + print(e) def add_register(parent, node): @@ -271,11 +265,11 @@ class SVDPeripheral: self.parent_base_address = parent.base_address # Look for a base address, as it is required - if "baseAddress" not in svd_elem: + if not hasattr(svd_elem, "baseAddress"): raise SVDNonFatalError("Periph without base address") self.base_address = int(str(svd_elem.baseAddress), 0) - if "@derivedFrom" in svd_elem: - derived_from = svd_elem["@derivedFrom"] + if "derivedFrom" in svd_elem.attrib: + derived_from = svd_elem.attrib["derivedFrom"] try: self.name = str(svd_elem.name) except AttributeError: @@ -301,14 +295,16 @@ class SVDPeripheral: self.clusters = SmartDict() if hasattr(svd_elem, "registers"): - if "register" in svd_elem.registers: - for r in svd_elem.registers.register: - if isinstance(r, x2d.ObjectDict): - add_register(self, r) - if "cluster" in svd_elem.registers: - for c in svd_elem.registers.cluster: - if isinstance(c, x2d.ObjectDict): - add_cluster(self, c) + registers = [ + r + for r in svd_elem.registers.getchildren() + if r.tag in ["cluster", "register"] + ] + for r in registers: + if r.tag == "cluster": + add_cluster(self, r) + elif r.tag == "register": + add_register(self, r) def refactor_parent(self, parent): self.parent_base_address = parent.base_address @@ -342,11 +338,11 @@ class SVDPeripheralRegister: else: self.size = 0x20 self.fields = SmartDict() - if "fields" in svd_elem: + if hasattr(svd_elem, "fields"): # Filter fields to only consider those of tag "field" - for f in svd_elem.fields.field: - if isinstance(f, x2d.ObjectDict): - self.fields[str(f.name)] = SVDPeripheralRegisterField(f, self) + fields = [f for f in svd_elem.fields.getchildren() if f.tag == "field"] + for f in fields: + self.fields[str(f.name)] = SVDPeripheralRegisterField(f, self) def refactor_parent(self, parent): self.parent_base_address = parent.base_address diff --git a/debug/PyCortexMDebug/cmdebug/svd_gdb.py b/scripts/debug/PyCortexMDebug/cmdebug/svd_gdb.py similarity index 100% rename from debug/PyCortexMDebug/cmdebug/svd_gdb.py rename to scripts/debug/PyCortexMDebug/cmdebug/svd_gdb.py diff --git a/debug/STM32WB55_CM4.svd b/scripts/debug/STM32WB55_CM4.svd similarity index 100% rename from debug/STM32WB55_CM4.svd rename to scripts/debug/STM32WB55_CM4.svd diff --git a/debug/flipperapps.py b/scripts/debug/flipperapps.py similarity index 100% rename from debug/flipperapps.py rename to scripts/debug/flipperapps.py diff --git a/scripts/debug/flipperversion.py b/scripts/debug/flipperversion.py new file mode 100644 index 000000000..4ac3bd200 --- /dev/null +++ b/scripts/debug/flipperversion.py @@ -0,0 +1,109 @@ +from dataclasses import dataclass, field +from typing import Dict, Optional + +import gdb + + +# Must match FuriHalRtcRegisterVersion index in FuriHalRtcRegister enum +RTC_BACKUP_VERSION_REGISTER_IDX = 0x2 + +RTC_BASE = 0x40002800 +RTC_BACKUP_BASE = RTC_BASE + 0x50 + +VERSION_REGISTER_ADDRESS = RTC_BACKUP_BASE + RTC_BACKUP_VERSION_REGISTER_IDX * 4 + +VERSION_STRUCT_MAGIC = 0xBE40 + + +@dataclass +class VersionData: + git_hash: str + git_branch: str + build_date: str + version: str + target: int + build_is_dirty: bool + extra: Optional[Dict[str, str]] = field(default_factory=dict) + + +class VersionLoader: + def __init__(self, version_ptr): + self.version_ptr = version_ptr + self._cstr_type = gdb.lookup_type("char").pointer() + self._uint_type = gdb.lookup_type("unsigned int") + + version_signature = version_ptr.dereference().cast(self._uint_type) + is_versioned = (version_signature & (0xFFFF)) == VERSION_STRUCT_MAGIC + if is_versioned: + self._version_data = self.load_versioned( + major=version_signature >> 16 & 0xFF, + minor=version_signature >> 24 & 0xFF, + ) + else: + self._version_data = self.load_unversioned() + + @property + def version(self) -> VersionData: + return self._version_data + + def load_versioned(self, major, minor): + if major != 1: + raise ValueError("Unsupported version struct major version") + + # Struct version 1.0 + extra_data = int(self.version_ptr[5].cast(self._uint_type)) + return VersionData( + git_hash=self.version_ptr[1].cast(self._cstr_type).string(), + git_branch=self.version_ptr[2].cast(self._cstr_type).string(), + build_date=self.version_ptr[3].cast(self._cstr_type).string(), + version=self.version_ptr[4].cast(self._cstr_type).string(), + target=extra_data & 0xF, + build_is_dirty=bool((extra_data >> 8) & 0xF), + ) + + def load_unversioned(self): + """Parse an early version of the version struct.""" + extra_data = int(self.version_ptr[5].cast(self._uint_type)) + return VersionData( + git_hash=self.version_ptr[0].cast(self._cstr_type).string(), + git_branch=self.version_ptr[1].cast(self._cstr_type).string(), + # branch number is #2, but we don't care about it + build_date=self.version_ptr[3].cast(self._cstr_type).string(), + version=self.version_ptr[4].cast(self._cstr_type).string(), + target=extra_data & 0xF, + build_is_dirty=bool((extra_data >> 8) & 0xF), + ) + + +class FlipperFwVersion(gdb.Command): + """Print the version of Flipper's firmware.""" + + def __init__(self): + super(FlipperFwVersion, self).__init__("fw-version", gdb.COMMAND_USER) + + def invoke(self, arg, from_tty): + void_ptr_type = gdb.lookup_type("void").pointer().pointer() + version_ptr_ptr = gdb.Value(VERSION_REGISTER_ADDRESS).cast(void_ptr_type) + + if not version_ptr_ptr: + print("RTC version register is NULL") + return + + version_ptr = version_ptr_ptr.dereference() + if not version_ptr: + print("Pointer to version struct is NULL") + return + + version_struct = version_ptr.cast(void_ptr_type) + + v = VersionLoader(version_struct) + print("Firmware version on attached Flipper:") + print(f"\tVersion: {v.version.version}") + print(f"\tBuilt on: {v.version.build_date}") + print(f"\tGit branch: {v.version.git_branch}") + print(f"\tGit commit: {v.version.git_hash}") + print(f"\tDirty: {v.version.build_is_dirty}") + print(f"\tHW Target: {v.version.target}") + + +FlipperFwVersion() diff --git a/debug/fw.jflash b/scripts/debug/fw.jflash similarity index 100% rename from debug/fw.jflash rename to scripts/debug/fw.jflash diff --git a/debug/gdbinit b/scripts/debug/gdbinit similarity index 100% rename from debug/gdbinit rename to scripts/debug/gdbinit diff --git a/debug/stm32wbx.cfg b/scripts/debug/stm32wbx.cfg similarity index 100% rename from debug/stm32wbx.cfg rename to scripts/debug/stm32wbx.cfg diff --git a/scripts/distfap.py b/scripts/distfap.py index 612ad9ad8..74601fdca 100644 --- a/scripts/distfap.py +++ b/scripts/distfap.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 +import os +import posixpath + from flipper.app import App from flipper.storage import FlipperStorage, FlipperStorageOperations from flipper.utils.cdc import resolve_port -import os -import posixpath - class Main(App): def init(self): diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 2357c19b5..0ae63e638 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -1,7 +1,7 @@ -from dataclasses import dataclass, field -from typing import List, Optional, Tuple, Callable -from enum import Enum import os +from dataclasses import dataclass, field +from enum import Enum +from typing import Callable, List, Optional, Tuple class FlipperManifestException(Exception): @@ -94,7 +94,7 @@ class AppManager: def get(self, appname: str): try: return self.known_apps[appname] - except KeyError as _: + except KeyError: raise FlipperManifestException( f"Missing application manifest for '{appname}'" ) @@ -298,7 +298,7 @@ class AppBuildset: try: parent_app = self.appmgr.get(parent_app_id) parent_app._plugins.append(extension_app) - except FlipperManifestException as e: + except FlipperManifestException: self._writer( f"Module {extension_app.appid} has unknown parent {parent_app_id}" ) diff --git a/scripts/fbt/elfmanifest.py b/scripts/fbt/elfmanifest.py index 17bceddf4..333888e14 100644 --- a/scripts/fbt/elfmanifest.py +++ b/scripts/fbt/elfmanifest.py @@ -1,12 +1,10 @@ -from dataclasses import dataclass import os - import struct from dataclasses import dataclass, field -from .appmanifest import FlipperApplication from flipper.assets.icon import file2image +from .appmanifest import FlipperApplication _MANIFEST_MAGIC = 0x52474448 diff --git a/scripts/fbt/fapassets.py b/scripts/fbt/fapassets.py index 0649f03ef..9902fd79a 100644 --- a/scripts/fbt/fapassets.py +++ b/scripts/fbt/fapassets.py @@ -1,5 +1,5 @@ -import os import hashlib +import os import struct from typing import TypedDict diff --git a/scripts/fbt/sdk/cache.py b/scripts/fbt/sdk/cache.py index 756c37827..b6f6edbe5 100644 --- a/scripts/fbt/sdk/cache.py +++ b/scripts/fbt/sdk/cache.py @@ -1,20 +1,13 @@ -import operator -import os import csv import operator - -from enum import Enum, auto -from typing import Set, ClassVar, Any +import os from dataclasses import dataclass +from enum import Enum, auto +from typing import Any, ClassVar, Set from ansi.color import fg -from . import ( - ApiEntries, - ApiEntryFunction, - ApiEntryVariable, - ApiHeader, -) +from . import ApiEntries, ApiEntryFunction, ApiEntryVariable, ApiHeader @dataclass(frozen=True) @@ -137,7 +130,7 @@ class SdkCache: f"API version is still WIP: {self.version}. Review the changes and re-run command." ) ) - print(f"CSV file entries to mark up:") + print("CSV file entries to mark up:") print( fg.yellow( "\n".join( diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index 7bdaea031..ae850a8c3 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -1,10 +1,9 @@ -import SCons -from SCons.Subst import quote_spaces -from SCons.Errors import StopError - -import re import os +import re +import SCons +from SCons.Errors import StopError +from SCons.Subst import quote_spaces WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)") diff --git a/scripts/fbt/version.py b/scripts/fbt/version.py index e7fe2edaf..09f48c8eb 100644 --- a/scripts/fbt/version.py +++ b/scripts/fbt/version.py @@ -1,5 +1,5 @@ -import subprocess import datetime +import subprocess from functools import cache diff --git a/scripts/fbt_tools/ccache.py b/scripts/fbt_tools/ccache.py index e88886ade..63577ab78 100644 --- a/scripts/fbt_tools/ccache.py +++ b/scripts/fbt_tools/ccache.py @@ -3,7 +3,7 @@ def exists(): def generate(env): - if ccache := env.WhereIs("ccache"): + if env.WhereIs("ccache"): env["CCACHE"] = "ccache" env["CC_NOCACHE"] = env["CC"] env["CC"] = "$CCACHE $CC_NOCACHE" diff --git a/scripts/fbt_tools/crosscc.py b/scripts/fbt_tools/crosscc.py index dd5cd5319..d0631ca33 100644 --- a/scripts/fbt_tools/crosscc.py +++ b/scripts/fbt_tools/crosscc.py @@ -1,15 +1,11 @@ -from SCons.Errors import StopError -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 subprocess + import gdb import objdump - +import strip from SCons.Action import _subproc -import subprocess +from SCons.Errors import StopError +from SCons.Tool import ar, asm, gcc, gnulink, gxx def prefix_commands(env, command_prefix, cmd_list): diff --git a/scripts/fbt_tools/fbt_apps.py b/scripts/fbt_tools/fbt_apps.py index 9dbe30720..cbb3bf726 100644 --- a/scripts/fbt_tools/fbt_apps.py +++ b/scripts/fbt_tools/fbt_apps.py @@ -1,15 +1,15 @@ -from SCons.Builder import Builder -from SCons.Action import Action -from SCons.Errors import StopError -from SCons.Warnings import warn, WarningOnByDefault from ansi.color import fg - from fbt.appmanifest import ( - FlipperAppType, - AppManager, ApplicationsCGenerator, + AppManager, + FlipperAppType, FlipperManifestException, ) +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Errors import StopError +from SCons.Warnings import WarningOnByDefault, warn +from SCons.Script import GetOption # Adding objects for application management to env # AppManager env["APPMGR"] - loads all manifests; manages list of known apps @@ -29,7 +29,8 @@ def LoadAppManifest(env, entry): env["APPMGR"].load_manifest(app_manifest_file_path, entry) env.Append(PY_LINT_SOURCES=[app_manifest_file_path]) except FlipperManifestException as e: - warn(WarningOnByDefault, str(e)) + if not GetOption("silent"): + warn(WarningOnByDefault, str(e)) def PrepareApplicationsBuild(env): diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index e4c567993..68617c254 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -1,10 +1,10 @@ -from SCons.Builder import Builder -from SCons.Action import Action -from SCons.Errors import StopError - import os import subprocess + from ansi.color import fg +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Errors import StopError def icons_emitter(target, source, env): @@ -76,11 +76,11 @@ def proto_ver_generator(target, source, env): target_file = target[0] src_dir = source[0].dir.abspath try: - git_fetch = _invoke_git( + _invoke_git( ["fetch", "--tags"], source_dir=src_dir, ) - except (subprocess.CalledProcessError, EnvironmentError) as e: + except (subprocess.CalledProcessError, EnvironmentError): # Not great, not terrible print(fg.boldred("Git: fetch failed")) @@ -89,7 +89,7 @@ def proto_ver_generator(target, source, env): ["describe", "--tags", "--abbrev=0"], source_dir=src_dir, ) - except (subprocess.CalledProcessError, EnvironmentError) as e: + except (subprocess.CalledProcessError, EnvironmentError): raise StopError("Git: describe failed") git_major, git_minor = git_describe.split(".") diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index 9abe59893..d46ecd8f3 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -1,5 +1,3 @@ -from re import search - from SCons.Errors import UserError @@ -20,7 +18,7 @@ def GetDevices(env): def generate(env, **kw): env.AddMethod(GetDevices) env.SetDefault( - FBT_DEBUG_DIR="${ROOT_DIR}/debug", + FBT_DEBUG_DIR="${FBT_SCRIPT_DIR}/debug", ) if (adapter_serial := env.subst("$OPENOCD_ADAPTER_SERIAL")) != "auto": @@ -41,10 +39,10 @@ def generate(env, **kw): "|openocd -c 'gdb_port pipe; log_output ${FBT_DEBUG_DIR}/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" ], GDBOPTS_BASE=[ - "-ex", - "target extended-remote ${GDBREMOTE}", "-ex", "source ${FBT_DEBUG_DIR}/gdbinit", + "-ex", + "target extended-remote ${GDBREMOTE}", ], GDBOPTS_BLACKMAGIC=[ "-q", @@ -63,6 +61,8 @@ def generate(env, **kw): "-ex", "source ${FBT_DEBUG_DIR}/flipperapps.py", "-ex", + "source ${FBT_DEBUG_DIR}/flipperversion.py", + "-ex", "fap-set-debug-elf-root ${FBT_FAP_DEBUG_ELF_ROOT}", "-ex", "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py", @@ -70,6 +70,8 @@ def generate(env, **kw): "svd_load ${SVD_FILE}", "-ex", "compare-sections", + "-ex", + "fw-version", ], JFLASHPROJECT="${FBT_DEBUG_DIR}/fw.jflash", ) diff --git a/scripts/fbt_tools/fbt_dist.py b/scripts/fbt_tools/fbt_dist.py index a5669c488..48de8e868 100644 --- a/scripts/fbt_tools/fbt_dist.py +++ b/scripts/fbt_tools/fbt_dist.py @@ -1,6 +1,5 @@ -from SCons.Builder import Builder from SCons.Action import Action -from SCons.Script import Mkdir +from SCons.Builder import Builder from SCons.Defaults import Touch diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 4ac1c6873..1a1bad29e 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -3,23 +3,19 @@ import os import pathlib import shutil from dataclasses import dataclass, field -from typing import Optional, TypedDict - -from ansi.color import fg +from typing import Optional import SCons.Warnings -from SCons.Action import Action -from SCons.Builder import Builder -from SCons.Errors import UserError -from SCons.Node import NodeList -from SCons.Node.FS import File, Entry - +from ansi.color import fg from fbt.appmanifest import FlipperApplication, FlipperAppType, FlipperManifestException from fbt.elfmanifest import assemble_manifest_data from fbt.fapassets import FileBundler from fbt.sdk.cache import SdkCache from fbt.util import extract_abs_dir_path - +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Errors import UserError +from SCons.Node.FS import Entry, File _FAP_META_SECTION = ".fapmeta" _FAP_FILEASSETS_SECTION = ".fapassets" @@ -289,7 +285,7 @@ def GetExtAppByIdOrPath(env, app_dir): try: # Maybe user passed an appid? app = appmgr.get(app_dir) - except FlipperManifestException as _: + except FlipperManifestException: # Look up path components in known app dirs for dir_part in reversed(pathlib.Path(app_dir).parts): if app := appmgr.find_by_appdir(dir_part): diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index 1b2903058..d971cfda5 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -34,6 +34,9 @@ Other: firmware_pvs: generate a PVS-Studio report +How to open a shell with toolchain environment and other build tools: + In your shell, type "source `./fbt -s env`". You can also use "." instead of "source". + For more targets & info, see documentation/fbt.md """ diff --git a/scripts/fbt_tools/fbt_hwtarget.py b/scripts/fbt_tools/fbt_hwtarget.py index 7deb3e87f..e7f857b1e 100644 --- a/scripts/fbt_tools/fbt_hwtarget.py +++ b/scripts/fbt_tools/fbt_hwtarget.py @@ -1,5 +1,3 @@ -from SCons.Builder import Builder -from SCons.Action import Action import json diff --git a/scripts/fbt_tools/fbt_sdk.py b/scripts/fbt_tools/fbt_sdk.py index 90d0831eb..2f7d62388 100644 --- a/scripts/fbt_tools/fbt_sdk.py +++ b/scripts/fbt_tools/fbt_sdk.py @@ -1,21 +1,20 @@ +import json +import os.path +import pathlib +import posixpath import shutil -from SCons.Builder import Builder + +from fbt.sdk.cache import SdkCache +from fbt.sdk.collector import SdkCollector +from fbt.util import path_as_posix from SCons.Action import Action +from SCons.Builder import Builder from SCons.Errors import UserError # from SCons.Scanner import C from SCons.Script import Entry from SCons.Util import LogicalLines -import os.path -import posixpath -import pathlib -import json - -from fbt.sdk.collector import SdkCollector -from fbt.sdk.cache import SdkCache -from fbt.util import path_as_posix - def ProcessSdkDepends(env, filename): try: diff --git a/scripts/fbt_tools/fbt_tweaks.py b/scripts/fbt_tools/fbt_tweaks.py index 700f66d23..68ac9d7d1 100644 --- a/scripts/fbt_tools/fbt_tweaks.py +++ b/scripts/fbt_tools/fbt_tweaks.py @@ -1,15 +1,13 @@ +import os +import sys +import traceback + import SCons.Warnings as Warnings +from ansi.color import fg from SCons.Errors import UserError - # from SCons.Script.Main import find_deepest_user_frame -from ansi.color import fg, bg, fx - -import traceback -import sys -import os - def find_deepest_user_frame(tb): tb.reverse() diff --git a/scripts/fbt_tools/fbt_version.py b/scripts/fbt_tools/fbt_version.py index 87497ca5f..8469e181a 100644 --- a/scripts/fbt_tools/fbt_version.py +++ b/scripts/fbt_tools/fbt_version.py @@ -1,5 +1,5 @@ -from SCons.Builder import Builder from SCons.Action import Action +from SCons.Builder import Builder def version_emitter(target, source, env): diff --git a/scripts/fbt_tools/fwbin.py b/scripts/fbt_tools/fwbin.py index f510c2a60..06a435b6d 100644 --- a/scripts/fbt_tools/fwbin.py +++ b/scripts/fbt_tools/fwbin.py @@ -1,6 +1,6 @@ -from SCons.Builder import Builder -from SCons.Action import Action import SCons +from SCons.Action import Action +from SCons.Builder import Builder __OBJCOPY_ARM_BIN = "arm-none-eabi-objcopy" __NM_ARM_BIN = "arm-none-eabi-nm" diff --git a/scripts/fbt_tools/gdb.py b/scripts/fbt_tools/gdb.py index 38256a0f8..ea29e9c92 100644 --- a/scripts/fbt_tools/gdb.py +++ b/scripts/fbt_tools/gdb.py @@ -1,7 +1,3 @@ -from SCons.Builder import Builder -from SCons.Action import Action - - def generate(env): env.SetDefault( GDB="gdb", diff --git a/scripts/fbt_tools/objdump.py b/scripts/fbt_tools/objdump.py index f5fa938a7..31f817648 100644 --- a/scripts/fbt_tools/objdump.py +++ b/scripts/fbt_tools/objdump.py @@ -1,5 +1,5 @@ -from SCons.Builder import Builder from SCons.Action import Action +from SCons.Builder import Builder def generate(env): diff --git a/scripts/fbt_tools/openocd.py b/scripts/fbt_tools/openocd.py index dcf0bf925..157d798f4 100644 --- a/scripts/fbt_tools/openocd.py +++ b/scripts/fbt_tools/openocd.py @@ -1,7 +1,7 @@ -from SCons.Builder import Builder -from SCons.Action import Action -from SCons.Defaults import Touch import SCons +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Defaults import Touch __OPENOCD_BIN = "openocd" diff --git a/scripts/fbt_tools/pvsstudio.py b/scripts/fbt_tools/pvsstudio.py index 593559a33..211f46aee 100644 --- a/scripts/fbt_tools/pvsstudio.py +++ b/scripts/fbt_tools/pvsstudio.py @@ -1,11 +1,12 @@ -from SCons.Builder import Builder -from SCons.Action import Action -from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten -import multiprocessing -import webbrowser import atexit -import sys +import multiprocessing import subprocess +import sys +import webbrowser + +from SCons.Action import Action +from SCons.Builder import Builder +from SCons.Script import Delete, Flatten, GetBuildFailures, Mkdir __no_browser = False diff --git a/scripts/fbt_tools/sconsmodular.py b/scripts/fbt_tools/sconsmodular.py index 57ae8f055..4dc2079a6 100644 --- a/scripts/fbt_tools/sconsmodular.py +++ b/scripts/fbt_tools/sconsmodular.py @@ -1,5 +1,6 @@ -import posixpath import os +import posixpath + from SCons.Errors import UserError diff --git a/scripts/fbt_tools/sconsrecursiveglob.py b/scripts/fbt_tools/sconsrecursiveglob.py index fbcee965b..7dbde531b 100644 --- a/scripts/fbt_tools/sconsrecursiveglob.py +++ b/scripts/fbt_tools/sconsrecursiveglob.py @@ -1,6 +1,6 @@ import SCons -from SCons.Script import Flatten from fbt.util import GLOB_FILE_EXCLUSION +from SCons.Script import Flatten def GlobRecursive(env, pattern, node=".", exclude=[]): diff --git a/scripts/fbt_tools/strip.py b/scripts/fbt_tools/strip.py index 053956f22..ee14fc185 100644 --- a/scripts/fbt_tools/strip.py +++ b/scripts/fbt_tools/strip.py @@ -1,5 +1,5 @@ -from SCons.Builder import Builder from SCons.Action import Action +from SCons.Builder import Builder def generate(env): diff --git a/scripts/flash.py b/scripts/flash.py index fb05b8b0b..6189dc1a2 100755 --- a/scripts/flash.py +++ b/scripts/flash.py @@ -1,13 +1,9 @@ #!/usr/bin/env python3 -import logging -import argparse -import sys -import os from flipper.app import App -from flipper.cube import CubeProgrammer from flipper.assets.coprobin import CoproBinary +from flipper.cube import CubeProgrammer STATEMENT = "AGREE_TO_LOSE_FLIPPER_FEATURES_THAT_USE_CRYPTO_ENCLAVE" @@ -94,59 +90,59 @@ class Main(App): } def wipe(self): - self.logger.info(f"Wiping flash") + self.logger.info("Wiping flash") cp = CubeProgrammer(self._getCubeParams()) - self.logger.info(f"Setting RDP to 0xBB") + self.logger.info("Setting RDP to 0xBB") cp.setOptionBytes({"RDP": ("0xBB", "rw")}) - self.logger.info(f"Verifying RDP") + self.logger.info("Verifying RDP") r = cp.checkOptionBytes({"RDP": ("0xBB", "rw")}) - assert r == True + assert r is True self.logger.info(f"Result: {r}") - self.logger.info(f"Setting RDP to 0xAA") + self.logger.info("Setting RDP to 0xAA") cp.setOptionBytes({"RDP": ("0xAA", "rw")}) - self.logger.info(f"Verifying RDP") + self.logger.info("Verifying RDP") r = cp.checkOptionBytes({"RDP": ("0xAA", "rw")}) - assert r == True + assert r is True self.logger.info(f"Result: {r}") - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 def core1bootloader(self): - self.logger.info(f"Flashing bootloader") + self.logger.info("Flashing bootloader") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x08000000", self.args.bootloader) - self.logger.info(f"Complete") + self.logger.info("Complete") cp.resetTarget() return 0 def core1firmware(self): - self.logger.info(f"Flashing firmware") + self.logger.info("Flashing firmware") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x08008000", self.args.firmware) - self.logger.info(f"Complete") + self.logger.info("Complete") cp.resetTarget() return 0 def core1(self): - self.logger.info(f"Flashing bootloader") + self.logger.info("Flashing bootloader") cp = CubeProgrammer(self._getCubeParams()) cp.flashBin("0x08000000", self.args.bootloader) - self.logger.info(f"Flashing firmware") + self.logger.info("Flashing firmware") cp.flashBin("0x08008000", self.args.firmware) cp.resetTarget() - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 def core2fus(self): if self.args.statement != STATEMENT: self.logger.error( - f"PLEASE DON'T. THIS FEATURE INTENDED ONLY FOR FACTORY FLASHING" + "PLEASE DON'T. THIS FEATURE INTENDED ONLY FOR FACTORY FLASHING" ) return 1 - self.logger.info(f"Flashing Firmware Update Service") + self.logger.info("Flashing Firmware Update Service") cp = CubeProgrammer(self._getCubeParams()) cp.flashCore2(self.args.fus_address, self.args.fus) - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 def core2radio(self): @@ -163,15 +159,15 @@ class Main(App): f"Radio address not provided, guessed as 0x{radio_address:X}" ) if radio_address > 0x080E0000: - self.logger.error(f"I KNOW WHAT YOU DID LAST SUMMER") + self.logger.error("I KNOW WHAT YOU DID LAST SUMMER") return 1 cp = CubeProgrammer(self._getCubeParams()) - self.logger.info(f"Removing Current Radio Stack") + self.logger.info("Removing Current Radio Stack") cp.deleteCore2RadioStack() - self.logger.info(f"Flashing Radio Stack") + self.logger.info("Flashing Radio Stack") cp.flashCore2(radio_address, self.args.radio) - self.logger.info(f"Complete") + self.logger.info("Complete") return 0 diff --git a/scripts/flipper/app.py b/scripts/flipper/app.py index 30630a5f9..405c4c399 100644 --- a/scripts/flipper/app.py +++ b/scripts/flipper/app.py @@ -44,7 +44,7 @@ class App: if isinstance(return_code, int): return self._exit(return_code) else: - self.logger.error(f"Missing return code") + self.logger.error("Missing return code") return self._exit(255) def _exit(self, code): diff --git a/scripts/flipper/assets/copro.py b/scripts/flipper/assets/copro.py index e0375b51f..f176e3b2e 100644 --- a/scripts/flipper/assets/copro.py +++ b/scripts/flipper/assets/copro.py @@ -1,16 +1,14 @@ -import logging import json -from io import BytesIO -import tarfile -import xml.etree.ElementTree as ET -import posixpath +import logging import os +import posixpath +import tarfile +from io import BytesIO -from flipper.utils import * from flipper.assets.coprobin import CoproBinary, get_stack_type +from flipper.utils import file_sha256, timestamp - -CUBE_COPRO_PATH = "Projects/STM32WB_Copro_Wireless_Binaries" +CUBE_COPRO_PATH = "firmware" MANIFEST_TEMPLATE = { "manifest": {"version": 0, "timestamp": 0}, @@ -27,8 +25,7 @@ MANIFEST_TEMPLATE = { class Copro: COPRO_TAR_DIR = "core2_firmware" - def __init__(self, mcu): - self.mcu = mcu + def __init__(self): self.version = None self.cube_dir = None self.mcu_copro = None @@ -38,20 +35,24 @@ class Copro: if not os.path.isdir(cube_dir): raise Exception(f'"{cube_dir}" doesn\'t exists') self.cube_dir = cube_dir - self.mcu_copro = os.path.join(self.cube_dir, CUBE_COPRO_PATH, self.mcu) + self.mcu_copro = os.path.join(self.cube_dir, CUBE_COPRO_PATH) if not os.path.isdir(self.mcu_copro): raise Exception(f'"{self.mcu_copro}" doesn\'t exists') - cube_manifest_file = os.path.join(self.cube_dir, "package.xml") - cube_manifest = ET.parse(cube_manifest_file) - cube_package = cube_manifest.find("PackDescription") - if not cube_package: - raise Exception(f"Unknown Cube manifest format") - cube_version = cube_package.get("Patch") or cube_package.get("Release") - if not cube_version or not cube_version.startswith("FW.WB"): - raise Exception(f"Incorrect Cube package or version info") - cube_version = cube_version.replace("FW.WB.", "", 1) + try: + cube_manifest_file = os.path.join(self.cube_dir, "VERSION") + with open(cube_manifest_file, "r") as cube_manifest: + cube_version = cube_manifest.read().strip() + except IOError: + raise Exception(f"Failed to read version from {cube_manifest_file}") + + if not cube_version.startswith("v"): + raise Exception(f"Invalid cube version: {cube_version}") + cube_version = cube_version[1:] + if cube_version != reference_cube_version: - raise Exception(f"Unsupported cube version") + raise Exception( + f"Unsupported cube version: {cube_version}, expecting {reference_cube_version}" + ) self.version = cube_version def _getFileName(self, name): diff --git a/scripts/flipper/assets/coprobin.py b/scripts/flipper/assets/coprobin.py index 64f0b8c87..75bf76d76 100644 --- a/scripts/flipper/assets/coprobin.py +++ b/scripts/flipper/assets/coprobin.py @@ -1,10 +1,11 @@ import struct import math -import os, os.path +import os +import os.path import sys -# From STM32CubeWB\Middlewares\ST\STM32_WPAN\interface\patterns\ble_thread\shci\shci.h +# From lib/stm32wb_copro/wpan/interface/patterns/ble_thread/shci/shci.h __STACK_TYPE_CODES = { "BLE_FULL": 0x01, "BLE_HCI": 0x02, diff --git a/scripts/flipper/assets/dolphin.py b/scripts/flipper/assets/dolphin.py index cbd1320b6..ebe9fd889 100644 --- a/scripts/flipper/assets/dolphin.py +++ b/scripts/flipper/assets/dolphin.py @@ -1,13 +1,11 @@ import multiprocessing import logging import os -import sys -import shutil from collections import Counter -from flipper.utils.fff import * -from flipper.utils.templite import * -from .icon import * +from flipper.utils.fff import FlipperFormatFile +from flipper.utils.templite import Templite +from .icon import ImageTools, file2image def _convert_image_to_bm(pair: set): @@ -121,7 +119,7 @@ class DolphinBubbleAnimation: self.meta["Passive frames"] + self.meta["Active frames"] == ordered_frames_count ) - except EOFError as e: + except EOFError: raise Exception("Invalid meta file: too short") except AssertionError as e: self.logger.exception(e) @@ -158,7 +156,7 @@ class DolphinBubbleAnimation: except AssertionError as e: self.logger.exception(e) self.logger.error( - f"Animation {self.name} bubble slot {bubble_slot} got incorrect data: {bubble}" + f"Animation {self.name} bubble slot {bubble['Slot']} got incorrect data: {bubble}" ) raise Exception("Meta file is invalid: incorrect bubble data") except EOFError: diff --git a/scripts/flipper/assets/icon.py b/scripts/flipper/assets/icon.py index f0dae25be..d5d2a585e 100644 --- a/scripts/flipper/assets/icon.py +++ b/scripts/flipper/assets/icon.py @@ -1,9 +1,6 @@ import logging -import argparse import subprocess import io -import os -import sys ICONS_SUPPORTED_FORMATS = ["png"] @@ -36,11 +33,8 @@ class ImageTools: @staticmethod def is_processing_slow(): try: - from PIL import Image, ImageOps - import heatshrink2 - return False - except ImportError as e: + except ImportError: return True def __init__(self): @@ -52,7 +46,7 @@ class ImageTools: try: from PIL import Image, ImageOps - except ImportError as e: + except ImportError: self.__pil_unavailable = True self.logger.info("pillow module is missing, using convert cli util") return self.png2xbm(file) @@ -72,7 +66,7 @@ class ImageTools: try: import heatshrink2 - except ImportError as e: + except ImportError: self.__hs2_unavailable = True self.logger.info("heatshrink2 module is missing, using heatshrink cli util") return self.xbm2hs(data) diff --git a/scripts/flipper/assets/manifest.py b/scripts/flipper/assets/manifest.py index a8f6855a4..a9bbb8dac 100644 --- a/scripts/flipper/assets/manifest.py +++ b/scripts/flipper/assets/manifest.py @@ -1,11 +1,10 @@ -import datetime import logging import os import posixpath from pathlib import Path -from flipper.utils import * -from flipper.utils.fstree import * +from flipper.utils import timestamp, file_md5 +from flipper.utils.fstree import FsNode, compare_fs_trees MANIFEST_VERSION = 0 diff --git a/scripts/flipper/assets/obdata.py b/scripts/flipper/assets/obdata.py index 0f7f5c192..eb35d0e17 100644 --- a/scripts/flipper/assets/obdata.py +++ b/scripts/flipper/assets/obdata.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 -import logging -import struct from enum import Enum from dataclasses import dataclass @@ -181,7 +179,7 @@ class OptionBytesData: def gen_values(self): obref = ObReferenceValuesGenerator() - converted_refs = list(obref.apply(ob) for ob in self.obs) + list(obref.apply(ob) for ob in self.obs) return obref diff --git a/scripts/flipper/cube.py b/scripts/flipper/cube.py index 38aa54a85..e4f9876df 100644 --- a/scripts/flipper/cube.py +++ b/scripts/flipper/cube.py @@ -14,7 +14,7 @@ class CubeProgrammer: if "port" in config and config["port"]: connect.append(f"port={config['port']}") else: - connect.append(f"port=swd") + connect.append("port=swd") if "serial" in config and config["serial"]: connect.append(f"sn={config['serial']}") self.params.append("-c " + " ".join(connect)) @@ -43,20 +43,20 @@ class CubeProgrammer: return output.decode() def getVersion(self): - output = self._execute(["--version"]) + self._execute(["--version"]) def checkOptionBytes(self, option_bytes): output = self._execute(["-ob displ"]) ob_correct = True for line in output.split("\n"): line = line.strip() - if not ":" in line: + if ":" not in line: self.logger.debug(f"Skipping line: {line}") continue key, data = line.split(":", 1) key = key.strip() data = data.strip() - if not key in option_bytes.keys(): + if key not in option_bytes.keys(): self.logger.debug(f"Skipping key: {key}") continue self.logger.debug(f"Processing key: {key} {data}") diff --git a/scripts/flipper/storage.py b/scripts/flipper/storage.py index cff32ceb1..f4d622bfe 100644 --- a/scripts/flipper/storage.py +++ b/scripts/flipper/storage.py @@ -1,12 +1,13 @@ -import os -import sys -import serial -import time -import hashlib -import math -import logging -import posixpath import enum +import hashlib +import logging +import math +import os +import posixpath +import sys +import time + +import serial def timing(func): @@ -151,7 +152,7 @@ class FlipperStorage: try: # TODO: better decoding, considering non-ascii characters line = line.decode("ascii") - except: + except Exception: continue line = line.strip() @@ -194,7 +195,7 @@ class FlipperStorage: try: # TODO: better decoding, considering non-ascii characters line = line.decode("ascii") - except: + except Exception: continue line = line.strip() @@ -236,6 +237,7 @@ class FlipperStorage: filesize = os.fstat(file.fileno()).st_size buffer_size = self.chunk_size + start_time = time.time() while True: filedata = file.read(buffer_size) size = len(filedata) @@ -254,11 +256,13 @@ class FlipperStorage: self.port.write(filedata) self.read.until(self.CLI_PROMPT) - percent = str(math.ceil(file.tell() / filesize * 100)) + ftell = file.tell() + percent = str(math.ceil(ftell / filesize * 100)) total_chunks = str(math.ceil(filesize / buffer_size)) - current_chunk = str(math.ceil(file.tell() / buffer_size)) + current_chunk = str(math.ceil(ftell / buffer_size)) + approx_speed = ftell / (time.time() - start_time + 0.0001) sys.stdout.write( - f"\r{percent}%, chunk {current_chunk} of {total_chunks}" + f"\r{percent}%, chunk {current_chunk} of {total_chunks} @ {approx_speed/1024:.2f} kb/s" ) sys.stdout.flush() print() @@ -323,7 +327,7 @@ class FlipperStorage: return False raise FlipperStorageException.from_error_code(path, error_code) - return True + return response == b"Directory" or response.startswith(b"Storage") def exist_file(self, path: str): """Does file exist on Flipper""" diff --git a/scripts/flipper/utils/__init__.py b/scripts/flipper/utils/__init__.py index 62bf98a25..6b4ebbd52 100644 --- a/scripts/flipper/utils/__init__.py +++ b/scripts/flipper/utils/__init__.py @@ -1,6 +1,5 @@ import datetime import hashlib -import os def timestamp(): diff --git a/scripts/flipper/utils/programmer_openocd.py b/scripts/flipper/utils/programmer_openocd.py index 3d2171854..5a8029f37 100644 --- a/scripts/flipper/utils/programmer_openocd.py +++ b/scripts/flipper/utils/programmer_openocd.py @@ -31,13 +31,13 @@ class OpenOCDProgrammer(Programmer): config["interface"] = interface config["target"] = "target/stm32wbx.cfg" - if not serial is None: + if serial is not None: if interface == "interface/cmsis-dap.cfg": config["serial"] = f"cmsis_dap_serial {serial}" elif "stlink" in interface: config["serial"] = f"stlink_serial {serial}" - if not port_base is None: + if port_base is not None: config["port_base"] = port_base self.openocd = OpenOCD(config) @@ -59,7 +59,7 @@ class OpenOCDProgrammer(Programmer): raise Exception(f"File {file_path} not found") self.openocd.start() - self.openocd.send_tcl(f"init") + self.openocd.send_tcl("init") self.openocd.send_tcl( f"program {file_path} 0x{address:08x}{' verify' if verify else ''} reset exit" ) @@ -196,7 +196,7 @@ class OpenOCDProgrammer(Programmer): if ob_need_to_apply: stm32.option_bytes_apply(self.openocd) else: - self.logger.info(f"Option Bytes are already correct") + self.logger.info("Option Bytes are already correct") # Load Option Bytes # That will reset and also lock the Option Bytes and the Flash @@ -256,7 +256,7 @@ class OpenOCDProgrammer(Programmer): already_written = False if already_written: - self.logger.info(f"OTP memory is already written with the given data") + self.logger.info("OTP memory is already written with the given data") return OpenOCDProgrammerResult.Success self.reset(self.RunMode.Stop) diff --git a/scripts/flipper/utils/stm32wb55.py b/scripts/flipper/utils/stm32wb55.py index 910b0d7d6..52a5ec4e3 100644 --- a/scripts/flipper/utils/stm32wb55.py +++ b/scripts/flipper/utils/stm32wb55.py @@ -123,7 +123,7 @@ class STM32WB55: def clear_flash_errors(self, oocd: OpenOCD): # Errata 2.2.9: Flash OPTVERR flag is always set after system reset # And also clear all other flash error flags - self.logger.debug(f"Resetting flash errors") + self.logger.debug("Resetting flash errors") self.FLASH_SR.load(oocd) self.FLASH_SR.OP_ERR = 1 self.FLASH_SR.PROG_ERR = 1 @@ -218,7 +218,7 @@ class STM32WB55: raise Exception("Flash lock failed") def option_bytes_apply(self, oocd: OpenOCD): - self.logger.debug(f"Applying Option Bytes") + self.logger.debug("Applying Option Bytes") self.FLASH_CR.load(oocd) self.FLASH_CR.OPT_STRT = 1 @@ -228,7 +228,7 @@ class STM32WB55: self.flash_wait_for_operation(oocd) def option_bytes_load(self, oocd: OpenOCD): - self.logger.debug(f"Loading Option Bytes") + self.logger.debug("Loading Option Bytes") self.FLASH_CR.load(oocd) self.FLASH_CR.OBL_LAUNCH = 1 self.FLASH_CR.store(oocd) diff --git a/scripts/flipper/utils/templite.py b/scripts/flipper/utils/templite.py index 2d958bd77..1d19585cd 100644 --- a/scripts/flipper/utils/templite.py +++ b/scripts/flipper/utils/templite.py @@ -77,8 +77,8 @@ class TempliteCompiler: return lines = self.block.splitlines() - margin = min(len(l) - len(l.lstrip()) for l in lines if l.strip()) - self.block = "\n".join("\t" * self.offset + l[margin:] for l in lines) + margin = min(len(line) - len(line.lstrip()) for line in lines if line.strip()) + self.block = "\n".join("\t" * self.offset + line[margin:] for line in lines) self.blocks.append(self.block) if self.block.endswith(":"): self.offset += 1 diff --git a/scripts/fwsize.py b/scripts/fwsize.py index 445c29049..75a825692 100644 --- a/scripts/fwsize.py +++ b/scripts/fwsize.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -from flipper.app import App -import subprocess -import os import math +import os +import subprocess + from ansi.color import fg +from flipper.app import App class Main(App): diff --git a/scripts/get_env.py b/scripts/get_env.py index 92f9243c2..5403bafeb 100644 --- a/scripts/get_env.py +++ b/scripts/get_env.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 -import ssl -import json -import os -import shlex -import re -import string -import random import argparse import datetime +import json +import os +import random +import re +import shlex +import ssl +import string import urllib.request diff --git a/scripts/lint.py b/scripts/lint.py index 58f2d69f5..8530209be 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -1,14 +1,13 @@ #!/usr/bin/env python3 +import multiprocessing import os import re import shutil import subprocess -import multiprocessing from flipper.app import App - SOURCE_CODE_FILE_EXTENSIONS = [".h", ".c", ".cpp", ".cxx", ".hpp"] SOURCE_CODE_FILE_PATTERN = r"^[0-9A-Za-z_]+\.[a-z]+$" SOURCE_CODE_DIR_PATTERN = r"^[0-9A-Za-z_]+$" @@ -59,7 +58,7 @@ class Main(App): show_message = True if show_message: self.logger.warning( - f"Folders are not renamed automatically, please fix it by yourself" + "Folders are not renamed automatically, please fix it by yourself" ) def _find_sources(self, folders: list): @@ -70,7 +69,7 @@ class Main(App): for filename in filenames: ext = os.path.splitext(filename.lower())[1] - if not ext in SOURCE_CODE_FILE_EXTENSIONS: + if ext not in SOURCE_CODE_FILE_EXTENSIONS: continue output.append(os.path.join(dirpath, filename)) return output @@ -80,7 +79,7 @@ class Main(App): try: subprocess.check_call(task) return True - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError: return False def _format_sources(self, sources: list, dry_run: bool = False): @@ -144,7 +143,7 @@ class Main(App): def _apply_file_permissions(self, sources: list, dry_run: bool = False): execute_permissions = 0o111 - pattern = re.compile(SOURCE_CODE_FILE_PATTERN) + re.compile(SOURCE_CODE_FILE_PATTERN) good = [] bad = [] # Check sources for unexpected execute permissions diff --git a/scripts/merge_report_qa.py b/scripts/merge_report_qa.py index caa742408..a33327e6b 100755 --- a/scripts/merge_report_qa.py +++ b/scripts/merge_report_qa.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 +import argparse import os import re import sys -import argparse + from slack_sdk import WebClient from slack_sdk.errors import SlackApiError diff --git a/scripts/meta.py b/scripts/meta.py index ae2f213b7..f47ef65fb 100755 --- a/scripts/meta.py +++ b/scripts/meta.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 -from flipper.app import App import json +from flipper.app import App + class Main(App): def init(self): diff --git a/scripts/ob.py b/scripts/ob.py index 178fe16a7..7010bdec5 100755 --- a/scripts/ob.py +++ b/scripts/ob.py @@ -44,7 +44,7 @@ class Main(App): ) def check(self): - self.logger.info(f"Checking Option Bytes") + self.logger.info("Checking Option Bytes") # OpenOCD openocd = OpenOCDProgrammer( @@ -60,7 +60,7 @@ class Main(App): return return_code def set(self): - self.logger.info(f"Setting Option Bytes") + self.logger.info("Setting Option Bytes") # OpenOCD openocd = OpenOCDProgrammer( diff --git a/scripts/otp.py b/scripts/otp.py index cb76bdc86..19b8c4df4 100755 --- a/scripts/otp.py +++ b/scripts/otp.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 +import datetime import logging -import argparse -import subprocess import os -import sys import re import struct -import datetime + +from flipper.app import App +from flipper.utils.programmer_openocd import OpenOCDProgrammer, OpenOCDProgrammerResult OTP_MAGIC = 0xBABE OTP_VERSION = 0x02 @@ -33,9 +33,6 @@ OTP_DISPLAYS = { "mgg": 0x02, } -from flipper.app import App -from flipper.utils.programmer_openocd import OpenOCDProgrammer, OpenOCDProgrammerResult - class OTPException(Exception): def __init__(self, message: str, result: OpenOCDProgrammerResult): @@ -158,7 +155,7 @@ class Main(App): ) def generate_all(self): - self.logger.info(f"Generating OTP") + self.logger.info("Generating OTP") self._processFirstArgs() self._processSecondArgs() with open(f"{self.args.file}_first.bin", "wb") as file: @@ -172,18 +169,18 @@ class Main(App): return 0 def flash_first(self): - self.logger.info(f"Flashing first block of OTP") + self.logger.info("Flashing first block of OTP") self._processFirstArgs() filename = f"otp_unknown_first_{self.timestamp}.bin" try: - self.logger.info(f"Packing binary data") + self.logger.info("Packing binary data") with open(filename, "wb") as file: file.write(self._packFirst()) - self.logger.info(f"Flashing OTP") + self.logger.info("Flashing OTP") openocd = OpenOCDProgrammer( self.args.interface, @@ -195,7 +192,7 @@ class Main(App): if programmer_result != OpenOCDProgrammerResult.Success: raise OTPException("Failed to flash OTP", programmer_result) - self.logger.info(f"Flashed Successfully") + self.logger.info("Flashed Successfully") except OTPException as e: self.logger.exception(e) return e.get_exit_code() @@ -205,18 +202,18 @@ class Main(App): return 0 def flash_second(self): - self.logger.info(f"Flashing second block of OTP") + self.logger.info("Flashing second block of OTP") self._processSecondArgs() filename = f"otp_{self.args.name}_second_{self.timestamp}.bin" try: - self.logger.info(f"Packing binary data") + self.logger.info("Packing binary data") with open(filename, "wb") as file: file.write(self._packSecond()) - self.logger.info(f"Flashing OTP") + self.logger.info("Flashing OTP") openocd = OpenOCDProgrammer( self.args.interface, @@ -228,7 +225,7 @@ class Main(App): if programmer_result != OpenOCDProgrammerResult.Success: raise OTPException("Failed to flash OTP", programmer_result) - self.logger.info(f"Flashed Successfully") + self.logger.info("Flashed Successfully") except OTPException as e: self.logger.exception(e) return e.get_exit_code() @@ -238,7 +235,7 @@ class Main(App): return 0 def flash_all(self): - self.logger.info(f"Flashing OTP") + self.logger.info("Flashing OTP") self._processFirstArgs() self._processSecondArgs() @@ -246,12 +243,12 @@ class Main(App): filename = f"otp_{self.args.name}_whole_{self.timestamp}.bin" try: - self.logger.info(f"Packing binary data") + self.logger.info("Packing binary data") with open(filename, "wb") as file: file.write(self._packFirst()) file.write(self._packSecond()) - self.logger.info(f"Flashing OTP") + self.logger.info("Flashing OTP") openocd = OpenOCDProgrammer( self.args.interface, @@ -263,7 +260,7 @@ class Main(App): if programmer_result != OpenOCDProgrammerResult.Success: raise OTPException("Failed to flash OTP", programmer_result) - self.logger.info(f"Flashed Successfully") + self.logger.info("Flashed Successfully") except OTPException as e: self.logger.exception(e) return e.get_exit_code() diff --git a/scripts/program.py b/scripts/program.py index c140a9024..f3e7e3e2d 100755 --- a/scripts/program.py +++ b/scripts/program.py @@ -1,13 +1,13 @@ #!/usr/bin/env python3 -import typing -import subprocess import logging -import time import os import socket - +import subprocess +import time +import typing from abc import ABC, abstractmethod from dataclasses import dataclass + from flipper.app import App @@ -223,7 +223,7 @@ class BlackmagicProgrammer(Programmer): try: socket.inet_aton(address) return True - except: + except Exception: return False def set_serial(self, serial: str): @@ -415,12 +415,12 @@ class Main(App): if len(interfaces) == 0: interfaces = [p for p in network_programmers if p.get_name() == i_name] else: - self.logger.info(f"Probing for interfaces...") + self.logger.info("Probing for interfaces...") interfaces = self._search_interface(self.args.serial) if len(interfaces) == 0: # Probe network blackmagic - self.logger.info(f"Probing for network interfaces...") + self.logger.info("Probing for network interfaces...") interfaces = self._search_network_interface(self.args.serial) if len(interfaces) == 0: diff --git a/scripts/runfap.py b/scripts/runfap.py index 397238c69..206c54cc1 100644 --- a/scripts/runfap.py +++ b/scripts/runfap.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 +import operator +from functools import reduce + from flipper.app import App from flipper.storage import FlipperStorage, FlipperStorageOperations from flipper.utils.cdc import resolve_port -import os -import posixpath -from functools import reduce -import operator - class Main(App): def init(self): @@ -38,8 +36,8 @@ class Main(App): self.parser.set_defaults(func=self.install) @staticmethod - def flatten(l): - return reduce(operator.concat, l, []) + def flatten(item_list): + return reduce(operator.concat, item_list, []) def install(self): self.args.sources = self.flatten(self.args.sources) diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index 5cbd2a703..0504264ac 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -5,7 +5,7 @@ import shutil import tarfile import zipfile from os import makedirs, walk, environ -from os.path import exists, join, relpath, basename, split +from os.path import basename, exists, join, relpath from ansi.color import fg from flipper.app import App @@ -170,7 +170,6 @@ class Main(App): "update.dir", "sdk_headers.dir", "lib.dir", - "debug.dir", "scripts.dir", ) diff --git a/scripts/selfupdate.py b/scripts/selfupdate.py index 9bfbfefa3..d222bf249 100644 --- a/scripts/selfupdate.py +++ b/scripts/selfupdate.py @@ -1,14 +1,12 @@ #!/usr/bin/env python3 -from typing import final -from flipper.app import App -from flipper.storage import FlipperStorage, FlipperStorageOperations -from flipper.utils.cdc import resolve_port - import logging import os import pathlib -import serial.tools.list_ports as list_ports + +from flipper.app import App +from flipper.storage import FlipperStorage, FlipperStorageOperations +from flipper.utils.cdc import resolve_port class Main(App): @@ -17,7 +15,7 @@ class Main(App): self.parser.add_argument("manifest_path", help="Manifest path") self.parser.add_argument( - "--pkg_dir_name", help="Update dir name", default="pcbundle", required=False + "--pkg_dir_name", help="Update dir name", default=None, required=False ) self.parser.set_defaults(func=self.install) @@ -54,7 +52,7 @@ class Main(App): f"update install {flipper_update_path}/{manifest_name}\r" ) result = storage.read.until(storage.CLI_EOL) - if not b"Verifying" in result: + if b"Verifying" not in result: self.logger.error(f"Unexpected response: {result.decode('ascii')}") return 3 result = storage.read.until(storage.CLI_EOL) diff --git a/scripts/serial_cli.py b/scripts/serial_cli.py index 390b1f263..2fa37d751 100644 --- a/scripts/serial_cli.py +++ b/scripts/serial_cli.py @@ -1,9 +1,10 @@ import logging -import subprocess -from flipper.utils.cdc import resolve_port import os +import subprocess import sys +from flipper.utils.cdc import resolve_port + def main(): logger = logging.getLogger() diff --git a/scripts/storage.py b/scripts/storage.py index 84c01021a..e04eaa7e1 100755 --- a/scripts/storage.py +++ b/scripts/storage.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 +import binascii +import filecmp +import os +import tempfile + from flipper.app import App from flipper.storage import FlipperStorage, FlipperStorageOperations from flipper.utils.cdc import resolve_port -import os -import binascii -import filecmp -import tempfile - def WrapStorageOp(func): def wrapper(*args, **kwargs): @@ -122,7 +122,7 @@ class Main(App): try: print("Text data:") print(data.decode()) - except: + except Exception: print("Binary hexadecimal data:") print(binascii.hexlify(data).decode()) diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index be4e405c4..d911c2334 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -56,6 +56,16 @@ fbtenv_restore_env() unset SSL_CERT_FILE; unset REQUESTS_CA_BUNDLE; fi + + if [ "$SYS_TYPE" = "Linux" ]; then + if [ -n "$SAVED_TERMINFO_DIRS" ]; then + export TERMINFO_DIRS="$SAVED_TERMINFO_DIRS"; + else + unset TERMINFO_DIRS; + fi + unset SAVED_TERMINFO_DIRS; + fi + export PYTHONNOUSERSITE="$SAVED_PYTHONNOUSERSITE"; export PYTHONPATH="$SAVED_PYTHONPATH"; export PYTHONHOME="$SAVED_PYTHONHOME"; @@ -335,6 +345,11 @@ fbtenv_main() export PYTHONNOUSERSITE=1; export PYTHONPATH=; export PYTHONHOME=; + + if [ "$SYS_TYPE" = "Linux" ]; then + export SAVED_TERMINFO_DIRS="${TERMINFO_DIRS:-""}"; + export TERMINFO_DIRS="$TOOLCHAIN_ARCH_DIR/ncurses/share/terminfo"; + fi } fbtenv_main "${1:-""}"; diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index ce7c8b978..4dd1fb5b9 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -1,7 +1,6 @@ from SCons.Platform import TempFileMunge from SCons.Node import FS from SCons.Errors import UserError -from SCons.Warnings import warn, WarningOnByDefault import os @@ -14,6 +13,7 @@ SetOption("max_drift", 1) ufbt_state_dir = Dir(os.environ.get("UFBT_STATE_DIR", "#.ufbt")) ufbt_script_dir = Dir(os.environ.get("UFBT_SCRIPT_DIR")) +ufbt_build_dir = ufbt_state_dir.Dir("build") ufbt_current_sdk_dir = ufbt_state_dir.Dir("current") @@ -63,16 +63,7 @@ core_env = Environment( ], ) -if "update" in BUILD_TARGETS: - SConscript( - "update.scons", - exports={"core_env": core_env}, - ) - -if "purge" in BUILD_TARGETS: - core_env.Execute(Delete(ufbt_state_dir)) - print("uFBT state purged") - Exit(0) +core_env.Append(CPPDEFINES=GetOption("extra_defines")) # Now we can import stuff bundled with SDK - it was added to sys.path by ufbt_state @@ -109,7 +100,7 @@ env = core_env.Clone( "fbt_assets", ("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}), ], - FBT_FAP_DEBUG_ELF_ROOT=ufbt_state_dir.Dir("build"), + FBT_FAP_DEBUG_ELF_ROOT=ufbt_build_dir, TEMPFILE=TempFileMunge, MAXLINELENGTH=2048, PROGSUFFIX=".elf", @@ -195,6 +186,33 @@ dist_env.PhonyTarget( FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(dist_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")), ) +# Debug alien elf +debug_other_opts = [ + "-ex", + "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py", + "-ex", + "source ${FBT_DEBUG_DIR}/flipperversion.py", + "-ex", + "fw-version", +] + +dist_env.PhonyTarget( + "debug_other", + "${GDBPYCOM}", + GDBOPTS="${GDBOPTS_BASE}", + GDBREMOTE="${OPENOCD_GDB_PIPE}", + GDBPYOPTS=debug_other_opts, +) + +dist_env.PhonyTarget( + "debug_other_blackmagic", + "${GDBPYCOM}", + GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", + GDBREMOTE="${BLACKMAGIC_ADDR}", + GDBPYOPTS=debug_other_opts, +) + + dist_env.PhonyTarget( "flash_blackmagic", "$GDB $GDBOPTS $SOURCES $GDBFLASH", @@ -389,8 +407,9 @@ dist_env.Alias("vscode_dist", vscode_dist) # Creating app from base template dist_env.SetDefault(FBT_APPID=appenv.subst("$APPID") or "template") +app_template_dir = project_template_dir.Dir("app_template") app_template_dist = [] -for template_file in project_template_dir.Dir("app_template").glob("*"): +for template_file in app_template_dir.glob("*"): dist_file_name = dist_env.subst(template_file.name) if template_file.name.endswith(".png"): app_template_dist.append( @@ -406,12 +425,13 @@ for template_file in project_template_dir.Dir("app_template").glob("*"): }, ) ) - AddPostAction( app_template_dist[-1], [ Mkdir(original_app_dir.Dir("images")), Touch(original_app_dir.Dir("images").File(".gitkeep")), + # scons' glob ignores .dot directories, so we need to copy .github manually + Copy(original_app_dir.Dir(".github"), app_template_dir.Dir(".github")), ], ) dist_env.Precious(app_template_dist) @@ -427,3 +447,30 @@ dist_env.PhonyTarget( "get_apiversion", "@echo $( ${UFBT_API_VERSION} $)", ) + +# Dolphin animation builder. Expects "external" directory in current dir +# with animation sources & manifests. Builds & uploads them to connected Flipper +dolphin_src_dir = original_app_dir.Dir("external") +if dolphin_src_dir.exists(): + dolphin_dir = ufbt_build_dir.Dir("dolphin") + dolphin_external = dist_env.DolphinExtBuilder( + ufbt_build_dir.Dir("dolphin"), + original_app_dir, + DOLPHIN_RES_TYPE="external", + ) + dist_env.PhonyTarget( + "dolphin_ext", + '${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py send "${SOURCE}" /ext/dolphin', + source=ufbt_build_dir.Dir("dolphin"), + ) +else: + + def missing_dolphin_folder(**kw): + raise UserError(f"Dolphin folder not found: {dolphin_src_dir}") + + dist_env.PhonyTarget("dolphin_ext", Action(missing_dolphin_folder, None)) + +dist_env.PhonyTarget( + "env", + "@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)", +) diff --git a/scripts/ufbt/commandline.scons b/scripts/ufbt/commandline.scons index 9af5e9bce..a9b91bbca 100644 --- a/scripts/ufbt/commandline.scons +++ b/scripts/ufbt/commandline.scons @@ -1,32 +1,18 @@ +AddOption( + "--extra-define", + action="append", + dest="extra_defines", + default=[], + help="Extra global define that will be passed to C/C++ compiler, can be specified multiple times", +) + AddOption( "--proxy-env", action="store", dest="proxy_env", default="", - help="Comma-separated list of additional environment variables to pass to child SCons processes", -) - -AddOption( - "--channel", - action="store", - dest="sdk_channel", - choices=["dev", "rc", "release"], - default="", - help="Release channel to use for SDK", -) - -AddOption( - "--branch", - action="store", - dest="sdk_branch", - help="Custom main repo branch to use for SDK", -) - -AddOption( - "--hw-target", - action="store", - dest="sdk_target", - help="SDK Hardware target", + help="Comma-separated list of additional environment variables to pass to " + "child SCons processes", ) vars = Variables("ufbt_options.py", ARGUMENTS) diff --git a/scripts/ufbt/project_template/.vscode/extensions.json b/scripts/ufbt/project_template/.vscode/extensions.json index 35f90700a..ead935b08 100644 --- a/scripts/ufbt/project_template/.vscode/extensions.json +++ b/scripts/ufbt/project_template/.vscode/extensions.json @@ -8,7 +8,8 @@ "amiralizadeh9480.cpp-helper", "marus25.cortex-debug", "zxh404.vscode-proto3", - "augustocdias.tasks-shell-input" + "augustocdias.tasks-shell-input", + "rioj7.command-variable" ], // List of extensions recommended by VS Code that should not be recommended for users of this workspace. "unwantedRecommendations": [ diff --git a/scripts/ufbt/project_template/.vscode/launch.json b/scripts/ufbt/project_template/.vscode/launch.json index 697de9a49..3269bab57 100644 --- a/scripts/ufbt/project_template/.vscode/launch.json +++ b/scripts/ufbt/project_template/.vscode/launch.json @@ -29,6 +29,8 @@ "@UFBT_DEBUG_DIR@/stm32wbx.cfg" ], "postAttachCommands": [ + "source @UFBT_DEBUG_DIR@/flipperversion.py", + "fw-version", "source @UFBT_DEBUG_DIR@/flipperapps.py", "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" ], @@ -49,6 +51,8 @@ "@UFBT_DEBUG_DIR@/stm32wbx.cfg" ], "postAttachCommands": [ + "source @UFBT_DEBUG_DIR@/flipperversion.py", + "fw-version", "source @UFBT_DEBUG_DIR@/flipperapps.py", "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" ], @@ -69,6 +73,8 @@ "attach 1", "set confirm off", "set mem inaccessible-by-default off", + "source @UFBT_DEBUG_DIR@/flipperversion.py", + "fw-version", "source @UFBT_DEBUG_DIR@/flipperapps.py", "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" ] @@ -86,6 +92,8 @@ "svdFile": "@UFBT_DEBUG_DIR@/STM32WB55_CM4.svd", "rtos": "FreeRTOS", "postAttachCommands": [ + "source @UFBT_DEBUG_DIR@/flipperversion.py", + "fw-version", "source @UFBT_DEBUG_DIR@/flipperapps.py", "fap-set-debug-elf-root @UFBT_DEBUG_ELF_DIR@" ] diff --git a/scripts/ufbt/project_template/app_template/.github/workflows/build.yml b/scripts/ufbt/project_template/app_template/.github/workflows/build.yml new file mode 100644 index 000000000..0834f8379 --- /dev/null +++ b/scripts/ufbt/project_template/app_template/.github/workflows/build.yml @@ -0,0 +1,41 @@ +name: "FAP: Build for multiple SDK sources" +# This will build your app for dev and release channels on GitHub. +# It will also build your app every day to make sure it's up to date with the latest SDK changes. +# See https://github.com/marketplace/actions/build-flipper-application-package-fap for more information + +on: + push: + ## put your main branch name under "braches" + #branches: + # - master + pull_request: + schedule: + # do a build every day + - cron: "1 1 * * *" + +jobs: + ufbt-build: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - name: dev channel + sdk-channel: dev + - name: release channel + sdk-channel: release + # You can add unofficial channels here. See ufbt action docs for more info. + name: 'ufbt: Build for ${{ matrix.name }}' + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build with ufbt + uses: flipperdevices/flipperzero-ufbt-action@v0.1.1 + id: build-app + with: + sdk-channel: ${{ matrix.sdk-channel }} + - name: Upload app artifacts + uses: actions/upload-artifact@v3 + with: + # See ufbt action docs for other output variables + name: ${{ github.event.repository.name }}-${{ steps.build-app.outputs.suffix }} + path: ${{ steps.build-app.outputs.fap-artifacts }} diff --git a/scripts/ufbt/site_init.py b/scripts/ufbt/site_init.py index 557085ede..8e38a36e9 100644 --- a/scripts/ufbt/site_init.py +++ b/scripts/ufbt/site_init.py @@ -1,8 +1,8 @@ -from SCons.Script import GetBuildFailures -import SCons.Errors - import atexit + +import SCons.Errors from ansi.color import fg, fx +from SCons.Script import GetBuildFailures def bf_to_str(bf): diff --git a/scripts/ufbt/site_tools/ufbt_help.py b/scripts/ufbt/site_tools/ufbt_help.py index da6ff6e51..3f13edcdb 100644 --- a/scripts/ufbt/site_tools/ufbt_help.py +++ b/scripts/ufbt/site_tools/ufbt_help.py @@ -40,6 +40,9 @@ How to create a new application: 2. Run `ufbt vscode_dist create APPID=myapp` 3. In VSCode, open the folder and start editing. 4. Run `ufbt launch` to build and upload your application. + +How to open a shell with toolchain environment and other build tools: + In your shell, type "source `ufbt -s env`". You can also use "." instead of "source". """ diff --git a/scripts/ufbt/site_tools/ufbt_state.py b/scripts/ufbt/site_tools/ufbt_state.py index 76c6e9acf..0038b66a3 100644 --- a/scripts/ufbt/site_tools/ufbt_state.py +++ b/scripts/ufbt/site_tools/ufbt_state.py @@ -1,12 +1,11 @@ -from SCons.Errors import StopError -from SCons.Warnings import warn, WarningOnByDefault - import json import os -import sys import pathlib +import sys from functools import reduce +from SCons.Errors import StopError + def _load_sdk_data(sdk_root): split_vars = { @@ -79,10 +78,8 @@ def generate(env, **kw): env.SetDefault( # Paths SDK_DEFINITION=env.File(sdk_data["sdk_symbols"]), - FBT_DEBUG_DIR=pathlib.Path( - sdk_current_sdk_dir_node.Dir(sdk_components["debug.dir"]).abspath - ).as_posix(), FBT_SCRIPT_DIR=scripts_dir, + FBT_DEBUG_DIR=scripts_dir.Dir("debug"), LIBPATH=sdk_current_sdk_dir_node.Dir(sdk_components["lib.dir"]), FW_ELF=sdk_current_sdk_dir_node.File(sdk_components["firmware.elf"]), FW_BIN=sdk_current_sdk_dir_node.File(sdk_components["full.bin"]), diff --git a/scripts/ufbt/update.scons b/scripts/ufbt/update.scons deleted file mode 100644 index 9658e0bb2..000000000 --- a/scripts/ufbt/update.scons +++ /dev/null @@ -1,37 +0,0 @@ -from SCons.Errors import StopError - -Import("core_env") - -update_env = core_env.Clone( - toolpath=[core_env["FBT_SCRIPT_DIR"].Dir("fbt_tools")], - tools=["python3"], -) -print("Updating SDK...") -ufbt_state = update_env["UFBT_STATE"] - -update_args = [ - "--ufbt-dir", - f'"{update_env["UFBT_STATE_DIR"]}"', -] - -if branch_name := GetOption("sdk_branch"): - update_args.extend(["--branch", branch_name]) -elif channel_name := GetOption("sdk_channel"): - update_args.extend(["--channel", channel_name]) -elif branch_name := ufbt_state.get("branch", None): - update_args.extend(["--branch", branch_name]) -elif channel_name := ufbt_state.get("channel", None): - update_args.extend(["--channel", channel_name]) -else: - raise StopError("No branch or channel specified for SDK update") - -if hw_target := GetOption("sdk_target"): - update_args.extend(["--hw-target", hw_target]) -else: - update_args.extend(["--hw-target", ufbt_state["hw_target"]]) - -update_env.Replace(UPDATE_ARGS=update_args) -result = update_env.Execute( - update_env.subst('$PYTHON3 "$UFBT_BOOTSTRAP_SCRIPT" $UPDATE_ARGS'), -) -Exit(result) diff --git a/scripts/update.py b/scripts/update.py index c90a853f5..8511c5b99 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -1,17 +1,17 @@ #!/usr/bin/env python3 -from flipper.app import App -from flipper.utils.fff import FlipperFormatFile -from flipper.assets.coprobin import CoproBinary, get_stack_type -from flipper.assets.obdata import OptionBytesData, ObReferenceValues -from os.path import basename, join, exists +import math import os import shutil -import zlib import tarfile -import math +import zlib +from os.path import exists, join import pathlib +from flipper.app import App +from flipper.assets.coprobin import CoproBinary, get_stack_type +from flipper.assets.obdata import ObReferenceValues, OptionBytesData +from flipper.utils.fff import FlipperFormatFile from slideshow import Main as SlideshowMain @@ -287,9 +287,9 @@ class Main(App): @staticmethod def batch(iterable, n=1): - l = len(iterable) - for ndx in range(0, l, n): - yield iterable[ndx : min(ndx + n, l)] + iterable_len = len(iterable) + for ndx in range(0, iterable_len, n): + yield iterable[ndx : min(ndx + n, iterable_len)] if __name__ == "__main__": diff --git a/scripts/version.py b/scripts/version.py index 4fd5fd3f9..6994e31c1 100644 --- a/scripts/version.py +++ b/scripts/version.py @@ -1,13 +1,13 @@ #!/usb/bin/env python3 -VERSION = "XFW-0044" +VERSION = "XFW-0046" + +import json +import os +import subprocess +from datetime import date, datetime from flipper.app import App -import subprocess -import os -import json -from datetime import date, datetime - class GitVersion: REVISION_SUFFIX_LENGTH = 8 @@ -56,7 +56,6 @@ class GitVersion: return { "GIT_COMMIT": commit, "GIT_BRANCH": branch, - "GIT_BRANCH_NUM": branch_num, "FURI_CUSTOM_FLIPPER_NAME": custom_fz_name, "VERSION": version, "BUILD_DIRTY": dirty and 1 or 0, @@ -65,7 +64,6 @@ class GitVersion: return { "GIT_COMMIT": commit, "GIT_BRANCH": branch, - "GIT_BRANCH_NUM": branch_num, "VERSION": version, "BUILD_DIRTY": dirty and 1 or 0, } diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 707132dc8..946844870 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -1,12 +1,12 @@ from dataclasses import dataclass, field +from fbt.appmanifest import FlipperAppType from SCons.Node import NodeList from SCons.Warnings import warn, WarningOnByDefault -from SCons.Errors import UserError + Import("ENV") -from fbt.appmanifest import FlipperAppType appenv = ENV["APPENV"] = ENV.Clone( tools=[