diff --git a/.drone.yml b/.drone.yml
deleted file mode 100644
index defde9435..000000000
--- a/.drone.yml
+++ /dev/null
@@ -1,311 +0,0 @@
-kind: pipeline
-type: docker
-name: "Release firmware"
-
-steps:
- - name: "Update submodules"
- image: alpine/git
- commands:
- - git submodule sync
- - git -c protocol.version=2 submodule update --init --force --recursive
- - git submodule foreach git config --local gc.auto 0
- - git log -1 --format='%H'
-
- - name: "Build firmware"
- image: hfdj/fztools
- pull: never
- commands:
- - export DIST_SUFFIX=${DRONE_TAG}
- - export WORKFLOW_BRANCH_OR_TAG=release-cfw
- - ./fbt COMPACT=1 DEBUG=0 updater_package
- - mkdir artifacts-default
- - mv dist/f7-C/* artifacts-default/
- - ls -laS artifacts-default
- - ls -laS artifacts-default/f7-update-${DRONE_TAG}
- - sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
- - echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
- environment:
- FBT_TOOLS_CUSTOM_LINK:
- from_secret: fbt_link
-
- - name: "Build no anims FW"
- image: hfdj/fztools
- pull: never
- commands:
- - rm -f assets/dolphin/external/manifest.txt
- - cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
- - export DIST_SUFFIX=${DRONE_TAG}n
- - export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
- - ./fbt COMPACT=1 DEBUG=0 updater_package
- - mkdir artifacts-ofw-anims
- - mv dist/f7-C/* artifacts-ofw-anims/
- - ls -laS artifacts-ofw-anims
- - ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
- - echo '' >> CHANGELOG.md
- - echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
- environment:
- FBT_TOOLS_CUSTOM_LINK:
- from_secret: fbt_link
-
- - name: "Bundle self-update packages"
- image: kramos/alpine-zip
- commands:
- - cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
- - cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
- - zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
- - zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
- - tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts debug
- - rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
- - rm -rf artifacts-default/f7-update-${DRONE_TAG}
- - ls -laS artifacts-ofw-anims
- - ls -laS artifacts-default
- - mv artifacts-default/ ${DRONE_TAG}
- - ls -laS ${DRONE_TAG}
-
- - name: "Upload default to updates srv"
- image: appleboy/drone-scp
- settings:
- host:
- from_secret: dep_host
- username:
- from_secret: dep_user
- password:
- from_secret: dep_passwd
- port:
- from_secret: dep_port
- target:
- from_secret: dep_target_new
- source:
- - ${DRONE_TAG}/*.tgz
- - ${DRONE_TAG}/*.zip
- - ${DRONE_TAG}/*.json
- - ${DRONE_TAG}/*.elf
- - ${DRONE_TAG}/*.dfu
- - ${DRONE_TAG}/*.bin
-
- - name: "Upload no-anims to updates srv"
- image: appleboy/drone-scp
- settings:
- host:
- from_secret: dep_host
- username:
- from_secret: dep_user
- password:
- from_secret: dep_passwd
- port:
- from_secret: dep_port
- target:
- from_secret: dep_target_noanim
- source: flipper-z-f7-update-${DRONE_TAG}n.tgz
-
- - name: "Do Github release"
- image: ddplugins/github-release
- pull: never
- settings:
- github_url: https://github.com
- repo_owner:
- from_secret: github_repoowner
- api_key:
- from_secret: github_apikey
- files:
- - ${DRONE_TAG}/*.tgz
- - ${DRONE_TAG}/*.zip
- - artifacts-ofw-anims/*.tgz
- title: ${DRONE_TAG}
- note: CHANGELOG.md
- checksum:
- - md5
- - sha1
- - crc32
-
- - name: "Trigger update server reindex"
- image: hfdj/fztools
- pull: never
- environment:
- UPD_KEY:
- from_secret: git_update_serv_token
- UPD_URL:
- from_secret: git_update_server_url
- commands:
- - curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
-
- - name: "Send files to telegram"
- image: appleboy/drone-telegram
- settings:
- token:
- from_secret: tgtoken
- to:
- from_secret: tgid
- format: markdown
- message: "New Unleashed firmware released!
-
-
- Version: {{build.tag}}
-
-
- [-Github-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
-
-
- [-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
-
-
- [-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
-
-
- [-Version without custom animations - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
-
-
- [-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})"
- document:
- - ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
-
- - name: "Send discord notification"
- image: appleboy/drone-discord
- settings:
- webhook_id:
- from_secret: ds_wh_id
- webhook_token:
- from_secret: ds_wh_token
- message: "New Unleashed firmware released!
-
-
- Version: {{build.tag}}
-
-
- [[Github]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
-
-
- [-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
-
-
- [-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
-
-
- [-Version without custom animations - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
-
-
- [-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})"
-
-trigger:
- event:
- - tag
-
-node:
- typ: haupt
-
----
-kind: pipeline
-type: docker
-name: "Dev build"
-
-steps:
- - name: "Update submodules"
- image: alpine/git
- commands:
- - git submodule sync
- - git -c protocol.version=2 submodule update --init --force --recursive
- - git submodule foreach git config --local gc.auto 0
- - git log -1 --format='%H'
-
- - name: "Build dev FW"
- image: hfdj/fztools
- pull: never
- commands:
- - export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
- - export WORKFLOW_BRANCH_OR_TAG=dev-cfw
- - ./fbt COMPACT=1 DEBUG=0 updater_package
- - mkdir artifacts-default
- - mv dist/f7-C/* artifacts-default/
- - ls -laS artifacts-default
- - ls -laS artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
- environment:
- FBT_TOOLS_CUSTOM_LINK:
- from_secret: fbt_link
-
- - name: "Bundle self-update packages"
- image: kramos/alpine-zip
- commands:
- - cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
- - rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
- - ls -laS artifacts-default
- - mv artifacts-default/ dev
- - ls -laS dev
-
- - name: "Clean dev folder"
- image: appleboy/drone-ssh
- settings:
- host:
- from_secret: dep_host
- username:
- from_secret: dep_user
- password:
- from_secret: dep_passwd
- port:
- from_secret: dep_port
- command_timeout: 30s
- script:
- - cd web/unleashedflip.com/public_html/fw/dev && rm -f ./*
-
- - name: "Upload default to updates srv"
- image: appleboy/drone-scp
- settings:
- host:
- from_secret: dep_host
- username:
- from_secret: dep_user
- password:
- from_secret: dep_passwd
- port:
- from_secret: dep_port
- target:
- from_secret: dep_target_new
- source:
- - dev/*.tgz
- - dev/*.zip
- - dev/*.json
- - dev/*.elf
- - dev/*.dfu
- - dev/*.bin
-
- - name: "Trigger update server reindex"
- image: hfdj/fztools
- pull: never
- environment:
- UPD_KEY:
- from_secret: git_update_serv_token
- UPD_URL:
- from_secret: git_update_server_url
- commands:
- - curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
-
- - name: "Send files to telegram"
- image: appleboy/drone-telegram
- settings:
- token:
- from_secret: tgtoken
- to:
- from_secret: tgid_dev
- format: markdown
- message: "Unleashed firmware dev build successful!
-
-
- Build: {{build.number}}
-
- SHA: {{commit.sha}}
-
-
- Commit: {{commit.message}}
-
-
- [-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})"
- document:
- - dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
-
-trigger:
- branch:
- - dev
- event:
- - push
-
-node:
- typ: haupt
diff --git a/.github/workflows/ansible.cfg b/.github/workflows/ansible.cfg
deleted file mode 100644
index 922e8902a..000000000
--- a/.github/workflows/ansible.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[defaults]
-inventory = inventory
-
-host_key_checking = true
\ No newline at end of file
diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml
deleted file mode 100644
index 4cd298384..000000000
--- a/.github/workflows/deployment.yml
+++ /dev/null
@@ -1,108 +0,0 @@
----
-- hosts: all
- become: yes
- become_user: ClaraCrazy
- gather_facts: True
- tasks:
-
- #########################################
- # Creating a temp directory on the host #
- #########################################
- - name: Create a temp directory if it does not exist
- ansible.builtin.file:
- path: ~/temp/flipper/flipperzero-firmware/
- state: directory
- mode: '0777'
-
- #########################################
- # Creating a temp directory on the host #
- #########################################
- - name: Create a build directory if it does not exist
- ansible.builtin.file:
- path: ~/temp/build/
- state: directory
- mode: '0777'
-
- ##########################
- # Checkout Flipper Repo #
- ##########################
- - name: Checkout the flipper git repo
- ansible.builtin.git:
- repo: 'https://github.com/flipperdevices/flipperzero-firmware'
- dest: ~/temp/flipper/flipperzero-firmware/
-
- ######################################################################
- # Clean up previous firmware contetns folder before build deployment #
- ######################################################################
- - name: Delete content & directory
- file:
- state: absent
- path: ~/temp/flipper/flipperzero-firmware/dist/f7-D/f7-update-local
-
- #####################
- # Run Build Command #
- #####################
- - name: This command will change the working directory to /temp/flipper/flipperzero-firmware/
- ansible.builtin.shell:
- chdir: ~/temp/flipper/flipperzero-firmware/
- cmd: ./fbt updater_package
-
- ##############################################
- # copy firmware contents to new build folder #
- ##############################################
- - name: copy git repo to remote server
- copy:
- src: ~/temp/flipper/flipperzero-firmware/dist/f7-D/f7-update-local
- dest: ~/flipper/build/
- remote_src: yes
-
- ###################################
- # Create a .tar based on contents #
- ###################################
- - name: Compress directory ~/flipper/build/
- archive:
- path: ~/flipper/build/
- dest: ~/flipper/build/newbuild.tgz
-
- # #########################
- # # Create update weblink #
- # #########################
- # - name: deploy Docker Compose stack on remote server
- # docker_compose:
- # project_src: ~/srv/authelia/
- # files:
- # - docker-compose.yml
- # recreate: always
-
- # ##########################################
- # # upload .zip to github #
- # ##########################################
- # - name: Delete content & directory
- # file:
- # state: absent
- # path: ~/temp/
-
- # #######################################
- # # post new release message on githhub #
- # #######################################
- # - name: copy git repo to remote server
- # copy:
- # src: ~/temp/authelia
- # dest: ~/srv/
- # remote_src: yes
-
- # ############################################
- # # Post result on CMD line after deployment #
- # ############################################
- # - debug:
- # var: ansible_facts["shell"]
-
- # #################################################
- # # clean up mess made when creating new firmware #
- # # and new firmware release folder #
- # #################################################
- # - name: copy git repo to remote server
- # copy:
- # src: ~/temp/authelia
- # dest: ~/srv/
- # remote_src: yes
\ No newline at end of file
diff --git a/ReadMe.md b/ReadMe.md
index 5f91fba05..779267ad7 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -54,7 +54,7 @@ Note: This repo is always updated with OFW & Unleashed. No need to mention all t
- SFW Mode
- Jamming Files
- Custom subghz presets
-- Subghz and IR signal replication via gpio | Credits to @ankris812, exact commit lost to time as of rn
+- Subghz and IR signal replication via gpio | Credits to @ankris812
- Honda Keys (CVE-2022-27254)
- NSFW Animations tied to the level system. Read more above
- New API Routes for Locale settings
@@ -65,6 +65,7 @@ Note: This repo is always updated with OFW & Unleashed. No need to mention all t
[Updated]
- All graphics
+- About 1k files to speed things up a lot
- Folder handling for empty ones (Now indicate they are empty)
- Applications now use the new Locale setting
- Compiler now handles all non-compiled faps during build
@@ -95,8 +96,7 @@ Note: This repo is always updated with OFW & Unleashed. No need to mention all t
Known Bugs:
```txt
-- Name Changer app crashes 50% of the time
-- Some apps dont allow to be set as Favorite
+- Nothing rn. Hopefully that wont change
```
----
diff --git a/SConstruct b/SConstruct
index 138b52d93..b8c65044d 100644
--- a/SConstruct
+++ b/SConstruct
@@ -165,6 +165,14 @@ Alias("fap_dist", fap_dist)
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
+# Copy all faps to device
+
+fap_deploy = distenv.PhonyTarget(
+ "fap_deploy",
+ "${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
+ source=Dir("#/assets/resources/apps"),
+)
+
# Target for bundling core2 package for qFlipper
copro_dist = distenv.CoproBuilder(
diff --git a/applications/ReadMe.md b/applications/ReadMe.md
index 6224cb45a..3bd2aeb06 100644
--- a/applications/ReadMe.md
+++ b/applications/ReadMe.md
@@ -86,4 +86,4 @@ Small applications providing configuration for basic firmware and its services.
Utility apps not visible in other menus.
- `storage_move_to_sd` - Data migration tool for internal storage
-- `updater` - Update service & application
+- `updater` - updater service & application
diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c
index 62a826ed6..1a73150a5 100644
--- a/applications/main/bad_usb/bad_usb_script.c
+++ b/applications/main/bad_usb/bad_usb_script.c
@@ -75,8 +75,8 @@ static const DuckyKey ducky_keys[] = {
{"BREAK", HID_KEYBOARD_PAUSE},
{"PAUSE", HID_KEYBOARD_PAUSE},
{"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
- {"DELETE", HID_KEYBOARD_DELETE},
- {"BACKSPACE", HID_KEYPAD_BACKSPACE},
+ {"DELETE", HID_KEYBOARD_DELETE_FORWARD},
+ {"BACKSPACE", HID_KEYBOARD_DELETE},
{"END", HID_KEYBOARD_END},
{"ESC", HID_KEYBOARD_ESCAPE},
{"ESCAPE", HID_KEYBOARD_ESCAPE},
diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c
index 55b04ed67..776343fb0 100644
--- a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c
+++ b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c
@@ -14,9 +14,12 @@ static const char* uart_ch[] = {"13,14", "15,16"};
static const char* flow_pins[] = {"None", "2,3", "6,7", "16,15"};
static const char* baudrate_mode[] = {"Host"};
static const uint32_t baudrate_list[] = {
+ 1200,
2400,
+ 4800,
9600,
19200,
+ 28800,
38400,
57600,
115200,
diff --git a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c
index 6c7096e17..5142a181f 100644
--- a/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c
+++ b/applications/main/infrared/scenes/infrared_scene_edit_rename_done.c
@@ -1,10 +1,18 @@
#include "../infrared_i.h"
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
void infrared_scene_edit_rename_done_on_enter(void* context) {
Infrared* infrared = context;
Popup* popup = infrared->popup;
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
- popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
+ if (settings->sfw_mode) {
+ popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw);
+ }
+ else {
+ popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
+ }
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
popup_set_callback(popup, infrared_popup_closed_callback);
@@ -13,6 +21,7 @@ void infrared_scene_edit_rename_done_on_enter(void* context) {
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
+ free(settings);
}
bool infrared_scene_edit_rename_done_on_event(void* context, SceneManagerEvent event) {
diff --git a/applications/main/infrared/scenes/infrared_scene_learn_done.c b/applications/main/infrared/scenes/infrared_scene_learn_done.c
index 54b7da724..ace9bb250 100644
--- a/applications/main/infrared/scenes/infrared_scene_learn_done.c
+++ b/applications/main/infrared/scenes/infrared_scene_learn_done.c
@@ -1,15 +1,23 @@
#include "../infrared_i.h"
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
void infrared_scene_learn_done_on_enter(void* context) {
Infrared* infrared = context;
Popup* popup = infrared->popup;
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
- popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
-
- if(infrared->app_state.is_learning_new_remote) {
- popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop);
- } else {
- popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
+ if (settings->sfw_mode) {
+ popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw);
+ if (infrared->app_state.is_learning_new_remote) {
+ popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop);
+ }
+ else {
+ popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
+ }
+ }
+ else {
+ popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
}
popup_set_callback(popup, infrared_popup_closed_callback);
@@ -18,6 +26,7 @@ void infrared_scene_learn_done_on_enter(void* context) {
popup_enable_timeout(popup);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
+ free(settings);
}
bool infrared_scene_learn_done_on_event(void* context, SceneManagerEvent event) {
diff --git a/applications/main/infrared/scenes/infrared_scene_learn_success.c b/applications/main/infrared/scenes/infrared_scene_learn_success.c
index 469d4de9e..ed9d8ce6e 100644
--- a/applications/main/infrared/scenes/infrared_scene_learn_success.c
+++ b/applications/main/infrared/scenes/infrared_scene_learn_success.c
@@ -1,4 +1,5 @@
#include "../infrared_i.h"
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
static void
infrared_scene_learn_success_dialog_result_callback(DialogExResult result, void* context) {
@@ -10,6 +11,8 @@ void infrared_scene_learn_success_on_enter(void* context) {
Infrared* infrared = context;
DialogEx* dialog_ex = infrared->dialog_ex;
InfraredSignal* signal = infrared->received_signal;
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
infrared_play_notification_message(infrared, InfraredNotificationMessageGreenOn);
@@ -47,12 +50,18 @@ void infrared_scene_learn_success_on_enter(void* context) {
dialog_ex_set_left_button_text(dialog_ex, "Retry");
dialog_ex_set_right_button_text(dialog_ex, "Save");
dialog_ex_set_center_button_text(dialog_ex, "Send");
- dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63);
+ if (settings->sfw_mode) {
+ dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63_sfw);
+ }
+ else {
+ dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63);
+ }
dialog_ex_set_result_callback(dialog_ex, infrared_scene_learn_success_dialog_result_callback);
dialog_ex_set_context(dialog_ex, context);
dialog_ex_enable_extended_events(dialog_ex);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
+ free(settings);
}
bool infrared_scene_learn_success_on_event(void* context, SceneManagerEvent event) {
diff --git a/applications/main/infrared/scenes/infrared_scene_start.c b/applications/main/infrared/scenes/infrared_scene_start.c
index c7df0f45b..79826ede9 100644
--- a/applications/main/infrared/scenes/infrared_scene_start.c
+++ b/applications/main/infrared/scenes/infrared_scene_start.c
@@ -3,6 +3,7 @@
enum SubmenuIndex {
SubmenuIndexUniversalRemotes,
SubmenuIndexLearnNewRemote,
+ SubmenuIndexLearnNewRemoteRaw,
SubmenuIndexSavedRemotes,
SubmenuIndexDebug
};
@@ -37,6 +38,12 @@ void infrared_scene_start_on_enter(void* context) {
infrared);
if(infrared->app_state.is_debug_enabled) {
+ submenu_add_item(
+ submenu,
+ "Learn New Remote RAW",
+ SubmenuIndexLearnNewRemoteRaw,
+ infrared_scene_start_submenu_callback,
+ infrared);
submenu_add_item(
submenu, "Debug", SubmenuIndexDebug, infrared_scene_start_submenu_callback, infrared);
}
@@ -61,7 +68,14 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) {
if(submenu_index == SubmenuIndexUniversalRemotes) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversal);
consumed = true;
- } else if(submenu_index == SubmenuIndexLearnNewRemote) {
+ } else if(
+ submenu_index == SubmenuIndexLearnNewRemote ||
+ submenu_index == SubmenuIndexLearnNewRemoteRaw) {
+
+ // enable automatic signal decoding if "Learn New Remote"
+ // disable automatic signal decoding if "Learn New Remote (RAW)"
+ infrared_worker_rx_enable_signal_decoding(
+ infrared->worker, submenu_index == SubmenuIndexLearnNewRemote);
infrared->app_state.is_learning_new_remote = true;
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
consumed = true;
diff --git a/applications/main/sub_playlist/playlist.c b/applications/main/sub_playlist/playlist.c
index 4e996c062..b11dae31e 100644
--- a/applications/main/sub_playlist/playlist.c
+++ b/applications/main/sub_playlist/playlist.c
@@ -681,10 +681,10 @@ int32_t playlist_app(void* p) {
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(&browser_options, PLAYLIST_EXT, &I_sub1_10px);
- browser_options.hide_ext = false;
+ browser_options.base_path = PLAYLIST_FOLDER;
+
+ bool res = dialog_file_browser_show(dialogs, app->file_path, app->file_path, &browser_options);
- const bool res =
- dialog_file_browser_show(dialogs, app->file_path, app->file_path, &browser_options);
furi_record_close(RECORD_DIALOGS);
// check if a file was selected
if(!res) {
diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h
index 694683f52..1ad41a8b5 100644
--- a/applications/main/subghz/scenes/subghz_scene_config.h
+++ b/applications/main/subghz/scenes/subghz_scene_config.h
@@ -32,4 +32,3 @@ ADD_SCENE(subghz, decode_raw, DecodeRAW)
ADD_SCENE(subghz, delete_raw, DeleteRAW)
ADD_SCENE(subghz, need_saving, NeedSaving)
ADD_SCENE(subghz, rpc, Rpc)
-ADD_SCENE(subghz, region_info, RegionInfo)
diff --git a/applications/main/subghz/scenes/subghz_scene_region_info.c b/applications/main/subghz/scenes/subghz_scene_region_info.c
deleted file mode 100644
index 82486314d..000000000
--- a/applications/main/subghz/scenes/subghz_scene_region_info.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include "../subghz_i.h"
-
-#include
-
-void subghz_scene_region_info_on_enter(void* context) {
- SubGhz* subghz = context;
- const FuriHalRegion* const region = furi_hal_region_get();
- FuriString* buffer;
- buffer = furi_string_alloc();
- if(region) {
- furi_string_cat_printf(buffer, "Region: %s, bands:\n", region->country_code);
- for(uint16_t i = 0; i < region->bands_count; ++i) {
- furi_string_cat_printf(
- buffer,
- " %lu-%lu kHz\n",
- region->bands[i].start / 1000,
- region->bands[i].end / 1000);
- }
- } else {
- furi_string_cat_printf(buffer, "Region: N/A\n");
- }
-
- widget_add_string_multiline_element(
- subghz->widget, 0, 0, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(buffer));
-
- furi_string_free(buffer);
- view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdWidget);
-}
-
-bool subghz_scene_region_info_on_event(void* context, SceneManagerEvent event) {
- UNUSED(context);
- UNUSED(event);
- return false;
-}
-
-void subghz_scene_region_info_on_exit(void* context) {
- SubGhz* subghz = context;
- widget_reset(subghz->widget);
-}
diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c
index 1177b6454..62e30784f 100644
--- a/applications/main/subghz/scenes/subghz_scene_start.c
+++ b/applications/main/subghz/scenes/subghz_scene_start.c
@@ -10,7 +10,6 @@ enum SubmenuIndex {
SubmenuIndexAddManually,
SubmenuIndexFrequencyAnalyzer,
SubmenuIndexReadRAW,
- SubmenuIndexShowRegionInfo
};
void subghz_scene_start_remove_advanced_preset(SubGhz* subghz) {
@@ -74,12 +73,6 @@ void subghz_scene_start_on_enter(void* context) {
SubmenuIndexFrequencyAnalyzer,
subghz_scene_start_submenu_callback,
subghz);
- submenu_add_item(
- subghz->submenu,
- "Region Information",
- SubmenuIndexShowRegionInfo,
- subghz_scene_start_submenu_callback,
- subghz);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
submenu_add_item(
subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
@@ -133,11 +126,6 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest);
return true;
- } else if(event.event == SubmenuIndexShowRegionInfo) {
- scene_manager_set_scene_state(
- subghz->scene_manager, SubGhzSceneStart, SubmenuIndexShowRegionInfo);
- scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRegionInfo);
- return true;
}
}
return false;
diff --git a/applications/main/u2f/scenes/u2f_scene_error.c b/applications/main/u2f/scenes/u2f_scene_error.c
index e10e9c098..20b7be952 100644
--- a/applications/main/u2f/scenes/u2f_scene_error.c
+++ b/applications/main/u2f/scenes/u2f_scene_error.c
@@ -1,4 +1,5 @@
#include "../u2f_app_i.h"
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
static void u2f_scene_error_event_callback(GuiButtonType result, InputType type, void* context) {
furi_assert(context);
@@ -11,6 +12,8 @@ static void u2f_scene_error_event_callback(GuiButtonType result, InputType type,
void u2f_scene_error_on_enter(void* context) {
U2fApp* app = context;
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
if(app->error == U2fAppErrorNoFiles) {
widget_add_icon_element(app->widget, 0, 0, &I_SDQuestion_35x43);
@@ -26,19 +29,34 @@ void u2f_scene_error_on_enter(void* context) {
app->widget, GuiButtonTypeLeft, "Back", u2f_scene_error_event_callback, app);
} else if(app->error == U2fAppErrorCloseRpc) {
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
- widget_add_string_multiline_element(
- app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
- widget_add_string_multiline_element(
- app->widget,
- 3,
- 30,
- AlignLeft,
- AlignTop,
- FontSecondary,
- "Disconnect from\nPC or phone to\nuse this function.");
+ if (settings->sfw_mode) {
+ widget_add_string_multiline_element(
+ app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
+ widget_add_string_multiline_element(
+ app->widget,
+ 3,
+ 30,
+ AlignLeft,
+ AlignTop,
+ FontSecondary,
+ "Disconnect from\nPC or phone to\nuse this function.");
+ }
+ else {
+ widget_add_string_multiline_element(
+ app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "I am not\na whore!");
+ widget_add_string_multiline_element(
+ app->widget,
+ 3,
+ 30,
+ AlignLeft,
+ AlignTop,
+ FontSecondary,
+ "Pull out from\nPC or phone to\nuse me like this.");
+ }
}
view_dispatcher_switch_to_view(app->view_dispatcher, U2fAppViewError);
+ free(settings);
}
bool u2f_scene_error_on_event(void* context, SceneManagerEvent event) {
diff --git a/applications/plugins/asteroids/app.c b/applications/plugins/asteroids/app.c
new file mode 100644
index 000000000..1a3945fd7
--- /dev/null
+++ b/applications/plugins/asteroids/app.c
@@ -0,0 +1,689 @@
+/* Copyright (C) 2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifndef PI
+#define PI 3.14159265358979f
+#endif
+
+#define TAG "Asteroids" // Used for logging
+#define DEBUG_MSG 1
+#define SCREEN_XRES 128
+#define SCREEN_YRES 64
+#define GAME_START_LIVES 3
+
+/* The game uses the OK button both to fire and to accelerate the ship.
+ * This makes it a lot more playable since the finger does not have to
+ * move between two keys. However it is important that the extra time the
+ * player needs to press the button to accelerate instead of just firing
+ * is precisely selected to provide a smooth experience. After a few
+ * attempts, it looks like 70 milliseconds is the right spot. */
+#define SHIP_ACCELERATION_KEYPRESS_TIME 70
+
+/* ============================ Data structures ============================= */
+
+typedef struct Ship {
+ float x, /* Ship x position. */
+ y, /* Ship y position. */
+ vx, /* x velocity. */
+ vy, /* y velocity. */
+ rot; /* Current rotation. 2*PI full rotation. */
+} Ship;
+
+typedef struct Bullet {
+ float x, y, vx, vy; /* Fields like in ship. */
+ uint32_t ttl; /* Time to live, in ticks. */
+} Bullet;
+
+typedef struct Asteroid {
+ float x, y, vx, vy, rot, /* Fields like ship. */
+ rot_speed, /* Angular velocity (rot speed and sense). */
+ size; /* Asteroid size. */
+ uint8_t shape_seed; /* Seed to give random shape. */
+} Asteroid;
+
+#define MAXBUL 10 /* Max bullets on the screen. */
+#define MAXAST 32 /* Max asteroids on the screen. */
+#define SHIP_HIT_ANIMATION_LEN 15
+typedef struct AsteroidsApp {
+ /* GUI */
+ Gui *gui;
+ ViewPort *view_port; /* We just use a raw viewport and we render
+ everything into the low level canvas. */
+ FuriMessageQueue *event_queue; /* Key press events go here. */
+
+ /* Game state. */
+ int running; /* Once false exists the app. */
+ bool gameover; /* Game over status. */
+ uint32_t ticks; /* Game ticks. Increments at each refresh. */
+ uint32_t score; /* Game score. */
+ uint32_t lives; /* Number of lives in the current game. */
+ uint32_t ship_hit; /* When non zero, the ship was hit by an asteroid
+ and we need to show an animation as long as
+ its value is non-zero (and decrease it's value
+ at each tick of animation). */
+
+ /* Ship state. */
+ struct Ship ship;
+
+ /* Bullets state. */
+ struct Bullet bullets[MAXBUL]; /* Each bullet state. */
+ int bullets_num; /* Active bullets. */
+ uint32_t last_bullet_tick; /* Tick the last bullet was fired. */
+
+ /* Asteroids state. */
+ Asteroid asteroids[MAXAST]; /* Each asteroid state. */
+ int asteroids_num; /* Active asteroids. */
+
+ uint32_t pressed[InputKeyMAX]; /* pressed[id] is true if pressed.
+ Each array item contains the time
+ in milliseconds the key was pressed. */
+ bool fire; /* Short press detected: fire a bullet. */
+} AsteroidsApp;
+
+/* ============================== Prototypes ================================ */
+
+// Only functions called before their definition are here.
+
+void restart_game_after_gameover(AsteroidsApp *app);
+uint32_t key_pressed_time(AsteroidsApp *app, InputKey key);
+
+/* ============================ 2D drawing ================================== */
+
+/* This structure represents a polygon of at most POLY_MAX points.
+ * The function draw_poly() is able to render it on the screen, rotated
+ * by the amount specified. */
+#define POLY_MAX 8
+typedef struct Poly {
+ float x[POLY_MAX];
+ float y[POLY_MAX];
+ uint32_t points; /* Number of points actually populated. */
+} Poly;
+
+/* Define the polygons we use. */
+Poly ShipPoly = {
+ {-3, 0, 3},
+ {-3, 6, -3},
+ 3
+};
+
+Poly ShipFirePoly = {
+ {-1.5, 0, 1.5},
+ {-3, -6, -3},
+ 3
+};
+
+/* Rotate the point of the polygon 'poly' and store the new rotated
+ * polygon in 'rot'. The polygon is rotated by an angle 'a', with
+ * center at 0,0. */
+void rotate_poly(Poly *rot, Poly *poly, float a) {
+ /* We want to compute sin(a) and cos(a) only one time
+ * for every point to rotate. It's a slow operation. */
+ float sin_a = (float)sin(a);
+ float cos_a = (float)cos(a);
+ for (uint32_t j = 0; j < poly->points; j++) {
+ rot->x[j] = poly->x[j]*cos_a - poly->y[j]*sin_a;
+ rot->y[j] = poly->y[j]*cos_a + poly->x[j]*sin_a;
+ }
+ rot->points = poly->points;
+}
+
+/* This is an 8 bit LFSR we use to generate a predictable and fast
+ * pseudorandom sequence of numbers, to give a different shape to
+ * each asteroid. */
+void lfsr_next(unsigned char *prev) {
+ unsigned char lsb = *prev & 1;
+ *prev = *prev >> 1;
+ if (lsb == 1) *prev ^= 0b11000111;
+ *prev ^= *prev<<7; /* Mix things a bit more. */
+}
+
+/* Render the polygon 'poly' at x,y, rotated by the specified angle. */
+void draw_poly(Canvas *const canvas, Poly *poly, uint8_t x, uint8_t y, float a)
+{
+ Poly rot;
+ rotate_poly(&rot,poly,a);
+ canvas_set_color(canvas, ColorBlack);
+ for (uint32_t j = 0; j < rot.points; j++) {
+ uint32_t a = j;
+ uint32_t b = j+1;
+ if (b == rot.points) b = 0;
+ canvas_draw_line(canvas,x+rot.x[a],y+rot.y[a],
+ x+rot.x[b],y+rot.y[b]);
+ }
+}
+
+/* A bullet is just a + pixels pattern. A single pixel is not
+ * visible enough. */
+void draw_bullet(Canvas *const canvas, Bullet *b) {
+ canvas_draw_dot(canvas,b->x-1,b->y);
+ canvas_draw_dot(canvas,b->x+1,b->y);
+ canvas_draw_dot(canvas,b->x,b->y);
+ canvas_draw_dot(canvas,b->x,b->y-1);
+ canvas_draw_dot(canvas,b->x,b->y+1);
+}
+
+/* Draw an asteroid. The asteroid shapes is computed on the fly and
+ * is not stored in a permanent shape structure. In order to generate
+ * the shape, we use an initial fixed shape that we resize according
+ * to the asteroid size, perturbed according to the asteroid shape
+ * seed, and finally draw it rotated of the right amount. */
+void draw_asteroid(Canvas *const canvas, Asteroid *ast) {
+ Poly ap;
+
+ /* Start with what is kinda of a circle. Note that this could be
+ * stored into a template and copied here, to avoid computing
+ * sin() / cos(). But the Flipper can handle it without problems. */
+ uint8_t r = ast->shape_seed;
+ for (int j = 0; j < 8; j++) {
+ float a = (PI*2)/8*j;
+
+ /* Before generating the point, to make the shape unique generate
+ * a random factor between .7 and 1.3 to scale the distance from
+ * the center. However this asteroid should have its unique shape
+ * that remains always the same, so we use a predictable PRNG
+ * implemented by an 8 bit shift register. */
+ lfsr_next(&r);
+ float scaling = .7+((float)r/255*.6);
+
+ ap.x[j] = (float)sin(a) * ast->size * scaling;
+ ap.y[j] = (float)cos(a) * ast->size * scaling;
+ }
+ ap.points = 8;
+ draw_poly(canvas,&ap,ast->x,ast->y,ast->rot);
+}
+
+/* Draw small ships in the top-right part of the screen, one for
+ * each left live. */
+void draw_left_lives(Canvas *const canvas, AsteroidsApp *app) {
+ int lives = app->lives;
+ int x = SCREEN_XRES-5;
+
+ Poly mini_ship = {
+ {-2, 0, 2},
+ {-2, 4, -2},
+ 3
+ };
+ while(lives--) {
+ draw_poly(canvas,&mini_ship,x,6,PI);
+ x -= 6;
+ }
+}
+
+/* Given the current position, update it according to the velocity and
+ * wrap it back to the other side if the object went over the screen. */
+void update_pos_by_velocity(float *x, float *y, float vx, float vy) {
+ /* Return back from one side to the other of the screen. */
+ *x += vx;
+ *y += vy;
+ if (*x >= SCREEN_XRES) *x = 0;
+ else if (*x < 0) *x = SCREEN_XRES-1;
+ if (*y >= SCREEN_YRES) *y = 0;
+ else if (*y < 0) *y = SCREEN_YRES-1;
+}
+
+/* Render the current game screen. */
+void render_callback(Canvas *const canvas, void *ctx) {
+ AsteroidsApp *app = ctx;
+
+ /* Clear screen. */
+ canvas_set_color(canvas, ColorWhite);
+ canvas_draw_box(canvas, 0, 0, SCREEN_XRES-1, SCREEN_YRES-1);
+
+ /* Draw score. */
+ canvas_set_color(canvas, ColorBlack);
+ canvas_set_font(canvas, FontSecondary);
+ char score[32];
+ snprintf(score,sizeof(score),"%lu",app->score);
+ canvas_draw_str(canvas, 0, 8, score);
+
+ /* Draw left ships. */
+ draw_left_lives(canvas,app);
+
+ /* Draw ship, asteroids, bullets. */
+ draw_poly(canvas,&ShipPoly,app->ship.x,app->ship.y,app->ship.rot);
+ if (key_pressed_time(app,InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME)
+ draw_poly(canvas,&ShipFirePoly,app->ship.x,app->ship.y,app->ship.rot);
+
+ for (int j = 0; j < app->bullets_num; j++)
+ draw_bullet(canvas,&app->bullets[j]);
+
+ for (int j = 0; j < app->asteroids_num; j++)
+ draw_asteroid(canvas,&app->asteroids[j]);
+
+ /* Game over text. */
+ if (app->gameover) {
+ canvas_set_color(canvas, ColorBlack);
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str(canvas, 28, 35, "GAME OVER");
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas, 25, 50, "Press OK to restart");
+ }
+}
+
+/* ============================ Game logic ================================== */
+
+float distance(float x1, float y1, float x2, float y2) {
+ float dx = x1-x2;
+ float dy = y1-y2;
+ return sqrt(dx*dx+dy*dy);
+}
+
+/* Detect a collision between the object at x1,y1 of radius r1 and
+ * the object at x2, y2 of radius r2. A factor < 1 will make the
+ * function detect the collision even if the objects are yet not
+ * relly touching, while a factor > 1 will make it detect the collision
+ * only after they are a bit overlapping. It basically is used to
+ * rescale the distance.
+ *
+ * Note that in this simplified 2D world, objects are all considered
+ * spheres (this is why this function only takes the radius). This
+ * is, after all, kinda accurate for asteroids, for bullets, and
+ * even for the ship "core" itself. */
+bool objects_are_colliding(float x1, float y1, float r1,
+ float x2, float y2, float r2,
+ float factor)
+{
+ /* The objects are colliding if the distance between object 1 and 2
+ * is smaller than the sum of the two radiuses r1 and r2.
+ * So it would be like: sqrt((x1-x2)^2+(y1-y2)^2) < r1+r2.
+ * However we can avoid computing the sqrt (which is slow) by
+ * squaring the second term and removing the square root, making
+ * the comparison like this:
+ *
+ * (x1-x2)^2+(y1-y2)^2 < (r1+r2)^2. */
+ float dx = (x1-x2)*factor;
+ float dy = (y1-y2)*factor;
+ float rsum = r1+r2;
+ return dx*dx+dy*dy < rsum*rsum;
+}
+
+/* Create a new bullet headed in the same direction of the ship. */
+void ship_fire_bullet(AsteroidsApp *app) {
+ if (app->bullets_num == MAXBUL) return;
+ Bullet *b = &app->bullets[app->bullets_num];
+ b->x = app->ship.x;
+ b->y = app->ship.y;
+ b->vx = -sin(app->ship.rot);
+ b->vy = cos(app->ship.rot);
+
+ /* Ship should fire from its head, not in the middle. */
+ b->x += b->vx*5;
+ b->y += b->vy*5;
+
+ /* Give the bullet some velocity (for now the vector is just
+ * normalized to 1). */
+ b->vx *= 3;
+ b->vy *= 3;
+
+ /* It's more realistic if we add the velocity vector of the
+ * ship, too. Otherwise if the ship is going fast the bullets
+ * will be slower, which is not how the world works. */
+ b->vx += app->ship.vx;
+ b->vy += app->ship.vy;
+
+ b->ttl = 50; /* The bullet will disappear after N ticks. */
+ app->bullets_num++;
+}
+
+/* Remove the specified bullet by id (index in the array). */
+void remove_bullet(AsteroidsApp *app, int bid) {
+ /* Replace the top bullet with the empty space left
+ * by the removal of this bullet. This way we always take the
+ * array dense, which is an advantage when looping. */
+ int n = --app->bullets_num;
+ if (n && bid != n) app->bullets[bid] = app->bullets[n];
+}
+
+/* Create a new asteroid, away from the ship. Return the
+ * pointer to the asteroid object, so that the caller can change
+ * certain things of the asteroid if needed. */
+Asteroid *add_asteroid(AsteroidsApp *app) {
+ if (app->asteroids_num == MAXAST) return NULL;
+ float size = 4+rand()%15;
+ float min_distance = 20;
+ float x,y;
+ do {
+ x = rand() % SCREEN_XRES;
+ y = rand() % SCREEN_YRES;
+ } while(distance(app->ship.x,app->ship.y,x,y) < min_distance+size);
+ Asteroid *a = &app->asteroids[app->asteroids_num++];
+ a->x = x;
+ a->y = y;
+ a->vx = 2*(-.5 + ((float)rand()/RAND_MAX));
+ a->vy = 2*(-.5 + ((float)rand()/RAND_MAX));
+ a->size = size;
+ a->rot = 0;
+ a->rot_speed = ((float)rand()/RAND_MAX)/10;
+ if (app->ticks & 1) a->rot_speed = -(a->rot_speed);
+ a->shape_seed = rand() & 255;
+ return a;
+}
+
+/* Remove the specified asteroid by id (index in the array). */
+void remove_asteroid(AsteroidsApp *app, int id) {
+ /* Replace the top asteroid with the empty space left
+ * by the removal of this one. This way we always take the
+ * array dense, which is an advantage when looping. */
+ int n = --app->asteroids_num;
+ if (n && id != n) app->asteroids[id] = app->asteroids[n];
+}
+
+/* Called when an asteroid was reached by a bullet. The asteroid
+ * hit is the one with the specified 'id'. */
+void asteroid_was_hit(AsteroidsApp *app, int id) {
+ float sizelimit = 6; // Smaller than that, they disappear in one shot.
+ Asteroid *a = &app->asteroids[id];
+
+ /* Asteroid is large enough to break into fragments. */
+ float size = a->size;
+ float x = a->x, y = a->y;
+ remove_asteroid(app,id);
+ if (size > sizelimit) {
+ int max_fragments = size / sizelimit;
+ int fragments = 2+rand()%max_fragments;
+ float newsize = size/fragments;
+ if (newsize < 2) newsize = 2;
+ for (int j = 0; j < fragments; j++) {
+ a = add_asteroid(app);
+ if (a == NULL) break; // Too many asteroids on screen.
+ a->x = x + -(size/2) + rand() % (int)newsize;
+ a->y = y + -(size/2) + rand() % (int)newsize;
+ a->size = newsize;
+ }
+ } else {
+ app->score++;
+ }
+}
+
+/* Set game over state. When in game-over mode, the game displays a
+ * game over text with a background of many asteroids floating around. */
+void game_over(AsteroidsApp *app) {
+ restart_game_after_gameover(app);
+ app->gameover = true;
+ int asteroids = 8;
+ while(asteroids-- && add_asteroid(app) != NULL);
+}
+
+/* Function called when a collision between the asteroid and the
+ * ship is detected. */
+void ship_was_hit(AsteroidsApp *app) {
+ app->ship_hit = SHIP_HIT_ANIMATION_LEN;
+ if (app->lives) {
+ app->lives--;
+ } else {
+ game_over(app);
+ }
+}
+
+/* Restart game after the ship is hit. Will reset the ship position, bullets
+ * and asteroids to restart the game. */
+void restart_game(AsteroidsApp *app) {
+ app->ship.x = SCREEN_XRES / 2;
+ app->ship.y = SCREEN_YRES / 2;
+ app->ship.rot = PI; /* Start headed towards top. */
+ app->ship.vx = 0;
+ app->ship.vy = 0;
+ app->bullets_num = 0;
+ app->last_bullet_tick = 0;
+ app->asteroids_num = 0;
+}
+
+/* Called after game over to restart the game. This function
+ * also calls restart_game(). */
+void restart_game_after_gameover(AsteroidsApp *app) {
+ app->gameover = false;
+ app->ticks = 0;
+ app->score = 0;
+ app->ship_hit = 0;
+ app->lives = GAME_START_LIVES-1; /* -1 to account for current one. */
+ restart_game(app);
+}
+
+/* Move bullets. */
+void update_bullets_position(AsteroidsApp *app) {
+ for (int j = 0; j < app->bullets_num; j++) {
+ update_pos_by_velocity(&app->bullets[j].x,&app->bullets[j].y,
+ app->bullets[j].vx,app->bullets[j].vy);
+ if (--app->bullets[j].ttl == 0) {
+ remove_bullet(app,j);
+ j--; /* Process this bullet index again: the removal will
+ fill it with the top bullet to take the array dense. */
+ }
+ }
+}
+
+/* Move asteroids. */
+void update_asteroids_position(AsteroidsApp *app) {
+ for (int j = 0; j < app->asteroids_num; j++) {
+ update_pos_by_velocity(&app->asteroids[j].x,&app->asteroids[j].y,
+ app->asteroids[j].vx,app->asteroids[j].vy);
+ app->asteroids[j].rot += app->asteroids[j].rot_speed;
+ if (app->asteroids[j].rot < 0) app->asteroids[j].rot = 2*PI;
+ else if (app->asteroids[j].rot > 2*PI) app->asteroids[j].rot = 0;
+ }
+}
+
+/* Collision detection and game state update based on collisions. */
+void detect_collisions(AsteroidsApp *app) {
+ /* Detect collision between bullet and asteroid. */
+ for (int j = 0; j < app->bullets_num; j++) {
+ Bullet *b = &app->bullets[j];
+ for (int i = 0; i < app->asteroids_num; i++) {
+ Asteroid *a = &app->asteroids[i];
+ if (objects_are_colliding(a->x, a->y, a->size,
+ b->x, b->y, 1.5, 1))
+ {
+ asteroid_was_hit(app,i);
+ remove_bullet(app,j);
+ /* The bullet no longer exist. Break the loop.
+ * However we want to start processing from the
+ * same bullet index, since now it is used by
+ * another bullet (see remove_bullet()). */
+ j--; /* Scan this j value again. */
+ break;
+ }
+ }
+ }
+
+ /* Detect collision between ship and asteroid. */
+ for (int j = 0; j < app->asteroids_num; j++) {
+ Asteroid *a = &app->asteroids[j];
+ if (objects_are_colliding(a->x, a->y, a->size,
+ app->ship.x, app->ship.y, 4, 1))
+ {
+ ship_was_hit(app);
+ break;
+ }
+ }
+}
+
+/* This is the main game execution function, called 10 times for
+ * second (with the Flipper screen latency, an higher FPS does not
+ * make sense). In this function we update the position of objects based
+ * on velocity. Detect collisions. Update the score and so forth.
+ *
+ * Each time this function is called, app->tick is incremented. */
+void game_tick(void *ctx) {
+ AsteroidsApp *app = ctx;
+
+ /* There are two special screens:
+ *
+ * 1. Ship was hit, we frozen the game as long as ship_hit isn't zero
+ * again, and show an animation of a rotating ship. */
+ if (app->ship_hit) {
+ app->ship.rot += 0.5;
+ app->ship_hit--;
+ view_port_update(app->view_port);
+ if (app->ship_hit == 0) {
+ restart_game(app);
+ }
+ return;
+ } else if (app->gameover) {
+ /* 2. Game over. We need to update only background asteroids. In this
+ * state the game just displays a GAME OVER text with the floating
+ * asteroids in background. */
+ if (key_pressed_time(app,InputKeyOk) > 100) {
+ restart_game_after_gameover(app);
+ }
+ update_asteroids_position(app);
+ view_port_update(app->view_port);
+ return;
+ }
+
+ /* Handle key presses. */
+ if (app->pressed[InputKeyLeft]) app->ship.rot -= .35;
+ if (app->pressed[InputKeyRight]) app->ship.rot += .35;
+ if (key_pressed_time(app,InputKeyOk) > SHIP_ACCELERATION_KEYPRESS_TIME) {
+ app->ship.vx -= 0.5*(float)sin(app->ship.rot);
+ app->ship.vy += 0.5*(float)cos(app->ship.rot);
+ } else if (app->pressed[InputKeyDown]) {
+ app->ship.vx *= 0.75;
+ app->ship.vy *= 0.75;
+ }
+
+ /* Fire a bullet if needed. app->fire is set in
+ * asteroids_update_keypress_state() since depends on exact
+ * pressure timing. */
+ if (app->fire) {
+ uint32_t bullet_min_period = 200; // In milliseconds
+ uint32_t now = furi_get_tick();
+ if (now - app->last_bullet_tick >= bullet_min_period) {
+ ship_fire_bullet(app);
+ app->last_bullet_tick = now;
+ }
+ app->fire = false;
+ }
+
+ /* Update positions and detect collisions. */
+ update_pos_by_velocity(&app->ship.x,&app->ship.y,app->ship.vx,app->ship.vy);
+ update_bullets_position(app);
+ update_asteroids_position(app);
+ detect_collisions(app);
+
+ /* From time to time, create a new asteroid. The more asteroids
+ * already on the screen, the smaller probability of creating
+ * a new one. */
+ if (app->asteroids_num == 0 ||
+ (random() % 5000) < (30/(1+app->asteroids_num)))
+ {
+ add_asteroid(app);
+ }
+
+ app->ticks++;
+ view_port_update(app->view_port);
+}
+
+/* ======================== Flipper specific code =========================== */
+
+/* Here all we do is putting the events into the queue that will be handled
+ * in the while() loop of the app entry point function. */
+void input_callback(InputEvent* input_event, void* ctx)
+{
+ AsteroidsApp *app = ctx;
+ furi_message_queue_put(app->event_queue,input_event,FuriWaitForever);
+}
+
+/* Allocate the application state and initialize a number of stuff.
+ * This is called in the entry point to create the application state. */
+AsteroidsApp* asteroids_app_alloc() {
+ AsteroidsApp *app = malloc(sizeof(AsteroidsApp));
+
+ app->gui = furi_record_open(RECORD_GUI);
+ app->view_port = view_port_alloc();
+ view_port_draw_callback_set(app->view_port, render_callback, app);
+ view_port_input_callback_set(app->view_port, input_callback, app);
+ gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
+ app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+
+ app->running = 1; /* Turns 0 when back is pressed. */
+ restart_game_after_gameover(app);
+ memset(app->pressed,0,sizeof(app->pressed));
+ return app;
+}
+
+/* Free what the application allocated. It is not clear to me if the
+ * Flipper OS, once the application exits, will be able to reclaim space
+ * even if we forget to free something here. */
+void asteroids_app_free(AsteroidsApp *app) {
+ furi_assert(app);
+
+ // View related.
+ view_port_enabled_set(app->view_port, false);
+ gui_remove_view_port(app->gui, app->view_port);
+ view_port_free(app->view_port);
+ furi_record_close(RECORD_GUI);
+ furi_message_queue_free(app->event_queue);
+ app->gui = NULL;
+
+ free(app);
+}
+
+/* Return the time in milliseconds the specified key is continuously
+ * pressed. Or 0 if it is not pressed. */
+uint32_t key_pressed_time(AsteroidsApp *app, InputKey key) {
+ return app->pressed[key] == 0 ? 0 :
+ furi_get_tick() - app->pressed[key];
+}
+
+/* Handle keys interaction. */
+void asteroids_update_keypress_state(AsteroidsApp *app, InputEvent input) {
+ if (input.type == InputTypePress) {
+ app->pressed[input.key] = furi_get_tick();
+ } else if (input.type == InputTypeRelease) {
+ uint32_t dur = key_pressed_time(app,input.key);
+ app->pressed[input.key] = 0;
+ if (dur < 200 && input.key == InputKeyOk) app->fire = true;
+ }
+}
+
+int32_t asteroids_app_entry(void* p) {
+ UNUSED(p);
+ AsteroidsApp *app = asteroids_app_alloc();
+
+ /* Create a timer. We do data analysis in the callback. */
+ FuriTimer *timer = furi_timer_alloc(game_tick, FuriTimerTypePeriodic, app);
+ furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10);
+
+ /* This is the main event loop: here we get the events that are pushed
+ * in the queue by input_callback(), and process them one after the
+ * other. */
+ InputEvent input;
+ while(app->running) {
+ FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
+ if (qstat == FuriStatusOk) {
+ if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u",
+ input.type, input.key);
+
+ /* Handle navigation here. Then handle view-specific inputs
+ * in the view specific handling function. */
+ if (input.type == InputTypeShort &&
+ input.key == InputKeyBack)
+ {
+ app->running = 0;
+ } else {
+ asteroids_update_keypress_state(app,input);
+ }
+ } else {
+ /* Useful to understand if the app is still alive when it
+ * does not respond because of bugs. */
+ if (DEBUG_MSG) {
+ static int c = 0; c++;
+ if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout");
+ }
+ }
+ }
+
+ furi_timer_free(timer);
+ asteroids_app_free(app);
+ return 0;
+}
diff --git a/applications/plugins/asteroids/appicon.png b/applications/plugins/asteroids/appicon.png
new file mode 100644
index 000000000..45da095af
Binary files /dev/null and b/applications/plugins/asteroids/appicon.png differ
diff --git a/applications/plugins/asteroids/application.fam b/applications/plugins/asteroids/application.fam
new file mode 100644
index 000000000..0a56122e7
--- /dev/null
+++ b/applications/plugins/asteroids/application.fam
@@ -0,0 +1,12 @@
+App(
+ appid="asteroids",
+ name="Asteroids",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="asteroids_app_entry",
+ cdefines=["APP_PROTOVIEW"],
+ requires=["gui"],
+ stack_size=8*1024,
+ order=50,
+ fap_icon="appicon.png",
+ fap_category="Games",
+)
diff --git a/applications/plugins/cli_bridge/.gitignore b/applications/plugins/cli_bridge/.gitignore
new file mode 100644
index 000000000..600d2d33b
--- /dev/null
+++ b/applications/plugins/cli_bridge/.gitignore
@@ -0,0 +1 @@
+.vscode
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/LICENSE b/applications/plugins/cli_bridge/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/applications/plugins/cli_bridge/LICENSE
@@ -0,0 +1,674 @@
+ 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/plugins/cli_bridge/README.md b/applications/plugins/cli_bridge/README.md
new file mode 100644
index 000000000..446f3b8a9
--- /dev/null
+++ b/applications/plugins/cli_bridge/README.md
@@ -0,0 +1,24 @@
+# flipperzero-cli-bridge
+Allows CLI control from GUI, giving untethered access to sub-ghz chat, system diagnostics, and more.
+# Installation
+## Easy way - get a .fap file from the releases page
+Swing by the [releases](https://github.com/ranchordo/flipperzero-cli-bridge/releases) page, and download a pre-built .fap file for the latest flipperzero firmware. Use [qFlipper](https://flipperzero.one/update) to copy the .fap file into SD Card/apps/Tools/. MAKE SURE TO UPGRADE FLIPPERZERO FIRMWARE TO NEWEST VERSION BEFORE INSTALLING.
+## Hard way - building from source
+The following commands will (probably) not work on Windows. If you run Windows, use wsl or a linux vm or something.
+```sh
+git clone https://github.com/flipperdevices/flipperzero-firmware
+cd ./flipperzero-firmware
+git clone https://github.com/ranchordo/flipperzero-cli-bridge ./applications_user/flipperzero-cli-bridge/
+./fbt fap_dist APPSRC=applications_user/flipperzero-cli-bridge
+# If everything went well, the built .fap file can be found in ./dist/f7-D/apps/apps/Tools/cli_gui.fap
+```
+# Usage
+On the flipperzero, you should be able to find a new application (CLI-GUI Bridge) under Applications->Tools. Opening it will result in a text prompt - the prompt for the command line. Enter a suitable command (quickly pressing the back button will input a space) such as `subghz chat [freq in hz, e.g. 310000000]`, etc, then navigate to and press the SAVE key. You should then see the command window. Use Up and Down to scroll, and use Left or Center to get back to the text input prompt. A quick tap of the back key while viewing the console output sends a Ctrl-C to the console.
+## Exiting the app
+Holding and then releasing the back key for at least a second or so (long press) will exit the app normally, meaning that the inner terminal will send Ctrl-C and close. Any sessions will be disconnected.
+
+
+Holding and then releasing the OK key for at least a second or so (long press) will exit the app while keeping the terminal open. Terminal output will be cleared the next time you launch the app, but whatever command or session was running previously will be resumed. This is especially handy with subghz chat - exiting the app while keeping the terminal open will not disconnect you from the chat, and the flipper will still vibrate briefly whenever a new message comes in (even if the app is closed).
+
+
+NOTE: USB functionality (qFlipper, normal USB CLI) may not work after running the app (especially after exiting without closing the terminal), simply restart your flipper and all USB functionality will return to normal.
diff --git a/applications/plugins/cli_bridge/application.fam b/applications/plugins/cli_bridge/application.fam
new file mode 100644
index 000000000..c9baa5254
--- /dev/null
+++ b/applications/plugins/cli_bridge/application.fam
@@ -0,0 +1,10 @@
+App(
+ appid="cli_gui",
+ name="CLI-GUI Bridge",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="cligui_main",
+ requires=["gui","cli"],
+ stack_size=8 * 1024,
+ fap_icon="cligui.png",
+ fap_category="Tools",
+)
diff --git a/applications/plugins/cli_bridge/cli_control.c b/applications/plugins/cli_bridge/cli_control.c
new file mode 100644
index 000000000..e159d7424
--- /dev/null
+++ b/applications/plugins/cli_bridge/cli_control.c
@@ -0,0 +1,109 @@
+#include "cli_control.h"
+
+#include
+#include
+#include
+#include "cligui_main_i.h"
+#include
+
+volatile bool gotCallbackSet = false;
+
+FuriStreamBuffer* tx_stream;
+FuriStreamBuffer* rx_stream;
+static FuriThread* volatile cliThread = NULL;
+static void tx_handler_stdout(const char* buffer, size_t size) {
+ furi_stream_buffer_send(tx_stream, buffer, size, FuriWaitForever);
+}
+static void tx_handler(const uint8_t* buffer, size_t size) {
+ furi_thread_set_stdout_callback(tx_handler_stdout);
+ cliThread = furi_thread_get_current();
+ furi_stream_buffer_send(tx_stream, buffer, size, FuriWaitForever);
+}
+static size_t real_rx_handler(uint8_t* buffer, size_t size, uint32_t timeout) {
+ size_t rx_cnt = 0;
+ while(size > 0) {
+ size_t batch_size = size;
+ if(batch_size > 128) batch_size = 128;
+ size_t len = furi_stream_buffer_receive(rx_stream, buffer, batch_size, timeout);
+ if(len == 0) break;
+ size -= len;
+ buffer += len;
+ rx_cnt += len;
+ }
+ return rx_cnt;
+}
+
+static CliCommand_internal* getInternalCliCommand(Cli* cli, const char* name) {
+ FuriString* target_command = furi_string_alloc();
+ furi_string_set_str(target_command, name);
+ CliCommand_internal* command =
+ CliCommandTree_internal_get(((Cli_internal*)cli)->commands, target_command);
+ furi_string_free(target_command);
+ return command;
+}
+
+static void session_init(void) {
+}
+static void session_deinit(void) {
+}
+static bool session_connected(void) {
+ return true;
+}
+static CliSession session;
+void latch_tx_handler() {
+ Cli* global_cli = furi_record_open(RECORD_CLI);
+
+ CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
+ cliThread = help_command->context;
+
+ furi_thread_set_stdout_callback(tx_handler_stdout);
+ if(cliThread != NULL) {
+ ((FuriThread_internal*)cliThread)->output.write_callback = &tx_handler_stdout;
+ }
+
+ rx_stream = furi_stream_buffer_alloc(128, 1);
+ tx_stream = furi_stream_buffer_alloc(128, 1);
+
+ session.tx = &tx_handler;
+ session.rx = &real_rx_handler;
+ session.tx_stdout = &tx_handler_stdout;
+ session.init = &session_init;
+ session.deinit = &session_deinit;
+ 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);
+ // Stash cliThread if not null
+ if(cliThread != NULL) {
+ CliCommand_internal* help_command = getInternalCliCommand(global_cli, "help");
+ help_command->context = cliThread;
+ }
+ // Switch to new session
+ if(persist) {
+ // Use dummy debug firmware function as is_connected
+ cli_vcp.is_connected = &furi_hal_version_do_i_belong_here;
+ } else {
+ // Send CTRL-C
+ char eot = 0x03;
+ furi_stream_buffer_send(rx_stream, &eot, 1, FuriWaitForever);
+ }
+ cli_session_open(global_cli, &cli_vcp);
+ furi_record_close(RECORD_CLI);
+ // Unblock waiting rx handler
+ furi_stream_buffer_send(rx_stream, "_", 1, FuriWaitForever);
+ // Reconfigure stdout_callback to cli_vcp
+ if(cliThread != NULL) {
+ ((FuriThread_internal*)cliThread)->output.write_callback = cli_vcp.tx_stdout;
+ }
+ // 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/plugins/cli_bridge/cli_control.h b/applications/plugins/cli_bridge/cli_control.h
new file mode 100644
index 000000000..9ea959155
--- /dev/null
+++ b/applications/plugins/cli_bridge/cli_control.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include
+#include
+extern void latch_tx_handler();
+extern void unlatch_tx_handler(bool persist);
+extern FuriStreamBuffer* tx_stream;
+extern FuriStreamBuffer* rx_stream;
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/cligui.png b/applications/plugins/cli_bridge/cligui.png
new file mode 100644
index 000000000..57a97049e
Binary files /dev/null and b/applications/plugins/cli_bridge/cligui.png differ
diff --git a/applications/plugins/cli_bridge/cligui_main.c b/applications/plugins/cli_bridge/cligui_main.c
new file mode 100644
index 000000000..afda14683
--- /dev/null
+++ b/applications/plugins/cli_bridge/cligui_main.c
@@ -0,0 +1,131 @@
+#include "cligui_main_i.h"
+#include "cli_control.h"
+#include "text_input.h"
+#include "console_output.h"
+
+static bool cligui_custom_event_cb(void* context, uint32_t event) {
+ UNUSED(event);
+ CliguiApp* app = context;
+ UNUSED(app);
+ return true;
+}
+static bool cligui_back_event_cb(void* context) {
+ CliguiApp* app = context;
+ UNUSED(app);
+ return true;
+}
+static void cligui_tick_event_cb(void* context) {
+ CliguiApp* app = context;
+ size_t available = furi_stream_buffer_bytes_available(app->data->streams.app_rx);
+ for(size_t i = 0; i < available; i++) {
+ char c = 0;
+ size_t len = furi_stream_buffer_receive(app->data->streams.app_rx, &c, 1, 100);
+ if(len > 0) {
+ furi_string_push_back(app->text_box_store, c);
+ }
+ }
+ if (available > 0) {
+ text_box_set_text(app->text_box, furi_string_get_cstr(app->text_box_store));
+ }
+ // Set input header stuff
+ size_t len = furi_string_size(app->text_box_store);
+ size_t idx = len - 2;
+ while (idx > 0) {
+ if (furi_string_get_char(app->text_box_store, idx) == '\n') {
+ idx++;
+ break;
+ }
+ idx--;
+ }
+ text_input_set_header_text(app->text_input, furi_string_get_cstr(app->text_box_store) + idx);
+ UNUSED(app);
+}
+
+ViewPortInputCallback prev_input_callback;
+volatile bool persistent_exit = false;
+static void input_callback_wrapper(InputEvent* event, void* context) {
+ CliguiApp* app = context;
+ if(event->type == InputTypeLong && event->key == InputKeyBack) {
+ persistent_exit = false;
+ view_dispatcher_stop(app->view_dispatcher);
+ }
+ if(event->type == InputTypeLong && event->key == InputKeyOk) {
+ persistent_exit = true;
+ view_dispatcher_stop(app->view_dispatcher);
+ }
+ if(app->data->state == ViewTextInput) {
+ text_input_input_handler(app, event);
+ } else {
+ console_output_input_handler(app, event);
+ }
+ prev_input_callback(event, app->view_dispatcher);
+}
+
+int32_t cligui_main(void* p) {
+ UNUSED(p);
+ CliguiApp* cligui = malloc(sizeof(CliguiApp));
+ cligui->data = malloc(sizeof(CliguiData));
+
+ latch_tx_handler();
+ cligui->data->streams.app_tx = rx_stream;
+ cligui->data->streams.app_rx = tx_stream;
+
+ cligui->gui = furi_record_open(RECORD_GUI);
+ cligui->view_dispatcher = view_dispatcher_alloc();
+ cligui->view_dispatcher_i = (ViewDispatcher_internal*)(cligui->view_dispatcher);
+ prev_input_callback =
+ ((ViewPort_internal*)cligui->view_dispatcher_i->view_port)->input_callback;
+ view_port_input_callback_set(
+ cligui->view_dispatcher_i->view_port, input_callback_wrapper, cligui);
+ view_dispatcher_enable_queue(cligui->view_dispatcher);
+ view_dispatcher_set_event_callback_context(cligui->view_dispatcher, cligui);
+ view_dispatcher_set_custom_event_callback(cligui->view_dispatcher, cligui_custom_event_cb);
+ view_dispatcher_set_navigation_event_callback(cligui->view_dispatcher, cligui_back_event_cb);
+ view_dispatcher_set_tick_event_callback(cligui->view_dispatcher, cligui_tick_event_cb, 100);
+
+ view_dispatcher_attach_to_gui(
+ cligui->view_dispatcher, cligui->gui, ViewDispatcherTypeFullscreen);
+
+ view_dispatcher_send_to_front(cligui->view_dispatcher);
+
+ cligui->text_box = text_box_alloc();
+ view_dispatcher_add_view(
+ cligui->view_dispatcher, ViewConsoleOutput, text_box_get_view(cligui->text_box));
+ cligui->text_box_store = furi_string_alloc();
+ furi_string_reserve(cligui->text_box_store, TEXT_BOX_STORE_SIZE);
+ furi_string_set_char(cligui->text_box_store, 0, 0);
+ text_box_set_text(cligui->text_box, furi_string_get_cstr(cligui->text_box_store));
+ text_box_set_focus(cligui->text_box, TextBoxFocusEnd);
+
+ cligui->text_input = text_input_alloc();
+ text_input_set_result_callback(
+ cligui->text_input,
+ text_input_result_callback,
+ cligui,
+ cligui->text_input_store,
+ TEXT_INPUT_STORE_SIZE,
+ true);
+ view_dispatcher_add_view(
+ cligui->view_dispatcher, ViewTextInput, text_input_get_view(cligui->text_input));
+
+ view_dispatcher_switch_to_view(cligui->view_dispatcher, ViewTextInput);
+ cligui->data->state = ViewTextInput;
+
+ view_dispatcher_run(cligui->view_dispatcher);
+
+ view_dispatcher_remove_view(cligui->view_dispatcher, ViewConsoleOutput);
+ view_dispatcher_remove_view(cligui->view_dispatcher, ViewTextInput);
+ text_box_free(cligui->text_box);
+ furi_string_free(cligui->text_box_store);
+ text_input_free(cligui->text_input);
+ view_dispatcher_free(cligui->view_dispatcher);
+
+ unlatch_tx_handler(persistent_exit);
+
+ furi_record_close(RECORD_GUI);
+
+ free(cligui->data);
+ free(cligui);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/cligui_main_i.h b/applications/plugins/cli_bridge/cligui_main_i.h
new file mode 100644
index 000000000..b3b5823c9
--- /dev/null
+++ b/applications/plugins/cli_bridge/cligui_main_i.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "internal_defs.h"
+
+#define TEXT_BOX_STORE_SIZE (4096)
+#define TEXT_INPUT_STORE_SIZE (512)
+
+typedef enum {
+ ViewTextInput,
+ ViewConsoleOutput,
+} CliguiState;
+
+typedef struct {
+ CliguiState state;
+ struct {
+ FuriStreamBuffer* app_tx;
+ FuriStreamBuffer* app_rx;
+ } streams;
+} CliguiData;
+
+typedef struct {
+ CliguiData* data;
+ Gui* gui;
+ TextBox* text_box;
+ FuriString* text_box_store;
+ char text_input_store[TEXT_INPUT_STORE_SIZE + 1];
+ TextInput* text_input;
+ ViewDispatcher* view_dispatcher;
+ ViewDispatcher_internal* view_dispatcher_i;
+} CliguiApp;
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/console_output.c b/applications/plugins/cli_bridge/console_output.c
new file mode 100644
index 000000000..933ee8431
--- /dev/null
+++ b/applications/plugins/cli_bridge/console_output.c
@@ -0,0 +1,13 @@
+#include "console_output.h"
+
+void console_output_input_handler(CliguiApp* app, InputEvent* event) {
+ if(event->type == InputTypeShort && (event->key == InputKeyOk || event->key == InputKeyLeft)) {
+ view_dispatcher_switch_to_view(app->view_dispatcher, ViewTextInput);
+ app->data->state = ViewTextInput;
+ }
+ if(event->type == InputTypeShort && event->key == InputKeyBack) {
+ char eot = 0x03;
+ furi_stream_buffer_send(app->data->streams.app_tx, &eot, 1, FuriWaitForever);
+ }
+
+}
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/console_output.h b/applications/plugins/cli_bridge/console_output.h
new file mode 100644
index 000000000..63e0d9afe
--- /dev/null
+++ b/applications/plugins/cli_bridge/console_output.h
@@ -0,0 +1,4 @@
+#pragma once
+#include "cligui_main_i.h"
+
+extern void console_output_input_handler(CliguiApp*, InputEvent*);
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/internal_defs.h b/applications/plugins/cli_bridge/internal_defs.h
new file mode 100644
index 000000000..cdb5f2fa9
--- /dev/null
+++ b/applications/plugins/cli_bridge/internal_defs.h
@@ -0,0 +1,118 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef struct {
+ FuriThreadStdoutWriteCallback write_callback;
+ FuriString* buffer;
+} FuriThreadStdout_internal;
+
+typedef struct {
+ bool is_service;
+ FuriThreadState state;
+ int32_t ret;
+
+ FuriThreadCallback callback;
+ void* context;
+
+ FuriThreadStateCallback state_callback;
+ void* state_context;
+
+ char* name;
+ configSTACK_DEPTH_TYPE stack_size;
+ FuriThreadPriority priority;
+
+ TaskHandle_t task_handle;
+ bool heap_trace_enabled;
+ size_t heap_size;
+
+ FuriThreadStdout_internal output;
+} FuriThread_internal;
+
+DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)
+typedef struct {
+ FuriMessageQueue* queue;
+ Gui* gui;
+ ViewPort* view_port;
+ ViewDict_t views;
+
+ View* current_view;
+
+ View* ongoing_input_view;
+ uint8_t ongoing_input;
+
+ ViewDispatcherCustomEventCallback custom_event_callback;
+ ViewDispatcherNavigationEventCallback navigation_event_callback;
+ ViewDispatcherTickEventCallback tick_event_callback;
+ uint32_t tick_period;
+ void* event_context;
+} ViewDispatcher_internal;
+
+typedef struct {
+ Gui* gui;
+ bool is_enabled;
+ ViewPortOrientation orientation;
+
+ uint8_t width;
+ uint8_t height;
+
+ ViewPortDrawCallback draw_callback;
+ void* draw_callback_context;
+
+ ViewPortInputCallback input_callback;
+ void* input_callback_context;
+} ViewPort_internal;
+
+typedef struct {
+ FuriThreadId loader_thread;
+
+ const void* application;
+ FuriThread* application_thread;
+ char* application_arguments;
+
+ void* cli;
+ void* gui;
+
+ void* view_dispatcher;
+ void* primary_menu;
+ void* plugins_menu;
+ void* debug_menu;
+ void* settings_menu;
+
+ volatile uint8_t lock_count;
+
+ void* pubsub;
+} Loader_internal;
+
+
+typedef struct {
+ CliCallback callback;
+ void* context;
+ uint32_t flags;
+} CliCommand_internal;
+
+#define CLI_COMMANDS_TREE_RANK 4
+BPTREE_DEF2(
+ CliCommandTree_internal,
+ CLI_COMMANDS_TREE_RANK,
+ FuriString*,
+ FURI_STRING_OPLIST,
+ CliCommand_internal,
+ M_POD_OPLIST)
+
+#define M_OPL_CliCommandTree_internal_t() BPTREE_OPLIST(CliCommandTree_internal, M_POD_OPLIST)
+
+typedef struct {
+ CliCommandTree_internal_t commands;
+ void* mutex;
+ void* idle_sem;
+ void* last_line;
+ void* line;
+ void* session;
+
+ size_t cursor_position;
+} Cli_internal;
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/text_input.c b/applications/plugins/cli_bridge/text_input.c
new file mode 100644
index 000000000..295e7629d
--- /dev/null
+++ b/applications/plugins/cli_bridge/text_input.c
@@ -0,0 +1,31 @@
+#include "text_input.h"
+#include "cligui_main_i.h"
+
+void text_input_result_callback(void* ctx) {
+ CliguiApp* app = ctx;
+ char* data = app->text_input_store;
+ size_t len = strlen(data);
+ for(size_t i = 0; i < len; i++) {
+ if(data[i] >= 0x41 && data[i] <= 0x5A) {
+ // Char is uppercase
+ data[i] += 0x20;
+ }
+ }
+ furi_stream_buffer_send(app->data->streams.app_tx, data, len, FuriWaitForever);
+ furi_stream_buffer_send(app->data->streams.app_tx, "\r\n", 2, FuriWaitForever);
+ data[0] = 0;
+ view_dispatcher_switch_to_view(app->view_dispatcher, ViewConsoleOutput);
+ app->data->state = ViewConsoleOutput;
+}
+
+void text_input_input_handler(CliguiApp* app, InputEvent* event) {
+ UNUSED(app);
+ UNUSED(event);
+ if(event->type == InputTypeShort && event->key == InputKeyBack) {
+ // view_dispatcher_switch_to_view(app->view_dispatcher, ViewConsoleOutput);
+ // app->data->state = ViewConsoleOutput;
+ size_t len = strlen(app->text_input_store);
+ app->text_input_store[len] = ' ';
+ app->text_input_store[len + 1] = 0;
+ }
+}
\ No newline at end of file
diff --git a/applications/plugins/cli_bridge/text_input.h b/applications/plugins/cli_bridge/text_input.h
new file mode 100644
index 000000000..77cc30efa
--- /dev/null
+++ b/applications/plugins/cli_bridge/text_input.h
@@ -0,0 +1,5 @@
+#pragma once
+#include "cligui_main_i.h"
+
+extern void text_input_result_callback(void* ctx);
+extern void text_input_input_handler(CliguiApp*, InputEvent*);
\ No newline at end of file
diff --git a/applications/plugins/dap_link/dap_link.c b/applications/plugins/dap_link/dap_link.c
index 156e16d05..510540588 100644
--- a/applications/plugins/dap_link/dap_link.c
+++ b/applications/plugins/dap_link/dap_link.c
@@ -16,6 +16,8 @@
#include
#include "DAP_Link_icons.h"
+#include "../../settings/desktop_settings/desktop_settings_app.h"
+
/***************************************************************************/
/****************************** DAP COMMON *********************************/
/***************************************************************************/
@@ -482,22 +484,37 @@ DapConfig* dap_app_get_config(DapApp* app) {
int32_t dap_link_app(void* p) {
UNUSED(p);
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
if(furi_hal_usb_is_locked()) {
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
- dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop);
- dialog_message_set_text(
- message,
- "Disconnect from\nPC or phone to\nuse this function.",
- 3,
- 30,
- AlignLeft,
- AlignTop);
+ if (settings->sfw_mode) {
+ dialog_message_set_header(message, "Connection\nis active!", 3, 2, AlignLeft, AlignTop);
+ dialog_message_set_text(
+ message,
+ "Disconnect from\nPC or phone to\nuse this function.",
+ 3,
+ 30,
+ AlignLeft,
+ AlignTop);
+ }
+ else {
+ dialog_message_set_header(message, "I am not\na whore!", 3, 2, AlignLeft, AlignTop);
+ dialog_message_set_text(
+ message,
+ "Pull out from\nPC or phone to\nuse me like this.",
+ 3,
+ 30,
+ AlignLeft,
+ AlignTop);
+ }
dialog_message_set_icon(message, &I_ActiveConnection_50x64, 78, 0);
dialog_message_show(dialogs, message);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
+ free(settings);
return -1;
}
@@ -524,4 +541,4 @@ int32_t dap_link_app(void* p) {
dap_app_free(app);
return 0;
-}
\ No newline at end of file
+}
diff --git a/applications/plugins/flashlight/application.fam b/applications/plugins/flashlight/application.fam
index d6d5aa791..368e14833 100644
--- a/applications/plugins/flashlight/application.fam
+++ b/applications/plugins/flashlight/application.fam
@@ -1,6 +1,6 @@
App(
appid="Flashlight",
- name="Flashlight",
+ name="[GPIO] Flashlight",
apptype=FlipperAppType.EXTERNAL,
entry_point="flashlight_app",
cdefines=["APP_FLASHLIGHT"],
diff --git a/applications/plugins/flipper_i2ctools/application.fam b/applications/plugins/flipper_i2ctools/application.fam
index 7d9c5944c..d8d10dfce 100644
--- a/applications/plugins/flipper_i2ctools/application.fam
+++ b/applications/plugins/flipper_i2ctools/application.fam
@@ -1,6 +1,6 @@
App(
appid="I2C_Tools",
- name="i2c Tools",
+ name="[GPIO] i2c Tools",
apptype=FlipperAppType.EXTERNAL,
entry_point="i2ctools_app",
cdefines=["APP_I2CTOOLS"],
diff --git a/applications/plugins/game2048/2048.png b/applications/plugins/game2048/2048.png
deleted file mode 100644
index 6f46d4de5..000000000
Binary files a/applications/plugins/game2048/2048.png and /dev/null differ
diff --git a/applications/plugins/game2048/application.fam b/applications/plugins/game2048/application.fam
deleted file mode 100644
index 61e474046..000000000
--- a/applications/plugins/game2048/application.fam
+++ /dev/null
@@ -1,12 +0,0 @@
-App(
- appid="2048",
- name="2048 (Original)",
- apptype=FlipperAppType.EXTERNAL,
- entry_point="game_2048_app",
- cdefines=["APP_2048_GAME"],
- requires=["gui"],
- stack_size=2 * 1024,
- order=10,
- fap_icon="2048.png",
- fap_category="Games",
-)
diff --git a/applications/plugins/game2048/font.c b/applications/plugins/game2048/font.c
deleted file mode 100644
index 9acfe8d23..000000000
--- a/applications/plugins/game2048/font.c
+++ /dev/null
@@ -1,155 +0,0 @@
-#include
-#include
-#include
-
-/* 7px 3 width digit font by Sefjor
- * digit encoding example
- *7 111
- *6 101
- *5 101
- *4 101
- *3 101
- *2 101
- *1 111
- *0 000 this string is empty, used to align
- * ? ? ?
- * FE 82 FE //0
- */
-
-static uint8_t font[10][3] = {
- {0xFE, 0x82, 0xFE}, // 0;
- {0x00, 0xFE, 0x00}, // 1;
- {0xF2, 0x92, 0x9E}, // 2;
- {0x92, 0x92, 0xFE}, // 3;
- {0x1E, 0x10, 0xFE}, // 4;
- {0x9E, 0x92, 0xF2}, // 5;
- {0xFE, 0x92, 0xF2}, // 6;
- {0x02, 0x02, 0xFE}, // 7;
- {0xFE, 0x92, 0xFE}, // 8;
- {0x9E, 0x92, 0xFE}, // 9;
-};
-
-#define FONT_HEIGHT 8
-#define FONT_WIDTH 3
-
-static void game_2048_draw_black_point(Canvas* const canvas, uint8_t x, uint8_t y) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_dot(canvas, x, y);
-}
-
-static void game_2048_draw_white_square(Canvas* const canvas, uint8_t x, uint8_t y) {
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_box(canvas, x, y, 15 - 1, 15 - 3);
-}
-
-static void _game_2048_draw_column(
- Canvas* const canvas,
- int digit,
- int coord_x,
- int coord_y,
- uint8_t column) {
- for(int x = 0; x < FONT_HEIGHT; ++x) {
- bool is_filled = (font[digit][column] >> x) & 0x1;
- if(is_filled) {
- game_2048_draw_black_point(canvas, coord_x, coord_y + x);
- }
- }
-}
-
-static uint8_t
- _game_2048_draw_digit(Canvas* const canvas, uint8_t digit, uint8_t coord_x, uint8_t coord_y) {
- uint8_t x_shift = 0;
-
- if(digit != 1) {
- for(int column = 0; column < FONT_WIDTH; column++) {
- _game_2048_draw_column(canvas, digit, coord_x + column, coord_y, column);
- }
- x_shift = 3;
- } else {
- _game_2048_draw_column(canvas, digit, coord_x, coord_y, true);
- x_shift = 1;
- }
-
- return x_shift;
-}
-
-/* We drawing text field with 1px white border
- * at given coords. Total size is:
- * x = 9 = 1 + 7 + 1
- * y = 1 + total text width + 1
- */
-
-/*
- * Returns array of digits and it's size,
- * digits should be at least 4 size
- * works from 1 to 9999
- */
-static void _game_2048_parse_number(uint16_t number, uint8_t* digits, uint8_t* size) {
- *size = 0;
- uint16_t divider = 1000;
- //find first digit, result is highest divider
- while(number / divider == 0) {
- divider /= 10;
- if(divider == 0) {
- break;
- }
- }
-
- for(int i = 0; divider != 0; i++) {
- digits[i] = number / divider;
- number %= divider;
- *size += 1;
- divider /= 10;
- }
-}
-
-uint8_t _game_2048_calculate_shift(uint16_t num) {
- uint8_t shift = 0;
- switch(num) {
- case 1:
- shift = 7;
- break;
- case 2:
- case 4:
- case 8:
- shift = 6;
- break;
- case 16:
- shift = 5;
- break;
- case 32:
- case 64:
- shift = 4;
- break;
- case 128:
- shift = 3;
- break;
- case 256:
- shift = 2;
- break;
- case 512:
- shift = 3;
- break;
- case 1024:
- shift = 2;
- break;
- }
- return shift;
-}
-
-void game_2048_draw_number(Canvas* const canvas, uint8_t x, uint8_t y, int number) {
- uint8_t digits[4];
- uint8_t size;
-
- _game_2048_parse_number(number, digits, &size);
- if(number > 512) {
- game_2048_draw_white_square(canvas, x, y);
- }
-
- x += _game_2048_calculate_shift(number);
- y += 4;
- for(int i = 0; i < size; ++i) {
- x += _game_2048_draw_digit(canvas, digits[i], x, y);
- x++;
- }
-}
\ No newline at end of file
diff --git a/applications/plugins/game2048/font.h b/applications/plugins/game2048/font.h
deleted file mode 100644
index 500123ac3..000000000
--- a/applications/plugins/game2048/font.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include
-
-void game_2048_draw_number(Canvas* const canvas, uint8_t x, uint8_t y, int number);
\ No newline at end of file
diff --git a/applications/plugins/game2048/game_2048.c b/applications/plugins/game2048/game_2048.c
deleted file mode 100644
index 706b95ce5..000000000
--- a/applications/plugins/game2048/game_2048.c
+++ /dev/null
@@ -1,495 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-
-#include "font.h"
-
-#define DEBUG false
-/*
- 0 empty
- 1 2
- 2 4
- 3 8
- 4 16
- 5 32
- 6 64
- 7 128
- 8 256
- 9 512
-10 1024
-11 2048
-12 4096
-...
- */
-typedef uint8_t cell_state;
-
-/* DirectionLeft <--
-┌╌╌╌╌┐┌╌╌╌╌┐┌╌╌╌╌┐┌╌╌╌╌┐
-╎ ╎╎ ╎╎ ╎╎ ╎
-└╌╌╌╌┘└╌╌╌╌┘└╌╌╌╌┘└╌╌╌╌┘
-┌╌╌╌╌┐┌╌╌╌╌┐┌╌╌╌╌┐┌╌╌╌╌┐
-╎ ╎╎ ╎╎ ╎╎ ╎
-└╌╌╌╌┘└╌╌╌╌┘└╌╌╌╌┘└╌╌╌╌┘
-┌╌╌┌╌╌╌╌┐╌╌┐┌╌╌╌╌┐┌╌╌╌╌┐
-╎ 2╎ 2 ╎ ╎╎ ╎╎ ╎
-└╌╌└╌╌╌╌┘╌╌┘└╌╌╌╌┘└╌╌╌╌┘
-┌╌╌┌╌╌╌╌┐┌╌╌┌╌╌╌╌┐┌╌╌╌╌┐
-╎ 4╎ 4 ╎╎ 2╎ 2 ╎╎ ╎
-└╌╌└╌╌╌╌┘└╌╌└╌╌╌╌┘└╌╌╌╌┘
-*/
-typedef enum {
- DirectionIdle,
- DirectionUp,
- DirectionRight,
- DirectionDown,
- DirectionLeft,
-} Direction;
-
-typedef struct {
- uint8_t y; // 0 <= y <= 3
- uint8_t x; // 0 <= x <= 3
-} Point;
-
-typedef struct {
- uint32_t gameScore;
- uint32_t highScore;
-} Score;
-
-typedef struct {
- /*
- +----X
- |
- | field[x][y]
- Y
- */
- uint8_t field[4][4];
-
- uint8_t next_field[4][4];
-
- Score score; // original scoring
-
- Direction direction;
- /*
- field {
- animation-timing-function: linear;
- animation-duration: 300ms;
- }
- */
- uint32_t animation_start_ticks;
-
- Point keyframe_from[4][4];
-
- Point keyframe_to[4][4];
-
- bool debug;
-
-} GameState;
-
-#define XtoPx(x) (33 + x * 15)
-
-#define YtoPx(x) (1 + y * 15)
-
-static void game_2048_render_callback(Canvas* const canvas, ValueMutex* const vm) {
- const GameState* game_state = acquire_mutex(vm, 25);
- if(game_state == NULL) {
- return;
- }
-
- // Before the function is called, the state is set with the canvas_reset(canvas)
-
- if(game_state->direction == DirectionIdle) {
- for(uint8_t y = 0; y < 4; y++) {
- for(uint8_t x = 0; x < 4; x++) {
- uint8_t field = game_state->field[y][x];
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_frame(canvas, XtoPx(x), YtoPx(y), 16, 16);
- if(field != 0) {
- game_2048_draw_number(canvas, XtoPx(x), YtoPx(y), 1 << field);
- }
- }
- }
-
- // display score
- char buffer[12];
- snprintf(buffer, sizeof(buffer), "%lu", game_state->score.gameScore);
- canvas_draw_str_aligned(canvas, 127, 8, AlignRight, AlignBottom, buffer);
-
- if(game_state->score.highScore > 0) {
- char buffer2[12];
- snprintf(buffer2, sizeof(buffer2), "%lu", game_state->score.highScore);
- canvas_draw_str_aligned(canvas, 127, 62, AlignRight, AlignBottom, buffer2);
- }
- } else { // if animation
- // for animation
- // (osKernelGetSysTimerCount() - game_state->animation_start_ticks) / osKernelGetSysTimerFreq();
-
- // TODO: end animation event/callback/set AnimationIdle
- }
-
- release_mutex(vm, game_state);
-}
-
-static void
- game_2048_input_callback(const InputEvent* const input_event, FuriMessageQueue* event_queue) {
- furi_assert(event_queue);
-
- furi_message_queue_put(event_queue, input_event, FuriWaitForever);
-}
-
-// if return false then Game Over
-static bool game_2048_set_new_number(GameState* const game_state) {
- uint8_t empty = 0;
- for(uint8_t y = 0; y < 4; y++) {
- for(uint8_t x = 0; x < 4; x++) {
- if(game_state->field[y][x] == 0) {
- empty++;
- }
- }
- }
-
- if(empty == 0) {
- return false;
- }
-
- if(empty == 1) {
- // If it is 1 move before losing, we help the player and get rid of randomness.
- for(uint8_t y = 0; y < 4; y++) {
- for(uint8_t x = 0; x < 4; x++) {
- if(game_state->field[y][x] == 0) {
- bool haveFour =
- // +----X
- // |
- // | field[x][y], 0 <= x, y <= 3
- // Y
-
- // up == 4 or
- (y > 0 && game_state->field[y - 1][x] == 2) ||
- // right == 4 or
- (x < 3 && game_state->field[y][x + 1] == 2) ||
- // down == 4
- (y < 3 && game_state->field[y + 1][x] == 2) ||
- // left == 4
- (x > 0 && game_state->field[y][x - 1] == 2);
-
- if(haveFour) {
- game_state->field[y][x] = 2;
- return true;
- }
-
- game_state->field[y][x] = 1;
- return true;
- }
- }
- }
- }
-
- uint8_t target = rand() % empty;
- uint8_t twoOrFore = rand() % 4 < 3;
- for(uint8_t y = 0; y < 4; y++) {
- for(uint8_t x = 0; x < 4; x++) {
- if(game_state->field[y][x] == 0) {
- if(target == 0) {
- if(twoOrFore) {
- game_state->field[y][x] = 1; // 2^1 == 2 75%
- } else {
- game_state->field[y][x] = 2; // 2^2 == 4 25%
- }
- goto exit;
- }
- target--;
- }
- }
- }
-exit:
- return true;
-}
-
-// static void game_2048_process_row(uint8_t before[4], uint8_t *(after[4])) {
-// // move 1 row left.
-// for(uint8_t i = 0; i <= 2; i++) {
-// if(before[i] != 0 && before[i] == before[i + 1]) {
-// before[i]++;
-// before[i + 1] = 0;
-// i++;
-// }
-// }
-// for(uint8_t i = 0, j = 0; i <= 3; i++) {
-// if (before[i] != 0) {
-// before[j] = before[i];
-// i++;
-// }
-// }
-// }
-
-static void game_2048_process_move(GameState* const game_state) {
- memset(game_state->next_field, 0, sizeof(game_state->next_field));
- // +----X
- // |
- // | field[x][y], 0 <= x, y <= 3
- // Y
-
- // up
- if(game_state->direction == DirectionUp) {
- for(uint8_t x = 0; x < 4; x++) {
- uint8_t next_y = 0;
- for(int8_t y = 0; y < 4; y++) {
- uint8_t field = game_state->field[y][x];
- if(field == 0) {
- continue;
- }
-
- if(game_state->next_field[next_y][x] == 0) {
- game_state->next_field[next_y][x] = field;
- continue;
- }
-
- if(field == game_state->next_field[next_y][x]) {
- game_state->next_field[next_y][x]++;
- game_state->score.gameScore += pow(2, game_state->next_field[next_y][x]);
- if(game_state->next_field[next_y][x] == 11 && !game_state->debug) {
- DOLPHIN_DEED(getRandomDeed());
- } // get some xp for making a 2048 tile
- next_y++;
- continue;
- }
-
- next_y++;
- game_state->next_field[next_y][x] = field;
- }
- }
- }
-
- // right
- if(game_state->direction == DirectionRight) {
- for(uint8_t y = 0; y < 4; y++) {
- uint8_t next_x = 3;
- for(int8_t x = 3; x >= 0; x--) {
- uint8_t field = game_state->field[y][x];
- if(field == 0) {
- continue;
- }
-
- if(game_state->next_field[y][next_x] == 0) {
- game_state->next_field[y][next_x] = field;
- continue;
- }
-
- if(field == game_state->next_field[y][next_x]) {
- game_state->next_field[y][next_x]++;
- game_state->score.gameScore += pow(2, game_state->next_field[y][next_x]);
- if(game_state->next_field[y][next_x] == 11 && !game_state->debug) {
- DOLPHIN_DEED(getRandomDeed());
- } // get some xp for making a 2048 tile
- next_x--;
- continue;
- }
-
- next_x--;
- game_state->next_field[y][next_x] = field;
- }
- }
- }
-
- // down
- if(game_state->direction == DirectionDown) {
- for(uint8_t x = 0; x < 4; x++) {
- uint8_t next_y = 3;
- for(int8_t y = 3; y >= 0; y--) {
- uint8_t field = game_state->field[y][x];
- if(field == 0) {
- continue;
- }
-
- if(game_state->next_field[next_y][x] == 0) {
- game_state->next_field[next_y][x] = field;
- continue;
- }
-
- if(field == game_state->next_field[next_y][x]) {
- game_state->next_field[next_y][x]++;
- game_state->score.gameScore += pow(2, game_state->next_field[next_y][x]);
- if(game_state->next_field[next_y][x] == 11 && !game_state->debug) {
- DOLPHIN_DEED(getRandomDeed());
- } // get some xp for making a 2048 tile
- next_y--;
- continue;
- }
-
- next_y--;
- game_state->next_field[next_y][x] = field;
- }
- }
- }
-
- // 0, 0, 1, 1
- // 1, 0, 0, 0
-
- // left
- if(game_state->direction == DirectionLeft) {
- for(uint8_t y = 0; y < 4; y++) {
- uint8_t next_x = 0;
- for(uint8_t x = 0; x < 4; x++) {
- uint8_t field = game_state->field[y][x];
- if(field == 0) {
- continue;
- }
-
- if(game_state->next_field[y][next_x] == 0) {
- game_state->next_field[y][next_x] = field;
- continue;
- }
-
- if(field == game_state->next_field[y][next_x]) {
- game_state->next_field[y][next_x]++;
- game_state->score.gameScore += pow(2, game_state->next_field[y][next_x]);
- if(game_state->next_field[y][next_x] == 11 && !game_state->debug) {
- DOLPHIN_DEED(getRandomDeed());
- } // get some xp for making a 2048 tile
- next_x++;
- continue;
- }
-
- next_x++;
- game_state->next_field[y][next_x] = field;
- }
- }
- }
-
- //
- game_state->direction = DirectionIdle;
- memcpy(game_state->field, game_state->next_field, sizeof(game_state->field));
- //
-}
-
-static void game_2048_restart(GameState* const game_state) {
- game_state->debug = DEBUG;
-
- // check score
- if(game_state->score.gameScore > game_state->score.highScore) {
- game_state->score.highScore = game_state->score.gameScore;
- }
-
- // clear all cells
- for(uint8_t y = 0; y < 4; y++) {
- for(uint8_t x = 0; x < 4; x++) {
- game_state->field[y][x] = 0;
- }
- }
-
- // start next game
- game_state->score.gameScore = 0;
- game_2048_set_new_number(game_state);
- game_2048_set_new_number(game_state);
-}
-
-int32_t game_2048_app(void* p) {
- UNUSED(p);
- int32_t return_code = 0;
-
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
-
- GameState* game_state = malloc(sizeof(GameState));
-
- ValueMutex state_mutex;
- if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) {
- return_code = 255;
- goto free_and_exit;
- }
-
- ViewPort* view_port = view_port_alloc();
- view_port_draw_callback_set(
- view_port, (ViewPortDrawCallback)game_2048_render_callback, &state_mutex);
- view_port_input_callback_set(
- view_port, (ViewPortInputCallback)game_2048_input_callback, event_queue);
-
- Gui* gui = furi_record_open(RECORD_GUI);
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
- game_state->direction = DirectionIdle;
- game_2048_restart(game_state);
-
- if(game_state->debug) {
- game_state->field[0][0] = 0;
- game_state->field[0][1] = 0;
- game_state->field[0][2] = 0;
- game_state->field[0][3] = 0;
-
- game_state->field[1][0] = 1;
- game_state->field[1][1] = 2;
- game_state->field[1][2] = 3;
- game_state->field[1][3] = 4;
-
- game_state->field[2][0] = 5;
- game_state->field[2][1] = 6;
- game_state->field[2][2] = 7;
- game_state->field[2][3] = 8;
-
- game_state->field[3][0] = 9;
- game_state->field[3][1] = 10;
- game_state->field[3][2] = 11;
- game_state->field[3][3] = 12;
- }
-
- InputEvent event;
- for(bool loop = true; loop;) {
- FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
- GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex);
-
- if(event_status == FuriStatusOk) {
- if(event.type == InputTypeShort) {
- switch(event.key) {
- case InputKeyUp:
- game_state->direction = DirectionUp;
- game_2048_process_move(game_state);
- game_2048_set_new_number(game_state);
- break;
- case InputKeyDown:
- game_state->direction = DirectionDown;
- game_2048_process_move(game_state);
- game_2048_set_new_number(game_state);
- break;
- case InputKeyRight:
- game_state->direction = DirectionRight;
- game_2048_process_move(game_state);
- game_2048_set_new_number(game_state);
- break;
- case InputKeyLeft:
- game_state->direction = DirectionLeft;
- game_2048_process_move(game_state);
- game_2048_set_new_number(game_state);
- break;
- case InputKeyOk:
- game_state->direction = DirectionIdle;
- break;
- case InputKeyBack:
- loop = false;
- break;
- default:
- break;
- }
- } else if(event.type == InputTypeLong) {
- if(event.key == InputKeyOk) {
- game_state->direction = DirectionIdle;
- game_2048_restart(game_state);
- }
- }
- }
-
- view_port_update(view_port);
- release_mutex(&state_mutex, game_state);
- }
-
- view_port_enabled_set(view_port, false);
- gui_remove_view_port(gui, view_port);
- furi_record_close(RECORD_GUI);
- view_port_free(view_port);
- delete_mutex(&state_mutex);
-
-free_and_exit:
- free(game_state);
- furi_message_queue_free(event_queue);
-
- return return_code;
-}
\ No newline at end of file
diff --git a/applications/plugins/gpioreader/application.fam b/applications/plugins/gpioreader/application.fam
index 55295f3ab..a7f297d47 100644
--- a/applications/plugins/gpioreader/application.fam
+++ b/applications/plugins/gpioreader/application.fam
@@ -1,6 +1,6 @@
App(
appid="GPIO_Reader_B",
- name="GPIO Reader (biotinker)",
+ name="[GPIO] Reader (biotinker)",
apptype=FlipperAppType.EXTERNAL,
entry_point="gpio_app",
cdefines=["APP_GPIOREADER"],
diff --git a/applications/plugins/gpioreader2/application.fam b/applications/plugins/gpioreader2/application.fam
index dd3a6acfe..57792fd0c 100644
--- a/applications/plugins/gpioreader2/application.fam
+++ b/applications/plugins/gpioreader2/application.fam
@@ -1,6 +1,6 @@
App(
appid="GPIO_Reader_A",
- name="GPIO Reader (Aurelilc)",
+ name="[GPIO] Reader (Aurelilc)",
apptype=FlipperAppType.EXTERNAL,
entry_point="GPIO_reader_app",
requires=["gui"],
diff --git a/applications/plugins/music_beeper/music_beeper.c b/applications/plugins/music_beeper/music_beeper.c
index edebbc597..f743e3c98 100644
--- a/applications/plugins/music_beeper/music_beeper.c
+++ b/applications/plugins/music_beeper/music_beeper.c
@@ -312,7 +312,7 @@ int32_t music_beeper_app(void* p) {
DialogsFileBrowserOptions browser_options;
dialog_file_browser_set_basic_options(
&browser_options, MUSIC_BEEPER_APP_EXTENSION, &I_music_10px);
- browser_options.hide_ext = false;
+ browser_options.base_path = MUSIC_BEEPER_APP_PATH_FOLDER;
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options);
diff --git a/applications/plugins/namechanger/icons/DolphinNice_96x59.png b/applications/plugins/namechanger/icons/DolphinNice_96x59.png
new file mode 100644
index 000000000..a299d3630
Binary files /dev/null and b/applications/plugins/namechanger/icons/DolphinNice_96x59.png differ
diff --git a/applications/plugins/namechanger/icons/MarioBlock.png b/applications/plugins/namechanger/icons/MarioBlock.png
new file mode 100644
index 000000000..86f159966
Binary files /dev/null and b/applications/plugins/namechanger/icons/MarioBlock.png differ
diff --git a/applications/plugins/pocsag_pager/images/Scanning_123x52.png b/applications/plugins/pocsag_pager/images/Scanning_123x52.png
index ec785948d..a48c5330e 100644
Binary files a/applications/plugins/pocsag_pager/images/Scanning_123x52.png and b/applications/plugins/pocsag_pager/images/Scanning_123x52.png differ
diff --git a/applications/plugins/pocsag_pager/images/Scanning_123x52_sfw.png b/applications/plugins/pocsag_pager/images/Scanning_123x52_sfw.png
new file mode 100644
index 000000000..ec785948d
Binary files /dev/null and b/applications/plugins/pocsag_pager/images/Scanning_123x52_sfw.png differ
diff --git a/applications/plugins/pocsag_pager/images/WarningDolphin_45x42.png b/applications/plugins/pocsag_pager/images/WarningDolphin_45x42.png
index d766ffbb4..db225de36 100644
Binary files a/applications/plugins/pocsag_pager/images/WarningDolphin_45x42.png and b/applications/plugins/pocsag_pager/images/WarningDolphin_45x42.png differ
diff --git a/applications/plugins/pocsag_pager/images/WarningDolphin_45x42_sfw.png b/applications/plugins/pocsag_pager/images/WarningDolphin_45x42_sfw.png
new file mode 100644
index 000000000..d766ffbb4
Binary files /dev/null and b/applications/plugins/pocsag_pager/images/WarningDolphin_45x42_sfw.png differ
diff --git a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c
index 972c8dafb..760fcd0fc 100644
--- a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c
+++ b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c
@@ -7,6 +7,8 @@
#include
#include
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
+
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 112
#define MENU_ITEMS 4u
@@ -179,6 +181,9 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
FuriString* str_buff;
str_buff = furi_string_alloc();
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
+
PCSGReceiverMenuItem* item_menu;
for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) {
@@ -204,7 +209,12 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
canvas_set_color(canvas, ColorBlack);
if(model->history_item == 0) {
- canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
+ if (settings->sfw_mode) {
+ canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw);
+ }
+ else {
+ canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
+ }
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Scanning...");
canvas_draw_line(canvas, 46, 51, 125, 51);
@@ -226,7 +236,12 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8);
canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8);
canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8);
- canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
+ if (settings->sfw_mode) {
+ canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42_sfw);
+ }
+ else {
+ canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
+ }
canvas_draw_dot(canvas, 17, 61);
break;
case PCSGReceiverBarShowUnlock:
@@ -239,6 +254,7 @@ void pcsg_view_receiver_draw(Canvas* canvas, PCSGReceiverModel* model) {
canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str));
break;
}
+ free(settings);
}
static void pcsg_view_receiver_timer_callback(void* context) {
diff --git a/applications/plugins/pong/application.fam b/applications/plugins/pong/application.fam
new file mode 100644
index 000000000..95484b6e7
--- /dev/null
+++ b/applications/plugins/pong/application.fam
@@ -0,0 +1,13 @@
+App(
+ appid="flipper_pong",
+ name="Pong",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="flipper_pong_app",
+ cdefines=["APP_FLIPPER_PONG"],
+ requires=[
+ "gui",
+ ],
+ stack_size=1 * 1024,
+ fap_icon="pong.png",
+ fap_category="Games",
+)
diff --git a/applications/plugins/pong/flipper_pong.c b/applications/plugins/pong/flipper_pong.c
new file mode 100644
index 000000000..2af3e6df4
--- /dev/null
+++ b/applications/plugins/pong/flipper_pong.c
@@ -0,0 +1,287 @@
+// CC0 1.0 Universal (CC0 1.0)
+// Public Domain Dedication
+// https://github.com/nmrr
+
+#include
+#include
+#include
+#include
+#include
+
+#define SCREEN_SIZE_X 128
+#define SCREEN_SIZE_Y 64
+#define FPS 20
+
+#define PAD_SIZE_X 3
+#define PAD_SIZE_Y 8
+#define PLAYER1_PAD_SPEED 2
+#define PLAYER2_PAD_SPEED 2
+#define BALL_SIZE 4
+
+typedef enum {
+ EventTypeInput,
+ ClockEventTypeTick,
+} EventType;
+
+typedef struct {
+ EventType type;
+ InputEvent input;
+} EventApp;
+
+typedef struct Players
+{
+ uint8_t player1_X,player1_Y,player2_X,player2_Y;
+ uint16_t player1_score,player2_score;
+ uint8_t ball_X,ball_Y,ball_X_speed,ball_Y_speed,ball_X_direction,ball_Y_direction;
+} Players;
+
+static void draw_callback(Canvas* canvas, void* ctx)
+{
+ UNUSED(ctx);
+ Players* playersMutex = (Players*)acquire_mutex_block((ValueMutex*)ctx);
+
+ 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_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);
+ canvas_draw_str_aligned(canvas, SCREEN_SIZE_X/2+15, SCREEN_SIZE_Y/2+2, AlignCenter, AlignTop, buffer);
+
+ release_mutex((ValueMutex*)ctx, playersMutex);
+}
+
+static void input_callback(InputEvent* input_event, void* ctx)
+{
+ furi_assert(ctx);
+ FuriMessageQueue* event_queue = ctx;
+ EventApp event = {.type = EventTypeInput, .input = *input_event};
+ furi_message_queue_put(event_queue, &event, FuriWaitForever);
+}
+
+static void clock_tick(void* ctx) {
+ furi_assert(ctx);
+ FuriMessageQueue* queue = ctx;
+ EventApp event = {.type = ClockEventTypeTick};
+ furi_message_queue_put(queue, &event, 0);
+}
+
+bool insidePad(uint8_t x, uint8_t y, uint8_t playerX, uint8_t playerY)
+{
+ if (x >= playerX && x <= playerX+PAD_SIZE_X && y >= playerY && y <= playerY+PAD_SIZE_Y) return true;
+ return false;
+}
+
+uint8_t changeSpeed()
+{
+ uint8_t randomuint8[1];
+ while(1)
+ {
+ furi_hal_random_fill_buf(randomuint8,1);
+ randomuint8[0] &= 0b00000011;
+ if (randomuint8[0] >= 1) break;
+ }
+ return randomuint8[0];
+}
+
+uint8_t changeDirection()
+{
+ uint8_t randomuint8[1];
+ furi_hal_random_fill_buf(randomuint8,1);
+ randomuint8[0] &= 0b1;
+ return randomuint8[0];
+}
+
+int32_t flipper_pong_app()
+{
+ EventApp event;
+ FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp));
+
+ Players players;
+ players.player1_X = SCREEN_SIZE_X-PAD_SIZE_X-1;
+ players.player1_Y = SCREEN_SIZE_Y/2 - PAD_SIZE_Y/2;
+ players.player1_score = 0;
+
+ players.player2_X = 1;
+ players.player2_Y = SCREEN_SIZE_Y/2 - PAD_SIZE_Y/2;
+ players.player2_score = 0;
+
+ players.ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2;
+ players.ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2;
+ players.ball_X_speed = 1;
+ players.ball_Y_speed = 1;
+ players.ball_X_direction = changeDirection();
+ players.ball_Y_direction = changeDirection();
+
+ ValueMutex state_mutex;
+ init_mutex(&state_mutex, &players, sizeof(Players));
+
+ ViewPort* view_port = view_port_alloc();
+ view_port_draw_callback_set(view_port, draw_callback, &state_mutex);
+ view_port_input_callback_set(view_port, input_callback, event_queue);
+
+ Gui* gui = furi_record_open(RECORD_GUI);
+ gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+ FuriTimer* timer = furi_timer_alloc(clock_tick, FuriTimerTypePeriodic, event_queue);
+ furi_timer_start(timer, 1000/FPS);
+
+ while(1)
+ {
+ FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever);
+ Players* playersMutex = (Players*)acquire_mutex_block(&state_mutex);
+
+ if (event_status == FuriStatusOk)
+ {
+ if(event.type == EventTypeInput)
+ {
+ if(event.input.key == InputKeyBack)
+ {
+ release_mutex(&state_mutex, playersMutex);
+ break;
+ }
+ else if(event.input.key == InputKeyUp)
+ {
+ if (playersMutex->player1_Y >= 1+PLAYER1_PAD_SPEED) playersMutex->player1_Y -= PLAYER1_PAD_SPEED;
+ else playersMutex->player1_Y = 1;
+ }
+ else if(event.input.key == InputKeyDown)
+ {
+ if (playersMutex->player1_Y <= SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER1_PAD_SPEED -1) playersMutex->player1_Y += PLAYER1_PAD_SPEED;
+ else playersMutex->player1_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1;
+ }
+ }
+ else if (event.type == ClockEventTypeTick)
+ {
+
+ if (playersMutex->ball_X + BALL_SIZE/2 <= SCREEN_SIZE_X*0.35 && playersMutex->ball_X_direction == 0)
+ {
+ if (playersMutex->ball_Y + BALL_SIZE/2 < playersMutex->player2_Y + PAD_SIZE_Y/2)
+ {
+ if (playersMutex->player2_Y >= 1+PLAYER2_PAD_SPEED) playersMutex->player2_Y -= PLAYER2_PAD_SPEED;
+ else playersMutex->player2_Y= 1;
+ }
+ else if (playersMutex->ball_Y + BALL_SIZE/2 > playersMutex->player2_Y + PAD_SIZE_Y/2)
+ {
+ if (playersMutex->player2_Y <= SCREEN_SIZE_Y - PAD_SIZE_Y - PLAYER2_PAD_SPEED -1) playersMutex->player2_Y += PLAYER2_PAD_SPEED;
+ else playersMutex->player2_Y = SCREEN_SIZE_Y - PAD_SIZE_Y - 1;
+ }
+ }
+
+ uint8_t ball_corner_X[4] = {playersMutex->ball_X, playersMutex->ball_X + BALL_SIZE, playersMutex->ball_X + BALL_SIZE, playersMutex->ball_X};
+ uint8_t ball_corner_Y[4] = {playersMutex->ball_Y, playersMutex->ball_Y, playersMutex->ball_Y + BALL_SIZE, playersMutex->ball_Y + BALL_SIZE};
+ bool insidePlayer1 = false, insidePlayer2 = false;
+
+ for (int i=0;i<4;i++)
+ {
+ if (insidePad(ball_corner_X[i], ball_corner_Y[i], playersMutex->player1_X, playersMutex->player1_Y) == true)
+ {
+ insidePlayer1 = true;
+ break;
+ }
+
+ if (insidePad(ball_corner_X[i], ball_corner_Y[i], playersMutex->player2_X, playersMutex->player2_Y) == true)
+ {
+ insidePlayer2 = true;
+ break;
+ }
+ }
+
+ if (insidePlayer1 == true)
+ {
+ playersMutex->ball_X_direction = 0;
+ playersMutex->ball_X -= playersMutex->ball_X_speed;
+ playersMutex->ball_X_speed = changeSpeed();
+ playersMutex->ball_Y_speed = changeSpeed();
+ }
+ else if (insidePlayer2 == true)
+ {
+ playersMutex->ball_X_direction = 1;
+ playersMutex->ball_X += playersMutex->ball_X_speed;
+ playersMutex->ball_X_speed = changeSpeed();
+ playersMutex->ball_Y_speed = changeSpeed();
+ }
+ else
+ {
+ if (playersMutex->ball_X_direction == 1)
+ {
+
+ if (playersMutex->ball_X <= SCREEN_SIZE_X - BALL_SIZE - 1 - playersMutex->ball_X_speed)
+ {
+ playersMutex->ball_X += playersMutex->ball_X_speed;
+ }
+ else
+ {
+ playersMutex->ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2;
+ playersMutex->ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2;
+ playersMutex->ball_X_speed = 1;
+ playersMutex->ball_Y_speed = 1;
+ playersMutex->ball_X_direction = 0;
+ playersMutex->player2_score++;
+ }
+ }
+ else
+ {
+ if (playersMutex->ball_X >= 1 + playersMutex->ball_X_speed)
+ {
+ playersMutex->ball_X -= playersMutex->ball_X_speed;
+ }
+ else
+ {
+ playersMutex->ball_X = SCREEN_SIZE_X/2 - BALL_SIZE/2;
+ playersMutex->ball_Y = SCREEN_SIZE_Y/2 - BALL_SIZE/2;
+ playersMutex->ball_X_speed = 1;
+ playersMutex->ball_Y_speed = 1;
+ playersMutex->ball_X_direction = 1;
+ playersMutex->player1_score++;
+ }
+ }
+ }
+
+ if (playersMutex->ball_Y_direction == 1)
+ {
+ if (playersMutex->ball_Y <= SCREEN_SIZE_Y - BALL_SIZE - 1 - playersMutex->ball_Y_speed)
+ {
+ playersMutex->ball_Y += playersMutex->ball_Y_speed;
+ }
+ else
+ {
+ playersMutex->ball_Y = SCREEN_SIZE_Y - BALL_SIZE - 1;
+ playersMutex->ball_X_speed = changeSpeed();
+ playersMutex->ball_Y_speed = changeSpeed();
+ playersMutex->ball_Y_direction = 0;
+ }
+ }
+ else
+ {
+ if (playersMutex->ball_Y >= 1 + playersMutex->ball_Y_speed)
+ {
+ playersMutex->ball_Y -= playersMutex->ball_Y_speed;
+ }
+ else
+ {
+ playersMutex->ball_Y = 1;
+ playersMutex->ball_X_speed = changeSpeed();
+ playersMutex->ball_Y_speed = changeSpeed();
+ playersMutex->ball_Y_direction = 1;
+ }
+ }
+ }
+ }
+
+ release_mutex(&state_mutex, playersMutex);
+ view_port_update(view_port);
+ }
+
+ furi_message_queue_free(event_queue);
+ delete_mutex(&state_mutex);
+ gui_remove_view_port(gui, view_port);
+ view_port_free(view_port);
+ furi_timer_free(timer);
+ furi_record_close(RECORD_GUI);
+
+ return 0;
+}
diff --git a/applications/plugins/pong/pong.png b/applications/plugins/pong/pong.png
new file mode 100644
index 000000000..507ce711c
Binary files /dev/null and b/applications/plugins/pong/pong.png differ
diff --git a/applications/plugins/protoview/README.md b/applications/plugins/protoview/README.md
index e7209d7d6..4b8a3c3a0 100644
--- a/applications/plugins/protoview/README.md
+++ b/applications/plugins/protoview/README.md
@@ -78,7 +78,7 @@ cd ~/flipperZero/official/
git clone --recursive https://github.com/flipperdevices/flipperzero-firmware.git ./
./fbt
```
-* Copy this application folder in `official/application_user`.
+* Copy this application folder in `official/applications_user`.
* Connect your Flipper via USB.
* Build and install with: `./fbt launch_app APPSRC=protoview`.
diff --git a/applications/plugins/protoview/TODO b/applications/plugins/protoview/TODO
index bc66ee75a..0003ccd38 100644
--- a/applications/plugins/protoview/TODO
+++ b/applications/plugins/protoview/TODO
@@ -3,9 +3,13 @@ Core improvements
- Detection of non Manchester and non RZ encoded signals. Not sure if there are any signals that are not self clocked widely used in RF. Note that the current approach already detects encodings using short high + long low and long high + short low to encode 0 and 1. In addition to the current classifier, it is possible to add one that checks for a sequence of pulses that are all multiples of some base length. This should detect, for instance, even NRZ encodings where 1 and 0 are just clocked as they are.
+- Views on-enter on-exit.
+
Features
========
+- Help screen (with press ok for next page).
+- Detect the line code used and try to decode the message as hex dump.
- Pressing right/left you browse different modes:
* Current best signal pulse classes.
* Raw square wave display. Central button freezes and resumes (toggle). When frozen we display "paused" (inverted) on the low part of the screen.
diff --git a/applications/plugins/protoview/app.c b/applications/plugins/protoview/app.c
index 10c3fe599..4e6b2ff3e 100644
--- a/applications/plugins/protoview/app.c
+++ b/applications/plugins/protoview/app.c
@@ -1,257 +1,42 @@
/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
* See the LICENSE file for information about the license. */
-#include
-#include
-#include
-#include
-#include
-#include
#include "app.h"
-#include "app_buffer.h"
+
+/* If this define is enabled, ProtoView is going to mess with the
+ * otherwise opaque SubGhzWorker structure in order to disable
+ * its filter for samples shorter than a given amount (30us at the
+ * time I'm writing this comment).
+ *
+ * This structure must be taken in sync with the one of the firmware. */
+#define PROTOVIEW_DISABLE_SUBGHZ_FILTER 0
+
+#ifdef PROTOVIEW_DISABLE_SUBGHZ_FILTER
+struct SubGhzWorker {
+ FuriThread* thread;
+ FuriStreamBuffer* stream;
+
+ volatile bool running;
+ volatile bool overrun;
+
+ LevelDuration filter_level_duration;
+ bool filter_running;
+ uint16_t filter_duration;
+
+ SubGhzWorkerOverrunCallback overrun_callback;
+ SubGhzWorkerPairCallback pair_callback;
+ void* context;
+};
+#endif
RawSamplesBuffer *RawSamples, *DetectedSamples;
extern const SubGhzProtocolRegistry protoview_protocol_registry;
-/* Render the received signal.
- *
- * The screen of the flipper is 128 x 64. Even using 4 pixels per line
- * (where low level signal is one pixel high, high level is 4 pixels
- * high) and 4 pixels of spacing between the different lines, we can
- * plot comfortably 8 lines.
- *
- * The 'idx' argument is the first sample to render in the circular
- * buffer. */
-void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) {
- canvas_set_color(canvas, ColorBlack);
-
- int rows = 8;
- uint32_t time_per_pixel = app->us_scale;
- bool level = 0;
- uint32_t dur = 0, sample_num = 0;
- for (int row = 0; row < rows ; row++) {
- for (int x = 0; x < 128; x++) {
- int y = 3 + row*8;
- if (dur < time_per_pixel/2) {
- /* Get more data. */
- raw_samples_get(buf, idx++, &level, &dur);
- sample_num++;
- }
-
- canvas_draw_line(canvas, x,y,x,y-(level*3));
-
- /* Write a small triangle under the last sample detected. */
- if (app->signal_bestlen != 0 &&
- sample_num == app->signal_bestlen+1)
- {
- canvas_draw_dot(canvas,x,y+2);
- canvas_draw_dot(canvas,x-1,y+3);
- canvas_draw_dot(canvas,x,y+3);
- canvas_draw_dot(canvas,x+1,y+3);
- sample_num++; /* Make sure we don't mark the next, too. */
- }
-
- /* Remove from the current level duration the time we
- * just plot. */
- if (dur > time_per_pixel)
- dur -= time_per_pixel;
- else
- dur = 0;
- }
- }
-}
-
-/* Return the time difference between a and b, always >= 0 since
- * the absolute value is returned. */
-uint32_t duration_delta(uint32_t a, uint32_t b) {
- return a > b ? a - b : b - a;
-}
-
-/* This function starts scanning samples at offset idx looking for the
- * longest run of pulses, either high or low, that are among 10%
- * of each other, for a maximum of three classes. The classes are
- * counted separtely for high and low signals (RF on / off) because
- * many devices tend to have different pulse lenghts depending on
- * the level of the pulse.
- *
- * For instance Oregon2 sensors, in the case of protocol 2.1 will send
- * pulses of ~400us (RF on) VS ~580us (RF off). */
-#define SEARCH_CLASSES 3
-uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
- struct {
- uint32_t dur[2]; /* dur[0] = low, dur[1] = high */
- uint32_t count[2]; /* Associated observed frequency. */
- } classes[SEARCH_CLASSES];
-
- memset(classes,0,sizeof(classes));
- uint32_t minlen = 40, maxlen = 4000; /* Depends on data rate, here we
- allow for high and low. */
- uint32_t len = 0; /* Observed len of coherent samples. */
- s->short_pulse_dur = 0;
- for (uint32_t j = idx; j < idx+500; j++) {
- bool level;
- uint32_t dur;
- raw_samples_get(s, j, &level, &dur);
- if (dur < minlen || dur > maxlen) break; /* return. */
-
- /* Let's see if it matches a class we already have or if we
- * can populate a new (yet empty) class. */
- uint32_t k;
- for (k = 0; k < SEARCH_CLASSES; k++) {
- if (classes[k].count[level] == 0) {
- classes[k].dur[level] = dur;
- classes[k].count[level] = 1;
- break; /* Sample accepted. */
- } else {
- uint32_t classavg = classes[k].dur[level];
- uint32_t count = classes[k].count[level];
- uint32_t delta = duration_delta(dur,classavg);
- if (delta < classavg/10) {
- /* It is useful to compute the average of the class
- * we are observing. We know how many samples we got so
- * far, so we can recompute the average easily.
- * By always having a better estimate of the pulse len
- * we can avoid missing next samples in case the first
- * observed samples are too off. */
- classavg = ((classavg * count) + dur) / (count+1);
- classes[k].dur[level] = classavg;
- classes[k].count[level]++;
- break; /* Sample accepted. */
- }
- }
- }
-
- if (k == SEARCH_CLASSES) break; /* No match, return. */
-
- /* If we are here, we accepted this sample. Try with the next
- * one. */
- len++;
- }
-
- /* Update the buffer setting the shortest pulse we found
- * among the three classes. This will be used when scaling
- * for visualization. */
- for (int j = 0; j < SEARCH_CLASSES; j++) {
- for (int level = 0; level < 2; level++) {
- if (classes[j].dur[level] == 0) continue;
- if (classes[j].count[level] < 3) continue;
- if (s->short_pulse_dur == 0 ||
- s->short_pulse_dur > classes[j].dur[level])
- {
- s->short_pulse_dur = classes[j].dur[level];
- }
- }
- }
- return len;
-}
-
-/* Search the buffer with the stored signal (last N samples received)
- * in order to find a coherent signal. If a signal that does not appear to
- * be just noise is found, it is set in DetectedSamples global signal
- * buffer, that is what is rendered on the screen. */
-void scan_for_signal(ProtoViewApp *app) {
- /* We need to work on a copy: the RawSamples buffer is populated
- * by the background thread receiving data. */
- RawSamplesBuffer *copy = raw_samples_alloc();
- raw_samples_copy(copy,RawSamples);
-
- /* Try to seek on data that looks to have a regular high low high low
- * pattern. */
- uint32_t minlen = 13; /* Min run of coherent samples. Up to
- 12 samples it's very easy to mistake
- noise for signal. */
-
- uint32_t i = 0;
- while (i < copy->total-1) {
- uint32_t thislen = search_coherent_signal(copy,i);
- if (thislen > minlen && thislen > app->signal_bestlen) {
- app->signal_bestlen = thislen;
- raw_samples_copy(DetectedSamples,copy);
- DetectedSamples->idx = (DetectedSamples->idx+i)%
- DetectedSamples->total;
- FURI_LOG_E(TAG, "Displayed sample updated (%d samples)",
- (int)thislen);
- }
- i += thislen ? thislen : 1;
- }
- raw_samples_free(copy);
-}
-
/* Draw some text with a border. If the outside color is black and the inside
* color is white, it just writes the border of the text, but the function can
* also be used to write a bold variation of the font setting both the
* colors to black, or alternatively to write a black text with a white
* border so that it is visible if there are black stuff on the background. */
-void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color)
-{
- struct {
- uint8_t x; uint8_t y;
- } dir[8] = {
- {-1,-1},
- {0,-1},
- {1,-1},
- {1,0},
- {1,1},
- {0,1},
- {-1,1},
- {-1,0}
- };
-
- /* Rotate in all the directions writing the same string to create a
- * border, then write the actual string in the other color in the
- * middle. */
- canvas_set_color(canvas, border_color);
- for (int j = 0; j < 8; j++)
- canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str);
- canvas_set_color(canvas, text_color);
- canvas_draw_str(canvas,x,y,str);
- canvas_set_color(canvas, ColorBlack);
-}
-
-/* Raw pulses rendering. This is our default view. */
-void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) {
- /* Show signal. */
- render_signal(app, canvas, DetectedSamples, 0);
-
- /* Show signal information. */
- char buf[64];
- snprintf(buf,sizeof(buf),"%luus",
- (unsigned long)DetectedSamples->short_pulse_dur);
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack);
-}
-
-/* Renders a single view with frequency and modulation setting. However
- * this are logically two different views, and only one of the settings
- * will be highlighted. */
-void render_view_settings(Canvas *const canvas, ProtoViewApp *app) {
- UNUSED(app);
- canvas_set_font(canvas, FontPrimary);
- if (app->current_view == ViewFrequencySettings)
- canvas_draw_str_with_border(canvas,1,10,"Frequency",ColorWhite,ColorBlack);
- else
- canvas_draw_str(canvas,1,10,"Frequency");
-
- if (app->current_view == ViewModulationSettings)
- canvas_draw_str_with_border(canvas,70,10,"Modulation",ColorWhite,ColorBlack);
- else
- canvas_draw_str(canvas,70,10,"Modulation");
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str(canvas,10,61,"Use up and down to modify");
-
- /* Show frequency. We can use big numbers font since it's just a number. */
- if (app->current_view == ViewFrequencySettings) {
- char buf[16];
- snprintf(buf,sizeof(buf),"%.2f",(double)app->frequency/1000000);
- canvas_set_font(canvas, FontBigNumbers);
- canvas_draw_str(canvas, 30, 40, buf);
- } else if (app->current_view == ViewModulationSettings) {
- int current = app->modulation;
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name);
- }
-}
-
/* The callback actually just passes the control to the actual active
* view callback, after setting up basic stuff like cleaning the screen
* and setting color to black. */
@@ -267,9 +52,11 @@ static void render_callback(Canvas *const canvas, void *ctx) {
/* Call who is in charge right now. */
switch(app->current_view) {
case ViewRawPulses: render_view_raw_pulses(canvas,app); break;
+ case ViewInfo: render_view_info(canvas,app); break;
case ViewFrequencySettings:
case ViewModulationSettings:
render_view_settings(canvas,app); break;
+ case ViewDirectSampling: render_view_direct_sampling(canvas,app); break;
case ViewLast: furi_crash(TAG " ViewLast selected"); break;
}
}
@@ -279,11 +66,29 @@ static void render_callback(Canvas *const canvas, void *ctx) {
static void input_callback(InputEvent* input_event, void* ctx)
{
ProtoViewApp *app = ctx;
+ furi_message_queue_put(app->event_queue,input_event,FuriWaitForever);
+}
- if (input_event->type == InputTypePress) {
- furi_message_queue_put(app->event_queue,input_event,FuriWaitForever);
- FURI_LOG_E(TAG, "INPUT CALLBACK %d", (int)input_event->key);
+
+/* Called to switch view (when left/right is pressed). Handles
+ * changing the current view ID and calling the enter/exit view
+ * callbacks if needed. */
+static void app_switch_view(ProtoViewApp *app, SwitchViewDirection dir) {
+ ProtoViewCurrentView old = app->current_view;
+ if (dir == AppNextView) {
+ app->current_view++;
+ if (app->current_view == ViewLast) app->current_view = 0;
+ } else if (dir == AppPrevView) {
+ if (app->current_view == 0)
+ app->current_view = ViewLast-1;
+ else
+ app->current_view--;
}
+ ProtoViewCurrentView new = app->current_view;
+
+ /* Call the enter/exit view callbacks if needed. */
+ if (old == ViewDirectSampling) view_exit_direct_sampling(app);
+ if (new == ViewDirectSampling) view_enter_direct_sampling(app);
}
/* Allocate the application state and initialize a number of stuff.
@@ -297,7 +102,7 @@ ProtoViewApp* protoview_app_alloc() {
//init setting
app->setting = subghz_setting_alloc();
- subghz_setting_load(app->setting, EXT_PATH("protoview/settings.txt"));
+ subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"));
// GUI
app->gui = furi_record_open(RECORD_GUI);
@@ -310,13 +115,20 @@ ProtoViewApp* protoview_app_alloc() {
// Signal found and visualization defaults
app->signal_bestlen = 0;
- app->us_scale = 100;
+ app->signal_decoded = false;
+ app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE;
+ app->signal_offset = 0;
//init Worker & Protocol
app->txrx = malloc(sizeof(ProtoViewTxRx));
/* Setup rx worker and environment. */
app->txrx->worker = subghz_worker_alloc();
+
+#ifdef PROTOVIEW_DISABLE_SUBGHZ_FILTER
+ app->txrx->worker->filter_running = 0;
+#endif
+
app->txrx->environment = subghz_environment_alloc();
subghz_environment_set_protocol_registry(
app->txrx->environment, (void*)&protoview_protocol_registry);
@@ -380,70 +192,6 @@ static void timer_callback(void *ctx) {
scan_for_signal(app);
}
-/* Handle input for the raw pulses view. */
-void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) {
- if (input.key == InputKeyOk) {
- /* Reset the current sample to capture the next. */
- app->signal_bestlen = 0;
- raw_samples_reset(DetectedSamples);
- raw_samples_reset(RawSamples);
- } else if (input.key == InputKeyDown) {
- /* Rescaling. The set becomes finer under 50us per pixel. */
- uint32_t scale_step = app->us_scale >= 50 ? 50 : 10;
- if (app->us_scale < 500) app->us_scale += scale_step;
- } else if (input.key == InputKeyUp) {
- uint32_t scale_step = app->us_scale > 50 ? 50 : 10;
- if (app->us_scale > 10) app->us_scale -= scale_step;
- }
-}
-
-/* Handle input for the settings view. */
-void process_input_settings(ProtoViewApp *app, InputEvent input) {
- /* Here we handle only up and down. Avoid any work if the user
- * pressed something else. */
- if (input.key != InputKeyDown && input.key != InputKeyUp) return;
-
- if (app->current_view == ViewFrequencySettings) {
- size_t curidx = 0, i;
- size_t count = subghz_setting_get_frequency_count(app->setting);
-
- /* Scan the list of frequencies to check for the index of the
- * currently set frequency. */
- for(i = 0; i < count; i++) {
- uint32_t freq = subghz_setting_get_frequency(app->setting,i);
- if (freq == app->frequency) {
- curidx = i;
- break;
- }
- }
- if (i == count) return; /* Should never happen. */
-
- if (input.key == InputKeyUp) {
- curidx = (curidx+1) % count;
- } else if (input.key == InputKeyDown) {
- curidx = curidx == 0 ? count-1 : curidx-1;
- }
- app->frequency = subghz_setting_get_frequency(app->setting,curidx);
- } else if (app->current_view == ViewModulationSettings) {
- uint32_t count = 0;
- uint32_t modid = app->modulation;
-
- while(ProtoViewModulations[count].name != NULL) count++;
- if (input.key == InputKeyUp) {
- modid = (modid+1) % count;
- } else if (input.key == InputKeyDown) {
- modid = modid == 0 ? count-1 : modid-1;
- }
- app->modulation = modid;
- }
-
- /* Apply changes. */
- FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name);
- radio_rx_end(app);
- radio_begin(app);
- radio_rx(app);
-}
-
int32_t protoview_app_entry(void* p) {
UNUSED(p);
ProtoViewApp *app = protoview_app_alloc();
@@ -465,39 +213,53 @@ int32_t protoview_app_entry(void* p) {
while(app->running) {
FuriStatus qstat = furi_message_queue_get(app->event_queue, &input, 100);
if (qstat == FuriStatusOk) {
- FURI_LOG_E(TAG, "Main Loop - Input: %u", input.key);
+ if (DEBUG_MSG) FURI_LOG_E(TAG, "Main Loop - Input: type %d key %u",
+ input.type, input.key);
/* Handle navigation here. Then handle view-specific inputs
* in the view specific handling function. */
- if (input.key == InputKeyBack) {
+ if (input.type == InputTypeShort &&
+ input.key == InputKeyBack)
+ {
/* Exit the app. */
app->running = 0;
- } else if (input.key == InputKeyRight) {
+ } else if (input.type == InputTypeShort &&
+ input.key == InputKeyRight)
+ {
/* Go to the next view. */
- app->current_view++;
- if (app->current_view == ViewLast) app->current_view = 0;
- } else if (input.key == InputKeyLeft) {
+ app_switch_view(app,AppNextView);
+ } else if (input.type == InputTypeShort &&
+ input.key == InputKeyLeft)
+ {
/* Go to the previous view. */
- if (app->current_view == 0)
- app->current_view = ViewLast-1;
- else
- app->current_view--;
+ app_switch_view(app,AppPrevView);
} else {
+ /* This is where we pass the control to the currently
+ * active view input processing. */
switch(app->current_view) {
case ViewRawPulses:
process_input_raw_pulses(app,input);
break;
+ case ViewInfo:
+ process_input_info(app,input);
+ break;
case ViewFrequencySettings:
case ViewModulationSettings:
process_input_settings(app,input);
break;
+ case ViewDirectSampling:
+ process_input_direct_sampling(app,input);
+ break;
case ViewLast: furi_crash(TAG " ViewLast selected"); break;
}
}
} else {
- static int c = 0;
- c++;
- if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout");
+ /* Useful to understand if the app is still alive when it
+ * does not respond because of bugs. */
+ if (DEBUG_MSG) {
+ static int c = 0; c++;
+ if (!(c % 20)) FURI_LOG_E(TAG, "Loop timeout");
+ }
}
view_port_update(app->view_port);
}
@@ -513,3 +275,4 @@ int32_t protoview_app_entry(void* p) {
protoview_app_free(app);
return 0;
}
+
diff --git a/applications/plugins/protoview/app.h b/applications/plugins/protoview/app.h
index 18852a14a..4ad0a9196 100644
--- a/applications/plugins/protoview/app.h
+++ b/applications/plugins/protoview/app.h
@@ -3,6 +3,11 @@
#pragma once
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -15,8 +20,13 @@
#include
#include
#include
+#include "app_buffer.h"
#define TAG "ProtoView"
+#define PROTOVIEW_RAW_VIEW_DEFAULT_SCALE 100
+#define BITMAP_SEEK_NOT_FOUND UINT32_MAX
+
+#define DEBUG_MSG 1
typedef struct ProtoViewApp ProtoViewApp;
@@ -30,14 +40,23 @@ typedef enum {
/* Currently active view. */
typedef enum {
ViewRawPulses,
+ ViewInfo,
ViewFrequencySettings,
ViewModulationSettings,
+ ViewDirectSampling,
ViewLast, /* Just a sentinel to wrap around. */
} ProtoViewCurrentView;
+/* Used by app_switch_view() */
+typedef enum {
+ AppNextView,
+ AppPrevView
+} SwitchViewDirection;
+
typedef struct {
const char *name;
FuriHalSubGhzPreset preset;
+ uint8_t *custom;
} ProtoViewModulation;
extern ProtoViewModulation ProtoViewModulations[]; /* In app_subghz.c */
@@ -54,6 +73,21 @@ struct ProtoViewTxRx {
typedef struct ProtoViewTxRx ProtoViewTxRx;
+/* This stucture is filled by the decoder for specific protocols with the
+ * informations about the message. ProtoView will display such information
+ * in the message info view. */
+#define PROTOVIEW_MSG_STR_LEN 32
+typedef struct ProtoViewMsgInfo {
+ char name[PROTOVIEW_MSG_STR_LEN]; /* Protocol name and version. */
+ char raw[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific raw representation.*/
+ /* The following is what the decoder wants to show to user. Each decoder
+ * can use the number of fileds it needs. */
+ char info1[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 1. */
+ char info2[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 2. */
+ char info3[PROTOVIEW_MSG_STR_LEN]; /* Protocol specific info line 3. */
+ uint64_t len; /* Bits consumed from the stream. */
+} ProtoViewMsgInfo;
+
struct ProtoViewApp {
/* GUI */
Gui *gui;
@@ -66,17 +100,66 @@ struct ProtoViewApp {
ProtoViewTxRx *txrx; /* Radio state. */
SubGhzSetting *setting; /* A list of valid frequencies. */
- /* Application state and config. */
+ /* Generic app state. */
int running; /* Once false exists the app. */
uint32_t signal_bestlen; /* Longest coherent signal observed so far. */
+ bool signal_decoded; /* Was the current signal decoded? */
+ ProtoViewMsgInfo signal_info; /* Decoded message, if signal_decoded true. */
+
+ /* Raw view apps state. */
uint32_t us_scale; /* microseconds per pixel. */
+ uint32_t signal_offset; /* Long press left/right panning in raw view. */
+
+ /* Configuration view app state. */
uint32_t frequency; /* Current frequency. */
uint8_t modulation; /* Current modulation ID, array index in the
ProtoViewModulations table. */
};
+typedef struct ProtoViewDecoder {
+ const char *name; /* Protocol name. */
+ /* The decode function takes a buffer that is actually a bitmap, with
+ * high and low levels represented as 0 and 1. The number of high/low
+ * pulses represented by the bitmap is passed as the 'numbits' argument,
+ * while 'numbytes' represents the total size of the bitmap pointed by
+ * 'bits'. So 'numbytes' is mainly useful to pass as argument to other
+ * functions that perform bit extraction with bound checking, such as
+ * bitmap_get() and so forth. */
+ bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info);
+} ProtoViewDecoder;
+
+extern RawSamplesBuffer *RawSamples, *DetectedSamples;
+
+/* app_radio.c */
void radio_begin(ProtoViewApp* app);
uint32_t radio_rx(ProtoViewApp* app);
void radio_idle(ProtoViewApp* app);
void radio_rx_end(ProtoViewApp* app);
void radio_sleep(ProtoViewApp* app);
+
+/* signal.c */
+uint32_t duration_delta(uint32_t a, uint32_t b);
+void reset_current_signal(ProtoViewApp *app);
+void scan_for_signal(ProtoViewApp *app);
+bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos);
+void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val);
+void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat);
+void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len);
+bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits);
+uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, uint32_t maxbits, const char *bits);
+uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t offset, const char *zero_pattern, const char *one_pattern);
+
+/* view_*.c */
+void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app);
+void process_input_raw_pulses(ProtoViewApp *app, InputEvent input);
+void render_view_settings(Canvas *const canvas, ProtoViewApp *app);
+void process_input_settings(ProtoViewApp *app, InputEvent input);
+void render_view_info(Canvas *const canvas, ProtoViewApp *app);
+void process_input_info(ProtoViewApp *app, InputEvent input);
+void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app);
+void process_input_direct_sampling(ProtoViewApp *app, InputEvent input);
+void view_enter_direct_sampling(ProtoViewApp *app);
+void view_exit_direct_sampling(ProtoViewApp *app);
+
+/* ui.c */
+void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color);
diff --git a/applications/plugins/protoview/app_buffer.c b/applications/plugins/protoview/app_buffer.c
index 0061a4142..df2e7074e 100644
--- a/applications/plugins/protoview/app_buffer.c
+++ b/applications/plugins/protoview/app_buffer.c
@@ -34,6 +34,12 @@ void raw_samples_reset(RawSamplesBuffer *s) {
furi_mutex_release(s->mutex);
}
+/* Set the raw sample internal index so that what is currently at
+ * offset 'offset', will appear to be at 0 index. */
+void raw_samples_center(RawSamplesBuffer *s, uint32_t offset) {
+ s->idx = (s->idx+offset) % RAW_SAMPLES_NUM;
+}
+
/* Add the specified sample in the circular buffer. */
void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur) {
furi_mutex_acquire(s->mutex,FuriWaitForever);
diff --git a/applications/plugins/protoview/app_buffer.h b/applications/plugins/protoview/app_buffer.h
index 90d186f89..5d997d02e 100644
--- a/applications/plugins/protoview/app_buffer.h
+++ b/applications/plugins/protoview/app_buffer.h
@@ -23,6 +23,7 @@ typedef struct RawSamplesBuffer {
RawSamplesBuffer *raw_samples_alloc(void);
void raw_samples_reset(RawSamplesBuffer *s);
+void raw_samples_center(RawSamplesBuffer *s, uint32_t offset);
void raw_samples_add(RawSamplesBuffer *s, bool level, uint32_t dur);
void raw_samples_get(RawSamplesBuffer *s, uint32_t idx, bool *level, uint32_t *dur);
void raw_samples_copy(RawSamplesBuffer *dst, RawSamplesBuffer *src);
diff --git a/applications/plugins/protoview/app_subghz.c b/applications/plugins/protoview/app_subghz.c
index e89cab214..2bb87af7a 100644
--- a/applications/plugins/protoview/app_subghz.c
+++ b/applications/plugins/protoview/app_subghz.c
@@ -2,17 +2,20 @@
* See the LICENSE file for information about the license. */
#include "app.h"
+#include "custom_presets.h"
#include
ProtoViewModulation ProtoViewModulations[] = {
- {"OOK 650Khz", FuriHalSubGhzPresetOok650Async},
- {"OOK 270Khz", FuriHalSubGhzPresetOok270Async},
- {"2FSK 2.38Khz", FuriHalSubGhzPreset2FSKDev238Async},
- {"2FSK 47.6Khz", FuriHalSubGhzPreset2FSKDev476Async},
- {"MSK", FuriHalSubGhzPresetMSK99_97KbAsync},
- {"GFSK", FuriHalSubGhzPresetGFSK9_99KbAsync},
- {NULL, 0} /* End of list sentinel. */
+ {"OOK 650Khz", FuriHalSubGhzPresetOok650Async, NULL},
+ {"OOK 270Khz", FuriHalSubGhzPresetOok270Async, NULL},
+ {"2FSK 2.38Khz", FuriHalSubGhzPreset2FSKDev238Async, NULL},
+ {"2FSK 47.6Khz", FuriHalSubGhzPreset2FSKDev476Async, NULL},
+ {"MSK", FuriHalSubGhzPresetMSK99_97KbAsync, NULL},
+ {"GFSK", FuriHalSubGhzPresetGFSK9_99KbAsync, NULL},
+ {"TPMS 1 (FSK)", 0, (uint8_t*)protoview_subghz_tpms1_async_regs},
+ {"TPMS 2 (FSK)", 0, (uint8_t*)protoview_subghz_tpms2_async_regs},
+ {NULL, 0, NULL} /* End of list sentinel. */
};
/* Called after the application initialization in order to setup the
@@ -23,7 +26,14 @@ void radio_begin(ProtoViewApp* app) {
furi_assert(app);
furi_hal_subghz_reset();
furi_hal_subghz_idle();
- furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset);
+
+ /* The CC1101 preset can be either one of the standard presets, if
+ * the modulation "custom" field is NULL, or a custom preset we
+ * defined in custom_presets.h. */
+ if (ProtoViewModulations[app->modulation].custom == NULL)
+ furi_hal_subghz_load_preset(ProtoViewModulations[app->modulation].preset);
+ else
+ furi_hal_subghz_load_custom_preset(ProtoViewModulations[app->modulation].custom);
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
app->txrx->txrx_state = TxRxStateIDLE;
}
diff --git a/applications/plugins/protoview/application.fam b/applications/plugins/protoview/application.fam
index 5b3589ce7..df2a77261 100644
--- a/applications/plugins/protoview/application.fam
+++ b/applications/plugins/protoview/application.fam
@@ -5,7 +5,7 @@ App(
entry_point="protoview_app_entry",
cdefines=["APP_PROTOVIEW"],
requires=["gui"],
- stack_size=8 * 1024,
+ stack_size=8*1024,
order=50,
fap_icon="appicon.png",
fap_category="Tools",
diff --git a/applications/plugins/protoview/binaries/protoview.fap b/applications/plugins/protoview/binaries/protoview.fap
index 9e1f9c7ec..f5a03056e 100644
Binary files a/applications/plugins/protoview/binaries/protoview.fap and b/applications/plugins/protoview/binaries/protoview.fap differ
diff --git a/applications/plugins/protoview/custom_presets.h b/applications/plugins/protoview/custom_presets.h
new file mode 100644
index 000000000..d34446f48
--- /dev/null
+++ b/applications/plugins/protoview/custom_presets.h
@@ -0,0 +1,132 @@
+#include
+
+/* This is how to configure registers MDMCFG3 and MDMCFG4.
+ *
+ * Data rate kBaud setting:
+ *
+ * MDMCFG3 is the data rate mantissa, the exponent is in MDMCFG4,
+ * last 4 bits of the register.
+ *
+ * The rate (assuming 26Mhz crystal) is calculated as follows:
+ *
+ * ((256+MDMCFG3)*(2^MDMCFG4:0..3bits)) / 2^28 * 26000000.
+ *
+ * For instance for the default values of MDMCFG3 (34) and MDMCFG4 (12):
+ *
+ * ((256+34)*(2^12))/(2^28)*26000000 = 115051.2688000000, that is 115KBaud
+ *
+ * Bandwidth filter setting:
+ *
+ * BW filter as just 16 possibilities depending on how the first nibble
+ * (first 4 bits) of the MDMCFG4 bits are set. Instead of providing the
+ * formula, it is simpler to show all the values of the nibble and the
+ * corresponding bandwidth filter.
+ *
+ * 0 812khz
+ * 1 650khz
+ * 2 541khz
+ * 3 464khz
+ * 4 406khz
+ * 5 325khz
+ * 6 270khz
+ * 7 232khz
+ * 8 203khz
+ * 9 162khz
+ * a 135khz
+ * b 116khz
+ * c 102khz
+ * d 82 khz
+ * e 68 khz
+ * f 58 khz
+ */
+
+/* 20 KBaud, 2FSK, 28.56 kHz deviation, 325 Khz bandwidth filter. */
+static uint8_t protoview_subghz_tpms1_async_regs[][2] = {
+ /* GPIO GD0 */
+ {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+ /* Frequency Synthesizer Control */
+ {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+ /* Packet engine */
+ {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+ {CC1101_PKTCTRL1, 0x04},
+
+ // // Modem Configuration
+ {CC1101_MDMCFG0, 0x00},
+ {CC1101_MDMCFG1, 0x02},
+ {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode.
+ {CC1101_MDMCFG3, 0x93}, // Data rate is 20kBaud
+ {CC1101_MDMCFG4, 0x59}, // Rx bandwidth filter is 325 kHz
+ {CC1101_DEVIATN, 0x41}, // Deviation 28.56 kHz
+
+ /* Main Radio Control State Machine */
+ {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+ /* Frequency Offset Compensation Configuration */
+ {CC1101_FOCCFG,
+ 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
+
+ /* Automatic Gain Control */
+ {CC1101_AGCCTRL0,
+ 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
+ {CC1101_AGCCTRL1,
+ 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
+ {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
+
+ /* Wake on radio and timeouts control */
+ {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+ /* Frontend configuration */
+ {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
+ {CC1101_FREND1, 0x56},
+
+ /* End */
+ {0, 0},
+};
+
+/* 40 KBaud, 2FSK, 19 kHz deviation, 102 Khz bandwidth filter. */
+static uint8_t protoview_subghz_tpms2_async_regs[][2] = {
+ /* GPIO GD0 */
+ {CC1101_IOCFG0, 0x0D}, // GD0 as async serial data output/input
+
+ /* Frequency Synthesizer Control */
+ {CC1101_FSCTRL1, 0x06}, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz
+
+ /* Packet engine */
+ {CC1101_PKTCTRL0, 0x32}, // Async, continious, no whitening
+ {CC1101_PKTCTRL1, 0x04},
+
+ // // Modem Configuration
+ {CC1101_MDMCFG0, 0x00},
+ {CC1101_MDMCFG1, 0x02},
+ {CC1101_MDMCFG2, 0x04}, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized). Other code reading TPMS uses GFSK, but should be the same when in RX mode.
+ {CC1101_MDMCFG3, 0x93}, // Data rate is 40kBaud
+ {CC1101_MDMCFG4, 0x6A}, // 6 = BW filter 270kHz, A = Data rate exp
+ {CC1101_DEVIATN, 0x41}, // Deviation 19.042 kHz
+
+ /* Main Radio Control State Machine */
+ {CC1101_MCSM0, 0x18}, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us)
+
+ /* Frequency Offset Compensation Configuration */
+ {CC1101_FOCCFG,
+ 0x16}, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
+
+ /* Automatic Gain Control */
+ {CC1101_AGCCTRL0,
+ 0x91}, //10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
+ {CC1101_AGCCTRL1,
+ 0x00}, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
+ {CC1101_AGCCTRL2, 0x07}, // 00 - DVGA all; 000 - MAX LNA+LNA2; 111 - MAIN_TARGET 42 dB
+
+ /* Wake on radio and timeouts control */
+ {CC1101_WORCTRL, 0xFB}, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours
+
+ /* Frontend configuration */
+ {CC1101_FREND0, 0x10}, // Adjusts current TX LO buffer
+ {CC1101_FREND1, 0x56},
+
+ /* End */
+ {0, 0},
+};
+
diff --git a/applications/plugins/protoview/protocols/b4b1.c b/applications/plugins/protoview/protocols/b4b1.c
new file mode 100644
index 000000000..6977c0eb3
--- /dev/null
+++ b/applications/plugins/protoview/protocols/b4b1.c
@@ -0,0 +1,44 @@
+/* PT/SC remotes. Usually 443.92 Mhz OOK.
+ *
+ * This line code is used in many remotes such as Princeton chips
+ * named PT, Silian Microelectronics SC5262 and others.
+ * Basically every 4 pulsee represent a bit, where 1000 means 0, and
+ * 1110 means 1. Usually we can read 24 bits of data.
+ * In this specific implementation we check for a prelude that is
+ * 1 bit high, 31 bits low, but the check is relaxed. */
+
+#include "../app.h"
+
+static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) {
+ if (numbits < 30) return false;
+ const char *sync_patterns[3] = {
+ "10000000000000000000000000000001", /* 30 zero bits. */
+ "100000000000000000000000000000001", /* 31 zero bits. */
+ "1000000000000000000000000000000001", /* 32 zero bits. */
+ };
+
+ uint32_t off;
+ int j;
+ for (j = 0; j < 3; j++) {
+ off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_patterns[j]);
+ if (off != BITMAP_SEEK_NOT_FOUND) break;
+ }
+ if (off == BITMAP_SEEK_NOT_FOUND) return false;
+ if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 preamble at: %lu",off);
+ off += strlen(sync_patterns[j])-1;
+
+ uint8_t d[3]; /* 24 bits of data. */
+ uint32_t decoded =
+ convert_from_line_code(d,sizeof(d),bits,numbytes,off,"1000","1110");
+
+ if (DEBUG_MSG) FURI_LOG_E(TAG, "B4B1 decoded: %lu",decoded);
+ if (decoded != 24) return false;
+ snprintf(info->name,PROTOVIEW_MSG_STR_LEN,"PT/SC remote");
+ snprintf(info->raw,PROTOVIEW_MSG_STR_LEN,"%02X%02X%02X",d[0],d[1],d[2]);
+ info->len = off+(4*24);
+ return true;
+}
+
+ProtoViewDecoder B4B1Decoder = {
+ "B4B1", decode
+};
diff --git a/applications/plugins/protoview/protocols/oregon2.c b/applications/plugins/protoview/protocols/oregon2.c
new file mode 100644
index 000000000..3aa57c72d
--- /dev/null
+++ b/applications/plugins/protoview/protocols/oregon2.c
@@ -0,0 +1,65 @@
+/* Oregon remote termometers. Usually 443.92 Mhz OOK.
+ *
+ * The protocol is described here:
+ * https://wmrx00.sourceforge.net/Arduino/OregonScientific-RF-Protocols.pdf
+ * This implementation is not very complete. */
+
+#include "../app.h"
+
+static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) {
+ if (numbits < 32) return false;
+ const char *sync_pattern = "01100110" "01100110" "10010110" "10010110";
+ uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern);
+ if (off == BITMAP_SEEK_NOT_FOUND) return false;
+ FURI_LOG_E(TAG, "Oregon2 preamble+sync found");
+
+ off += 32; /* Skip preamble. */
+
+ uint8_t buffer[8], raw[8] = {0};
+ uint32_t decoded =
+ convert_from_line_code(buffer,sizeof(buffer),bits,numbytes,off,"1001","0110");
+ FURI_LOG_E(TAG, "Oregon2 decoded bits: %lu", decoded);
+
+ if (decoded < 11*4) return false; /* Minimum len to extract some data. */
+
+ char temp[3] = {0}, deviceid[2] = {0}, hum[2] = {0};
+ for (int j = 0; j < 64; j += 4) {
+ uint8_t nib[1];
+ nib[0] = (bitmap_get(buffer,8,j+0) |
+ bitmap_get(buffer,8,j+1) << 1 |
+ bitmap_get(buffer,8,j+2) << 2 |
+ bitmap_get(buffer,8,j+3) << 3);
+ if (DEBUG_MSG) FURI_LOG_E(TAG, "Not inverted nibble[%d]: %x", j/4, (unsigned int)nib[0]);
+ raw[j/8] |= nib[0] << (4-(j%4));
+ switch(j/4) {
+ case 1: deviceid[0] |= nib[0]; break;
+ case 0: deviceid[0] |= nib[0] << 4; break;
+ case 3: deviceid[1] |= nib[0]; break;
+ case 2: deviceid[1] |= nib[0] << 4; break;
+ case 10: temp[0] = nib[0]; break;
+ /* Fixme: take the temperature sign from nibble 11. */
+ case 9: temp[1] = nib[0]; break;
+ case 8: temp[2] = nib[0]; break;
+ case 13: hum[0] = nib[0]; break;
+ case 12: hum[1] = nib[0]; break;
+ }
+ }
+
+ snprintf(info->name,sizeof(info->name),"%s","Oregon v2.1");
+ /* The following line crashes the Flipper because of broken
+ * snprintf() implementation. */
+ snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X",
+ raw[0],raw[1],raw[2],raw[3],raw[4],raw[5],
+ raw[6],raw[7]);
+ snprintf(info->info1,sizeof(info->info1),"Sensor ID %02X%02X",
+ deviceid[0], deviceid[1]);
+ snprintf(info->info2,sizeof(info->info2),"Temperature %d%d.%d",
+ temp[0],temp[1],temp[2]);
+ snprintf(info->info3,sizeof(info->info3),"Humidity %d%d",
+ hum[0],hum[1]);
+ return true;
+}
+
+ProtoViewDecoder Oregon2Decoder = {
+ "Oregon2", decode
+};
diff --git a/applications/plugins/protoview/protocols/oregon2.txt b/applications/plugins/protoview/protocols/oregon2.txt
new file mode 100644
index 000000000..362631431
--- /dev/null
+++ b/applications/plugins/protoview/protocols/oregon2.txt
@@ -0,0 +1,6 @@
+11001100110011001100110011001100110011001100110011001100110 (Preamble)
+10 01 01 10 10 01 01 10 (Sync)
+01 10 10 01 10 01 10 01 01 10 10 01 01 10 01 10 10 01 01 10 10 01 10 01 10 01 10 01 10 01 10 01 01 10 10 01 10 01 10 01 01 10 01 10 01 10 01 10 01 10 01 10 10 01 01 10 01 10 10 01 10 01 10 01 10 01 10 01 01 10 10 01 10 01 01 10 01 10 10 01 01 10 10 01 10 01 10 01 10 01 10 01 10 01 11 0
+
+We need to seek the following bytes: 01100110 01100110 10010110 10010110
+ 0x66 0x66 96 96
diff --git a/applications/plugins/protoview/protocols/renault_tpms.c b/applications/plugins/protoview/protocols/renault_tpms.c
new file mode 100644
index 000000000..3022a5d4e
--- /dev/null
+++ b/applications/plugins/protoview/protocols/renault_tpms.c
@@ -0,0 +1,63 @@
+/* Renault tires TPMS. Usually 443.92 Mhz FSK.
+ *
+ * Preamble + marshal-encoded bits. 9 Bytes in total if we don't
+ * count the preamble. */
+
+#include "../app.h"
+
+#define USE_TEST_VECTOR 0
+static const char *test_vector =
+ "10101010" "10101010" "10101010" "10101001" // Preamble + sync.
+
+ /* The following is marshal encoded, so each two characters are
+ * actaully one bit. 01 = 1, 10 = 0. */
+ "010110010110" // Flags.
+ "10011001101010011001" // Pressure, multiply by 0.75 to obtain kpa.
+ // 244 kpa here.
+ "1010010110011010" // Temperature, subtract 30 to obtain celsius. 22C here.
+ "1001010101101001"
+ "0101100110010101"
+ "1001010101100110" // Tire ID. 0x7AD779 here.
+ "0101010101010101"
+ "0101010101010101" // Two FF bytes (usually). Unknown.
+ "0110010101010101"; // CRC8 with (poly 7, initialization 0).
+
+static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info) {
+
+ if (USE_TEST_VECTOR) { /* Test vector to check that decoding works. */
+ bitmap_set_pattern(bits,numbytes,test_vector);
+ numbits = strlen(test_vector);
+ }
+
+ if (numbits < 13*8) return false;
+
+ const char *sync_pattern = "10101010" "10101010" "10101010" "10101001";
+ uint64_t off = bitmap_seek_bits(bits,numbytes,0,numbits,sync_pattern);
+ if (off == BITMAP_SEEK_NOT_FOUND) return false;
+ FURI_LOG_E(TAG, "Renault TPMS preamble+sync found");
+
+ off += 32; /* Skip preamble. */
+
+ uint8_t raw[9];
+ uint32_t decoded =
+ convert_from_line_code(raw,sizeof(raw),bits,numbytes,off,
+ "10","01"); /* Manchester. */
+ FURI_LOG_E(TAG, "Renault TPMS decoded bits: %lu", decoded);
+
+ if (decoded < 8*9) return false; /* Require the full 9 bytes. */
+
+ float kpa = 0.75 *((uint32_t)((raw[0]&3)<<8) | raw[1]);
+ int temp = raw[2]-30;
+
+ snprintf(info->name,sizeof(info->name),"%s","Renault TPMS");
+ snprintf(info->raw,sizeof(info->raw),"%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ raw[0],raw[1],raw[2],raw[3],raw[4],raw[5],
+ raw[6],raw[7],raw[8]);
+ snprintf(info->info1,sizeof(info->info1),"Pressure %.2f kpa", (double)kpa);
+ snprintf(info->info2,sizeof(info->info2),"Temperature %d C", temp);
+ return true;
+}
+
+ProtoViewDecoder RenaultTPMSDecoder = {
+ "Renault TPMS", decode
+};
diff --git a/applications/plugins/protoview/signal.c b/applications/plugins/protoview/signal.c
new file mode 100644
index 000000000..2ff632811
--- /dev/null
+++ b/applications/plugins/protoview/signal.c
@@ -0,0 +1,420 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info);
+void initialize_msg_info(ProtoViewMsgInfo *i);
+
+/* =============================================================================
+ * Raw signal detection
+ * ===========================================================================*/
+
+/* Return the time difference between a and b, always >= 0 since
+ * the absolute value is returned. */
+uint32_t duration_delta(uint32_t a, uint32_t b) {
+ return a > b ? a - b : b - a;
+}
+
+/* Reset the current signal, so that a new one can be detected. */
+void reset_current_signal(ProtoViewApp *app) {
+ app->signal_bestlen = 0;
+ app->signal_offset = 0;
+ app->signal_decoded = false;
+ raw_samples_reset(DetectedSamples);
+ raw_samples_reset(RawSamples);
+}
+
+/* This function starts scanning samples at offset idx looking for the
+ * longest run of pulses, either high or low, that are not much different
+ * from each other, for a maximum of three duration classes.
+ * So for instance 50 successive pulses that are roughly long 340us or 670us
+ * will be sensed as a coherent signal (example: 312, 361, 700, 334, 667, ...)
+ *
+ * The classes are counted separtely for high and low signals (RF on / off)
+ * because many devices tend to have different pulse lenghts depending on
+ * the level of the pulse.
+ *
+ * For instance Oregon2 sensors, in the case of protocol 2.1 will send
+ * pulses of ~400us (RF on) VS ~580us (RF off). */
+#define SEARCH_CLASSES 3
+uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
+ struct {
+ uint32_t dur[2]; /* dur[0] = low, dur[1] = high */
+ uint32_t count[2]; /* Associated observed frequency. */
+ } classes[SEARCH_CLASSES];
+
+ memset(classes,0,sizeof(classes));
+ uint32_t minlen = 30, maxlen = 4000; /* Depends on data rate, here we
+ allow for high and low. */
+ uint32_t len = 0; /* Observed len of coherent samples. */
+ s->short_pulse_dur = 0;
+ for (uint32_t j = idx; j < idx+500; j++) {
+ bool level;
+ uint32_t dur;
+ raw_samples_get(s, j, &level, &dur);
+ if (dur < minlen || dur > maxlen) break; /* return. */
+
+ /* Let's see if it matches a class we already have or if we
+ * can populate a new (yet empty) class. */
+ uint32_t k;
+ for (k = 0; k < SEARCH_CLASSES; k++) {
+ if (classes[k].count[level] == 0) {
+ classes[k].dur[level] = dur;
+ classes[k].count[level] = 1;
+ break; /* Sample accepted. */
+ } else {
+ uint32_t classavg = classes[k].dur[level];
+ uint32_t count = classes[k].count[level];
+ uint32_t delta = duration_delta(dur,classavg);
+ /* Is the difference in duration between this signal and
+ * the class we are inspecting less than a given percentage?
+ * If so, accept this signal. */
+ if (delta < classavg/8) { /* 100%/8 = 12%. */
+ /* It is useful to compute the average of the class
+ * we are observing. We know how many samples we got so
+ * far, so we can recompute the average easily.
+ * By always having a better estimate of the pulse len
+ * we can avoid missing next samples in case the first
+ * observed samples are too off. */
+ classavg = ((classavg * count) + dur) / (count+1);
+ classes[k].dur[level] = classavg;
+ classes[k].count[level]++;
+ break; /* Sample accepted. */
+ }
+ }
+ }
+
+ if (k == SEARCH_CLASSES) break; /* No match, return. */
+
+ /* If we are here, we accepted this sample. Try with the next
+ * one. */
+ len++;
+ }
+
+ /* Update the buffer setting the shortest pulse we found
+ * among the three classes. This will be used when scaling
+ * for visualization. */
+ uint32_t short_dur[2] = {0,0};
+ for (int j = 0; j < SEARCH_CLASSES; j++) {
+ for (int level = 0; level < 2; level++) {
+ if (classes[j].dur[level] == 0) continue;
+ if (classes[j].count[level] < 3) continue;
+ if (short_dur[level] == 0 ||
+ short_dur[level] > classes[j].dur[level])
+ {
+ short_dur[level] = classes[j].dur[level];
+ }
+ }
+ }
+
+ /* Use the average between high and low short pulses duration.
+ * Often they are a bit different, and using the average is more robust
+ * when we do decoding sampling at short_pulse_dur intervals. */
+ if (short_dur[0] == 0) short_dur[0] = short_dur[1];
+ if (short_dur[1] == 0) short_dur[1] = short_dur[0];
+ s->short_pulse_dur = (short_dur[0]+short_dur[1])/2;
+
+ return len;
+}
+
+/* Search the buffer with the stored signal (last N samples received)
+ * in order to find a coherent signal. If a signal that does not appear to
+ * be just noise is found, it is set in DetectedSamples global signal
+ * buffer, that is what is rendered on the screen. */
+void scan_for_signal(ProtoViewApp *app) {
+ /* We need to work on a copy: the RawSamples buffer is populated
+ * by the background thread receiving data. */
+ RawSamplesBuffer *copy = raw_samples_alloc();
+ raw_samples_copy(copy,RawSamples);
+
+ /* Try to seek on data that looks to have a regular high low high low
+ * pattern. */
+ uint32_t minlen = 13; /* Min run of coherent samples. Up to
+ 12 samples it's very easy to mistake
+ noise for signal. */
+
+ ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo));
+ uint32_t i = 0;
+
+ while (i < copy->total-1) {
+ uint32_t thislen = search_coherent_signal(copy,i);
+
+ /* For messages that are long enough, attempt decoding. */
+ if (thislen > minlen) {
+ initialize_msg_info(info);
+ uint32_t saved_idx = copy->idx; /* Save index, see later. */
+ /* decode_signal() expects the detected signal to start
+ * from index .*/
+ raw_samples_center(copy,i);
+ bool decoded = decode_signal(copy,thislen,info);
+ copy->idx = saved_idx; /* Restore the index as we are scanning
+ the signal in the loop. */
+
+ /* Accept this signal as the new signal if either it's longer
+ * than the previous one, or the previous one was unknown and
+ * this is decoded. */
+ if (thislen > app->signal_bestlen ||
+ (app->signal_decoded == false && decoded))
+ {
+ app->signal_info = *info;
+ app->signal_bestlen = thislen;
+ app->signal_decoded = decoded;
+ raw_samples_copy(DetectedSamples,copy);
+ raw_samples_center(DetectedSamples,i);
+ FURI_LOG_E(TAG, "Displayed sample updated (%d samples %lu us)",
+ (int)thislen, DetectedSamples->short_pulse_dur);
+ }
+ }
+ i += thislen ? thislen : 1;
+ }
+ raw_samples_free(copy);
+ free(info);
+}
+
+/* =============================================================================
+ * Decoding
+ *
+ * The following code will translates the raw singals as received by
+ * the CC1101 into logical signals: a bitmap of 0s and 1s sampled at
+ * the detected data clock interval.
+ *
+ * Then the converted signal is passed to the protocols decoders, that look
+ * for protocol-specific information. We stop at the first decoder that is
+ * able to decode the data, so protocols here should be registered in
+ * order of complexity and specificity, with the generic ones at the end.
+ * ===========================================================================*/
+
+/* Set the 'bitpos' bit to value 'val', in the specified bitmap
+ * 'b' of len 'blen'.
+ * Out of range bits will silently be discarded. */
+void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) {
+ uint32_t byte = bitpos/8;
+ uint32_t bit = 7-(bitpos&7);
+ if (byte >= blen) return;
+ if (val)
+ b[byte] |= 1<= blen) return 0;
+ return (b[byte] & (1< rate/2) numbits++; /* There is another one. */
+
+ /* Limit how much a single sample can spawn. There are likely no
+ * protocols doing such long pulses when the rate is low. */
+ if (numbits > 1024) numbits = 1024;
+
+ if (0) /* Super verbose, so not under the DEBUG_MSG define. */
+ FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits",
+ dur,numbits,(int)level);
+
+ /* If the signal is too short, let's claim it an interference
+ * and ignore it completely. */
+ if (numbits == 0) continue;
+
+ while(numbits--) bitmap_set(b,blen,bitpos++,level);
+ }
+ return bitpos;
+}
+
+/* This function converts the line code used to the final data representation.
+ * The representation is put inside 'buf', for up to 'buflen' bytes of total
+ * data. For instance in order to convert manchester I can use "10" and "01"
+ * as zero and one patterns. It is possible to use "?" inside patterns in
+ * order to skip certain bits. For instance certain devices encode data twice,
+ * with each bit encoded in manchester encoding and then in its reversed
+ * representation. In such a case I could use "10??" and "01??".
+ *
+ * The function returns the number of bits converted. It will stop as soon
+ * as it finds a pattern that does not match zero or one patterns, or when
+ * the end of the bitmap pointed by 'bits' is reached (the length is
+ * specified in bytes by the caller, via the 'len' parameters).
+ *
+ * The decoding starts at the specified offset (in bits) 'off'. */
+uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, const char *zero_pattern, const char *one_pattern)
+{
+ uint32_t decoded = 0; /* Number of bits extracted. */
+ len *= 8; /* Convert bytes to bits. */
+ while(off < len) {
+ bool bitval;
+ if (bitmap_match_bits(bits,len,off,zero_pattern)) {
+ bitval = false;
+ off += strlen(zero_pattern);
+ } else if (bitmap_match_bits(bits,len,off,one_pattern)) {
+ bitval = true;
+ off += strlen(one_pattern);
+ } else {
+ break;
+ }
+ bitmap_set(buf,buflen,decoded++,bitval);
+ if (decoded/8 == buflen) break; /* No space left on target buffer. */
+ }
+ return decoded;
+}
+
+/* Supported protocols go here, with the relevant implementation inside
+ * protocols/.c */
+
+extern ProtoViewDecoder Oregon2Decoder;
+extern ProtoViewDecoder B4B1Decoder;
+extern ProtoViewDecoder RenaultTPMSDecoder;
+
+ProtoViewDecoder *Decoders[] = {
+ &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */
+ &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */
+ &RenaultTPMSDecoder, /* Renault TPMS. */
+ NULL
+};
+
+/* Reset the message info structure before passing it to the decoding
+ * functions. */
+void initialize_msg_info(ProtoViewMsgInfo *i) {
+ memset(i,0,sizeof(ProtoViewMsgInfo));
+}
+
+/* This function is called when a new signal is detected. It converts it
+ * to a bitstream, and the calls the protocol specific functions for
+ * decoding. If the signal was decoded correctly by some protocol, true
+ * is returned. Otherwise false is returned. */
+bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
+ uint32_t bitmap_bits_size = 4096*8;
+ uint32_t bitmap_size = bitmap_bits_size/8;
+
+ /* We call the decoders with an offset a few bits before the actual
+ * signal detected and for a len of a few bits after its end. */
+ uint32_t before_after_bits = 2;
+
+ uint8_t *bitmap = malloc(bitmap_size);
+ uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_after_bits,len+before_after_bits*2,s->short_pulse_dur);
+
+ if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */
+ char *str = malloc(1024);
+ uint32_t j;
+ for (j = 0; j < bits && j < 1023; j++) {
+ str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0';
+ }
+ str[j] = 0;
+ FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str);
+ free(str);
+ }
+
+ /* Try all the decoders available. */
+ int j = 0;
+
+ bool decoded = false;
+ while(Decoders[j]) {
+ uint32_t start_time = furi_get_tick();
+ decoded = Decoders[j]->decode(bitmap,bitmap_size,bits,info);
+ uint32_t delta = furi_get_tick() - start_time;
+ FURI_LOG_E(TAG, "Decoder %s took %lu ms",
+ Decoders[j]->name, (unsigned long)delta);
+ if (decoded) break;
+ j++;
+ }
+
+ if (!decoded) {
+ FURI_LOG_E(TAG, "No decoding possible");
+ } else {
+ FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3);
+ }
+ free(bitmap);
+ return decoded;
+}
diff --git a/applications/plugins/protoview/ui.c b/applications/plugins/protoview/ui.c
new file mode 100644
index 000000000..e22e4d57e
--- /dev/null
+++ b/applications/plugins/protoview/ui.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+void canvas_draw_str_with_border(Canvas* canvas, uint8_t x, uint8_t y, const char* str, Color text_color, Color border_color)
+{
+ struct {
+ uint8_t x; uint8_t y;
+ } dir[8] = {
+ {-1,-1},
+ {0,-1},
+ {1,-1},
+ {1,0},
+ {1,1},
+ {0,1},
+ {-1,1},
+ {-1,0}
+ };
+
+ /* Rotate in all the directions writing the same string to create a
+ * border, then write the actual string in the other color in the
+ * middle. */
+ canvas_set_color(canvas, border_color);
+ for (int j = 0; j < 8; j++)
+ canvas_draw_str(canvas,x+dir[j].x,y+dir[j].y,str);
+ canvas_set_color(canvas, text_color);
+ canvas_draw_str(canvas,x,y,str);
+ canvas_set_color(canvas, ColorBlack);
+}
diff --git a/applications/plugins/protoview/view_direct_sampling.c b/applications/plugins/protoview/view_direct_sampling.c
new file mode 100644
index 000000000..a287dc14a
--- /dev/null
+++ b/applications/plugins/protoview/view_direct_sampling.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+#include
+
+/* Read directly from the G0 CC1101 pin, and draw a black or white
+ * dot depending on the level. */
+void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) {
+ UNUSED(app);
+ for (int y = 0; y < 64; y++) {
+ for (int x = 0; x < 128; x++) {
+ bool level = furi_hal_gpio_read(&gpio_cc1101_g0);
+ if (level) canvas_draw_dot(canvas,x,y);
+ /* Busy loop: this is a terrible approach as it blocks
+ * everything else, but for now it's the best we can do
+ * to obtain direct data with some spacing. */
+ uint32_t x = 500; while(x--);
+ }
+ }
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_with_border(canvas,40,60,"Direct sampling",
+ ColorWhite,ColorBlack);
+}
+
+/* Handle input */
+void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) {
+ UNUSED(app);
+ UNUSED(input);
+}
+
+/* Enter view. Stop the subghz thread to prevent access as we read
+ * the CC1101 data directly. */
+void view_enter_direct_sampling(ProtoViewApp *app) {
+ if (app->txrx->txrx_state == TxRxStateRx) {
+ subghz_worker_stop(app->txrx->worker);
+ }
+}
+
+/* Exit view. Restore the subghz thread. */
+void view_exit_direct_sampling(ProtoViewApp *app) {
+ if (app->txrx->txrx_state == TxRxStateRx) {
+ subghz_worker_start(app->txrx->worker);
+ }
+}
diff --git a/applications/plugins/protoview/view_info.c b/applications/plugins/protoview/view_info.c
new file mode 100644
index 000000000..fff9c836e
--- /dev/null
+++ b/applications/plugins/protoview/view_info.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+/* Renders the view with the detected message information. */
+void render_view_info(Canvas *const canvas, ProtoViewApp *app) {
+ if (app->signal_decoded == false) {
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas, 30,36,"No signal decoded");
+ return;
+ }
+
+ /* Protocol name as title. */
+ canvas_set_font(canvas, FontPrimary);
+ uint8_t y = 8, lineheight = 10;
+ canvas_draw_str(canvas, 0, y, app->signal_info.name);
+ y += lineheight;
+
+ /* Info fields. */
+ char buf[128];
+ canvas_set_font(canvas, FontSecondary);
+ if (app->signal_info.raw[0]) {
+ snprintf(buf,sizeof(buf),"Raw: %s", app->signal_info.raw);
+ canvas_draw_str(canvas, 0, y, buf);
+ y += lineheight;
+ }
+ canvas_draw_str(canvas, 0, y, app->signal_info.info1);
+ y += lineheight;
+ canvas_draw_str(canvas, 0, y, app->signal_info.info2);
+ y += lineheight;
+ canvas_draw_str(canvas, 0, y, app->signal_info.info3);
+ y += lineheight;
+}
+
+/* Handle input for the settings view. */
+void process_input_info(ProtoViewApp *app, InputEvent input) {
+ UNUSED(app);
+ UNUSED(input);
+ return;
+}
diff --git a/applications/plugins/protoview/view_raw_signal.c b/applications/plugins/protoview/view_raw_signal.c
new file mode 100644
index 000000000..58d23e8ee
--- /dev/null
+++ b/applications/plugins/protoview/view_raw_signal.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+/* Render the received signal.
+ *
+ * The screen of the flipper is 128 x 64. Even using 4 pixels per line
+ * (where low level signal is one pixel high, high level is 4 pixels
+ * high) and 4 pixels of spacing between the different lines, we can
+ * plot comfortably 8 lines.
+ *
+ * The 'idx' argument is the first sample to render in the circular
+ * buffer. */
+void render_signal(ProtoViewApp *app, Canvas *const canvas, RawSamplesBuffer *buf, uint32_t idx) {
+ canvas_set_color(canvas, ColorBlack);
+
+ int rows = 8;
+ uint32_t time_per_pixel = app->us_scale;
+ uint32_t start_idx = idx;
+ bool level = 0;
+ uint32_t dur = 0, sample_num = 0;
+ for (int row = 0; row < rows ; row++) {
+ for (int x = 0; x < 128; x++) {
+ int y = 3 + row*8;
+ if (dur < time_per_pixel/2) {
+ /* Get more data. */
+ raw_samples_get(buf, idx++, &level, &dur);
+ sample_num++;
+ }
+
+ canvas_draw_line(canvas, x,y,x,y-(level*3));
+
+ /* Write a small triangle under the last sample detected. */
+ if (app->signal_bestlen != 0 &&
+ sample_num+start_idx == app->signal_bestlen+1)
+ {
+ canvas_draw_dot(canvas,x,y+2);
+ canvas_draw_dot(canvas,x-1,y+3);
+ canvas_draw_dot(canvas,x,y+3);
+ canvas_draw_dot(canvas,x+1,y+3);
+ sample_num++; /* Make sure we don't mark the next, too. */
+ }
+
+ /* Remove from the current level duration the time we
+ * just plot. */
+ if (dur > time_per_pixel)
+ dur -= time_per_pixel;
+ else
+ dur = 0;
+ }
+ }
+}
+
+/* Raw pulses rendering. This is our default view. */
+void render_view_raw_pulses(Canvas *const canvas, ProtoViewApp *app) {
+ /* Show signal. */
+ render_signal(app, canvas, DetectedSamples, app->signal_offset);
+
+ /* Show signal information. */
+ char buf[64];
+ snprintf(buf,sizeof(buf),"%luus",
+ (unsigned long)DetectedSamples->short_pulse_dur);
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_with_border(canvas, 97, 63, buf, ColorWhite, ColorBlack);
+ if (app->signal_decoded) {
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str_with_border(canvas, 1, 61, app->signal_info.name, ColorWhite, ColorBlack);
+ }
+}
+
+/* Handle input for the raw pulses view. */
+void process_input_raw_pulses(ProtoViewApp *app, InputEvent input) {
+ if (input.type == InputTypeRepeat) {
+ /* Handle panning of the signal window. Long pressing
+ * right will show successive samples, long pressing left
+ * previous samples. */
+ if (input.key == InputKeyRight) app->signal_offset++;
+ else if (input.key == InputKeyLeft) app->signal_offset--;
+ else if (input.key == InputKeyOk) {
+ app->signal_offset = 0;
+ app->us_scale = PROTOVIEW_RAW_VIEW_DEFAULT_SCALE;
+ }
+ } else if (input.type == InputTypeShort) {
+ if (input.key == InputKeyOk) {
+ /* Reset the current sample to capture the next. */
+ reset_current_signal(app);
+ } else if (input.key == InputKeyDown) {
+ /* Rescaling. The set becomes finer under 50us per pixel. */
+ uint32_t scale_step = app->us_scale >= 50 ? 50 : 10;
+ if (app->us_scale < 500) app->us_scale += scale_step;
+ } else if (input.key == InputKeyUp) {
+ uint32_t scale_step = app->us_scale > 50 ? 50 : 10;
+ if (app->us_scale > 10) app->us_scale -= scale_step;
+ }
+ }
+}
diff --git a/applications/plugins/protoview/view_settings.c b/applications/plugins/protoview/view_settings.c
new file mode 100644
index 000000000..22ac5ef0f
--- /dev/null
+++ b/applications/plugins/protoview/view_settings.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+/* Renders a single view with frequency and modulation setting. However
+ * this are logically two different views, and only one of the settings
+ * will be highlighted. */
+void render_view_settings(Canvas *const canvas, ProtoViewApp *app) {
+ canvas_set_font(canvas, FontPrimary);
+ if (app->current_view == ViewFrequencySettings)
+ canvas_draw_str_with_border(canvas,1,10,"Frequency",ColorWhite,ColorBlack);
+ else
+ canvas_draw_str(canvas,1,10,"Frequency");
+
+ if (app->current_view == ViewModulationSettings)
+ canvas_draw_str_with_border(canvas,70,10,"Modulation",ColorWhite,ColorBlack);
+ else
+ canvas_draw_str(canvas,70,10,"Modulation");
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str(canvas,10,61,"Use up and down to modify");
+
+ /* Show frequency. We can use big numbers font since it's just a number. */
+ if (app->current_view == ViewFrequencySettings) {
+ char buf[16];
+ snprintf(buf,sizeof(buf),"%.2f",(double)app->frequency/1000000);
+ canvas_set_font(canvas, FontBigNumbers);
+ canvas_draw_str(canvas, 30, 40, buf);
+ } else if (app->current_view == ViewModulationSettings) {
+ int current = app->modulation;
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str(canvas, 33, 39, ProtoViewModulations[current].name);
+ }
+}
+
+/* Handle input for the settings view. */
+void process_input_settings(ProtoViewApp *app, InputEvent input) {
+ if (input.type == InputTypeLong && input.key == InputKeyOk) {
+ /* Long pressing to OK sets the default frequency and
+ * modulation. */
+ app->frequency = subghz_setting_get_default_frequency(app->setting);
+ app->modulation = 0;
+ } else if (input.type == InputTypePress &&
+ (input.key != InputKeyDown || input.key != InputKeyUp))
+ {
+ /* Handle up and down to change frequency or modulation. */
+ if (app->current_view == ViewFrequencySettings) {
+ size_t curidx = 0, i;
+ size_t count = subghz_setting_get_frequency_count(app->setting);
+
+ /* Scan the list of frequencies to check for the index of the
+ * currently set frequency. */
+ for(i = 0; i < count; i++) {
+ uint32_t freq = subghz_setting_get_frequency(app->setting,i);
+ if (freq == app->frequency) {
+ curidx = i;
+ break;
+ }
+ }
+ if (i == count) return; /* Should never happen. */
+
+ if (input.key == InputKeyUp) {
+ curidx = curidx == 0 ? count-1 : curidx-1;
+ } else if (input.key == InputKeyDown) {
+ curidx = (curidx+1) % count;
+ } else {
+ return;
+ }
+ app->frequency = subghz_setting_get_frequency(app->setting,curidx);
+ } else if (app->current_view == ViewModulationSettings) {
+ uint32_t count = 0;
+ uint32_t modid = app->modulation;
+
+ while(ProtoViewModulations[count].name != NULL) count++;
+ if (input.key == InputKeyUp) {
+ modid = modid == 0 ? count-1 : modid-1;
+ } else if (input.key == InputKeyDown) {
+ modid = (modid+1) % count;
+ } else {
+ return;
+ }
+ app->modulation = modid;
+ }
+ } else {
+ return;
+ }
+
+ /* Apply changes. */
+ FURI_LOG_E(TAG, "Setting view, setting frequency/modulation to %lu %s", app->frequency, ProtoViewModulations[app->modulation].name);
+ radio_rx_end(app);
+ radio_begin(app);
+ radio_rx(app);
+}
diff --git a/applications/plugins/rc2014_coleco/application.fam b/applications/plugins/rc2014_coleco/application.fam
index 2a3900e19..6856b716b 100644
--- a/applications/plugins/rc2014_coleco/application.fam
+++ b/applications/plugins/rc2014_coleco/application.fam
@@ -1,6 +1,6 @@
App(
appid="RC2014_Coleco",
- name="RC2014 ColecoVision",
+ name="[RC2014] ColecoVision",
apptype=FlipperAppType.EXTERNAL,
entry_point="coleco_app",
cdefines=["APP_COLECO"],
diff --git a/applications/plugins/signal_generator/application.fam b/applications/plugins/signal_generator/application.fam
index 7d9d181ec..133319cf4 100644
--- a/applications/plugins/signal_generator/application.fam
+++ b/applications/plugins/signal_generator/application.fam
@@ -1,6 +1,6 @@
App(
appid="Signal_Generator",
- name="Signal Generator",
+ name="[GPIO] Signal Generator",
apptype=FlipperAppType.EXTERNAL,
entry_point="signal_gen_app",
cdefines=["APP_SIGNAL_GEN"],
diff --git a/applications/plugins/usb_midi/.gitignore b/applications/plugins/text_viewer/.gitignore
similarity index 100%
rename from applications/plugins/usb_midi/.gitignore
rename to applications/plugins/text_viewer/.gitignore
diff --git a/applications/plugins/wii_ec_anal/LICENSE b/applications/plugins/text_viewer/LICENSE
similarity index 96%
rename from applications/plugins/wii_ec_anal/LICENSE
rename to applications/plugins/text_viewer/LICENSE
index 95e544a06..69004dc62 100644
--- a/applications/plugins/wii_ec_anal/LICENSE
+++ b/applications/plugins/text_viewer/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2022 BlueChip
+Copyright (c) 2022 Roman Shchekin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/applications/plugins/text_viewer/README.md b/applications/plugins/text_viewer/README.md
new file mode 100644
index 000000000..cc41931be
--- /dev/null
+++ b/applications/plugins/text_viewer/README.md
@@ -0,0 +1,9 @@
+# flipper-zero-text-viewer
+
+Text Viewer application for Flipper Zero!
+
+A fork with a few changes from [QTRoS' hex viewer](https://github.com/QtRoS/flipper-zero-hex-viewer) to just display text without any hex byte representation
+
+
+
+[Link to FAP](https://github.com/kyhwana/latest_flipper_zero_apps/raw/main/text_viewer.fap)
diff --git a/applications/plugins/text_viewer/application.fam b/applications/plugins/text_viewer/application.fam
new file mode 100644
index 000000000..4f5182edf
--- /dev/null
+++ b/applications/plugins/text_viewer/application.fam
@@ -0,0 +1,16 @@
+App(
+ appid="text_viewer",
+ name="Text Viewer",
+ apptype=FlipperAppType.EXTERNAL,
+ entry_point="hex_viewer_app",
+ cdefines=["APP_TEXT_VIEWER"],
+ requires=[
+ "gui",
+ "dialogs",
+ ],
+ stack_size=2 * 1024,
+ order=20,
+ fap_icon="icons/hex_10px.png",
+ fap_category="Misc",
+ fap_icon_assets="icons",
+)
diff --git a/applications/plugins/text_viewer/hex_viewer.c b/applications/plugins/text_viewer/hex_viewer.c
new file mode 100644
index 000000000..3830a6602
--- /dev/null
+++ b/applications/plugins/text_viewer/hex_viewer.c
@@ -0,0 +1,282 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define TAG "TextViewer"
+
+#define HEX_VIEWER_APP_PATH_FOLDER "/any"
+#define HEX_VIEWER_APP_EXTENSION "*"
+
+#define HEX_VIEWER_BYTES_PER_LINE 20u
+#define HEX_VIEWER_LINES_ON_SCREEN 5u
+#define HEX_VIEWER_BUF_SIZE (HEX_VIEWER_LINES_ON_SCREEN * HEX_VIEWER_BYTES_PER_LINE)
+
+typedef struct {
+ uint8_t file_bytes[HEX_VIEWER_LINES_ON_SCREEN][HEX_VIEWER_BYTES_PER_LINE];
+ uint32_t file_offset;
+ uint32_t file_read_bytes;
+ uint32_t file_size;
+ Stream* stream;
+ bool mode; // Print address or content
+} HexViewerModel;
+
+typedef struct {
+ HexViewerModel* model;
+ FuriMutex** mutex;
+
+ FuriMessageQueue* input_queue;
+
+ ViewPort* view_port;
+ Gui* gui;
+ Storage* storage;
+} HexViewer;
+
+static void render_callback(Canvas* canvas, void* ctx) {
+ HexViewer* hex_viewer = ctx;
+ furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+
+ canvas_clear(canvas);
+ canvas_set_color(canvas, ColorBlack);
+
+ //elements_button_left(canvas, hex_viewer->model->mode ? "Addr" : "Text");
+ hex_viewer->model->mode = 1; //text mode
+ //elements_button_right(canvas, "Info");
+
+ int ROW_HEIGHT = 12;
+ int TOP_OFFSET = 10;
+ int LEFT_OFFSET = 3;
+
+ uint32_t line_count = hex_viewer->model->file_size / HEX_VIEWER_BYTES_PER_LINE;
+ if(hex_viewer->model->file_size % HEX_VIEWER_BYTES_PER_LINE != 0) line_count += 1;
+ uint32_t first_line_on_screen = hex_viewer->model->file_offset / HEX_VIEWER_BYTES_PER_LINE;
+ if(line_count > HEX_VIEWER_LINES_ON_SCREEN) {
+ uint8_t width = canvas_width(canvas);
+ elements_scrollbar_pos(
+ canvas,
+ width,
+ 0,
+ ROW_HEIGHT * HEX_VIEWER_LINES_ON_SCREEN,
+ first_line_on_screen, // TODO
+ line_count - (HEX_VIEWER_LINES_ON_SCREEN - 1));
+ }
+
+ char temp_buf[32];
+ uint32_t row_iters = hex_viewer->model->file_read_bytes / HEX_VIEWER_BYTES_PER_LINE;
+ if(hex_viewer->model->file_read_bytes % HEX_VIEWER_BYTES_PER_LINE != 0) row_iters += 1;
+
+ for(uint32_t i = 0; i < row_iters; ++i) {
+ uint32_t bytes_left_per_row =
+ hex_viewer->model->file_read_bytes - i * HEX_VIEWER_BYTES_PER_LINE;
+ bytes_left_per_row = MIN(bytes_left_per_row, HEX_VIEWER_BYTES_PER_LINE);
+
+ if(hex_viewer->model->mode) {
+ memcpy(temp_buf, hex_viewer->model->file_bytes[i], bytes_left_per_row);
+ temp_buf[bytes_left_per_row] = '\0';
+ for(uint32_t j = 0; j < bytes_left_per_row; ++j)
+ if(!isprint((int)temp_buf[j])) temp_buf[j] = '.';
+
+ canvas_set_font(canvas, FontKeyboard);
+ canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
+ } else {
+ uint32_t addr = hex_viewer->model->file_offset + i * HEX_VIEWER_BYTES_PER_LINE;
+ snprintf(temp_buf, 32, "%04lX", addr);
+
+ canvas_set_font(canvas, FontKeyboard);
+ canvas_draw_str(canvas, LEFT_OFFSET, TOP_OFFSET + i * ROW_HEIGHT, temp_buf);
+ }
+ }
+
+ furi_mutex_release(hex_viewer->mutex);
+}
+
+static void input_callback(InputEvent* input_event, void* ctx) {
+ HexViewer* hex_viewer = ctx;
+ if(input_event->type == InputTypeShort || input_event->type == InputTypeRepeat) {
+ furi_message_queue_put(hex_viewer->input_queue, input_event, 0);
+ }
+}
+
+static HexViewer* hex_viewer_alloc() {
+ HexViewer* instance = malloc(sizeof(HexViewer));
+
+ instance->model = malloc(sizeof(HexViewerModel));
+ memset(instance->model, 0x0, sizeof(HexViewerModel));
+
+ instance->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+
+ instance->input_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+
+ instance->view_port = view_port_alloc();
+ view_port_draw_callback_set(instance->view_port, render_callback, instance);
+ view_port_input_callback_set(instance->view_port, input_callback, instance);
+
+ instance->gui = furi_record_open(RECORD_GUI);
+ gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen);
+
+ instance->storage = furi_record_open(RECORD_STORAGE);
+
+ return instance;
+}
+
+static void hex_viewer_free(HexViewer* instance) {
+ furi_record_close(RECORD_STORAGE);
+
+ gui_remove_view_port(instance->gui, instance->view_port);
+ furi_record_close(RECORD_GUI);
+ view_port_free(instance->view_port);
+
+ furi_message_queue_free(instance->input_queue);
+
+ furi_mutex_free(instance->mutex);
+
+ if(instance->model->stream) buffered_file_stream_close(instance->model->stream);
+
+ free(instance->model);
+ free(instance);
+}
+
+static bool hex_viewer_open_file(HexViewer* hex_viewer, const char* file_path) {
+ furi_assert(hex_viewer);
+ furi_assert(file_path);
+
+ hex_viewer->model->stream = buffered_file_stream_alloc(hex_viewer->storage);
+ bool isOk = true;
+
+ do {
+ if(!buffered_file_stream_open(
+ hex_viewer->model->stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) {
+ 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);
+
+ return isOk;
+}
+
+static bool hex_viewer_read_file(HexViewer* hex_viewer) {
+ furi_assert(hex_viewer);
+ furi_assert(hex_viewer->model->stream);
+ furi_assert(hex_viewer->model->file_offset % HEX_VIEWER_BYTES_PER_LINE == 0);
+
+ memset(hex_viewer->model->file_bytes, 0x0, HEX_VIEWER_BUF_SIZE);
+ bool isOk = true;
+
+ do {
+ uint32_t offset = hex_viewer->model->file_offset;
+ if(!stream_seek(hex_viewer->model->stream, offset, true)) {
+ FURI_LOG_E(TAG, "Unable to seek stream");
+ isOk = false;
+ break;
+ }
+
+ hex_viewer->model->file_read_bytes = stream_read(
+ hex_viewer->model->stream,
+ (uint8_t*)hex_viewer->model->file_bytes,
+ HEX_VIEWER_BUF_SIZE);
+ } while(false);
+
+ return isOk;
+}
+
+int32_t hex_viewer_app(void* p) {
+ HexViewer* hex_viewer = hex_viewer_alloc();
+
+ FuriString* file_path;
+ file_path = furi_string_alloc();
+
+ do {
+ if(p && strlen(p)) {
+ furi_string_set(file_path, (const char*)p);
+ } else {
+ furi_string_set(file_path, HEX_VIEWER_APP_PATH_FOLDER);
+
+ DialogsFileBrowserOptions browser_options;
+ dialog_file_browser_set_basic_options(
+ &browser_options, HEX_VIEWER_APP_EXTENSION, &I_hex_10px);
+ browser_options.hide_ext = false;
+
+ DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
+ bool res = dialog_file_browser_show(dialogs, file_path, file_path, &browser_options);
+
+ furi_record_close(RECORD_DIALOGS);
+ if(!res) {
+ FURI_LOG_I(TAG, "No file selected");
+ break;
+ }
+ }
+
+ FURI_LOG_I(TAG, "File selected: %s", furi_string_get_cstr(file_path));
+
+ if(!hex_viewer_open_file(hex_viewer, furi_string_get_cstr(file_path))) break;
+ hex_viewer_read_file(hex_viewer);
+
+ InputEvent input;
+ while(furi_message_queue_get(hex_viewer->input_queue, &input, FuriWaitForever) ==
+ FuriStatusOk) {
+ if(input.key == InputKeyBack) {
+ break;
+ } else if(input.key == InputKeyUp) {
+ furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+ if(hex_viewer->model->file_offset > 0) {
+ hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE;
+ if(!hex_viewer_read_file(hex_viewer)) break;
+ }
+ furi_mutex_release(hex_viewer->mutex);
+ } else if(input.key == InputKeyDown) {
+ furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+ uint32_t last_byte_on_screen =
+ hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes;
+
+ if(hex_viewer->model->file_size > last_byte_on_screen) {
+ hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE;
+ if(!hex_viewer_read_file(hex_viewer)) break;
+ }
+ furi_mutex_release(hex_viewer->mutex);
+ } else if(input.key == InputKeyLeft) {
+ furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
+ hex_viewer->model->mode = !hex_viewer->model->mode;
+ furi_mutex_release(hex_viewer->mutex);
+ } else if(input.key == InputKeyRight) {
+ FuriString* buffer;
+ buffer = furi_string_alloc();
+ furi_string_printf(
+ buffer,
+ "File path: %s\nFile size: %lu (0x%lX)",
+ furi_string_get_cstr(file_path),
+ hex_viewer->model->file_size,
+ hex_viewer->model->file_size);
+
+ DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
+ DialogMessage* message = dialog_message_alloc();
+ dialog_message_set_header(message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop);
+ dialog_message_set_icon(message, &I_hex_10px, 3, 2);
+ dialog_message_set_text(
+ message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
+ dialog_message_set_buttons(message, NULL, NULL, "Back");
+ dialog_message_show(dialogs, message);
+
+ furi_string_free(buffer);
+ dialog_message_free(message);
+ furi_record_close(RECORD_DIALOGS);
+ }
+ view_port_update(hex_viewer->view_port);
+ }
+ } while(false);
+
+ furi_string_free(file_path);
+ hex_viewer_free(hex_viewer);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/applications/plugins/text_viewer/icons/hex_10px.png b/applications/plugins/text_viewer/icons/hex_10px.png
new file mode 100644
index 000000000..582e288c6
Binary files /dev/null and b/applications/plugins/text_viewer/icons/hex_10px.png differ
diff --git a/applications/plugins/text_viewer/textviewerflipper.PNG b/applications/plugins/text_viewer/textviewerflipper.PNG
new file mode 100644
index 000000000..d357b7455
Binary files /dev/null and b/applications/plugins/text_viewer/textviewerflipper.PNG differ
diff --git a/applications/plugins/unitemp/application.fam b/applications/plugins/unitemp/application.fam
index 4fc9472cc..3ac128eef 100644
--- a/applications/plugins/unitemp/application.fam
+++ b/applications/plugins/unitemp/application.fam
@@ -1,6 +1,6 @@
App(
appid="unitemp",
- name="Unitemp",
+ name="[GPIO] Unitemp",
apptype=FlipperAppType.EXTERNAL,
entry_point="unitemp_app",
cdefines=["UNITEMP_APP"],
diff --git a/applications/plugins/unitemp/assets/sherlok_53x45.png b/applications/plugins/unitemp/assets/sherlok_53x45.png
index 1f258737e..65571203e 100644
Binary files a/applications/plugins/unitemp/assets/sherlok_53x45.png and b/applications/plugins/unitemp/assets/sherlok_53x45.png differ
diff --git a/applications/plugins/unitemp/assets/sherlok_53x45_sfw.png b/applications/plugins/unitemp/assets/sherlok_53x45_sfw.png
new file mode 100644
index 000000000..1f258737e
Binary files /dev/null and b/applications/plugins/unitemp/assets/sherlok_53x45_sfw.png differ
diff --git a/applications/plugins/unitemp/views/General_view.c b/applications/plugins/unitemp/views/General_view.c
index e21b04de2..b48349bdd 100644
--- a/applications/plugins/unitemp/views/General_view.c
+++ b/applications/plugins/unitemp/views/General_view.c
@@ -19,6 +19,7 @@
#include "unitemp_icons.h"
#include
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
static View* view;
@@ -169,7 +170,14 @@ static void _draw_singleSensor(Canvas* canvas, Sensor* sensor, const uint8_t pos
}
static void _draw_view_noSensors(Canvas* canvas) {
- canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45);
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
+ if (settings->sfw_mode) {
+ canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45_sfw);
+ }
+ else {
+ canvas_draw_icon(canvas, 7, 17, &I_sherlok_53x45);
+ }
//Рисование рамки
canvas_draw_rframe(canvas, 0, 0, 128, 63, 7);
canvas_draw_rframe(canvas, 0, 0, 128, 64, 7);
@@ -184,6 +192,7 @@ static void _draw_view_noSensors(Canvas* canvas) {
canvas_draw_str(canvas, x, y + 18, "press OK");
canvas_draw_icon(canvas, x + 37, y + 10, &I_Ok_btn_9x9);
+ free(settings);
}
static void _draw_view_sensorsList(Canvas* canvas) {
diff --git a/applications/plugins/usb_hid_autofire/CHANGELOG.md b/applications/plugins/usb_hid_autofire/CHANGELOG.md
index d0924edd3..62929bc8f 100644
--- a/applications/plugins/usb_hid_autofire/CHANGELOG.md
+++ b/applications/plugins/usb_hid_autofire/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## 0.5
+- Fix compatibility with Flipper Zero firmware 0.74.2
+
## 0.4
- Show active/inactive state in primary font (bold)
diff --git a/applications/plugins/usb_hid_autofire/application.fam b/applications/plugins/usb_hid_autofire/application.fam
index 10e3e6cf4..8a184d674 100644
--- a/applications/plugins/usb_hid_autofire/application.fam
+++ b/applications/plugins/usb_hid_autofire/application.fam
@@ -1,5 +1,7 @@
+# qv. https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/AppManifests.md
+
App(
- appid="USB_HID_Autofire",
+ appid="usb_hid_autofire",
name="USB HID Autofire",
apptype=FlipperAppType.EXTERNAL,
entry_point="usb_hid_autofire_app",
diff --git a/applications/plugins/usb_hid_autofire/tools.c b/applications/plugins/usb_hid_autofire/tools.c
new file mode 100644
index 000000000..2b452b55b
--- /dev/null
+++ b/applications/plugins/usb_hid_autofire/tools.c
@@ -0,0 +1,56 @@
+//
+// 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/plugins/usb_hid_autofire/tools.h b/applications/plugins/usb_hid_autofire/tools.h
new file mode 100644
index 000000000..9c71ea6ca
--- /dev/null
+++ b/applications/plugins/usb_hid_autofire/tools.h
@@ -0,0 +1,7 @@
+#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/plugins/usb_hid_autofire/usb_hid_autofire.c b/applications/plugins/usb_hid_autofire/usb_hid_autofire.c
index 97c9d4759..1333ba94a 100644
--- a/applications/plugins/usb_hid_autofire/usb_hid_autofire.c
+++ b/applications/plugins/usb_hid_autofire/usb_hid_autofire.c
@@ -4,6 +4,7 @@
#include
#include
#include "version.h"
+#include "tools.h"
// Uncomment to be able to make a screenshot
//#define USB_HID_AUTOFIRE_SCREENSHOT
@@ -25,7 +26,9 @@ 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);
@@ -85,19 +88,19 @@ int32_t usb_hid_autofire_app(void* p) {
}
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;
+ 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;
}
}
}
diff --git a/applications/plugins/usb_hid_autofire/version.h b/applications/plugins/usb_hid_autofire/version.h
index ac1f5d0fa..669b388a5 100644
--- a/applications/plugins/usb_hid_autofire/version.h
+++ b/applications/plugins/usb_hid_autofire/version.h
@@ -1 +1 @@
-#define VERSION "0.4"
+#define VERSION "0.5"
diff --git a/applications/plugins/usb_midi/.gitattributes b/applications/plugins/usb_midi/.gitattributes
deleted file mode 100644
index dfe077042..000000000
--- a/applications/plugins/usb_midi/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-# Auto detect text files and perform LF normalization
-* text=auto
diff --git a/applications/plugins/usb_midi/application.fam b/applications/plugins/usb_midi/application.fam
deleted file mode 100644
index d44153fd7..000000000
--- a/applications/plugins/usb_midi/application.fam
+++ /dev/null
@@ -1,14 +0,0 @@
-App(
- appid="USB_Midi",
- name="USB Midi",
- apptype=FlipperAppType.EXTERNAL,
- entry_point="usb_midi_app",
- requires=[
- "gui",
- ],
- stack_size=4 * 1024,
- order=20,
- fap_icon="usb_midi.png",
- fap_category="Music",
- # fap_icon_assets="icons",
-)
diff --git a/applications/plugins/usb_midi/midi/config.h b/applications/plugins/usb_midi/midi/config.h
deleted file mode 100644
index c62c1b1ef..000000000
--- a/applications/plugins/usb_midi/midi/config.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include
-
-#define SYSEX_BUFFER_LEN 16
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/message.c b/applications/plugins/usb_midi/midi/message.c
deleted file mode 100644
index 7bee9816a..000000000
--- a/applications/plugins/usb_midi/midi/message.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "message.h"
-
-/** Returns the data within the MidiEvent as a NoteOffEvent struct */
-NoteOffEvent AsNoteOff(MidiEvent* event) {
- NoteOffEvent m;
- m.channel = event->channel;
- m.note = event->data[0];
- m.velocity = event->data[1];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a NoteOnEvent struct */
-NoteOnEvent AsNoteOn(MidiEvent* event) {
- NoteOnEvent m;
- m.channel = event->channel;
- m.note = event->data[0];
- m.velocity = event->data[1];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a PolyphonicKeyPressureEvent struct */
-PolyphonicKeyPressureEvent AsPolyphonicKeyPressure(MidiEvent* event) {
- PolyphonicKeyPressureEvent m;
- m.channel = event->channel;
- m.note = event->data[0];
- m.pressure = event->data[1];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a ControlChangeEvent struct.*/
-ControlChangeEvent AsControlChange(MidiEvent* event) {
- ControlChangeEvent m;
- m.channel = event->channel;
- m.control_number = event->data[0];
- m.value = event->data[1];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
-ProgramChangeEvent AsProgramChange(MidiEvent* event) {
- ProgramChangeEvent m;
- m.channel = event->channel;
- m.program = event->data[0];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
-ChannelPressureEvent AsChannelPressure(MidiEvent* event) {
- ChannelPressureEvent m;
- m.channel = event->channel;
- m.pressure = event->data[0];
- return m;
-}
-
-/** Returns the data within the MidiEvent as a PitchBendEvent struct.*/
-PitchBendEvent AsPitchBend(MidiEvent* event) {
- PitchBendEvent m;
- m.channel = event->channel;
- m.value = ((uint16_t)(event->data[1]) << 7) + (event->data[0] - 8192);
- return m;
-}
-
-SystemExclusiveEvent AsSystemExclusive(MidiEvent* event) {
- SystemExclusiveEvent m;
- m.length = event->sysex_message_len;
- for(int i = 0; i < SYSEX_BUFFER_LEN; i++) {
- m.data[i] = 0;
- if(i < m.length) {
- m.data[i] = event->sysex_data[i];
- }
- }
- return m;
-}
-
-MTCQuarterFrameEvent AsMTCQuarterFrame(MidiEvent* event) {
- MTCQuarterFrameEvent m;
- m.message_type = (event->data[0] & 0x70) >> 4;
- m.value = (event->data[0]) & 0x0f;
- return m;
-}
-
-SongPositionPointerEvent AsSongPositionPointer(MidiEvent* event) {
- SongPositionPointerEvent m;
- m.position = ((uint16_t)(event->data[1]) << 7) | (event->data[0]);
- return m;
-}
-
-SongSelectEvent AsSongSelect(MidiEvent* event) {
- SongSelectEvent m;
- m.song = event->data[0];
- return m;
-}
-
-AllSoundOffEvent AsAllSoundOff(MidiEvent* event) {
- AllSoundOffEvent m;
- m.channel = event->channel;
- return m;
-}
-
-ResetAllControllersEvent AsResetAllControllers(MidiEvent* event) {
- ResetAllControllersEvent m;
- m.channel = event->channel;
- m.value = event->data[1];
- return m;
-}
-
-LocalControlEvent AsLocalControl(MidiEvent* event) {
- LocalControlEvent m;
- m.channel = event->channel;
- m.local_control_off = (event->data[1] == 0);
- m.local_control_on = (event->data[1] == 127);
- return m;
-}
-
-AllNotesOffEvent AsAllNotesOff(MidiEvent* event) {
- AllNotesOffEvent m;
- m.channel = event->channel;
- return m;
-}
-
-OmniModeOffEvent AsOmniModeOff(MidiEvent* event) {
- OmniModeOffEvent m;
- m.channel = event->channel;
- return m;
-}
-
-OmniModeOnEvent AsOmniModeOn(MidiEvent* event) {
- OmniModeOnEvent m;
- m.channel = event->channel;
- return m;
-}
-
-MonoModeOnEvent AsMonoModeOn(MidiEvent* event) {
- MonoModeOnEvent m;
- m.channel = event->channel;
- m.num_channels = event->data[1];
- return m;
-}
-
-PolyModeOnEvent AsPolyModeOn(MidiEvent* event) {
- PolyModeOnEvent m;
- m.channel = event->channel;
- return m;
-}
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/message.h b/applications/plugins/usb_midi/midi/message.h
deleted file mode 100644
index 88402c4a4..000000000
--- a/applications/plugins/usb_midi/midi/message.h
+++ /dev/null
@@ -1,251 +0,0 @@
-#pragma once
-#include
-#include
-#include "config.h"
-
-typedef enum {
- NoteOff, /**< & */
- NoteOn, /**< & */
- PolyphonicKeyPressure, /**< & */
- ControlChange, /**< & */
- ProgramChange, /**< & */
- ChannelPressure, /**< & */
- PitchBend, /**< & */
- SystemCommon, /**< & */
- SystemRealTime, /**< & */
- ChannelMode, /**< & */
- MessageLast, /**< & */
-} MidiMessageType;
-
-typedef enum {
- SystemExclusive, /**< & */
- MTCQuarterFrame, /**< & */
- SongPositionPointer, /**< & */
- SongSelect, /**< & */
- SCUndefined0, /**< & */
- SCUndefined1, /**< & */
- TuneRequest, /**< & */
- SysExEnd, /**< & */
- SystemCommonLast, /**< & */
-} SystemCommonType;
-
-typedef enum {
- TimingClock, /**< & */
- SRTUndefined0, /**< & */
- Start, /**< & */
- Continue, /**< & */
- Stop, /**< & */
- SRTUndefined1, /**< & */
- ActiveSensing, /**< & */
- Reset, /**< & */
- SystemRealTimeLast, /**< & */
-} SystemRealTimeType;
-
-typedef enum {
- AllSoundOff, /**< & */
- ResetAllControllers, /**< & */
- LocalControl, /**< & */
- AllNotesOff, /**< & */
- OmniModeOff, /**< & */
- OmniModeOn, /**< & */
- MonoModeOn, /**< & */
- PolyModeOn, /**< & */
- ChannelModeLast, /**< & */
-} ChannelModeType;
-
-/** Struct containing note, and velocity data for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t note; /**< & */
- uint8_t velocity; /**< & */
-} NoteOffEvent;
-
-/** Struct containing note, and velocity data for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t note; /**< & */
- uint8_t velocity; /**< & */
-} NoteOnEvent;
-
-/** Struct containing note, and pressure data for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel;
- uint8_t note;
- uint8_t pressure;
-} PolyphonicKeyPressureEvent;
-
-/** Struct containing control number, and value for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t control_number; /**< & */
- uint8_t value; /**< & */
-} ControlChangeEvent;
-
-/** Struct containing new program number, for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t program; /**< & */
-} ProgramChangeEvent;
-
-/** Struct containing pressure (aftertouch), for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t pressure; /**< & */
-} ChannelPressureEvent;
-
-/** Struct containing pitch bend value for a given channel.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- int16_t value; /**< & */
-} PitchBendEvent;
-
-/** Struct containing sysex data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int length;
- uint8_t data[SYSEX_BUFFER_LEN]; /**< & */
-} SystemExclusiveEvent;
-
-/** Struct containing QuarterFrame data.
-Can be made from MidiEvent
-*/
-typedef struct {
- uint8_t message_type; /**< & */
- uint8_t value; /**< & */
-} MTCQuarterFrameEvent;
-
-/** Struct containing song position data.
-Can be made from MidiEvent
-*/
-typedef struct {
- uint16_t position; /**< & */
-} SongPositionPointerEvent;
-
-/** Struct containing song select data.
-Can be made from MidiEvent
-*/
-typedef struct {
- uint8_t song; /**< & */
-} SongSelectEvent;
-
-/** Struct containing sound off data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
-} AllSoundOffEvent;
-
-/** Struct containing ResetAllControllersEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t value; /**< & */
-} ResetAllControllersEvent;
-
-/** Struct containing LocalControlEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- bool local_control_off; /**< & */
- bool local_control_on; /**< & */
-} LocalControlEvent;
-
-/** Struct containing AllNotesOffEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
-} AllNotesOffEvent;
-
-/** Struct containing OmniModeOffEvent data.
- * Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
-} OmniModeOffEvent;
-
-/** Struct containing OmniModeOnEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
-} OmniModeOnEvent;
-
-/** Struct containing MonoModeOnEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
- uint8_t num_channels; /**< & */
-} MonoModeOnEvent;
-
-/** Struct containing PolyModeOnEvent data.
-Can be made from MidiEvent
-*/
-typedef struct {
- int channel; /**< & */
-} PolyModeOnEvent;
-
-/** Simple MidiEvent with message type, channel, and data[2] members.
-*/
-typedef struct {
- MidiMessageType type;
- int channel;
- uint8_t data[2];
- uint8_t sysex_data[SYSEX_BUFFER_LEN];
- uint8_t sysex_message_len;
- SystemCommonType sc_type;
- SystemRealTimeType srt_type;
- ChannelModeType cm_type;
-} MidiEvent;
-
-/** Returns the data within the MidiEvent as a NoteOffEvent struct */
-NoteOffEvent AsNoteOff(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a NoteOnEvent struct */
-NoteOnEvent AsNoteOn(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a PolyphonicKeyPressureEvent struct */
-PolyphonicKeyPressureEvent AsPolyphonicKeyPressure(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a ControlChangeEvent struct.*/
-ControlChangeEvent AsControlChange(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
-ProgramChangeEvent AsProgramChange(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a ProgramChangeEvent struct.*/
-ChannelPressureEvent AsChannelPressure(MidiEvent* event);
-
-/** Returns the data within the MidiEvent as a PitchBendEvent struct.*/
-PitchBendEvent AsPitchBend(MidiEvent* event);
-
-SystemExclusiveEvent AsSystemExclusive(MidiEvent* event);
-MTCQuarterFrameEvent AsMTCQuarterFrame(MidiEvent* event);
-SongPositionPointerEvent AsSongPositionPointer(MidiEvent* event);
-SongSelectEvent AsSongSelect(MidiEvent* event);
-AllSoundOffEvent AsAllSoundOff(MidiEvent* event);
-ResetAllControllersEvent AsResetAllControllers(MidiEvent* event);
-LocalControlEvent AsLocalControl(MidiEvent* event);
-AllNotesOffEvent AsAllNotesOff(MidiEvent* event);
-OmniModeOffEvent AsOmniModeOff(MidiEvent* event);
-OmniModeOnEvent AsOmniModeOn(MidiEvent* event);
-MonoModeOnEvent AsMonoModeOn(MidiEvent* event);
-PolyModeOnEvent AsPolyModeOn(MidiEvent* event);
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/parser.c b/applications/plugins/usb_midi/midi/parser.c
deleted file mode 100644
index 86120e007..000000000
--- a/applications/plugins/usb_midi/midi/parser.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include
-#include "parser.h"
-
-typedef enum {
- ParserEmpty,
- ParserHasStatus,
- ParserHasData0,
- ParserSysEx,
-} ParserState;
-
-const uint8_t kStatusByteMask = 0x80;
-const uint8_t kMessageMask = 0x70;
-const uint8_t kDataByteMask = 0x7F;
-const uint8_t kSystemCommonMask = 0xF0;
-const uint8_t kChannelMask = 0x0F;
-const uint8_t kRealTimeMask = 0xF8;
-const uint8_t kSystemRealTimeMask = 0x07;
-
-struct MidiParser {
- MidiMessageType status;
- ParserState state;
- MidiEvent incoming_message;
-};
-
-MidiParser* midi_parser_alloc(void) {
- MidiParser* parser = malloc(sizeof(MidiParser));
- parser->incoming_message.type = MessageLast;
- parser->state = ParserEmpty;
- return parser;
-}
-
-void midi_parser_free(MidiParser* parser) {
- free(parser);
-}
-
-bool midi_parser_parse(MidiParser* parser, uint8_t byte) {
- bool parsed = false;
- MidiEvent* event = &parser->incoming_message;
-
- switch(parser->state) {
- case ParserEmpty:
- // check byte for valid Status Byte
- if(byte & kStatusByteMask) {
- // Get MessageType, and Channel
- event->channel = byte & kChannelMask;
- event->type = (MidiMessageType)((byte & kMessageMask) >> 4);
-
- // Validate, and move on.
- if(event->type < MessageLast) {
- parser->state = ParserHasStatus;
- // Mark this status byte as running_status
- parser->status = event->type;
-
- if(parser->status == SystemCommon) {
- event->channel = 0;
- //system real time = 1111 1xxx
- if(byte & 0x08) {
- event->type = SystemRealTime;
- parser->status = SystemRealTime;
- event->srt_type = (SystemRealTimeType)(byte & kSystemRealTimeMask);
-
- //short circuit to start
- parser->state = ParserEmpty;
- //queue_.push(incoming_message_);
- parsed = true;
- }
- //system common
- else {
- event->sc_type = (SystemCommonType)(byte & 0x07);
- //sysex
- if(event->sc_type == SystemExclusive) {
- parser->state = ParserSysEx;
- event->sysex_message_len = 0;
- }
- //short circuit
- else if(event->sc_type > SongSelect) {
- parser->state = ParserEmpty;
- //queue_.push(incoming_message_);
- parsed = true;
- }
- }
- }
- }
- // Else we'll keep waiting for a valid incoming status byte
- } else {
- // Handle as running status
- event->type = parser->status;
- event->data[0] = byte & kDataByteMask;
- parser->state = ParserHasData0;
- }
- break;
- case ParserHasStatus:
- if((byte & kStatusByteMask) == 0) {
- event->data[0] = byte & kDataByteMask;
- if(parser->status == ChannelPressure || parser->status == ProgramChange ||
- event->sc_type == MTCQuarterFrame || event->sc_type == SongSelect) {
- //these are just one data byte, so we short circuit back to start
- parser->state = ParserEmpty;
- //queue_.push(incoming_message_);
- parsed = true;
- } else {
- parser->state = ParserHasData0;
- }
-
- //ChannelModeMessages (reserved Control Changes)
- if(parser->status == ControlChange && event->data[0] > 119) {
- event->type = ChannelMode;
- parser->status = ChannelMode;
- event->cm_type = (ChannelModeType)(event->data[0] - 120);
- }
- } else {
- // invalid message go back to start ;p
- parser->state = ParserEmpty;
- }
- break;
- case ParserHasData0:
- if((byte & kStatusByteMask) == 0) {
- event->data[1] = byte & kDataByteMask;
- // At this point the message is valid, and we can add this MidiEvent to the queue
- //queue_.push(incoming_message_);
- parsed = true;
- }
- // Regardless, of whether the data was valid or not we go back to empty
- // because either the message is queued for handling or its not.
- parser->state = ParserEmpty;
- break;
- case ParserSysEx:
- // end of sysex
- if(byte == 0xf7) {
- parser->state = ParserEmpty;
- //queue_.push(incoming_message_);
- parsed = true;
- } else {
- if(event->sysex_message_len < SYSEX_BUFFER_LEN) {
- event->sysex_data[event->sysex_message_len] = byte;
- event->sysex_message_len++;
- }
- }
- break;
- default:
- break;
- }
-
- return parsed;
-}
-
-MidiEvent* midi_parser_get_message(MidiParser* parser) {
- return &parser->incoming_message;
-}
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/parser.h b/applications/plugins/usb_midi/midi/parser.h
deleted file mode 100644
index 93630f026..000000000
--- a/applications/plugins/usb_midi/midi/parser.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include
-#include
-#include "message.h"
-
-typedef struct MidiParser MidiParser;
-
-MidiParser* midi_parser_alloc(void);
-
-void midi_parser_free(MidiParser* parser);
-
-bool midi_parser_parse(MidiParser* parser, uint8_t data);
-
-MidiEvent* midi_parser_get_message(MidiParser* parser);
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/usb_message.c b/applications/plugins/usb_midi/midi/usb_message.c
deleted file mode 100644
index b6844c5f4..000000000
--- a/applications/plugins/usb_midi/midi/usb_message.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "usb_message.h"
-
-CodeIndex code_index_from_data(uint8_t data) {
- return (CodeIndex)(data & 0b00001111);
-}
-
-uint8_t cable_id_from_data(uint8_t data) {
- return (data >> 4) & 0b00001111;
-}
-
-uint8_t usb_message_data_size(CodeIndex code_index) {
- uint8_t data_size = 0;
- switch(code_index) {
- case CodeIndexCommon1Byte:
- /* case CodeIndexSysExEnd1Byte: */
- case CodeIndexSingleByte:
- data_size = 1;
- break;
- case CodeIndexSysEx2Byte:
- case CodeIndexSysExEnd2Byte:
- case CodeIndexProgramChange:
- case CodeIndexChannelPressure:
- data_size = 2;
- break;
- case CodeIndexSysEx3Byte:
- case CodeIndexSysExStart:
- case CodeIndexSysExEnd3Byte:
- case CodeIndexNoteOff:
- case CodeIndexNoteOn:
- case CodeIndexPolyKeyPress:
- case CodeIndexControlChange:
- case CodeIndexPitchBendChange:
- data_size = 3;
- break;
- default:
- break;
- }
-
- return data_size;
-}
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/midi/usb_message.h b/applications/plugins/usb_midi/midi/usb_message.h
deleted file mode 100644
index 852e9cb4f..000000000
--- a/applications/plugins/usb_midi/midi/usb_message.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-#include
-
-typedef enum {
- CodeIndexMisc = 0x0, /**< Reserved, MIDI Size: 1, 2, 3 */
- CodeIndexCableEvent = 0x1, /**< Reserved, MIDI Size: 1, 2, 3 */
- CodeIndexSysEx2Byte = 0x2, /**< MIDI Size: 2 */
- CodeIndexSysEx3Byte = 0x3, /**< MIDI Size: 3 */
- CodeIndexSysExStart = 0x4, /**< MIDI Size: 3 */
- CodeIndexCommon1Byte = 0x5, /**< MIDI Size: 1 */
- CodeIndexSysExEnd1Byte = 0x5, /**< MIDI Size: 1 */
- CodeIndexSysExEnd2Byte = 0x6, /**< MIDI Size: 2 */
- CodeIndexSysExEnd3Byte = 0x7, /**< MIDI Size: 3 */
- CodeIndexNoteOff = 0x8, /**< MIDI Size: 3 */
- CodeIndexNoteOn = 0x9, /**< MIDI Size: 3 */
- CodeIndexPolyKeyPress = 0xA, /**< MIDI Size: 3 */
- CodeIndexControlChange = 0xB, /**< MIDI Size: 3 */
- CodeIndexProgramChange = 0xC, /**< MIDI Size: 2 */
- CodeIndexChannelPressure = 0xD, /**< MIDI Size: 2 */
- CodeIndexPitchBendChange = 0xE, /**< MIDI Size: 3 */
- CodeIndexSingleByte = 0xF, /**< MIDI Size: 1 */
-} CodeIndex;
-
-CodeIndex code_index_from_data(uint8_t data);
-
-uint8_t cable_id_from_data(uint8_t data);
-
-uint8_t usb_message_data_size(CodeIndex code_index);
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/usb/cm3_usb_audio.h b/applications/plugins/usb_midi/usb/cm3_usb_audio.h
deleted file mode 100644
index 3c767f929..000000000
--- a/applications/plugins/usb_midi/usb/cm3_usb_audio.h
+++ /dev/null
@@ -1,234 +0,0 @@
-/** @defgroup usb_audio_defines USB Audio Type Definitions
-
-@brief Defined Constants and Types for the USB Audio Type Definitions
-
-@ingroup USB_defines
-
-@version 1.0.0
-
-@author @htmlonly © @endhtmlonly 2014
-Daniel Thompson
-Seb Holzapfel
-
-@date 19 April 2014
-
-LGPL License Terms @ref lgpl_license
-*/
-
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2014 Daniel Thompson
- * Copyright (C) 2018 Seb Holzapfel
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see .
- */
-
-/**@{*/
-
-#ifndef LIBOPENCM3_USB_AUDIO_H
-#define LIBOPENCM3_USB_AUDIO_H
-
-#include
-
-/*
- * Definitions from the USB_AUDIO_ or usb_audio_ namespace come from:
- * "Universal Serial Bus Class Definitions for Audio Devices, Revision 1.0"
- */
-
-/* Table A-1: Audio Interface Class Code */
-#define USB_CLASS_AUDIO 0x01
-
-/* Table A-2: Audio Interface Subclass Codes */
-#define USB_AUDIO_SUBCLASS_UNDEFINED 0x00
-#define USB_AUDIO_SUBCLASS_CONTROL 0x01
-#define USB_AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
-#define USB_AUDIO_SUBCLASS_MIDISTREAMING 0x03
-
-/* Table A-4: Audio Class-specific Descriptor Types */
-#define USB_AUDIO_DT_CS_UNDEFINED 0x20
-#define USB_AUDIO_DT_CS_DEVICE 0x21
-#define USB_AUDIO_DT_CS_CONFIGURATION 0x22
-#define USB_AUDIO_DT_CS_STRING 0x23
-#define USB_AUDIO_DT_CS_INTERFACE 0x24
-#define USB_AUDIO_DT_CS_ENDPOINT 0x25
-
-/* Table A-5: Audio Class-Specific AC Interface Descriptor Subtypes */
-#define USB_AUDIO_TYPE_AC_DESCRIPTOR_UNDEFINED 0x00
-#define USB_AUDIO_TYPE_HEADER 0x01
-#define USB_AUDIO_TYPE_INPUT_TERMINAL 0x02
-#define USB_AUDIO_TYPE_OUTPUT_TERMINAL 0x03
-#define USB_AUDIO_TYPE_MIXER_UNIT 0x04
-#define USB_AUDIO_TYPE_SELECTOR_UNIT 0x05
-#define USB_AUDIO_TYPE_FEATURE_UNIT 0x06
-#define USB_AUDIO_TYPE_PROCESSING_UNIT 0x07
-#define USB_AUDIO_TYPE_EXTENSION_UNIT 0x08
-
-/* Table 4-2: Class-Specific AC Interface Header Descriptor (head) */
-struct usb_audio_header_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint16_t bcdADC;
- uint16_t wTotalLength;
- uint8_t bInCollection;
- /* ... */
-} __attribute__((packed));
-
-/* Table 4-2: Class-Specific AC Interface Header Descriptor (body) */
-struct usb_audio_header_descriptor_body {
- /* ... */
- uint8_t baInterfaceNr;
-} __attribute__((packed));
-
-/* Table 4-3: Input Terminal Descriptor */
-struct usb_audio_input_terminal_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bTerminalID;
- uint16_t wTerminalType;
- uint8_t bAssocTerminal;
- uint8_t bNrChannels;
- uint16_t wChannelConfig;
- uint8_t iChannelNames;
- uint8_t iTerminal;
-} __attribute__((packed));
-
-/* Table 4-3: Output Terminal Descriptor */
-struct usb_audio_output_terminal_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bTerminalID;
- uint16_t wTerminalType;
- uint8_t bAssocTerminal;
- uint8_t bSourceID;
- uint8_t iTerminal;
-} __attribute__((packed));
-
-/* Table 4-7: Feature Unit Descriptor (head) */
-struct usb_audio_feature_unit_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bUnitID;
- uint8_t bSourceID;
- uint8_t bControlSize;
- uint16_t bmaControlMaster; /* device can assume 16-bit, given highest
- * defined bit in spec is bit #9.
- * (it is thus required bControlSize=2) */
- /* ... */
-} __attribute__((packed));
-
-/* Table 4-7: Feature Unit Descriptor (body) */
-struct usb_audio_feature_unit_descriptor_body {
- /* ... */
- uint16_t bmaControl;
- /* ... */
-} __attribute__((packed));
-
-/* Table 4-7: Feature Unit Descriptor (tail) */
-struct usb_audio_feature_unit_descriptor_tail {
- /* ... */
- uint8_t iFeature;
-} __attribute__((packed));
-
-/* Table 4-7: Feature Unit Descriptor (2-channel)
- *
- * This structure is a convenience covering the (common) case where
- * there are 2 channels associated with the feature unit
- */
-struct usb_audio_feature_unit_descriptor_2ch {
- struct usb_audio_feature_unit_descriptor_head head;
- struct usb_audio_feature_unit_descriptor_body channel_control[2];
- struct usb_audio_feature_unit_descriptor_tail tail;
-} __attribute__((packed));
-
-/* Table 4-19: Class-Specific AS Interface Descriptor */
-struct usb_audio_stream_interface_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bTerminalLink;
- uint8_t bDelay;
- uint16_t wFormatTag;
-} __attribute__((packed));
-
-/* Table 4-20: Standard AS Isochronous Audio Data Endpoint Descriptor */
-struct usb_audio_stream_endpoint_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bEndpointAddress;
- uint8_t bmAttributes;
- uint16_t wMaxPacketSize;
- uint8_t bInterval;
- uint8_t bRefresh;
- uint8_t bSynchAddress;
-} __attribute__((packed));
-
-/* Table 4-21: Class-Specific AS Isochronous Audio Data Endpoint Descriptor */
-struct usb_audio_stream_audio_endpoint_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bmAttributes;
- uint8_t bLockDelayUnits;
- uint16_t wLockDelay;
-} __attribute__((packed));
-
-/*
- * Definitions from the USB_AUDIO_FORMAT_ or usb_audio_format_ namespace come from:
- * "Universal Serial Bus Device Class Definition for Audio Data Formats, Revision 1.0"
- */
-
-/* Table 2-1: Type I Format Type Descriptor (head) */
-struct usb_audio_format_type1_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bFormatType;
- uint8_t bNrChannels;
- uint8_t bSubFrameSize;
- uint8_t bBitResolution;
- uint8_t bSamFreqType;
- /* ... */
-} __attribute__((packed));
-
-/* Table 2-2: Continuous Sampling Frequency */
-struct usb_audio_format_continuous_sampling_frequency {
- /* ... */
- uint32_t tLowerSamFreq : 24;
- uint32_t tUpperSamFreq : 24;
-} __attribute__((packed));
-
-/* Table 2-3: Discrete Number of Sampling Frequencies */
-struct usb_audio_format_discrete_sampling_frequency {
- /* ... */
- uint32_t tSamFreq : 24;
-} __attribute__((packed));
-
-/* Table 2-1: Type I Format Type Descriptor (1 sampling frequency)
- *
- * This structure is a convenience covering the (common) case where
- * only 1 discrete sampling frequency is used
- */
-struct usb_audio_format_type1_descriptor_1freq {
- struct usb_audio_format_type1_descriptor_head head;
- struct usb_audio_format_discrete_sampling_frequency freqs[1];
-} __attribute__((packed));
-
-#endif
-
-/**@}*/
diff --git a/applications/plugins/usb_midi/usb/cm3_usb_midi.h b/applications/plugins/usb_midi/usb/cm3_usb_midi.h
deleted file mode 100644
index 8435c883e..000000000
--- a/applications/plugins/usb_midi/usb/cm3_usb_midi.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/** @defgroup usb_audio_defines USB MIDI Type Definitions
-
-@brief Defined Constants and Types for the USB MIDI Type Definitions
-
-@ingroup USB_defines
-
-@version 1.0.0
-
-@author @htmlonly © @endhtmlonly 2014
-Daniel Thompson
-
-@date 19 April 2014
-
-LGPL License Terms @ref lgpl_license
-*/
-
-/*
- * This file is part of the libopencm3 project.
- *
- * Copyright (C) 2014 Daniel Thompson
- *
- * This library is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This library 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see .
- */
-
-/**@{*/
-
-#ifndef LIBOPENCM3_USB_MIDI_H
-#define LIBOPENCM3_USB_MIDI_H
-
-#include
-
-/*
- * Definitions from the USB_MIDI_ or usb_midi_ namespace come from:
- * "Universal Serial Bus Class Definitions for MIDI Devices, Revision 1.0"
- */
-
-/* Appendix A.1: MS Class-Specific Interface Descriptor Subtypes */
-#define USB_MIDI_SUBTYPE_MS_DESCRIPTOR_UNDEFINED 0x00
-#define USB_MIDI_SUBTYPE_MS_HEADER 0x01
-#define USB_MIDI_SUBTYPE_MIDI_IN_JACK 0x02
-#define USB_MIDI_SUBTYPE_MIDI_OUT_JACK 0x03
-#define USB_MIDI_SUBTYPE_MIDI_ELEMENT 0x04
-
-/* Appendix A.2: MS Class-Specific Endpoint Descriptor Subtypes */
-#define USB_MIDI_SUBTYPE_DESCRIPTOR_UNDEFINED 0x00
-#define USB_MIDI_SUBTYPE_MS_GENERAL 0x01
-
-/* Appendix A.3: MS MIDI IN and OUT Jack types */
-#define USB_MIDI_JACK_TYPE_UNDEFINED 0x00
-#define USB_MIDI_JACK_TYPE_EMBEDDED 0x01
-#define USB_MIDI_JACK_TYPE_EXTERNAL 0x02
-
-/* Appendix A.5.1 Endpoint Control Selectors */
-#define USB_MIDI_EP_CONTROL_UNDEFINED 0x00
-#define USB_MIDI_ASSOCIATION_CONTROL 0x01
-
-/* Table 6-2: Class-Specific MS Interface Header Descriptor */
-struct usb_midi_header_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint16_t bcdMSC;
- uint16_t wTotalLength;
-} __attribute__((packed));
-
-/* Table 6-3: MIDI IN Jack Descriptor */
-struct usb_midi_in_jack_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bJackType;
- uint8_t bJackID;
- uint8_t iJack;
-} __attribute__((packed));
-
-/* Table 6-4: MIDI OUT Jack Descriptor (head) */
-struct usb_midi_out_jack_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bJackType;
- uint8_t bJackID;
- uint8_t bNrInputPins;
- /* ... */
-} __attribute__((packed));
-
-/* Table 6.4: MIDI OUT Jack Descriptor (body) */
-struct usb_midi_out_jack_descriptor_body {
- /* ... */
- uint8_t baSourceID;
- uint8_t baSourcePin;
- /* ... */
-} __attribute__((packed));
-
-/* Table 6.4: MIDI OUT Jack Descriptor (tail) */
-struct usb_midi_out_jack_descriptor_tail {
- /* ... */
- uint8_t iJack;
-} __attribute__((packed));
-
-/* Table 6.4: MIDI OUT Jack Descriptor (single)
- *
- * This structure is a convenience covering the (normal) case where
- * there is only one input pin.
- */
-struct usb_midi_out_jack_descriptor {
- struct usb_midi_out_jack_descriptor_head head;
- struct usb_midi_out_jack_descriptor_body source[1];
- struct usb_midi_out_jack_descriptor_tail tail;
-} __attribute__((packed));
-
-/* Table 6-5: MIDI Element Descriptor (head) */
-struct usb_midi_element_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubtype;
- uint8_t bElementID;
- uint8_t bNrInputPins;
- /* ... */
-} __attribute__((packed));
-
-/* Table 6-5: MIDI Element Descriptor (body) */
-struct usb_midi_element_descriptor_body {
- /* ... */
- uint8_t baSourceID;
- uint8_t baSourcePin;
- /* ... */
-} __attribute__((packed));
-
-/* Table 6-5: MIDI Element Descriptor (tail) */
-struct usb_midi_element_descriptor_tail {
- /* ... */
- uint8_t bNrOutputPins;
- uint8_t bInTerminalLink;
- uint8_t bOutTerminalLink;
- uint8_t bElCapsSize;
- uint16_t bmElementCaps; /* host cannot assume this is 16-bit but device
- can (since highest defined bitmap value in
- v1.0 is bit 11) */
- uint8_t iElement;
-} __attribute__((packed));
-
-/* Table 6-5: MIDI Element Descriptor (single)
- *
- * This structure is a convenience covering the (common) case where
- * there is only one input pin.
- */
-struct usb_midi_element_descriptor {
- struct usb_midi_element_descriptor_head head;
- struct usb_midi_element_descriptor_body source[1];
- struct usb_midi_element_descriptor_tail tail;
-} __attribute__((packed));
-
-/* Table 6-7: Class-specific MS Bulk Data Endpoint Descriptor (head) */
-struct usb_midi_endpoint_descriptor_head {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bDescriptorSubType;
- uint8_t bNumEmbMIDIJack;
-} __attribute__((packed));
-
-/* Table 6-7: Class-specific MS Bulk Data Endpoint Descriptor (body) */
-struct usb_midi_endpoint_descriptor_body {
- uint8_t baAssocJackID;
-} __attribute__((packed));
-
-/* Table 6.7: Class-specific MS Bulk Data Endpoint Descriptor (single)
- *
- * This structure is a convenience covering the (normal) case where
- * there is only one input pin.
- */
-struct usb_midi_endpoint_descriptor {
- struct usb_midi_endpoint_descriptor_head head;
- struct usb_midi_endpoint_descriptor_body jack[1];
-} __attribute__((packed));
-
-#endif
-
-/**@}*/
diff --git a/applications/plugins/usb_midi/usb/usb_midi_driver.c b/applications/plugins/usb_midi/usb/usb_midi_driver.c
deleted file mode 100644
index 9abf77d12..000000000
--- a/applications/plugins/usb_midi/usb/usb_midi_driver.c
+++ /dev/null
@@ -1,428 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "usb_midi_driver.h"
-#include "cm3_usb_audio.h"
-#include "cm3_usb_midi.h"
-
-// Appendix B. "Example: Simple MIDI Adapter" from "Universal Serial Bus Device Class Definition for MIDI Devices", Revision 1.0
-
-#define USB_VID 0x6666
-#define USB_PID 0x5119
-
-#define USB_EP0_SIZE 8
-
-#define USB_MIDI_EP_SIZE 64
-#define USB_MIDI_EP_IN 0x81
-#define USB_MIDI_EP_OUT 0x01
-
-#define EP_CFG_DECONFIGURE 0
-#define EP_CFG_CONFIGURE 1
-
-enum {
- USB_STR_ZERO,
- USB_STR_MANUFACTURER,
- USB_STR_PRODUCT,
- USB_STR_SERIAL_NUMBER,
-};
-
-/*
- B.1 Device Descriptor
-*/
-static const struct usb_device_descriptor device_descriptor = {
- .bLength = sizeof(struct usb_device_descriptor),
- .bDescriptorType = USB_DTYPE_DEVICE,
- .bcdUSB = VERSION_BCD(2, 0, 0), // was 0x0110, 1.10 - current revision of USBspecification.
- .bDeviceClass = USB_CLASS_PER_INTERFACE,
- .bDeviceSubClass = USB_SUBCLASS_NONE,
- .bDeviceProtocol = USB_PROTO_NONE,
- .bMaxPacketSize0 = USB_EP0_SIZE,
- .idVendor = USB_VID,
- .idProduct = USB_PID,
- .bcdDevice = VERSION_BCD(1, 0, 0),
- .iManufacturer = USB_STR_MANUFACTURER,
- .iProduct = USB_STR_PRODUCT,
- .iSerialNumber = USB_STR_SERIAL_NUMBER,
- .bNumConfigurations = 1,
-};
-
-struct usb_audio_header_descriptor {
- struct usb_audio_header_descriptor_head head;
- struct usb_audio_header_descriptor_body body;
-} __attribute__((packed));
-
-struct usb_midi_jacks_descriptor {
- struct usb_midi_header_descriptor header;
- struct usb_midi_in_jack_descriptor in_embedded;
- struct usb_midi_in_jack_descriptor in_external;
- struct usb_midi_out_jack_descriptor out_embedded;
- struct usb_midi_out_jack_descriptor out_external;
-} __attribute__((packed));
-
-struct MidiConfigDescriptor {
- /*
- B.2 Configuration Descriptor
- */
- struct usb_config_descriptor config;
-
- /*
- B.3 AudioControl Interface Descriptors
-
- The AudioControl interface describes the device structure (audio function topology)
- and is used to manipulate the Audio Controls. This device has no audio function incorporated.
- However, the AudioControl interface is mandatory and therefore both the standard AC interface
- descriptor and the classspecific AC interface descriptor must be present.
- The class-specific AC interface descriptor only contains the header descriptor.
- */
- // B.3.1 Standard AC Interface Descriptor
- struct usb_interface_descriptor audio_control_iface;
- // B.3.2 Class-specific AC Interface Descriptor
- struct usb_audio_header_descriptor audio_control_header;
-
- /*
- B.4 MIDIStreaming Interface Descriptors
- */
- // B.4.1 Standard MS Interface Descriptor
- struct usb_interface_descriptor midi_streaming_iface;
- // B.4.2 Class-specific MS Interface Descriptor
- // B.4.3 MIDI IN Jack Descriptor
- // B.4.4 MIDI OUT Jack Descriptor
- struct usb_midi_jacks_descriptor midi_jacks;
-
- /*
- B.5 Bulk OUT Endpoint Descriptors
- */
- // B.5.1 Standard Bulk OUT Endpoint Descriptor
- struct usb_endpoint_descriptor bulk_out;
- // B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor
- struct usb_midi_endpoint_descriptor midi_bulk_out;
-
- /*
- B.6 Bulk IN Endpoint Descriptors
- */
- // B.6.1 Standard Bulk IN Endpoint Descriptor
- struct usb_endpoint_descriptor bulk_in;
- // B.6.2 Class-specific MS Bulk IN Endpoint Descriptor
- struct usb_midi_endpoint_descriptor midi_bulk_in;
-} __attribute__((packed));
-
-static const struct MidiConfigDescriptor config_descriptor = {
- .config =
- {
- .bLength = sizeof(struct usb_config_descriptor),
- .bDescriptorType = USB_DTYPE_CONFIGURATION,
- .wTotalLength = sizeof(struct MidiConfigDescriptor),
- .bNumInterfaces = 2, /* control and data */
- .bConfigurationValue = 1,
- .iConfiguration = 0,
- .bmAttributes = USB_CFG_ATTR_RESERVED,
- .bMaxPower = USB_CFG_POWER_MA(100),
- },
- .audio_control_iface =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = 0,
- .bInterfaceClass = USB_CLASS_AUDIO,
- .bInterfaceSubClass = USB_AUDIO_SUBCLASS_CONTROL,
- .bInterfaceProtocol = USB_PROTO_NONE,
- .iInterface = 0,
- },
- .audio_control_header =
- {
- .head =
- {
- .bLength = sizeof(struct usb_audio_header_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_AUDIO_TYPE_HEADER,
- .bcdADC = VERSION_BCD(1, 0, 0),
- .wTotalLength = sizeof(struct usb_audio_header_descriptor),
- .bInCollection = 1,
- },
- .body =
- {
- .baInterfaceNr = 1,
- },
- },
- .midi_streaming_iface =
- {
- .bLength = sizeof(struct usb_interface_descriptor),
- .bDescriptorType = USB_DTYPE_INTERFACE,
- .bInterfaceNumber = 1,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = USB_CLASS_AUDIO,
- .bInterfaceSubClass = USB_AUDIO_SUBCLASS_MIDISTREAMING,
- .bInterfaceProtocol = USB_PROTO_NONE,
- .iInterface = 0,
- },
- .midi_jacks =
- {
- .header =
- {
- .bLength = sizeof(struct usb_midi_header_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MIDI_SUBTYPE_MS_HEADER,
- .bcdMSC = VERSION_BCD(1, 0, 0),
- .wTotalLength = sizeof(struct usb_midi_jacks_descriptor),
- },
- .in_embedded =
- {
- .bLength = sizeof(struct usb_midi_in_jack_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_IN_JACK,
- .bJackType = USB_MIDI_JACK_TYPE_EMBEDDED,
- .bJackID = 0x01,
- .iJack = 0x00,
- },
- .in_external =
- {
- .bLength = sizeof(struct usb_midi_in_jack_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_IN_JACK,
- .bJackType = USB_MIDI_JACK_TYPE_EXTERNAL,
- .bJackID = 0x02,
- .iJack = 0x00,
- },
- .out_embedded =
- {
- .head =
- {
- .bLength = sizeof(struct usb_midi_out_jack_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_OUT_JACK,
- .bJackType = USB_MIDI_JACK_TYPE_EMBEDDED,
- .bJackID = 0x03,
- .bNrInputPins = 1,
- },
- .source[0] =
- {
- .baSourceID = 0x02,
- .baSourcePin = 0x01,
- },
- .tail =
- {
- .iJack = 0x00,
- },
- },
- .out_external =
- {
- .head =
- {
- .bLength = sizeof(struct usb_midi_out_jack_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_INTERFACE,
- .bDescriptorSubtype = USB_MIDI_SUBTYPE_MIDI_OUT_JACK,
- .bJackType = USB_MIDI_JACK_TYPE_EXTERNAL,
- .bJackID = 0x04,
- .bNrInputPins = 1,
- },
- .source[0] =
- {
- .baSourceID = 0x01,
- .baSourcePin = 0x01,
- },
- .tail =
- {
- .iJack = 0x00,
- },
- },
- },
- .bulk_out =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = USB_MIDI_EP_OUT,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = USB_MIDI_EP_SIZE,
- .bInterval = 0,
- },
- .midi_bulk_out =
- {
- .head =
- {
- .bLength = sizeof(struct usb_midi_endpoint_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_ENDPOINT,
- .bDescriptorSubType = USB_MIDI_SUBTYPE_MS_GENERAL,
- .bNumEmbMIDIJack = 1,
- },
- .jack[0] =
- {
- .baAssocJackID = 0x01,
- },
- },
- .bulk_in =
- {
- .bLength = sizeof(struct usb_endpoint_descriptor),
- .bDescriptorType = USB_DTYPE_ENDPOINT,
- .bEndpointAddress = USB_MIDI_EP_IN,
- .bmAttributes = USB_EPTYPE_BULK,
- .wMaxPacketSize = USB_MIDI_EP_SIZE,
- .bInterval = 0,
- },
- .midi_bulk_in =
- {
- .head =
- {
- .bLength = sizeof(struct usb_midi_endpoint_descriptor),
- .bDescriptorType = USB_AUDIO_DT_CS_ENDPOINT,
- .bDescriptorSubType = USB_MIDI_SUBTYPE_MS_GENERAL,
- .bNumEmbMIDIJack = 1,
- },
- .jack[0] =
- {
- .baAssocJackID = 0x03,
- },
- },
-};
-
-static const struct usb_string_descriptor dev_manufacturer_string =
- USB_STRING_DESC("Flipper Devices Inc.");
-
-static const struct usb_string_descriptor dev_product_string =
- USB_STRING_DESC("Flipper MIDI Device");
-
-static const struct usb_string_descriptor dev_serial_number_string =
- USB_STRING_DESC("Serial Number");
-
-static void midi_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx);
-static void midi_deinit(usbd_device* dev);
-static void midi_on_wakeup(usbd_device* dev);
-static void midi_on_suspend(usbd_device* dev);
-static usbd_respond midi_ep_config(usbd_device* dev, uint8_t cfg);
-static usbd_respond midi_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback);
-
-FuriHalUsbInterface midi_usb_interface = {
- .init = midi_init,
- .deinit = midi_deinit,
- .wakeup = midi_on_wakeup,
- .suspend = midi_on_suspend,
- .dev_descr = (struct usb_device_descriptor*)&device_descriptor,
- .cfg_descr = (void*)&config_descriptor,
-};
-
-typedef struct {
- usbd_device* dev;
- MidiRxCallback rx_callback;
- void* context;
- FuriSemaphore* semaphore_tx;
- bool connected;
-} MidiUsb;
-
-static MidiUsb midi_usb;
-
-void midi_usb_set_context(void* context) {
- midi_usb.context = context;
-}
-
-void midi_usb_set_rx_callback(MidiRxCallback callback) {
- midi_usb.rx_callback = callback;
-}
-
-size_t midi_usb_rx(uint8_t* buffer, size_t size) {
- size_t len = usbd_ep_read(midi_usb.dev, USB_MIDI_EP_OUT, buffer, size);
- return len;
-}
-
-size_t midi_usb_tx(uint8_t* buffer, uint8_t size) {
- if((midi_usb.semaphore_tx == NULL) || (midi_usb.connected == false)) return 0;
-
- furi_check(furi_semaphore_acquire(midi_usb.semaphore_tx, FuriWaitForever) == FuriStatusOk);
-
- if(midi_usb.connected) {
- int32_t len = usbd_ep_write(midi_usb.dev, USB_MIDI_EP_IN, buffer, size);
- return len;
- } else {
- return 0;
- }
-}
-
-static void midi_init(usbd_device* dev, FuriHalUsbInterface* intf, void* ctx) {
- UNUSED(intf);
- UNUSED(ctx);
-
- midi_usb_interface.str_manuf_descr = (void*)&dev_manufacturer_string;
- midi_usb_interface.str_prod_descr = (void*)&dev_product_string;
- midi_usb_interface.str_serial_descr = (void*)&dev_serial_number_string;
- midi_usb_interface.dev_descr->idVendor = USB_VID;
- midi_usb_interface.dev_descr->idProduct = USB_PID;
-
- midi_usb.dev = dev;
- if(midi_usb.semaphore_tx == NULL) midi_usb.semaphore_tx = furi_semaphore_alloc(1, 1);
-
- usbd_reg_config(dev, midi_ep_config);
- usbd_reg_control(dev, midi_control);
-
- usbd_connect(dev, true);
-}
-
-static void midi_deinit(usbd_device* dev) {
- midi_usb.connected = false;
- midi_usb.dev = NULL;
- furi_semaphore_free(midi_usb.semaphore_tx);
-
- usbd_reg_config(dev, NULL);
- usbd_reg_control(dev, NULL);
-}
-
-static void midi_on_wakeup(usbd_device* dev) {
- UNUSED(dev);
- if(!midi_usb.connected) {
- midi_usb.connected = true;
- }
-}
-
-static void midi_on_suspend(usbd_device* dev) {
- UNUSED(dev);
- if(midi_usb.connected) {
- midi_usb.connected = false;
- }
-}
-
-static void midi_tx_rx(usbd_device* dev, uint8_t event, uint8_t ep) {
- UNUSED(dev);
- UNUSED(ep);
-
- switch(event) {
- case usbd_evt_eptx:
- furi_semaphore_release(midi_usb.semaphore_tx);
- break;
- case usbd_evt_eprx:
- if(midi_usb.rx_callback != NULL) {
- midi_usb.rx_callback(midi_usb.context);
- }
- break;
- default:
- break;
- }
-}
-
-static usbd_respond midi_ep_config(usbd_device* dev, uint8_t cfg) {
- switch(cfg) {
- case EP_CFG_DECONFIGURE:
- usbd_ep_deconfig(dev, USB_MIDI_EP_OUT);
- usbd_ep_deconfig(dev, USB_MIDI_EP_IN);
- usbd_reg_endpoint(dev, USB_MIDI_EP_OUT, NULL);
- usbd_reg_endpoint(dev, USB_MIDI_EP_IN, NULL);
- return usbd_ack;
- case EP_CFG_CONFIGURE:
- usbd_ep_config(dev, USB_MIDI_EP_OUT, USB_EPTYPE_BULK, USB_MIDI_EP_SIZE);
- usbd_ep_config(dev, USB_MIDI_EP_IN, USB_EPTYPE_BULK, USB_MIDI_EP_SIZE);
- usbd_reg_endpoint(dev, USB_MIDI_EP_OUT, midi_tx_rx);
- usbd_reg_endpoint(dev, USB_MIDI_EP_IN, midi_tx_rx);
- return usbd_ack;
- default:
- return usbd_fail;
- }
-}
-
-static usbd_respond midi_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_callback* callback) {
- UNUSED(dev);
- UNUSED(req);
- UNUSED(callback);
-
- return usbd_fail;
-}
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/usb/usb_midi_driver.h b/applications/plugins/usb_midi/usb/usb_midi_driver.h
deleted file mode 100644
index d385efcb5..000000000
--- a/applications/plugins/usb_midi/usb/usb_midi_driver.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include
-
-extern FuriHalUsbInterface midi_usb_interface;
-
-typedef void (*MidiRxCallback)(void* context);
-
-void midi_usb_set_context(void* context);
-
-void midi_usb_set_rx_callback(MidiRxCallback callback);
-
-size_t midi_usb_rx(uint8_t* buffer, size_t size);
-
-size_t midi_usb_tx(uint8_t* buffer, uint8_t size);
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/usb_midi.c b/applications/plugins/usb_midi/usb_midi.c
deleted file mode 100644
index d82fb74d7..000000000
--- a/applications/plugins/usb_midi/usb_midi.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include
-#include
-#include "usb/usb_midi_driver.h"
-#include "midi/parser.h"
-#include "midi/usb_message.h"
-#include
-
-float note_to_frequency(int note) {
- float a = 440;
- return (a / 32) * powf(2, ((note - 9) / 12.0));
-}
-
-typedef enum {
- MidiThreadEventStop = (1 << 0),
- MidiThreadEventRx = (1 << 1),
- MidiThreadEventAll = MidiThreadEventStop | MidiThreadEventRx,
-} MidiThreadEvent;
-
-static void midi_rx_callback(void* context) {
- furi_assert(context);
- FuriThreadId thread_id = (FuriThreadId)context;
- furi_thread_flags_set(thread_id, MidiThreadEventRx);
-}
-
-int32_t usb_midi_app(void* p) {
- UNUSED(p);
-
- FuriHalUsbInterface* usb_config_prev;
- usb_config_prev = furi_hal_usb_get_config();
- midi_usb_set_context(furi_thread_get_id(furi_thread_get_current()));
- midi_usb_set_rx_callback(midi_rx_callback);
- furi_hal_usb_set_config(&midi_usb_interface, NULL);
-
- MidiParser* parser = midi_parser_alloc();
- uint32_t events;
- uint8_t current_note = 255;
-
- while(1) {
- events = furi_thread_flags_wait(MidiThreadEventAll, FuriFlagWaitAny, FuriWaitForever);
-
- if(!(events & FuriFlagError)) {
- if(events & MidiThreadEventRx) {
- uint8_t buffer[64];
- size_t size = midi_usb_rx(buffer, sizeof(buffer));
- // loopback
- // midi_usb_tx(buffer, size);
- size_t start = 0;
- while(start < size) {
- CodeIndex code_index = code_index_from_data(buffer[start]);
- uint8_t data_size = usb_message_data_size(code_index);
- if(data_size == 0) break;
-
- start += 1;
- for(size_t j = 0; j < data_size; j++) {
- if(midi_parser_parse(parser, buffer[start + j])) {
- MidiEvent* event = midi_parser_get_message(parser);
- if(event->type == NoteOn) {
- NoteOnEvent note_on = AsNoteOn(event);
- current_note = note_on.note;
- if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
- furi_hal_speaker_start(
- note_to_frequency(note_on.note),
- note_on.velocity / 127.0f);
- }
- } else if(event->type == NoteOff) {
- NoteOffEvent note_off = AsNoteOff(event);
- if(note_off.note == current_note && furi_hal_speaker_is_mine()) {
- furi_hal_speaker_stop();
- furi_hal_speaker_release();
- }
- }
- }
- }
- start += data_size;
- }
- }
- }
- }
-
- midi_parser_free(parser);
- furi_hal_usb_set_config(usb_config_prev, NULL);
-
- return 0;
-}
\ No newline at end of file
diff --git a/applications/plugins/usb_midi/usb_midi.png b/applications/plugins/usb_midi/usb_midi.png
deleted file mode 100644
index 6d0ac6fed..000000000
Binary files a/applications/plugins/usb_midi/usb_midi.png and /dev/null differ
diff --git a/applications/plugins/weather_station/images/Scanning_123x52.png b/applications/plugins/weather_station/images/Scanning_123x52.png
index ec785948d..a48c5330e 100644
Binary files a/applications/plugins/weather_station/images/Scanning_123x52.png and b/applications/plugins/weather_station/images/Scanning_123x52.png differ
diff --git a/applications/plugins/weather_station/images/Scanning_123x52_sfw.png b/applications/plugins/weather_station/images/Scanning_123x52_sfw.png
new file mode 100644
index 000000000..ec785948d
Binary files /dev/null and b/applications/plugins/weather_station/images/Scanning_123x52_sfw.png differ
diff --git a/applications/plugins/weather_station/images/WarningDolphin_45x42.png b/applications/plugins/weather_station/images/WarningDolphin_45x42.png
index d766ffbb4..db225de36 100644
Binary files a/applications/plugins/weather_station/images/WarningDolphin_45x42.png and b/applications/plugins/weather_station/images/WarningDolphin_45x42.png differ
diff --git a/applications/plugins/weather_station/images/WarningDolphin_45x42_sfw.png b/applications/plugins/weather_station/images/WarningDolphin_45x42_sfw.png
new file mode 100644
index 000000000..d766ffbb4
Binary files /dev/null and b/applications/plugins/weather_station/images/WarningDolphin_45x42_sfw.png differ
diff --git a/applications/plugins/weather_station/views/weather_station_receiver.c b/applications/plugins/weather_station/views/weather_station_receiver.c
index 42a90b22d..89dbc7a0a 100644
--- a/applications/plugins/weather_station/views/weather_station_receiver.c
+++ b/applications/plugins/weather_station/views/weather_station_receiver.c
@@ -7,6 +7,8 @@
#include
#include
+#include "../../../settings/desktop_settings/desktop_settings_app.h"
+
#define FRAME_HEIGHT 12
#define MAX_LEN_PX 112
#define MENU_ITEMS 4u
@@ -176,6 +178,9 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
FuriString* str_buff;
str_buff = furi_string_alloc();
+ DesktopSettings* settings = malloc(sizeof(DesktopSettings));
+ DESKTOP_SETTINGS_LOAD(settings);
+
WSReceiverMenuItem* item_menu;
for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) {
@@ -200,7 +205,12 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_set_color(canvas, ColorBlack);
if(model->history_item == 0) {
- canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
+ if (settings->sfw_mode) {
+ canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52_sfw);
+ }
+ else {
+ canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52);
+ }
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 63, 46, "Scanning...");
canvas_draw_line(canvas, 46, 51, 125, 51);
@@ -222,7 +232,12 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_draw_icon(canvas, 65, 42, &I_Pin_back_arrow_10x8);
canvas_draw_icon(canvas, 80, 42, &I_Pin_back_arrow_10x8);
canvas_draw_icon(canvas, 95, 42, &I_Pin_back_arrow_10x8);
- canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
+ if (settings->sfw_mode) {
+ canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42_sfw);
+ }
+ else {
+ canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
+ }
canvas_draw_dot(canvas, 17, 61);
break;
case WSReceiverBarShowUnlock:
@@ -235,6 +250,7 @@ void ws_view_receiver_draw(Canvas* canvas, WSReceiverModel* model) {
canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str));
break;
}
+ free(settings);
}
static void ws_view_receiver_timer_callback(void* context) {
diff --git a/applications/plugins/wii_ec_anal/README.md b/applications/plugins/wii_ec_anal/README.md
deleted file mode 100644
index 8d439c7e0..000000000
--- a/applications/plugins/wii_ec_anal/README.md
+++ /dev/null
@@ -1,234 +0,0 @@
-# [FlipperZero] Wii Extension Controller Protocol Analyser
-This Protocol Analyser offers a full Test and Calibrate system for Wii Extension Controllers.
-
-__Disclaimer:__ *Use of this plugin, and notably connecting an Extension Controller to the FlipperZero is performed entirely at your own risk.*
-
-# Notes
-This plugin has (todate) only been tested with official Nintendo Nunchucks and Classic Controllers - namely Nunchucks and Classic Controllers.
-
-# Encryption
-This plugin has SOME code to handle encryption, but it it unused, untested, and some of it is known to un-work.
-
-This plugin (currently) only works with Extension Controllers which implement the encryption-bypass strategy. IE. `i2c_write(0xf0, 0x55) ; i2c_write(0xfb, 0x00)`
-
-If you need this functionality, either raise an Issue or, better still, a Pull Request.
-
-# Screen: SPLASH
-
-The SPLASH Screen is displayed when the Plugin starts. It can be cleared by pressing any key, else it will auto-clear after 3.5 seconds.
-
-# Screen: WAIT
-
-The WAIT screen will display which pins you need to connect between the flipper and the Wii Extension Controller.
-
-__Disclaimer:__ Use of this plugin, and notably connecting the Controller to the FlipperZero is performed entirely at your own risk.
-
-Looking in to the exposed side of the Extension Controller plug, with the notch on the bottom
-
-| EC Pin # | EC Position | EC Pin ID | Pin Function | FZ GPIO Pin Name | FZ GPIO Pin # |
-| :---: | :---: | :---: | :---: | :---: | :---: |
-| 1 | top-left | +3v3 | Power | 3v3 | 9 |
-| 2 | bottom-left | SCL | i2c clock | C0 | 16 |
-| 3 | top-centre | EN | ¿detect? | | |
-| 4 | bottom-centre | -x- | -none- | | |
-| 5 | top-right | SDA | i2c data | C1 | 15 |
-| 6 | bottom-right | Gnd | Power | Gnd | 18 |
-
-Keys:
-* Left - Show splash screen
-* Back - exit plugin
-
-The easiest way to connect a Wii Extension Controller to a FlipperZero is arguably with a ["WiiChuck"](https://www.ebay.co.uk/sch/?_nkw=wiichuck) or a ["Nunchucky"](https://www.solarbotics.com/product/31040)
-
-
-### ** WARNING **
-Neither the WiiChuck, nor the Nunchucky have a pin polarisation mechanism.
-If you plug the adaptor in the wrong way around you WILL apply voltage to the Controller the wrong way round!!
-I have no idea if THIS WILL PERMANENTLY KILL THE CONTROLLER ...Who wants to try it?
-
-On all the WiiChucks I have seen:
-* The WiiChuck has THREE connectors on one side, and TWO connectors on the other.
-* The side with TWO connectors should go against the side of the Controller plug with the big indent.
-```
-+-------------+
-| _________ |
-| | = = = | |
-| |_=_____=_| | <-- notice missing pin
-| ___ |
-| | | | <-- notice indent
-+----+ +----+
-```
-
-
-...BUT I *highly* recommend you check the pins on your adaptor to make sure everything goes well.
-
-I believe the unconnected pin on the top is a "presence detect" function, but I have not (yet) verified this.
-This feature is NOT required by this plugin, as the detection is performed by means of an i2c handshake.
-
-When a device is connected it will be immediately recognised. If it is not, either:
-* The Controller is not correctly connected
-...This may be as simple as a broken wire.
-* The controller board in the Controller is faulty.
-...Repair of which is beyond the scope of this document.
-
-To get the list of "known" Controllers, run `./info.sh`
-As of writing this, that returns:
-```c
-[PID_UNKNOWN ] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "Unknown Perhipheral", SCENE_DUMP,
-[PID_NUNCHUCK ] = { {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}, "Nunchuck", SCENE_NUNCHUCK,
-[PID_CLASSIC ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}, "Classic Controller", SCENE_CLASSIC,
-[PID_BALANCE ] = { {0x00, 0x00, 0xA4, 0x20, 0x04, 0x02}, "Balance Board", SCENE_DUMP,
-[PID_GH_GUITAR ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero Guitar", SCENE_DUMP,
-[PID_GH_DRUMS ] = { {0x01, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero World Tour Drums", SCENE_DUMP,
-[PID_TURNTABLE ] = { {0x03, 0x00, 0xA4, 0x20, 0x01, 0x03}, "DJ Hero Turntable", SCENE_DUMP,
-[PID_TAIKO_DRUMS] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x11}, "Taiko Drum Controller)", SCENE_DUMP,
-
-```
-
-You can see that there are EIGHT known devices. One is the default for an unknown controller; SEVEN devices are known by name; and TWO (of those seven) have bespoke "scenes" (ie. SCENE_NUNCHUCK & SCENE_CLASSIC).
-
-# Screen: NUNCHUCK - MAIN
-
-When you connect a Nunchuck, you will see a screen displaying:
-* Accelerometer{X,Y,Z} values
-* Joystick{X,Y} values
-* Joystick graphic
-* Button{C,Z}
-
-Keys:
-* Left - Go to the DUMP screen
-* Right - Go to the NUNCHUCK_ACC accelerometers screen
-* Up/Down/OK - [qv. Peak Meters]
-* Short-Back - Reset controller
-* Long-Back - Exit plugin
-
-# Screen: NUNCHUCK - ACCELEROMETERS
-
-
-
-| Axis | Movement | Lower | Higher |
-| :---: | :---: | :---: | :---: |
-| X | Left / Right | Left | Right |
-| Y | Fwd / Bkwd | Fwd | Bkwd |
-| Z | Down / Up | Down | Up |
-
-* Movement in the direction of an axis changes that axis reading
-* Twisting/tilting around an axis changes the other two readings
-* EG.
- * Move left (along the X axis) will effect X
- * Turn left (a rotation around the Y axis) will effect X and Z
-
-Keys:
-* Left - go to the main NUNCHUCK screen
-* Up
- * Auto-Pause Disabled --> Enable Auto-Pause
- * Paused at the end of a page --> Restart scanner
- * Running with Auto-Pause Enabled --> Disable Auto-Pause
-* Nunchuck-Z - Toggle pause
-* Nunchuck-C - Toggle auto-pause
-* Long-OK - Enter Software Calibration mode [qv. Calibration]
- * Calibration mode on the Accelerometer screen will ONLY calibrate the accelerometer
-* Short-OK - Leave Software Calibration mode *and* Calibrate CENTRE position(s)
-* Short-Back - Reset controller
-* Long-Back - Exit plugin
-
-NB. Code DOES exist to scroll the display, but the LCD refresh rate is too low, and it looks awful
-
-# Screen: CLASSIC
-
-When you connect a Classic Controller [Pro], you will see a screen displaying a Classic Controller
-* The Classic Controller will animate in line with controller events
-* The scan rate is set to 30fps, but in reality there is a bit of lag with the LCD screen, so YMMV.
-
-Keys:
-* Left - go to the DUMP screen
-* Right - show analogue readings (Left to hide them again)
-* Up/Down/OK - [qv. Peak Meters]
-* Short-Back - Reset controller
-* Long-Back - Exit plugin
-
-# Screen: DUMP
-
-The Dump screen will show you the raw readings from the device.
-If you connect a device which does not have a bespoke `_decode()` function (etc.), you will see (only) this screen.
-* SID - String ID - human-readable name (from the `info` table)
-* PID - Peripheral ID - The 6 bytes which identify the device.
-* Cal - Calibration data - 16 bytes
-* The bottom row of hex shows the SIX bytes of Controller data
- * Below each hex digit is the binary representation of that digit
- * By example. With a Nunchuck connected, click the Z button, and watch the bit on the far right
-
-Keys:
-* Right - return to controller-specific screen (if there is one)
-* Short-Back - Reset controller
-* Long-Back - Exit plugin
-
-# Peak Meters (Calibration values)
-
-On any Controller-specific screen with a Peak/Trough menu displayed:
-* Up - [toggle] only show peak values
-* Down - [toggle] only show trough values
-* Long-OK - Enter Software Calibration mode [qv. Calibration]
-* Short-OK - Leave Software Calibration mode / Calibrate CENTRE position(s)
-
-# Calibration
-
-
-* __This project handles Calibration of Analogue Controls, but has NO understanding of Accelerometer values (yet).__
-
-Digital buttons do NOT require Calibration.
-
-Some Calibration data is calculated at the factory, and stored in memory (¿OTP?) on the Controller.
-
-Each device has a different way to interpret the Calibration Data.
-EG. A Nunchuck has one joystick, and an accelerometer ...whereas a Classic Controller has 2 joysticks and 2 analogue buttons.
-
-I have personally found the calibration data to be inaccurate (when compared to actual readings), I guess Controllers drift over the years‽
-If the factory-values LIMIT movement, this is easily resolved - by expanding them on-the-fly.
-BUT, I have seen Controllers with factory calibration data that suggests the limits are FURTHER than the joystick can reach ...and this requires a full re-calibration of the Controller!
-
-Probably the best way to calibrate is to:
-* Take a/some reading(s) while the Controller is 'at rest', IE. perfectly still and level.
-* Move the Controller to all extremes and store the extreme {peak/trough} values.
-
-Nintendo (allegedly) take the 'at rest' reading immediately after the Controller is connected, and a 're-calibration' can be performed at any time by pressing {`A`, `B`, `+`, `-`} at the same time, for at least 3 seconds. Although I have no details on what this actually does.
-
-### This tool calibrates as such:
-* When the Controller is first recognised
- * The factory Calibration data is used to decide the Centre/Middle position and extreme values (eg. far-left & far-right) for each analogue Control
-* Long-OK button press (on the FlipperZero) ...Do NOT touch ANY of the analogue controllers while you are pressing Long-OK
- * Start the calibrate button flashing
- * Take the current reading as the Centre position
- * Set the range limits to "no range"
- * You must now move the Control between its extremes, so the code can work out the new Calibration/range/peak+trough values
- * When done, press Short-OK to end Software Calibration mode
-* Short-OK button press (on the FlipperZero) ...Do NOT touch ANY of the analogue controllers while you are pressing Short-OK
- * Stop the calibrate button flashing
- * Calibrate the centre position of all analogue controls (accelerometers not supported (yet))
-
-# Screen: DEBUG
-
-On any screen (except SPLASH) you may press Long-Down to enter Debug mode.
-
-You can (at any time) attach to the FlipperZero (via USB) with a serial console {`minicom`, `putty`, whatever} and start the `log` function to see the debug messages.
-
-When you enter the DEBUG screen, the real-time scanner will be stopped. And the following keys made available:
-* Up - Attempt to initialise the attached Controller
-* OK - Take a reading from the attached Controller
-* Long-Down - Restart the real-time scanner and return to the WAIT screen
-
-You can limit the messages at compile-time [see `./info.sh`], or at runtime [FZ->Settings->System->LogLevel]
-
-[This is probably irrelevant since the introduction of FAP support]
-If you have memory issues, limiting the messages at compile-time will make the plugin smaller.
-But (¿obviously?) the more you limit the messsages, the less debug information will be sent to the logger.
-
-# TODO
-
-* FZ Bug: At the time of writing this, there are problems with the i2c FZ functions [qv `i2c_workaround.c`]
-
diff --git a/applications/plugins/wii_ec_anal/README.txt b/applications/plugins/wii_ec_anal/README.txt
deleted file mode 100644
index e7ebe7a4c..000000000
--- a/applications/plugins/wii_ec_anal/README.txt
+++ /dev/null
@@ -1,67 +0,0 @@
- ,-------.
----( Files )---
- `-------'
-
- README.md - User Manual : Body [github markdown]
- _images/ - User Manual : Images
- _images/GIMP/ - User Manual : GIMP image masters
-
- LICENSE - Tech Docs : MIT Licence file
- README.txt - Tech Docs : Dev notes
- notes.txt - Tech Docs : Random dev notes
- info.sh - Tech Docs : Retrieve info from source code
-
- application.fam - FAP : Header file
- WiiEC.png - FAP : Icon {10x10}
-
- gfx/ - Analyser : Images [generated by bc_image_tool]
- wii_anal.c|h - Analyser : Main application
- wii_anal_ec.c|h - Analyser : Extension controller actions
- wii_anal_keys.c|h - Analyser : Keyboard handling
- wii_anal_lcd.c|h - Analyser : LCD handling
-
- i2c_workaround.h - Temporary workaround for i2c bug in FZ code
- err.h - Errors
- bc_logging.h - Logging macros - especially LOG_LEVEL
-
- wii_i2c.c|h - i2c functionality
-
- wii_ec.c|h - Extension Controller basic functions
- wii_ec_macros.h - Bespoke Extension Controller handy-dandy MACROs
- wii_ec_classic.c|h - EC: Classic Controller Pro scene
- wii_ec_nunchuck.c|h - EC: Nunchuck scene
- wii_ec_udraw.c|h - EC: UDraw scene - not written
-
- ,----------------------------------.
----( Adding a new Extension Controller )---
- `----------------------------------'
-
-//! I'll finish this when I write the UDraw code
-
-Create a new Extension Controller called "mydev"
-
-Create wii_ec_mydev.c and wii_ec_mydev.h
-
-In wii_ec_mydev.c|h
- Create the functions [& prototypes]
- bool mydev_init (wiiEC_t* const) ; // Additional initialisation code
- void mydev_decode (wiiEC_t* const) ; // Decode controller input data
- void mydev_msg (wiiEC_t* const, FuriMessageQueue* const) ; // Put event messages in the event queue
- void mydev_calib (wiiEC_t* const, ecCalib_t) ; // Controller calibration function
- void mydev_show (Canvas* const, state_t* const) ; // Scene LCD display
- bool mydev_key (const eventMsg_t* const, state_t* const) ; // Scene key controls
-
-In wii_ec.h
- Include the new header
- #include "wii_ec_mydev.h"
- Add a perhipheral id to enum ecPid
- PID_MYDEV
-
-In wii_anal.h
- As a scene name to enum scene
- SCENE_MYDEV
-
-In wii_ec.c
- Add the device definition to the ecId[] array
- [PID_MYDEV] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "My Device", SCENE_MYDEV,
- mydev_init, mydev_decode, mydev_msg, mydev_calib, mydev_show, mydev_key },
diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert.c b/applications/plugins/wii_ec_anal/_image_tool/_convert.c
index 57deeb083..267985e8d 100644
--- a/applications/plugins/wii_ec_anal/_image_tool/_convert.c
+++ b/applications/plugins/wii_ec_anal/_image_tool/_convert.c
@@ -3,146 +3,136 @@
#include
#include
-int main(int argc, char* argv[]) {
- const unsigned char* pp = NULL;
- uint32_t pix = 0;
- int bit = 0;
+int main (int argc, char* argv[])
+{
+ const unsigned char* pp = NULL;
+ uint32_t pix = 0;
+ int bit = 0;
- uint8_t b = 0;
- uint8_t bcnt = 0;
+ uint8_t b = 0;
+ uint8_t bcnt = 0;
- unsigned int lcnt = 0;
- static const int lmax = 16; // max hex values per line
+ unsigned int lcnt = 0;
+ static const int lmax = 16; // max hex values per line
- uint8_t* buf = NULL;
- uint8_t* bp = NULL;
- unsigned int blen = 0;
+ uint8_t* buf = NULL;
+ uint8_t* bp = NULL;
+ unsigned int blen = 0;
- uint8_t* cmp = NULL;
- uint8_t* cp = NULL;
- unsigned int clen = 0;
- uint8_t ctag = 0xFF;
- uint32_t tag[256] = {0};
- uint32_t tmax = UINT32_MAX;
+ uint8_t* cmp = NULL;
+ uint8_t* cp = NULL;
+ unsigned int clen = 0;
+ uint8_t ctag = 0xFF;
+ uint32_t tag[256] = {0};
+ uint32_t tmax = UINT32_MAX;
- unsigned int x, y, z;
+ unsigned int x, y, z;
- const char* name = argv[1];
- FILE* fh = fopen(argv[2], "wb");
+ const char* name = argv[1];
+ FILE* fh = fopen(argv[2], "wb");
- uint32_t white = 0xFF;
+ uint32_t white = 0xFF;
- int rv = 0; // assume success
+ int rv = 0; // assume success
- // allocate buffers
- blen = ((img.w * img.h) + 0x7) >> 3;
- bp = (buf = calloc(blen + 1, 1));
- cp = (cmp = calloc(blen + 4, 1));
+ // allocate buffers
+ blen = ((img.w * img.h) +0x7) >>3;
+ bp = (buf = calloc(blen +1, 1));
+ cp = (cmp = calloc(blen +4, 1));
- // sanity check
- if(!fh || !buf || !cmp) {
- printf("! fopen() or malloc() fail.\n");
- rv = 255;
- goto bail;
- }
+ // sanity check
+ if (!fh || !buf || !cmp) {
+ printf("! fopen() or malloc() fail.\n");
+ rv = 255;
+ goto bail;
+ }
- // Find white value
- for(x = 1; x < img.bpp; x++) white = (white << 8) | 0xFF;
+ // Find white value
+ for (x = 1; x < img.bpp; x++)
+ white = (white << 8) | 0xFF ;
- // build bit pattern
- // create the comment as we go
- for(pp = img.b, y = 0; y < img.h; y++) {
- fprintf(fh, "// ");
- for(x = 0; x < img.w; x++) {
- // read pixel
- for(pix = 0, z = 0; z < img.bpp; pix = (pix << 8) | *pp++, z++)
- ;
- // get bit and draw
- if(pix < white) {
- b = (b << 1) | 1;
- fprintf(fh, "##");
- } else {
- b <<= 1;
- fprintf(fh, "..");
- }
- // got byte
- if((++bcnt) == 8) {
- *bp++ = b;
- tag[b]++;
- bcnt = (b = 0);
- }
- }
- fprintf(fh, "\n");
- }
- fprintf(fh, "\n");
- // padding
- if(bcnt) {
- b <<= (bcnt = 8 - bcnt);
- *bp++ = b;
- tag[b]++;
- }
- // Kill the compression
- *bp = ~bp[-1]; // https://youtube.com/clip/Ugkx-JZIr16hETy7hz_H6yIdKPtxVe8C5w_V
+ // build bit pattern
+ // create the comment as we go
+ for (pp = img.b, y = 0; y < img.h; y++) {
+ fprintf(fh, "// ");
+ for (x = 0; x < img.w; x++) {
+ // read pixel
+ for (pix = 0, z = 0; z < img.bpp; pix = (pix << 8) | *pp++, z++) ;
+ // get bit and draw
+ if (pix < white) {
+ b = (b << 1) | 1;
+ fprintf(fh, "##");
+ } else {
+ b <<= 1;
+ fprintf(fh, "..");
+ }
+ // got byte
+ if ((++bcnt) == 8) {
+ *bp++ = b;
+ tag[b]++;
+ bcnt = (b = 0);
+ }
+ }
+ fprintf(fh, "\n");
+ }
+ fprintf(fh, "\n");
+ // padding
+ if (bcnt) {
+ b <<= (bcnt = 8 - bcnt);
+ *bp++ = b;
+ tag[b]++;
+ }
+ // Kill the compression
+ *bp = ~bp[-1]; // https://youtube.com/clip/Ugkx-JZIr16hETy7hz_H6yIdKPtxVe8C5w_V
- // Byte run length compression
- // Find a good tag
- for(x = 0; tmax && (x < 256); x++) {
- if(tag[x] < tmax) {
- tmax = tag[x];
- ctag = x;
- }
- }
+ // Byte run length compression
+ // Find a good tag
+ for (x = 0; tmax && (x < 256); x++) {
+ if (tag[x] < tmax) {
+ tmax = tag[x];
+ ctag = x;
+ }
+ }
- // compress the data
- for(bp = buf, x = 0; (clen < blen) && (x < blen); x++) {
- // need at least 4 the same to be worth it
- // must compress tag (if it occurs)
- if((bp[x] == bp[x + 1]) && (bp[x] == bp[x + 2]) && (bp[x] == bp[x + 3]) ||
- (bp[x] == ctag)) {
- for(y = 1; (y < 255) && (bp[x] == bp[x + y]); y++)
- ;
- *cp++ = ctag; // tag
- *cp++ = y; // length
- *cp++ = bp[x]; // byte
- x += y - 1;
- clen += 3;
- } else {
- *cp++ = bp[x];
- clen++;
- }
- }
+ // compress the data
+ for (bp = buf, x = 0; (clen < blen) && (x < blen); x++) {
+ // need at least 4 the same to be worth it
+ // must compress tag (if it occurs)
+ if ((bp[x] == bp[x+1]) && (bp[x] == bp[x+2]) && (bp[x] == bp[x+3]) || (bp[x] == ctag)) {
+ for (y = 1; (y < 255) && (bp[x] == bp[x+y]); y++) ;
+ *cp++ = ctag; // tag
+ *cp++ = y; // length
+ *cp++ = bp[x]; // byte
+ x += y -1;
+ clen += 3;
+ } else {
+ *cp++ = bp[x];
+ clen++;
+ }
+ }
- // create struct
- fprintf(fh, "#include \"images.h\"\n\n");
- fprintf(fh, "const image_t img_%s = { %d, %d, ", name, img.w, img.h);
+ // create struct
+ fprintf(fh, "#include \"images.h\"\n\n");
+ fprintf(fh, "const image_t img_%s = { %d, %d, ", name, img.w, img.h);
- if(clen < blen) { // dump compressed?
- fprintf(
- fh,
- "true, %d, 0x%02X, { // orig:%d, comp:%.2f%%\n\t",
- clen,
- ctag,
- blen,
- 100.0 - ((clen * 100.0) / blen));
- for(x = 0; x < clen; x++)
- if(x == clen - 1)
- fprintf(fh, "0x%02X\n}};\n", cmp[x]);
- else
- fprintf(fh, "0x%02X%s", cmp[x], (!((x + 1) % 16)) ? ",\n\t" : ", ");
+ if (clen < blen) { // dump compressed?
+ fprintf(fh, "true, %d, 0x%02X, { // orig:%d, comp:%.2f%%\n\t",
+ clen, ctag, blen, 100.0-((clen*100.0)/blen));
+ for (x = 0; x < clen; x++)
+ if (x == clen -1) fprintf(fh, "0x%02X\n}};\n", cmp[x]) ;
+ else fprintf(fh, "0x%02X%s", cmp[x], (!((x+1)%16)) ? ",\n\t" : ", ") ;
- } else { // dump UNcompressed
- fprintf(fh, "false, %d, 0, {\n\t", blen);
- for(x = 0; x < blen; x++)
- if(x == blen - 1)
- fprintf(fh, "0x%02X\n}};\n", buf[x]);
- else
- fprintf(fh, "0x%02X%s", buf[x], (!((x + 1) % 16)) ? ",\n\t" : ", ");
- }
+ } else { // dump UNcompressed
+ fprintf(fh, "false, %d, 0, {\n\t", blen);
+ for (x = 0; x < blen; x++)
+ if (x == blen -1) fprintf(fh, "0x%02X\n}};\n", buf[x]) ;
+ else fprintf(fh, "0x%02X%s", buf[x], (!((x+1)%16)) ? ",\n\t" : ", ") ;
+ }
bail:
- if(fh) fclose(fh);
- if(buf) free(buf);
- if(cmp) free(cmp);
+ if (fh) fclose(fh) ;
+ if (buf) free(buf) ;
+ if (cmp) free(cmp) ;
- return rv;
+ return rv;
}
diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c
index e8ab899f7..57046e9a3 100644
--- a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c
+++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.c
@@ -1,49 +1,55 @@
-#include // GUI (screen/keyboard) API
+#include // GUI (screen/keyboard) API
-#include "images.h"
+#include "images.h"
//----------------------------------------------------------------------------- ----------------------------------------
-static Canvas* _canvas;
-static uint8_t _tlx;
-static uint8_t _tly;
+static Canvas* _canvas;
+static uint8_t _tlx;
+static uint8_t _tly;
-static uint8_t _x;
-static uint8_t _y;
+static uint8_t _x;
+static uint8_t _y;
-static const image_t* _img;
+static const image_t* _img;
-static bool _blk;
-static Color _set;
-static Color _clr;
+static bool _blk;
+static Color _set;
+static Color _clr;
//+============================================================================
-static void _showByteSet(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if(b & m) // plot only SET bits
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteSet (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if (b & m) // plot only SET bits
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
-static void _showByteClr(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if(!(b & m)) // plot only CLR bits
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteClr (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if (!(b & m)) // plot only CLR bits
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
-static void _showByteAll(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if((!!(b & m)) ^ _blk) { // Change colour only when required
- canvas_set_color(_canvas, ((b & m) ? _set : _clr));
- _blk = !_blk;
- }
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteAll (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if ((!!(b & m)) ^ _blk) { // Change colour only when required
+ canvas_set_color(_canvas, ((b & m) ? _set : _clr));
+ _blk = !_blk;
+ }
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
@@ -55,83 +61,81 @@ static void _showByteAll(const uint8_t b) {
// SHOW_ALL - plot all images pixels as they are
// SHOW_ALL_INV - plot all images pixels inverted
//
-void show(
- Canvas* const canvas,
- const uint8_t tlx,
- const uint8_t tly,
- const image_t* img,
- const showMode_t mode) {
- void (*fnShow)(const uint8_t) = NULL;
+void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly,
+ const image_t* img, const showMode_t mode)
+{
+ void(*fnShow)(const uint8_t) = NULL;
- const uint8_t* bp = img->data;
+ const uint8_t* bp = img->data;
- // code size optimisation
- switch(mode & SHOW_INV_) {
- case SHOW_NRM_:
- _set = ColorBlack;
- _clr = ColorWhite;
- break;
+ // code size optimisation
+ switch (mode & SHOW_INV_) {
+ case SHOW_NRM_:
+ _set = ColorBlack;
+ _clr = ColorWhite;
+ break;
- case SHOW_INV_:
- _set = ColorWhite;
- _clr = ColorBlack;
- break;
+ case SHOW_INV_:
+ _set = ColorWhite;
+ _clr = ColorBlack;
+ break;
- case SHOW_BLK_:
- canvas_set_color(canvas, ColorBlack);
- break;
+ case SHOW_BLK_:
+ canvas_set_color(canvas, ColorBlack);
+ break;
- case SHOW_WHT_:
- canvas_set_color(canvas, ColorWhite);
- break;
- }
- switch(mode & SHOW_INV_) {
- case SHOW_NRM_:
- case SHOW_INV_:
- fnShow = _showByteAll;
- canvas_set_color(canvas, ColorWhite);
- _blk = 0;
- break;
+ case SHOW_WHT_:
+ canvas_set_color(canvas, ColorWhite);
+ break;
- case SHOW_BLK_:
- case SHOW_WHT_:
- switch(mode & SHOW_ALL_) {
- case SHOW_SET_:
- fnShow = _showByteSet;
- break;
- case SHOW_CLR_:
- fnShow = _showByteClr;
- break;
- }
- break;
- }
- furi_check(fnShow);
+ }
+ switch (mode & SHOW_INV_) {
+ case SHOW_NRM_:
+ case SHOW_INV_:
+ fnShow = _showByteAll;
+ canvas_set_color(canvas, ColorWhite);
+ _blk = 0;
+ break;
- // I want nested functions!
- _canvas = canvas;
- _img = img;
- _tlx = tlx;
- _tly = tly;
- _x = 0;
- _y = 0;
+ case SHOW_BLK_:
+ case SHOW_WHT_:
+ switch (mode & SHOW_ALL_) {
+ case SHOW_SET_:
+ fnShow = _showByteSet;
+ break;
+ case SHOW_CLR_:
+ fnShow = _showByteClr;
+ break;
+ }
+ break;
+ }
+ furi_check(fnShow);
- // Compressed
- if(img->c) {
- for(unsigned int i = 0; i < img->len; i++, bp++) {
- // Compressed data? {tag, length, value}
- if(*bp == img->tag) {
- for(uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]);
- bp += 3 - 1;
- i += 3 - 1;
+ // I want nested functions!
+ _canvas = canvas;
+ _img = img;
+ _tlx = tlx;
+ _tly = tly;
+ _x = 0;
+ _y = 0;
- // Uncompressed byte
- } else {
- fnShow(*bp);
- }
- }
+ // Compressed
+ if (img->c) {
+ for (unsigned int i = 0; i < img->len; i++, bp++) {
+ // Compressed data? {tag, length, value}
+ if (*bp == img->tag) {
+ for (uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]) ;
+ bp += 3 -1;
+ i += 3 -1;
- // Not compressed
- } else {
- for(unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp);
- }
+ // Uncompressed byte
+ } else {
+ fnShow(*bp);
+ }
+ }
+
+ // Not compressed
+ } else {
+ for (unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp) ;
+ }
}
diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h
index 1743cb409..bfc44568e 100644
--- a/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h
+++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_images.h
@@ -1,53 +1,53 @@
-#ifndef IMAGES_H_
-#define IMAGES_H_
+#ifndef IMAGES_H_
+#define IMAGES_H_
#include
#include
//----------------------------------------------------------------------------- ----------------------------------------
-typedef enum showMode {
- // {INV:--:WHT:BLK::--:--:CLR:SET}
- SHOW_SET_ = 0x01,
- SHOW_CLR_ = 0x02,
- SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_,
+typedef
+ enum showMode {
+ // {INV:--:WHT:BLK::--:--:CLR:SET}
+ SHOW_SET_ = 0x01,
+ SHOW_CLR_ = 0x02,
+ SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_,
- SHOW_BLK_ = 0x10,
- SHOW_WHT_ = 0x20,
- SHOW_NRM_ = 0x00,
- SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_,
+ SHOW_BLK_ = 0x10,
+ SHOW_WHT_ = 0x20,
+ SHOW_NRM_ = 0x00,
+ SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_,
- SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_,
- SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_,
+ SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_,
+ SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_,
- SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_,
- SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_,
+ SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_,
+ SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_,
- SHOW_ALL = SHOW_ALL_ | SHOW_NRM_,
- SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_,
-} showMode_t;
+ SHOW_ALL = SHOW_ALL_ | SHOW_NRM_,
+ SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_,
+ }
+showMode_t;
//----------------------------------------------------------------------------- ----------------------------------------
-typedef struct image {
- uint8_t w; // width
- uint8_t h; // height
- bool c; // compressed?
- uint16_t len; // image data length
- uint8_t tag; // rle tag
- uint8_t data[]; // image data
-} image_t;
+typedef
+ struct image {
+ uint8_t w; // width
+ uint8_t h; // height
+ bool c; // compressed?
+ uint16_t len; // image data length
+ uint8_t tag; // rle tag
+ uint8_t data[]; // image data
+ }
+image_t;
//----------------------------------------------------------------------------- ----------------------------------------
//[TAG]
//----------------------------------------------------------------------------- ----------------------------------------
#ifndef IMGTEST
-#include
-void show(
- Canvas* const canvas,
- const uint8_t tlx,
- const uint8_t tly,
- const image_t* img,
- const showMode_t mode);
+# include
+ void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly,
+ const image_t* img, const showMode_t mode) ;
#endif
#endif //IMAGES_H_
diff --git a/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c b/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c
index fdc2ee946..4bdb531d5 100644
--- a/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c
+++ b/applications/plugins/wii_ec_anal/_image_tool/_convert_test.c
@@ -1,59 +1,59 @@
-#include
-#include
+#include
+#include
-#include "images.h"
+#include "images.h"
//-----------------------------------------------------------------------------
// This will be the plot function out of your graphics library
//
-#define PLOT(x, y, c) \
- do { \
- printf("%s", (c ? "#" : ".")); \
- if(x == img->w - 1) printf("\n"); \
- } while(0)
+#define PLOT(x,y,c) do { \
+ printf("%s", (c ? "#" : ".")); \
+ if (x == img->w -1) printf("\n") ; \
+}while(0)
//+============================================================================
// The pain we endure to avoid code duplication cleanly
//
-#define PLOTBYTE(b) \
- do { \
- for(uint8_t m = 0x80; m; m >>= 1) { \
- PLOT(x, y, (b & m)); \
- if(((++x) == img->w) && !(x = 0) && ((++y) == img->h)) break; \
- } \
- } while(0)
+#define PLOTBYTE(b) do { \
+ for (uint8_t m = 0x80; m; m>>=1) { \
+ PLOT(x,y, (b & m)); \
+ if ( ((++x) == img->w) && !(x = 0) && ((++y) == img->h) ) break ; \
+ } \
+}while(0)
-void show(const image_t* img) {
- // Some variables
- const uint8_t* bp = img->data;
- unsigned int x = 0;
- unsigned int y = 0;
+void show (const image_t* img)
+{
+ // Some variables
+ const uint8_t* bp = img->data;
+ unsigned int x = 0;
+ unsigned int y = 0;
- // Compressed
- if(img->c) {
- for(unsigned int i = 0; i < img->len; i++, bp++) {
- // Compressed data? {tag, length, value}
- if(*bp == img->tag) {
- for(uint16_t c = 0; c < bp[1]; c++) PLOTBYTE(bp[2]);
- bp += 3 - 1;
- i += 3 - 1;
+ // Compressed
+ if (img->c) {
+ for (unsigned int i = 0; i < img->len; i++, bp++) {
+ // Compressed data? {tag, length, value}
+ if (*bp == img->tag) {
+ for (uint16_t c = 0; c < bp[1]; c++) PLOTBYTE(bp[2]) ;
+ bp += 3 -1;
+ i += 3 -1;
- // Uncompressed byte
- } else {
- PLOTBYTE(*bp);
- }
- }
+ // Uncompressed byte
+ } else {
+ PLOTBYTE(*bp);
+ }
+ }
- // Not compressed
- } else {
- for(unsigned int i = 0; i < img->len; i++, bp++) PLOTBYTE(*bp);
- }
+ // Not compressed
+ } else {
+ for (unsigned int i = 0; i < img->len; i++, bp++) PLOTBYTE(*bp) ;
+ }
}
-#undef PLOTBYTE
+#undef PLOTBYTE
//+============================================================================
-int main(void) {
- show(&img_zzz);
- return 0;
+int main (void)
+{
+ show(&img_zzz);
+ return 0;
}
diff --git a/applications/plugins/wii_ec_anal/application.fam b/applications/plugins/wii_ec_anal/application.fam
index 42ed7e979..655b5f938 100644
--- a/applications/plugins/wii_ec_anal/application.fam
+++ b/applications/plugins/wii_ec_anal/application.fam
@@ -2,7 +2,7 @@
App(
# --- App Info
- appid="Wii_EC_Analyser",
+ appid="wii_ec_anal",
name="Wii EC Analyser",
# --- Entry point
@@ -32,5 +32,5 @@ App(
# fap_version=(1,0),
fap_icon="WiiEC.png",
- fap_category="Misc",
+ fap_category="GPIO",
)
diff --git a/applications/plugins/wii_ec_anal/bc_logging.h b/applications/plugins/wii_ec_anal/bc_logging.h
index 73dda80bd..d9bb48c92 100644
--- a/applications/plugins/wii_ec_anal/bc_logging.h
+++ b/applications/plugins/wii_ec_anal/bc_logging.h
@@ -1,13 +1,13 @@
-#ifndef BC_LOGGING_H_
-#define BC_LOGGING_H_
+#ifndef BC_LOGGING_H_
+#define BC_LOGGING_H_
#include
-#include "err.h" // appName
+#include "err.h" // appName
//! WARNING: There is a bug in Furi such that if you crank LOG_LEVEL up to 6=TRACE
//! AND you have menu->settings->system->logLevel = trace
//! THEN this program will cause the FZ to crash when the plugin exits!
-#define LOG_LEVEL 4
+#define LOG_LEVEL 4
//----------------------------------------------------------------------------- ----------------------------------------
// The FlipperZero Settings->System menu allows you to set the logging level at RUN-time
@@ -27,44 +27,44 @@
// The FlipperZero Settings->System menu allows you to set the logging level at RUN-time
// This lets you limit it at COMPILE-time
#ifndef LOG_LEVEL
-#define LOG_LEVEL 6 // default = full logging
+# define LOG_LEVEL 6 // default = full logging
#endif
-#if(LOG_LEVEL < 2)
-#undef FURI_LOG_E
-#define FURI_LOG_E(tag, fmt, ...)
+#if (LOG_LEVEL < 2)
+# undef FURI_LOG_E
+# define FURI_LOG_E(tag, fmt, ...)
#endif
-#if(LOG_LEVEL < 3)
-#undef FURI_LOG_W
-#define FURI_LOG_W(tag, fmt, ...)
+#if (LOG_LEVEL < 3)
+# undef FURI_LOG_W
+# define FURI_LOG_W(tag, fmt, ...)
#endif
-#if(LOG_LEVEL < 4)
-#undef FURI_LOG_I
-#define FURI_LOG_I(tag, fmt, ...)
+#if (LOG_LEVEL < 4)
+# undef FURI_LOG_I
+# define FURI_LOG_I(tag, fmt, ...)
#endif
-#if(LOG_LEVEL < 5)
-#undef FURI_LOG_D
-#define FURI_LOG_D(tag, fmt, ...)
+#if (LOG_LEVEL < 5)
+# undef FURI_LOG_D
+# define FURI_LOG_D(tag, fmt, ...)
#endif
-#if(LOG_LEVEL < 6)
-#undef FURI_LOG_T
-#define FURI_LOG_T(tag, fmt, ...)
+#if (LOG_LEVEL < 6)
+# undef FURI_LOG_T
+# define FURI_LOG_T(tag, fmt, ...)
#endif
//----------------------------------------------------------
// Logging helper macros
//
-#define ERROR(fmt, ...) FURI_LOG_E(appName, fmt __VA_OPT__(, ) __VA_ARGS__)
-#define WARN(fmt, ...) FURI_LOG_W(appName, fmt __VA_OPT__(, ) __VA_ARGS__)
-#define INFO(fmt, ...) FURI_LOG_I(appName, fmt __VA_OPT__(, ) __VA_ARGS__)
-#define DEBUG(fmt, ...) FURI_LOG_D(appName, fmt __VA_OPT__(, ) __VA_ARGS__)
-#define TRACE(fmt, ...) FURI_LOG_T(appName, fmt __VA_OPT__(, ) __VA_ARGS__)
+#define ERROR(fmt, ...) FURI_LOG_E(appName, fmt __VA_OPT__(,) __VA_ARGS__)
+#define WARN(fmt, ...) FURI_LOG_W(appName, fmt __VA_OPT__(,) __VA_ARGS__)
+#define INFO(fmt, ...) FURI_LOG_I(appName, fmt __VA_OPT__(,) __VA_ARGS__)
+#define DEBUG(fmt, ...) FURI_LOG_D(appName, fmt __VA_OPT__(,) __VA_ARGS__)
+#define TRACE(fmt, ...) FURI_LOG_T(appName, fmt __VA_OPT__(,) __VA_ARGS__)
-#define ENTER TRACE("(+) %s", __func__)
-#define LEAVE TRACE("(-) %s", __func__)
+#define ENTER TRACE("(+) %s", __func__)
+#define LEAVE TRACE("(-) %s", __func__)
#endif //BC_LOGGING_H_
diff --git a/applications/plugins/wii_ec_anal/err.h b/applications/plugins/wii_ec_anal/err.h
index 5a25c93f8..9398a3fb8 100644
--- a/applications/plugins/wii_ec_anal/err.h
+++ b/applications/plugins/wii_ec_anal/err.h
@@ -1,11 +1,11 @@
// Avoid circular/nested/mulitple inclusion
-#ifndef ERR_H_
-#define ERR_H_
+#ifndef ERR_H_
+#define ERR_H_
//----------------------------------------------------------------------------- ----------------------------------------
// Application name
//
-static const char* const appName = "Wii_i2c"; //$ Name used in log files
+static const char* const appName = "Wii_i2c"; //$ Name used in log files
//----------------------------------------------------------------------------- ----------------------------------------
// Error codes and messages
@@ -13,60 +13,57 @@ static const char* const appName = "Wii_i2c"; //$ Name used in log files
// You should only ever (need to) edit this list
// ...Watch out for extraneous whitespace after the terminating backslashes
-#define FOREACH_ES(esPrial) \
- /* The first line MUST define 'ERR_OK = 0' */ \
- esPrial(0, ERR_OK, "OK (no error)") \
- \
- esPrial(1, ERR_MALLOC_QUEUE, "malloc() fail - queue") esPrial( \
- 2, \
- ERR_MALLOC_STATE, \
- "malloc() fail - state") esPrial(3, ERR_MALLOC_TEXT, "malloc() fail - text") \
- esPrial(4, ERR_MALLOC_VIEW, "malloc() fail - viewport") esPrial( \
- 5, ERR_NO_MUTEX, "Cannot create mutex") esPrial(6, ERR_NO_GUI, "Cannot open GUI") \
- esPrial(7, ERR_NO_TIMER, "Cannot create timer") esPrial( \
- 8, ERR_NO_NOTIFY, "Cannot acquire notifications handle") \
- \
- esPrial(10, ERR_MUTEX_BLOCK, "Mutex block failed") esPrial( \
- 11, ERR_MUTEX_RELEASE, "Mutex release failed") \
- \
- esPrial(20, ERR_QUEUE_RTOS, "queue - Undefined RTOS error") \
- esPrial(21, DEBUG_QUEUE_TIMEOUT, "queue - Timeout") esPrial( \
- 22, ERR_QUEUE_RESOURCE, "queue - Resource not available") \
- esPrial(23, ERR_QUEUE_BADPRM, "queue - Bad parameter") esPrial( \
- 24, ERR_QUEUE_NOMEM, "queue - Out of memory") \
- esPrial(25, ERR_QUEUE_ISR, "queue - Banned in ISR") esPrial( \
- 26, ERR_QUEUE_UNK, "queue - Unknown") \
- \
- esPrial(30, WARN_SCAN_START, "Scan - Already started") \
- esPrial(31, WARN_SCAN_STOP, "Scan - Already stopped") \
- esPrial( \
- 32, \
- ERR_TIMER_START, \
- "Scan - Cannot start timer") \
- esPrial( \
- 33, \
- ERR_TIMER_STOP, \
- "Scan - Cannot stop timer") //[EOT]
+#define FOREACH_ES(esPrial) \
+ /* The first line MUST define 'ERR_OK = 0' */ \
+ esPrial( 0, ERR_OK , "OK (no error)") \
+\
+ esPrial( 1, ERR_MALLOC_QUEUE , "malloc() fail - queue") \
+ esPrial( 2, ERR_MALLOC_STATE , "malloc() fail - state") \
+ esPrial( 3, ERR_MALLOC_TEXT , "malloc() fail - text") \
+ esPrial( 4, ERR_MALLOC_VIEW , "malloc() fail - viewport") \
+ esPrial( 5, ERR_NO_MUTEX , "Cannot create mutex") \
+ esPrial( 6, ERR_NO_GUI , "Cannot open GUI") \
+ esPrial( 7, ERR_NO_TIMER , "Cannot create timer") \
+ esPrial( 8, ERR_NO_NOTIFY , "Cannot acquire notifications handle") \
+\
+ esPrial(10, ERR_MUTEX_BLOCK , "Mutex block failed") \
+ esPrial(11, ERR_MUTEX_RELEASE , "Mutex release failed") \
+\
+ esPrial(20, ERR_QUEUE_RTOS , "queue - Undefined RTOS error") \
+ esPrial(21, DEBUG_QUEUE_TIMEOUT, "queue - Timeout") \
+ esPrial(22, ERR_QUEUE_RESOURCE , "queue - Resource not available") \
+ esPrial(23, ERR_QUEUE_BADPRM , "queue - Bad parameter") \
+ esPrial(24, ERR_QUEUE_NOMEM , "queue - Out of memory") \
+ esPrial(25, ERR_QUEUE_ISR , "queue - Banned in ISR") \
+ esPrial(26, ERR_QUEUE_UNK , "queue - Unknown") \
+\
+ esPrial(30, WARN_SCAN_START , "Scan - Already started") \
+ esPrial(31, WARN_SCAN_STOP , "Scan - Already stopped") \
+ esPrial(32, ERR_TIMER_START , "Scan - Cannot start timer") \
+ esPrial(33, ERR_TIMER_STOP , "Scan - Cannot stop timer") \
+//[EOT]
// Declare list extraction macros
-#define ES_ENUM(num, ename, string) ename = num,
-#define ES_STRING(num, ename, string) string "\r\n",
+#define ES_ENUM(num, ename, string) ename = num,
+#define ES_STRING(num, ename, string) string"\r\n",
// Build the enum
-typedef enum err { FOREACH_ES(ES_ENUM) } err_t;
+typedef
+ enum err { FOREACH_ES(ES_ENUM) }
+err_t ;
// You need to '#define ERR_C_' in precisely ONE source file
#ifdef ERR_C_
-// Build the string list
-const char* const wii_errs[] = {FOREACH_ES(ES_STRING)};
+ // Build the string list
+ const char* const wii_errs[] = { FOREACH_ES(ES_STRING) };
#else
-// Give access to string list
-extern const char* const wii_errs[];
+ // Give access to string list
+ extern const char* const wii_errs[];
#endif
// This is a header file, clean up
-#undef ES_ENUM
-#undef ES_STRING
-#undef FOREACH_ES
+#undef ES_ENUM
+#undef ES_STRING
+#undef FOREACH_ES
#endif // ERR_H_
diff --git a/applications/plugins/wii_ec_anal/gfx/images.c b/applications/plugins/wii_ec_anal/gfx/images.c
index e8ab899f7..57046e9a3 100644
--- a/applications/plugins/wii_ec_anal/gfx/images.c
+++ b/applications/plugins/wii_ec_anal/gfx/images.c
@@ -1,49 +1,55 @@
-#include // GUI (screen/keyboard) API
+#include // GUI (screen/keyboard) API
-#include "images.h"
+#include "images.h"
//----------------------------------------------------------------------------- ----------------------------------------
-static Canvas* _canvas;
-static uint8_t _tlx;
-static uint8_t _tly;
+static Canvas* _canvas;
+static uint8_t _tlx;
+static uint8_t _tly;
-static uint8_t _x;
-static uint8_t _y;
+static uint8_t _x;
+static uint8_t _y;
-static const image_t* _img;
+static const image_t* _img;
-static bool _blk;
-static Color _set;
-static Color _clr;
+static bool _blk;
+static Color _set;
+static Color _clr;
//+============================================================================
-static void _showByteSet(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if(b & m) // plot only SET bits
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteSet (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if (b & m) // plot only SET bits
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
-static void _showByteClr(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if(!(b & m)) // plot only CLR bits
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteClr (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if (!(b & m)) // plot only CLR bits
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
-static void _showByteAll(const uint8_t b) {
- for(uint8_t m = 0x80; m; m >>= 1) {
- if((!!(b & m)) ^ _blk) { // Change colour only when required
- canvas_set_color(_canvas, ((b & m) ? _set : _clr));
- _blk = !_blk;
- }
- canvas_draw_dot(_canvas, (_tlx + _x), (_tly + _y));
- if(((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h)) break;
- }
+static
+void _showByteAll (const uint8_t b)
+{
+ for (uint8_t m = 0x80; m; m >>= 1) {
+ if ((!!(b & m)) ^ _blk) { // Change colour only when required
+ canvas_set_color(_canvas, ((b & m) ? _set : _clr));
+ _blk = !_blk;
+ }
+ canvas_draw_dot(_canvas, (_tlx +_x), (_tly +_y)) ;
+ if ( ((++_x) == _img->w) && !(_x = 0) && ((++_y) == _img->h) ) break ;
+ }
}
//+============================================================================
@@ -55,83 +61,81 @@ static void _showByteAll(const uint8_t b) {
// SHOW_ALL - plot all images pixels as they are
// SHOW_ALL_INV - plot all images pixels inverted
//
-void show(
- Canvas* const canvas,
- const uint8_t tlx,
- const uint8_t tly,
- const image_t* img,
- const showMode_t mode) {
- void (*fnShow)(const uint8_t) = NULL;
+void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly,
+ const image_t* img, const showMode_t mode)
+{
+ void(*fnShow)(const uint8_t) = NULL;
- const uint8_t* bp = img->data;
+ const uint8_t* bp = img->data;
- // code size optimisation
- switch(mode & SHOW_INV_) {
- case SHOW_NRM_:
- _set = ColorBlack;
- _clr = ColorWhite;
- break;
+ // code size optimisation
+ switch (mode & SHOW_INV_) {
+ case SHOW_NRM_:
+ _set = ColorBlack;
+ _clr = ColorWhite;
+ break;
- case SHOW_INV_:
- _set = ColorWhite;
- _clr = ColorBlack;
- break;
+ case SHOW_INV_:
+ _set = ColorWhite;
+ _clr = ColorBlack;
+ break;
- case SHOW_BLK_:
- canvas_set_color(canvas, ColorBlack);
- break;
+ case SHOW_BLK_:
+ canvas_set_color(canvas, ColorBlack);
+ break;
- case SHOW_WHT_:
- canvas_set_color(canvas, ColorWhite);
- break;
- }
- switch(mode & SHOW_INV_) {
- case SHOW_NRM_:
- case SHOW_INV_:
- fnShow = _showByteAll;
- canvas_set_color(canvas, ColorWhite);
- _blk = 0;
- break;
+ case SHOW_WHT_:
+ canvas_set_color(canvas, ColorWhite);
+ break;
- case SHOW_BLK_:
- case SHOW_WHT_:
- switch(mode & SHOW_ALL_) {
- case SHOW_SET_:
- fnShow = _showByteSet;
- break;
- case SHOW_CLR_:
- fnShow = _showByteClr;
- break;
- }
- break;
- }
- furi_check(fnShow);
+ }
+ switch (mode & SHOW_INV_) {
+ case SHOW_NRM_:
+ case SHOW_INV_:
+ fnShow = _showByteAll;
+ canvas_set_color(canvas, ColorWhite);
+ _blk = 0;
+ break;
- // I want nested functions!
- _canvas = canvas;
- _img = img;
- _tlx = tlx;
- _tly = tly;
- _x = 0;
- _y = 0;
+ case SHOW_BLK_:
+ case SHOW_WHT_:
+ switch (mode & SHOW_ALL_) {
+ case SHOW_SET_:
+ fnShow = _showByteSet;
+ break;
+ case SHOW_CLR_:
+ fnShow = _showByteClr;
+ break;
+ }
+ break;
+ }
+ furi_check(fnShow);
- // Compressed
- if(img->c) {
- for(unsigned int i = 0; i < img->len; i++, bp++) {
- // Compressed data? {tag, length, value}
- if(*bp == img->tag) {
- for(uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]);
- bp += 3 - 1;
- i += 3 - 1;
+ // I want nested functions!
+ _canvas = canvas;
+ _img = img;
+ _tlx = tlx;
+ _tly = tly;
+ _x = 0;
+ _y = 0;
- // Uncompressed byte
- } else {
- fnShow(*bp);
- }
- }
+ // Compressed
+ if (img->c) {
+ for (unsigned int i = 0; i < img->len; i++, bp++) {
+ // Compressed data? {tag, length, value}
+ if (*bp == img->tag) {
+ for (uint16_t c = 0; c < bp[1]; c++) fnShow(bp[2]) ;
+ bp += 3 -1;
+ i += 3 -1;
- // Not compressed
- } else {
- for(unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp);
- }
+ // Uncompressed byte
+ } else {
+ fnShow(*bp);
+ }
+ }
+
+ // Not compressed
+ } else {
+ for (unsigned int i = 0; i < img->len; i++, bp++) fnShow(*bp) ;
+ }
}
diff --git a/applications/plugins/wii_ec_anal/gfx/images.h b/applications/plugins/wii_ec_anal/gfx/images.h
index d21909176..87f2b89b7 100644
--- a/applications/plugins/wii_ec_anal/gfx/images.h
+++ b/applications/plugins/wii_ec_anal/gfx/images.h
@@ -1,134 +1,134 @@
-#ifndef IMAGES_H_
-#define IMAGES_H_
+#ifndef IMAGES_H_
+#define IMAGES_H_
#include
#include
//----------------------------------------------------------------------------- ----------------------------------------
-typedef enum showMode {
- // {INV:--:WHT:BLK::--:--:CLR:SET}
- SHOW_SET_ = 0x01,
- SHOW_CLR_ = 0x02,
- SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_,
+typedef
+ enum showMode {
+ // {INV:--:WHT:BLK::--:--:CLR:SET}
+ SHOW_SET_ = 0x01,
+ SHOW_CLR_ = 0x02,
+ SHOW_ALL_ = SHOW_SET_ | SHOW_CLR_,
- SHOW_BLK_ = 0x10,
- SHOW_WHT_ = 0x20,
- SHOW_NRM_ = 0x00,
- SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_,
+ SHOW_BLK_ = 0x10,
+ SHOW_WHT_ = 0x20,
+ SHOW_NRM_ = 0x00,
+ SHOW_INV_ = SHOW_BLK_ | SHOW_WHT_,
- SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_,
- SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_,
+ SHOW_SET_BLK = SHOW_SET_ | SHOW_BLK_,
+ SHOW_SET_WHT = SHOW_SET_ | SHOW_WHT_,
- SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_,
- SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_,
+ SHOW_CLR_BLK = SHOW_CLR_ | SHOW_BLK_,
+ SHOW_CLR_WHT = SHOW_CLR_ | SHOW_WHT_,
- SHOW_ALL = SHOW_ALL_ | SHOW_NRM_,
- SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_,
-} showMode_t;
+ SHOW_ALL = SHOW_ALL_ | SHOW_NRM_,
+ SHOW_ALL_INV = SHOW_ALL_ | SHOW_INV_,
+ }
+showMode_t;
//----------------------------------------------------------------------------- ----------------------------------------
-typedef struct image {
- uint8_t w; // width
- uint8_t h; // height
- bool c; // compressed?
- uint16_t len; // image data length
- uint8_t tag; // rle tag
- uint8_t data[]; // image data
-} image_t;
+typedef
+ struct image {
+ uint8_t w; // width
+ uint8_t h; // height
+ bool c; // compressed?
+ uint16_t len; // image data length
+ uint8_t tag; // rle tag
+ uint8_t data[]; // image data
+ }
+image_t;
//----------------------------------------------------------------------------- ----------------------------------------
//[TAG]
-extern const image_t img_csLogo_Small;
-extern const image_t img_3x5_v;
-extern const image_t img_3x5_9;
-extern const image_t img_3x5_8;
-extern const image_t img_3x5_7;
-extern const image_t img_3x5_6;
-extern const image_t img_3x5_5;
-extern const image_t img_3x5_4;
-extern const image_t img_3x5_3;
-extern const image_t img_3x5_2;
-extern const image_t img_3x5_1;
-extern const image_t img_3x5_0;
-extern const image_t img_key_Ui;
-extern const image_t img_key_OKi;
-extern const image_t img_RIP;
-extern const image_t img_cc_trg_R4;
-extern const image_t img_cc_trg_R3;
-extern const image_t img_cc_trg_R2;
-extern const image_t img_cc_trg_R1;
-extern const image_t img_cc_trg_L4;
-extern const image_t img_cc_trg_L3;
-extern const image_t img_cc_trg_L2;
-extern const image_t img_cc_trg_L1;
-extern const image_t img_cc_Joy;
-extern const image_t img_cc_Main;
-extern const image_t img_cc_Cable;
-extern const image_t img_key_Back;
-extern const image_t img_key_OK;
-extern const image_t img_6x8_Z;
-extern const image_t img_6x8_Y;
-extern const image_t img_6x8_X;
-extern const image_t img_key_U;
-extern const image_t img_key_D;
-extern const image_t img_csLogo_FULL;
-extern const image_t img_6x8_7;
-extern const image_t img_key_R;
-extern const image_t img_key_L;
-extern const image_t img_5x7_7;
-extern const image_t img_5x7_F;
-extern const image_t img_5x7_E;
-extern const image_t img_5x7_D;
-extern const image_t img_5x7_C;
-extern const image_t img_5x7_B;
-extern const image_t img_5x7_A;
-extern const image_t img_5x7_9;
-extern const image_t img_5x7_8;
-extern const image_t img_5x7_6;
-extern const image_t img_5x7_5;
-extern const image_t img_5x7_4;
-extern const image_t img_5x7_3;
-extern const image_t img_5x7_2;
-extern const image_t img_5x7_1;
-extern const image_t img_5x7_0;
-extern const image_t img_6x8_v;
-extern const image_t img_6x8_n;
-extern const image_t img_6x8_G;
-extern const image_t img_6x8_F;
-extern const image_t img_6x8_E;
-extern const image_t img_6x8_d;
-extern const image_t img_6x8_C;
-extern const image_t img_6x8_B;
-extern const image_t img_6x8_A;
-extern const image_t img_6x8_9;
-extern const image_t img_6x8_8;
-extern const image_t img_6x8_6;
-extern const image_t img_6x8_5;
-extern const image_t img_6x8_4;
-extern const image_t img_6x8_3;
-extern const image_t img_6x8_2;
-extern const image_t img_6x8_1;
-extern const image_t img_6x8_0;
-extern const image_t img_ecp_SDA;
-extern const image_t img_ecp_SCL;
-extern const image_t img_ecp_port;
-extern const image_t img_cc_pad_UD1;
-extern const image_t img_cc_pad_LR1;
-extern const image_t img_cc_btn_Y1;
-extern const image_t img_cc_btn_X1;
-extern const image_t img_cc_btn_B1;
-extern const image_t img_cc_btn_A1;
-extern const image_t img_6x8_D;
+extern const image_t img_csLogo_Small;
+extern const image_t img_3x5_v;
+extern const image_t img_3x5_9;
+extern const image_t img_3x5_8;
+extern const image_t img_3x5_7;
+extern const image_t img_3x5_6;
+extern const image_t img_3x5_5;
+extern const image_t img_3x5_4;
+extern const image_t img_3x5_3;
+extern const image_t img_3x5_2;
+extern const image_t img_3x5_1;
+extern const image_t img_3x5_0;
+extern const image_t img_key_Ui;
+extern const image_t img_key_OKi;
+extern const image_t img_RIP;
+extern const image_t img_cc_trg_R4;
+extern const image_t img_cc_trg_R3;
+extern const image_t img_cc_trg_R2;
+extern const image_t img_cc_trg_R1;
+extern const image_t img_cc_trg_L4;
+extern const image_t img_cc_trg_L3;
+extern const image_t img_cc_trg_L2;
+extern const image_t img_cc_trg_L1;
+extern const image_t img_cc_Joy;
+extern const image_t img_cc_Main;
+extern const image_t img_cc_Cable;
+extern const image_t img_key_Back;
+extern const image_t img_key_OK;
+extern const image_t img_6x8_Z;
+extern const image_t img_6x8_Y;
+extern const image_t img_6x8_X;
+extern const image_t img_key_U;
+extern const image_t img_key_D;
+extern const image_t img_csLogo_FULL;
+extern const image_t img_6x8_7;
+extern const image_t img_key_R;
+extern const image_t img_key_L;
+extern const image_t img_5x7_7;
+extern const image_t img_5x7_F;
+extern const image_t img_5x7_E;
+extern const image_t img_5x7_D;
+extern const image_t img_5x7_C;
+extern const image_t img_5x7_B;
+extern const image_t img_5x7_A;
+extern const image_t img_5x7_9;
+extern const image_t img_5x7_8;
+extern const image_t img_5x7_6;
+extern const image_t img_5x7_5;
+extern const image_t img_5x7_4;
+extern const image_t img_5x7_3;
+extern const image_t img_5x7_2;
+extern const image_t img_5x7_1;
+extern const image_t img_5x7_0;
+extern const image_t img_6x8_v;
+extern const image_t img_6x8_n;
+extern const image_t img_6x8_G;
+extern const image_t img_6x8_F;
+extern const image_t img_6x8_E;
+extern const image_t img_6x8_d;
+extern const image_t img_6x8_C;
+extern const image_t img_6x8_B;
+extern const image_t img_6x8_A;
+extern const image_t img_6x8_9;
+extern const image_t img_6x8_8;
+extern const image_t img_6x8_6;
+extern const image_t img_6x8_5;
+extern const image_t img_6x8_4;
+extern const image_t img_6x8_3;
+extern const image_t img_6x8_2;
+extern const image_t img_6x8_1;
+extern const image_t img_6x8_0;
+extern const image_t img_ecp_SDA;
+extern const image_t img_ecp_SCL;
+extern const image_t img_ecp_port;
+extern const image_t img_cc_pad_UD1;
+extern const image_t img_cc_pad_LR1;
+extern const image_t img_cc_btn_Y1;
+extern const image_t img_cc_btn_X1;
+extern const image_t img_cc_btn_B1;
+extern const image_t img_cc_btn_A1;
+extern const image_t img_6x8_D;
//----------------------------------------------------------------------------- ----------------------------------------
#ifndef IMGTEST
-#include
-void show(
- Canvas* const canvas,
- const uint8_t tlx,
- const uint8_t tly,
- const image_t* img,
- const showMode_t mode);
+# include
+ void show (Canvas* const canvas, const uint8_t tlx, const uint8_t tly,
+ const image_t* img, const showMode_t mode) ;
#endif
#endif //IMAGES_H_
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c
index 8fc8e0e14..975d98d35 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_0.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_0 = {3, 5, false, 2, 0, {0xF6, 0xDE}};
+const image_t img_3x5_0 = { 3, 5, false, 2, 0, {
+ 0xF6, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c
index 8b7d4cf80..0d9dc3fe4 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_1.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_1 = {3, 5, false, 2, 0, {0xC9, 0x2E}};
+const image_t img_3x5_1 = { 3, 5, false, 2, 0, {
+ 0xC9, 0x2E
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c
index 89a81c75e..d98bf4e93 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_2.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_2 = {3, 5, false, 2, 0, {0xE7, 0xCE}};
+const image_t img_3x5_2 = { 3, 5, false, 2, 0, {
+ 0xE7, 0xCE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c
index 97ff0478a..8d08ed1b6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_3.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_3 = {3, 5, false, 2, 0, {0xE5, 0x9E}};
+const image_t img_3x5_3 = { 3, 5, false, 2, 0, {
+ 0xE5, 0x9E
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c
index 2bbd9ef42..795e9b76f 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_4.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_4 = {3, 5, false, 2, 0, {0x97, 0x92}};
+const image_t img_3x5_4 = { 3, 5, false, 2, 0, {
+ 0x97, 0x92
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c
index e0466f37a..377853507 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_5.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_5 = {3, 5, false, 2, 0, {0xF3, 0x9E}};
+const image_t img_3x5_5 = { 3, 5, false, 2, 0, {
+ 0xF3, 0x9E
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c
index 1b62caf72..d3af64071 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_6.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_6 = {3, 5, false, 2, 0, {0xD3, 0xDE}};
+const image_t img_3x5_6 = { 3, 5, false, 2, 0, {
+ 0xD3, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c
index acfe57cf8..2c3b1e0b9 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_7.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_7 = {3, 5, false, 2, 0, {0xE5, 0x24}};
+const image_t img_3x5_7 = { 3, 5, false, 2, 0, {
+ 0xE5, 0x24
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c
index 31f32af52..5cb6d3354 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_8.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_8 = {3, 5, false, 2, 0, {0xF7, 0xDE}};
+const image_t img_3x5_8 = { 3, 5, false, 2, 0, {
+ 0xF7, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c
index 4b1ba1e09..ee5e82b87 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_9.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_9 = {3, 5, false, 2, 0, {0xF7, 0x96}};
+const image_t img_3x5_9 = { 3, 5, false, 2, 0, {
+ 0xF7, 0x96
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c b/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c
index 2282e1697..dcf3f631d 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_3x5_v.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_3x5_v = {3, 5, false, 2, 0, {0x02, 0xD4}};
+const image_t img_3x5_v = { 3, 5, false, 2, 0, {
+ 0x02, 0xD4
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c
index 7ae2186b3..c59852f19 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_0.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_0 = {5, 7, false, 5, 0, {0x74, 0x67, 0x5C, 0xC5, 0xC0}};
+const image_t img_5x7_0 = { 5, 7, false, 5, 0, {
+ 0x74, 0x67, 0x5C, 0xC5, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c
index c1a9cec74..4bd08f89c 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_1 = {5, 7, false, 5, 0, {0x65, 0x08, 0x42, 0x13, 0xE0}};
+const image_t img_5x7_1 = { 5, 7, false, 5, 0, {
+ 0x65, 0x08, 0x42, 0x13, 0xE0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c
index 7fab90010..1270393f7 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_2.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_2 = {5, 7, false, 5, 0, {0x74, 0x42, 0x22, 0x23, 0xE0}};
+const image_t img_5x7_2 = { 5, 7, false, 5, 0, {
+ 0x74, 0x42, 0x22, 0x23, 0xE0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c
index 2099bf795..e26bac523 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_3.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_3 = {5, 7, false, 5, 0, {0x74, 0x42, 0x60, 0xC5, 0xC0}};
+const image_t img_5x7_3 = { 5, 7, false, 5, 0, {
+ 0x74, 0x42, 0x60, 0xC5, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c
index 1eee4f07d..e0dc5687f 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_4.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_4 = {5, 7, false, 5, 0, {0x84, 0x25, 0x2F, 0x88, 0x40}};
+const image_t img_5x7_4 = { 5, 7, false, 5, 0, {
+ 0x84, 0x25, 0x2F, 0x88, 0x40
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c
index be1e54681..81747376f 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_5.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_5 = {5, 7, false, 5, 0, {0xFC, 0x21, 0xE0, 0x87, 0xC0}};
+const image_t img_5x7_5 = { 5, 7, false, 5, 0, {
+ 0xFC, 0x21, 0xE0, 0x87, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c
index da155c1b5..455c874dc 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_6.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_6 = {5, 7, false, 5, 0, {0x74, 0x21, 0xE8, 0xC5, 0xC0}};
+const image_t img_5x7_6 = { 5, 7, false, 5, 0, {
+ 0x74, 0x21, 0xE8, 0xC5, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c
index fde7e8ea2..73e813a21 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_7.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_7 = {5, 7, false, 5, 0, {0xF8, 0x44, 0x22, 0x10, 0x80}};
+const image_t img_5x7_7 = { 5, 7, false, 5, 0, {
+ 0xF8, 0x44, 0x22, 0x10, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c
index aff178282..0f04a48bf 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_8.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_8 = {5, 7, false, 5, 0, {0x74, 0x62, 0xE8, 0xC5, 0xC0}};
+const image_t img_5x7_8 = { 5, 7, false, 5, 0, {
+ 0x74, 0x62, 0xE8, 0xC5, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c
index 2417c57e8..2b1e978c6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_9.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_9 = {5, 7, false, 5, 0, {0x74, 0x62, 0xF0, 0x85, 0xC0}};
+const image_t img_5x7_9 = { 5, 7, false, 5, 0, {
+ 0x74, 0x62, 0xF0, 0x85, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c
index 910c034a2..a6b049f01 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_A.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_A = {5, 7, false, 5, 0, {0x74, 0x63, 0xF8, 0xC6, 0x20}};
+const image_t img_5x7_A = { 5, 7, false, 5, 0, {
+ 0x74, 0x63, 0xF8, 0xC6, 0x20
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c
index 93808fee2..06b36599c 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_B.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_B = {5, 7, false, 5, 0, {0xF4, 0x63, 0x68, 0xC7, 0xC0}};
+const image_t img_5x7_B = { 5, 7, false, 5, 0, {
+ 0xF4, 0x63, 0x68, 0xC7, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c
index 1438eaf44..c058d09a9 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_C.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_C = {5, 7, false, 5, 0, {0x74, 0x61, 0x08, 0x45, 0xC0}};
+const image_t img_5x7_C = { 5, 7, false, 5, 0, {
+ 0x74, 0x61, 0x08, 0x45, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c
index 9c6b590ee..3425e3648 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_D.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_D = {5, 7, false, 5, 0, {0x75, 0x4A, 0x52, 0xD5, 0xC0}};
+const image_t img_5x7_D = { 5, 7, false, 5, 0, {
+ 0x75, 0x4A, 0x52, 0xD5, 0xC0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c
index bc15fb240..c7bbc301a 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_E.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_E = {5, 7, false, 5, 0, {0xFC, 0x21, 0xC8, 0x43, 0xE0}};
+const image_t img_5x7_E = { 5, 7, false, 5, 0, {
+ 0xFC, 0x21, 0xC8, 0x43, 0xE0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c b/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c
index e4ad0db69..440c37eae 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_5x7_F.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_5x7_F = {5, 7, false, 5, 0, {0xFC, 0x21, 0xC8, 0x42, 0x00}};
+const image_t img_5x7_F = { 5, 7, false, 5, 0, {
+ 0xFC, 0x21, 0xC8, 0x42, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c
index 952cf34d8..b8b4c7d9a 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_0.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_0 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE}};
+const image_t img_6x8_0 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xFC, 0xF3, 0xCF, 0x3F, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c
index 846a6876c..91e2b2cfa 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_1.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_1 = {6, 8, false, 6, 0, {0x73, 0xC3, 0x0C, 0x30, 0xCF, 0xFF}};
+const image_t img_6x8_1 = { 6, 8, false, 6, 0, {
+ 0x73, 0xC3, 0x0C, 0x30, 0xCF, 0xFF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c
index 4534bb67c..7d24c64d6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_2.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_2 = {6, 8, false, 6, 0, {0x7B, 0xF0, 0xC7, 0x31, 0x8F, 0xFF}};
+const image_t img_6x8_2 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xF0, 0xC7, 0x31, 0x8F, 0xFF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c
index 7e79eb03a..3a8f9f211 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_3.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_3 = {6, 8, false, 6, 0, {0x7B, 0xF0, 0xCF, 0x3C, 0x3F, 0xDE}};
+const image_t img_6x8_3 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xF0, 0xCF, 0x3C, 0x3F, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c
index 324b036ce..c5ae9efef 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_4.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_4 = {6, 8, false, 6, 0, {0xC3, 0x0D, 0xB6, 0xFF, 0xF1, 0x86}};
+const image_t img_6x8_4 = { 6, 8, false, 6, 0, {
+ 0xC3, 0x0D, 0xB6, 0xFF, 0xF1, 0x86
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c
index cdfda5f2b..787e39ea6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_5.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_5 = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFE}};
+const image_t img_6x8_5 = { 6, 8, false, 6, 0, {
+ 0xFF, 0xFC, 0x3E, 0xFC, 0x3F, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c
index 781a060f1..8f07f1bfc 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_6.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_6 = {6, 8, false, 6, 0, {0x7B, 0xEC, 0x3E, 0xFF, 0x3F, 0xDE}};
+const image_t img_6x8_6 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xEC, 0x3E, 0xFF, 0x3F, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c
index fec5f4bf4..cad50c65d 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_7.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_7 = {6, 8, false, 6, 0, {0xFF, 0xF0, 0xC6, 0x18, 0xC3, 0x0C}};
+const image_t img_6x8_7 = { 6, 8, false, 6, 0, {
+ 0xFF, 0xF0, 0xC6, 0x18, 0xC3, 0x0C
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c
index a5b21c375..a38b2110d 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_8.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_8 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xDE, 0xFF, 0x3F, 0xDE}};
+const image_t img_6x8_8 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xFC, 0xDE, 0xFF, 0x3F, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c
index f7707c0df..b740c7f90 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_9.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_9 = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xFF, 0x7C, 0x37, 0xDE}};
+const image_t img_6x8_9 = { 6, 8, false, 6, 0, {
+ 0x7B, 0xFC, 0xFF, 0x7C, 0x37, 0xDE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c
index 1bb65c902..fa3aed598 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_A.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_A = {6, 8, false, 6, 0, {0x7B, 0xFC, 0xF3, 0xFF, 0xFC, 0xF3}};
+const image_t img_6x8_A = { 6, 8, false, 6, 0, {
+ 0x7B, 0xFC, 0xF3, 0xFF, 0xFC, 0xF3
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c
index 00e012d53..14c1e28c6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_B.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_B = {6, 8, false, 6, 0, {0xFB, 0xFC, 0xFE, 0xFB, 0x3F, 0xFE}};
+const image_t img_6x8_B = { 6, 8, false, 6, 0, {
+ 0xFB, 0xFC, 0xFE, 0xFB, 0x3F, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c
index 694901009..6d8f7aa32 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_C.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_C = {6, 8, false, 6, 0, {0x7F, 0xFC, 0x30, 0xC3, 0x0F, 0xDF}};
+const image_t img_6x8_C = { 6, 8, false, 6, 0, {
+ 0x7F, 0xFC, 0x30, 0xC3, 0x0F, 0xDF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c
index a95e760eb..474e4a235 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_D.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_D = {6, 8, false, 6, 0, {0xFB, 0xF6, 0xDB, 0x6D, 0xBF, 0xFE}};
+const image_t img_6x8_D = { 6, 8, false, 6, 0, {
+ 0xFB, 0xF6, 0xDB, 0x6D, 0xBF, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c
index f49503f00..00f2cb559 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_E.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_E = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3C, 0xF3, 0x0F, 0xFF}};
+const image_t img_6x8_E = { 6, 8, false, 6, 0, {
+ 0xFF, 0xFC, 0x3C, 0xF3, 0x0F, 0xFF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c
index 0037b2544..8958a0419 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_F.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_F = {6, 8, false, 6, 0, {0xFF, 0xFC, 0x3C, 0xF3, 0x0C, 0x30}};
+const image_t img_6x8_F = { 6, 8, false, 6, 0, {
+ 0xFF, 0xFC, 0x3C, 0xF3, 0x0C, 0x30
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c
index f30bc9952..f5e8f03f4 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_G.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_G = {6, 8, false, 6, 0, {0x7F, 0xFC, 0x30, 0xDF, 0x3F, 0xDF}};
+const image_t img_6x8_G = { 6, 8, false, 6, 0, {
+ 0x7F, 0xFC, 0x30, 0xDF, 0x3F, 0xDF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c
index 4735e82a1..7b162baf3 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_X.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_X = {6, 8, false, 6, 0, {0xCF, 0x36, 0x8E, 0x71, 0x6C, 0xF3}};
+const image_t img_6x8_X = { 6, 8, false, 6, 0, {
+ 0xCF, 0x36, 0x8E, 0x71, 0x6C, 0xF3
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c
index 508e786bd..b39392948 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_Y.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_Y = {6, 8, false, 6, 0, {0xCF, 0x3C, 0xF3, 0x78, 0xC3, 0x0C}};
+const image_t img_6x8_Y = { 6, 8, false, 6, 0, {
+ 0xCF, 0x3C, 0xF3, 0x78, 0xC3, 0x0C
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c
index c42d560ac..9904d08b4 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_Z.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_Z = {6, 8, false, 6, 0, {0xFF, 0xF0, 0xC6, 0x31, 0x8F, 0xFF}};
+const image_t img_6x8_Z = { 6, 8, false, 6, 0, {
+ 0xFF, 0xF0, 0xC6, 0x31, 0x8F, 0xFF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c
index 1f8123a6c..2a00713fd 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_d_.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_d = {6, 8, false, 6, 0, {0x0C, 0x30, 0xDF, 0xFF, 0x3F, 0xDF}};
+const image_t img_6x8_d = { 6, 8, false, 6, 0, {
+ 0x0C, 0x30, 0xDF, 0xFF, 0x3F, 0xDF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c
index 15d403d28..086bdd2de 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_n_.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_n = {6, 8, false, 6, 0, {0x00, 0x07, 0xBF, 0xCF, 0x3C, 0xF3}};
+const image_t img_6x8_n = { 6, 8, false, 6, 0, {
+ 0x00, 0x07, 0xBF, 0xCF, 0x3C, 0xF3
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c b/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c
index 1229701a1..c897aadff 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_6x8_v_.c
@@ -9,4 +9,6 @@
#include "images.h"
-const image_t img_6x8_v = {6, 8, false, 6, 0, {0x00, 0x08, 0x73, 0xCF, 0xF7, 0x8C}};
+const image_t img_6x8_v = { 6, 8, false, 6, 0, {
+ 0x00, 0x08, 0x73, 0xCF, 0xF7, 0x8C
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_RIP.c b/applications/plugins/wii_ec_anal/gfx/img_RIP.c
index c20877ef0..55cb7bfc2 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_RIP.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_RIP.c
@@ -65,66 +65,58 @@
#include "images.h"
-const image_t img_RIP = {
- 128,
- 64,
- true,
- 837,
- 0x06,
- {// orig:1024, comp:18.26%
- 0x06, 0x20, 0xFF, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC8, 0x01,
- 0xFC, 0x1E, 0x1F, 0xF0, 0x00, 0xFE, 0x20, 0x8F, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x13, 0xD4,
- 0x01, 0xFC, 0x0E, 0x0F, 0xF0, 0x00, 0xFE, 0x71, 0xCF, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x2B,
- 0xC0, 0x00, 0x0E, 0x0A, 0x00, 0x38, 0x01, 0x87, 0x71, 0xD8, 0x77, 0x1C, 0x07, 0x71, 0xC0,
- 0x03, 0xC0, 0x03, 0x8E, 0x0A, 0x0E, 0x28, 0x01, 0xC5, 0x51, 0x5C, 0x77, 0x1D, 0xC7, 0x71,
- 0x40, 0x03, 0xC0, 0x03, 0x8A, 0x0A, 0x0E, 0x28, 0x01, 0x47, 0x51, 0x5C, 0x55, 0x15, 0xC5,
- 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15,
- 0x45, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A, 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55,
- 0x15, 0x45, 0x51, 0xC0, 0x03, 0xC0, 0x02, 0x8E, 0x0A, 0x0A, 0x38, 0x01, 0x40, 0x51, 0x54,
- 0x75, 0x55, 0x47, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x71,
- 0xD7, 0xC5, 0x15, 0x7C, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8, 0x0A, 0x0B, 0xE0, 0x01, 0x40,
- 0x3F, 0x97, 0xC5, 0x15, 0x7C, 0x57, 0x80, 0x03, 0xC0, 0x02, 0x9C, 0x0A, 0x0A, 0x00, 0x01,
- 0x40, 0x1B, 0x14, 0x75, 0x55, 0x4E, 0x57, 0xC0, 0x03, 0xC0, 0x02, 0x94, 0x0A, 0x0A, 0x00,
- 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, 0x0A, 0x0A,
- 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94, 0x0A,
- 0x0A, 0x00, 0x01, 0xC7, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94,
- 0x0A, 0x0A, 0x00, 0x01, 0xC5, 0x0A, 0x1C, 0x77, 0x1D, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02,
- 0x94, 0x0A, 0x0A, 0x00, 0x01, 0x87, 0x0E, 0x1C, 0x77, 0x1D, 0x4A, 0x61, 0xC0, 0x03, 0xC0,
- 0x03, 0x9C, 0xCE, 0xCE, 0xC0, 0x00, 0xFE, 0x0E, 0x0F, 0xE3, 0xF9, 0xCE, 0x3F, 0x80, 0x03,
- 0xC0, 0x03, 0x8E, 0xDE, 0xDE, 0xC0, 0x00, 0xFE, 0x1F, 0x0F, 0xE3, 0xF9, 0xC7, 0x3F, 0x80,
- 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0A, 0x00,
- 0x01, 0x8C, 0x07, 0xF0, 0x03, 0xC0, 0x06, 0x07, 0x00, 0x04, 0x00, 0x00, 0x02, 0x52, 0x18,
- 0x0C, 0x03, 0xC1, 0xD5, 0xC7, 0x57, 0x77, 0x6D, 0xC4, 0x5D, 0x2B, 0x8E, 0xE0, 0x03, 0x5A,
- 0x20, 0x02, 0x03, 0xC0, 0x95, 0x04, 0x54, 0x24, 0x55, 0x04, 0x55, 0xA1, 0x0A, 0x80, 0x01,
- 0x8C, 0x47, 0xC1, 0x03, 0xC0, 0x9D, 0x87, 0x27, 0x26, 0x55, 0xC5, 0x55, 0x61, 0x0C, 0xC0,
- 0x00, 0x50, 0x88, 0x21, 0x03, 0xC0, 0x95, 0x01, 0x21, 0x24, 0x44, 0x45, 0x55, 0x21, 0x0A,
- 0x80, 0x00, 0x20, 0x90, 0x11, 0x03, 0xC0, 0x95, 0xC7, 0x27, 0x27, 0x45, 0xC6, 0xDD, 0x21,
- 0x0E, 0xE0, 0x00, 0x70, 0x91, 0x91, 0x03, 0xC0, 0x06, 0x0B, 0x00, 0x88, 0x92, 0x51, 0x03,
- 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08, 0x92, 0x91, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08,
- 0x92, 0x11, 0x03, 0xC1, 0xD5, 0xC7, 0x76, 0xDC, 0x45, 0xDD, 0x5D, 0x5C, 0x57, 0x50, 0x00,
- 0x87, 0x11, 0xE2, 0x03, 0xC0, 0x95, 0x04, 0x55, 0x50, 0x44, 0x89, 0x55, 0x48, 0x55, 0x50,
- 0x00, 0x80, 0x88, 0x03, 0x03, 0xC0, 0x9D, 0x87, 0x75, 0x58, 0x54, 0x89, 0xD5, 0x48, 0x25,
- 0x50, 0x00, 0x40, 0x7C, 0x04, 0x83, 0xC0, 0x95, 0x01, 0x54, 0x50, 0x54, 0x89, 0x55, 0x48,
- 0x25, 0x50, 0x00, 0x40, 0x07, 0xF8, 0x43, 0xC0, 0x95, 0xC7, 0x54, 0x5C, 0x6D, 0xC9, 0x5D,
- 0xC8, 0x27, 0x70, 0x00, 0x30, 0x00, 0x00, 0x43, 0xC0, 0x06, 0x0B, 0x00, 0x0F, 0xFF, 0xFF,
- 0x83, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7,
- 0xF1, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07,
- 0xC7, 0xF1, 0xFC, 0x7F, 0x00, 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00,
- 0x05, 0x4E, 0x3B, 0x8E, 0xE3, 0x80, 0x07, 0x1D, 0xC7, 0x71, 0xDC, 0x70, 0x00, 0x03, 0xC0,
- 0x00, 0x01, 0x4E, 0x3A, 0x8E, 0xE3, 0x80, 0x05, 0x15, 0xC7, 0x51, 0x54, 0x50, 0x00, 0x03,
- 0xC0, 0x00, 0x01, 0x4A, 0x2B, 0x8A, 0xA2, 0x80, 0x07, 0x15, 0x45, 0x71, 0x5C, 0x50, 0x00,
- 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA2, 0x80, 0x00, 0x15, 0x45, 0x01, 0x40, 0x50,
- 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA6, 0x80, 0x00, 0x15, 0x4D, 0x01, 0x40,
- 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x28, 0x0E, 0xA6, 0x80, 0x00, 0x1D, 0x4D, 0x01,
- 0xC0, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x0E, 0xAA, 0x9F, 0xE1, 0xF9, 0x55,
- 0x1F, 0x87, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x38, 0xAA, 0x90, 0x23, 0xF1,
- 0x55, 0x3F, 0x0F, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x38, 0xB2, 0x9F, 0xE7,
- 0x01, 0x65, 0x70, 0x1C, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xB2, 0x80,
- 0x05, 0x01, 0x65, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2,
- 0x80, 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28,
- 0xA2, 0x80, 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38,
- 0x28, 0xE3, 0x80, 0x05, 0x01, 0xC7, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40,
- 0x38, 0x28, 0xE3, 0x80, 0x05, 0x0D, 0xC7, 0x50, 0xD4, 0x30, 0x00, 0x03, 0xD4, 0x00, 0x07,
- 0xF3, 0xF0, 0x38, 0x7F, 0x00, 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x2B, 0xC8, 0x00,
- 0x0F, 0xFB, 0xF0, 0x38, 0x7F, 0x00, 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x13, 0xD4,
- 0x06, 0x0E, 0x00, 0x2B, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0x06, 0x20, 0xFF}};
+const image_t img_RIP = { 128, 64, true, 837, 0x06, { // orig:1024, comp:18.26%
+ 0x06, 0x20, 0xFF, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC8, 0x01, 0xFC,
+ 0x1E, 0x1F, 0xF0, 0x00, 0xFE, 0x20, 0x8F, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x13, 0xD4, 0x01, 0xFC,
+ 0x0E, 0x0F, 0xF0, 0x00, 0xFE, 0x71, 0xCF, 0xE3, 0xF8, 0xFE, 0x3F, 0x80, 0x2B, 0xC0, 0x00, 0x0E,
+ 0x0A, 0x00, 0x38, 0x01, 0x87, 0x71, 0xD8, 0x77, 0x1C, 0x07, 0x71, 0xC0, 0x03, 0xC0, 0x03, 0x8E,
+ 0x0A, 0x0E, 0x28, 0x01, 0xC5, 0x51, 0x5C, 0x77, 0x1D, 0xC7, 0x71, 0x40, 0x03, 0xC0, 0x03, 0x8A,
+ 0x0A, 0x0E, 0x28, 0x01, 0x47, 0x51, 0x5C, 0x55, 0x15, 0xC5, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A,
+ 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x8A,
+ 0x0A, 0x0A, 0x28, 0x01, 0x40, 0x51, 0x54, 0x55, 0x15, 0x45, 0x51, 0xC0, 0x03, 0xC0, 0x02, 0x8E,
+ 0x0A, 0x0A, 0x38, 0x01, 0x40, 0x51, 0x54, 0x75, 0x55, 0x47, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8,
+ 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x71, 0xD7, 0xC5, 0x15, 0x7C, 0x50, 0x00, 0x03, 0xC0, 0x02, 0xF8,
+ 0x0A, 0x0B, 0xE0, 0x01, 0x40, 0x3F, 0x97, 0xC5, 0x15, 0x7C, 0x57, 0x80, 0x03, 0xC0, 0x02, 0x9C,
+ 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x1B, 0x14, 0x75, 0x55, 0x4E, 0x57, 0xC0, 0x03, 0xC0, 0x02, 0x94,
+ 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94,
+ 0x0A, 0x0A, 0x00, 0x01, 0x40, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x51, 0x40, 0x03, 0xC0, 0x02, 0x94,
+ 0x0A, 0x0A, 0x00, 0x01, 0xC7, 0x0A, 0x14, 0x55, 0x15, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94,
+ 0x0A, 0x0A, 0x00, 0x01, 0xC5, 0x0A, 0x1C, 0x77, 0x1D, 0x4A, 0x71, 0x40, 0x03, 0xC0, 0x02, 0x94,
+ 0x0A, 0x0A, 0x00, 0x01, 0x87, 0x0E, 0x1C, 0x77, 0x1D, 0x4A, 0x61, 0xC0, 0x03, 0xC0, 0x03, 0x9C,
+ 0xCE, 0xCE, 0xC0, 0x00, 0xFE, 0x0E, 0x0F, 0xE3, 0xF9, 0xCE, 0x3F, 0x80, 0x03, 0xC0, 0x03, 0x8E,
+ 0xDE, 0xDE, 0xC0, 0x00, 0xFE, 0x1F, 0x0F, 0xE3, 0xF9, 0xC7, 0x3F, 0x80, 0x03, 0xC0, 0x06, 0x0E,
+ 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x8C, 0x07, 0xF0, 0x03,
+ 0xC0, 0x06, 0x07, 0x00, 0x04, 0x00, 0x00, 0x02, 0x52, 0x18, 0x0C, 0x03, 0xC1, 0xD5, 0xC7, 0x57,
+ 0x77, 0x6D, 0xC4, 0x5D, 0x2B, 0x8E, 0xE0, 0x03, 0x5A, 0x20, 0x02, 0x03, 0xC0, 0x95, 0x04, 0x54,
+ 0x24, 0x55, 0x04, 0x55, 0xA1, 0x0A, 0x80, 0x01, 0x8C, 0x47, 0xC1, 0x03, 0xC0, 0x9D, 0x87, 0x27,
+ 0x26, 0x55, 0xC5, 0x55, 0x61, 0x0C, 0xC0, 0x00, 0x50, 0x88, 0x21, 0x03, 0xC0, 0x95, 0x01, 0x21,
+ 0x24, 0x44, 0x45, 0x55, 0x21, 0x0A, 0x80, 0x00, 0x20, 0x90, 0x11, 0x03, 0xC0, 0x95, 0xC7, 0x27,
+ 0x27, 0x45, 0xC6, 0xDD, 0x21, 0x0E, 0xE0, 0x00, 0x70, 0x91, 0x91, 0x03, 0xC0, 0x06, 0x0B, 0x00,
+ 0x88, 0x92, 0x51, 0x03, 0xC0, 0x06, 0x0A, 0x00, 0x01, 0x08, 0x92, 0x91, 0x03, 0xC0, 0x06, 0x0A,
+ 0x00, 0x01, 0x08, 0x92, 0x11, 0x03, 0xC1, 0xD5, 0xC7, 0x76, 0xDC, 0x45, 0xDD, 0x5D, 0x5C, 0x57,
+ 0x50, 0x00, 0x87, 0x11, 0xE2, 0x03, 0xC0, 0x95, 0x04, 0x55, 0x50, 0x44, 0x89, 0x55, 0x48, 0x55,
+ 0x50, 0x00, 0x80, 0x88, 0x03, 0x03, 0xC0, 0x9D, 0x87, 0x75, 0x58, 0x54, 0x89, 0xD5, 0x48, 0x25,
+ 0x50, 0x00, 0x40, 0x7C, 0x04, 0x83, 0xC0, 0x95, 0x01, 0x54, 0x50, 0x54, 0x89, 0x55, 0x48, 0x25,
+ 0x50, 0x00, 0x40, 0x07, 0xF8, 0x43, 0xC0, 0x95, 0xC7, 0x54, 0x5C, 0x6D, 0xC9, 0x5D, 0xC8, 0x27,
+ 0x70, 0x00, 0x30, 0x00, 0x00, 0x43, 0xC0, 0x06, 0x0B, 0x00, 0x0F, 0xFF, 0xFF, 0x83, 0xC0, 0x06,
+ 0x0E, 0x00, 0x03, 0xC0, 0x06, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7, 0xF1, 0xFC, 0x7F, 0x00,
+ 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x07, 0xC7, 0xF1, 0xFC, 0x7F, 0x00,
+ 0x03, 0xF8, 0xFE, 0x3F, 0x8F, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x05, 0x4E, 0x3B, 0x8E, 0xE3, 0x80,
+ 0x07, 0x1D, 0xC7, 0x71, 0xDC, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x3A, 0x8E, 0xE3, 0x80,
+ 0x05, 0x15, 0xC7, 0x51, 0x54, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x2B, 0x8A, 0xA2, 0x80,
+ 0x07, 0x15, 0x45, 0x71, 0x5C, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA2, 0x80,
+ 0x00, 0x15, 0x45, 0x01, 0x40, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4A, 0x28, 0x0A, 0xA6, 0x80,
+ 0x00, 0x15, 0x4D, 0x01, 0x40, 0x50, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x4E, 0x28, 0x0E, 0xA6, 0x80,
+ 0x00, 0x1D, 0x4D, 0x01, 0xC0, 0x70, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x0E, 0xAA, 0x9F,
+ 0xE1, 0xF9, 0x55, 0x1F, 0x87, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xC3, 0xE8, 0x38, 0xAA, 0x90,
+ 0x23, 0xF1, 0x55, 0x3F, 0x0F, 0xC0, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x38, 0xB2, 0x9F,
+ 0xE7, 0x01, 0x65, 0x70, 0x1C, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xB2, 0x80,
+ 0x05, 0x01, 0x65, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2, 0x80,
+ 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x28, 0x28, 0xA2, 0x80,
+ 0x05, 0x01, 0x45, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38, 0x28, 0xE3, 0x80,
+ 0x05, 0x01, 0xC7, 0x50, 0x14, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x40, 0x38, 0x28, 0xE3, 0x80,
+ 0x05, 0x0D, 0xC7, 0x50, 0xD4, 0x30, 0x00, 0x03, 0xD4, 0x00, 0x07, 0xF3, 0xF0, 0x38, 0x7F, 0x00,
+ 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x2B, 0xC8, 0x00, 0x0F, 0xFB, 0xF0, 0x38, 0x7F, 0x00,
+ 0x07, 0xFC, 0xFE, 0x7F, 0xDF, 0xF0, 0x00, 0x13, 0xD4, 0x06, 0x0E, 0x00, 0x2B, 0xC0, 0x06, 0x0E,
+ 0x00, 0x03, 0x06, 0x20, 0xFF
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c
index f4ac26173..2fc6b5f23 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Cable.c
@@ -12,14 +12,6 @@
#include "images.h"
-const image_t img_cc_Cable = {
- 4,
- 11,
- true,
- 4,
- 0x00,
- {// orig:6, comp:33.33%
- 0x00,
- 0x05,
- 0xDB,
- 0xD0}};
+const image_t img_cc_Cable = { 4, 11, true, 4, 0x00, { // orig:6, comp:33.33%
+ 0x00, 0x05, 0xDB, 0xD0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c
index 5054103b3..dd189cb7e 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Joy.c
@@ -18,8 +18,8 @@
#include "images.h"
-const image_t img_cc_Joy = {17, 17, false, 37, 0, {0x00, 0x80, 0x01, 0xF0, 0x0F, 0xDF, 0x87, 0x01,
- 0xC3, 0x00, 0x61, 0x00, 0x11, 0x80, 0x0C, 0xC0,
- 0x06, 0xC0, 0x01, 0xB0, 0x01, 0x98, 0x00, 0xC4,
- 0x00, 0x43, 0x00, 0x61, 0xC0, 0x70, 0xFD, 0xF8,
- 0x07, 0xC0, 0x00, 0x80, 0x00}};
+const image_t img_cc_Joy = { 17, 17, false, 37, 0, {
+ 0x00, 0x80, 0x01, 0xF0, 0x0F, 0xDF, 0x87, 0x01, 0xC3, 0x00, 0x61, 0x00, 0x11, 0x80, 0x0C, 0xC0,
+ 0x06, 0xC0, 0x01, 0xB0, 0x01, 0x98, 0x00, 0xC4, 0x00, 0x43, 0x00, 0x61, 0xC0, 0x70, 0xFD, 0xF8,
+ 0x07, 0xC0, 0x00, 0x80, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c b/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c
index b29a9ab57..8e7bd5ed9 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_Main.c
@@ -54,47 +54,39 @@
#include "images.h"
-const image_t img_cc_Main = {
- 116,
- 53,
- true,
- 542,
- 0x05,
- {// orig:769, comp:29.52%
- 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x05, 0x05, 0x00, 0x3F, 0xE0, 0x05, 0x04, 0x00, 0x01, 0xF8,
- 0x04, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x02, 0x01, 0xF8, 0x05, 0x04, 0x00, 0x60, 0x00, 0x41,
- 0x04, 0x00, 0x60, 0x02, 0x08, 0x20, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xF0,
- 0x7F, 0xFF, 0xFF, 0xE0, 0xFE, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x41, 0x04,
- 0x00, 0x60, 0x02, 0x08, 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x50, 0x03, 0xFC, 0x10, 0x40,
- 0x06, 0x00, 0x20, 0x83, 0xFC, 0x00, 0xA0, 0x00, 0x00, 0x09, 0x0F, 0xC0, 0x00, 0xF8, 0x00,
- 0x00, 0x01, 0xF0, 0x00, 0x3F, 0x09, 0x00, 0x00, 0x01, 0x1F, 0x05, 0x09, 0x00, 0x0F, 0x88,
- 0x00, 0x00, 0x20, 0x05, 0x0A, 0xFF, 0xF0, 0x40, 0x00, 0x04, 0x78, 0x05, 0x09, 0x00, 0x01,
- 0xE2, 0x00, 0x00, 0x9C, 0x05, 0x0A, 0x00, 0x03, 0x90, 0x00, 0x13, 0x05, 0x0B, 0x00, 0x0C,
- 0x80, 0x03, 0xE0, 0x05, 0x0B, 0x00, 0x7C, 0x00, 0x38, 0x05, 0x05, 0x00, 0xC6, 0xD8, 0x05,
- 0x04, 0x00, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0D, 0x60, 0x00, 0x00, 0x00,
- 0x0E, 0x00, 0x0E, 0x00, 0x60, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xD6, 0xD8, 0x00, 0x00, 0x01,
- 0xF0, 0x00, 0x60, 0x0C, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0D, 0x6D, 0x80, 0x00, 0x00, 0x31,
- 0x80, 0x03, 0x01, 0xC0, 0x01, 0x83, 0x00, 0x00, 0x00, 0x6C, 0xD8, 0x00, 0x00, 0x06, 0x0C,
- 0x00, 0x38, 0x18, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xCA, 0x60, 0x01, 0x81, 0x00, 0x01,
- 0x93, 0x05, 0x07, 0x00, 0x0C, 0x46, 0x00, 0x0C, 0x30, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00,
- 0xCA, 0x60, 0x00, 0xC2, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x07, 0x06, 0x0C, 0x1C,
- 0x04, 0x60, 0x0F, 0xF8, 0x3F, 0xE0, 0x05, 0x05, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x64, 0x00,
- 0xC0, 0x00, 0x06, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x02, 0x40, 0x0C,
- 0x00, 0x00, 0x60, 0x01, 0x99, 0x99, 0x98, 0x03, 0x06, 0x0E, 0x0C, 0x98, 0x2C, 0x00, 0xCE,
- 0x00, 0xE6, 0x00, 0x10, 0x90, 0x90, 0x80, 0x65, 0x30, 0x01, 0x94, 0xC3, 0x80, 0x0C, 0x00,
- 0x00, 0x60, 0x01, 0x09, 0x09, 0x08, 0x06, 0x73, 0x00, 0x19, 0xCC, 0x18, 0x00, 0xC0, 0x00,
- 0x06, 0x00, 0x19, 0x99, 0x99, 0x80, 0x61, 0x30, 0x01, 0x94, 0xC1, 0x80, 0x0F, 0xF8, 0x3F,
- 0xE0, 0x00, 0xF0, 0xF0, 0xF0, 0x03, 0x26, 0x0E, 0x0C, 0x18, 0x18, 0x00, 0xFF, 0x83, 0xFE,
- 0x05, 0x05, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x06, 0x00,
- 0xF8, 0x31, 0x83, 0xE0, 0x18, 0x00, 0x01, 0x93, 0x05, 0x06, 0x00, 0x07, 0x06, 0x8C, 0x1C,
- 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xC8, 0x60, 0x00, 0x18, 0x00, 0x01, 0x83,
- 0x05, 0x07, 0x00, 0x0C, 0xC6, 0x00, 0x01, 0x80, 0x00, 0x18, 0x30, 0x05, 0x07, 0x00, 0xCA,
- 0x60, 0x00, 0x1C, 0x00, 0x01, 0xFF, 0x05, 0x07, 0x00, 0x06, 0x6C, 0x00, 0x03, 0x40, 0x00,
- 0x1F, 0xF0, 0x05, 0x07, 0x00, 0x31, 0x80, 0x00, 0x24, 0x05, 0x0A, 0x00, 0x01, 0xF0, 0x00,
- 0x02, 0x60, 0x05, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x62, 0x05, 0x0D, 0x00, 0x04, 0x20, 0x05,
- 0x0D, 0x00, 0x43, 0x05, 0x0D, 0x00, 0x0C, 0x10, 0x05, 0x0D, 0x00, 0x81, 0x80, 0x05, 0x0C,
- 0x00, 0x18, 0x0C, 0x05, 0x0C, 0x00, 0x03, 0x00, 0x60, 0x05, 0x0C, 0x00, 0x60, 0x03, 0x05,
- 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x05, 0x0B, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x05, 0x0B, 0x00,
- 0x70, 0x00, 0x03, 0x05, 0x0B, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x05, 0x0A, 0x00, 0x03, 0x80,
- 0x00, 0x00, 0x78, 0x05, 0x09, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x05, 0x0A, 0xFF, 0xF0,
- 0x00, 0x00}};
+const image_t img_cc_Main = { 116, 53, true, 542, 0x05, { // orig:769, comp:29.52%
+ 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x05, 0x05, 0x00, 0x3F, 0xE0, 0x05, 0x04, 0x00, 0x01, 0xF8, 0x04,
+ 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x02, 0x01, 0xF8, 0x05, 0x04, 0x00, 0x60, 0x00, 0x41, 0x04, 0x00,
+ 0x60, 0x02, 0x08, 0x20, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xF0, 0x7F, 0xFF, 0xFF,
+ 0xE0, 0xFE, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x41, 0x04, 0x00, 0x60, 0x02, 0x08,
+ 0x20, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x50, 0x03, 0xFC, 0x10, 0x40, 0x06, 0x00, 0x20, 0x83, 0xFC,
+ 0x00, 0xA0, 0x00, 0x00, 0x09, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x3F, 0x09,
+ 0x00, 0x00, 0x01, 0x1F, 0x05, 0x09, 0x00, 0x0F, 0x88, 0x00, 0x00, 0x20, 0x05, 0x0A, 0xFF, 0xF0,
+ 0x40, 0x00, 0x04, 0x78, 0x05, 0x09, 0x00, 0x01, 0xE2, 0x00, 0x00, 0x9C, 0x05, 0x0A, 0x00, 0x03,
+ 0x90, 0x00, 0x13, 0x05, 0x0B, 0x00, 0x0C, 0x80, 0x03, 0xE0, 0x05, 0x0B, 0x00, 0x7C, 0x00, 0x38,
+ 0x05, 0x05, 0x00, 0xC6, 0xD8, 0x05, 0x04, 0x00, 0x01, 0xC0, 0x07, 0x00, 0x1F, 0xF0, 0x00, 0x00,
+ 0x0D, 0x60, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x60, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xD6,
+ 0xD8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x60, 0x0C, 0x00, 0x18, 0x30, 0x00, 0x00, 0x0D, 0x6D, 0x80,
+ 0x00, 0x00, 0x31, 0x80, 0x03, 0x01, 0xC0, 0x01, 0x83, 0x00, 0x00, 0x00, 0x6C, 0xD8, 0x00, 0x00,
+ 0x06, 0x0C, 0x00, 0x38, 0x18, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xCA, 0x60, 0x01, 0x81, 0x00,
+ 0x01, 0x93, 0x05, 0x07, 0x00, 0x0C, 0x46, 0x00, 0x0C, 0x30, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00,
+ 0xCA, 0x60, 0x00, 0xC2, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x07, 0x06, 0x0C, 0x1C, 0x04,
+ 0x60, 0x0F, 0xF8, 0x3F, 0xE0, 0x05, 0x05, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x64, 0x00, 0xC0, 0x00,
+ 0x06, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x02, 0x40, 0x0C, 0x00, 0x00, 0x60,
+ 0x01, 0x99, 0x99, 0x98, 0x03, 0x06, 0x0E, 0x0C, 0x98, 0x2C, 0x00, 0xCE, 0x00, 0xE6, 0x00, 0x10,
+ 0x90, 0x90, 0x80, 0x65, 0x30, 0x01, 0x94, 0xC3, 0x80, 0x0C, 0x00, 0x00, 0x60, 0x01, 0x09, 0x09,
+ 0x08, 0x06, 0x73, 0x00, 0x19, 0xCC, 0x18, 0x00, 0xC0, 0x00, 0x06, 0x00, 0x19, 0x99, 0x99, 0x80,
+ 0x61, 0x30, 0x01, 0x94, 0xC1, 0x80, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0xF0, 0xF0, 0xF0, 0x03, 0x26,
+ 0x0E, 0x0C, 0x18, 0x18, 0x00, 0xFF, 0x83, 0xFE, 0x05, 0x05, 0x00, 0x18, 0xC1, 0xF0, 0x63, 0x01,
+ 0x80, 0x00, 0x19, 0x30, 0x05, 0x06, 0x00, 0xF8, 0x31, 0x83, 0xE0, 0x18, 0x00, 0x01, 0x93, 0x05,
+ 0x06, 0x00, 0x07, 0x06, 0x8C, 0x1C, 0x01, 0x80, 0x00, 0x19, 0x30, 0x05, 0x07, 0x00, 0xC8, 0x60,
+ 0x00, 0x18, 0x00, 0x01, 0x83, 0x05, 0x07, 0x00, 0x0C, 0xC6, 0x00, 0x01, 0x80, 0x00, 0x18, 0x30,
+ 0x05, 0x07, 0x00, 0xCA, 0x60, 0x00, 0x1C, 0x00, 0x01, 0xFF, 0x05, 0x07, 0x00, 0x06, 0x6C, 0x00,
+ 0x03, 0x40, 0x00, 0x1F, 0xF0, 0x05, 0x07, 0x00, 0x31, 0x80, 0x00, 0x24, 0x05, 0x0A, 0x00, 0x01,
+ 0xF0, 0x00, 0x02, 0x60, 0x05, 0x0A, 0x00, 0x0E, 0x00, 0x00, 0x62, 0x05, 0x0D, 0x00, 0x04, 0x20,
+ 0x05, 0x0D, 0x00, 0x43, 0x05, 0x0D, 0x00, 0x0C, 0x10, 0x05, 0x0D, 0x00, 0x81, 0x80, 0x05, 0x0C,
+ 0x00, 0x18, 0x0C, 0x05, 0x0C, 0x00, 0x03, 0x00, 0x60, 0x05, 0x0C, 0x00, 0x60, 0x03, 0x05, 0x0C,
+ 0x00, 0x0C, 0x00, 0x18, 0x05, 0x0B, 0x00, 0x01, 0x80, 0x00, 0xE0, 0x05, 0x0B, 0x00, 0x70, 0x00,
+ 0x03, 0x05, 0x0B, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x05, 0x0A, 0x00, 0x03, 0x80, 0x00, 0x00, 0x78,
+ 0x05, 0x09, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x05, 0x0A, 0xFF, 0xF0, 0x00, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c
index 0889b2a08..4d54cbf22 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_A1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_cc_btn_A1 = {7, 7, false, 7, 0, {0xFF, 0xDF, 0x5E, 0x3D, 0x7F, 0xFF, 0x80}};
+const image_t img_cc_btn_A1 = { 7, 7, false, 7, 0, {
+ 0xFF, 0xDF, 0x5E, 0x3D, 0x7F, 0xFF, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c
index bbf5fba1a..89d357282 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_B1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_cc_btn_B1 = {7, 7, false, 7, 0, {0xFF, 0xBF, 0x7E, 0x7D, 0x7C, 0xFF, 0x80}};
+const image_t img_cc_btn_B1 = { 7, 7, false, 7, 0, {
+ 0xFF, 0xBF, 0x7E, 0x7D, 0x7C, 0xFF, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c
index 2352ba695..a1e7f2876 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_X1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_cc_btn_X1 = {7, 7, false, 7, 0, {0xFF, 0xFF, 0x5F, 0x7D, 0x7F, 0xFF, 0x80}};
+const image_t img_cc_btn_X1 = { 7, 7, false, 7, 0, {
+ 0xFF, 0xFF, 0x5F, 0x7D, 0x7F, 0xFF, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c
index d7192e3e7..01f66b4c7 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_btn_Y1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_cc_btn_Y1 = {7, 7, false, 7, 0, {0xFF, 0xFF, 0x5E, 0x3F, 0x7D, 0xFF, 0x80}};
+const image_t img_cc_btn_Y1 = { 7, 7, false, 7, 0, {
+ 0xFF, 0xFF, 0x5E, 0x3F, 0x7D, 0xFF, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c
index 300ed5eee..698fcfdd6 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_LR1.c
@@ -6,4 +6,6 @@
#include "images.h"
-const image_t img_cc_pad_LR1 = {7, 5, false, 5, 0, {0xFF, 0xFF, 0x1F, 0xFF, 0xE0}};
+const image_t img_cc_pad_LR1 = { 7, 5, false, 5, 0, {
+ 0xFF, 0xFF, 0x1F, 0xFF, 0xE0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c
index feb32d283..b7d104ee4 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_pad_UD1.c
@@ -8,4 +8,6 @@
#include "images.h"
-const image_t img_cc_pad_UD1 = {5, 7, false, 5, 0, {0xFF, 0xF7, 0xBD, 0xFF, 0xE0}};
+const image_t img_cc_pad_UD1 = { 5, 7, false, 5, 0, {
+ 0xFF, 0xF7, 0xBD, 0xFF, 0xE0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c
index c70e35334..cf4d7159b 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L1.c
@@ -7,10 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_L1 = {
- 17,
- 6,
- false,
- 13,
- 0,
- {0x1F, 0xC9, 0x34, 0x92, 0x64, 0x92, 0x54, 0x92, 0x44, 0x93, 0xFC, 0xFE, 0x00}};
+const image_t img_cc_trg_L1 = { 17, 6, false, 13, 0, {
+ 0x1F, 0xC9, 0x34, 0x92, 0x64, 0x92, 0x54, 0x92, 0x44, 0x93, 0xFC, 0xFE, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c
index 47561ab98..9e61a64cc 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L2.c
@@ -7,22 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_L2 = {
- 17,
- 6,
- true,
- 12,
- 0x01,
- {// orig:13, comp:7.69%
- 0x1F,
- 0xD5,
- 0x35,
- 0x55,
- 0x75,
- 0x01,
- 0x04,
- 0x55,
- 0x57,
- 0xFD,
- 0x7E,
- 0x00}};
+const image_t img_cc_trg_L2 = { 17, 6, true, 12, 0x01, { // orig:13, comp:7.69%
+ 0x1F, 0xD5, 0x35, 0x55, 0x75, 0x01, 0x04, 0x55, 0x57, 0xFD, 0x7E, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c
index 0b51bed35..1b06de5ee 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L3.c
@@ -7,10 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_L3 = {
- 17,
- 6,
- false,
- 13,
- 0,
- {0x1F, 0xB6, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6F, 0xFB, 0x7E, 0x00}};
+const image_t img_cc_trg_L3 = { 17, 6, false, 13, 0, {
+ 0x1F, 0xB6, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6D, 0xBB, 0x6F, 0xFB, 0x7E, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c
index 062caca77..12f877ab1 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_L4.c
@@ -7,18 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_L4 = {
- 17,
- 6,
- true,
- 8,
- 0x01,
- {// orig:13, comp:38.46%
- 0x1F,
- 0xFF,
- 0xBF,
- 0x01,
- 0x08,
- 0xFF,
- 0xFE,
- 0x00}};
+const image_t img_cc_trg_L4 = { 17, 6, true, 8, 0x01, { // orig:13, comp:38.46%
+ 0x1F, 0xFF, 0xBF, 0x01, 0x08, 0xFF, 0xFE, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c
index 6f08886d3..a196c0fe1 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R1.c
@@ -7,10 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_R1 = {
- 17,
- 6,
- false,
- 13,
- 0,
- {0x49, 0xFC, 0x49, 0x25, 0x92, 0x49, 0x24, 0x92, 0x5F, 0xE4, 0x90, 0x0F, 0xE4}};
+const image_t img_cc_trg_R1 = { 17, 6, false, 13, 0, {
+ 0x49, 0xFC, 0x49, 0x25, 0x92, 0x49, 0x24, 0x92, 0x5F, 0xE4, 0x90, 0x0F, 0xE4
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c
index d85e45761..ea5458f39 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R2.c
@@ -7,10 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_R2 = {
- 17,
- 6,
- false,
- 13,
- 0,
- {0x55, 0xFC, 0x55, 0x55, 0x95, 0x55, 0x75, 0x55, 0x5F, 0xF5, 0x50, 0x0F, 0xD4}};
+const image_t img_cc_trg_R2 = { 17, 6, false, 13, 0, {
+ 0x55, 0xFC, 0x55, 0x55, 0x95, 0x55, 0x75, 0x55, 0x5F, 0xF5, 0x50, 0x0F, 0xD4
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c
index 082d160e2..94cf02bf0 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R3.c
@@ -7,10 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_R3 = {
- 17,
- 6,
- false,
- 13,
- 0,
- {0xB6, 0xFC, 0x36, 0xDB, 0xAD, 0xB6, 0xFB, 0x6D, 0xBF, 0xFB, 0x68, 0x0F, 0xD8}};
+const image_t img_cc_trg_R3 = { 17, 6, false, 13, 0, {
+ 0xB6, 0xFC, 0x36, 0xDB, 0xAD, 0xB6, 0xFB, 0x6D, 0xBF, 0xFB, 0x68, 0x0F, 0xD8
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c
index 0395058b8..c90fbe20b 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_cc_trg_R4.c
@@ -7,21 +7,6 @@
#include "images.h"
-const image_t img_cc_trg_R4 = {
- 17,
- 6,
- true,
- 11,
- 0x00,
- {// orig:13, comp:15.38%
- 0xFF,
- 0xFC,
- 0x7F,
- 0xFF,
- 0xBF,
- 0x00,
- 0x05,
- 0xFF,
- 0xF8,
- 0x0F,
- 0xFC}};
+const image_t img_cc_trg_R4 = { 17, 6, true, 11, 0x00, { // orig:13, comp:15.38%
+ 0xFF, 0xFC, 0x7F, 0xFF, 0xBF, 0x00, 0x05, 0xFF, 0xF8, 0x0F, 0xFC
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c b/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c
index a8c030fa2..97f09ac17 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_csLogo_FULL.c
@@ -41,49 +41,41 @@
#include "images.h"
-const image_t img_csLogo_FULL = {
- 124,
- 40,
- true,
- 571,
- 0x0B,
- {// orig:620, comp:7.90%
- 0x3F, 0xFF, 0xFE, 0x10, 0x43, 0xF8, 0x7F, 0x0F, 0xE1, 0xFC, 0x0B, 0x05, 0x00, 0x03, 0xFF,
- 0xFF, 0xE3, 0x8E, 0x3F, 0x87, 0xF0, 0xFE, 0x1F, 0xC0, 0x0B, 0x05, 0x00, 0xFC, 0x00, 0x07,
- 0x38, 0xE6, 0x1C, 0xE3, 0x80, 0x73, 0x8E, 0x03, 0xBB, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00,
- 0x52, 0x8A, 0x71, 0xCE, 0x39, 0xC7, 0x38, 0xA0, 0x22, 0x10, 0x00, 0x00, 0x00, 0xFC, 0x00,
- 0x05, 0x28, 0xA7, 0x14, 0xA2, 0x9C, 0x52, 0x8A, 0x03, 0x39, 0x00, 0x00, 0x00, 0x0C, 0xC0,
- 0x00, 0x52, 0x8A, 0x51, 0x4A, 0x29, 0x45, 0x28, 0xA0, 0x20, 0x90, 0x00, 0x00, 0x00, 0xFC,
- 0x00, 0x07, 0x28, 0xA5, 0x14, 0xA2, 0x94, 0x52, 0x8E, 0x03, 0xB9, 0x40, 0x00, 0x00, 0x0F,
- 0xC0, 0x00, 0x02, 0x8A, 0x51, 0xCA, 0xA9, 0x47, 0x28, 0x0B, 0x06, 0x00, 0xCC, 0x00, 0x00,
- 0x38, 0xE5, 0xF0, 0xA2, 0x97, 0xC2, 0x80, 0x06, 0xEE, 0x80, 0x00, 0x00, 0x0E, 0xC3, 0x00,
- 0x01, 0xFC, 0x5F, 0x0A, 0x29, 0x7C, 0x2B, 0xC0, 0x2A, 0xAA, 0x00, 0x00, 0x00, 0xDC, 0x30,
- 0x00, 0x0D, 0x85, 0x1C, 0xAA, 0x94, 0xE2, 0xBE, 0x02, 0xEE, 0xE0, 0x00, 0x00, 0x0E, 0xC0,
- 0x30, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x28, 0xA0, 0x22, 0xA2, 0x00, 0x00, 0x00, 0xDC,
- 0x04, 0x80, 0x05, 0x05, 0x14, 0xA2, 0x94, 0xA2, 0x8A, 0x07, 0x2E, 0x20, 0x00, 0x08, 0x0E,
- 0xC0, 0x48, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x38, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x40,
- 0xDC, 0x03, 0x00, 0x05, 0x07, 0x1C, 0xE3, 0x94, 0xA3, 0x8A, 0x0B, 0x04, 0x00, 0xE2, 0x0C,
- 0xC0, 0x00, 0x00, 0x70, 0x71, 0xCE, 0x39, 0x4A, 0x30, 0xE0, 0x00, 0x00, 0x00, 0x0C, 0x90,
- 0xCC, 0x00, 0x00, 0x07, 0x03, 0xF8, 0x7F, 0x1C, 0xE1, 0xFC, 0x0B, 0x04, 0x00, 0x94, 0x8C,
- 0xC0, 0x00, 0x00, 0xF8, 0x3F, 0x87, 0xF1, 0xC7, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x72, 0x24,
- 0xCC, 0x0B, 0x0C, 0x00, 0x06, 0x15, 0x2C, 0xC0, 0x0B, 0x0C, 0x00, 0x48, 0x89, 0xCC, 0x00,
- 0xFE, 0x10, 0x43, 0xF8, 0xFF, 0x8F, 0xE1, 0xFC, 0x3F, 0x80, 0x00, 0x39, 0x05, 0x3C, 0xC0,
- 0x0F, 0xE3, 0x8E, 0x3F, 0x8F, 0xF8, 0xFE, 0x1F, 0xC3, 0xF8, 0x00, 0x03, 0x22, 0x27, 0xDC,
- 0x01, 0x87, 0x38, 0xE6, 0x1C, 0xDD, 0x99, 0xF3, 0xFE, 0x61, 0xC0, 0x00, 0x21, 0x50, 0xFE,
- 0xC0, 0x1C, 0x52, 0x8A, 0x71, 0x41, 0x41, 0xC0, 0x3A, 0xE7, 0x14, 0x00, 0x1C, 0x88, 0x9E,
- 0xDC, 0x01, 0x45, 0x28, 0xA5, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51, 0x40, 0x01, 0x94, 0x13,
- 0xEE, 0xC0, 0x14, 0x52, 0x8A, 0x51, 0x41, 0x41, 0x40, 0x2A, 0xA5, 0x14, 0x00, 0x12, 0x22,
- 0x7F, 0xDC, 0x01, 0x47, 0x28, 0xA5, 0x1C, 0x14, 0x14, 0x02, 0xAA, 0x51, 0xC0, 0x0E, 0x05,
- 0x0F, 0x3E, 0xC0, 0x1C, 0x02, 0x8A, 0x70, 0x01, 0x41, 0x4E, 0x2A, 0xA7, 0x00, 0x00, 0xC0,
- 0x09, 0xF0, 0xCC, 0x00, 0xFC, 0x38, 0xE3, 0xF0, 0x14, 0x17, 0x82, 0xAA, 0x3F, 0x00, 0x09,
- 0x01, 0x3F, 0x8F, 0xC0, 0x03, 0xE1, 0xFC, 0x0F, 0x81, 0x41, 0x78, 0x2A, 0xA0, 0xF8, 0x01,
- 0x28, 0x27, 0x98, 0xFC, 0x00, 0x07, 0x0D, 0x80, 0x1C, 0x14, 0x14, 0xE2, 0xAA, 0x01, 0xC0,
- 0x28, 0x40, 0xF8, 0x0C, 0xC0, 0x1C, 0x50, 0x50, 0x71, 0x41, 0x41, 0x40, 0x28, 0xA7, 0x14,
- 0x03, 0x02, 0x9F, 0xC0, 0xFC, 0x01, 0x45, 0x05, 0x05, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51,
- 0x40, 0x32, 0x13, 0xCC, 0x0F, 0xC1, 0x94, 0x50, 0x50, 0x51, 0x41, 0x41, 0x40, 0x28, 0xA5,
- 0x14, 0x01, 0xF2, 0x7C, 0x00, 0xFC, 0x19, 0x47, 0x05, 0x05, 0x1C, 0x14, 0x1C, 0x02, 0x8A,
- 0x51, 0xC0, 0x0E, 0x0F, 0xE0, 0x0F, 0xC1, 0x9C, 0x30, 0x70, 0x70, 0xC1, 0x41, 0x9F, 0x28,
- 0xA7, 0x0C, 0x00, 0x61, 0xE6, 0x00, 0x3F, 0xF8, 0xFE, 0x07, 0x03, 0xF8, 0x1C, 0x0F, 0xE3,
- 0x8E, 0x3F, 0x80, 0x03, 0xBE, 0x00, 0x03, 0xFF, 0x8F, 0xE0, 0xF8, 0x3F, 0x81, 0xC0, 0xFE,
- 0x38, 0xE3, 0xF8, 0x00, 0x1F, 0xF0, 0x0B, 0x0E, 0x00, 0xF3, 0x0B, 0x0E, 0x00, 0x06, 0x00,
- 0x00}};
+const image_t img_csLogo_FULL = { 124, 40, true, 571, 0x0B, { // orig:620, comp:7.90%
+ 0x3F, 0xFF, 0xFE, 0x10, 0x43, 0xF8, 0x7F, 0x0F, 0xE1, 0xFC, 0x0B, 0x05, 0x00, 0x03, 0xFF, 0xFF,
+ 0xE3, 0x8E, 0x3F, 0x87, 0xF0, 0xFE, 0x1F, 0xC0, 0x0B, 0x05, 0x00, 0xFC, 0x00, 0x07, 0x38, 0xE6,
+ 0x1C, 0xE3, 0x80, 0x73, 0x8E, 0x03, 0xBB, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x52, 0x8A, 0x71,
+ 0xCE, 0x39, 0xC7, 0x38, 0xA0, 0x22, 0x10, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x05, 0x28, 0xA7, 0x14,
+ 0xA2, 0x9C, 0x52, 0x8A, 0x03, 0x39, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x52, 0x8A, 0x51, 0x4A,
+ 0x29, 0x45, 0x28, 0xA0, 0x20, 0x90, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x07, 0x28, 0xA5, 0x14, 0xA2,
+ 0x94, 0x52, 0x8E, 0x03, 0xB9, 0x40, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x02, 0x8A, 0x51, 0xCA, 0xA9,
+ 0x47, 0x28, 0x0B, 0x06, 0x00, 0xCC, 0x00, 0x00, 0x38, 0xE5, 0xF0, 0xA2, 0x97, 0xC2, 0x80, 0x06,
+ 0xEE, 0x80, 0x00, 0x00, 0x0E, 0xC3, 0x00, 0x01, 0xFC, 0x5F, 0x0A, 0x29, 0x7C, 0x2B, 0xC0, 0x2A,
+ 0xAA, 0x00, 0x00, 0x00, 0xDC, 0x30, 0x00, 0x0D, 0x85, 0x1C, 0xAA, 0x94, 0xE2, 0xBE, 0x02, 0xEE,
+ 0xE0, 0x00, 0x00, 0x0E, 0xC0, 0x30, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x28, 0xA0, 0x22, 0xA2,
+ 0x00, 0x00, 0x00, 0xDC, 0x04, 0x80, 0x05, 0x05, 0x14, 0xA2, 0x94, 0xA2, 0x8A, 0x07, 0x2E, 0x20,
+ 0x00, 0x08, 0x0E, 0xC0, 0x48, 0x00, 0x50, 0x51, 0x4A, 0x29, 0x4A, 0x38, 0xA0, 0x00, 0x00, 0x00,
+ 0x01, 0x40, 0xDC, 0x03, 0x00, 0x05, 0x07, 0x1C, 0xE3, 0x94, 0xA3, 0x8A, 0x0B, 0x04, 0x00, 0xE2,
+ 0x0C, 0xC0, 0x00, 0x00, 0x70, 0x71, 0xCE, 0x39, 0x4A, 0x30, 0xE0, 0x00, 0x00, 0x00, 0x0C, 0x90,
+ 0xCC, 0x00, 0x00, 0x07, 0x03, 0xF8, 0x7F, 0x1C, 0xE1, 0xFC, 0x0B, 0x04, 0x00, 0x94, 0x8C, 0xC0,
+ 0x00, 0x00, 0xF8, 0x3F, 0x87, 0xF1, 0xC7, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x72, 0x24, 0xCC, 0x0B,
+ 0x0C, 0x00, 0x06, 0x15, 0x2C, 0xC0, 0x0B, 0x0C, 0x00, 0x48, 0x89, 0xCC, 0x00, 0xFE, 0x10, 0x43,
+ 0xF8, 0xFF, 0x8F, 0xE1, 0xFC, 0x3F, 0x80, 0x00, 0x39, 0x05, 0x3C, 0xC0, 0x0F, 0xE3, 0x8E, 0x3F,
+ 0x8F, 0xF8, 0xFE, 0x1F, 0xC3, 0xF8, 0x00, 0x03, 0x22, 0x27, 0xDC, 0x01, 0x87, 0x38, 0xE6, 0x1C,
+ 0xDD, 0x99, 0xF3, 0xFE, 0x61, 0xC0, 0x00, 0x21, 0x50, 0xFE, 0xC0, 0x1C, 0x52, 0x8A, 0x71, 0x41,
+ 0x41, 0xC0, 0x3A, 0xE7, 0x14, 0x00, 0x1C, 0x88, 0x9E, 0xDC, 0x01, 0x45, 0x28, 0xA5, 0x14, 0x14,
+ 0x14, 0x02, 0xAA, 0x51, 0x40, 0x01, 0x94, 0x13, 0xEE, 0xC0, 0x14, 0x52, 0x8A, 0x51, 0x41, 0x41,
+ 0x40, 0x2A, 0xA5, 0x14, 0x00, 0x12, 0x22, 0x7F, 0xDC, 0x01, 0x47, 0x28, 0xA5, 0x1C, 0x14, 0x14,
+ 0x02, 0xAA, 0x51, 0xC0, 0x0E, 0x05, 0x0F, 0x3E, 0xC0, 0x1C, 0x02, 0x8A, 0x70, 0x01, 0x41, 0x4E,
+ 0x2A, 0xA7, 0x00, 0x00, 0xC0, 0x09, 0xF0, 0xCC, 0x00, 0xFC, 0x38, 0xE3, 0xF0, 0x14, 0x17, 0x82,
+ 0xAA, 0x3F, 0x00, 0x09, 0x01, 0x3F, 0x8F, 0xC0, 0x03, 0xE1, 0xFC, 0x0F, 0x81, 0x41, 0x78, 0x2A,
+ 0xA0, 0xF8, 0x01, 0x28, 0x27, 0x98, 0xFC, 0x00, 0x07, 0x0D, 0x80, 0x1C, 0x14, 0x14, 0xE2, 0xAA,
+ 0x01, 0xC0, 0x28, 0x40, 0xF8, 0x0C, 0xC0, 0x1C, 0x50, 0x50, 0x71, 0x41, 0x41, 0x40, 0x28, 0xA7,
+ 0x14, 0x03, 0x02, 0x9F, 0xC0, 0xFC, 0x01, 0x45, 0x05, 0x05, 0x14, 0x14, 0x14, 0x02, 0xAA, 0x51,
+ 0x40, 0x32, 0x13, 0xCC, 0x0F, 0xC1, 0x94, 0x50, 0x50, 0x51, 0x41, 0x41, 0x40, 0x28, 0xA5, 0x14,
+ 0x01, 0xF2, 0x7C, 0x00, 0xFC, 0x19, 0x47, 0x05, 0x05, 0x1C, 0x14, 0x1C, 0x02, 0x8A, 0x51, 0xC0,
+ 0x0E, 0x0F, 0xE0, 0x0F, 0xC1, 0x9C, 0x30, 0x70, 0x70, 0xC1, 0x41, 0x9F, 0x28, 0xA7, 0x0C, 0x00,
+ 0x61, 0xE6, 0x00, 0x3F, 0xF8, 0xFE, 0x07, 0x03, 0xF8, 0x1C, 0x0F, 0xE3, 0x8E, 0x3F, 0x80, 0x03,
+ 0xBE, 0x00, 0x03, 0xFF, 0x8F, 0xE0, 0xF8, 0x3F, 0x81, 0xC0, 0xFE, 0x38, 0xE3, 0xF8, 0x00, 0x1F,
+ 0xF0, 0x0B, 0x0E, 0x00, 0xF3, 0x0B, 0x0E, 0x00, 0x06, 0x00, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c b/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c
index 71debc2ff..5cd2f613f 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_csLogo_Small.c
@@ -13,10 +13,6 @@
#include "images.h"
-const image_t img_csLogo_Small = {
- 9,
- 12,
- false,
- 14,
- 0,
- {0xFF, 0xFF, 0xF0, 0x78, 0x3D, 0x06, 0x3F, 0x13, 0x88, 0xC7, 0xE0, 0x7D, 0x3E, 0xF0}};
+const image_t img_csLogo_Small = { 9, 12, false, 14, 0, {
+ 0xFF, 0xFF, 0xF0, 0x78, 0x3D, 0x06, 0x3F, 0x13, 0x88, 0xC7, 0xE0, 0x7D, 0x3E, 0xF0
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c
index e3622a626..533b79c7b 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_SCL.c
@@ -8,10 +8,6 @@
#include "images.h"
-const image_t img_ecp_SCL = {
- 16,
- 7,
- false,
- 14,
- 0,
- {0x3F, 0x8F, 0x3F, 0x8F, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0xF1, 0xFC, 0xF1, 0xFC}};
+const image_t img_ecp_SCL = { 16, 7, false, 14, 0, {
+ 0x3F, 0x8F, 0x3F, 0x8F, 0x31, 0x8C, 0x31, 0x8C, 0x31, 0x8C, 0xF1, 0xFC, 0xF1, 0xFC
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c
index 5ce0cbec4..7384fc87c 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_SDA.c
@@ -13,7 +13,7 @@
#include "images.h"
-const image_t img_ecp_SDA = {17, 12, false, 26, 0, {0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F,
- 0xFC, 0x0F, 0xFE, 0x43, 0x00, 0x30, 0xC0,
- 0x0C, 0x27, 0xFF, 0x03, 0xFF, 0x80, 0x01,
- 0x80, 0x01, 0x80, 0x00, 0x80}};
+const image_t img_ecp_SDA = { 17, 12, false, 26, 0, {
+ 0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1F, 0xFC, 0x0F, 0xFE, 0x43, 0x00, 0x30, 0xC0, 0x0C, 0x27,
+ 0xFF, 0x03, 0xFF, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x80
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c b/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c
index 60f535458..942f0c593 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_ecp_port.c
@@ -43,30 +43,24 @@
#include "images.h"
-const image_t img_ecp_port = {
- 69,
- 42,
- true,
- 290,
- 0x04,
- {// orig:363, comp:20.11%
- 0x00, 0x2A, 0x04, 0x06, 0xAA, 0xA8, 0x02, 0x04, 0x07, 0xAA, 0x80, 0x2A, 0x04, 0x07, 0xAA,
- 0x02, 0x04, 0x07, 0xAA, 0xA0, 0x2A, 0x04, 0x07, 0xAA, 0x82, 0x04, 0x07, 0xAA, 0xA8, 0x2A,
- 0x04, 0x07, 0xAA, 0xA3, 0x04, 0x07, 0xFF, 0xAA, 0x1F, 0x04, 0x06, 0xFF, 0xFE, 0xA8, 0xC0,
- 0x04, 0x06, 0x00, 0x6A, 0x86, 0x04, 0x06, 0x00, 0x03, 0xAA, 0x30, 0x04, 0x06, 0x00, 0x1A,
- 0xA1, 0x80, 0x04, 0x06, 0x00, 0xEA, 0x8C, 0x04, 0x06, 0x00, 0x06, 0xA8, 0x61, 0x04, 0x05,
- 0xFF, 0xFC, 0x3A, 0xA3, 0x0F, 0x04, 0x05, 0xFF, 0xE1, 0xAA, 0x18, 0x61, 0x83, 0x0C, 0x18,
- 0x60, 0xC3, 0x0E, 0xA8, 0xC3, 0x0C, 0x18, 0x60, 0xC3, 0x06, 0x18, 0x6A, 0x86, 0x18, 0x7F,
- 0xC3, 0xFE, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x86, 0x1A, 0xA1,
- 0x86, 0x04, 0x05, 0x00, 0x30, 0xEA, 0xBC, 0x30, 0x04, 0x04, 0x00, 0x01, 0x86, 0xFB, 0xE1,
- 0x80, 0x04, 0x04, 0x00, 0x0C, 0x3F, 0xFF, 0x0C, 0x04, 0x05, 0x00, 0x61, 0xBE, 0x78, 0x60,
- 0x04, 0x04, 0x00, 0x03, 0x0F, 0xF8, 0xC3, 0x0F, 0xF8, 0x00, 0x03, 0xFE, 0x18, 0x6A, 0x86,
- 0x18, 0x7F, 0xC0, 0x00, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0x06, 0x1F, 0xF0, 0xC1, 0x86,
- 0x1A, 0xA1, 0x86, 0x18, 0x30, 0x80, 0x86, 0x0C, 0x30, 0xEA, 0x8C, 0x3F, 0x04, 0x05, 0xFF,
- 0x86, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x04, 0x06, 0x00, 0x01, 0xAA, 0x18,
- 0x04, 0x06, 0x00, 0x0E, 0xA8, 0xC0, 0x04, 0x06, 0x00, 0x6A, 0x86, 0x00, 0x00, 0x7F, 0xFF,
- 0xF0, 0x00, 0x03, 0xAA, 0x30, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1A, 0xA1, 0x80, 0x00,
- 0x1A, 0xA0, 0x0C, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xEA, 0x00, 0x60, 0x00, 0x06, 0xA0,
- 0x60, 0x00, 0x06, 0xA0, 0x03, 0x00, 0x00, 0x3A, 0x03, 0x00, 0x00, 0x3A, 0x00, 0x18, 0x00,
- 0x01, 0xA0, 0x1F, 0xFF, 0xFF, 0xA0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00,
- 0x07, 0xFF, 0xFF, 0xE0, 0x00}};
+const image_t img_ecp_port = { 69, 42, true, 290, 0x04, { // orig:363, comp:20.11%
+ 0x00, 0x2A, 0x04, 0x06, 0xAA, 0xA8, 0x02, 0x04, 0x07, 0xAA, 0x80, 0x2A, 0x04, 0x07, 0xAA, 0x02,
+ 0x04, 0x07, 0xAA, 0xA0, 0x2A, 0x04, 0x07, 0xAA, 0x82, 0x04, 0x07, 0xAA, 0xA8, 0x2A, 0x04, 0x07,
+ 0xAA, 0xA3, 0x04, 0x07, 0xFF, 0xAA, 0x1F, 0x04, 0x06, 0xFF, 0xFE, 0xA8, 0xC0, 0x04, 0x06, 0x00,
+ 0x6A, 0x86, 0x04, 0x06, 0x00, 0x03, 0xAA, 0x30, 0x04, 0x06, 0x00, 0x1A, 0xA1, 0x80, 0x04, 0x06,
+ 0x00, 0xEA, 0x8C, 0x04, 0x06, 0x00, 0x06, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x0F,
+ 0x04, 0x05, 0xFF, 0xE1, 0xAA, 0x18, 0x61, 0x83, 0x0C, 0x18, 0x60, 0xC3, 0x0E, 0xA8, 0xC3, 0x0C,
+ 0x18, 0x60, 0xC3, 0x06, 0x18, 0x6A, 0x86, 0x18, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xC3, 0xAA, 0x30,
+ 0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x86, 0x1A, 0xA1, 0x86, 0x04, 0x05, 0x00, 0x30, 0xEA, 0xBC, 0x30,
+ 0x04, 0x04, 0x00, 0x01, 0x86, 0xFB, 0xE1, 0x80, 0x04, 0x04, 0x00, 0x0C, 0x3F, 0xFF, 0x0C, 0x04,
+ 0x05, 0x00, 0x61, 0xBE, 0x78, 0x60, 0x04, 0x04, 0x00, 0x03, 0x0F, 0xF8, 0xC3, 0x0F, 0xF8, 0x00,
+ 0x03, 0xFE, 0x18, 0x6A, 0x86, 0x18, 0x7F, 0xC0, 0x00, 0x1F, 0xF0, 0xC3, 0xAA, 0x30, 0xC3, 0x06,
+ 0x1F, 0xF0, 0xC1, 0x86, 0x1A, 0xA1, 0x86, 0x18, 0x30, 0x80, 0x86, 0x0C, 0x30, 0xEA, 0x8C, 0x3F,
+ 0x04, 0x05, 0xFF, 0x86, 0xA8, 0x61, 0x04, 0x05, 0xFF, 0xFC, 0x3A, 0xA3, 0x04, 0x06, 0x00, 0x01,
+ 0xAA, 0x18, 0x04, 0x06, 0x00, 0x0E, 0xA8, 0xC0, 0x04, 0x06, 0x00, 0x6A, 0x86, 0x00, 0x00, 0x7F,
+ 0xFF, 0xF0, 0x00, 0x03, 0xAA, 0x30, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1A, 0xA1, 0x80, 0x00,
+ 0x1A, 0xA0, 0x0C, 0x00, 0x00, 0xEA, 0x0C, 0x00, 0x00, 0xEA, 0x00, 0x60, 0x00, 0x06, 0xA0, 0x60,
+ 0x00, 0x06, 0xA0, 0x03, 0x00, 0x00, 0x3A, 0x03, 0x00, 0x00, 0x3A, 0x00, 0x18, 0x00, 0x01, 0xA0,
+ 0x1F, 0xFF, 0xFF, 0xA0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF,
+ 0xE0, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_Back.c b/applications/plugins/wii_ec_anal/gfx/img_key_Back.c
index 23c17fe2b..d13bcf7f2 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_Back.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_Back.c
@@ -10,5 +10,6 @@
#include "images.h"
-const image_t img_key_Back =
- {9, 9, false, 11, 0, {0x7F, 0x7F, 0xFB, 0xF8, 0x7E, 0xDF, 0xEF, 0xCF, 0xFF, 0x3F, 0x00}};
+const image_t img_key_Back = { 9, 9, false, 11, 0, {
+ 0x7F, 0x7F, 0xFB, 0xF8, 0x7E, 0xDF, 0xEF, 0xCF, 0xFF, 0x3F, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_D.c b/applications/plugins/wii_ec_anal/gfx/img_key_D.c
index 689b9148c..8d182427c 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_D.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_D.c
@@ -9,5 +9,6 @@
#include "images.h"
-const image_t img_key_D =
- {9, 8, false, 9, 0, {0x7F, 0x7F, 0xFF, 0xF8, 0x3E, 0x3F, 0xBF, 0xFE, 0xFE}};
+const image_t img_key_D = { 9, 8, false, 9, 0, {
+ 0x7F, 0x7F, 0xFF, 0xF8, 0x3E, 0x3F, 0xBF, 0xFE, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_L.c b/applications/plugins/wii_ec_anal/gfx/img_key_L.c
index a5fca1a21..1fc5556b1 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_L.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_L.c
@@ -10,5 +10,6 @@
#include "images.h"
-const image_t img_key_L =
- {8, 9, false, 9, 0, {0x7E, 0xFF, 0xF7, 0xE7, 0xC7, 0xE7, 0xF7, 0xFF, 0x7E}};
+const image_t img_key_L = { 8, 9, false, 9, 0, {
+ 0x7E, 0xFF, 0xF7, 0xE7, 0xC7, 0xE7, 0xF7, 0xFF, 0x7E
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_OK.c b/applications/plugins/wii_ec_anal/gfx/img_key_OK.c
index 926d91c2e..ef64128f8 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_OK.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_OK.c
@@ -10,5 +10,6 @@
#include "images.h"
-const image_t img_key_OK =
- {9, 9, false, 11, 0, {0x7F, 0x7F, 0xF8, 0xF8, 0x3C, 0x1E, 0x0F, 0x8F, 0xFF, 0x3F, 0x00}};
+const image_t img_key_OK = { 9, 9, false, 11, 0, {
+ 0x7F, 0x7F, 0xF8, 0xF8, 0x3C, 0x1E, 0x0F, 0x8F, 0xFF, 0x3F, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c b/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c
index aa6f9e692..595f2f431 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_OKi.c
@@ -10,5 +10,6 @@
#include "images.h"
-const image_t img_key_OKi =
- {9, 9, false, 11, 0, {0x7F, 0x60, 0xE7, 0x37, 0xDB, 0xED, 0xF6, 0x73, 0x83, 0x7F, 0x00}};
+const image_t img_key_OKi = { 9, 9, false, 11, 0, {
+ 0x7F, 0x60, 0xE7, 0x37, 0xDB, 0xED, 0xF6, 0x73, 0x83, 0x7F, 0x00
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_R.c b/applications/plugins/wii_ec_anal/gfx/img_key_R.c
index 8b97c7b48..87cc385bc 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_R.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_R.c
@@ -10,5 +10,6 @@
#include "images.h"
-const image_t img_key_R =
- {8, 9, false, 9, 0, {0x7E, 0xFF, 0xEF, 0xE7, 0xE3, 0xE7, 0xEF, 0xFF, 0x7E}};
+const image_t img_key_R = { 8, 9, false, 9, 0, {
+ 0x7E, 0xFF, 0xEF, 0xE7, 0xE3, 0xE7, 0xEF, 0xFF, 0x7E
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_U.c b/applications/plugins/wii_ec_anal/gfx/img_key_U.c
index 65f4cd9e0..aca5bb62a 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_U.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_U.c
@@ -9,5 +9,6 @@
#include "images.h"
-const image_t img_key_U =
- {9, 8, false, 9, 0, {0x7F, 0x7F, 0xFD, 0xFC, 0x7C, 0x1F, 0xFF, 0xFE, 0xFE}};
+const image_t img_key_U = { 9, 8, false, 9, 0, {
+ 0x7F, 0x7F, 0xFD, 0xFC, 0x7C, 0x1F, 0xFF, 0xFE, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c b/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c
index 30c60c66e..b740780ad 100644
--- a/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c
+++ b/applications/plugins/wii_ec_anal/gfx/img_key_Ui.c
@@ -9,5 +9,6 @@
#include "images.h"
-const image_t img_key_Ui =
- {9, 8, false, 9, 0, {0x7F, 0x60, 0xE2, 0x33, 0x9B, 0xEC, 0x07, 0x06, 0xFE}};
+const image_t img_key_Ui = { 9, 8, false, 9, 0, {
+ 0x7F, 0x60, 0xE2, 0x33, 0x9B, 0xEC, 0x07, 0x06, 0xFE
+}};
diff --git a/applications/plugins/wii_ec_anal/i2c_workaround.h b/applications/plugins/wii_ec_anal/i2c_workaround.h
index b24efaf48..de1dbba54 100644
--- a/applications/plugins/wii_ec_anal/i2c_workaround.h
+++ b/applications/plugins/wii_ec_anal/i2c_workaround.h
@@ -40,70 +40,62 @@ void furi_hal_i2c_release (FuriHalI2cBusHandle* handle)
*/
-#ifndef I2C_WORKAROUND_H_
-#define I2C_WORKAROUND_H_
+#ifndef I2C_WORKAROUND_H_
+#define I2C_WORKAROUND_H_
-#include
+#include
#define ENABLE_WORKAROUND 1
#if ENABLE_WORKAROUND == 1
-//+============================================================================ ========================================
-static inline bool furi_hal_Wi2c_is_device_ready(
- FuriHalI2cBusHandle* const bus,
- const uint8_t addr,
- const uint32_t tmo) {
- furi_hal_i2c_acquire(bus);
- bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo);
- furi_hal_i2c_release(bus);
- return rv;
-}
+ //+============================================================================ ========================================
+ static inline
+ bool furi_hal_Wi2c_is_device_ready (FuriHalI2cBusHandle* const bus, const uint8_t addr, const uint32_t tmo)
+ {
+ furi_hal_i2c_acquire(bus);
+ bool rv = furi_hal_i2c_is_device_ready(bus, addr, tmo);
+ furi_hal_i2c_release(bus);
+ return rv;
+ }
-//+============================================================================
-static inline bool furi_hal_Wi2c_tx(
- FuriHalI2cBusHandle* const bus,
- const uint8_t addr,
- const void* buf,
- const size_t len,
- const uint32_t tmo) {
- furi_hal_i2c_acquire(bus);
- bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo);
- furi_hal_i2c_release(bus);
- return rv;
-}
+ //+============================================================================
+ static inline
+ bool furi_hal_Wi2c_tx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
+ const void* buf, const size_t len, const uint32_t tmo )
+ {
+ furi_hal_i2c_acquire(bus);
+ bool rv = furi_hal_i2c_tx(bus, addr, buf, len, tmo);
+ furi_hal_i2c_release(bus);
+ return rv;
+ }
-//+============================================================================
-static inline bool furi_hal_Wi2c_rx(
- FuriHalI2cBusHandle* const bus,
- const uint8_t addr,
- void* buf,
- const size_t len,
- const uint32_t tmo) {
- furi_hal_i2c_acquire(bus);
- bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo);
- furi_hal_i2c_release(bus);
- return rv;
-}
+ //+============================================================================
+ static inline
+ bool furi_hal_Wi2c_rx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
+ void* buf, const size_t len, const uint32_t tmo )
+ {
+ furi_hal_i2c_acquire(bus);
+ bool rv = furi_hal_i2c_rx(bus, addr, buf, len, tmo);
+ furi_hal_i2c_release(bus);
+ return rv;
+ }
-//+============================================================================
-static inline bool furi_hal_Wi2c_trx(
- FuriHalI2cBusHandle* const bus,
- const uint8_t addr,
- const void* tx,
- const size_t txlen,
- void* rx,
- const size_t rxlen,
- const uint32_t tmo) {
- bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo);
- if(rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo);
- return rv;
-}
+ //+============================================================================
+ static inline
+ bool furi_hal_Wi2c_trx ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
+ const void* tx, const size_t txlen,
+ void* rx, const size_t rxlen, const uint32_t tmo )
+ {
+ bool rv = furi_hal_Wi2c_tx(bus, addr, tx, txlen, tmo);
+ if (rv) rv = furi_hal_Wi2c_rx(bus, addr, rx, rxlen, tmo);
+ return rv;
+ }
-//----------------------------------------------------------------------------- ----------------------------------------
-#define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__)
-#define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__)
-#define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__)
-#define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__)
+ //----------------------------------------------------------------------------- ----------------------------------------
+# define furi_hal_i2c_is_device_ready(...) furi_hal_Wi2c_is_device_ready(__VA_ARGS__)
+# define furi_hal_i2c_tx(...) furi_hal_Wi2c_tx(__VA_ARGS__)
+# define furi_hal_i2c_rx(...) furi_hal_Wi2c_rx(__VA_ARGS__)
+# define furi_hal_i2c_trx(...) furi_hal_Wi2c_trx(__VA_ARGS__)
#endif //ENABLE_WORKAROUND
@@ -111,21 +103,17 @@ static inline bool furi_hal_Wi2c_trx(
// Some devices take a moment to respond to read requests
// The puts a delay between the address being set and the data being read
//
-static inline bool furi_hal_i2c_trxd(
- FuriHalI2cBusHandle* const bus,
- const uint8_t addr,
- const void* tx,
- const size_t txlen,
- void* rx,
- const size_t rxlen,
- const uint32_t tmo,
- const uint32_t us) {
- bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo);
- if(rv) {
- furi_delay_us(us);
- rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo);
- }
- return rv;
+static inline
+bool furi_hal_i2c_trxd ( FuriHalI2cBusHandle* const bus, const uint8_t addr,
+ const void* tx, const size_t txlen,
+ void* rx, const size_t rxlen, const uint32_t tmo, const uint32_t us )
+{
+ bool rv = furi_hal_i2c_tx(bus, addr, tx, txlen, tmo);
+ if (rv) {
+ furi_delay_us(us);
+ rv = furi_hal_i2c_rx(bus, addr, rx, rxlen, tmo);
+ }
+ return rv;
}
#endif //I2C_WORKAROUND_H_
diff --git a/applications/plugins/wii_ec_anal/notes.txt b/applications/plugins/wii_ec_anal/notes.txt
deleted file mode 100644
index 61b6e29af..000000000
--- a/applications/plugins/wii_ec_anal/notes.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-//+============================================================================ ========================================
-// Select font
-// A full list of u8g2 fonts can be found here:
-// https://github.com/olikraus/u8g2/wiki/fntlistall
-// ...and here are the ones available in FZ (currently: all of them):
-// grep -P '.*u8g2.*\[[0-9]*\]' lib/u8g2/u8g2_fonts.c | sed 's/.*\(u8g2_.*\)\[.*/\1/'
-//
-#if 0 //! Extra fonts is just too memory hungry
-#include
-void setFont (Canvas* const canvas, const uint8_t* font)
-{
- u8g2_SetFontMode(&canvas->fb, 1); // no idea - but canvas.c does it
- u8g2_SetFont(&canvas->fb, font);
-}
-#endif
-
-litui : @BlueChip for posterity, the function to break at is flipper_application_spawn. At that point, you can set new breakpoints in your fap code and continue.
-
-/*
-
-This is wrong on quite a few levels!
-https://training.ti.com/introduction-i2c-reserved-addresses
-
-void doit (void)
-{
- furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
- printf("Scanning external i2c on PC0(SCL)/PC1(SDA)\r\n"
- "Clock: 100khz, 7bit address\r\n"
- "\r\n");
- printf(" | 0 1 2 3 4 5 6 7 8 9 A B C D E F\r\n");
- printf("--+--------------------------------\r\n");
- for(uint8_t row = 0; row < 0x8; row++) {
- printf("%x | ", row);
- for(uint8_t column = 0; column <= 0xF; column++) {
- bool ret = furi_hal_i2c_is_device_ready(
- &furi_hal_i2c_handle_external, ((row << 4) + column) << 1, 2);
- printf("%c ", ret ? '#' : '-');
- }
- printf("\r\n");
- }
- furi_hal_i2c_release(&furi_hal_i2c_handle_external);
-}
-*/
-
-
-region locking : firmware/targets/f7/furi_hal/furi_hal_region.c
-
-
-# if 0 //! scrolling works beautifully, but the LCD refresh can't keep up :(
- // Waveform
- if (cnt) { // start
- for (int a = ACC_1; a < ACC_N; a++) {
- canvas_draw_dot(canvas, x,y[a]+v[a][idx]);
- for (int i = 1; i < aw -cnt; i++) {
- canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
- }
- }
- } else { // scroll
- for (int a = ACC_1; a < ACC_N; a++) {
- for (int i = 0; i < aw; i++) {
- int off = (idx +i) %aw;
- int prev = off ? off-1 : aw-1;
- canvas_draw_line(canvas, x+i,y[a]+v[a][prev] , x+i,y[a]+v[a][off]);
- }
- }
- }
-
-# else
- int end = idx ? idx : aw;
- for (int a = ACC_1; a < ACC_N; a++) {
- canvas_draw_dot(canvas, x,y[a]+v[a][idx]);
- if (state->apause) {
- for (int i = 1; i < end; i++)
- canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
- } else {
- for (int i = 1; i < end; i++)
- canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
- for (int i = end+10; i < aw -cnt; i++)
- canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
- }
- }
-
- // Wipe bar
- if (end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
- if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
- if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
-# endif
diff --git a/applications/plugins/wii_ec_anal/wii_anal.c b/applications/plugins/wii_ec_anal/wii_anal.c
index f0af1c9c5..fdf718b63 100644
--- a/applications/plugins/wii_ec_anal/wii_anal.c
+++ b/applications/plugins/wii_ec_anal/wii_anal.c
@@ -3,34 +3,34 @@
//
// System libs
-#include // malloc
-#include // uint32_t
-#include // __VA_ARGS__
-#include
-#include
+#include // malloc
+#include // uint32_t
+#include // __VA_ARGS__
+#include
+#include
// FlipperZero libs
-#include // Core API
-#include // GUI (screen/keyboard) API
-#include // GUI Input extensions
-#include
+#include // Core API
+#include // GUI (screen/keyboard) API
+#include // GUI Input extensions
+#include
// Do this first!
#define ERR_C_ // Do this in precisely ONE file
-#include "err.h" // Error numbers & messages
+#include "err.h" // Error numbers & messages
-#include "bc_logging.h"
+#include "bc_logging.h"
// Local headers
-#include "wii_anal.h" // Various enums and struct declarations
-#include "wii_i2c.h" // Wii i2c functions
-#include "wii_ec.h" // Wii Extension Controller functions (eg. draw)
-#include "wii_anal_keys.h" // key mappings
-#include "gfx/images.h" // Images
-#include "wii_anal_lcd.h" // Drawing functions
-#include "wii_anal_ec.h" // Wii controller events
+#include "wii_anal.h" // Various enums and struct declarations
+#include "wii_i2c.h" // Wii i2c functions
+#include "wii_ec.h" // Wii Extension Controller functions (eg. draw)
+#include "wii_anal_keys.h" // key mappings
+#include "gfx/images.h" // Images
+#include "wii_anal_lcd.h" // Drawing functions
+#include "wii_anal_ec.h" // Wii controller events
-#include "wii_anal_ver.h" // Version number
+#include "wii_anal_ver.h" // Version number
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OOOOO // SSSSS CCCCC AAA L L BBBB AAA CCCC K K SSSSS
@@ -44,42 +44,48 @@
// OS Callback : Timer tick
// We register this function to be called when the OS signals a timer 'tick' event
//
-static void cbTimer(FuriMessageQueue* queue) {
- ENTER;
- furi_assert(queue);
+static
+void cbTimer (FuriMessageQueue* queue)
+{
+ ENTER;
+ furi_assert(queue);
- eventMsg_t message = {.id = EVID_TICK};
- furi_message_queue_put(queue, &message, 0);
+ eventMsg_t message = {.id = EVID_TICK};
+ furi_message_queue_put(queue, &message, 0);
- LEAVE;
- return;
+ LEAVE;
+ return;
}
//+============================================================================ ========================================
// OS Callback : Keypress
// We register this function to be called when the OS detects a keypress
//
-static void cbInput(InputEvent* event, FuriMessageQueue* queue) {
- ENTER;
- furi_assert(queue);
- furi_assert(event);
+static
+void cbInput (InputEvent* event, FuriMessageQueue* queue)
+{
+ ENTER;
+ furi_assert(queue);
+ furi_assert(event);
- // Put an "input" event message on the message queue
- eventMsg_t message = {.id = EVID_KEY, .input = *event};
- furi_message_queue_put(queue, &message, FuriWaitForever);
+ // Put an "input" event message on the message queue
+ eventMsg_t message = {.id = EVID_KEY, .input = *event};
+ furi_message_queue_put(queue, &message, FuriWaitForever);
- LEAVE;
- return;
+ LEAVE;
+ return;
}
//+============================================================================
// Show version number
//
-static void showVer(Canvas* const canvas) {
- show(canvas, 0, 59, &img_3x5_v, SHOW_SET_BLK);
- 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);
+static
+void showVer (Canvas* const canvas)
+{
+ show(canvas, 0,59, &img_3x5_v, SHOW_SET_BLK);
+ 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);
}
//+============================================================================
@@ -89,103 +95,105 @@ static void showVer(Canvas* const canvas) {
// We actually instruct the OS to perform this request, after we update the interface
// I guess it's possible that this instruction may able be issued by other threads !?
//
-static void cbDraw(Canvas* const canvas, void* ctx) {
- ENTER;
- furi_assert(canvas);
- furi_assert(ctx);
+static
+void cbDraw (Canvas* const canvas, void* ctx)
+{
+ ENTER;
+ furi_assert(canvas);
+ furi_assert(ctx);
- state_t* state = NULL;
+ state_t* state = NULL;
- // Try to acquire the mutex for the plugin state variables, timeout = 25mS
- if(!(state = (state_t*)acquire_mutex((ValueMutex*)ctx, 25))) return;
+ // Try to acquire the mutex for the plugin state variables, timeout = 25mS
+ if ( !(state = (state_t*)acquire_mutex((ValueMutex*)ctx, 25)) ) return ;
- switch(state->scene) {
- //---------------------------------------------------------------------
- case SCENE_SPLASH:
- show(canvas, 2, 0, &img_csLogo_FULL, SHOW_SET_BLK);
+ switch (state->scene) {
+ //---------------------------------------------------------------------
+ case SCENE_SPLASH:
+ show(canvas, 2,0, &img_csLogo_FULL, SHOW_SET_BLK);
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str_aligned(canvas, 64, 43, AlignCenter, AlignTop, "Wii Extension Controller");
- canvas_draw_str_aligned(canvas, 64, 55, AlignCenter, AlignTop, "Protocol Analyser");
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_aligned(canvas, 64,43, AlignCenter, AlignTop, "Wii Extension Controller");
+ canvas_draw_str_aligned(canvas, 64,55, AlignCenter, AlignTop, "Protocol Analyser");
- showVer(canvas);
+ showVer(canvas);
- break;
+ break;
- //---------------------------------------------------------------------
- case SCENE_RIP:
- show(canvas, 0, 0, &img_RIP, SHOW_SET_BLK);
- break;
+ //---------------------------------------------------------------------
+ case SCENE_RIP:
+ show(canvas, 0,0, &img_RIP, SHOW_SET_BLK);
+ break;
- //---------------------------------------------------------------------
- case SCENE_WAIT:
-#define xo 2
+ //---------------------------------------------------------------------
+ case SCENE_WAIT:
+# define xo 2
- show(canvas, 3 + xo, 10, &img_ecp_port, SHOW_SET_BLK);
+ show(canvas, 3+xo,10, &img_ecp_port, SHOW_SET_BLK);
- BOX_TL(22 + xo, 6, 82 + xo, 23); // 3v3
- BOX_TL(48 + xo, 21, 82 + xo, 23); // C1
- BOX_BL(22 + xo, 41, 82 + xo, 58); // C0
- BOX_BL(48 + xo, 41, 82 + xo, 44); // Gnd
+ BOX_TL(22+xo, 6, 82+xo,23); // 3v3
+ BOX_TL(48+xo,21, 82+xo,23); // C1
+ BOX_BL(22+xo,41, 82+xo,58); // C0
+ BOX_BL(48+xo,41, 82+xo,44); // Gnd
- show(canvas, 90 + xo, 3, &img_6x8_3, SHOW_SET_BLK); // 3v3
- show(canvas, 97 + xo, 3, &img_6x8_v, SHOW_SET_BLK);
- show(canvas, 104 + xo, 3, &img_6x8_3, SHOW_SET_BLK);
+ show(canvas, 90+xo, 3, &img_6x8_3, SHOW_SET_BLK); // 3v3
+ show(canvas, 97+xo, 3, &img_6x8_v, SHOW_SET_BLK);
+ show(canvas, 104+xo, 3, &img_6x8_3, SHOW_SET_BLK);
- show(canvas, 90 + xo, 18, &img_6x8_C, SHOW_SET_BLK); // C1 <->
- show(canvas, 98 + xo, 18, &img_6x8_1, SHOW_SET_BLK);
- show(canvas, 107 + xo, 16, &img_ecp_SDA, SHOW_SET_BLK);
+ show(canvas, 90+xo,18, &img_6x8_C, SHOW_SET_BLK); // C1 <->
+ show(canvas, 98+xo,18, &img_6x8_1, SHOW_SET_BLK);
+ show(canvas, 107+xo,16, &img_ecp_SDA, SHOW_SET_BLK);
- show(canvas, 90 + xo, 40, &img_6x8_G, SHOW_SET_BLK); // Gnd
- show(canvas, 97 + xo, 40, &img_6x8_n, SHOW_SET_BLK);
- show(canvas, 104 + xo, 40, &img_6x8_d, SHOW_SET_BLK);
+ show(canvas, 90+xo,40, &img_6x8_G, SHOW_SET_BLK); // Gnd
+ show(canvas, 97+xo,40, &img_6x8_n, SHOW_SET_BLK);
+ show(canvas, 104+xo,40, &img_6x8_d, SHOW_SET_BLK);
- show(canvas, 90 + xo, 54, &img_6x8_C, SHOW_SET_BLK); // C0 _-_-
- show(canvas, 98 + xo, 54, &img_6x8_0, SHOW_SET_BLK);
- show(canvas, 108 + xo, 54, &img_ecp_SCL, SHOW_SET_BLK);
+ show(canvas, 90+xo,54, &img_6x8_C, SHOW_SET_BLK); // C0 _-_-
+ show(canvas, 98+xo,54, &img_6x8_0, SHOW_SET_BLK);
+ show(canvas, 108+xo,54, &img_ecp_SCL, SHOW_SET_BLK);
- show(canvas, 0, 0, &img_csLogo_Small, SHOW_SET_BLK);
- showVer(canvas);
+ show(canvas, 0,0, &img_csLogo_Small, SHOW_SET_BLK);
+ showVer(canvas);
-#undef xo
- break;
+# undef xo
+ break;
- //---------------------------------------------------------------------
- case SCENE_DEBUG:
- canvas_set_font(canvas, FontSecondary);
+ //---------------------------------------------------------------------
+ case SCENE_DEBUG:
+ canvas_set_font(canvas, FontSecondary);
- show(canvas, 0, 0, &img_key_U, SHOW_SET_BLK);
- canvas_draw_str_aligned(canvas, 11, 0, AlignLeft, AlignTop, "Initialise Perhipheral");
+ show(canvas, 0,0, &img_key_U, SHOW_SET_BLK);
+ canvas_draw_str_aligned(canvas, 11, 0, AlignLeft, AlignTop, "Initialise Perhipheral");
- show(canvas, 0, 11, &img_key_OK, SHOW_SET_BLK);
- canvas_draw_str_aligned(canvas, 11, 11, AlignLeft, AlignTop, "Read values [see log]");
+ show(canvas, 0,11, &img_key_OK, SHOW_SET_BLK);
+ canvas_draw_str_aligned(canvas, 11,11, AlignLeft, AlignTop, "Read values [see log]");
- show(canvas, 0, 23, &img_key_D, SHOW_SET_BLK);
- canvas_draw_str_aligned(canvas, 11, 22, AlignLeft, AlignTop, "Restart Scanner");
+ show(canvas, 0,23, &img_key_D, SHOW_SET_BLK);
+ canvas_draw_str_aligned(canvas, 11,22, AlignLeft, AlignTop, "Restart Scanner");
- show(canvas, 0, 33, &img_key_Back, SHOW_SET_BLK);
- canvas_draw_str_aligned(canvas, 11, 33, AlignLeft, AlignTop, "Exit");
+ show(canvas, 0,33, &img_key_Back, SHOW_SET_BLK);
+ canvas_draw_str_aligned(canvas, 11,33, AlignLeft, AlignTop, "Exit");
- break;
+ break ;
- //---------------------------------------------------------------------
- default:
- if(state->ec.pidx >= PID_ERROR) {
- ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
- } else {
- if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].show)
- ecId[PID_UNKNOWN].show(canvas, state);
- else
- ecId[state->ec.pidx].show(canvas, state);
- }
- break;
- }
+ //---------------------------------------------------------------------
+ default:
+ if (state->ec.pidx >= PID_ERROR) {
+ ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
+ } else {
+ if ((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].show)
+ ecId[PID_UNKNOWN].show(canvas, state);
+ else
+ ecId[state->ec.pidx].show(canvas, state);
+ }
+ break;
+ }
- // Release the mutex
- release_mutex((ValueMutex*)ctx, state);
+ // Release the mutex
+ release_mutex((ValueMutex*)ctx, state);
- LEAVE;
- return;
+ LEAVE;
+ return;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -199,54 +207,56 @@ static void cbDraw(Canvas* const canvas, void* ctx) {
//+============================================================================ ========================================
// Initialise plugin state variables
//
-static inline bool stateInit(state_t* const state) {
- ENTER;
- furi_assert(state);
+static inline
+bool stateInit (state_t* const state)
+{
+ ENTER;
+ furi_assert(state);
- bool rv = true; // assume success
+ bool rv = true; // assume success
- // Enable the main loop
- state->run = true;
+ // Enable the main loop
+ state->run = true;
- // Timer
- state->timerEn = false;
- state->timer = NULL;
- state->timerHz = furi_kernel_get_tick_frequency();
- state->fps = 30;
+ // Timer
+ state->timerEn = false;
+ state->timer = NULL;
+ state->timerHz = furi_kernel_get_tick_frequency();
+ state->fps = 30;
- // Scene
- state->scene = SCENE_SPLASH;
- state->scenePrev = SCENE_NONE;
- state->scenePegg = SCENE_NONE;
+ // Scene
+ state->scene = SCENE_SPLASH;
+ state->scenePrev = SCENE_NONE;
+ state->scenePegg = SCENE_NONE;
- state->hold = 0; // show hold meters (-1=lowest, 0=current, +1=highest}
- state->calib = CAL_TRACK;
- state->pause = false; // animation running
- state->apause = false; // auto-pause animation
+ state->hold = 0; // show hold meters (-1=lowest, 0=current, +1=highest}
+ state->calib = CAL_TRACK;
+ state->pause = false; // animation running
+ state->apause = false; // auto-pause animation
- // Notifications
- state->notify = NULL;
+ // Notifications
+ state->notify = NULL;
- // Perhipheral
- state->ec.init = false;
- state->ec.pidx = PID_UNKNOWN;
- state->ec.sid = ecId[state->ec.pidx].name;
+ // Perhipheral
+ state->ec.init = false;
+ state->ec.pidx = PID_UNKNOWN;
+ state->ec.sid = ecId[state->ec.pidx].name;
- // Controller data
- memset(state->ec.pid, 0xC5, PID_LEN); // Cyborg 5ystems
- memset(state->ec.calF, 0xC5, CAL_LEN);
- memset(state->ec.joy, 0xC5, JOY_LEN);
+ // Controller data
+ memset(state->ec.pid, 0xC5, PID_LEN); // Cyborg 5ystems
+ memset(state->ec.calF, 0xC5, CAL_LEN);
+ memset(state->ec.joy, 0xC5, JOY_LEN);
- // Encryption details
- state->ec.encrypt = false;
- memset(state->ec.encKey, 0x00, ENC_LEN);
+ // Encryption details
+ state->ec.encrypt = false;
+ memset(state->ec.encKey, 0x00, ENC_LEN);
- // Seed the PRNG
- // CYCCNT --> lib/STM32CubeWB/Drivers/CMSIS/Include/core_cm7.h
- // srand(DWT->CYCCNT);
+ // Seed the PRNG
+ // CYCCNT --> lib/STM32CubeWB/Drivers/CMSIS/Include/core_cm7.h
+// srand(DWT->CYCCNT);
- LEAVE;
- return rv;
+ LEAVE;
+ return rv;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -260,284 +270,271 @@ static inline bool stateInit(state_t* const state) {
//+============================================================================ ========================================
// Enable/Disable scanning
//
-void timerEn(state_t* state, bool on) {
- ENTER;
- furi_assert(state);
+void timerEn (state_t* state, bool on)
+{
+ ENTER;
+ furi_assert(state);
- // ENable scanning
- if(on) {
- if(state->timerEn) {
- WARN(wii_errs[WARN_SCAN_START]);
- } else {
- // Set the timer to fire at 'fps' times/second
- if(furi_timer_start(state->timer, state->timerHz / state->fps) == FuriStatusOk) {
- state->timerEn = true;
- INFO("%s : monitor started", __func__);
- } else {
- ERROR(wii_errs[ERR_TIMER_START]);
- }
- }
+ // ENable scanning
+ if (on) {
+ if (state->timerEn) {
+ WARN(wii_errs[WARN_SCAN_START]);
+ } else {
+ // Set the timer to fire at 'fps' times/second
+ if (furi_timer_start(state->timer, state->timerHz/state->fps) == FuriStatusOk) {
+ state->timerEn = true;
+ INFO("%s : monitor started", __func__);
+ } else {
+ ERROR(wii_errs[ERR_TIMER_START]);
+ }
+ }
- // DISable scanning
- } else {
- if(!state->timerEn) {
- WARN(wii_errs[WARN_SCAN_STOP]);
- } else {
- // Stop the timer
- if(furi_timer_stop(state->timer) == FuriStatusOk) {
- state->timerEn = false;
- INFO("%s : monitor stopped", __func__);
- } else {
- ERROR(wii_errs[ERR_TIMER_STOP]);
- }
- }
- }
+ // DISable scanning
+ } else {
+ if (!state->timerEn) {
+ WARN(wii_errs[WARN_SCAN_STOP]);
+ } else {
+ // Stop the timer
+ if (furi_timer_stop(state->timer) == FuriStatusOk) {
+ state->timerEn = false;
+ INFO("%s : monitor stopped", __func__);
+ } else {
+ ERROR(wii_errs[ERR_TIMER_STOP]);
+ }
+ }
+ }
- LEAVE;
- return;
+ LEAVE;
+ return;
}
//+============================================================================ ========================================
// Plugin entry point
//
-int32_t wii_ec_anal(void) {
- ENTER;
+int32_t wii_ec_anal (void)
+{
+ ENTER;
- // ===== Variables =====
- err_t error = 0; // assume success
- Gui* gui = NULL;
- ViewPort* vpp = NULL;
- state_t* state = NULL;
- ValueMutex mutex = {0};
- FuriMessageQueue* queue = NULL;
- const uint32_t queueSz = 20; // maximum messages in queue
- uint32_t tmo = (3.5f * 1000); // timeout splash screen after N seconds
+ // ===== Variables =====
+ err_t error = 0; // assume success
+ Gui* gui = NULL;
+ ViewPort* vpp = NULL;
+ state_t* state = NULL;
+ ValueMutex mutex = {0};
+ FuriMessageQueue* queue = NULL;
+ const uint32_t queueSz = 20; // maximum messages in queue
+ uint32_t tmo = (3.5f *1000); // timeout splash screen after N seconds
- // The queue will contain plugin event-messages
- // --> local
- eventMsg_t msg = {0};
+ // The queue will contain plugin event-messages
+ // --> local
+ eventMsg_t msg = {0};
- INFO("BEGIN");
+ INFO("BEGIN");
- // ===== Message queue =====
- // 1. Create a message queue (for up to 8 (keyboard) event messages)
- if(!(queue = furi_message_queue_alloc(queueSz, sizeof(msg)))) {
- ERROR(wii_errs[(error = ERR_MALLOC_QUEUE)]);
- goto bail;
- }
+ // ===== Message queue =====
+ // 1. Create a message queue (for up to 8 (keyboard) event messages)
+ if ( !(queue = furi_message_queue_alloc(queueSz, sizeof(msg))) ) {
+ ERROR(wii_errs[(error = ERR_MALLOC_QUEUE)]);
+ goto bail;
+ }
- // ===== Create GUI Interface =====
- // 2. Create a GUI interface
- if(!(gui = furi_record_open("gui"))) {
- ERROR(wii_errs[(error = ERR_NO_GUI)]);
- goto bail;
- }
+ // ===== Create GUI Interface =====
+ // 2. Create a GUI interface
+ if ( !(gui = furi_record_open("gui")) ) {
+ ERROR(wii_errs[(error = ERR_NO_GUI)]);
+ goto bail;
+ }
- // ===== Plugin state variables =====
- // 3. Allocate space on the heap for the plugin state variables
- if(!(state = malloc(sizeof(state_t)))) {
- ERROR(wii_errs[(error = ERR_MALLOC_STATE)]);
- goto bail;
- }
- // 4. Initialise the plugin state variables
- if(!stateInit(state)) {
- // error message(s) is/are output by stateInit()
- error = 15;
- goto bail;
- }
- // 5. Create a mutex for (reading/writing) the plugin state variables
- if(!init_mutex(&mutex, state, sizeof(state))) {
- ERROR(wii_errs[(error = ERR_NO_MUTEX)]);
- goto bail;
- }
+ // ===== Plugin state variables =====
+ // 3. Allocate space on the heap for the plugin state variables
+ if ( !(state = malloc(sizeof(state_t))) ) {
+ ERROR(wii_errs[(error = ERR_MALLOC_STATE)]);
+ goto bail;
+ }
+ // 4. Initialise the plugin state variables
+ if (!stateInit(state)) {
+ // error message(s) is/are output by stateInit()
+ error = 15;
+ goto bail;
+ }
+ // 5. Create a mutex for (reading/writing) the plugin state variables
+ if (!init_mutex(&mutex, state, sizeof(state))) {
+ ERROR(wii_errs[(error = ERR_NO_MUTEX)]);
+ goto bail;
+ }
- // ===== Viewport =====
- // 6. Allocate space on the heap for the viewport
- if(!(vpp = view_port_alloc())) {
- ERROR(wii_errs[(error = ERR_MALLOC_VIEW)]);
- goto bail;
- }
- // 7a. Register a callback for input events
- view_port_input_callback_set(vpp, cbInput, queue);
- // 7b. Register a callback for draw events
- view_port_draw_callback_set(vpp, cbDraw, &mutex);
+ // ===== Viewport =====
+ // 6. Allocate space on the heap for the viewport
+ if ( !(vpp = view_port_alloc()) ) {
+ ERROR(wii_errs[(error = ERR_MALLOC_VIEW)]);
+ goto bail;
+ }
+ // 7a. Register a callback for input events
+ view_port_input_callback_set(vpp, cbInput, queue);
+ // 7b. Register a callback for draw events
+ view_port_draw_callback_set(vpp, cbDraw, &mutex);
- // ===== Start GUI Interface =====
- // 8. Attach the viewport to the GUI
- gui_add_view_port(gui, vpp, GuiLayerFullscreen);
+ // ===== Start GUI Interface =====
+ // 8. Attach the viewport to the GUI
+ gui_add_view_port(gui, vpp, GuiLayerFullscreen);
- // ===== Timer =====
- // 9. Allocate a timer
- if(!(state->timer = furi_timer_alloc(cbTimer, FuriTimerTypePeriodic, queue))) {
- ERROR(wii_errs[(error = ERR_NO_TIMER)]);
- goto bail;
- }
+ // ===== Timer =====
+ // 9. Allocate a timer
+ if ( !(state->timer = furi_timer_alloc(cbTimer, FuriTimerTypePeriodic, queue)) ) {
+ ERROR(wii_errs[(error = ERR_NO_TIMER)]);
+ goto bail;
+ }
- // === System Notifications ===
- // 10. Acquire a handle for the system notification queue
- if(!(state->notify = furi_record_open(RECORD_NOTIFICATION))) {
- ERROR(wii_errs[(error = ERR_NO_NOTIFY)]);
- goto bail;
- }
- patBacklight(state); // Turn on the backlight [qv. remote FAP launch]
+ // === System Notifications ===
+ // 10. Acquire a handle for the system notification queue
+ if ( !(state->notify = furi_record_open(RECORD_NOTIFICATION)) ) {
+ ERROR(wii_errs[(error = ERR_NO_NOTIFY)]);
+ goto bail;
+ }
+ patBacklight(state); // Turn on the backlight [qv. remote FAP launch]
- INFO("INITIALISED");
+ INFO("INITIALISED");
- // ==================== Main event loop ====================
+ // ==================== Main event loop ====================
- if(state->run) do {
- bool redraw = false;
- FuriStatus status = FuriStatusErrorTimeout;
+ if (state->run) do {
+ bool redraw = false;
+ FuriStatus status = FuriStatusErrorTimeout;
- // Wait for a message
- // while ((status = furi_message_queue_get(queue, &msg, tmo)) == FuriStatusErrorTimeout) ;
- status = furi_message_queue_get(queue, &msg, tmo);
+ // Wait for a message
+// while ((status = furi_message_queue_get(queue, &msg, tmo)) == FuriStatusErrorTimeout) ;
+ status = furi_message_queue_get(queue, &msg, tmo);
- // Clear splash screen
- if((state->scene == SCENE_SPLASH) &&
- (state->scenePrev == SCENE_NONE) && // Initial splash
- ((status == FuriStatusErrorTimeout) || // timeout
- ((msg.id == EVID_KEY) && (msg.input.type == InputTypeShort))) // or key-short
- ) {
- tmo = 60 * 1000; // increase message-wait timeout to 60secs
- timerEn(state, true); // start scanning the i2c bus
- status = FuriStatusOk; // pass status check
- msg.id = EVID_NONE; // valid msg ID
- sceneSet(state, SCENE_WAIT); // move to wait screen
- }
+ // Clear splash screen
+ if ( (state->scene == SCENE_SPLASH) && (state->scenePrev == SCENE_NONE) && // Initial splash
+ ( (status == FuriStatusErrorTimeout) || // timeout
+ ((msg.id == EVID_KEY) && (msg.input.type == InputTypeShort)) ) // or key-short
+ ) {
+ tmo = 60 *1000; // increase message-wait timeout to 60secs
+ timerEn(state, true); // start scanning the i2c bus
+ status = FuriStatusOk; // pass status check
+ msg.id = EVID_NONE; // valid msg ID
+ sceneSet(state, SCENE_WAIT); // move to wait screen
+ }
- // Check for queue errors
- if(status != FuriStatusOk) {
- switch(status) {
- case FuriStatusErrorTimeout:
- DEBUG(wii_errs[DEBUG_QUEUE_TIMEOUT]);
- continue;
- case FuriStatusError:
- ERROR(wii_errs[(error = ERR_QUEUE_RTOS)]);
- goto bail;
- case FuriStatusErrorResource:
- ERROR(wii_errs[(error = ERR_QUEUE_RESOURCE)]);
- goto bail;
- case FuriStatusErrorParameter:
- ERROR(wii_errs[(error = ERR_QUEUE_BADPRM)]);
- goto bail;
- case FuriStatusErrorNoMemory:
- ERROR(wii_errs[(error = ERR_QUEUE_NOMEM)]);
- goto bail;
- case FuriStatusErrorISR:
- ERROR(wii_errs[(error = ERR_QUEUE_ISR)]);
- goto bail;
- default:
- ERROR(wii_errs[(error = ERR_QUEUE_UNK)]);
- goto bail;
- }
- }
- // Read successful
+ // Check for queue errors
+ if (status != FuriStatusOk) {
+ switch (status) {
+ case FuriStatusErrorTimeout: DEBUG(wii_errs[DEBUG_QUEUE_TIMEOUT]); continue ;
+ case FuriStatusError: ERROR(wii_errs[(error = ERR_QUEUE_RTOS)]); goto bail ;
+ case FuriStatusErrorResource: ERROR(wii_errs[(error = ERR_QUEUE_RESOURCE)]); goto bail ;
+ case FuriStatusErrorParameter: ERROR(wii_errs[(error = ERR_QUEUE_BADPRM)]); goto bail ;
+ case FuriStatusErrorNoMemory: ERROR(wii_errs[(error = ERR_QUEUE_NOMEM)]); goto bail ;
+ case FuriStatusErrorISR: ERROR(wii_errs[(error = ERR_QUEUE_ISR)]); goto bail ;
+ default: ERROR(wii_errs[(error = ERR_QUEUE_UNK)]); goto bail ;
+ }
+ }
+ // Read successful
- // *** Try to lock the plugin state variables ***
- if(!(state = (state_t*)acquire_mutex_block(&mutex))) {
- ERROR(wii_errs[(error = ERR_MUTEX_BLOCK)]);
- goto bail;
- }
+ // *** Try to lock the plugin state variables ***
+ if ( !(state = (state_t*)acquire_mutex_block(&mutex)) ) {
+ ERROR(wii_errs[(error = ERR_MUTEX_BLOCK)]);
+ goto bail;
+ }
- // *** Handle events ***
- switch(msg.id) {
- //---------------------------------------------
- case EVID_TICK: // Timer events
- //! I would prefer to have ecPoll() called by cbTimer()
- //! ...but how does cbTimer() get the required access to the state variables? Namely: 'state->ec'
- //! So, for now, the timer pushes a message to call ecPoll()
- //! which, in turn, will push WIIEC event meesages!
- ecPoll(&state->ec, queue);
- break;
+ // *** Handle events ***
+ switch (msg.id) {
+ //---------------------------------------------
+ case EVID_TICK: // Timer events
+ //! I would prefer to have ecPoll() called by cbTimer()
+ //! ...but how does cbTimer() get the required access to the state variables? Namely: 'state->ec'
+ //! So, for now, the timer pushes a message to call ecPoll()
+ //! which, in turn, will push WIIEC event meesages!
+ ecPoll(&state->ec, queue);
+ break;
- //---------------------------------------------
- case EVID_WIIEC: // WiiMote Perhipheral
- if(evWiiEC(&msg, state)) redraw = true;
- break;
+ //---------------------------------------------
+ case EVID_WIIEC: // WiiMote Perhipheral
+ if (evWiiEC(&msg, state)) redraw = true ;
+ break;
- //---------------------------------------------
- case EVID_KEY: // Key events
- patBacklight(state);
- if(evKey(&msg, state)) redraw = true;
- break;
+ //---------------------------------------------
+ case EVID_KEY: // Key events
+ patBacklight(state);
+ if (evKey(&msg, state)) redraw = true;
+ break;
- //---------------------------------------------
- case EVID_NONE:
- break;
+ //---------------------------------------------
+ case EVID_NONE:
+ break;
- //---------------------------------------------
- default: // Unknown event
- WARN("Unknown message.ID [%d]", msg.id);
- break;
- }
+ //---------------------------------------------
+ default: // Unknown event
+ WARN("Unknown message.ID [%d]", msg.id);
+ break;
+ }
- // *** Update the GUI screen via the viewport ***
- if(redraw) view_port_update(vpp);
+ // *** Update the GUI screen via the viewport ***
+ if (redraw) view_port_update(vpp) ;
- // *** Try to release the plugin state variables ***
- if(!release_mutex(&mutex, state)) {
- ERROR(wii_errs[(error = ERR_MUTEX_RELEASE)]);
- goto bail;
- }
- } while(state->run);
+ // *** Try to release the plugin state variables ***
+ if ( !release_mutex(&mutex, state) ) {
+ ERROR(wii_errs[(error = ERR_MUTEX_RELEASE)]);
+ goto bail;
+ }
+ } while (state->run);
- // ===== Game Over =====
- INFO("USER EXIT");
+ // ===== Game Over =====
+ INFO("USER EXIT");
bail:
- // 10. Release system notification queue
- if(state->notify) {
- furi_record_close(RECORD_NOTIFICATION);
- state->notify = NULL;
- }
+ // 10. Release system notification queue
+ if (state->notify) {
+ furi_record_close(RECORD_NOTIFICATION);
+ state->notify = NULL;
+ }
- // 9. Stop the timer
- if(state->timer) {
- (void)furi_timer_stop(state->timer);
- furi_timer_free(state->timer);
- state->timer = NULL;
- state->timerEn = false;
- }
+ // 9. Stop the timer
+ if (state->timer) {
+ (void)furi_timer_stop(state->timer);
+ furi_timer_free(state->timer);
+ state->timer = NULL;
+ state->timerEn = false;
+ }
- // 8. Detach the viewport
- gui_remove_view_port(gui, vpp);
+ // 8. Detach the viewport
+ gui_remove_view_port(gui, vpp);
- // 7. No need to unreqgister the callbacks
- // ...they will go when the viewport is destroyed
+ // 7. No need to unreqgister the callbacks
+ // ...they will go when the viewport is destroyed
- // 6. Destroy the viewport
- if(vpp) {
- view_port_enabled_set(vpp, false);
- view_port_free(vpp);
- vpp = NULL;
- }
+ // 6. Destroy the viewport
+ if (vpp) {
+ view_port_enabled_set(vpp, false);
+ view_port_free(vpp);
+ vpp = NULL;
+ }
- // 5. Free the mutex
- if(mutex.mutex) {
- delete_mutex(&mutex);
- mutex.mutex = NULL;
- }
+ // 5. Free the mutex
+ if (mutex.mutex) {
+ delete_mutex(&mutex);
+ mutex.mutex = NULL;
+ }
- // 4. Free up state pointer(s)
- // none
+ // 4. Free up state pointer(s)
+ // none
- // 3. Free the plugin state variables
- if(state) {
- free(state);
- state = NULL;
- }
+ // 3. Free the plugin state variables
+ if (state) {
+ free(state);
+ state = NULL;
+ }
- // 2. Close the GUI
- furi_record_close("gui");
+ // 2. Close the GUI
+ furi_record_close("gui");
- // 1. Destroy the message queue
- if(queue) {
- furi_message_queue_free(queue);
- queue = NULL;
- }
+ // 1. Destroy the message queue
+ if (queue) {
+ furi_message_queue_free(queue);
+ queue = NULL;
+ }
- INFO("CLEAN EXIT ... Exit code: %d", error);
- LEAVE;
- return (int32_t)error;
+ INFO("CLEAN EXIT ... Exit code: %d", error);
+ LEAVE;
+ return (int32_t)error;
}
diff --git a/applications/plugins/wii_ec_anal/wii_anal.h b/applications/plugins/wii_ec_anal/wii_anal.h
index 3aae61fdc..ac7ffddb1 100644
--- a/applications/plugins/wii_ec_anal/wii_anal.h
+++ b/applications/plugins/wii_ec_anal/wii_anal.h
@@ -1,89 +1,97 @@
-#ifndef WII_ANAL_H_
-#define WII_ANAL_H_
+#ifndef WII_ANAL_H_
+#define WII_ANAL_H_
-#include // Core API
-#include // GUI Input extensions
-#include
+#include // Core API
+#include // GUI Input extensions
+#include
//----------------------------------------------------------------------------- ----------------------------------------
// GUI scenes
//
-typedef enum scene {
- SCENE_NONE = 0,
- SCENE_SPLASH = 1,
- SCENE_RIP = 2,
- SCENE_WAIT = 3,
- SCENE_DEBUG = 4,
- SCENE_DUMP = 5,
- SCENE_CLASSIC = 6,
- SCENE_CLASSIC_N = 7,
- SCENE_NUNCHUCK = 8,
- SCENE_NUNCHUCK_ACC = 9,
-} scene_t;
+typedef
+ enum scene {
+ SCENE_NONE = 0,
+ SCENE_SPLASH = 1,
+ SCENE_RIP = 2,
+ SCENE_WAIT = 3,
+ SCENE_DEBUG = 4,
+ SCENE_DUMP = 5,
+ SCENE_CLASSIC = 6,
+ SCENE_CLASSIC_N = 7,
+ SCENE_NUNCHUCK = 8,
+ SCENE_NUNCHUCK_ACC = 9,
+ }
+scene_t;
//----------------------------------------------------------------------------- ----------------------------------------
-#include "wii_i2c.h"
-#include "wii_ec.h"
+#include "wii_i2c.h"
+#include "wii_ec.h"
//----------------------------------------------------------------------------- ----------------------------------------
// A list of event IDs handled by this plugin
//
-typedef enum eventID {
- EVID_NONE,
- EVID_UNKNOWN,
+typedef
+ enum eventID {
+ EVID_NONE,
+ EVID_UNKNOWN,
- // A full list of events can be found with: `grep -r --color "void.*set_.*_callback" applications/gui/*`
- // ...A free gift to you from the makers of well written code that conforms to a good coding standard
- EVID_KEY, // keypad
- EVID_TICK, // tick
- EVID_WIIEC, // wii extension controller
-} eventID_t;
+ // A full list of events can be found with: `grep -r --color "void.*set_.*_callback" applications/gui/*`
+ // ...A free gift to you from the makers of well written code that conforms to a good coding standard
+ EVID_KEY, // keypad
+ EVID_TICK, // tick
+ EVID_WIIEC, // wii extension controller
+ }
+eventID_t;
//----------------------------------------------------------------------------- ----------------------------------------
// An item in the event message-queue
//
-typedef struct eventMsg {
- eventID_t id;
- union {
- InputEvent input; // --> applications/input/input.h
- wiiEcEvent_t wiiEc; // --> local
- };
-} eventMsg_t;
+typedef
+ struct eventMsg {
+ eventID_t id;
+ union {
+ InputEvent input; // --> applications/input/input.h
+ wiiEcEvent_t wiiEc; // --> local
+ };
+ }
+eventMsg_t;
//----------------------------------------------------------------------------- ----------------------------------------
// State variables for this plugin
// An instance of this is allocated on the heap, and the pointer is passed back to the OS
// Access to this memory is controlled by mutex
//
-typedef struct state {
- bool run; // true : plugin is running
+typedef
+ struct state {
+ bool run; // true : plugin is running
- bool timerEn; // controller scanning enabled
- FuriTimer* timer; // the timer
- uint32_t timerHz; // system ticks per second
- int fps; // poll/refresh [frames]-per-second
+ bool timerEn; // controller scanning enabled
+ FuriTimer* timer; // the timer
+ uint32_t timerHz; // system ticks per second
+ int fps; // poll/refresh [frames]-per-second
- int cnvW; // canvas width
- int cnvH; // canvas height
- scene_t scene; // current scene
- scene_t scenePrev; // previous scene
- scene_t scenePegg; // previous scene for easter eggs
- int flash; // flash counter (flashing icons)
+ int cnvW; // canvas width
+ int cnvH; // canvas height
+ scene_t scene; // current scene
+ scene_t scenePrev; // previous scene
+ scene_t scenePegg; // previous scene for easter eggs
+ int flash; // flash counter (flashing icons)
- int hold; // hold type: {-1=tough-peak, 0=none, +1=peak-hold}
- ecCalib_t calib; // Software calibration mode
+ int hold; // hold type: {-1=tough-peak, 0=none, +1=peak-hold}
+ ecCalib_t calib; // Software calibration mode
- bool pause; // Accelerometer animation pause
- bool apause; // Accelerometer animation auto-pause
+ bool pause; // Accelerometer animation pause
+ bool apause; // Accelerometer animation auto-pause
- NotificationApp* notify; // OS nitifcation queue (for patting the backlight watchdog timer)
+ NotificationApp* notify; // OS nitifcation queue (for patting the backlight watchdog timer)
- wiiEC_t ec; // Extension Controller details
-} state_t;
+ wiiEC_t ec; // Extension Controller details
+ }
+state_t;
//============================================================================= ========================================
// Function prototypes
//
-void timerEn(state_t* state, bool on);
+void timerEn (state_t* state, bool on) ;
#endif //WII_ANAL_H_
diff --git a/applications/plugins/wii_ec_anal/wii_anal_ec.c b/applications/plugins/wii_ec_anal/wii_anal_ec.c
index dab167bc0..0bfa47362 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_ec.c
+++ b/applications/plugins/wii_ec_anal/wii_anal_ec.c
@@ -1,115 +1,97 @@
-#include
-#include
+#include
+#include
-#include "wii_anal.h"
-#include "wii_anal_lcd.h"
-#include "wii_anal_keys.h"
+#include "wii_anal.h"
+#include "wii_anal_lcd.h"
+#include "wii_anal_keys.h"
//+============================================================================ ========================================
// Handle Wii Extension Controller events
//
-bool evWiiEC(const eventMsg_t* const msg, state_t* const state) {
- bool redraw = false;
+bool evWiiEC (const eventMsg_t* const msg, state_t* const state)
+{
+ bool redraw = false;
-#if LOG_LEVEL >= 4
- {
- const char* s = NULL;
- switch(msg->wiiEc.type) {
- case WIIEC_NONE:
- s = "Error";
- break;
- case WIIEC_CONN:
- s = "Connect";
- break;
- case WIIEC_DISCONN:
- s = "Disconnect";
- break;
- case WIIEC_PRESS:
- s = "Press";
- break;
- case WIIEC_RELEASE:
- s = "Release";
- break;
- case WIIEC_ANALOG:
- s = "Analog";
- break;
- case WIIEC_ACCEL:
- s = "Accel";
- break;
- default:
- s = "Bug";
- break;
- }
- INFO(
- "WIIP : %s '%c' = %d",
- s,
- (isprint((int)msg->wiiEc.in) ? msg->wiiEc.in : '_'),
- msg->wiiEc.val);
- if((msg->wiiEc.type == WIIEC_CONN) || (msg->wiiEc.type == WIIEC_DISCONN))
- INFO("...%d=\"%s\"", msg->wiiEc.val, ecId[msg->wiiEc.val].name);
- }
+# if LOG_LEVEL >= 4
+ {
+ const char* s = NULL;
+ switch (msg->wiiEc.type) {
+ case WIIEC_NONE: s = "Error"; break ;
+ case WIIEC_CONN: s = "Connect"; break ;
+ case WIIEC_DISCONN: s = "Disconnect"; break ;
+ case WIIEC_PRESS: s = "Press"; break ;
+ case WIIEC_RELEASE: s = "Release"; break ;
+ case WIIEC_ANALOG: s = "Analog"; break ;
+ case WIIEC_ACCEL: s = "Accel"; break ;
+ default: s = "Bug"; break ;
+ }
+ INFO("WIIP : %s '%c' = %d", s, (isprint((int)msg->wiiEc.in) ? msg->wiiEc.in : '_'), msg->wiiEc.val);
+ if ((msg->wiiEc.type == WIIEC_CONN) || (msg->wiiEc.type == WIIEC_DISCONN))
+ INFO("...%d=\"%s\"", msg->wiiEc.val, ecId[msg->wiiEc.val].name);
+ }
+# endif
+
+ switch (msg->wiiEc.type) {
+ case WIIEC_CONN:
+ patBacklight(state);
+ state->hold = 0;
+ state->calib = CAL_TRACK;
+ sceneSet(state, ecId[msg->wiiEc.val].scene);
+ redraw = true ;
+
+#if 1 // Workaround for Classic Controller Pro, which shows 00's for Factory Calibration Data!?
+ if (state->ec.pidx == PID_CLASSIC_PRO) {
+ // Simulate a Long-OK keypress, to start Software Calibration mode
+ eventMsg_t msg = {
+// .id = EVID_KEY,
+ .input.type = InputTypeLong,
+ .input.key = InputKeyOk
+ };
+ key_calib(&msg, state);
+ }
#endif
+ break;
- switch(msg->wiiEc.type) {
- case WIIEC_CONN:
- patBacklight(state);
- state->hold = 0;
- state->calib = CAL_TRACK;
- sceneSet(state, ecId[msg->wiiEc.val].scene);
- redraw = true;
+ case WIIEC_DISCONN:
+ patBacklight(state);
+ sceneSet(state, SCENE_WAIT);
+ redraw = true;
+ break;
-#if 1 // Workaround for Classic Controller Pro, which shows 00's for Factory Calibration Data!?
- if(state->ec.pidx == PID_CLASSIC_PRO) {
- // Simulate a Long-OK keypress, to start Software Calibration mode
- eventMsg_t msg = {// .id = EVID_KEY,
- .input.type = InputTypeLong,
- .input.key = InputKeyOk};
- key_calib(&msg, state);
- }
+ case WIIEC_PRESS:
+ if (state->scene == SCENE_NUNCHUCK_ACC) switch (msg->wiiEc.in) {
+ case 'z': // un-pause
+ state->pause = !state->pause;
+ break;
+ case 'c': // toggle auto-pause
+ state->pause = false;
+ state->apause = !state->apause;
+ break;
+ default: break ;
+ }
+
+#if 1 //! factory calibration method not known for classic triggers - this will set the digital switch point
+ if ((state->ec.pidx == PID_CLASSIC) || (state->ec.pidx == PID_CLASSIC_PRO)) {
+ if (msg->wiiEc.in == 'l') state->ec.calS.classic[2].trgZL = msg->wiiEc.val ;
+ if (msg->wiiEc.in == 'r') state->ec.calS.classic[2].trgZR = msg->wiiEc.val ;
+ }
#endif
- break;
+ __attribute__ ((fallthrough));
- case WIIEC_DISCONN:
- patBacklight(state);
- sceneSet(state, SCENE_WAIT);
- redraw = true;
- break;
+ case WIIEC_RELEASE:
+ patBacklight(state);
+ redraw = true;
+ break;
- case WIIEC_PRESS:
- if(state->scene == SCENE_NUNCHUCK_ACC) switch(msg->wiiEc.in) {
- case 'z': // un-pause
- state->pause = !state->pause;
- break;
- case 'c': // toggle auto-pause
- state->pause = false;
- state->apause = !state->apause;
- break;
- default:
- break;
- }
+ case WIIEC_ANALOG:
+ case WIIEC_ACCEL:
+ ecCalibrate(&state->ec, state->calib);
+ redraw = true;
+ break;
-#if 1 //! factory calibration method not known for classic triggers - this will set the digital switch point
- if((state->ec.pidx == PID_CLASSIC) || (state->ec.pidx == PID_CLASSIC_PRO)) {
- if(msg->wiiEc.in == 'l') state->ec.calS.classic[2].trgZL = msg->wiiEc.val;
- if(msg->wiiEc.in == 'r') state->ec.calS.classic[2].trgZR = msg->wiiEc.val;
- }
-#endif
- __attribute__((fallthrough));
+ default:
+ break;
+ }
- case WIIEC_RELEASE:
- patBacklight(state);
- redraw = true;
- break;
-
- case WIIEC_ANALOG:
- case WIIEC_ACCEL:
- ecCalibrate(&state->ec, state->calib);
- redraw = true;
- break;
-
- default:
- break;
- }
-
- return redraw;
+ return redraw;
}
diff --git a/applications/plugins/wii_ec_anal/wii_anal_ec.h b/applications/plugins/wii_ec_anal/wii_anal_ec.h
index eec6b523c..886b60281 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_ec.h
+++ b/applications/plugins/wii_ec_anal/wii_anal_ec.h
@@ -1,14 +1,14 @@
-#ifndef WII_ANAL_EC_H_
-#define WII_ANAL_EC_H_
+#ifndef WII_ANAL_EC_H_
+#define WII_ANAL_EC_H_
-#include
+#include
//============================================================================= ========================================
// Function prototypes
//
-typedef struct eventMsg eventMsg_t;
-typedef struct state state_t;
+typedef struct eventMsg eventMsg_t ;
+typedef struct state state_t ;
-bool evWiiEC(const eventMsg_t* const msg, state_t* const state);
+bool evWiiEC (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_ANAL_EC_H_
diff --git a/applications/plugins/wii_ec_anal/wii_anal_keys.c b/applications/plugins/wii_ec_anal/wii_anal_keys.c
index 8c5c99b4e..3d2fae14a 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_keys.c
+++ b/applications/plugins/wii_ec_anal/wii_anal_keys.c
@@ -1,35 +1,40 @@
-#include
+#include
-#include "bc_logging.h"
+#include "bc_logging.h"
-#include "wii_anal.h"
+#include "wii_anal.h"
//+============================================================================ ========================================
// Stop Calibration mode
//
-static void calStop(state_t* const state) {
- state->hold = 0; // stop calibration mode
- state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ...
+static
+void calStop (state_t* const state)
+{
+ state->hold = 0; // stop calibration mode
+ state->calib &= ~(CAL_RANGE | CAL_NOTJOY); // ...
}
//+============================================================================ ========================================
// Change to another scene
//
-void sceneSet(state_t* const state, const scene_t scene) {
- calStop(state); // Stop software calibration
- state->scenePrev = state->scene; // Remember where we came from
- state->scene = scene; // Go to new scene
- INFO("Scene : %d -> %d", state->scenePrev, state->scene);
+void sceneSet (state_t* const state, const scene_t scene)
+{
+ calStop(state); // Stop software calibration
+ state->scenePrev = state->scene; // Remember where we came from
+ state->scene = scene; // Go to new scene
+ INFO("Scene : %d -> %d", state->scenePrev, state->scene);
}
//+============================================================================ ========================================
// Change to an easter egg scene
//
-static void sceneSetEgg(state_t* const state, const scene_t scene) {
- calStop(state); // Stop software calibration
- state->scenePegg = state->scene; // Remember where we came from
- state->scene = scene; // Go to new scene
- INFO("Scene* : %d => %d", state->scenePegg, state->scene);
+static
+void sceneSetEgg (state_t* const state, const scene_t scene)
+{
+ calStop(state); // Stop software calibration
+ state->scenePegg = state->scene; // Remember where we came from
+ state->scene = scene; // Go to new scene
+ INFO("Scene* : %d => %d", state->scenePegg, state->scene);
}
//+============================================================================ ========================================
@@ -37,263 +42,256 @@ static void sceneSetEgg(state_t* const state, const scene_t scene) {
// Enabling peak-hold on screen with no peak meters will have no effect
// So, to avoid code duplication...
//
-bool key_calib(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+bool key_calib (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyUp: //# hold = (state->hold == +1) ? 0 : +1; // toggle peak hold
- used = true;
- break;
+ switch (msg->input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyUp: //# hold = (state->hold == +1) ? 0 : +1 ; // toggle peak hold
+ used = true;
+ break;
- case InputKeyDown: //# hold = (state->hold == -1) ? 0 : -1; // toggle trough hold
- used = true;
- break;
+ case InputKeyDown: //# hold = (state->hold == -1) ? 0 : -1 ; // toggle trough hold
+ used = true;
+ break;
- case InputKeyOk: //# calib & CAL_RANGE)
- calStop(state); // STOP softare calibration
- else
- ecCalibrate(&state->ec, CAL_CENTRE); // perform centre calibration
- used = true;
- break;
+ case InputKeyOk: //# calib & CAL_RANGE) calStop(state) ; // STOP softare calibration
+ else ecCalibrate(&state->ec, CAL_CENTRE) ; // perform centre calibration
+ used = true;
+ break;
- default:
- break;
- }
- break;
+ default: break ;
+ }
+ break;
- case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
- switch(msg->input.key) {
- case InputKeyOk: //# >O [ LONG-OK ]
- ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration
- state->hold = 0;
- state->calib |= CAL_RANGE;
- state->flash = 8; // start with flash ON
- used = true;
- break;
+ case InputTypeLong: //# >! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
+ switch (msg->input.key) {
+ case InputKeyOk: //# >O [ LONG-OK ]
+ ecCalibrate(&state->ec, CAL_RESET | CAL_CENTRE); // START software calibration
+ state->hold = 0;
+ state->calib |= CAL_RANGE;
+ state->flash = 8; // start with flash ON
+ used = true;
+ break;
- default:
- break;
- }
- break;
+ default: break ;
+ }
+ break;
- default:
- break;
- }
+ default: break ;
+ }
- return used;
+ return used;
}
//+============================================================================ ========================================
// WAIT screen
//
-static inline bool wait_key(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+static inline
+bool wait_key (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- if(msg->input.type == InputTypeShort) {
- switch(msg->input.key) {
- case InputKeyLeft: //# input.type == InputTypeShort) {
+ switch (msg->input.key) {
+ case InputKeyLeft: //# run = false;
- used = true;
- break;
+ case InputKeyBack: //# run = false;
+ used = true;
+ break;
- default:
- break;
- }
- }
+ default: break ;
+ }
+ }
- return used;
+ return used;
}
//+============================================================================ ========================================
// DEBUG screen
//
-static inline bool debug_key(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+static inline
+bool debug_key (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyUp: { //# ec, NULL); // Initialise the controller //! NULL = no encryption
- (void)init; // in case INFO is optimised out
- INFO("%s : %s", __func__, (init ? "init OK" : "init fail"));
- used = true;
- break;
- }
+ switch (msg->input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyUp: { //# ec, NULL); // Initialise the controller //! NULL = no encryption
+ (void)init; // in case INFO is optimised out
+ INFO("%s : %s", __func__, (init ? "init OK" : "init fail"));
+ used = true;
+ break;
+ }
- case InputKeyOk: //# ec) == 0) { // Read the controller
- INFO(
- "%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}",
- __func__,
- state->ec.joy[0],
- state->ec.joy[1],
- state->ec.joy[2],
- state->ec.joy[3],
- state->ec.joy[4],
- state->ec.joy[5]);
- }
- used = true;
- break;
+ case InputKeyOk: //# ec) == 0) { // Read the controller
+ INFO( "%s : joy: {%02X,%02X,%02X,%02X,%02X,%02X}", __func__,
+ state->ec.joy[0], state->ec.joy[1], state->ec.joy[2],
+ state->ec.joy[3], state->ec.joy[4], state->ec.joy[5] );
+ }
+ used = true;
+ break;
- case InputKeyDown: //# scenePrev);
- used = true;
- break;
+ case InputKeyDown: //# scenePrev);
+ used = true;
+ break;
- case InputKeyBack: //# run = false;
- used = true;
- break;
+ case InputKeyBack: //# run = false;
+ used = true;
+ break;
- default:
- break; //#
- }
- break;
+ default: break ; //#
+ }
+ break;
- default:
- break;
- }
+ default: break ;
+ }
- return used;
+ return used;
}
//+============================================================================ ========================================
// SPLASH and RIP screen
//
-static inline bool splash_key(const eventMsg_t* const msg, state_t* const state) {
- // Back key on the initial SPLASH screen (this will catch the InputKeyPress)
- if((msg->input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false;
+static inline
+bool splash_key (const eventMsg_t* const msg, state_t* const state)
+{
+ // Back key on the initial SPLASH screen (this will catch the InputKeyPress)
+ if ((msg->input.key == InputKeyBack) && (state->scenePrev == SCENE_NONE)) state->run = false ;
- // ANY-other-KEY press
- if(msg->input.type == InputTypeShort) {
- timerEn(state, true); // Restart the timer
- state->scene = state->scenePegg;
- }
+ // ANY-other-KEY press
+ if (msg->input.type == InputTypeShort) {
+ timerEn(state, true); // Restart the timer
+ state->scene = state->scenePegg;
+ }
- return true;
+ return true;
}
+
//+============================================================================ ========================================
// "_pre" allows the plugin to use the key before the active scene gets a chance
//
-static inline bool key_pre(const eventMsg_t* const msg, state_t* const state) {
- (void)msg;
- (void)state;
+static inline
+bool key_pre (const eventMsg_t* const msg, state_t* const state)
+{
+ (void)msg;
+ (void)state;
- return false;
+ return false;
}
//+============================================================================ ========================================
// "_post" allows the plugin to use a key if it was not used by the active scene
//
-static inline bool key_post(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+static inline
+bool key_post (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- if(msg->input.key == InputKeyBack) {
- if(msg->input.type == InputTypeShort) { //# ec.init = false; // reset/disconnect the controller
- sceneSet(state, SCENE_WAIT);
- used = true;
+ if (msg->input.key == InputKeyBack) {
+ if (msg->input.type == InputTypeShort) { //# ec.init = false; // reset/disconnect the controller
+ sceneSet(state, SCENE_WAIT);
+ used = true;
- } else if(msg->input.type == InputTypeLong) { //# >B [LONG-BACK]
- state->run = false; // Signal the plugin to exit
- used = true;
- }
- }
+ } else if (msg->input.type == InputTypeLong) { //# >B [LONG-BACK]
+ state->run = false; // Signal the plugin to exit
+ used = true;
+ }
+ }
- // Easter eggs
- switch(state->scene) {
- case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs
- case SCENE_RIP:
- case SCENE_DEBUG:
- break;
- default:
- if(msg->input.type == InputTypeLong) {
- switch(msg->input.key) {
- case InputKeyDown: //# >D [LONG-DOWN]
- timerEn(state, false); // Stop the timer
- sceneSetEgg(state, SCENE_DEBUG);
- used = true;
- break;
+ // Easter eggs
+ switch (state->scene) {
+ case SCENE_SPLASH: // Scenes that do NOT offer Easter eggs
+ case SCENE_RIP:
+ case SCENE_DEBUG:
+ break;
+ default:
+ if (msg->input.type == InputTypeLong) {
+ switch (msg->input.key) {
+ case InputKeyDown: //# >D [LONG-DOWN]
+ timerEn(state, false); // Stop the timer
+ sceneSetEgg(state, SCENE_DEBUG);
+ used = true;
+ break;
- case InputKeyLeft: //# >L [ LONG-LEFT ]
- timerEn(state, false); // Stop the timer
- sceneSetEgg(state, SCENE_SPLASH);
- used = true;
- break;
+ case InputKeyLeft: //# >L [ LONG-LEFT ]
+ timerEn(state, false); // Stop the timer
+ sceneSetEgg(state, SCENE_SPLASH);
+ used = true;
+ break;
- case InputKeyUp: //# >U [ LONG-UP ]
- timerEn(state, false); // Stop the timer
- sceneSetEgg(state, SCENE_RIP);
- used = true;
- break;
+ case InputKeyUp: //# >U [ LONG-UP ]
+ timerEn(state, false); // Stop the timer
+ sceneSetEgg(state, SCENE_RIP);
+ used = true;
+ break;
- default:
- break;
- }
- }
- break;
- }
+ default: break ;
+ }
+ }
+ break;
+ }
- return used;
+ return used;
}
//+============================================================================ ========================================
// Handle a key press event
//
-bool evKey(const eventMsg_t* const msg, state_t* const state) {
- furi_assert(msg);
- furi_assert(state);
+bool evKey (const eventMsg_t* const msg, state_t* const state)
+{
+ furi_assert(msg);
+ furi_assert(state);
- bool used = key_pre(msg, state);
+ bool used = key_pre(msg, state);
- if(!used) switch(state->scene) {
- case SCENE_SPLASH: //...
- case SCENE_RIP:
- used = splash_key(msg, state);
- break;
+ if (!used) switch (state->scene) {
+ case SCENE_SPLASH: //...
+ case SCENE_RIP: used = splash_key(msg, state); break ;
- case SCENE_WAIT:
- used = wait_key(msg, state);
- break;
- case SCENE_DEBUG:
- used = debug_key(msg, state);
- break;
+ case SCENE_WAIT: used = wait_key(msg, state); break ;
+ case SCENE_DEBUG: used = debug_key(msg, state); break ;
- default:
- if(state->ec.pidx >= PID_ERROR) {
- ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
- } else {
- if((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys)
- ecId[PID_UNKNOWN].keys(msg, state);
- else
- ecId[state->ec.pidx].keys(msg, state);
- }
- break;
+ default:
+ if (state->ec.pidx >= PID_ERROR) {
+ ERROR("%s : bad PID = %d", __func__, state->ec.pidx);
+ } else {
+ if ((state->scene == SCENE_DUMP) || !ecId[state->ec.pidx].keys)
+ ecId[PID_UNKNOWN].keys(msg, state);
+ else
+ ecId[state->ec.pidx].keys(msg, state);
+ }
+ break;
- case SCENE_NONE:
- break;
- }
+ case SCENE_NONE: break;
+ }
- if(!used) used = key_post(msg, state);
+ if (!used) used = key_post(msg, state) ;
- return used;
+ return used;
}
+
diff --git a/applications/plugins/wii_ec_anal/wii_anal_keys.h b/applications/plugins/wii_ec_anal/wii_anal_keys.h
index c10fcd1ef..0ebbd5e8e 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_keys.h
+++ b/applications/plugins/wii_ec_anal/wii_anal_keys.h
@@ -1,16 +1,16 @@
-#ifndef WII_ANAL_KEYS_H_
-#define WII_ANAL_KEYS_H_
+#ifndef WII_ANAL_KEYS_H_
+#define WII_ANAL_KEYS_H_
//============================================================================= ========================================
// Function prototypes
//
-#include // bool
-typedef struct eventMsg eventMsg_t;
-typedef struct state state_t;
-typedef enum scene scene_t;
+#include // bool
+typedef struct eventMsg eventMsg_t ;
+typedef struct state state_t ;
+typedef enum scene scene_t ;
-void sceneSet(state_t* const state, const scene_t scene);
-bool key_calib(const eventMsg_t* const msg, state_t* const state);
-bool evKey(const eventMsg_t* const msg, state_t* const state);
+void sceneSet (state_t* const state, const scene_t scene) ;
+bool key_calib (const eventMsg_t* const msg, state_t* const state) ;
+bool evKey (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_ANAL_KEYS_H_
diff --git a/applications/plugins/wii_ec_anal/wii_anal_lcd.c b/applications/plugins/wii_ec_anal/wii_anal_lcd.c
index 921a3708e..d031bc120 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_lcd.c
+++ b/applications/plugins/wii_ec_anal/wii_anal_lcd.c
@@ -1,45 +1,17 @@
-#include "wii_anal.h"
-#include "gfx/images.h" // Images
+#include "wii_anal.h"
+#include "gfx/images.h" // Images
//----------------------------------------------------------------------------- ----------------------------------------
// A couple of monospaced hex fonts
//
-const image_t* img_6x8[16] = {
- &img_6x8_0,
- &img_6x8_1,
- &img_6x8_2,
- &img_6x8_3,
- &img_6x8_4,
- &img_6x8_5,
- &img_6x8_6,
- &img_6x8_7,
- &img_6x8_8,
- &img_6x8_9,
- &img_6x8_A,
- &img_6x8_B,
- &img_6x8_C,
- &img_6x8_D,
- &img_6x8_E,
- &img_6x8_F,
+const image_t* img_6x8[16] = {
+ &img_6x8_0, &img_6x8_1, &img_6x8_2, &img_6x8_3, &img_6x8_4, &img_6x8_5, &img_6x8_6, &img_6x8_7,
+ &img_6x8_8, &img_6x8_9, &img_6x8_A, &img_6x8_B, &img_6x8_C, &img_6x8_D, &img_6x8_E, &img_6x8_F,
};
-const image_t* img_5x7[16] = {
- &img_5x7_0,
- &img_5x7_1,
- &img_5x7_2,
- &img_5x7_3,
- &img_5x7_4,
- &img_5x7_5,
- &img_5x7_6,
- &img_5x7_7,
- &img_5x7_8,
- &img_5x7_9,
- &img_5x7_A,
- &img_5x7_B,
- &img_5x7_C,
- &img_5x7_D,
- &img_5x7_E,
- &img_5x7_F,
+const image_t* img_5x7[16] = {
+ &img_5x7_0, &img_5x7_1, &img_5x7_2, &img_5x7_3, &img_5x7_4, &img_5x7_5, &img_5x7_6, &img_5x7_7,
+ &img_5x7_8, &img_5x7_9, &img_5x7_A, &img_5x7_B, &img_5x7_C, &img_5x7_D, &img_5x7_E, &img_5x7_F,
};
//+============================================================================ ========================================
@@ -58,71 +30,66 @@ const image_t* img_5x7[16] = {
// // Do this ONCE ... at plugin quit
// furi_record_close(RECORD_NOTIFICATION);
// }
-void patBacklight(state_t* state) {
- notification_message(state->notify, &sequence_display_backlight_on);
+void patBacklight (state_t* state)
+{
+ notification_message(state->notify, &sequence_display_backlight_on);
}
//============================================================================= ========================================
// Show a hex number in an inverted box (for ananlogue readings)
//
-void showHex(
- Canvas* const canvas,
- uint8_t x,
- uint8_t y,
- const uint32_t val,
- const uint8_t cnt,
- const int b) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_box(canvas, x++, y++, 1 + (cnt * (6 + 1)), 10);
+void showHex ( Canvas* const canvas, uint8_t x, uint8_t y,
+ const uint32_t val, const uint8_t cnt, const int b )
+{
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_box(canvas, x++,y++, 1 +(cnt *(6 +1)), 10);
- // thicken border
- if(b == 2) canvas_draw_frame(canvas, x - 2, y - 2, 1 + (cnt * (6 + 1)) + 2, 10 + 2);
+ // thicken border
+ if (b == 2) canvas_draw_frame(canvas, x-2,y-2, 1 +(cnt *(6 +1))+2, 10+2);
- for(int i = (cnt - 1) * 4; i >= 0; i -= 4, x += 6 + 1)
- show(canvas, x, y, img_6x8[(val >> i) & 0xF], SHOW_SET_WHT);
+ for (int i = (cnt -1) *4; i >= 0; i -= 4, x += 6+1)
+ show(canvas, x,y, img_6x8[(val >>i) &0xF], SHOW_SET_WHT) ;
}
//============================================================================= ========================================
// Show the up/down "peak hold" controls in the bottom right
//
-void showPeakHold(state_t* const state, Canvas* const canvas, const int hold) {
- switch(hold) {
- case 0:
- show(canvas, 119, 51, &img_key_U, SHOW_CLR_BLK);
- show(canvas, 119, 56, &img_key_D, SHOW_CLR_BLK);
- break;
- case +1:
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_box(canvas, 120, 52, 7, 6);
- show(canvas, 119, 51, &img_key_U, SHOW_CLR_WHT);
- show(canvas, 119, 56, &img_key_D, SHOW_CLR_BLK);
- break;
- case -1:
- show(canvas, 119, 51, &img_key_U, SHOW_CLR_BLK);
- canvas_draw_box(canvas, 120, 57, 7, 6);
- show(canvas, 119, 56, &img_key_D, SHOW_CLR_WHT);
- break;
- default:
- break;
- }
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_frame(canvas, 119, 51, 9, 13);
+void showPeakHold (state_t* const state, Canvas* const canvas, const int hold)
+{
+ switch (hold) {
+ case 0:
+ show(canvas, 119,51, &img_key_U, SHOW_CLR_BLK);
+ show(canvas, 119,56, &img_key_D, SHOW_CLR_BLK);
+ break;
+ case +1:
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_box(canvas, 120,52, 7,6);
+ show(canvas, 119,51, &img_key_U, SHOW_CLR_WHT);
+ show(canvas, 119,56, &img_key_D, SHOW_CLR_BLK);
+ break;
+ case -1:
+ show(canvas, 119,51, &img_key_U, SHOW_CLR_BLK);
+ canvas_draw_box(canvas, 120,57, 7,6);
+ show(canvas, 119,56, &img_key_D, SHOW_CLR_WHT);
+ break;
+ default:
+ break;
+ }
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_frame(canvas, 119,51, 9,13);
- // calibration indicator
- show(
- canvas,
- 108,
- 55,
- ((state->calib & CAL_RANGE) && (++state->flash & 8)) ? &img_key_OKi : &img_key_OK,
- SHOW_SET_BLK);
+ // calibration indicator
+ show( canvas, 108,55,
+ ((state->calib & CAL_RANGE) && (++state->flash &8)) ? &img_key_OKi : &img_key_OK,
+ SHOW_SET_BLK );
}
//============================================================================= ========================================
-// This code performs a FULL calibration on the device EVERY time it draws a joystick
+// This code performs a FULL calibration on the device EVERY time it draws a joystick
//...This is NOT a good way forward for anything other than a test tool.
//
// Realistically you would do all the maths when the controller is connected
-// or, if you prefer (and it IS a good thing), have a "calibrate controller" menu option
+// or, if you prefer (and it IS a good thing), have a "calibrate controller" menu option
// ...and then just use a lookup table, or trivial formual
//
// THIS algorithm chops the joystick in to one of 9 zones
@@ -130,12 +97,12 @@ void showPeakHold(state_t* const state, Canvas* const canvas, const int hold) {
// FullLeft and FullRight have a deadzone of N [qv. xDead] ..a total of N+1 positions
// Middle has a deadzone of N EACH WAY ...a total of 2N+1 positions
//
-// If the remaining range does not divide evenly in to three zones,
+// If the remaining range does not divide evenly in to three zones,
// the first remainder is added to zone3,
// and the second remainder (if there is one) is added to zone2
// ...giving finer control near the centre of the joystick
//
-// The value of the deadzone is based on the number of bits in the
+// The value of the deadzone is based on the number of bits in the
// joystcik {x,y} values - the larger the range, the larger the deadzone.
//
// 03 15 29
@@ -151,132 +118,106 @@ void showPeakHold(state_t* const state, Canvas* const canvas, const int hold) {
// Turn and object - this is probably good enough
// Start slowly & pick up speed - how about a log or sine curve?
//
-void showJoy(
- Canvas* const canvas,
- const uint8_t x,
- const uint8_t y, // x,y is the CENTRE of the Joystick
- const uint8_t xMin,
- const uint8_t xMid,
- const uint8_t xMax,
- const uint8_t yMin,
- const uint8_t yMid,
- const uint8_t yMax,
- const uint8_t xPos,
- const uint8_t yPos,
- const uint8_t bits) {
- int xOff = 0; // final offset of joystick hat image
- int yOff = 0;
+void showJoy ( Canvas* const canvas, const uint8_t x, const uint8_t y, // x,y is the CENTRE of the Joystick
+ const uint8_t xMin, const uint8_t xMid, const uint8_t xMax,
+ const uint8_t yMin, const uint8_t yMid, const uint8_t yMax,
+ const uint8_t xPos, const uint8_t yPos, const uint8_t bits )
+{
+ int xOff = 0; // final offset of joystick hat image
+ int yOff = 0;
- int xDead = (bits < 7) ? (1 << 0) : (1 << 3); // dead zone (centre & limits)
- int yDead = xDead;
+ int xDead = (bits < 7) ? (1<<0) : (1<<3); // dead zone (centre & limits)
+ int yDead = xDead;
- // This code is NOT optimised ...and it's still barely readable!
- if((xPos >= (xMid - xDead)) && (xPos <= (xMid + xDead)))
- xOff = 0; // centre [most likely]
- else if(xPos <= (xMin + xDead))
- xOff = -4; // full left
- else if(xPos >= (xMax - xDead))
- xOff = +4; // full right
- else if(xPos < (xMid - xDead)) { // part left
- // very much hard-coded for 3 interim positions
- int lo = (xMin + xDead) + 1; // lowest position
- int hi = (xMid - xDead) - 1; // highest position
+ // This code is NOT optimised ...and it's still barely readable!
+ if ((xPos >= (xMid -xDead)) && (xPos <= (xMid +xDead))) xOff = 0 ; // centre [most likely]
+ else if (xPos <= (xMin +xDead)) xOff = -4 ; // full left
+ else if (xPos >= (xMax -xDead)) xOff = +4 ; // full right
+ else if (xPos < (xMid -xDead)) { // part left
+ // very much hard-coded for 3 interim positions
+ int lo = (xMin +xDead) +1; // lowest position
+ int hi = (xMid -xDead) -1; // highest position
- // this is the only duplicated bit of code
- int range = (hi - lo) + 1; // range covered
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
+ // this is the only duplicated bit of code
+ int range = (hi -lo) +1; // range covered
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
- // int hi1 = hi; // lowest value for zone #-1
- // int lo1 = hi1 -div +1; // highest value for zone #-1
- // int hi2 = lo1 -1; // lowest value for zone #-2
- // int lo2 = hi2 -div +1 -(rem==2); // highest value for zone #-2 expand out remainder
- // int hi3 = lo2 -1; // lowest value for zone #-3
- // int lo3 = hi3 -div +1 -(rem>=1); // highest value for zone #-3 expand out remainder
+// int hi1 = hi; // lowest value for zone #-1
+// int lo1 = hi1 -div +1; // highest value for zone #-1
+// int hi2 = lo1 -1; // lowest value for zone #-2
+// int lo2 = hi2 -div +1 -(rem==2); // highest value for zone #-2 expand out remainder
+// int hi3 = lo2 -1; // lowest value for zone #-3
+// int lo3 = hi3 -div +1 -(rem>=1); // highest value for zone #-3 expand out remainder
- int lo1 = hi - div + 1; // (in brevity)
- int hi3 = hi - div - div - (rem == 2); // ...
+ int lo1 = hi -div +1; // (in brevity)
+ int hi3 = hi -div -div -(rem==2); // ...
- if(xPos <= hi3)
- xOff = -3; // zone #-3
- else if(xPos >= lo1)
- xOff = -1; // zone #-1
- else
- xOff = -2; // zone #-2
+ if (xPos <= hi3) xOff = -3 ; // zone #-3
+ else if (xPos >= lo1) xOff = -1 ; // zone #-1
+ else xOff = -2 ; // zone #-2
- } else /*if (xPos > (xMid +xDead))*/ { // part right
- // very much hard-coded for 3 interim positions
- int lo = (xMid + xDead) + 1; // lowest position
- int hi = (xMax - xDead) - 1; // highest position
+ } else /*if (xPos > (xMid +xDead))*/ { // part right
+ // very much hard-coded for 3 interim positions
+ int lo = (xMid +xDead) +1; // lowest position
+ int hi = (xMax -xDead) -1; // highest position
- int range = (hi - lo) + 1; // range covered
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
+ int range = (hi -lo) +1; // range covered
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
- // int lo1 = lo; // lowest value for zone #+1
- // int hi1 = lo +div -1; // highest value for zone #+1
- // int lo2 = hi1 +1; // lowest value for zone #+2
- // int hi2 = lo2 +div -1 +(rem==2); // highest value for zone #+2 expand out remainder
- // int lo3 = hi2 +1; // lowest value for zone #+3
- // int hi3 = lo3 +div -1 +(rem>=1); // highest value for zone #+3 expand out remainder
+// int lo1 = lo; // lowest value for zone #+1
+// int hi1 = lo +div -1; // highest value for zone #+1
+// int lo2 = hi1 +1; // lowest value for zone #+2
+// int hi2 = lo2 +div -1 +(rem==2); // highest value for zone #+2 expand out remainder
+// int lo3 = hi2 +1; // lowest value for zone #+3
+// int hi3 = lo3 +div -1 +(rem>=1); // highest value for zone #+3 expand out remainder
- int hi1 = lo + div - 1; // (in brevity)
- int lo3 = lo + div + div + (rem == 2); // ...
+ int hi1 = lo +div -1; // (in brevity)
+ int lo3 = lo +div +div +(rem==2); // ...
- if(xPos <= hi1)
- xOff = 1; // zone #1
- else if(xPos >= lo3)
- xOff = 3; // zone #3
- else
- xOff = 2; // zone #2
- }
+ if (xPos <= hi1) xOff = 1 ; // zone #1
+ else if (xPos >= lo3) xOff = 3 ; // zone #3
+ else xOff = 2 ; // zone #2
+ }
- // All this to print a 3x3 square (in the right place) - LOL!
- if((yPos >= (yMid - yDead)) && (yPos <= (yMid + yDead)))
- yOff = 0; // centre [most likely]
- else if(yPos <= (yMin + yDead))
- yOff = +4; // full down
- else if(yPos >= (yMax - yDead))
- yOff = -4; // full up
- else if(yPos < (yMid - yDead)) { // part down
- int lo = (yMin + yDead) + 1; // lowest position
- int hi = (yMid - yDead) - 1; // highest position
+ // All this to print a 3x3 square (in the right place) - LOL!
+ if ((yPos >= (yMid -yDead)) && (yPos <= (yMid +yDead))) yOff = 0 ; // centre [most likely]
+ else if (yPos <= (yMin +yDead)) yOff = +4 ; // full down
+ else if (yPos >= (yMax -yDead)) yOff = -4 ; // full up
+ else if (yPos < (yMid -yDead)) { // part down
+ int lo = (yMin +yDead) +1; // lowest position
+ int hi = (yMid -yDead) -1; // highest position
- int range = (hi - lo) + 1; // range covered
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
+ int range = (hi -lo) +1; // range covered
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
- int lo1 = hi - div + 1; // (in brevity)
- int hi3 = hi - div - div - (rem == 2); // ...
+ int lo1 = hi -div +1; // (in brevity)
+ int hi3 = hi -div -div -(rem==2); // ...
- if(yPos <= hi3)
- yOff = +3; // zone #3
- else if(yPos >= lo1)
- yOff = +1; // zone #1
- else
- yOff = +2; // zone #2
+ if (yPos <= hi3) yOff = +3 ; // zone #3
+ else if (yPos >= lo1) yOff = +1 ; // zone #1
+ else yOff = +2 ; // zone #2
- } else /*if (yPos > (yMid +yDead))*/ { // part up
- int lo = (yMid + yDead) + 1; // lowest position
- int hi = (yMax - yDead) - 1; // highest position
+ } else /*if (yPos > (yMid +yDead))*/ { // part up
+ int lo = (yMid +yDead) +1; // lowest position
+ int hi = (yMax -yDead) -1; // highest position
- int range = (hi - lo) + 1; // range covered
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
+ int range = (hi -lo) +1; // range covered
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
- int hi1 = lo + div - 1; // (in brevity)
- int lo3 = lo + div + div + (rem == 2); // ...
+ int hi1 = lo +div -1; // (in brevity)
+ int lo3 = lo +div +div +(rem==2); // ...
- if(yPos <= hi1)
- yOff = -1; // zone #-1
- else if(yPos >= lo3)
- yOff = -3; // zone #-3
- else
- yOff = -2; // zone #-2
- }
+ if (yPos <= hi1) yOff = -1 ; // zone #-1
+ else if (yPos >= lo3) yOff = -3 ; // zone #-3
+ else yOff = -2 ; // zone #-2
+ }
- show(canvas, x - (img_cc_Joy.w / 2), y - (img_cc_Joy.h / 2), &img_cc_Joy, SHOW_SET_BLK);
+ show(canvas, x-(img_cc_Joy.w/2),y-(img_cc_Joy.h/2), &img_cc_Joy, SHOW_SET_BLK);
- // All ^that^ for v-this-v - LOL!!
- canvas_draw_box(canvas, (x - 1) + xOff, (y - 1) + yOff, 3, 3);
+ // All ^that^ for v-this-v - LOL!!
+ canvas_draw_box(canvas, (x-1)+xOff,(y-1)+yOff, 3,3);
}
diff --git a/applications/plugins/wii_ec_anal/wii_anal_lcd.h b/applications/plugins/wii_ec_anal/wii_anal_lcd.h
index e52a3adc6..5258c4de1 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_lcd.h
+++ b/applications/plugins/wii_ec_anal/wii_anal_lcd.h
@@ -1,57 +1,43 @@
-#ifndef WII_ANAL_LCD_H_
-#define WII_ANAL_LCD_H_
+#ifndef WII_ANAL_LCD_H_
+#define WII_ANAL_LCD_H_
//----------------------------------------------------------------------------- ----------------------------------------
// A couple of monospaced hex fonts
//
#include "gfx/images.h"
-extern const image_t* img_6x8[];
-extern const image_t* img_5x7[];
+extern const image_t* img_6x8[];
+extern const image_t* img_5x7[];
//============================================================================= ========================================
// macros to draw only two sides of a box
// these are used for drawing the wires on the WAIT screen
//
-#define BOX_TL(x1, y1, x2, y2) \
- do { \
- canvas_draw_frame(canvas, x1, y1, x2 - x1 + 1, 2); \
- canvas_draw_frame(canvas, x1, y1 + 2, 2, y2 - y1 + 1 - 2); \
- } while(0)
+#define BOX_TL(x1,y1,x2,y2) do { \
+ canvas_draw_frame(canvas, x1,y1, x2-x1+1,2); \
+ canvas_draw_frame(canvas, x1,y1+2, 2,y2-y1+1-2); \
+}while(0)
+
+#define BOX_BL(x1,y1,x2,y2) do { \
+ canvas_draw_frame(canvas, x1,y2-1, x2-x1+1,2); \
+ canvas_draw_frame(canvas, x1,y1, 2,y2-y1+1-2); \
+}while(0)
-#define BOX_BL(x1, y1, x2, y2) \
- do { \
- canvas_draw_frame(canvas, x1, y2 - 1, x2 - x1 + 1, 2); \
- canvas_draw_frame(canvas, x1, y1, 2, y2 - y1 + 1 - 2); \
- } while(0)
//============================================================================= ========================================
// Function prototypes
//
-void patBacklight(state_t* state);
+void patBacklight (state_t* state) ;
-void showHex(
- Canvas* const canvas,
- uint8_t x,
- uint8_t y,
- const uint32_t val,
- const uint8_t cnt,
- const int b);
+void showHex ( Canvas* const canvas, uint8_t x, uint8_t y,
+ const uint32_t val, const uint8_t cnt, const int b ) ;
-void showPeakHold(state_t* const state, Canvas* const canvas, const int hold);
+void showPeakHold (state_t* const state, Canvas* const canvas, const int hold) ;
+
+void showJoy ( Canvas* const canvas, const uint8_t x, const uint8_t y, // x,y is the CENTRE of the Joystick
+ const uint8_t xMin, const uint8_t xMid, const uint8_t xMax,
+ const uint8_t yMin, const uint8_t yMid, const uint8_t yMax,
+ const uint8_t xPos, const uint8_t yPos, const uint8_t bits ) ;
-void showJoy(
- Canvas* const canvas,
- const uint8_t x,
- const uint8_t y, // x,y is the CENTRE of the Joystick
- const uint8_t xMin,
- const uint8_t xMid,
- const uint8_t xMax,
- const uint8_t yMin,
- const uint8_t yMid,
- const uint8_t yMax,
- const uint8_t xPos,
- const uint8_t yPos,
- const uint8_t bits);
#endif //WII_ANAL_LCD_H_
diff --git a/applications/plugins/wii_ec_anal/wii_anal_ver.h b/applications/plugins/wii_ec_anal/wii_anal_ver.h
index 3f2c8c0e6..88ed17d19 100644
--- a/applications/plugins/wii_ec_anal/wii_anal_ver.h
+++ b/applications/plugins/wii_ec_anal/wii_anal_ver.h
@@ -1,9 +1,9 @@
-#ifndef WII_ANAL_VER_H_
-#define WII_ANAL_VER_H_
+#ifndef WII_ANAL_VER_H_
+#define WII_ANAL_VER_H_
-#include "gfx/images.h"
+#include "gfx/images.h"
-#define VER_MAJ &img_3x5_1
-#define VER_MIN &img_3x5_0
+#define VER_MAJ &img_3x5_1
+#define VER_MIN &img_3x5_0
#endif //WII_ANAL_VER_H_
diff --git a/applications/plugins/wii_ec_anal/wii_ec.c b/applications/plugins/wii_ec_anal/wii_ec.c
index 00dcbf922..93b17c67c 100644
--- a/applications/plugins/wii_ec_anal/wii_ec.c
+++ b/applications/plugins/wii_ec_anal/wii_ec.c
@@ -1,298 +1,220 @@
-#include
-#include // Core API
+#include
+#include // Core API
-#include "wii_anal.h"
-#include "wii_i2c.h"
-#include "wii_ec.h"
-#include "bc_logging.h"
+#include "wii_anal.h"
+#include "wii_i2c.h"
+#include "wii_ec.h"
+#include "bc_logging.h"
-#include "gfx/images.h" // Images
-#include "wii_anal_lcd.h" // Drawing functions
-#include "wii_anal_keys.h" // key mappings
+#include "gfx/images.h" // Images
+#include "wii_anal_lcd.h" // Drawing functions
+#include "wii_anal_keys.h" // key mappings
//----------------------------------------------------------------------------- ----------------------------------------
// List of known perhipherals
//
// More perhipheral ID codes here: https://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way
//
-const ecId_t ecId[PID_CNT] = {
- [PID_UNKNOWN] =
- {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- "Unknown Perhipheral",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- ec_show,
- ec_key},
+const ecId_t ecId[PID_CNT] = {
+ [PID_UNKNOWN ] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, "Unknown Perhipheral", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, ec_show, ec_key},
- // If you're wise, ONLY edit this bit
- [PID_NUNCHUCK] =
- {{0x00, 0x00, 0xA4, 0x20, 0x00, 0x00},
- "Nunchuck",
- SCENE_NUNCHUCK,
- NULL,
- nunchuck_decode,
- nunchuck_msg,
- nunchuck_calib,
- nunchuck_show,
- nunchuck_key},
+ // If you're wise, ONLY edit this bit
+ [PID_NUNCHUCK ] = { {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}, "Nunchuck", SCENE_NUNCHUCK,
+ NULL, nunchuck_decode, nunchuck_msg, nunchuck_calib, nunchuck_show, nunchuck_key },
- [PID_NUNCHUCK_R2] =
- {{0xFF, 0x00, 0xA4, 0x20, 0x00, 0x00},
- "Nunchuck (rev2)",
- SCENE_NUNCHUCK,
- NULL,
- nunchuck_decode,
- nunchuck_msg,
- nunchuck_calib,
- nunchuck_show,
- nunchuck_key},
+ [PID_NUNCHUCK_R2] = { {0xFF, 0x00, 0xA4, 0x20, 0x00, 0x00}, "Nunchuck (rev2)", SCENE_NUNCHUCK,
+ NULL, nunchuck_decode, nunchuck_msg, nunchuck_calib, nunchuck_show, nunchuck_key },
- [PID_CLASSIC] =
- {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x01},
- "Classic Controller",
- SCENE_CLASSIC,
- NULL,
- classic_decode,
- classic_msg,
- classic_calib,
- classic_show,
- classic_key},
+ [PID_CLASSIC ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}, "Classic Controller", SCENE_CLASSIC,
+ NULL, classic_decode, classic_msg, classic_calib, classic_show, classic_key },
- [PID_CLASSIC_PRO] =
- {{0x01, 0x00, 0xA4, 0x20, 0x01, 0x01},
- "Classic Controller Pro",
- SCENE_CLASSIC,
- NULL,
- classic_decode,
- classic_msg,
- classic_calib,
- classic_show,
- classic_key},
+ [PID_CLASSIC_PRO] = { {0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}, "Classic Controller Pro", SCENE_CLASSIC,
+ NULL, classic_decode, classic_msg, classic_calib, classic_show, classic_key },
- [PID_BALANCE] =
- {{0x00, 0x00, 0xA4, 0x20, 0x04, 0x02},
- "Balance Board",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ [PID_BALANCE ] = { {0x00, 0x00, 0xA4, 0x20, 0x04, 0x02}, "Balance Board", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, NULL, NULL },
- [PID_GH_GUITAR] =
- {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x03},
- "Guitar Hero Guitar",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ [PID_GH_GUITAR ] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero Guitar", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, NULL, NULL },
- [PID_GH_DRUMS] =
- {{0x01, 0x00, 0xA4, 0x20, 0x01, 0x03},
- "Guitar Hero World Tour Drums",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ [PID_GH_DRUMS ] = { {0x01, 0x00, 0xA4, 0x20, 0x01, 0x03}, "Guitar Hero World Tour Drums", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, NULL, NULL },
- [PID_TURNTABLE] =
- {{0x03, 0x00, 0xA4, 0x20, 0x01, 0x03},
- "DJ Hero Turntable",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ [PID_TURNTABLE ] = { {0x03, 0x00, 0xA4, 0x20, 0x01, 0x03}, "DJ Hero Turntable", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, NULL, NULL },
- [PID_TAIKO_DRUMS] =
- {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x11},
- "Taiko Drum Controller)",
- SCENE_DUMP,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL}, // Taiko no Tatsujin TaTaCon (Drum controller)
+ [PID_TAIKO_DRUMS] = { {0x00, 0x00, 0xA4, 0x20, 0x01, 0x11}, "Taiko Drum Controller)", SCENE_DUMP,
+ NULL, NULL, NULL, NULL, NULL, NULL }, // Taiko no Tatsujin TaTaCon (Drum controller)
- [PID_UDRAW] =
- {{0xFF, 0x00, 0xA4, 0x20, 0x00, 0x13},
- "uDraw Tablet",
- SCENE_DUMP,
- udraw_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL}, //! same as drawsome?
- // -----
+ [PID_UDRAW ] = { {0xFF, 0x00, 0xA4, 0x20, 0x00, 0x13}, "uDraw Tablet", SCENE_DUMP,
+ udraw_init, NULL, NULL, NULL, NULL, NULL }, //! same as drawsome?
+ // -----
- [PID_ERROR] =
- {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
- "Read Error",
- SCENE_NONE,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL},
+ [PID_ERROR ] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, "Read Error", SCENE_NONE,
+ NULL, NULL, NULL, NULL, NULL, NULL },
- [PID_NULL] = {{0}, NULL, SCENE_NONE, NULL, NULL, NULL, NULL, NULL, NULL} // last entry
+ [PID_NULL ] = { {0}, NULL, SCENE_NONE, NULL, NULL, NULL, NULL, NULL, NULL } // last entry
};
//+============================================================================ ========================================
-void ecDecode(wiiEC_t* pec) {
- if(ecId[pec->pidx].decode) ecId[pec->pidx].decode(pec);
+void ecDecode (wiiEC_t* pec)
+{
+ if (ecId[pec->pidx].decode) ecId[pec->pidx].decode(pec) ;
}
//+============================================================================ ========================================
-void ecCalibrate(wiiEC_t* const pec, ecCalib_t c) {
- if(ecId[pec->pidx].calib) ecId[pec->pidx].calib(pec, c);
+void ecCalibrate (wiiEC_t* const pec, ecCalib_t c)
+{
+ if (ecId[pec->pidx].calib) ecId[pec->pidx].calib(pec, c) ;
}
//+============================================================================ ========================================
-void ecPoll(wiiEC_t* const pec, FuriMessageQueue* const queue) {
- ENTER;
- furi_assert(queue);
+void ecPoll (wiiEC_t* const pec, FuriMessageQueue* const queue)
+{
+ ENTER;
+ furi_assert(queue);
- if(!pec->init) {
- // Attempt to initialise
- if(ecInit(pec, NULL)) { //! need a way to auto-start with encryption enabled
- eventMsg_t msg = {
- .id = EVID_WIIEC, .wiiEc = {.type = WIIEC_CONN, .in = '<', .val = pec->pidx}};
- furi_message_queue_put(queue, &msg, 0);
- }
+ if (!pec->init) {
+ // Attempt to initialise
+ if (ecInit(pec, NULL)) { //! need a way to auto-start with encryption enabled
+ eventMsg_t msg = {
+ .id = EVID_WIIEC,
+ .wiiEc = {
+ .type = WIIEC_CONN,
+ .in = '<',
+ .val = pec->pidx
+ }
+ };
+ furi_message_queue_put(queue, &msg, 0);
+ }
- } else {
- // Attempt to read
- switch(ecRead(pec)) {
- case 2: { // device gone
- eventMsg_t msg = {
- .id = EVID_WIIEC, .wiiEc = {.type = WIIEC_DISCONN, .in = '>', .val = pec->pidx}};
- furi_message_queue_put(queue, &msg, 0);
- break;
- }
+ } else {
+ // Attempt to read
+ switch (ecRead(pec)) {
+ case 2: { // device gone
+ eventMsg_t msg = {
+ .id = EVID_WIIEC,
+ .wiiEc = {
+ .type = WIIEC_DISCONN,
+ .in = '>',
+ .val = pec->pidx
+ }
+ };
+ furi_message_queue_put(queue, &msg, 0);
+ break;
+ }
- case 0: { // read OK
- void (*fn)(wiiEC_t*, FuriMessageQueue*) = ecId[pec->pidx].check;
- if(fn) fn(pec, queue);
- break;
- }
+ case 0: { // read OK
+ void (*fn)(wiiEC_t*, FuriMessageQueue*) = ecId[pec->pidx].check;
+ if (fn) fn(pec, queue);
+ break;
+ }
- case 3: // read fail
- // this is probably temporary just ignore it
- break;
+ case 3: // read fail
+ // this is probably temporary just ignore it
+ break;
- default: // bug: unknown
- case 1: // bug: not initialised - should never happen
- ERROR("%s : read bug", __func__);
- break;
- }
- }
+ default: // bug: unknown
+ case 1: // bug: not initialised - should never happen
+ ERROR("%s : read bug", __func__);
+ break;
+ }
+ }
- LEAVE;
- return;
+ LEAVE;
+ return;
}
//+============================================================================ ========================================
// This is the screen drawn for an unknown controller
// It is also available by pressing LEFT (at least once) on a "known controller" screen
//
-void ec_show(Canvas* const canvas, state_t* const state) {
- wiiEC_t* pec = &state->ec;
- int h = 11; // line height
- int x = 1; // (initial) offset for bits
- int y = -h; // previous y value
- int yb = 0; // y for bit patterns
- int c2 = 17; // column 2
+void ec_show (Canvas* const canvas, state_t* const state)
+{
+ wiiEC_t* pec = &state->ec;
+ int h = 11; // line height
+ int x = 1; // (initial) offset for bits
+ int y = -h; // previous y value
+ int yb = 0; // y for bit patterns
+ int c2 = 17; // column 2
- // Headings
- canvas_set_font(canvas, FontSecondary);
- canvas_set_color(canvas, ColorBlack);
+ // Headings
+ canvas_set_font(canvas, FontSecondary);
+ canvas_set_color(canvas, ColorBlack);
- canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "SID:");
- canvas_draw_str_aligned(canvas, c2, 0, AlignLeft, AlignTop, pec->sid);
+ canvas_draw_str_aligned(canvas, 0 ,0, AlignLeft, AlignTop, "SID:");
+ canvas_draw_str_aligned(canvas, c2,0, AlignLeft, AlignTop, pec->sid);
- canvas_draw_str_aligned(canvas, 0, 11, AlignLeft, AlignTop, "PID:");
- canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Cal:");
+ canvas_draw_str_aligned(canvas, 0 ,11, AlignLeft, AlignTop, "PID:");
+ canvas_draw_str_aligned(canvas, 0 ,22, AlignLeft, AlignTop, "Cal:");
- // PID
- x = c2;
- for(int i = 0; i < 6; i++) {
- show(canvas, x, 11, img_5x7[pec->pid[i] >> 4], SHOW_SET_BLK);
- x += 5 + 1;
- show(canvas, x, 11, img_5x7[pec->pid[i] & 0xF], SHOW_SET_BLK);
- x += 5 + 1 + 2;
- }
+ // PID
+ x = c2;
+ for (int i = 0; i < 6; i++) {
+ show(canvas, x,11, img_5x7[pec->pid[i]>>4], SHOW_SET_BLK);
+ x += 5+1;
+ show(canvas, x,11, img_5x7[pec->pid[i]&0xF], SHOW_SET_BLK);
+ x += 5+1+2;
+ }
- // Calibrations data
- y = 11;
- for(int j = 0; j <= 8; j += 8) {
- x = c2;
- y += 11;
- for(int i = 0; i < 8; i++) {
- show(canvas, x, y, img_5x7[pec->calF[i + j] >> 4], SHOW_SET_BLK);
- x += 5 + 1;
- show(canvas, x, y, img_5x7[pec->calF[i + j] & 0xF], SHOW_SET_BLK);
- x += 5 + 1 + 2;
- }
- }
+ // Calibrations data
+ y = 11;
+ for (int j = 0; j <= 8; j += 8) {
+ x = c2;
+ y += 11;
+ for (int i = 0; i < 8; i++) {
+ show(canvas, x,y, img_5x7[pec->calF[i+j]>>4], SHOW_SET_BLK);
+ x += 5+1;
+ show(canvas, x,y, img_5x7[pec->calF[i+j]&0xF], SHOW_SET_BLK);
+ x += 5+1+2;
+ }
+ }
- // Reading
- x = 1;
- y++;
- yb = (y += h) + h + 2;
+ // Reading
+ x = 1;
+ y++;
+ yb = (y+=h) +h +2;
- canvas_draw_line(canvas, x, y - 1, x, yb + 4);
- x += 2;
+ canvas_draw_line(canvas, x,y-1, x,yb+4);
+ x += 2;
- for(int i = 0; i < JOY_LEN; i++) {
- show(canvas, x + 1, y, img_6x8[pec->joy[i] >> 4], SHOW_SET_BLK);
- show(canvas, x + 11, y, img_6x8[pec->joy[i] & 0xF], SHOW_SET_BLK);
+ for (int i = 0; i < JOY_LEN; i++) {
+ show(canvas, x+ 1,y, img_6x8[pec->joy[i]>>4], SHOW_SET_BLK);
+ show(canvas, x+11,y, img_6x8[pec->joy[i]&0xF], SHOW_SET_BLK);
- // bits
- for(int m = 0x80; m; m >>= 1) {
- x += 2 * !!(m & 0x08); // nybble step
- canvas_draw_box(canvas, x, yb + (2 * !(pec->joy[i] & m)), 2, 2);
- x += 2; // bit step
- }
+ // bits
+ for (int m = 0x80; m; m >>= 1) {
+ x += 2 * !!(m & 0x08) ; // nybble step
+ canvas_draw_box(canvas, x,yb +(2*!(pec->joy[i] & m)), 2,2) ;
+ x += 2; // bit step
+ }
- // byte step
- x += 1;
- canvas_draw_line(canvas, x, y - 1, x, yb + 4);
- x += 2;
- }
+ // byte step
+ x += 1;
+ canvas_draw_line(canvas, x,y-1, x,yb+4);
+ x += 2;
+ }
- // Scene navigation
- if(state->scenePrev != SCENE_WAIT) show(canvas, 120, 0, &img_key_R, SHOW_SET_BLK);
+ // Scene navigation
+ if (state->scenePrev != SCENE_WAIT)
+ show(canvas, 120,0, &img_key_R, SHOW_SET_BLK);
}
//+============================================================================ ========================================
-// The DUMP screen is
+// The DUMP screen is
//
-bool ec_key(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+bool ec_key (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- if(state->scenePrev != SCENE_WAIT) {
- //# input.type == InputTypeShort) && (msg->input.key == InputKeyRight)) {
- sceneSet(state, state->scenePrev);
- used = true;
- }
- }
+ if (state->scenePrev != SCENE_WAIT) {
+ //# input.type == InputTypeShort) && (msg->input.key == InputKeyRight)) {
+ sceneSet(state, state->scenePrev);
+ used = true;
+ }
+ }
- return used;
+ return used;
}
diff --git a/applications/plugins/wii_ec_anal/wii_ec.h b/applications/plugins/wii_ec_anal/wii_ec.h
index a28453740..e8745ba13 100644
--- a/applications/plugins/wii_ec_anal/wii_ec.h
+++ b/applications/plugins/wii_ec_anal/wii_ec.h
@@ -1,142 +1,158 @@
-#ifndef WII_EC_H_
-#define WII_EC_H_
+#ifndef WII_EC_H_
+#define WII_EC_H_
-#include
+#include
-#include
+#include
-#include "wii_ec_nunchuck.h"
-#include "wii_ec_classic.h"
-#include "wii_ec_udraw.h"
+#include "wii_ec_nunchuck.h"
+#include "wii_ec_classic.h"
+#include "wii_ec_udraw.h"
//----------------------------------------------------------------------------- ----------------------------------------
// Crypto key (PSK), base register : {0x40..0x4F}[2][8]
-#define ENC_LEN (2 * 8)
+#define ENC_LEN (2*8)
// Controller State data, base register : {0x00..0x05}[6]
-#define JOY_LEN (6)
+#define JOY_LEN (6)
// Calibration data, base register : {0x20..0x2F}[16]
-#define CAL_LEN (16)
+#define CAL_LEN (16)
// Controller ID, base register : {0xFA..0xFF}[6]
-#define PID_LEN (6)
+#define PID_LEN (6)
//----------------------------------------------------------------------------- ----------------------------------------
// Perhipheral specific parameters union
//
-typedef union ecDec {
- ecDecNunchuck_t nunchuck;
- ecDecClassic_t classic;
-} ecDec_t;
+typedef
+ union ecDec {
+ ecDecNunchuck_t nunchuck;
+ ecDecClassic_t classic;
+ }
+ecDec_t;
//-----------------------------------------------------------------------------
-typedef union ecCal {
- // 0=lowest seen ; 1=min ; 2=mid ; 3=max ; 4=highest seen
- ecCalNunchuck_t nunchuck[5];
- ecCalClassic_t classic[5];
-} ecCal_t;
+typedef
+ union ecCal {
+ // 0=lowest seen ; 1=min ; 2=mid ; 3=max ; 4=highest seen
+ ecCalNunchuck_t nunchuck[5];
+ ecCalClassic_t classic[5];
+ }
+ecCal_t;
//----------------------------------------------------------------------------- ----------------------------------------
// Wii Extension Controller events
//
-typedef enum wiiEcEventType {
- WIIEC_NONE,
- WIIEC_CONN, // Connect
- WIIEC_DISCONN, // Disconnect
- WIIEC_PRESS, // Press button
- WIIEC_RELEASE, // Release button
- WIIEC_ANALOG, // Analogue change (Joystick/Trigger)
- WIIEC_ACCEL, // Accelerometer change
-} wiiEcEventType_t;
+typedef
+ enum wiiEcEventType {
+ WIIEC_NONE,
+ WIIEC_CONN, // Connect
+ WIIEC_DISCONN, // Disconnect
+ WIIEC_PRESS, // Press button
+ WIIEC_RELEASE, // Release button
+ WIIEC_ANALOG, // Analogue change (Joystick/Trigger)
+ WIIEC_ACCEL, // Accelerometer change
+ }
+wiiEcEventType_t;
//-----------------------------------------------------------------------------
-typedef struct wiiEcEvent {
- wiiEcEventType_t type; // event type
- char in; // input (see device specific options)
- uint32_t val; // new value - meaningless for digital button presses
-} wiiEcEvent_t;
+typedef
+ struct wiiEcEvent {
+ wiiEcEventType_t type; // event type
+ char in; // input (see device specific options)
+ uint32_t val; // new value - meaningless for digital button presses
+ }
+wiiEcEvent_t;
//----------------------------------------------------------------------------- ----------------------------------------
// Known perhipheral types
//
-typedef enum ecPid {
- PID_UNKNOWN = 0,
- PID_FIRST = 1,
- PID_NUNCHUCK = PID_FIRST,
+typedef
+ enum ecPid {
+ PID_UNKNOWN = 0,
+ PID_FIRST = 1,
+ PID_NUNCHUCK = PID_FIRST,
- // If you're wise, ONLY edit this section
- PID_NUNCHUCK_R2,
- PID_CLASSIC,
- PID_CLASSIC_PRO,
- PID_BALANCE,
- PID_GH_GUITAR,
- PID_GH_DRUMS,
- PID_TURNTABLE,
- PID_TAIKO_DRUMS,
- PID_UDRAW, //! same as drawsome?
- // -----
+ // If you're wise, ONLY edit this section
+ PID_NUNCHUCK_R2,
+ PID_CLASSIC,
+ PID_CLASSIC_PRO,
+ PID_BALANCE,
+ PID_GH_GUITAR,
+ PID_GH_DRUMS,
+ PID_TURNTABLE,
+ PID_TAIKO_DRUMS,
+ PID_UDRAW, //! same as drawsome?
+ // -----
- PID_ERROR,
- PID_NULL,
- PID_CNT,
-} ecPid_t;
+ PID_ERROR,
+ PID_NULL,
+ PID_CNT,
+ }
+ecPid_t;
//-----------------------------------------------------------------------------
// Calibration strategies
//
-typedef enum ecCalib {
- CAL_FACTORY = 0x01, // (re)set to factory defaults
- CAL_TRACK = 0x02, // track maximum and minimum values seen
- CAL_RESET = 0x04, // initialise ready for software calibration
- CAL_RANGE = 0x08, // perform software calibration step
- CAL_CENTRE = 0x10, // reset centre point of joystick
- CAL_NOTJOY = 0x20, // do NOT calibrate the joystick
-} ecCalib_t;
+typedef
+ enum ecCalib {
+ CAL_FACTORY = 0x01, // (re)set to factory defaults
+ CAL_TRACK = 0x02, // track maximum and minimum values seen
+ CAL_RESET = 0x04, // initialise ready for software calibration
+ CAL_RANGE = 0x08, // perform software calibration step
+ CAL_CENTRE = 0x10, // reset centre point of joystick
+ CAL_NOTJOY = 0x20, // do NOT calibrate the joystick
+ }
+ecCalib_t;
//-----------------------------------------------------------------------------
// ecId table entry
//
-typedef struct ecId {
- uint8_t id[6]; // 6 byte ID string returned by Extension Controller
- char* name; // Friendly name
- scene_t scene; // Default scene
- bool (*init)(wiiEC_t*); // Additional initialisation code
- void (*decode)(wiiEC_t*); // Decode function
- void (*check)(wiiEC_t*, FuriMessageQueue*); // check (for action) function
- void (*calib)(wiiEC_t*, ecCalib_t); // calibrate analogue controllers [SOFTWARE]
- void (*show)(Canvas* const, state_t* const); // Draw scene
- bool (*keys)(const eventMsg_t* const, state_t* const); // Interpret keys
-} ecId_t;
+typedef
+ struct ecId {
+ uint8_t id[6]; // 6 byte ID string returned by Extension Controller
+ char* name; // Friendly name
+ scene_t scene; // Default scene
+ bool (*init)(wiiEC_t*); // Additional initialisation code
+ void (*decode)(wiiEC_t*); // Decode function
+ void (*check)(wiiEC_t*, FuriMessageQueue*); // check (for action) function
+ void (*calib)(wiiEC_t*, ecCalib_t); // calibrate analogue controllers [SOFTWARE]
+ void (*show)(Canvas* const, state_t* const); // Draw scene
+ bool (*keys)(const eventMsg_t* const, state_t* const); // Interpret keys
+ }
+ecId_t;
//-----------------------------------------------------------------------------
// List of known perhipherals
//
// More perhipheral ID codes here: https://wiibrew.org/wiki/Wiimote/Extension_Controllers#The_New_Way
//
-extern const ecId_t ecId[PID_CNT];
+extern const ecId_t ecId[PID_CNT] ;
//----------------------------------------------------------------------------- ----------------------------------------
// Data pertaining to a single Perhipheral instance
//
-typedef struct wiiEC {
- // Perhipheral state
- bool init; // Initialised?
+typedef
+ struct wiiEC {
+ // Perhipheral state
+ bool init; // Initialised?
- uint8_t pid[PID_LEN]; // PID string - eg. {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}
- ecPid_t pidx; // Index in to ecId table
- const char* sid; // just for convenience
+ uint8_t pid[PID_LEN]; // PID string - eg. {0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}
+ ecPid_t pidx; // Index in to ecId table
+ const char* sid; // just for convenience
- bool encrypt; // encryption enabled?
- uint8_t encKey[ENC_LEN]; // encryption key
+ bool encrypt; // encryption enabled?
+ uint8_t encKey[ENC_LEN]; // encryption key
- uint8_t calF[CAL_LEN]; // factory calibration data (not software)
- uint8_t joy[JOY_LEN]; // Perhipheral raw data
+ uint8_t calF[CAL_LEN]; // factory calibration data (not software)
+ uint8_t joy[JOY_LEN]; // Perhipheral raw data
- ecDec_t dec[2]; // device specific decode (two, so we can spot changes)
- int decN; // which decode set is most recent {0, 1}
- ecCal_t calS; // software calibration data
-} wiiEC_t;
+ ecDec_t dec[2]; // device specific decode (two, so we can spot changes)
+ int decN; // which decode set is most recent {0, 1}
+ ecCal_t calS; // software calibration data
+ }
+wiiEC_t;
//----------------------------------------------------------------------------- ----------------------------------------
// Function prototypes
@@ -145,17 +161,17 @@ typedef struct wiiEC {
// top level check() function will handle connect/disconnect messages
//
-#include // Canvas
-typedef struct wiiEC wiiEC_t;
-typedef enum ecCalib ecCalib_t;
-typedef struct state state_t;
-typedef struct eventMsg eventMsg_t;
+#include // Canvas
+typedef struct wiiEC wiiEC_t ;
+typedef enum ecCalib ecCalib_t ;
+typedef struct state state_t ;
+typedef struct eventMsg eventMsg_t ;
-void ecDecode(wiiEC_t* const pec);
-void ecPoll(wiiEC_t* const pec, FuriMessageQueue* const queue);
-void ecCalibrate(wiiEC_t* const pec, ecCalib_t c);
+void ecDecode (wiiEC_t* const pec) ;
+void ecPoll (wiiEC_t* const pec, FuriMessageQueue* const queue) ;
+void ecCalibrate (wiiEC_t* const pec, ecCalib_t c) ;
-void ec_show(Canvas* const canvas, state_t* const state);
-bool ec_key(const eventMsg_t* const msg, state_t* const state);
+void ec_show ( Canvas* const canvas, state_t* const state) ;
+bool ec_key (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_EC_H_
diff --git a/applications/plugins/wii_ec_anal/wii_ec_classic.c b/applications/plugins/wii_ec_anal/wii_ec_classic.c
index 5bd3398ca..91393ba07 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_classic.c
+++ b/applications/plugins/wii_ec_anal/wii_ec_classic.c
@@ -1,17 +1,17 @@
-#include
-#include // Core API
+#include
+#include // Core API
-#include "wii_anal.h"
-#include "wii_ec.h"
-#include "bc_logging.h"
+#include "wii_anal.h"
+#include "wii_ec.h"
+#include "bc_logging.h"
//#include "gfx/images.h" // Images
-#include "wii_anal_lcd.h" // Drawing functions
-#include "wii_anal_keys.h" // key mappings
+#include "wii_anal_lcd.h" // Drawing functions
+#include "wii_anal_keys.h" // key mappings
// ** If you want to see what this source code looks like with all the MACROs expanded
// ** grep -v '#include ' wii_i2c_classic.c | gcc -E -o /dev/stdout -xc -
-#include "wii_ec_macros.h"
+# include "wii_ec_macros.h"
//----------------------------------------------------------------------------- ----------------------------------------
// Classic Controller ... Classic Controller Pro is electronically the same
@@ -36,115 +36,102 @@
// ...And yes, the left-joystick has an extra 'bit' of precision!
// ...Also: trgZ{L|R} WILL continue to increase after btnZ{L|R} has gone active
//
-void classic_decode(wiiEC_t* const pec) {
- ecDecClassic_t* p = &pec->dec[(pec->decN = !pec->decN)].classic;
- uint8_t* joy = pec->joy;
+void classic_decode (wiiEC_t* const pec)
+{
+ ecDecClassic_t* p = &pec->dec[(pec->decN = !pec->decN)].classic;
+ uint8_t* joy = pec->joy;
- p->trgZL = ((joy[2] >> 2) & 0x18) | ((joy[3] >> 5) & 0x07); // {5}
- p->btnZL = !(joy[4] & 0x20); // !{1}
+ p->trgZL = ((joy[2] >>2) &0x18) | ((joy[3] >>5) &0x07); // {5}
+ p->btnZL = !(joy[4] & 0x20); // !{1}
- p->trgZR = joy[3] & 0x1F; // {5}
- p->btnZR = !(joy[4] & 0x02); // !{1}
+ p->trgZR = joy[3] & 0x1F; // {5}
+ p->btnZR = !(joy[4] & 0x02); // !{1}
- p->btnL = !(joy[5] & 0x80); // !{1}
- p->btnR = !(joy[5] & 0x04); // !{1}
+ p->btnL = !(joy[5] & 0x80); // !{1}
+ p->btnR = !(joy[5] & 0x04); // !{1}
- p->padU = !(joy[5] & 0x01); // !{1}
- p->padD = !(joy[4] & 0x40); // !{1}
- p->padL = !(joy[5] & 0x02); // !{1}
- p->padR = !(joy[4] & 0x80); // !{1}
+ p->padU = !(joy[5] & 0x01); // !{1}
+ p->padD = !(joy[4] & 0x40); // !{1}
+ p->padL = !(joy[5] & 0x02); // !{1}
+ p->padR = !(joy[4] & 0x80); // !{1}
- p->btnM = !(joy[4] & 0x10); // !{1}
- p->btnH = !(joy[4] & 0x08); // !{1}
- p->btnP = !(joy[4] & 0x04); // !{1}
+ p->btnM = !(joy[4] & 0x10); // !{1}
+ p->btnH = !(joy[4] & 0x08); // !{1}
+ p->btnP = !(joy[4] & 0x04); // !{1}
- p->btnX = !(joy[5] & 0x08); // !{1}
- p->btnY = !(joy[5] & 0x20); // !{1}
+ p->btnX = !(joy[5] & 0x08); // !{1}
+ p->btnY = !(joy[5] & 0x20); // !{1}
- p->btnA = !(joy[5] & 0x10); // !{1}
- p->btnB = !(joy[5] & 0x40); // !{1}
+ p->btnA = !(joy[5] & 0x10); // !{1}
+ p->btnB = !(joy[5] & 0x40); // !{1}
- p->joyLX = joy[0] & 0x3F; // {6}
- p->joyLY = joy[1] & 0x3F; // {6}
+ p->joyLX = joy[0] & 0x3F; // {6}
+ p->joyLY = joy[1] & 0x3F; // {6}
- p->joyRX = ((joy[0] >> 3) & 0x18) | ((joy[1] >> 5) & 0x06) | ((joy[2] >> 7) & 0x01); // {5}
- p->joyRY = joy[2] & 0x1F; // {5}
+ p->joyRX = ((joy[0] >>3) &0x18) | ((joy[1] >>5) &0x06) | ((joy[2] >>7) &0x01); // {5}
+ p->joyRY = joy[2] & 0x1F; // {5}
- DEBUG(
- ">%d> ZL{%02X}%c, L:%c, R:%c, ZR{%02X}%c",
- pec->decN,
- p->trgZL,
- (p->btnZL ? '#' : '.'),
- (p->btnL ? '#' : '.'),
- (p->btnR ? '#' : '.'),
- p->trgZR,
- (p->btnZR ? '#' : '.'));
- DEBUG(
- ">%d> D:{%c,%c,%c,%c}, H:{%c,%c,%c}, B:{%c,%c,%c,%c}",
- pec->decN,
- (p->padU ? 'U' : '.'),
- (p->padD ? 'D' : '.'),
- (p->padL ? 'L' : '.'),
- (p->padR ? 'R' : '.'),
- (p->btnM ? '-' : '.'),
- (p->btnH ? 'H' : '.'),
- (p->btnP ? '+' : '.'),
- (p->btnX ? 'X' : '.'),
- (p->btnY ? 'Y' : '.'),
- (p->btnA ? 'A' : '.'),
- (p->btnB ? 'B' : '.'));
- DEBUG(
- ">%d> JoyL{x:%02X, y:%02X}, JoyR{x:%02X, y:%02X}",
- pec->decN,
- p->joyLX,
- p->joyLY,
- p->joyRX,
- p->joyRY);
+ DEBUG( ">%d> ZL{%02X}%c, L:%c, R:%c, ZR{%02X}%c", pec->decN,
+ p->trgZL, (p->btnZL ? '#' : '.'),
+ (p->btnL ? '#' : '.'),
+ (p->btnR ? '#' : '.'),
+ p->trgZR, (p->btnZR ? '#' : '.')
+ );
+ DEBUG( ">%d> D:{%c,%c,%c,%c}, H:{%c,%c,%c}, B:{%c,%c,%c,%c}", pec->decN,
+ (p->padU ? 'U' : '.'), (p->padD ? 'D' : '.'), (p->padL ? 'L' : '.'), (p->padR ? 'R' : '.'),
+ (p->btnM ? '-' : '.'), (p->btnH ? 'H' : '.'), (p->btnP ? '+' : '.'),
+ (p->btnX ? 'X' : '.'), (p->btnY ? 'Y' : '.'), (p->btnA ? 'A' : '.'), (p->btnB ? 'B' : '.')
+ );
+ DEBUG( ">%d> JoyL{x:%02X, y:%02X}, JoyR{x:%02X, y:%02X}", pec->decN,
+ p->joyLX, p->joyLY, p->joyRX, p->joyRY
+ );
}
//+============================================================================ ========================================
// Give each button a unique character identifier
//
-void classic_msg(wiiEC_t* const pec, FuriMessageQueue* const queue) {
- ecDecClassic_t* new = &pec->dec[pec->decN].classic;
- ecDecClassic_t* old = &pec->dec[!pec->decN].classic;
+void classic_msg (wiiEC_t* const pec, FuriMessageQueue* const queue)
+{
+ ecDecClassic_t* new = &pec->dec[pec->decN].classic;
+ ecDecClassic_t* old = &pec->dec[!pec->decN].classic;
- eventMsg_t msg = {
- .id = EVID_WIIEC,
- .wiiEc = {
- .type = WIIEC_NONE,
- .in = ' ',
- .val = 0,
- }};
+ eventMsg_t msg = {
+ .id = EVID_WIIEC,
+ .wiiEc = {
+ .type = WIIEC_NONE,
+ .in = ' ',
+ .val = 0,
+ }
+ };
- ANALOG(trgZL, 'l'); // FIVE bit value
- ANABTN(btnZL, trgZL, 'l');
+ ANALOG(trgZL, 'l'); // FIVE bit value
+ ANABTN(btnZL, trgZL, 'l');
- BUTTON(btnL, 'L');
- BUTTON(btnR, 'R');
+ BUTTON(btnL, 'L');
+ BUTTON(btnR, 'R');
- ANALOG(trgZR, 'r'); // FIVE bit value
- ANABTN(btnZR, trgZR, 'r');
+ ANALOG(trgZR, 'r'); // FIVE bit value
+ ANABTN(btnZR, trgZR, 'r');
- BUTTON(padU, 'W');
- BUTTON(padL, 'A');
- BUTTON(padD, 'S');
- BUTTON(padR, 'D');
+ BUTTON(padU, 'W');
+ BUTTON(padL, 'A');
+ BUTTON(padD, 'S');
+ BUTTON(padR, 'D');
- BUTTON(btnM, '-');
- BUTTON(btnH, 'h');
- BUTTON(btnP, '+');
+ BUTTON(btnM, '-');
+ BUTTON(btnH, 'h');
+ BUTTON(btnP, '+');
- BUTTON(btnX, 'x');
- BUTTON(btnY, 'y');
- BUTTON(btnA, 'a');
- BUTTON(btnB, 'b');
+ BUTTON(btnX, 'x');
+ BUTTON(btnY, 'y');
+ BUTTON(btnA, 'a');
+ BUTTON(btnB, 'b');
- ANALOG(joyLX, 'x'); // SIX bit values
- ANALOG(joyLY, 'y');
+ ANALOG(joyLX, 'x'); // SIX bit values
+ ANALOG(joyLY, 'y');
- ANALOG(joyRX, 'X'); // FIVE bit values
- ANALOG(joyRY, 'Y');
+ ANALOG(joyRX, 'X'); // FIVE bit values
+ ANALOG(joyRY, 'Y');
}
//+============================================================================ ========================================
@@ -157,283 +144,255 @@ void classic_msg(wiiEC_t* const pec, FuriMessageQueue* const queue) {
// 9..11 right analog stick Y axis {maximum, minimum, center} ... JoyR is 5bits, so >>3 to compare to readings
// 12..15 somehow describe the shoulder {5bit} button values!?
//
-void classic_calib(wiiEC_t* const pec, ecCalib_t c) {
- ecDecClassic_t* src = &pec->dec[pec->decN].classic; // from input
- ecCalClassic_t* dst = pec->calS.classic; // to calibration data
+void classic_calib (wiiEC_t* const pec, ecCalib_t c)
+{
+ ecDecClassic_t* src = &pec->dec[pec->decN].classic; // from input
+ ecCalClassic_t* dst = pec->calS.classic; // to calibration data
- if(c & CAL_RESET) { // initialise ready for software calibration
- // LO is set to the MAXIMUM value (so it can be reduced)
- // HI is set to ZERO (so it can be increased)
- RESET_LO_HI(trgZL, 5); // 5bit value
- RESET_LO_HI(trgZR, 5); // 5bit value
+ if (c & CAL_RESET) { // initialise ready for software calibration
+ // LO is set to the MAXIMUM value (so it can be reduced)
+ // HI is set to ZERO (so it can be increased)
+ RESET_LO_HI(trgZL, 5); // 5bit value
+ RESET_LO_HI(trgZR, 5); // 5bit value
- RESET_LO_MID_HI(joyLX, 6); // 6bit value
- RESET_LO_MID_HI(joyLY, 6); // 6bit value
+ RESET_LO_MID_HI(joyLX, 6); // 6bit value
+ RESET_LO_MID_HI(joyLY, 6); // 6bit value
- RESET_LO_MID_HI(joyRX, 5); // 5bit value
- RESET_LO_MID_HI(joyRY, 5); // 5bit value
- }
- if(c & CAL_FACTORY) { // (re)set to factory defaults
- //! strategy for factory calibration for classic controller [pro] triggers is (currently) unknown
- //! FACTORY_LO( trgZL, pec->calF[12..15]);
- //! FACTORY_MID(trgZL, pec->calF[12..15]);
- //! FACTORY_HI( trgZL, pec->calF[12..15]);
+ RESET_LO_MID_HI(joyRX, 5); // 5bit value
+ RESET_LO_MID_HI(joyRY, 5); // 5bit value
+ }
+ if (c & CAL_FACTORY) { // (re)set to factory defaults
+//! strategy for factory calibration for classic controller [pro] triggers is (currently) unknown
+//! FACTORY_LO( trgZL, pec->calF[12..15]);
+//! FACTORY_MID(trgZL, pec->calF[12..15]);
+//! FACTORY_HI( trgZL, pec->calF[12..15]);
- //! FACTORY_LO( trgZR, pec->calF[12..15]);
- //! FACTORY_MID(trgZR, pec->calF[12..15]);
- //! FACTORY_HI( trgZR, pec->calF[12..15]);
+//! FACTORY_LO( trgZR, pec->calF[12..15]);
+//! FACTORY_MID(trgZR, pec->calF[12..15]);
+//! FACTORY_HI( trgZR, pec->calF[12..15]);
#if 1
- FACTORY_LO(trgZL, 0x03);
- FACTORY_LO(trgZR, 0x03);
+ FACTORY_LO(trgZL, 0x03);
+ FACTORY_LO(trgZR, 0x03);
- FACTORY_MID(trgZL, 0x1B); //! these will be set every time the digital switch changes to ON
- FACTORY_MID(trgZR, 0x1B);
+ FACTORY_MID(trgZL, 0x1B); //! these will be set every time the digital switch changes to ON
+ FACTORY_MID(trgZR, 0x1B);
#endif
- FACTORY_LO(joyLX, pec->calF[1] >> 2);
- FACTORY_MID(joyLX, pec->calF[2] >> 2);
- FACTORY_HI(joyLX, pec->calF[0] >> 2);
+ FACTORY_LO( joyLX, pec->calF[ 1] >>2);
+ FACTORY_MID(joyLX, pec->calF[ 2] >>2);
+ FACTORY_HI( joyLX, pec->calF[ 0] >>2);
- FACTORY_LO(joyLY, pec->calF[4] >> 2);
- FACTORY_MID(joyLY, pec->calF[5] >> 2);
- FACTORY_HI(joyLY, pec->calF[3] >> 2);
+ FACTORY_LO( joyLY, pec->calF[ 4] >>2);
+ FACTORY_MID(joyLY, pec->calF[ 5] >>2);
+ FACTORY_HI( joyLY, pec->calF[ 3] >>2);
- FACTORY_LO(joyRX, pec->calF[7] >> 3);
- FACTORY_MID(joyRX, pec->calF[8] >> 3);
- FACTORY_HI(joyRX, pec->calF[6] >> 3);
+ FACTORY_LO( joyRX, pec->calF[ 7] >>3);
+ FACTORY_MID(joyRX, pec->calF[ 8] >>3);
+ FACTORY_HI( joyRX, pec->calF[ 6] >>3);
- FACTORY_LO(joyRY, pec->calF[10] >> 3);
- FACTORY_MID(joyRY, pec->calF[11] >> 3);
- FACTORY_HI(joyRY, pec->calF[9] >> 3);
- }
- if(c & CAL_TRACK) { // track maximum and minimum values seen
- TRACK_LO_HI(trgZL);
- TRACK_LO_HI(trgZR);
+ FACTORY_LO( joyRY, pec->calF[10] >>3);
+ FACTORY_MID(joyRY, pec->calF[11] >>3);
+ FACTORY_HI( joyRY, pec->calF[ 9] >>3);
+ }
+ if (c & CAL_TRACK) { // track maximum and minimum values seen
+ TRACK_LO_HI(trgZL);
+ TRACK_LO_HI(trgZR);
- TRACK_LO_HI(joyLX);
- TRACK_LO_HI(joyLY);
+ TRACK_LO_HI(joyLX);
+ TRACK_LO_HI(joyLY);
- TRACK_LO_HI(joyRX);
- TRACK_LO_HI(joyRY);
- }
- if(c & CAL_RANGE) { // perform software calibration step
- RANGE_LO_HI(trgZL);
- RANGE_LO_HI(trgZR);
+ TRACK_LO_HI(joyRX);
+ TRACK_LO_HI(joyRY);
+ }
+ if (c & CAL_RANGE) { // perform software calibration step
+ RANGE_LO_HI(trgZL);
+ RANGE_LO_HI(trgZR);
- RANGE_LO_HI(joyLX);
- RANGE_LO_HI(joyLY);
+ RANGE_LO_HI(joyLX);
+ RANGE_LO_HI(joyLY);
- RANGE_LO_HI(joyRX);
- RANGE_LO_HI(joyRY);
- }
- if(c & CAL_CENTRE) { // reset centre point of joystick
- CENTRE(joyLX);
- CENTRE(joyLY);
+ RANGE_LO_HI(joyRX);
+ RANGE_LO_HI(joyRY);
+ }
+ if (c & CAL_CENTRE) { // reset centre point of joystick
+ CENTRE(joyLX);
+ CENTRE(joyLY);
- CENTRE(joyRX);
- CENTRE(joyRY);
- }
+ CENTRE(joyRX);
+ CENTRE(joyRY);
+ }
}
//+============================================================================ ========================================
// bits that are common to both screens
//
-static void classic_show_(Canvas* const canvas, state_t* const state) {
- ecDecClassic_t* d = &state->ec.dec[state->ec.decN].classic;
- ecCalClassic_t* js = state->ec.calS.classic;
+static
+void classic_show_ (Canvas* const canvas, state_t* const state)
+{
+ ecDecClassic_t* d = &state->ec.dec[state->ec.decN].classic;
+ ecCalClassic_t* js = state->ec.calS.classic;
- static const int dead = 1; // trigger deadzone
- const image_t* img = NULL; // trigger image
+ static const int dead = 1; // trigger deadzone
+ const image_t* img = NULL; // trigger image
- show(canvas, 6, 0, &img_cc_Main, SHOW_SET_BLK);
- show(canvas, 62, 53, &img_cc_Cable, SHOW_SET_BLK);
+ show(canvas, 6, 0, &img_cc_Main , SHOW_SET_BLK);
+ show(canvas, 62,53, &img_cc_Cable, SHOW_SET_BLK);
- // classic triggers
- if(d->trgZL >= js[2].trgZL)
- img = &img_cc_trg_L4;
- else if(d->trgZL <= js[1].trgZL + dead)
- img = NULL;
- else {
- // copied from the joystick calibration code
- int lo = js[1].trgZL + dead + 1;
- int hi = js[2].trgZL - 1;
- int range = hi - lo + 1;
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
- int hi1 = lo + div - 1; // (in brevity)
- int lo3 = lo + div + div + (rem == 2); // ...
+ // classic triggers
+ if (d->trgZL >= js[2].trgZL ) img = &img_cc_trg_L4;
+ else if (d->trgZL <= js[1].trgZL +dead) img = NULL;
+ else {
+ // copied from the joystick calibration code
+ int lo = js[1].trgZL +dead +1;
+ int hi = js[2].trgZL -1;
+ int range = hi -lo +1;
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
+ int hi1 = lo +div -1; // (in brevity)
+ int lo3 = lo +div +div +(rem==2); // ...
- if(d->trgZL <= hi1)
- img = &img_cc_trg_L1; // zone #1
- else if(d->trgZL >= lo3)
- img = &img_cc_trg_L3; // zone #3
- else
- img = &img_cc_trg_L2; // zone #2
- }
- if(img) show(canvas, 22, 1, img, SHOW_SET_BLK);
+ if (d->trgZL <= hi1) img = &img_cc_trg_L1 ; // zone #1
+ else if (d->trgZL >= lo3) img = &img_cc_trg_L3 ; // zone #3
+ else img = &img_cc_trg_L2 ; // zone #2
+ }
+ if (img) show(canvas, 22,1, img, SHOW_SET_BLK) ;
- if(d->trgZR >= js[2].trgZR)
- img = &img_cc_trg_R4;
- else if(d->trgZR <= js[1].trgZR + dead)
- img = NULL;
- else {
- // copied from the joystick calibration code
- int lo = js[1].trgZR + dead + 1;
- int hi = js[2].trgZR - 1;
- int range = hi - lo + 1;
- int div = range / 3; // each division (base amount, eg. 17/3==5)
- int rem = range - (div * 3); // remainder (ie. range%3)
- int hi1 = lo + div - 1; // (in brevity)
- int lo3 = lo + div + div + (rem == 2); // ...
+ if (d->trgZR >= js[2].trgZR ) img = &img_cc_trg_R4;
+ else if (d->trgZR <= js[1].trgZR +dead) img = NULL;
+ else {
+ // copied from the joystick calibration code
+ int lo = js[1].trgZR +dead +1;
+ int hi = js[2].trgZR -1;
+ int range = hi -lo +1;
+ int div = range /3; // each division (base amount, eg. 17/3==5)
+ int rem = range -(div *3); // remainder (ie. range%3)
+ int hi1 = lo +div -1; // (in brevity)
+ int lo3 = lo +div +div +(rem==2); // ...
- if(d->trgZR <= hi1)
- img = &img_cc_trg_R1; // zone #1
- else if(d->trgZR >= lo3)
- img = &img_cc_trg_R3; // zone #3
- else
- img = &img_cc_trg_R2; // zone #2
- }
- if(img) show(canvas, 89, 1, img, SHOW_SET_BLK);
+ if (d->trgZR <= hi1) img = &img_cc_trg_R1 ; // zone #1
+ else if (d->trgZR >= lo3) img = &img_cc_trg_R3 ; // zone #3
+ else img = &img_cc_trg_R2 ; // zone #2
+ }
+ if (img) show(canvas, 89,1, img, SHOW_SET_BLK) ;
- if(d->padU) show(canvas, 27, 16, &img_cc_pad_UD1, SHOW_ALL);
- if(d->padL) show(canvas, 20, 23, &img_cc_pad_LR1, SHOW_ALL);
- if(d->padD) show(canvas, 27, 28, &img_cc_pad_UD1, SHOW_ALL);
- if(d->padR) show(canvas, 32, 23, &img_cc_pad_LR1, SHOW_ALL);
+ if (d->padU ) show(canvas, 27,16, &img_cc_pad_UD1, SHOW_ALL) ;
+ if (d->padL ) show(canvas, 20,23, &img_cc_pad_LR1, SHOW_ALL) ;
+ if (d->padD ) show(canvas, 27,28, &img_cc_pad_UD1, SHOW_ALL) ;
+ if (d->padR ) show(canvas, 32,23, &img_cc_pad_LR1, SHOW_ALL) ;
- if(d->btnX) show(canvas, 96, 16, &img_cc_btn_X1, SHOW_ALL);
- if(d->btnY) show(canvas, 85, 23, &img_cc_btn_Y1, SHOW_ALL);
- if(d->btnA) show(canvas, 107, 23, &img_cc_btn_A1, SHOW_ALL);
- if(d->btnB) show(canvas, 96, 30, &img_cc_btn_B1, SHOW_ALL);
+ if (d->btnX ) show(canvas, 96,16, &img_cc_btn_X1, SHOW_ALL) ;
+ if (d->btnY ) show(canvas, 85,23, &img_cc_btn_Y1, SHOW_ALL) ;
+ if (d->btnA ) show(canvas, 107,23, &img_cc_btn_A1, SHOW_ALL) ;
+ if (d->btnB ) show(canvas, 96,30, &img_cc_btn_B1, SHOW_ALL) ;
- canvas_set_color(canvas, ColorBlack);
- if(d->btnL) canvas_draw_box(canvas, 46, 2, 5, 4);
- if(d->btnR) canvas_draw_box(canvas, 77, 2, 5, 4);
+ canvas_set_color(canvas, ColorBlack);
+ if (d->btnL ) canvas_draw_box(canvas, 46,2, 5,4) ;
+ if (d->btnR ) canvas_draw_box(canvas, 77,2, 5,4) ;
- if(d->btnM) canvas_draw_box(canvas, 54, 24, 4, 4);
- if(d->btnH) canvas_draw_box(canvas, 62, 24, 4, 4);
- if(d->btnP) canvas_draw_box(canvas, 70, 24, 4, 4);
+ if (d->btnM ) canvas_draw_box(canvas, 54,24, 4,4) ;
+ if (d->btnH ) canvas_draw_box(canvas, 62,24, 4,4) ;
+ if (d->btnP ) canvas_draw_box(canvas, 70,24, 4,4) ;
- // Show joysticks
- showJoy(
- canvas,
- 48,
- 42,
- js[1].joyLX,
- js[2].joyLX,
- js[3].joyLX,
- js[1].joyLY,
- js[2].joyLY,
- js[3].joyLY,
- d->joyLX,
- d->joyLY,
- 6);
- showJoy(
- canvas,
- 78,
- 42,
- js[1].joyRX,
- js[2].joyRX,
- js[3].joyRX,
- js[1].joyRY,
- js[2].joyRY,
- js[3].joyRY,
- d->joyRX,
- d->joyRY,
- 5);
+ // Show joysticks
+ showJoy(canvas, 48,42, js[1].joyLX,js[2].joyLX, js[3].joyLX,
+ js[1].joyLY,js[2].joyLY, js[3].joyLY, d->joyLX,d->joyLY, 6);
+ showJoy(canvas, 78,42, js[1].joyRX,js[2].joyRX, js[3].joyRX,
+ js[1].joyRY,js[2].joyRY, js[3].joyRY, d->joyRX,d->joyRY, 5);
- show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK);
+ show(canvas, 0,55, &img_key_L, SHOW_SET_BLK);
}
//+============================================================================ ========================================
-static void classic_showN(Canvas* const canvas, state_t* const state) {
- ecCalClassic_t* c = (state->hold) ?
- &state->ec.calS.classic[(state->hold < 0) ? 0 : 4] :
- (ecCalClassic_t*)(&state->ec.dec[state->ec.decN].classic); //! danger
+static
+void classic_showN (Canvas* const canvas, state_t* const state)
+{
+ ecCalClassic_t* c = (state->hold) ? &state->ec.calS.classic[(state->hold < 0) ? 0 : 4]
+ : (ecCalClassic_t*)(&state->ec.dec[state->ec.decN].classic) ; //! danger
- classic_show_(canvas, state);
+ classic_show_(canvas, state);
- showHex(canvas, 0, 0, c->trgZL, 2, 1); // 5bits
- showHex(canvas, 113, 0, c->trgZR, 2, 1); // 5bits
+ showHex(canvas, 0, 0, c->trgZL, 2,1); // 5bits
+ showHex(canvas, 113, 0, c->trgZR, 2,1); // 5bits
- showHex(canvas, 24, 41, c->joyLX, 2, 1); // 6bits
- showHex(canvas, 41, 54, c->joyLY, 2, 1); // 6bits
+ showHex(canvas, 24,41, c->joyLX, 2,1); // 6bits
+ showHex(canvas, 41,54, c->joyLY, 2,1); // 6bits
- showHex(canvas, 88, 41, c->joyRX, 2, 1); // 5bits
- showHex(canvas, 71, 54, c->joyRY, 2, 1); // 5bits
+ showHex(canvas, 88,41, c->joyRX, 2,1); // 5bits
+ showHex(canvas, 71,54, c->joyRY, 2,1); // 5bits
- showPeakHold(state, canvas, state->hold); // peak keys
+ showPeakHold(state, canvas, state->hold); // peak keys
}
//+============================================================================ ========================================
-void classic_show(Canvas* const canvas, state_t* const state) {
- // Classic controllers have TWO scenes
- if(state->scene == SCENE_CLASSIC_N) return classic_showN(canvas, state);
+void classic_show (Canvas* const canvas, state_t* const state)
+{
+ // Classic controllers have TWO scenes
+ if (state->scene == SCENE_CLASSIC_N) return classic_showN(canvas, state) ;
- // Default scene
- classic_show_(canvas, state);
- show(canvas, 9, 55, &img_key_R, SHOW_SET_BLK);
+ // Default scene
+ classic_show_(canvas, state);
+ show(canvas, 9,55, &img_key_R, SHOW_SET_BLK);
- show(
- canvas,
- 119,
- 55,
- ((state->calib & CAL_RANGE) && (++state->flash & 8)) ? &img_key_OKi : &img_key_OK,
- SHOW_SET_BLK);
+ show( canvas, 119,55,
+ ((state->calib & CAL_RANGE) && (++state->flash &8)) ? &img_key_OKi : &img_key_OK,
+ SHOW_SET_BLK );
}
//+============================================================================ ========================================
-static bool classic_keyN(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+static
+bool classic_keyN (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- if((msg->input.type == InputTypeShort) && (msg->input.key == InputKeyLeft)) {
- sceneSet(state, SCENE_CLASSIC);
- used = true;
- }
+ if ((msg->input.type == InputTypeShort) && (msg->input.key == InputKeyLeft)) {
+ sceneSet(state, SCENE_CLASSIC);
+ used = true;
+ }
- // Calibration keys
- if(!used) used = key_calib(msg, state);
+ // Calibration keys
+ if (!used) used = key_calib(msg, state) ;
- return used;
+ return used;
}
//+============================================================================ ========================================
-bool classic_key(const eventMsg_t* const msg, state_t* const state) {
- // Classic controllers have TWO scenes
- if(state->scene == SCENE_CLASSIC_N) return classic_keyN(msg, state);
+bool classic_key (const eventMsg_t* const msg, state_t* const state)
+{
+ // Classic controllers have TWO scenes
+ if (state->scene == SCENE_CLASSIC_N) return classic_keyN(msg, state) ;
- // Default scene
- int used = false; // assume key is NOT-handled
+ // Default scene
+ int used = false; // assume key is NOT-handled
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyUp: //# input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyUp: //#
-#include
+#include
+#include
//----------------------------------------------------------------------------- ----------------------------------------
// Classic Controller ... Classic Controller Pro is electronically the same
@@ -25,55 +25,60 @@
//----------------------------------------------------------------------------- ----------------------------------------
// Controllers which have calibration must have their calibratable controls here
//! Is there a better way to get the start of the decode struct to match the calibration struct ?
-#define CLASSIC_ANALOGUE \
- uint8_t trgZL, trgZR; /* ANA{l, l} lowercase=trigger 5bit values {5} */ \
- uint8_t joyLX, joyLY; /* ANA{x, y} left=lowercase 6bit values {6}<-- */ \
- uint8_t joyRX, joyRY; /* ANA{X, Y} 5bit values {5} */
+#define CLASSIC_ANALOGUE \
+ uint8_t trgZL, trgZR; /* ANA{l, l} lowercase=trigger 5bit values {5} */ \
+ uint8_t joyLX, joyLY; /* ANA{x, y} left=lowercase 6bit values {6}<-- */ \
+ uint8_t joyRX, joyRY; /* ANA{X, Y} 5bit values {5} */
//-----------------------------------------------------------------------------
// Calibratable controls
//
-typedef struct ecCalClassic {
- CLASSIC_ANALOGUE
-} ecCalClassic_t;
+typedef
+ struct ecCalClassic
+ {
+ CLASSIC_ANALOGUE
+ }
+ecCalClassic_t;
//-----------------------------------------------------------------------------
// All controls
//
-typedef struct ecDecClassic {
- CLASSIC_ANALOGUE // MUST be first
+typedef
+ struct ecDecClassic
+ {
+ CLASSIC_ANALOGUE // MUST be first
- // Digital controls
- bool btnZL,
- btnZR; // BTN{l, l}
+ // Digital controls
+ bool btnZL, btnZR; // BTN{l, l}
- bool btnL, btnR; // BTN{L, R} upperrcase=shoulder
+ bool btnL, btnR; // BTN{L, R} upperrcase=shoulder
- bool padU, padL, padD, padR; // BTN{W, A, S, D}
+ bool padU, padL, padD, padR; // BTN{W, A, S, D}
- bool btnM, btnH, btnP; // BTN{-, h, +}
+ bool btnM, btnH, btnP; // BTN{-, h, +}
- bool btnX, btnY; // BTN{x, y}
- bool btnA, btnB; // BTN{a, b}
+ bool btnX, btnY; // BTN{x, y}
+ bool btnA, btnB; // BTN{a, b}
-} ecDecClassic_t;
+ }
+ecDecClassic_t;
#undef CLASSIC_ANALOGUE
//============================================================================= ========================================
// Function prototypes
//
-#include // Canvas
-typedef struct wiiEC wiiEC_t;
-typedef enum ecCalib ecCalib_t;
-typedef struct state state_t;
-typedef struct eventMsg eventMsg_t;
+#include // Canvas
+typedef struct wiiEC wiiEC_t ;
+typedef enum ecCalib ecCalib_t ;
+typedef struct state state_t ;
+typedef struct eventMsg eventMsg_t ;
-void classic_decode(wiiEC_t* const pec);
-void classic_msg(wiiEC_t* const pec, FuriMessageQueue* const queue);
-void classic_calib(wiiEC_t* const pec, ecCalib_t c);
+void classic_decode (wiiEC_t* const pec) ;
+void classic_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) ;
+void classic_calib (wiiEC_t* const pec, ecCalib_t c) ;
-void classic_show(Canvas* const canvas, state_t* const state);
-bool classic_key(const eventMsg_t* const msg, state_t* const state);
+void classic_show (Canvas* const canvas, state_t* const state) ;
+bool classic_key (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_EC_CLASSIC_H_
diff --git a/applications/plugins/wii_ec_anal/wii_ec_macros.h b/applications/plugins/wii_ec_anal/wii_ec_macros.h
index 00ab9825b..33daf944d 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_macros.h
+++ b/applications/plugins/wii_ec_anal/wii_ec_macros.h
@@ -9,53 +9,49 @@
//
//if (furi_message_queue_get_count(queue) > 18) WARN("queue high %d", furi_message_queue_get_count(queue));
-#define MSGQ(lbl) \
- do { \
- msg.wiiEc.in = lbl; \
- furi_message_queue_put(queue, &msg, 0); \
- } while(0)
+#define MSGQ(lbl) do { \
+ msg.wiiEc.in = lbl; \
+ furi_message_queue_put(queue, &msg, 0); \
+}while(0)
+
// A 'standard' "button" is an independent SPST switch
// Eg. Nunchuck 'Z' button
// The "value" will always be 0
-#define BUTTON(btn, lbl) \
- do { \
- if(new->btn != old->btn) { \
- msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \
- msg.wiiEc.val = 0; \
- MSGQ(lbl); \
- } \
- } while(0)
+#define BUTTON(btn,lbl) do { \
+ if (new->btn != old->btn) { \
+ msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \
+ msg.wiiEc.val = 0; \
+ MSGQ(lbl); \
+ } \
+}while(0)
// An "analogue button" is an SPST coupled with an ananlogue 'switch'
// Eg. The "bottom out" switches on the triggers of the classic controller
// The "value" will be the value of the associated analogue controller
-#define ANABTN(btn, ana, lbl) \
- do { \
- if(new->btn != old->btn) { \
- msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \
- msg.wiiEc.val = new->ana; \
- MSGQ(lbl); \
- } \
- } while(0)
+#define ANABTN(btn,ana,lbl) do { \
+ if (new->btn != old->btn) { \
+ msg.wiiEc.type = (new->btn) ? WIIEC_PRESS : WIIEC_RELEASE; \
+ msg.wiiEc.val = new->ana; \
+ MSGQ(lbl); \
+ } \
+}while(0)
-#define ANALOG(ana, lbl) \
- do { \
- if(new->ana != old->ana) { \
- msg.wiiEc.type = WIIEC_ANALOG; \
- msg.wiiEc.val = new->ana; \
- MSGQ(lbl); \
- } \
- } while(0)
+#define ANALOG(ana,lbl) do { \
+ if (new->ana != old->ana) { \
+ msg.wiiEc.type = WIIEC_ANALOG; \
+ msg.wiiEc.val = new->ana; \
+ MSGQ(lbl); \
+ } \
+}while(0)
-#define ACCEL(acc, lbl) \
- do { \
- if(new->acc != old->acc) { \
- msg.wiiEc.type = WIIEC_ACCEL; \
- msg.wiiEc.val = new->acc; \
- MSGQ(lbl); \
- } \
- } while(0)
+#define ACCEL(acc,lbl) do { \
+ if (new->acc != old->acc) { \
+ msg.wiiEc.type = WIIEC_ACCEL; \
+ msg.wiiEc.val = new->acc; \
+ MSGQ(lbl); \
+ } \
+}while(0)
//----------------------------------------------------------------------------- ----------------------------------------
// CALIBRATION MACROS
@@ -65,74 +61,24 @@
//
// ... v=variable, n=number
//
-#define FACTORY_LO(v, n) \
- do { \
- (dst[1].v) = n; \
- } while(0)
-#define FACTORY_MID(v, n) \
- do { \
- (dst[2].v) = n; \
- } while(0)
-#define FACTORY_HI(v, n) \
- do { \
- (dst[3].v) = n; \
- } while(0)
+#define FACTORY_LO(v,n) do{ (dst[1]. v) = n; }while(0)
+#define FACTORY_MID(v,n) do{ (dst[2]. v) = n; }while(0)
+#define FACTORY_HI(v,n) do{ (dst[3]. v) = n; }while(0)
-#define TRACK_LO(v) \
- do { \
- if((src->v) < (dst[0].v)) (dst[0].v) = (src->v); \
- } while(0)
-#define TRACK_HI(v) \
- do { \
- if((src->v) > (dst[4].v)) (dst[4].v) = (src->v); \
- } while(0)
-#define TRACK_LO_HI(v) \
- do { \
- TRACK_LO(v); \
- TRACK_HI(v); \
- } while(0)
+#define TRACK_LO(v) do{ if ((src-> v) < (dst[0]. v)) (dst[0]. v) = (src-> v); }while(0)
+#define TRACK_HI(v) do{ if ((src-> v) > (dst[4]. v)) (dst[4]. v) = (src-> v); }while(0)
+#define TRACK_LO_HI(v) do{ TRACK_LO(v); TRACK_HI(v); }while(0)
-#define RESET_LO(v, b) \
- do { \
- (dst[0].v) = (dst[1].v) = ((1 << (b)) - 1); \
- } while(0)
-#define RESET_HI(v) \
- do { \
- (dst[4].v) = (dst[3].v) = 0; \
- } while(0)
-#define RESET_MID(v) \
- do { \
- (dst[2].v) = (src->v); \
- } while(0)
-#define RESET_LO_HI(v, b) \
- do { \
- RESET_LO(v, b); \
- RESET_HI(v); \
- } while(0)
-#define RESET_LO_MID_HI(v, b) \
- do { \
- RESET_LO(v, b); \
- RESET_MID(v); \
- RESET_HI(v); \
- } while(0)
+#define RESET_LO(v,b) do{ (dst[0]. v) = (dst[1]. v) = ((1<<(b))-1); }while(0)
+#define RESET_HI(v) do{ (dst[4]. v) = (dst[3]. v) = 0; }while(0)
+#define RESET_MID(v) do{ (dst[2]. v) = (src-> v); }while(0)
+#define RESET_LO_HI(v,b) do{ RESET_LO(v,b); RESET_HI(v); }while(0)
+#define RESET_LO_MID_HI(v,b) do{ RESET_LO(v,b); RESET_MID(v); RESET_HI(v); }while(0)
-#define RANGE_LO(v) \
- do { \
- if((src->v) < (dst[1].v)) (dst[1].v) = (src->v); \
- } while(0)
-#define RANGE_HI(v) \
- do { \
- if((src->v) > (dst[3].v)) (dst[3].v) = (src->v); \
- } while(0)
-#define RANGE_LO_HI(v) \
- do { \
- RANGE_LO(v); \
- RANGE_HI(v); \
- } while(0)
+#define RANGE_LO(v) do{ if ((src-> v) < (dst[1]. v)) (dst[1]. v) = (src-> v); }while(0)
+#define RANGE_HI(v) do{ if ((src-> v) > (dst[3]. v)) (dst[3]. v) = (src-> v); }while(0)
+#define RANGE_LO_HI(v) do{ RANGE_LO(v); RANGE_HI(v); }while(0)
-#define CENTRE(v) \
- do { \
- (dst[2].v) = (src->v); \
- } while(0)
+#define CENTRE(v) do{ (dst[2]. v) = (src-> v); } while(0)
#endif //WII_EC_MACROS_H_
diff --git a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c
index d88d535b6..81c32a243 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c
+++ b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.c
@@ -1,144 +1,142 @@
-#include
-#include // Core API
+#include
+#include // Core API
-#include "wii_anal.h"
-#include "wii_i2c.h"
-#include "bc_logging.h"
+#include "wii_anal.h"
+#include "wii_i2c.h"
+#include "bc_logging.h"
-#include "gfx/images.h" // Images
-#include "wii_anal_lcd.h" // Drawing functions
-#include "wii_anal_keys.h" // key mappings
+#include "gfx/images.h" // Images
+#include "wii_anal_lcd.h" // Drawing functions
+#include "wii_anal_keys.h" // key mappings
// ** If you want to see what this source code looks like with all the MACROs expanded
// ** grep -v '#include ' wii_ec_nunchuck.c | gcc -E -o /dev/stdout -xc -
-#include "wii_ec_macros.h"
+# include "wii_ec_macros.h"
//+============================================================================ ========================================
// Standard Nunchuck : 2 buttons, 1 analogue joystick, 1 3-axis accelerometer
-//
-void nunchuck_decode(wiiEC_t* const pec) {
- ecDecNunchuck_t* p = &pec->dec[(pec->decN = !pec->decN)].nunchuck;
- uint8_t* joy = pec->joy;
+//
+void nunchuck_decode (wiiEC_t* const pec)
+{
+ ecDecNunchuck_t* p = &pec->dec[(pec->decN = !pec->decN)].nunchuck;
+ uint8_t* joy = pec->joy;
- p->btnC = !(joy[5] & 0x02); // !{1}
- p->btnZ = !(joy[5] & 0x01); // !{1}
+ p->btnC = !(joy[5] & 0x02); // !{1}
+ p->btnZ = !(joy[5] & 0x01); // !{1}
- p->joyX = joy[0]; // {8}
- p->joyY = joy[1]; // {8}
+ p->joyX = joy[0]; // {8}
+ p->joyY = joy[1]; // {8}
- p->accX = ((uint16_t)joy[2] << 2) | ((joy[5] >> 2) & 0x03); // {10}
- p->accY = ((uint16_t)joy[3] << 2) | ((joy[5] >> 4) & 0x03); // {10}
- p->accZ = ((uint16_t)joy[4] << 2) | ((joy[5] >> 6) & 0x03); // {10}
+ p->accX = ((uint16_t)joy[2] << 2) | ((joy[5] >>2) & 0x03); // {10}
+ p->accY = ((uint16_t)joy[3] << 2) | ((joy[5] >>4) & 0x03); // {10}
+ p->accZ = ((uint16_t)joy[4] << 2) | ((joy[5] >>6) & 0x03); // {10}
- DEBUG(
- ">%d> C:%c, Z:%c, Joy{x:%02X, y:%02X}, Acc{x:%03X, y:%03X, z:%03X}",
- pec->decN,
- (p->btnC ? '#' : '.'),
- (p->btnZ ? '#' : '.'),
- p->joyX,
- p->joyY,
- p->accX,
- p->accY,
- p->accZ);
+ DEBUG(">%d> C:%c, Z:%c, Joy{x:%02X, y:%02X}, Acc{x:%03X, y:%03X, z:%03X}", pec->decN,
+ (p->btnC ? '#' : '.'), (p->btnZ ? '#' : '.'),
+ p->joyX, p->joyY, p->accX, p->accY, p->accZ
+ );
}
//+============================================================================ ========================================
// Give each button a unique character identifier
//
-void nunchuck_msg(wiiEC_t* const pec, FuriMessageQueue* const queue) {
- ecDecNunchuck_t* new = &pec->dec[pec->decN].nunchuck;
- ecDecNunchuck_t* old = &pec->dec[!pec->decN].nunchuck;
+void nunchuck_msg (wiiEC_t* const pec, FuriMessageQueue* const queue)
+{
+ ecDecNunchuck_t* new = &pec->dec[pec->decN].nunchuck;
+ ecDecNunchuck_t* old = &pec->dec[!pec->decN].nunchuck;
- eventMsg_t msg = {
- .id = EVID_WIIEC,
- .wiiEc = {
- .type = WIIEC_NONE,
- .in = ' ',
- .val = 0,
- }};
+ eventMsg_t msg = {
+ .id = EVID_WIIEC,
+ .wiiEc = {
+ .type = WIIEC_NONE,
+ .in = ' ',
+ .val = 0,
+ }
+ };
- BUTTON(btnC, 'c');
- BUTTON(btnZ, 'z');
+ BUTTON(btnC, 'c');
+ BUTTON(btnZ, 'z');
- ANALOG(joyX, 'x');
- ANALOG(joyY, 'y');
+ ANALOG(joyX, 'x');
+ ANALOG(joyY, 'y');
- ACCEL(accX, 'x');
- ACCEL(accY, 'y');
- ACCEL(accZ, 'z');
+ ACCEL(accX, 'x');
+ ACCEL(accY, 'y');
+ ACCEL(accZ, 'z');
}
//+============================================================================ ========================================
// https://www.hackster.io/infusion/using-a-wii-nunchuk-with-arduino-597254#toc-5--read-actual-calibration-data-from-the-device-14
//
-void nunchuck_calib(wiiEC_t* const pec, ecCalib_t c) {
- ecDecNunchuck_t* src = &pec->dec[pec->decN].nunchuck; // from input
- ecCalNunchuck_t* dst = pec->calS.nunchuck; // to calibration data
+void nunchuck_calib (wiiEC_t* const pec, ecCalib_t c)
+{
+ ecDecNunchuck_t* src = &pec->dec[pec->decN].nunchuck; // from input
+ ecCalNunchuck_t* dst = pec->calS.nunchuck; // to calibration data
- if(c & CAL_RESET) { // initialise ready for software calibration
- // LO is set to the MAXIMUM value (so it can be reduced)
- // HI is set to ZERO (so it can be increased)
- RESET_LO_HI(accX, 10); // 10bit value
- RESET_LO_HI(accY, 10); // 10bit value
- RESET_LO_HI(accZ, 10); // 10bit value
+ if (c & CAL_RESET) { // initialise ready for software calibration
+ // LO is set to the MAXIMUM value (so it can be reduced)
+ // HI is set to ZERO (so it can be increased)
+ RESET_LO_HI(accX, 10); // 10bit value
+ RESET_LO_HI(accY, 10); // 10bit value
+ RESET_LO_HI(accZ, 10); // 10bit value
- RESET_LO_HI(joyX, 8); // 8bit value
- RESET_LO_HI(joyY, 8); // 8bit value
- }
- if(c & CAL_FACTORY) { // (re)set to factory defaults
- //! "[4] LSB of Zero value of X,Y,Z axes" ...helpful!
- //! ...Well, my test nunchuck has bits set in the bottom 6 bits, so let's guess ;)
+ RESET_LO_HI(joyX, 8); // 8bit value
+ RESET_LO_HI(joyY, 8); // 8bit value
+ }
+ if (c & CAL_FACTORY) { // (re)set to factory defaults
+ //! "[4] LSB of Zero value of X,Y,Z axes" ...helpful!
+ //! ...Well, my test nunchuck has bits set in the bottom 6 bits, so let's guess ;)
- // No value available - annecdotal tests suggest 8 is reasonable
- FACTORY_LO(accX, 8);
- FACTORY_LO(accY, 8);
- FACTORY_LO(accZ, 8);
+ // No value available - annecdotal tests suggest 8 is reasonable
+ FACTORY_LO( accX, 8);
+ FACTORY_LO( accY, 8);
+ FACTORY_LO( accZ, 8);
- // @ 0G
- FACTORY_MID(accX, ((pec->calF[0] << 2) | ((pec->calF[3] >> 4) & 0x3)));
- FACTORY_MID(accY, ((pec->calF[1] << 2) | ((pec->calF[3] >> 2) & 0x3)));
- FACTORY_MID(accZ, ((pec->calF[2] << 2) | ((pec->calF[3]) & 0x3)));
+ // @ 0G
+ FACTORY_MID( accX, ((pec->calF[0] <<2) | ((pec->calF[3] >>4) &0x3)) ) ;
+ FACTORY_MID( accY, ((pec->calF[1] <<2) | ((pec->calF[3] >>2) &0x3)) ) ;
+ FACTORY_MID( accZ, ((pec->calF[2] <<2) | ((pec->calF[3] ) &0x3)) ) ;
- // @ 1G
- FACTORY_HI(accX, ((pec->calF[4] << 2) | ((pec->calF[7] >> 4) & 0x3)));
- FACTORY_HI(accY, ((pec->calF[5] << 2) | ((pec->calF[7] >> 2) & 0x3)));
- FACTORY_HI(accZ, ((pec->calF[6] << 2) | ((pec->calF[7]) & 0x3)));
+ // @ 1G
+ FACTORY_HI( accX, ((pec->calF[4] <<2) | ((pec->calF[7] >>4) &0x3)) ) ;
+ FACTORY_HI( accY, ((pec->calF[5] <<2) | ((pec->calF[7] >>2) &0x3)) ) ;
+ FACTORY_HI( accZ, ((pec->calF[6] <<2) | ((pec->calF[7] ) &0x3)) ) ;
- // Joysticks
- FACTORY_LO(joyX, pec->calF[9]);
- FACTORY_MID(joyX, pec->calF[10]);
- FACTORY_HI(joyX, pec->calF[8]);
+ // Joysticks
+ FACTORY_LO( joyX, pec->calF[ 9] ) ;
+ FACTORY_MID(joyX, pec->calF[10] ) ;
+ FACTORY_HI( joyX, pec->calF[ 8] ) ;
- FACTORY_LO(joyY, pec->calF[12]);
- FACTORY_MID(joyY, pec->calF[13]);
- FACTORY_HI(joyY, pec->calF[11]);
- }
- if(c & CAL_TRACK) { // track maximum and minimum values seen
- TRACK_LO_HI(accX);
- TRACK_LO_HI(accY);
- TRACK_LO_HI(accZ);
+ FACTORY_LO( joyY, pec->calF[12] ) ;
+ FACTORY_MID(joyY, pec->calF[13] ) ;
+ FACTORY_HI( joyY, pec->calF[11] ) ;
+ }
+ if (c & CAL_TRACK) { // track maximum and minimum values seen
+ TRACK_LO_HI(accX);
+ TRACK_LO_HI(accY);
+ TRACK_LO_HI(accZ);
- TRACK_LO_HI(joyX);
- TRACK_LO_HI(joyY);
- }
- if(c & CAL_RANGE) { // perform software calibration step
- RANGE_LO_HI(accX);
- RANGE_LO_HI(accY);
- RANGE_LO_HI(accZ);
+ TRACK_LO_HI(joyX);
+ TRACK_LO_HI(joyY);
+ }
+ if (c & CAL_RANGE) { // perform software calibration step
+ RANGE_LO_HI(accX);
+ RANGE_LO_HI(accY);
+ RANGE_LO_HI(accZ);
- if(!(c & CAL_NOTJOY)) { // double negative!
- RANGE_LO_HI(joyX);
- RANGE_LO_HI(joyY);
- }
- }
- if(c & CAL_CENTRE) { // reset centre point of joystick
- CENTRE(accX);
- CENTRE(accY);
- CENTRE(accZ);
+ if (!(c & CAL_NOTJOY)) { // double negative!
+ RANGE_LO_HI(joyX);
+ RANGE_LO_HI(joyY);
+ }
+ }
+ if (c & CAL_CENTRE) { // reset centre point of joystick
+ CENTRE(accX);
+ CENTRE(accY);
+ CENTRE(accZ);
- CENTRE(joyX);
- CENTRE(joyY);
- }
+ CENTRE(joyX);
+ CENTRE(joyY);
+ }
}
//============================================================================= ========================================
@@ -154,323 +152,308 @@ void nunchuck_calib(wiiEC_t* const pec, ecCalib_t c) {
//
// EG. Move left will effect X ; turn left will effect Y & Z
//
-#define aw 110 // axis width
-#define ah 15 // height {0......7......14}
-#define am 7 // midpoint { 7 }
-#define ar 7 // range {1234567 1234567}
+#define aw 110 // axis width
+#define ah 15 // height {0......7......14}
+#define am 7 // midpoint { 7 }
+#define ar 7 // range {1234567 1234567}
enum {
- ACC_X = 0,
- ACC_Y = 1,
- ACC_Z = 2,
- ACC_CNT = 3,
- ACC_1 = ACC_X, // first
- ACC_N = ACC_Z, // last
+ ACC_X = 0,
+ ACC_Y = 1,
+ ACC_Z = 2,
+ ACC_CNT = 3,
+ ACC_1 = ACC_X, // first
+ ACC_N = ACC_Z, // last
};
//+============================================================================
-static void nunchuck_showAcc(Canvas* const canvas, state_t* const state) {
- ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck;
- ecCalNunchuck_t* lo = &state->ec.calS.nunchuck[1];
- ecCalNunchuck_t* mid = &state->ec.calS.nunchuck[2];
- ecCalNunchuck_t* hi = &state->ec.calS.nunchuck[3];
+static
+void nunchuck_showAcc (Canvas* const canvas, state_t* const state)
+{
+ ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck;
+ ecCalNunchuck_t* lo = &state->ec.calS.nunchuck[1];
+ ecCalNunchuck_t* mid = &state->ec.calS.nunchuck[2];
+ ecCalNunchuck_t* hi = &state->ec.calS.nunchuck[3];
- int y[ACC_CNT] = {0, 0 + (ah + 4), 0 + ((ah + 4) * 2)};
- int x = 10;
+ int y[ACC_CNT] = {0, 0+(ah+4), 0+((ah+4)*2)};
+ int x = 10;
- static uint16_t v[ACC_CNT][aw] = {0};
- // static uint16_t tv[ACC_CNT][aw] = {0};
+ static uint16_t v[ACC_CNT][aw] = {0};
+// static uint16_t tv[ACC_CNT][aw] = {0};
- static uint16_t idx = 0;
- static uint16_t cnt = aw - 1;
+ static uint16_t idx = 0;
+ static uint16_t cnt = aw -1;
- // Only record when scanner NOT-paused
- if(!state->pause) {
- uint16_t dead = (1 << 5);
+ // Only record when scanner NOT-paused
+ if (!state->pause) {
+ uint16_t dead = (1<<5);
- // Find axes y-offsets
- for(int a = ACC_1; a <= ACC_N; a++) {
- uint16_t* dp = NULL; // data value (current reading)
- uint16_t* lp = NULL; // lo value
- uint16_t* mp = NULL; // mid value
- uint16_t* hp = NULL; // hi value
- uint16_t* vp = NULL; // value (result)
+ // Find axes y-offsets
+ for (int a = ACC_1; a <= ACC_N; a++) {
+ uint16_t* dp = NULL; // data value (current reading)
+ uint16_t* lp = NULL; // lo value
+ uint16_t* mp = NULL; // mid value
+ uint16_t* hp = NULL; // hi value
+ uint16_t* vp = NULL; // value (result)
- switch(a) {
- case ACC_X:
- dp = &d->accX; // data (input)
- lp = &lo->accX; // low \.
- mp = &mid->accX; // mid > calibration
- hp = &hi->accX; // high /
- vp = &v[ACC_X][idx]; // value (where to store the result)
- break;
- case ACC_Y:
- dp = &d->accY;
- lp = &lo->accY;
- mp = &mid->accY;
- hp = &hi->accY;
- vp = &v[ACC_Y][idx];
- break;
- case ACC_Z:
- dp = &d->accZ;
- lp = &lo->accZ;
- mp = &mid->accZ;
- hp = &hi->accZ;
- vp = &v[ACC_Z][idx];
- break;
- default:
- break;
- }
+ switch (a) {
+ case ACC_X:
+ dp = & d->accX; // data (input)
+ lp = & lo->accX; // low \.
+ mp = &mid->accX; // mid > calibration
+ hp = & hi->accX; // high /
+ vp = &v[ ACC_X][idx]; // value (where to store the result)
+ break;
+ case ACC_Y:
+ dp = & d->accY;
+ lp = & lo->accY;
+ mp = &mid->accY;
+ hp = & hi->accY;
+ vp = &v[ ACC_Y][idx];
+ break;
+ case ACC_Z:
+ dp = & d->accZ;
+ lp = & lo->accZ;
+ mp = &mid->accZ;
+ hp = & hi->accZ;
+ vp = &v[ ACC_Z][idx];
+ break;
+ default: break ;
+ }
- // Again - qv. the joysick calibration:
- // This is not the "right way" to do this, it is just "one way" to do it
- // ...mid point and extreme zones have a deadzone
- // ...the rest is evenly divided by the amount of space on the graph
- if((*dp >= (*mp - dead)) && (*dp <= (*mp + dead)))
- *vp = ar;
- else if(*dp >= (*hp - dead))
- *vp = ah - 1;
- else if(*dp <= (*lp + dead))
- *vp = 0;
- else if(*dp < *mp) {
- uint16_t min = ((*lp + dead) + 1);
- uint16_t max = ((*mp - dead) - 1);
- float range = (max - min) + 1;
- float m = range / (ar - 1); // 6 evenly(/fairly) divided zones
- *vp = ((int)((*dp - min) / m)) + 1;
+ // Again - qv. the joysick calibration:
+ // This is not the "right way" to do this, it is just "one way" to do it
+ // ...mid point and extreme zones have a deadzone
+ // ...the rest is evenly divided by the amount of space on the graph
+ if ((*dp >= (*mp -dead)) && (*dp <= (*mp +dead))) *vp = ar ;
+ else if (*dp >= (*hp -dead)) *vp = ah-1 ;
+ else if (*dp <= (*lp +dead)) *vp = 0 ;
+ else if (*dp < *mp) {
+ uint16_t min = ((*lp +dead) +1);
+ uint16_t max = ((*mp -dead) -1);
+ float range = (max -min) +1;
+ float m = range /(ar-1); // 6 evenly(/fairly) divided zones
+ *vp = ((int)((*dp -min) /m)) +1;
- } else { //if (*dp > *mp)
- uint16_t min = ((*mp + dead) + 1);
- uint16_t max = ((*hp - dead) - 1);
- float range = (max - min) + 1;
- float m = range / (ar - 1); // 6 evenly(/fairly) divided zones
- *vp = ((int)((*dp - min) / m)) + 1 + ar;
- }
- }
+ } else {//if (*dp > *mp)
+ uint16_t min = ((*mp +dead) +1);
+ uint16_t max = ((*hp -dead) -1);
+ float range = (max -min) +1;
+ float m = range /(ar-1); // 6 evenly(/fairly) divided zones
+ *vp = ((int)((*dp -min) /m)) +1 +ar;
+ }
+ }
- //! If we decide to offer "export to CSV"
- //! I suggest we keep a second array of true-values, rather than do all the maths every time
- //! Also - the data will need to me moved to the 'state' table - so a.n.other function can save it off
- // tv[ACC_X][idx] = d->accX;
- // tv[ACC_Y][idx] = d->accY;
- // tv[ACC_Z][idx] = d->accZ;
+//! If we decide to offer "export to CSV"
+//! I suggest we keep a second array of true-values, rather than do all the maths every time
+//! Also - the data will need to me moved to the 'state' table - so a.n.other function can save it off
+// tv[ACC_X][idx] = d->accX;
+// tv[ACC_Y][idx] = d->accY;
+// tv[ACC_Z][idx] = d->accZ;
- // Prepare for the next datapoint
- if(++idx >= aw) idx = 0;
- if(cnt) cnt--;
- }
+ // Prepare for the next datapoint
+ if (++idx >= aw) idx = 0 ;
+ if (cnt) cnt-- ;
+ }
- // Auto-pause
- if(state->apause && !idx) state->pause = true;
+ // Auto-pause
+ if (state->apause && !idx) state->pause = true ;
- // *** Draw axes ***
- show(canvas, 0, y[ACC_X] + ((ah - img_6x8_X.h) / 2), &img_6x8_X, SHOW_SET_BLK);
- show(canvas, 0, y[ACC_Y] + ((ah - img_6x8_Y.h) / 2), &img_6x8_Y, SHOW_SET_BLK);
- show(canvas, 0, y[ACC_Z] + ((ah - img_6x8_Z.h) / 2), &img_6x8_Z, SHOW_SET_BLK);
+ // *** Draw axes ***
+ show(canvas, 0,y[ACC_X] +((ah -img_6x8_X.h) /2), &img_6x8_X, SHOW_SET_BLK);
+ show(canvas, 0,y[ACC_Y] +((ah -img_6x8_Y.h) /2), &img_6x8_Y, SHOW_SET_BLK);
+ show(canvas, 0,y[ACC_Z] +((ah -img_6x8_Z.h) /2), &img_6x8_Z, SHOW_SET_BLK);
- canvas_set_color(canvas, ColorBlack);
- for(int a = ACC_1; a <= ACC_N; a++) {
- canvas_draw_line(canvas, x - 1, y[a], x - 1, y[a] + ah);
- canvas_draw_line(canvas, x, y[a] + ah, x + aw - 1, y[a] + ah);
+ canvas_set_color(canvas, ColorBlack);
+ for (int a = ACC_1; a <= ACC_N; a++) {
+ canvas_draw_line(canvas, x-1,y[a] , x -1,y[a]+ah);
+ canvas_draw_line(canvas, x ,y[a]+ah, x+aw-1,y[a]+ah);
- // Mid & Peak lines
- for(int i = 1; i < aw; i += 3) {
- canvas_draw_dot(canvas, x + i, y[a]);
- canvas_draw_dot(canvas, x + i, y[a] + (ah / 2));
- }
- }
+ // Mid & Peak lines
+ for (int i = 1; i < aw; i += 3) {
+ canvas_draw_dot(canvas, x+i,y[a]);
+ canvas_draw_dot(canvas, x+i,y[a] +(ah /2));
+ }
+ }
- // Data (wiper display - see notes.txt for scrolling algorithm)
- int end = idx ? idx : aw;
- for(int a = ACC_1; a <= ACC_N; a++) {
- canvas_draw_dot(canvas, x, y[a] + v[a][idx]);
- for(int i = 1; i < end; i++)
- canvas_draw_line(canvas, x + i, y[a] + v[a][i - 1], x + i, y[a] + v[a][i]);
- if(!state->apause)
- for(int i = end + 10; i < aw - cnt; i++)
- canvas_draw_line(canvas, x + i, y[a] + v[a][i - 1], x + i, y[a] + v[a][i]);
- }
- // Wipe bar
- if(end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1);
- if(++end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1);
- if(++end < aw) canvas_draw_line(canvas, x + end, y[0], x + end, y[2] + ah - 1);
+ // Data (wiper display - see notes.txt for scrolling algorithm)
+ int end = idx ? idx : aw;
+ for (int a = ACC_1; a <= ACC_N; a++) {
+ canvas_draw_dot(canvas, x,y[a]+v[a][idx]);
+ for (int i = 1; i < end; i++)
+ canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
+ if (!state->apause)
+ for (int i = end+10; i < aw -cnt; i++)
+ canvas_draw_line(canvas, x+i,y[a]+v[a][i-1] , x+i,y[a]+v[a][i]);
+ }
+ // Wipe bar
+ if (end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
+ if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
+ if (++end < aw) canvas_draw_line(canvas, x+end,y[0], x+end,y[2]+ah-1);
- // *** Mode buttons ***
- show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK); // mode key
+ // *** Mode buttons ***
+ show(canvas, 0,55, &img_key_L, SHOW_SET_BLK); // mode key
- if((state->calib & CAL_RANGE) || state->pause) state->flash++;
+ if ((state->calib & CAL_RANGE) || state->pause) state->flash++ ;
- // -pause- ...yeah, this got a little out of hand! LOL!
- if(state->pause || state->apause) {
- if(state->pause && state->apause && !idx) {
- if(state->flash & 8) {
- show(canvas, 108, 56, &img_key_U, SHOW_SET_BLK);
- } else {
- show(canvas, 108, 56, &img_key_Ui, SHOW_SET_BLK);
- canvas_draw_line(canvas, x + aw, y[0], x + aw, y[2] + ah - 1);
- }
- } else {
- show(canvas, 108, 56, &img_key_Ui, SHOW_SET_BLK);
- }
- } else {
- show(canvas, 108, 56, &img_key_U, SHOW_SET_BLK); // pause
- }
+ // -pause- ...yeah, this got a little out of hand! LOL!
+ if (state->pause || state->apause) {
+ if (state->pause && state->apause && !idx) {
+ if (state->flash &8) {
+ show(canvas, 108,56, &img_key_U, SHOW_SET_BLK);
+ } else {
+ show(canvas, 108,56, &img_key_Ui, SHOW_SET_BLK);
+ canvas_draw_line(canvas, x+aw,y[0], x+aw,y[2]+ah-1);
+ }
+ } else {
+ show(canvas, 108,56, &img_key_Ui, SHOW_SET_BLK);
+ }
+ } else {
+ show(canvas, 108,56, &img_key_U, SHOW_SET_BLK); // pause
+ }
- // -calibration-
- if(state->calib & CAL_RANGE) {
- show(canvas, 119, 55, (state->flash & 8) ? &img_key_OKi : &img_key_OK, SHOW_SET_BLK);
- } else {
- show(canvas, 119, 55, &img_key_OK, SHOW_SET_BLK);
- }
+ // -calibration-
+ if (state->calib & CAL_RANGE) {
+ show(canvas, 119,55, (state->flash &8) ? &img_key_OKi : &img_key_OK, SHOW_SET_BLK);
+ } else {
+ show(canvas, 119,55, &img_key_OK, SHOW_SET_BLK);
+ }
}
-#undef aw
-#undef ah
-#undef am
-#undef ar
+# undef aw
+# undef ah
+# undef am
+# undef ar
//+============================================================================ ========================================
// Default nunchuck screen
//
-void nunchuck_show(Canvas* const canvas, state_t* const state) {
- // Nunchucks have TWO scenes
- if(state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_showAcc(canvas, state);
+void nunchuck_show (Canvas* const canvas, state_t* const state)
+{
+ // Nunchucks have TWO scenes
+ if (state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_showAcc(canvas, state) ;
- // Default scene
- ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck;
- ecCalNunchuck_t* c = (state->hold) ? &state->ec.calS.nunchuck[(state->hold < 0) ? 0 : 4] :
- (ecCalNunchuck_t*)d; //! danger will robinson!
- ecCalNunchuck_t* js = state->ec.calS.nunchuck;
+ // Default scene
+ ecDecNunchuck_t* d = &state->ec.dec[state->ec.decN].nunchuck;
+ ecCalNunchuck_t* c = (state->hold) ? &state->ec.calS.nunchuck[(state->hold < 0) ? 0 : 4]
+ : (ecCalNunchuck_t*)d ; //! danger will robinson!
+ ecCalNunchuck_t* js = state->ec.calS.nunchuck;
- // X, Y, Z
- show(canvas, 42, 0, &img_6x8_X, SHOW_SET_BLK);
- show(canvas, 73, 0, &img_6x8_Y, SHOW_SET_BLK);
- show(canvas, 104, 0, &img_6x8_Z, SHOW_SET_BLK);
+ // X, Y, Z
+ show(canvas, 42,0, &img_6x8_X, SHOW_SET_BLK);
+ show(canvas, 73,0, &img_6x8_Y, SHOW_SET_BLK);
+ show(canvas, 104,0, &img_6x8_Z, SHOW_SET_BLK);
- canvas_draw_str_aligned(canvas, 0, 14, AlignLeft, AlignTop, "Accel");
- canvas_draw_str_aligned(canvas, 0, 28, AlignLeft, AlignTop, "Joy");
+ canvas_draw_str_aligned(canvas, 0,14, AlignLeft, AlignTop, "Accel");
+ canvas_draw_str_aligned(canvas, 0,28, AlignLeft, AlignTop, "Joy");
- // accel values
- showHex(canvas, 34, 12, c->accX, 3, 2);
- showHex(canvas, 65, 12, c->accY, 3, 2);
- showHex(canvas, 96, 12, c->accZ, 3, 2);
- // Joy values
- showHex(canvas, 38, 27, c->joyX, 2, 2);
- showHex(canvas, 69, 27, c->joyY, 2, 2);
+ // accel values
+ showHex(canvas, 34,12, c->accX, 3,2);
+ showHex(canvas, 65,12, c->accY, 3,2);
+ showHex(canvas, 96,12, c->accZ, 3,2);
+ // Joy values
+ showHex(canvas, 38,27, c->joyX, 2,2);
+ showHex(canvas, 69,27, c->joyY, 2,2);
- showJoy(
- canvas,
- 103,
- 32,
- js[1].joyX,
- js[2].joyX,
- js[3].joyX,
- js[1].joyY,
- js[2].joyY,
- js[3].joyY,
- d->joyX,
- d->joyY,
- 8);
+ showJoy(canvas, 103,32, js[1].joyX, js[2].joyX, js[3].joyX,
+ js[1].joyY, js[2].joyY, js[3].joyY, d->joyX,d->joyY, 8);
- // buttons
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str_aligned(canvas, 0, 44, AlignLeft, AlignTop, "Button");
+ // buttons
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_str_aligned(canvas, 0,44, AlignLeft, AlignTop, "Button");
- if(!d->btnC) {
- canvas_draw_rframe(canvas, 36, 42, 18, 12, 6);
- show(canvas, 42, 44, &img_6x8_C, SHOW_SET_BLK);
- } else {
- canvas_draw_rbox(canvas, 36, 42, 18, 12, 6);
- show(canvas, 42, 44, &img_6x8_C, SHOW_SET_WHT);
- canvas_set_color(canvas, ColorBlack);
- }
+ if (!d->btnC) {
+ canvas_draw_rframe(canvas, 36,42, 18,12, 6);
+ show(canvas, 42,44, &img_6x8_C, SHOW_SET_BLK);
+ } else {
+ canvas_draw_rbox(canvas, 36,42, 18,12, 6);
+ show(canvas, 42,44, &img_6x8_C, SHOW_SET_WHT);
+ canvas_set_color(canvas, ColorBlack);
+ }
- if(!d->btnZ) {
- canvas_draw_rframe(canvas, 64, 40, 24, 16, 2);
- show(canvas, 73, 44, &img_6x8_Z, SHOW_SET_BLK);
- } else {
- canvas_draw_rbox(canvas, 64, 40, 24, 16, 2);
- show(canvas, 73, 44, &img_6x8_Z, SHOW_SET_WHT);
- }
+ if (!d->btnZ) {
+ canvas_draw_rframe(canvas, 64,40, 24,16, 2);
+ show(canvas, 73,44, &img_6x8_Z, SHOW_SET_BLK);
+ } else {
+ canvas_draw_rbox(canvas, 64,40, 24,16, 2);
+ show(canvas, 73,44, &img_6x8_Z, SHOW_SET_WHT);
+ }
- // Navigation
- showPeakHold(state, canvas, state->hold); // peak keys
- show(canvas, 0, 55, &img_key_L, SHOW_SET_BLK); // mode keys
- show(canvas, 9, 55, &img_key_R, SHOW_SET_BLK);
+ // Navigation
+ showPeakHold(state, canvas, state->hold); // peak keys
+ show(canvas, 0,55, &img_key_L, SHOW_SET_BLK); // mode keys
+ show(canvas, 9,55, &img_key_R, SHOW_SET_BLK);
}
//+============================================================================ ========================================
-static bool nunchuck_keyAcc(const eventMsg_t* const msg, state_t* const state) {
- int used = false; // assume key is NOT-handled
+static
+bool nunchuck_keyAcc (const eventMsg_t* const msg, state_t* const state)
+{
+ int used = false; // assume key is NOT-handled
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyDown: //# input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyDown: //# pause)
- state->pause = false; // Paused? Restart
- else
- state->apause = !state->apause; // No? toggle auto-pause
- used = true;
- break;
+ case InputKeyUp: //# pause) state->pause = false ; // Paused? Restart
+ else state->apause = !state->apause ; // No? toggle auto-pause
+ used = true;
+ break;
- case InputKeyLeft: //# calib &= ~CAL_NOTJOY; // DO calibrate joystick in NUNCHUCK mode
- used = true;
- break;
+ case InputKeyLeft: //# calib &= ~CAL_NOTJOY; // DO calibrate joystick in NUNCHUCK mode
+ used = true;
+ break;
- default:
- break; //#
- }
- break;
+ default: break ; //#
+ }
+ break;
- default:
- break;
- }
+ default: break ;
+ }
- // Calibration keys
- if(!used) used = key_calib(msg, state);
+ // Calibration keys
+ if (!used) used = key_calib(msg, state) ;
- return used;
+ return used;
}
//+============================================================================ ========================================
-bool nunchuck_key(const eventMsg_t* const msg, state_t* const state) {
- // Nunchucks have TWO scenes
- if(state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_keyAcc(msg, state);
+bool nunchuck_key (const eventMsg_t* const msg, state_t* const state)
+{
+ // Nunchucks have TWO scenes
+ if (state->scene == SCENE_NUNCHUCK_ACC) return nunchuck_keyAcc(msg, state) ;
- // Default scene
- int used = false; // assume key is NOT-handled
+ // Default scene
+ int used = false; // assume key is NOT-handled
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyLeft: //# input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyLeft: //# calib |= CAL_NOTJOY; // do NOT calibrate joystick in _ACC mode
- used = true;
- break;
- default:
- break; //#
- }
- break;
+ case InputKeyRight: //# calib |= CAL_NOTJOY; // do NOT calibrate joystick in _ACC mode
+ used = true;
+ break;
+ default: break ; //#
+ }
+ break;
- default:
- break;
- }
+ default: break ;
+ }
- // Calibration keys
- if(!used) used = key_calib(msg, state);
+ // Calibration keys
+ if (!used) used = key_calib(msg, state) ;
- return used;
+ return used;
}
diff --git a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.h b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.h
index e202cc7f1..020ecd555 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_nunchuck.h
+++ b/applications/plugins/wii_ec_anal/wii_ec_nunchuck.h
@@ -1,50 +1,53 @@
-#ifndef WII_EC_NUNCHUCK_H_
-#define WII_EC_NUNCHUCK_H_
+#ifndef WII_EC_NUNCHUCK_H_
+#define WII_EC_NUNCHUCK_H_
-#include
-#include
+#include
+#include
//-----------------------------------------------------------------------------
// Controllers which have calibration must have their calibratable controls here
//! Is there a better way to get the start of the decode struct to match the calibration struct ?
#define NUNCHUCK_ANALOGUE \
- uint8_t joyX, joyY; \
- uint16_t accX, accY, accZ;
+ uint8_t joyX, joyY; \
+ uint16_t accX, accY, accZ;
//-----------------------------------------------------------------------------
// Calibratable controls
//
-typedef struct ecCalNunchuck {
- NUNCHUCK_ANALOGUE
-} ecCalNunchuck_t;
+typedef
+ struct ecCalNunchuck {
+ NUNCHUCK_ANALOGUE
+ }
+ecCalNunchuck_t;
//-----------------------------------------------------------------------------
// All controls
//
-typedef struct ecDecNunchuck {
- NUNCHUCK_ANALOGUE // MUST be first
+typedef
+ struct ecDecNunchuck {
+ NUNCHUCK_ANALOGUE // MUST be first
- // Digital controls
- bool btnC,
- btnZ; // BTN{c, z}
-} ecDecNunchuck_t;
+ // Digital controls
+ bool btnC, btnZ; // BTN{c, z}
+ }
+ecDecNunchuck_t;
#undef NUNCHUCK_ANALOGUE
//=============================================================================
// Function prototypes
//
-#include // Canvas
-typedef struct wiiEC wiiEC_t;
-typedef enum ecCalib ecCalib_t;
-typedef struct state state_t;
-typedef struct eventMsg eventMsg_t;
+#include // Canvas
+typedef struct wiiEC wiiEC_t ;
+typedef enum ecCalib ecCalib_t ;
+typedef struct state state_t ;
+typedef struct eventMsg eventMsg_t ;
-void nunchuck_decode(wiiEC_t* const pec);
-void nunchuck_msg(wiiEC_t* const pec, FuriMessageQueue* const queue);
-void nunchuck_calib(wiiEC_t* const pec, ecCalib_t c);
+void nunchuck_decode (wiiEC_t* const pec) ;
+void nunchuck_msg (wiiEC_t* const pec, FuriMessageQueue* const queue) ;
+void nunchuck_calib (wiiEC_t* const pec, ecCalib_t c) ;
-void nunchuck_show(Canvas* const canvas, state_t* const state);
-bool nunchuck_key(const eventMsg_t* const msg, state_t* const state);
+void nunchuck_show (Canvas* const canvas, state_t* const state) ;
+bool nunchuck_key (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_EC_NUNCHUCK_H_
diff --git a/applications/plugins/wii_ec_anal/wii_ec_udraw.c b/applications/plugins/wii_ec_anal/wii_ec_udraw.c
index 82987b205..babbc92ab 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_udraw.c
+++ b/applications/plugins/wii_ec_anal/wii_ec_udraw.c
@@ -1,16 +1,16 @@
//! udraw support is NOT written - this is just notes about the init function
-#include
-#include // Core API
+#include
+#include // Core API
-#include "wii_anal.h"
-#include "wii_ec.h"
-#include "bc_logging.h"
+#include "wii_anal.h"
+#include "wii_ec.h"
+#include "bc_logging.h"
-#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header]
+#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header]
// ** If you want to see what this source code looks like with all the MACROs expanded
// ** grep -v '#include ' wii_ec_udraw.c | gcc -E -o /dev/stdout -xc -
-#include "wii_ec_macros.h"
+# include "wii_ec_macros.h"
//+============================================================================ ========================================
// https://github.com/madhephaestus/WiiChuck/blob/master/src/Drawsome.cpp#L3
@@ -27,12 +27,13 @@
// read 6 bytes starting from 0x00 (#3)
// read 6 bytes starting from 0x00 (#4)
//
-bool udraw_init(wiiEC_t* const pec) {
- ENTER;
- bool rv = true;
+bool udraw_init (wiiEC_t* const pec)
+{
+ ENTER;
+ bool rv = true;
- (void)pec;
- /*
+(void)pec;
+/*
//! this is the Drawsome code, NOT the uDraw code !!
static const uint8_t reg[9] = {0x20, 0x28, 0x30, 0x38, 0x00, 0x00, 0xFB, 0x00, 0x00}; // 0..8
const uint8_t* p = reg;
@@ -71,79 +72,74 @@ fail:
done:
*/
- LEAVE;
- return rv;
+ LEAVE;
+ return rv;
}
//+============================================================================ ========================================
-bool udraw_key(const eventMsg_t* const msg, state_t* const state) {
- (void)state;
- bool run = true;
+bool udraw_key (const eventMsg_t* const msg, state_t* const state)
+{
+(void)state;
+ bool run = true;
- switch(msg->input.type) {
- case InputTypeShort: //# input.key) {
- case InputKeyUp: //# ! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
- switch(msg->input.key) {
- case InputKeyUp: //# >U [ LONG-UP ]
- case InputKeyDown: //# >D [ LONG-DOWN ]
- case InputKeyLeft: //# >L [ LONG-LEFT ]
- case InputKeyRight: //# >R [ LONG-RIGHT ]
- case InputKeyOk: //# >O [ LONG-OK ]
- case InputKeyBack: //# >B [ LONG-BACK ]
- default:
- break; //# >?
- }
- break;
- case InputTypePress: //# +! After debounce
- switch(msg->input.key) {
- case InputKeyUp: //# +U [ SHORT-UP ]
- case InputKeyDown: //# +D [ SHORT-DOWN ]
- case InputKeyLeft: //# +L [ SHORT-LEFT ]
- case InputKeyRight: //# +R [ SHORT-RIGHT ]
- case InputKeyOk: //# +O [ SHORT-OK ]
- case InputKeyBack: //# +B [ SHORT-BACK ]
- default:
- break; //# +?
- }
- break;
- case InputTypeRepeat: //# *! With INPUT_REPEATE_PRESS period after InputTypeLong event
- switch(msg->input.key) {
- case InputKeyUp: //# *U [ REPEAT-UP ]
- case InputKeyDown: //# *D [ REPEAT-DOWN ]
- case InputKeyLeft: //# *L [ REPEAT-LEFT ]
- case InputKeyRight: //# *R [ REPEAT-RIGHT ]
- case InputKeyOk: //# *O [ REPEAT-OK ]
- case InputKeyBack: //# *B [ REPEAT-BACK ]
- default:
- break; //# *?
- }
- break;
- case InputTypeRelease: //# -! After debounce
- switch(msg->input.key) {
- case InputKeyUp: //# -U [ RELEASE-UP ]
- case InputKeyDown: //# -D [ RELEASE-DOWN ]
- case InputKeyLeft: //# -L [ RELEASE-LEFT ]
- case InputKeyRight: //# -R [ RELEASE-RIGHT ]
- case InputKeyOk: //# -O [ RELEASE-OK ]
- case InputKeyBack: //# -B [ RELEASE-BACK ]
- default:
- break; //# -?
- }
- break;
- default:
- return true;
- }
+ switch (msg->input.type) {
+ case InputTypeShort: //# input.key) {
+ case InputKeyUp: //# ! After INPUT_LONG_PRESS interval, asynch to InputTypeRelease
+ switch (msg->input.key) {
+ case InputKeyUp: //# >U [ LONG-UP ]
+ case InputKeyDown: //# >D [ LONG-DOWN ]
+ case InputKeyLeft: //# >L [ LONG-LEFT ]
+ case InputKeyRight: //# >R [ LONG-RIGHT ]
+ case InputKeyOk: //# >O [ LONG-OK ]
+ case InputKeyBack: //# >B [ LONG-BACK ]
+ default: break ; //# >?
+ }
+ break;
+ case InputTypePress: //# +! After debounce
+ switch (msg->input.key) {
+ case InputKeyUp: //# +U [ SHORT-UP ]
+ case InputKeyDown: //# +D [ SHORT-DOWN ]
+ case InputKeyLeft: //# +L [ SHORT-LEFT ]
+ case InputKeyRight: //# +R [ SHORT-RIGHT ]
+ case InputKeyOk: //# +O [ SHORT-OK ]
+ case InputKeyBack: //# +B [ SHORT-BACK ]
+ default: break ; //# +?
+ }
+ break;
+ case InputTypeRepeat: //# *! With INPUT_REPEATE_PRESS period after InputTypeLong event
+ switch (msg->input.key) {
+ case InputKeyUp: //# *U [ REPEAT-UP ]
+ case InputKeyDown: //# *D [ REPEAT-DOWN ]
+ case InputKeyLeft: //# *L [ REPEAT-LEFT ]
+ case InputKeyRight: //# *R [ REPEAT-RIGHT ]
+ case InputKeyOk: //# *O [ REPEAT-OK ]
+ case InputKeyBack: //# *B [ REPEAT-BACK ]
+ default: break ; //# *?
+ }
+ break;
+ case InputTypeRelease: //# -! After debounce
+ switch (msg->input.key) {
+ case InputKeyUp: //# -U [ RELEASE-UP ]
+ case InputKeyDown: //# -D [ RELEASE-DOWN ]
+ case InputKeyLeft: //# -L [ RELEASE-LEFT ]
+ case InputKeyRight: //# -R [ RELEASE-RIGHT ]
+ case InputKeyOk: //# -O [ RELEASE-OK ]
+ case InputKeyBack: //# -B [ RELEASE-BACK ]
+ default: break ; //# -?
+ }
+ break;
+ default: return true ;
+ }
- return run;
+ return run;
}
diff --git a/applications/plugins/wii_ec_anal/wii_ec_udraw.h b/applications/plugins/wii_ec_anal/wii_ec_udraw.h
index 9283fd95d..1721894e5 100644
--- a/applications/plugins/wii_ec_anal/wii_ec_udraw.h
+++ b/applications/plugins/wii_ec_anal/wii_ec_udraw.h
@@ -1,18 +1,18 @@
-#ifndef WII_EC_UDRAW_H_
-#define WII_EC_UDRAW_H_
+#ifndef WII_EC_UDRAW_H_
+#define WII_EC_UDRAW_H_
-#include
-#include
+#include
+#include
//============================================================================= =======================================
// Function prototypes
//
-typedef struct wiiEC wiiEC_t;
-typedef enum ecCalib ecCalib_t;
-typedef struct eventMsg eventMsg_t;
-typedef struct state state_t;
+typedef struct wiiEC wiiEC_t ;
+typedef enum ecCalib ecCalib_t ;
+typedef struct eventMsg eventMsg_t ;
+typedef struct state state_t ;
-bool udraw_init(wiiEC_t* const pec);
-bool udraw_key(const eventMsg_t* const msg, state_t* const state);
+bool udraw_init (wiiEC_t* const pec) ;
+bool udraw_key (const eventMsg_t* const msg, state_t* const state) ;
#endif //WII_EC_UDRAW_H_
diff --git a/applications/plugins/wii_ec_anal/wii_i2c.c b/applications/plugins/wii_ec_anal/wii_i2c.c
index f5d6840d9..90fe22163 100644
--- a/applications/plugins/wii_ec_anal/wii_i2c.c
+++ b/applications/plugins/wii_ec_anal/wii_i2c.c
@@ -17,98 +17,103 @@
// 0xFA..0xFF ( 6 bytes) ... [r] Perhipheral ID
//----------------------------------------------------------------------------- ----------------------------------------
-#include
-#include
-#include
+#include
+#include
+#include
-#include
-#include
-#include
+#include
+#include
+#include
-#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header]
+#include "i2c_workaround.h" //! temporary workaround for a bug in furi i2c [see header]
-#include "wii_anal.h"
-#include "wii_i2c.h"
-#include "wii_ec.h"
+#include "wii_anal.h"
+#include "wii_i2c.h"
+#include "wii_ec.h"
-#include "bc_logging.h"
+#include "bc_logging.h"
//----------------------------------------------------------------------------- ----------------------------------------
// Wii Extension Controller i2c Bus address
-static const uint8_t ec_i2cAddr = 0x52;
+static const uint8_t ec_i2cAddr = 0x52;
// Initialise for UNencrypted comms
-static const uint8_t regInit1 = 0xF0;
-static const uint8_t regInit2 = 0xFB;
-static const uint8_t cmdInit1[] = {regInit1, 0x55};
-static const uint8_t cmdInit2[] = {regInit2, 0x00};
+static const uint8_t regInit1 = 0xF0;
+static const uint8_t regInit2 = 0xFB;
+static const uint8_t cmdInit1[] = {regInit1, 0x55};
+static const uint8_t cmdInit2[] = {regInit2, 0x00};
// Initialise for ENcrypted comms
-static const uint8_t regInitEnc = 0x40;
-static const uint8_t cmdInitEnc[] = {regInitEnc, 0x00};
+static const uint8_t regInitEnc = 0x40;
+static const uint8_t cmdInitEnc[] = {regInitEnc, 0x00};
// Crypto key (PSK), base register : {0x40..0x4F}[2][8]
-static const uint8_t regEnc = 0x40; // ENC_LEN
+static const uint8_t regEnc = 0x40; // ENC_LEN
// Controller State data, base register : {0x00..0x05}[6]
-static const uint8_t regJoy = 0x00; // JOY_LEN
+static const uint8_t regJoy = 0x00; // JOY_LEN
// Calibration data, base register : {0x20..0x2F}[16]
-static const uint8_t regCal = 0x20; // CAL_LEN
+static const uint8_t regCal = 0x20; // CAL_LEN
// Controller ID, base register : {0xFA..0xFF}[6]
-static const uint8_t regPid = 0xFA; // PID_LEN
+static const uint8_t regPid = 0xFA; // PID_LEN
//+============================================================================ ========================================
// Hexdump a buffer to the logfile
//
#if LOG_LEVEL >= 4 // INFO
-static void dump(const uint8_t* buf, const unsigned int len, const char* id) {
- // snprintf() would be useful!
- char s[128] = {0};
- char* p = NULL;
+static
+void dump (const uint8_t* buf, const unsigned int len, const char* id)
+{
+ // snprintf() would be useful!
+ char s[128] = {0};
+ char* p = NULL;
- strcpy(s, id);
- p = s + strlen(s);
- *p++ = ':';
- *p++ = ' ';
- *p++ = '{';
+ strcpy(s, id);
+ p = s +strlen(s);
+ *p++ = ':';
+ *p++ = ' ';
+ *p++ = '{';
- for(unsigned int i = 0; i < len; i++) {
- uint8_t hi = (buf[i] & 0xF0) >> 4;
- uint8_t lo = (buf[i] & 0x0F);
+ for (unsigned int i = 0; i < len; i++) {
+ uint8_t hi = (buf[i] &0xF0) >>4;
+ uint8_t lo = (buf[i] &0x0F);
- hi = hi + ((hi > 9) ? ('A' - 10) : '0');
- lo = lo + ((lo > 9) ? ('A' - 10) : '0');
+ hi = hi + ((hi > 9) ? ('A' -10) : '0');
+ lo = lo + ((lo > 9) ? ('A' -10) : '0');
- *p++ = (char)hi;
- *p++ = (char)lo;
- *p++ = ',';
- }
- *p = '\0';
- *--p = '}';
- INFO(s);
+ *p++ = (char)hi;
+ *p++ = (char)lo;
+ *p++ = ',';
+ }
+ *p = '\0';
+ *--p = '}';
+ INFO(s);
}
#else
-#define dump(...)
+# define dump(...)
#endif
//+============================================================================ ========================================
//
//! -W-A-R-N-I-N-G- : THIS ENCRYPTION CODE SHOULD NEVER BE REQUIRED ... AS SUCH, I'VE NEVER TESTED IT
//
-static void decrypt(uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsigned int len) {
-#if 1 // Use standard algorithm
- // decrypted_byte = (encrypted_byte XOR encKey[1][address%8]) + encKey[2][address%8]
- for(uint8_t* p = buf; p < buf + len; p++)
- *p = (*p ^ encKey[(reg + (p - buf)) % 8]) + encKey[8 + ((reg + (p - buf)) % 8)];
+static
+void decrypt (uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsigned int len)
+{
+#if 1 // Use standard algorithm
+ // decrypted_byte = (encrypted_byte XOR encKey[1][address%8]) + encKey[2][address%8]
+ for (uint8_t* p = buf; p < buf+len; p++)
+ *p = (*p ^ encKey[(reg +(p -buf)) %8]) + encKey[8 +((reg +(p -buf)) %8)];
-#else //! This is (I think) a shortcut for an all-zero key [not tested]
- (void)encKey;
- (void)reg;
- for(uint8_t* p = buf; p < buf + len; p++) *p = (*p ^ 0x17) + 0x17;
+#else //! This is (I think) a shortcut for an all-zero key [not tested]
+ (void)encKey;
+ (void)reg;
+ for (uint8_t* p = buf; p < buf+len; p++)
+ *p = (*p ^ 0x17) + 0x17;
#endif
}
@@ -118,38 +123,38 @@ static void decrypt(uint8_t* buf, const uint8_t* encKey, const uint8_t reg, unsi
//
// Returns: {0:OK, >0:Error}
//
-int ecRead(wiiEC_t* pec) {
- ENTER;
- int rv = 0; // assume success
+int ecRead (wiiEC_t* pec)
+{
+ ENTER;
+ int rv = 0; // assume success
- if(!pec->init) {
- WARN("%s : device not initialised", __func__);
- rv = 1;
- goto bail;
- }
+ if (!pec->init) {
+ WARN("%s : device not initialised", __func__);
+ rv = 1;
+ goto bail;
+ }
- if(!furi_hal_i2c_is_device_ready(i2cBus, i2cAddr, i2cTimeout)) {
- INFO("%s : device disconnected", __func__);
- pec->init = false;
- rv = 2;
- goto bail;
- }
+ if (!furi_hal_i2c_is_device_ready(i2cBus,i2cAddr, i2cTimeout)) {
+ INFO("%s : device disconnected", __func__);
+ pec->init = false;
+ rv = 2;
+ goto bail;
+ }
- if(!furi_hal_i2c_trxd(
- i2cBus, i2cAddr, ®Joy, 1, pec->joy, JOY_LEN, i2cTimeout, i2cReadWait)) {
- ERROR("%s : trxd fail", __func__);
- rv = 3;
- goto bail;
- }
+ if (!furi_hal_i2c_trxd(i2cBus,i2cAddr, ®Joy,1, pec->joy,JOY_LEN, i2cTimeout,i2cReadWait)) {
+ ERROR("%s : trxd fail", __func__);
+ rv = 3;
+ goto bail;
+ }
- if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN);
+ if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN) ;
- // Decode the readings (according to Controller type)
- ecDecode(pec);
+ // Decode the readings (according to Controller type)
+ ecDecode(pec);
bail:
- LEAVE;
- return rv;
+ LEAVE;
+ return rv;
}
//+============================================================================ ========================================
@@ -157,145 +162,148 @@ bail:
//
//! To disable encryption, pass a NULL encryption key <-- this is currently ALWAYS the case
//
-bool ecInit(wiiEC_t* pec, const uint8_t* encKey) {
- ENTER;
+bool ecInit (wiiEC_t* pec, const uint8_t* encKey)
+{
+ ENTER;
- bool rv = false; // assume failure
+ bool rv = false; // assume failure
-#if 0 //! i2c workaround
+#if 0 //! i2c workaround
//! I think this is done during OS startup - long before the plugin starts
furi_hal_i2c_init();
#endif
-#if 0 //! i2c workaround
+#if 0 //! i2c workaround
// May become relevant when the i2c issues are resolved
// Take control of the i2c bus [which returns void !?]
// --> firmware/targets/f7/furi_hal/furi_hal_i2c.c
furi_hal_i2c_acquire(i2cBus);
#endif
- pec->init = false; // assume failure
+ pec->init = false; // assume failure
- // === See if the device is alive ===
- if(!furi_hal_i2c_is_device_ready(i2cBus, i2cAddr, i2cTimeout)) {
- TRACE("%s : waiting for device", __func__);
- goto bail;
- }
- INFO("%s : device connected", __func__);
+ // === See if the device is alive ===
+ if (!furi_hal_i2c_is_device_ready(i2cBus,i2cAddr, i2cTimeout)) {
+ TRACE("%s : waiting for device", __func__);
+ goto bail;
+ }
+ INFO("%s : device connected", __func__);
- // === Initialise the device ===
- pec->init = false; // This goes true AFTER the (optional) controller-specific init code
+ // === Initialise the device ===
+ pec->init = false; // This goes true AFTER the (optional) controller-specific init code
- // === Start the Extension Controller ===
- if(encKey) { //! start in encrypted mode
+ // === Start the Extension Controller ===
+ if (encKey) { //! start in encrypted mode
- //! todo - should this happen here, or AFTER we've got the ID ?
+ //! todo - should this happen here, or AFTER we've got the ID ?
- } else {
- if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInit1, sizeof(cmdInit1), i2cTimeout)) {
- ERROR("%s : init fail (dec1)", __func__);
- goto bail;
- }
- TRACE("%s : init OK1", __func__);
+ } else {
- if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInit2, sizeof(cmdInit2), i2cTimeout)) {
- ERROR("%s : init fail (dec2)", __func__);
- goto bail;
- }
- TRACE("%s : init OK2", __func__);
- }
+ if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInit1,sizeof(cmdInit1), i2cTimeout) ) {
+ ERROR("%s : init fail (dec1)", __func__);
+ goto bail;
+ }
+ TRACE("%s : init OK1", __func__);
- // === Retrieve the Extension Controller ID ===
- if(!furi_hal_i2c_trx(i2cBus, i2cAddr, ®Pid, 1, pec->pid, PID_LEN, i2cTimeout)) {
- ERROR("%s : T(R)x fail (pid)", __func__);
- goto bail;
- }
- if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN);
- dump(pec->pid, PID_LEN, "pid"); // debug INFO
+ if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInit2,sizeof(cmdInit2), i2cTimeout) ) {
+ ERROR("%s : init fail (dec2)", __func__);
+ goto bail;
+ }
+ TRACE("%s : init OK2", __func__);
+ }
- // Find the StringID in the lookup table
- for(pec->pidx = PID_FIRST; pec->pidx < PID_ERROR; pec->pidx++)
- if(memcmp(pec->pid, ecId[pec->pidx].id, PID_LEN) == 0) break;
- if(pec->pidx == PID_ERROR) pec->pidx = PID_UNKNOWN;
- pec->sid = ecId[pec->pidx].name;
- INFO("sid: %s", pec->sid);
+ // === Retrieve the Extension Controller ID ===
+ if (!furi_hal_i2c_trx(i2cBus,i2cAddr, ®Pid,1, pec->pid,PID_LEN, i2cTimeout)) {
+ ERROR("%s : T(R)x fail (pid)", __func__);
+ goto bail;
+ }
+ if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN);
+ dump(pec->pid, PID_LEN, "pid"); // debug INFO
- // === (optionally) Enable encryption ===
- if(!encKey) {
- pec->encrypt = false;
+ // Find the StringID in the lookup table
+ for (pec->pidx = PID_FIRST; pec->pidx < PID_ERROR; pec->pidx++)
+ if (memcmp(pec->pid, ecId[pec->pidx].id, PID_LEN) == 0) break ;
+ if (pec->pidx == PID_ERROR) pec->pidx = PID_UNKNOWN ;
+ pec->sid = ecId[pec->pidx].name;
+ INFO("sid: %s", pec->sid);
- } else { // Controller WILL encrypt ALL tranmissions
- //! this encryption code fails - should it be done earlier?
- //! as it is probably never of any use, I'm kinda loathed to spend time on it
- //! https://github.com/madhephaestus/WiiChuck/blob/master/src/Accessory.cpp#L138
- uint8_t encTx[1 + ENC_LEN] = {0};
- uint8_t* ep = encTx;
+ // === (optionally) Enable encryption ===
+ if (!encKey) {
+ pec->encrypt = false;
- pec->encrypt = true;
+ } else { // Controller WILL encrypt ALL tranmissions
+//! this encryption code fails - should it be done earlier?
+//! as it is probably never of any use, I'm kinda loathed to spend time on it
+//! https://github.com/madhephaestus/WiiChuck/blob/master/src/Accessory.cpp#L138
+ uint8_t encTx[1+ENC_LEN] = {0};
+ uint8_t* ep = encTx;
- // ** Start the Controller in ENcrytped mode
- if(!furi_hal_i2c_tx(i2cBus, i2cAddr, cmdInitEnc, sizeof(cmdInitEnc), i2cTimeout)) {
- ERROR("%s : init fail (enc)", __func__);
- goto bail;
- }
+ pec->encrypt = true;
- // Copy the (symmetric) encryption key to the controller state table
- if(pec->encKey != encKey) memcpy(pec->encKey, encKey, ENC_LEN);
+ // ** Start the Controller in ENcrytped mode
+ if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, cmdInitEnc,sizeof(cmdInitEnc), i2cTimeout) ) {
+ ERROR("%s : init fail (enc)", __func__);
+ goto bail;
+ }
- // Build the encryption key packet
- *ep++ = regEnc;
- memcpy(ep, pec->encKey, ENC_LEN);
+ // Copy the (symmetric) encryption key to the controller state table
+ if (pec->encKey != encKey)
+ memcpy(pec->encKey, encKey, ENC_LEN);
- // ** Send encryption key (PSK)
- if(!furi_hal_i2c_tx(i2cBus, i2cAddr, encTx, (1 + ENC_LEN), i2cTimeout)) {
- ERROR("%s : key fail", __func__);
- goto bail;
- }
+ // Build the encryption key packet
+ *ep++ = regEnc;
+ memcpy(ep, pec->encKey, ENC_LEN);
- TRACE("%s : init OK (enc)", __func__);
- }
+ // ** Send encryption key (PSK)
+ if ( !furi_hal_i2c_tx(i2cBus,i2cAddr, encTx,(1+ENC_LEN), i2cTimeout) ) {
+ ERROR("%s : key fail", __func__);
+ goto bail;
+ }
- // === Some devices [eg. Drawsome/uDraw] require additional init code ===
- if(ecId[pec->init].init && (ecId[pec->init].init(pec) == false)) goto bail;
- pec->init = true;
+ TRACE("%s : init OK (enc)", __func__);
+ }
- // === Read calibration data ===
- if(!furi_hal_i2c_trx(i2cBus, i2cAddr, ®Cal, 1, pec->calF, CAL_LEN, i2cTimeout)) {
- ERROR("%s : trx fail (cal)", __func__);
- goto bail;
- }
- if(pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN);
- dump(pec->calF, CAL_LEN, "cal");
+ // === Some devices [eg. Drawsome/uDraw] require additional init code ===
+ if ( ecId[pec->init].init && (ecId[pec->init].init(pec) == false) ) goto bail ;
+ pec->init = true;
- ecCalibrate(pec, CAL_RESET | CAL_FACTORY); // Load factory default calibration
+ // === Read calibration data ===
+ if (!furi_hal_i2c_trx(i2cBus,i2cAddr, ®Cal,1, pec->calF,CAL_LEN, i2cTimeout)) {
+ ERROR("%s : trx fail (cal)", __func__);
+ goto bail;
+ }
+ if (pec->encrypt) decrypt(pec->joy, pec->encKey, regJoy, JOY_LEN);
+ dump(pec->calF, CAL_LEN, "cal");
- // === Initialise decode buffers ===
- pec->decN = 0; // read in to decode[1] (yes, N=0 -> read in to dec[1])
- switch(ecRead(pec)) {
- case 0: // read OK
- memcpy(&pec->dec[0], &pec->dec[1], sizeof(pec->dec[0]));
- dump(pec->joy, JOY_LEN, "joy");
- break;
+ ecCalibrate(pec, CAL_RESET | CAL_FACTORY); // Load factory default calibration
- default: // bug: unknown
- case 1: // bug: not initialised - should never happen
- ERROR("%s : read bug", __func__);
- break;
+ // === Initialise decode buffers ===
+ pec->decN = 0; // read in to decode[1] (yes, N=0 -> read in to dec[1])
+ switch (ecRead(pec)) {
+ case 0: // read OK
+ memcpy(&pec->dec[0], &pec->dec[1], sizeof(pec->dec[0]));
+ dump(pec->joy, JOY_LEN, "joy");
+ break;
- case 2: // device gone
- case 3: // read fail
- // Logging done by ecRead()
- pec->init = false;
- goto bail;
- }
+ default: // bug: unknown
+ case 1: // bug: not initialised - should never happen
+ ERROR("%s : read bug", __func__);
+ break;
- rv = true; // yay :)
+ case 2: // device gone
+ case 3: // read fail
+ // Logging done by ecRead()
+ pec->init = false;
+ goto bail;
+ }
+
+ rv = true; // yay :)
bail:
#if 0 //! i2c workaround
furi_hal_i2c_release(i2cBus);
#endif
- LEAVE;
- return rv;
+ LEAVE;
+ return rv;
}
diff --git a/applications/plugins/wii_ec_anal/wii_i2c.h b/applications/plugins/wii_ec_anal/wii_i2c.h
index efebefcf9..18cb5ee9b 100644
--- a/applications/plugins/wii_ec_anal/wii_i2c.h
+++ b/applications/plugins/wii_ec_anal/wii_i2c.h
@@ -1,7 +1,7 @@
-#ifndef WII_I2C_H_
-#define WII_I2C_H_
+#ifndef WII_I2C_H_
+#define WII_I2C_H_
-#include