فهرست منبع

Move apps out of .modules/

Willy-JL 2 سال پیش
والد
کامیت
ef723e0234
100فایلهای تغییر یافته به همراه2 افزوده شده و 3979 حذف شده
  1. 2 5
      .gitmodules
  2. 0 15
      .modules/camera_suite/.github/images/bitcoin-btc-logo.svg
  3. BIN
      .modules/camera_suite/.github/images/camera-suite.png
  4. BIN
      .modules/camera_suite/.github/images/esp32-cam-back.png
  5. BIN
      .modules/camera_suite/.github/images/esp32-cam-front.png
  6. BIN
      .modules/camera_suite/.github/images/esp32-cam-pinout-guide.png
  7. BIN
      .modules/camera_suite/.github/images/firmware-build-success.png
  8. 0 36
      .modules/camera_suite/.github/images/flipper-zero-buy-now.svg
  9. 0 41
      .modules/camera_suite/.github/images/flipper-zero-docs.svg
  10. BIN
      .modules/camera_suite/.github/images/preview.png
  11. 0 5
      .modules/camera_suite/.github/ng-icons/Angular Material Icons.url
  12. 0 12
      .modules/camera_suite/.github/ng-icons/email.svg
  13. 0 2
      .modules/camera_suite/.github/simple-icons/Simple Icons.url
  14. 0 0
      .modules/camera_suite/.github/simple-icons/buymeacoffee.svg
  15. 0 36
      .modules/camera_suite/.github/workflows/deploy-main.yml
  16. 0 22
      .modules/camera_suite/.github/workflows/lint-pull-request.yml
  17. 0 13
      .modules/camera_suite/.gitignore
  18. 0 7
      .modules/camera_suite/.gitmodules
  19. 0 1
      .modules/camera_suite/.gitremote
  20. 0 28
      .modules/camera_suite/LICENSE
  21. 0 251
      .modules/camera_suite/README.md
  22. 0 27
      .modules/camera_suite/arduino-cli.yaml
  23. 0 16
      .modules/camera_suite/fap/application.fam
  24. 0 135
      .modules/camera_suite/fap/camera_suite.c
  25. 0 86
      .modules/camera_suite/fap/camera_suite.h
  26. 0 48
      .modules/camera_suite/fap/docs/CHANGELOG.md
  27. 0 37
      .modules/camera_suite/fap/docs/README.md
  28. 0 67
      .modules/camera_suite/fap/helpers/camera_suite_custom_event.h
  29. 0 35
      .modules/camera_suite/fap/helpers/camera_suite_haptic.c
  30. 0 7
      .modules/camera_suite/fap/helpers/camera_suite_haptic.h
  31. 0 38
      .modules/camera_suite/fap/helpers/camera_suite_led.c
  32. 0 3
      .modules/camera_suite/fap/helpers/camera_suite_led.h
  33. 0 26
      .modules/camera_suite/fap/helpers/camera_suite_speaker.c
  34. 0 5
      .modules/camera_suite/fap/helpers/camera_suite_speaker.h
  35. 0 120
      .modules/camera_suite/fap/helpers/camera_suite_storage.c
  36. 0 23
      .modules/camera_suite/fap/helpers/camera_suite_storage.h
  37. BIN
      .modules/camera_suite/fap/icons/camera_suite.png
  38. 0 20
      .modules/camera_suite/fap/manifest.yml
  39. 0 30
      .modules/camera_suite/fap/scenes/camera_suite_scene.c
  40. 0 29
      .modules/camera_suite/fap/scenes/camera_suite_scene.h
  41. 0 52
      .modules/camera_suite/fap/scenes/camera_suite_scene_camera.c
  42. 0 5
      .modules/camera_suite/fap/scenes/camera_suite_scene_config.h
  43. 0 51
      .modules/camera_suite/fap/scenes/camera_suite_scene_guide.c
  44. 0 73
      .modules/camera_suite/fap/scenes/camera_suite_scene_menu.c
  45. 0 226
      .modules/camera_suite/fap/scenes/camera_suite_scene_settings.c
  46. 0 55
      .modules/camera_suite/fap/scenes/camera_suite_scene_start.c
  47. BIN
      .modules/camera_suite/fap/screenshots/camera_preview.png
  48. BIN
      .modules/camera_suite/fap/screenshots/guide.png
  49. BIN
      .modules/camera_suite/fap/screenshots/main_menu.png
  50. BIN
      .modules/camera_suite/fap/screenshots/settings.png
  51. BIN
      .modules/camera_suite/fap/screenshots/start_screen.png
  52. 0 577
      .modules/camera_suite/fap/views/camera_suite_view_camera.c
  53. 0 81
      .modules/camera_suite/fap/views/camera_suite_view_camera.h
  54. 0 119
      .modules/camera_suite/fap/views/camera_suite_view_guide.c
  55. 0 19
      .modules/camera_suite/fap/views/camera_suite_view_guide.h
  56. 0 126
      .modules/camera_suite/fap/views/camera_suite_view_start.c
  57. 0 19
      .modules/camera_suite/fap/views/camera_suite_view_start.h
  58. 0 188
      .modules/camera_suite/firmware-flash.bat
  59. 0 22
      .modules/camera_suite/firmware/camera.h
  60. 0 47
      .modules/camera_suite/firmware/camera.ino
  61. 0 14
      .modules/camera_suite/firmware/camera_config.h
  62. 0 30
      .modules/camera_suite/firmware/camera_config.ino
  63. 0 43
      .modules/camera_suite/firmware/camera_model.h
  64. 0 13
      .modules/camera_suite/firmware/camera_model.ino
  65. 0 11
      .modules/camera_suite/firmware/dither_image.h
  66. 0 82
      .modules/camera_suite/firmware/dither_image.ino
  67. 0 12
      .modules/camera_suite/firmware/firmware.h
  68. 0 30
      .modules/camera_suite/firmware/firmware.ino
  69. 0 23
      .modules/camera_suite/firmware/pins.h
  70. 0 13
      .modules/camera_suite/firmware/process_image.h
  71. 0 54
      .modules/camera_suite/firmware/process_image.ino
  72. 0 13
      .modules/camera_suite/firmware/process_serial_commands.h
  73. 0 63
      .modules/camera_suite/firmware/process_serial_commands.ino
  74. 0 13
      .modules/camera_suite/firmware/save_picture_to_sd_card.h
  75. 0 58
      .modules/camera_suite/firmware/save_picture_to_sd_card.ino
  76. 0 1
      .modules/geiger/.gitremote
  77. 0 224
      .modules/geiger/README.md
  78. BIN
      .modules/geiger/flipper_geiger.fap
  79. 0 13
      .modules/geiger/flipper_geiger/application.fam
  80. 0 383
      .modules/geiger/flipper_geiger/flipper_geiger.c
  81. BIN
      .modules/geiger/flipper_geiger/geiger.png
  82. BIN
      .modules/geiger/img/dice.jpg
  83. BIN
      .modules/geiger/img/flipper1.png
  84. BIN
      .modules/geiger/img/flipper10.png
  85. BIN
      .modules/geiger/img/flipper11.png
  86. BIN
      .modules/geiger/img/flipper12.png
  87. BIN
      .modules/geiger/img/flipper13.png
  88. BIN
      .modules/geiger/img/flipper14.png
  89. BIN
      .modules/geiger/img/flipper2.png
  90. BIN
      .modules/geiger/img/flipper3.png
  91. BIN
      .modules/geiger/img/flipper4.png
  92. BIN
      .modules/geiger/img/flipper5.png
  93. BIN
      .modules/geiger/img/flipper6.png
  94. BIN
      .modules/geiger/img/flipper7.png
  95. BIN
      .modules/geiger/img/flipper8.png
  96. BIN
      .modules/geiger/img/flipper9.png
  97. BIN
      .modules/geiger/img/jack.png
  98. BIN
      .modules/geiger/img/logo.jpg
  99. BIN
      .modules/geiger/img/schema.jpg
  100. BIN
      .modules/geiger/img/user/IMG-1552.jpg

+ 2 - 5
.gitmodules

@@ -1,7 +1,4 @@
-[submodule ".modules/good-faps/dap_link/lib/free-dap"]
-	path = .modules/good-faps/dap_link/lib/free-dap
-	url = https://github.com/ataradov/free-dap.git
-[submodule ".modules/totp/totp/lib/wolfssl"]
-	path = .modules/totp/totp/lib/wolfssl
+[submodule "totp/lib/wolfssl"]
+	path = totp/lib/wolfssl
 	url = https://github.com/wolfSSL/wolfssl.git
 	branch = master

+ 0 - 15
.modules/camera_suite/.github/images/bitcoin-btc-logo.svg

@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Creator: CorelDRAW 2019 (64-Bit) -->
-<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100%" height="100%" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
-viewBox="0 0 4091.27 4091.73"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
- <g id="Layer_x0020_1">
-  <metadata id="CorelCorpID_0Corel-Layer"/>
-  <g id="_1421344023328">
-   <path fill="#F7931A" fill-rule="nonzero" d="M4030.06 2540.77c-273.24,1096.01 -1383.32,1763.02 -2479.46,1489.71 -1095.68,-273.24 -1762.69,-1383.39 -1489.33,-2479.31 273.12,-1096.13 1383.2,-1763.19 2479,-1489.95 1096.06,273.24 1763.03,1383.51 1489.76,2479.57l0.02 -0.02z"/>
-   <path fill="white" fill-rule="nonzero" d="M2947.77 1754.38c40.72,-272.26 -166.56,-418.61 -450,-516.24l91.95 -368.8 -224.5 -55.94 -89.51 359.09c-59.02,-14.72 -119.63,-28.59 -179.87,-42.34l90.16 -361.46 -224.36 -55.94 -92 368.68c-48.84,-11.12 -96.81,-22.11 -143.35,-33.69l0.26 -1.16 -309.59 -77.31 -59.72 239.78c0,0 166.56,38.18 163.05,40.53 90.91,22.69 107.35,82.87 104.62,130.57l-104.74 420.15c6.26,1.59 14.38,3.89 23.34,7.49 -7.49,-1.86 -15.46,-3.89 -23.73,-5.87l-146.81 588.57c-11.11,27.62 -39.31,69.07 -102.87,53.33 2.25,3.26 -163.17,-40.72 -163.17,-40.72l-111.46 256.98 292.15 72.83c54.35,13.63 107.61,27.89 160.06,41.3l-92.9 373.03 224.24 55.94 92 -369.07c61.26,16.63 120.71,31.97 178.91,46.43l-91.69 367.33 224.51 55.94 92.89 -372.33c382.82,72.45 670.67,43.24 791.83,-303.02 97.63,-278.78 -4.86,-439.58 -206.26,-544.44 146.69,-33.83 257.18,-130.31 286.64,-329.61l-0.07 -0.05zm-512.93 719.26c-69.38,278.78 -538.76,128.08 -690.94,90.29l123.28 -494.2c152.17,37.99 640.17,113.17 567.67,403.91zm69.43 -723.3c-63.29,253.58 -453.96,124.75 -580.69,93.16l111.77 -448.21c126.73,31.59 534.85,90.55 468.94,355.05l-0.02 0z"/>
-  </g>
- </g>
-</svg>

BIN
.modules/camera_suite/.github/images/camera-suite.png


BIN
.modules/camera_suite/.github/images/esp32-cam-back.png


BIN
.modules/camera_suite/.github/images/esp32-cam-front.png


BIN
.modules/camera_suite/.github/images/esp32-cam-pinout-guide.png


BIN
.modules/camera_suite/.github/images/firmware-build-success.png


+ 0 - 36
.modules/camera_suite/.github/images/flipper-zero-buy-now.svg

@@ -1,36 +0,0 @@
-<svg 
-  aria-label="BUY NOW: FLIPPER ZERO"
-  height="28" 
-  role="img" 
-  width="201.75" 
-  xmlns:xlink="http://www.w3.org/1999/xlink" 
-  xmlns="http://www.w3.org/2000/svg" 
->
-  <title>BUY NOW: FLIPPER ZERO</title>
-  <g shape-rendering="crispEdges">
-    <rect width="81.75" height="28" fill="#555"/>
-    <rect x="81.75" width="120" height="28" fill="#ee6e00"/>
-  </g>
-  <g 
-    fill="#fff" 
-    font-family="Verdana,Geneva,DejaVu Sans,sans-serif" 
-    font-size="100"
-    text-anchor="middle" 
-    text-rendering="geometricPrecision" 
-  >
-    <text 
-      fill="#fff"
-      textLength="577.5" 
-      transform="scale(.1)" 
-      x="408.75" 
-      y="175" 
-    >BUY NOW</text>
-    <text 
-      fill="#fff" 
-      font-weight="bold"
-      textLength="960" 
-      transform="scale(.1)" 
-      x="1417.5" y="175" 
-    >FLIPPER ZERO</text>
-  </g>
-</svg>

+ 0 - 41
.modules/camera_suite/.github/images/flipper-zero-docs.svg

@@ -1,41 +0,0 @@
-<svg 
-  aria-label="DOCS: FLIPPER ZERO"
-  height="28" 
-  role="img" 
-  width="178" 
-  xmlns:xlink="http://www.w3.org/1999/xlink" 
-  xmlns="http://www.w3.org/2000/svg" 
->
-  <title>DOCS: FLIPPER ZERO</title>
-  <g shape-rendering="crispEdges">
-    <rect width="58" height="28" fill="#555"/>
-    <rect x="58" width="120" height="28" fill="#ee6e00"/>
-  </g>
-  <g 
-    fill="#fff" 
-    font-family="Verdana,Geneva,DejaVu Sans,sans-serif" 
-    font-size="100"
-    text-anchor="middle" 
-    text-rendering="geometricPrecision" 
-  >
-    <text 
-      fill="#fff"
-      textLength="340" 
-      transform="scale(.1)" 
-      x="290" 
-      y="175" 
-    >
-      DOCS
-    </text>
-    <text 
-      fill="#fff" 
-      font-weight="bold"
-      textLength="960" 
-      transform="scale(.1)" 
-      x="1180" 
-      y="175" 
-    >
-      FLIPPER ZERO
-    </text>
-  </g>
-</svg>

BIN
.modules/camera_suite/.github/images/preview.png


+ 0 - 5
.modules/camera_suite/.github/ng-icons/Angular Material Icons.url

@@ -1,5 +0,0 @@
-[{000214A0-0000-0000-C000-000000000046}]
-Prop3=19,11
-[InternetShortcut]
-IDList=
-URL=https://fonts.google.com/icons

+ 0 - 12
.modules/camera_suite/.github/ng-icons/email.svg

@@ -1,12 +0,0 @@
-<svg 
-    xmlns="http://www.w3.org/2000/svg" 
-    height="24" 
-    viewBox="0 -960 960 960" 
-    width="24"
->
-    <title>Email</title>
-    <path 
-        fill="#8ab4f8"
-        d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm320-280L160-640v400h640v-400L480-440Zm0-80 320-200H160l320 200ZM160-640v-80 480-400Z"
-    />
-</svg>

+ 0 - 2
.modules/camera_suite/.github/simple-icons/Simple Icons.url

@@ -1,2 +0,0 @@
-[InternetShortcut]
-URL=https://github.com/simple-icons

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
.modules/camera_suite/.github/simple-icons/buymeacoffee.svg


+ 0 - 36
.modules/camera_suite/.github/workflows/deploy-main.yml

@@ -1,36 +0,0 @@
-name: "Build + upload."
-on:
-  push:
-    branches:
-      # Run on push to main.
-      - main
-  schedule:
-    # Run every day at 00:00 UTC (midnight)
-    - cron: "0 0 * * *"
-jobs:
-  ufbt-build-action:
-    runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        include:
-          - name: dev
-            sdk-channel: dev
-          - name: release
-            sdk-channel: release
-    name: "ufbt: Build for ${{ matrix.name }}"
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-        with:
-          submodules: recursive
-      - name: Build with ufbt
-        uses: flipperdevices/flipperzero-ufbt-action@v0.1.2
-        id: build-app
-        with:
-          app-dir: ./fap
-          sdk-channel: ${{ matrix.sdk-channel }}
-      - name: Upload app artifacts
-        uses: actions/upload-artifact@v3
-        with:
-          name: ${{ github.event.repository.name }}-${{ matrix.name }}-${{ steps.build-app.outputs.suffix }}.zip
-          path: ${{ steps.build-app.outputs.fap-artifacts }}

+ 0 - 22
.modules/camera_suite/.github/workflows/lint-pull-request.yml

@@ -1,22 +0,0 @@
-name: "Build test + lint."
-on: pull_request
-jobs:
-  ufbt-build-action:
-    runs-on: ubuntu-latest
-    name: "ufbt: Build for Dev branch"
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-      - name: Build with ufbt
-        # Flipper Zero ufbt action
-        # https://github.com/flipperdevices/flipperzero-ufbt-action
-        uses: flipperdevices/flipperzero-ufbt-action@v0.1.2
-        id: build-app
-        with:
-          app-dir: ./fap
-          sdk-channel: dev
-      - name: Lint sources
-        uses: flipperdevices/flipperzero-ufbt-action@v0.1.2
-        with:
-          skip-setup: true
-          task: lint

+ 0 - 13
.modules/camera_suite/.gitignore

@@ -1,13 +0,0 @@
-*.clang-format
-*.editorconfig
-*.exe
-*.flag
-*.vscode
-*.zip
-.DS_Store
-.idea
-.submodules/*
-/venv
-__pycache__
-dist/*
-fap/dist/*

+ 0 - 7
.modules/camera_suite/.gitmodules

@@ -1,7 +0,0 @@
-[submodule ".submodules/flipper-application-catalog"]
-	path = .submodules/flipper-application-catalog
-	url = https://github.com/flipperdevices/flipper-application-catalog
-[submodule ".submodules/flipperzero-firmware"]
-	path = .submodules/flipperzero-firmware
-	url = https://github.com/flipperdevices/flipperzero-firmware
-	branch = dev

+ 0 - 1
.modules/camera_suite/.gitremote

@@ -1 +0,0 @@
-https://github.com/CodyTolene/Flipper-Zero-Camera-Suite main

+ 0 - 28
.modules/camera_suite/LICENSE

@@ -1,28 +0,0 @@
-BSD 3-Clause License
-
-Copyright (c) 2023, Zalán Kórósi
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 0 - 251
.modules/camera_suite/README.md

@@ -1,251 +0,0 @@
-<div align="center">
-  <img align="center" src=".github/images/camera-suite.png" />
-  <h2 align="center">Flipper Zero - Camera Suite</h2>
-  <p align="center">
-    Firmware and software to run an ESP32-CAM module on your Flipper Zero device.
-  </p>
-  <a href="https://shop.flipperzero.one/">
-    <img src=".github/images/flipper-zero-buy-now.svg" />
-  </a>
-  <a href="https://docs.flipperzero.one/">
-    <img src=".github/images/flipper-zero-docs.svg" />
-  </a>
-</div>
-
----
-
-## Table of Contents <a name="index"></a>
-
-- [Introduction](#intro)
-- [Hardware Requirements](#hardware-requirements)
-- [Hardware Installation](#hardware-installation)
-- [Firmware Installation](#firmware-installation)
-- [Software Installation](#software-installation)
-- [Software Guide](#software-guide)
-- [Attributions](#attributions)
-- [Contributions](#contributions)
-- [Changelog](fap/docs/CHANGELOG.md)
-
-## Introduction <a name="intro"></a>
-
-<img align="center" src=".github/images/preview.png" />
-
-### Welcome to the ESP32-CAM Suite for Flipper Zero
-
-Discover a new dimension of possibilities by connecting your ESP32-CAM module with your Flipper Zero device. The ESP32-CAM module, a compact ~~powerful~~ cheap camera module, enables you to capture images and stream a live video to your Flipper Zero. With this suite, your Flipper Zero becomes a hub of creativity and utility.
-
-**What You Can Do:**
-
-- **Capture Moments:** This custom Flipper Zero application empowers you to take pictures effortlessly. View real-time image previews on your Flipper Zero screen while you capture high quality blocky and pixelated memories! Hey it's still a memory and we're at least having fun...
-
-- **Personalize Your Experience:** Tailor your camera settings with ease. Adjust camera orientation, experiment with various dithering options, and toggle flash, haptic feedback, sound effects, and LED effects to match your preferences. Feel free to use this as a flashlight too, it's pretty bright and good at blinding yourself unexpectedly!
-
-There will be many more features added in the future! If you have any ideas or suggestions, please let me know by opening an issue [here][issues-link].
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Hardware Requirements <a name="hardware-requirements"></a>
-
-Requires an ESP32-CAM module. Below are two images of the ESP32-CAM module. You can find these all over Amazon, Ali Express, and other retailers.
-
-<img src=".github/images/esp32-cam-front.png" /><img src=".github/images/esp32-cam-back.png" />
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Hardware Installation <a name="hardware-installation"></a>
-
-Below is the pinout guide and diagram for the ESP32-CAM module to the Flipper Zero. From the ESP32-CAM module to the Flipper Zero:
-
-```markdown
-VCC to 3V3
-GND to GND (Be sure to use the right GND, see image below.)
-U0R to TX
-U0T to RX
-```
-
-On the ESP32-CAM module itself you'll also need to connect the `IO0` pin to `GND`. This will place the module into flash mode for installing the firmware later on (see [Firmware Installation](#firmware-installation)). You can do this by connecting a jumper wire, a button, or a switch to do this.
-
-<img align="center" src=".github/images/esp32-cam-pinout-guide.png" />
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Firmware Installation <a name="firmware-installation"></a>
-
-The firmware is the software that runs on the ESP32-CAM module. It is required to use the camera module with your Flipper Zero. There are two ways to install the firmware, the new, easy way, and the old, hard way. The new way is a script that will do everything for you, the old way is a manual process that requires you to install the Arduino IDE and manually flash the firmware to the ESP32-CAM module. I recommend the new way, but if you have issues with it, try the old way.
-
-<details>
-
-<summary>Simple Installation - Firmware Flashing Utility</summary>
-
-### Firmware Flashing Utility (Windows 10+ batch script)
-
-1. Download/clone this repository to your computer.
-2. Run the script found at the root of this directory: `firmware-flash.bat`.
-3. Follow the on screen instructions to continue to flash the firmware to your ESP32-CAM module.
-
-That's it, let me know if you have any issues!
-
-</details>
-
-<details>
-
-<summary>Involved Installation - Manually flash with Arduino IDE</summary>
-
-### Arduino IDE
-
-1. Clone/download this repository to your computer.
-2. Download and install the Arduino IDE from [here][arduino-ide].
-3. Open `flipper-zero-camera-suite\firmware\firmware.ino` with your Arduino IDE.
-4. In the Arduino IDE, go to `File > Preferences`.
-5. In the `Settings` tab, add the following URL to the `Additional Boards Manager URLs` field:
-
-   ```markdown
-   https://dl.espressif.com/dl/package_esp32_index.json
-   ```
-   
-6. In the Arduino IDE, go to `Tools > Board > Boards Manager`.
-7. Search for `esp32` and install `esp32` by `Espressif Systems`.
-8. Plug in your Flipper Zero via USB. Make sure qFlipper or something else isn't connected to it already after doing so.
-9. On your Flipper Zero, open `GPIO > USB-UART Bridge`.
-10. In the Arduino IDE, go to `Tools > Board > esp32 > AI Thinker ESP32-CAM`.
-11. In the Arduino IDE, go to `Tools > Port` and select the port that your Flipper Zero is connected to.
-12. Plug in the ESP32-CAM module to your Flipper Zero while connecting the `IO0` pin to `GND`. See [Hardware Installation](#hardware-installation) for more information.
-13. Press the RST button on the back of the ESP32-CAM module to boot it into flash mode.
-14. In the Arduino IDE, go to `Sketch > Upload` to upload the firmware to your ESP32-CAM module. You will see upload progress in % and receive a message on completion if successful.
-15. Fin! Now you may use the [Software Installation](#software-installation) section to install the software on your Flipper Zero to take advantage of this hardwares firmware.
-
-Note the upload may fail a few times, this is normal, try again. If it still fails, try pressing the RST button on the back of the ESP32-CAM module again or checking your connections.
-
-On success, your screen should look like this:
-
-<img align="center" src=".github/images/firmware-build-success.png" />
-
-</details>
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Software Installation <a name="software-installation"></a>
-
-Below are two ways to install the software on your Flipper Zero. The first way is the simple way, the second way is the involved way. The simple way is to install the fap file via the Flipper Zero application catalog. The involved way is to manually install the fap file to your Flipper Zero MicroSD card.
-
-<details>
-
-<summary>Simple Installation - Flipper Zero Application Catalog</summary>
-
-### Flipper Zero Application Catalog
-
-This fap app is available on your phones Flipper Zero application catalog! Simply open the Flipper Zero app on your phone, go to the "Applications" tab, and search for "Camera Suite". Install it and you're good to go! More information about Flipper Zero applications can be found [here][flipper-zero-apps].
-
-</details>
-
-<details>
-
-<summary>Involved Installation - Manually Install Files</summary>
-
-### Manually Install Files
-
-1. Connect your Flipper Zero via USB, or insert your MicroSD.
-2. Navigate to the latest GitHub "Build + upload" action [here][github-actions-link].
-3. Open the most recent action on that page (top of the list) and download the fap zip for either "dev" or "release" build versions of the Flipper Zero firmware depending on your usage. Generally you'll want to use the "release" build version.
-4. Move "camera_suite.fap" into `~\apps\gpio\` on your Flipper Zero MicroSD:
-
-   ```markdown
-   .                            # The Flipper Zero MicroSD root.
-   ├── apps                     # The Flipper Zero Applications folder.
-   |   ├── gpio                 # The Flipper Zero GPIO folder.
-   |   |   ├── camera_suite.fap # The Camera Suite application.
-   ```
-
-5. Reinsert your MicroSD into your Flipper Zero if you took it out.
-6. Plug in your ESP32-CAM module to your Flipper Zero.
-7. Press the "Power" button on your Flipper Zero to turn it on.
-8. Open the application "[ESP32] Camera Suite":
-
-   ```markdown
-   Applications > GPIO > [ESP32] Camera Suite
-   ```
-
-9. That's it! Follow the on screen instructions to continue.
-
-</details>
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Software Guide <a name="software-guide"></a>
-
-### Flipper Zero button mappings
-
-🔼 = Contrast Up
-
-🔽 = Contrast Down
-
-◀️ = Toggle invert.
-
-▶️ = Toggle dithering on/off.
-
-↩️ = Go back.
-
-🔵 = Take a picture and save to the "DCIM" folder at the root of your SD card. Image will be saved as a bitmap file with a timestamp as the filename ("YYYYMMDD-HHMMSS.bmp"). If flash is on in the settings (enabled by default) the ESP32-CAM onboard LED will light up when the camera is opened.
-
-### Camera Suite settings
-
-**Orientation:** Rotate the camera image 90 degrees counter-clockwise starting at zero by default (0, 90, 180, 270). This is useful if you have your camera module mounted in a different orientation than the default.
-
-**Dithering Type:** Change between the Cycle Floyd–Steinberg, Jarvis-Judice-Ninke, and Stucki dithering types.
-
-**Flash:** Toggle the ESP32-CAM onboard LED on/off while using the camera.
-
-**Haptic FX:** Toggle haptic feedback on/off.
-
-**Sound FX:** Toggle sound effects on/off.
-
-**LED FX:** Toggle LED effects on/off.
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Attributions <a name="attributions"></a>
-
-This project is based on/forked from the [Flipper Zero Camera Application][flipperzero-camera]
-by [Z4urce][github-profile-z4urce] combined with the [Flipper Zero Boilerplate Application][flipper-zero-fap-boilerplate]
-by [Dave Lee][github-profile-leedave].
-
-The firmware provided here also works with Z4urce's [Flipper Zero Camera Application][flipperzero-camera] so if you have their application installed it too should work fine.
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-## Contributions <a name="contributions"></a>
-
-1. Fork.
-2. Create a new branch: `<username>/[<issue-#>]-<feature-or-bug-fix-desc>`
-3. Program. Commit changes, push.
-4. Request PR [here][pull-request-link], introduce work via your branch.
-5. Wait for review and merge.
-
-Thank you!
-
-<p align="right">[ <a href="#index">Back to top</a> ]</p>
-
-Donations are welcome and appreciated!
-
-| Type                                                           | Info                                                                               |
-| :------------------------------------------------------------- | :--------------------------------------------------------------------------------- |
-| <img width="48" src=".github/ng-icons/email.svg" />            | webmaster@codytolene.com                                                           |
-| <img width="48" src=".github/simple-icons/buymeacoffee.svg" /> | https://www.buymeacoffee.com/codytolene                                            |
-| <img width="48" src=".github/images/bitcoin-btc-logo.svg" />   | [bc1qfx3lvspkj0q077u3gnrnxqkqwyvcku2nml86wmudy7yf2u8edmqq0a5vnt][btc-address-link] |
-
-Fin. Thanks for looking and happy programming friend!
-
-Cody
-
-<!-- LINKS -->
-
-[arduino-ide]: https://www.arduino.cc/en/software
-[btc-address-link]: https://explorer.btc.com/btc/address/bc1qfx3lvspkj0q077u3gnrnxqkqwyvcku2nml86wmudy7yf2u8edmqq0a5vnt
-[flipper-zero-apps]: https://docs.flipper.net/apps
-[flipper-zero-fap-boilerplate]: https://github.com/leedave/flipper-zero-fap-boilerplate
-[flipperzero-camera]: https://github.com/Z4urce/flipperzero-camera
-[github-actions-link]: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/actions?query=workflow%3A%22Build+%2B+upload.%22
-[github-profile-leedave]: https://github.com/leedave
-[github-profile-z4urce]: https://github.com/Z4urce
-[issues-link]: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues
-[pull-request-link]: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/pulls

+ 0 - 27
.modules/camera_suite/arduino-cli.yaml

@@ -1,27 +0,0 @@
-board_manager:
-  additional_urls:
-  - https://dl.espressif.com/dl/package_esp32_index.json
-build_cache:
-  compilations_before_purge: 10
-  ttl: 720h0m0s
-daemon:
-  port: "50051"
-directories:
-  data: C:\temp\arduino-cli\data
-  downloads: C:\temp\arduino-cli\downloads
-  user: C:\temp\arduino-cli\user
-library:
-  enable_unsafe_install: false
-logging:
-  file: ""
-  format: text
-  level: info
-metrics:
-  addr: :9090
-  enabled: true
-output:
-  no_color: false
-sketch:
-  always_export_binaries: false
-updater:
-  enable_notification: true

+ 0 - 16
.modules/camera_suite/fap/application.fam

@@ -1,16 +0,0 @@
-App(
-    appid="camera_suite",
-    apptype=FlipperAppType.EXTERNAL,
-    cdefines=["APP_CAMERA_SUITE"],
-    entry_point="camera_suite_app",
-    fap_author="@CodyTolene @Z4urce @leedave",
-    fap_category="GPIO",
-    fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.",
-    fap_icon="icons/camera_suite.png",
-    fap_version="1.3",
-    fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam",
-    name="[ESP32] Camera Suite",
-    order=1,
-    requires=["gui", "storage"],
-    stack_size=8 * 1024,
-)

+ 0 - 135
.modules/camera_suite/fap/camera_suite.c

@@ -1,135 +0,0 @@
-#include "camera_suite.h"
-#include <stdlib.h>
-
-bool camera_suite_custom_event_callback(void* context, uint32_t event) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    return scene_manager_handle_custom_event(app->scene_manager, event);
-}
-
-void camera_suite_tick_event_callback(void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    scene_manager_handle_tick_event(app->scene_manager);
-}
-
-// Leave app if back button pressed.
-bool camera_suite_navigation_event_callback(void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    return scene_manager_handle_back_event(app->scene_manager);
-}
-
-CameraSuite* camera_suite_app_alloc() {
-    CameraSuite* app = malloc(sizeof(CameraSuite));
-    app->gui = furi_record_open(RECORD_GUI);
-    app->notification = furi_record_open(RECORD_NOTIFICATION);
-
-    // Turn backlight on.
-    notification_message(app->notification, &sequence_display_backlight_on);
-
-    // Scene additions
-    app->view_dispatcher = view_dispatcher_alloc();
-    view_dispatcher_enable_queue(app->view_dispatcher);
-
-    app->scene_manager = scene_manager_alloc(&camera_suite_scene_handlers, app);
-    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
-    view_dispatcher_set_navigation_event_callback(
-        app->view_dispatcher, camera_suite_navigation_event_callback);
-    view_dispatcher_set_tick_event_callback(
-        app->view_dispatcher, camera_suite_tick_event_callback, 100);
-    view_dispatcher_set_custom_event_callback(
-        app->view_dispatcher, camera_suite_custom_event_callback);
-    app->submenu = submenu_alloc();
-
-    // Set defaults, in case no config loaded
-    app->orientation = 0; // Orientation is "portrait", zero degrees by default.
-    app->dither = 0; // Dither algorithm is "Floyd Steinberg" by default.
-    app->flash = 1; // Flash is enabled by default.
-    app->haptic = 1; // Haptic is enabled by default
-    app->jpeg = 0; // Save JPEG to ESP32-CAM sd-card is disabled by default.
-    app->speaker = 1; // Speaker is enabled by default
-    app->led = 1; // LED is enabled by default
-
-    // Load configs
-    camera_suite_read_settings(app);
-
-    view_dispatcher_add_view(
-        app->view_dispatcher, CameraSuiteViewIdMenu, submenu_get_view(app->submenu));
-
-    app->camera_suite_view_start = camera_suite_view_start_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher,
-        CameraSuiteViewIdStartscreen,
-        camera_suite_view_start_get_view(app->camera_suite_view_start));
-
-    app->camera_suite_view_camera = camera_suite_view_camera_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher,
-        CameraSuiteViewIdCamera,
-        camera_suite_view_camera_get_view(app->camera_suite_view_camera));
-
-    app->camera_suite_view_guide = camera_suite_view_guide_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher,
-        CameraSuiteViewIdGuide,
-        camera_suite_view_guide_get_view(app->camera_suite_view_guide));
-
-    app->button_menu = button_menu_alloc();
-
-    app->variable_item_list = variable_item_list_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher,
-        CameraSuiteViewIdSettings,
-        variable_item_list_get_view(app->variable_item_list));
-
-    //End Scene Additions
-
-    return app;
-}
-
-void camera_suite_app_free(CameraSuite* app) {
-    furi_assert(app);
-
-    // Scene manager
-    scene_manager_free(app->scene_manager);
-
-    // View Dispatcher
-    view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdStartscreen);
-    view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdMenu);
-    view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdCamera);
-    view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdGuide);
-    view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdSettings);
-    submenu_free(app->submenu);
-
-    view_dispatcher_free(app->view_dispatcher);
-    furi_record_close(RECORD_GUI);
-
-    // Free remaining resources
-    camera_suite_view_start_free(app->camera_suite_view_start);
-    camera_suite_view_camera_free(app->camera_suite_view_camera);
-    camera_suite_view_guide_free(app->camera_suite_view_guide);
-    button_menu_free(app->button_menu);
-    variable_item_list_free(app->variable_item_list);
-
-    app->gui = NULL;
-    app->notification = NULL;
-
-    //Remove whatever is left
-    free(app);
-}
-
-/** Main entry point for initialization. */
-int32_t camera_suite_app(void* p) {
-    UNUSED(p);
-    CameraSuite* app = camera_suite_app_alloc();
-    view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
-    // Init with start scene.
-    scene_manager_next_scene(app->scene_manager, CameraSuiteSceneStart);
-    furi_hal_power_suppress_charge_enter();
-    view_dispatcher_run(app->view_dispatcher);
-    camera_suite_save_settings(app);
-    furi_hal_power_suppress_charge_exit();
-    camera_suite_app_free(app);
-    return 0;
-}

+ 0 - 86
.modules/camera_suite/fap/camera_suite.h

@@ -1,86 +0,0 @@
-#pragma once
-
-#include "helpers/camera_suite_storage.h"
-#include "scenes/camera_suite_scene.h"
-#include "views/camera_suite_view_guide.h"
-#include "views/camera_suite_view_start.h"
-#include "views/camera_suite_view_camera.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <gui/modules/button_menu.h>
-#include <gui/modules/submenu.h>
-#include <gui/modules/variable_item_list.h>
-#include <gui/scene_manager.h>
-#include <gui/view_dispatcher.h>
-#include <input/input.h>
-#include <notification/notification_messages.h>
-#include <stdlib.h>
-
-#define TAG "Camera Suite"
-
-typedef struct {
-    Gui* gui;
-    NotificationApp* notification;
-    ViewDispatcher* view_dispatcher;
-    Submenu* submenu;
-    SceneManager* scene_manager;
-    VariableItemList* variable_item_list;
-    CameraSuiteViewStart* camera_suite_view_start;
-    CameraSuiteViewCamera* camera_suite_view_camera;
-    CameraSuiteViewGuide* camera_suite_view_guide;
-    uint32_t orientation;
-    uint32_t dither;
-    uint32_t flash;
-    uint32_t haptic;
-    uint32_t jpeg;
-    uint32_t speaker;
-    uint32_t led;
-    ButtonMenu* button_menu;
-} CameraSuite;
-
-typedef enum {
-    CameraSuiteViewIdStartscreen,
-    CameraSuiteViewIdMenu,
-    CameraSuiteViewIdCamera,
-    CameraSuiteViewIdGuide,
-    CameraSuiteViewIdSettings,
-} CameraSuiteViewId;
-
-typedef enum {
-    CameraSuiteOrientation0,
-    CameraSuiteOrientation90,
-    CameraSuiteOrientation180,
-    CameraSuiteOrientation270,
-} CameraSuiteOrientationState;
-
-typedef enum {
-    CameraSuiteDitherFloydSteinberg,
-    CameraSuiteDitherStucki,
-    CameraSuiteDitherJarvisJudiceNinke,
-} CameraSuiteDitherState;
-
-typedef enum {
-    CameraSuiteFlashOff,
-    CameraSuiteFlashOn,
-} CameraSuiteFlashState;
-
-typedef enum {
-    CameraSuiteJpegOff,
-    CameraSuiteJpegOn,
-} CameraSuiteJpegState;
-
-typedef enum {
-    CameraSuiteHapticOff,
-    CameraSuiteHapticOn,
-} CameraSuiteHapticState;
-
-typedef enum {
-    CameraSuiteSpeakerOff,
-    CameraSuiteSpeakerOn,
-} CameraSuiteSpeakerState;
-
-typedef enum {
-    CameraSuiteLedOff,
-    CameraSuiteLedOn,
-} CameraSuiteLedState;

+ 0 - 48
.modules/camera_suite/fap/docs/CHANGELOG.md

@@ -1,48 +0,0 @@
-## Roadmap
-
-- Store images to onboard ESP32-CAM SD card (currently in progress, #24).
-- Camera preview GUI overlay (#21).
-- Full screen 90 degree and 270 degree fill (#6).
-
-## v1.3 (current)
-
-- Important: Firmware Update Required! Ensure you update your firmware to fully utilize the new features. Backwards compatibility should be ok.
-- New Feature: Introducing the Firmware Flash utility, simplifying the firmware flashing process. Refer to the project readme for detailed instructions. (Closes #26)
-- Enhancement: Flash functionality now remains active during camera preview, making it easier to take pictures in areas of low light.
-- Bug Fix: Addressed picture inversion issue reported by user leedave. Thanks for your contribution! (Closes #23)
-- Code Refinement: Enhanced firmware code for readability and maintainability. Separated concerns into individual files for a more organized structure.
-- Technical Improvements: Implemented general code enhancements and introduced syntactic sugar for cleaner, more efficient code.
-- Work in Progress: Added a new test function for saving pictures to the onboard ESP32-CAM SD card. This feature is under development and will allow users to save pictures directly to the SD card in the future. Tracked under feature request #24.
-
-## v1.2
-
-- Save image support. When the center button is pressed take a picture and save it to the "DCIM" folder at the root of your SD card. The image will be saved as a bitmap file with a timestamp as the filename ("YYYYMMDD-HHMMSS.bmp").
-- Camera flash support. Flashes the ESP32-CAM onboard LED when a picture is taken if enabled in the settings.
-- Move the camera dithering type to the settings scene as a new configurable option.
-- Add "Flash" option to the settings scene as a new configurable option.
-- Update documentation to reflect changes.
-- Update firmware with new dithering options set.
-- Update firmware with new flash support.
-- Update repo to reflect https://github.com/CodyTolene/Flipper-Zero-Development-Toolkit for easier tooling.
-
-## v1.1
-
-- Support and picture stabilization for all camera orientations (0 degree, 90 degree, 180 degree, and 270 degree).
-- Rename "Scene 1" to "Camera". No UX changes there.
-- Clean up unused "Scene 2". This was inaccessible to users previously and unused.
-- Add new dithering variations (requires the latest firmware installation, see here for the installation guide https://github.com/CodyTolene/Flipper-Zero-Camera-Suite#firmware-installation):
-  - "Jarvis Judice Ninke" dithering option
-  - "Stucki" dithering option.
-  - "Floyd-Steinberg" dithering option.
-  - Cycle through the dithering options with the center button on the Flipper Zero.
-- Resolves issue https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues/7
-- Resolves issue https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/pull/17
-
-## v1.0
-
-- Builds upon Z4urce's software found here (updated 6 months ago): https://github.com/Z4urce/flipperzero-camera
-- Utilizes the superb C boilerplate examples laid out by leedave (updated last month): https://github.com/leedave/flipper-zero-fap-boilerplate
-- Builds upon the "Camera" software into the new "Camera Suite" application with new usage:
-  - Add a scene for a guide.
-  - Add a scene for settings.
-  - Add ability to rotate the camera orientation.

+ 0 - 37
.modules/camera_suite/fap/docs/README.md

@@ -1,37 +0,0 @@
-## Flipper Zero - Camera Suite
-
-Software to run an ESP32-CAM module on your Flipper Zero device.
-
-Full setup, wiring guide, etc. in the main project README here: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite
-
-Firmware is needed for the ESP32-CAM module, see here for more information: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite#firmware-installation
-
-## Software Guide
-
-Button mappings:
-
-**Up** = Contrast Up
-
-**Down** = Contrast Down
-
-**Left** = Toggle invert.
-
-**Right** = Toggle dithering on/off.
-
-**Center** = Take a picture and save to the "DCIM" folder at the root of your SD card. Image will be saved as a bitmap file with a timestamp as the filename ("YYYYMMDD-HHMMSS.bmp"). If flash is on in the settings (enabled by default) the ESP32-CAM onboard LED will light up when the picture is taken.
-
-**Back** = Go back.
-
-Settings:
-
-**Orientation** = Rotate the camera image 90 degrees counter-clockwise starting at zero by default (0, 90, 180, 270). This is useful if you have your camera module mounted in a different orientation than the default.
-
-**Flash** Toggle the ESP32-CAM onboard LED on/off when taking a picture.
-
-**Dithering Type** Change between the Cycle Floyd–Steinberg, Jarvis-Judice-Ninke, and Stucki dithering types.
-
-**Haptic FX** = Toggle haptic feedback on/off.
-
-**Sound FX** = Toggle sound effects on/off.
-
-**LED FX** = Toggle LED effects on/off.

+ 0 - 67
.modules/camera_suite/fap/helpers/camera_suite_custom_event.h

@@ -1,67 +0,0 @@
-#pragma once
-
-typedef enum {
-    // Scene events: Start menu
-    CameraSuiteCustomEventStartUp,
-    CameraSuiteCustomEventStartDown,
-    CameraSuiteCustomEventStartLeft,
-    CameraSuiteCustomEventStartRight,
-    CameraSuiteCustomEventStartOk,
-    CameraSuiteCustomEventStartBack,
-    // Scene events: Camera
-    CameraSuiteCustomEventSceneCameraUp,
-    CameraSuiteCustomEventSceneCameraDown,
-    CameraSuiteCustomEventSceneCameraLeft,
-    CameraSuiteCustomEventSceneCameraRight,
-    CameraSuiteCustomEventSceneCameraOk,
-    CameraSuiteCustomEventSceneCameraBack,
-    // Scene events: Guide
-    CameraSuiteCustomEventSceneGuideUp,
-    CameraSuiteCustomEventSceneGuideDown,
-    CameraSuiteCustomEventSceneGuideLeft,
-    CameraSuiteCustomEventSceneGuideRight,
-    CameraSuiteCustomEventSceneGuideOk,
-    CameraSuiteCustomEventSceneGuideBack,
-} CameraSuiteCustomEvent;
-
-enum CameraSuiteCustomEventType {
-    // Reserve first 100 events for button types and indexes, starting from 0.
-    CameraSuiteCustomEventMenuVoid,
-    CameraSuiteCustomEventMenuSelected,
-};
-
-#pragma pack(push, 1)
-
-typedef union {
-    uint32_t packed_value;
-    struct {
-        uint16_t type;
-        int16_t value;
-    } content;
-} CameraSuiteCustomEventMenu;
-
-#pragma pack(pop)
-
-static inline uint32_t camera_suite_custom_menu_event_pack(uint16_t type, int16_t value) {
-    CameraSuiteCustomEventMenu event = {.content = {.type = type, .value = value}};
-    return event.packed_value;
-}
-
-static inline void
-    camera_suite_custom_menu_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) {
-    CameraSuiteCustomEventMenu event = {.packed_value = packed_value};
-    if(type) *type = event.content.type;
-    if(value) *value = event.content.value;
-}
-
-static inline uint16_t camera_suite_custom_menu_event_get_type(uint32_t packed_value) {
-    uint16_t type;
-    camera_suite_custom_menu_event_unpack(packed_value, &type, NULL);
-    return type;
-}
-
-static inline int16_t camera_suite_custom_menu_event_get_value(uint32_t packed_value) {
-    int16_t value;
-    camera_suite_custom_menu_event_unpack(packed_value, NULL, &value);
-    return value;
-}

+ 0 - 35
.modules/camera_suite/fap/helpers/camera_suite_haptic.c

@@ -1,35 +0,0 @@
-#include "camera_suite_haptic.h"
-#include "../camera_suite.h"
-
-void camera_suite_play_happy_bump(void* context) {
-    CameraSuite* app = context;
-    if(app->haptic != 1) {
-        return;
-    }
-    notification_message(app->notification, &sequence_set_vibro_on);
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 20);
-    notification_message(app->notification, &sequence_reset_vibro);
-}
-
-void camera_suite_play_bad_bump(void* context) {
-    CameraSuite* app = context;
-    if(app->haptic != 1) {
-        return;
-    }
-    notification_message(app->notification, &sequence_set_vibro_on);
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 100);
-    notification_message(app->notification, &sequence_reset_vibro);
-}
-
-void camera_suite_play_long_bump(void* context) {
-    CameraSuite* app = context;
-    if(app->haptic != 1) {
-        return;
-    }
-    for(int i = 0; i < 4; i++) {
-        notification_message(app->notification, &sequence_set_vibro_on);
-        furi_thread_flags_wait(0, FuriFlagWaitAny, 50);
-        notification_message(app->notification, &sequence_reset_vibro);
-        furi_thread_flags_wait(0, FuriFlagWaitAny, 100);
-    }
-}

+ 0 - 7
.modules/camera_suite/fap/helpers/camera_suite_haptic.h

@@ -1,7 +0,0 @@
-#include <notification/notification_messages.h>
-
-void camera_suite_play_happy_bump(void* context);
-
-void camera_suite_play_bad_bump(void* context);
-
-void camera_suite_play_long_bump(void* context);

+ 0 - 38
.modules/camera_suite/fap/helpers/camera_suite_led.c

@@ -1,38 +0,0 @@
-#include "camera_suite_led.h"
-#include "../camera_suite.h"
-
-void camera_suite_led_set_rgb(void* context, int red, int green, int blue) {
-    CameraSuite* app = context;
-    if(app->led != 1) {
-        return;
-    }
-    NotificationMessage notification_led_message_1;
-    notification_led_message_1.type = NotificationMessageTypeLedRed;
-    NotificationMessage notification_led_message_2;
-    notification_led_message_2.type = NotificationMessageTypeLedGreen;
-    NotificationMessage notification_led_message_3;
-    notification_led_message_3.type = NotificationMessageTypeLedBlue;
-
-    notification_led_message_1.data.led.value = red;
-    notification_led_message_2.data.led.value = green;
-    notification_led_message_3.data.led.value = blue;
-    const NotificationSequence notification_sequence = {
-        &notification_led_message_1,
-        &notification_led_message_2,
-        &notification_led_message_3,
-        &message_do_not_reset,
-        NULL,
-    };
-    notification_message(app->notification, &notification_sequence);
-    //Delay, prevent removal from RAM before LED value set.
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 10);
-}
-
-void camera_suite_led_reset(void* context) {
-    CameraSuite* app = context;
-    notification_message(app->notification, &sequence_reset_red);
-    notification_message(app->notification, &sequence_reset_green);
-    notification_message(app->notification, &sequence_reset_blue);
-    //Delay, prevent removal from RAM before LED value set.
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 300);
-}

+ 0 - 3
.modules/camera_suite/fap/helpers/camera_suite_led.h

@@ -1,3 +0,0 @@
-void camera_suite_led_set_rgb(void* context, int red, int green, int blue);
-
-void camera_suite_led_reset(void* context);

+ 0 - 26
.modules/camera_suite/fap/helpers/camera_suite_speaker.c

@@ -1,26 +0,0 @@
-#include "camera_suite_speaker.h"
-#include "../camera_suite.h"
-
-#define NOTE_INPUT 587.33f
-
-void camera_suite_play_input_sound(void* context) {
-    CameraSuite* app = context;
-    if(app->speaker != 1) {
-        return;
-    }
-    float volume = 1.0f;
-    if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
-        furi_hal_speaker_start(NOTE_INPUT, volume);
-    }
-}
-
-void camera_suite_stop_all_sound(void* context) {
-    CameraSuite* app = context;
-    if(app->speaker != 1) {
-        return;
-    }
-    if(furi_hal_speaker_is_mine()) {
-        furi_hal_speaker_stop();
-        furi_hal_speaker_release();
-    }
-}

+ 0 - 5
.modules/camera_suite/fap/helpers/camera_suite_speaker.h

@@ -1,5 +0,0 @@
-#define NOTE_INPUT 587.33f
-
-void camera_suite_play_input_sound(void* context);
-
-void camera_suite_stop_all_sound(void* context);

+ 0 - 120
.modules/camera_suite/fap/helpers/camera_suite_storage.c

@@ -1,120 +0,0 @@
-#include "camera_suite_storage.h"
-
-static Storage* camera_suite_open_storage() {
-    return furi_record_open(RECORD_STORAGE);
-}
-
-static void camera_suite_close_storage() {
-    furi_record_close(RECORD_STORAGE);
-}
-
-static void camera_suite_close_config_file(FlipperFormat* file) {
-    if(file == NULL) return;
-    flipper_format_file_close(file);
-    flipper_format_free(file);
-}
-
-void camera_suite_save_settings(void* context) {
-    CameraSuite* app = context;
-
-    FURI_LOG_D(TAG, "Saving Settings");
-    Storage* storage = camera_suite_open_storage();
-    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
-
-    // Overwrite wont work, so delete first
-    if(storage_file_exists(storage, BOILERPLATE_SETTINGS_SAVE_PATH)) {
-        storage_simply_remove(storage, BOILERPLATE_SETTINGS_SAVE_PATH);
-    }
-
-    // Open File, create if not exists
-    if(!storage_common_stat(storage, BOILERPLATE_SETTINGS_SAVE_PATH, NULL) == FSE_OK) {
-        FURI_LOG_D(
-            TAG, "Config file %s is not found. Will create new.", BOILERPLATE_SETTINGS_SAVE_PATH);
-        if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
-            FURI_LOG_D(
-                TAG, "Directory %s doesn't exist. Will create new.", CONFIG_FILE_DIRECTORY_PATH);
-            if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
-                FURI_LOG_E(TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
-            }
-        }
-    }
-
-    if(!flipper_format_file_open_new(fff_file, BOILERPLATE_SETTINGS_SAVE_PATH)) {
-        //totp_close_config_file(fff_file);
-        FURI_LOG_E(TAG, "Error creating new file %s", BOILERPLATE_SETTINGS_SAVE_PATH);
-        camera_suite_close_storage();
-        return;
-    }
-
-    // Store Settings
-    flipper_format_write_header_cstr(
-        fff_file, BOILERPLATE_SETTINGS_HEADER, BOILERPLATE_SETTINGS_FILE_VERSION);
-    flipper_format_write_uint32(
-        fff_file, BOILERPLATE_SETTINGS_KEY_ORIENTATION, &app->orientation, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_DITHER, &app->dither, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_FLASH, &app->flash, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_JPEG, &app->jpeg, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
-    flipper_format_write_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_LED, &app->led, 1);
-
-    if(!flipper_format_rewind(fff_file)) {
-        camera_suite_close_config_file(fff_file);
-        FURI_LOG_E(TAG, "Rewind error");
-        camera_suite_close_storage();
-        return;
-    }
-
-    camera_suite_close_config_file(fff_file);
-    camera_suite_close_storage();
-}
-
-void camera_suite_read_settings(void* context) {
-    CameraSuite* app = context;
-    Storage* storage = camera_suite_open_storage();
-    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
-
-    if(storage_common_stat(storage, BOILERPLATE_SETTINGS_SAVE_PATH, NULL) != FSE_OK) {
-        camera_suite_close_config_file(fff_file);
-        camera_suite_close_storage();
-        return;
-    }
-    uint32_t file_version;
-    FuriString* temp_str = furi_string_alloc();
-
-    if(!flipper_format_file_open_existing(fff_file, BOILERPLATE_SETTINGS_SAVE_PATH)) {
-        FURI_LOG_E(TAG, "Cannot open file %s", BOILERPLATE_SETTINGS_SAVE_PATH);
-        camera_suite_close_config_file(fff_file);
-        camera_suite_close_storage();
-        return;
-    }
-
-    if(!flipper_format_read_header(fff_file, temp_str, &file_version)) {
-        FURI_LOG_E(TAG, "Missing Header Data");
-        camera_suite_close_config_file(fff_file);
-        camera_suite_close_storage();
-        return;
-    }
-
-    if(file_version < BOILERPLATE_SETTINGS_FILE_VERSION) {
-        FURI_LOG_I(TAG, "old config version, will be removed.");
-        camera_suite_close_config_file(fff_file);
-        camera_suite_close_storage();
-        return;
-    }
-
-    // Read settings
-    flipper_format_read_uint32(
-        fff_file, BOILERPLATE_SETTINGS_KEY_ORIENTATION, &app->orientation, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_DITHER, &app->dither, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_FLASH, &app->flash, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_JPEG, &app->jpeg, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
-    flipper_format_read_uint32(fff_file, BOILERPLATE_SETTINGS_KEY_LED, &app->led, 1);
-
-    flipper_format_rewind(fff_file);
-
-    camera_suite_close_config_file(fff_file);
-    camera_suite_close_storage();
-}

+ 0 - 23
.modules/camera_suite/fap/helpers/camera_suite_storage.h

@@ -1,23 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <storage/storage.h>
-#include <flipper_format/flipper_format_i.h>
-#include "../camera_suite.h"
-
-#define BOILERPLATE_SETTINGS_FILE_VERSION 1
-#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/camera_suite")
-#define BOILERPLATE_SETTINGS_SAVE_PATH CONFIG_FILE_DIRECTORY_PATH "/camera_suite.conf"
-#define BOILERPLATE_SETTINGS_SAVE_PATH_TMP BOILERPLATE_SETTINGS_SAVE_PATH ".tmp"
-#define BOILERPLATE_SETTINGS_HEADER "Camera Suite Config File"
-#define BOILERPLATE_SETTINGS_KEY_ORIENTATION "Orientation"
-#define BOILERPLATE_SETTINGS_KEY_DITHER "Dither"
-#define BOILERPLATE_SETTINGS_KEY_FLASH "Flash"
-#define BOILERPLATE_SETTINGS_KEY_JPEG "SaveJPEG"
-#define BOILERPLATE_SETTINGS_KEY_HAPTIC "Haptic"
-#define BOILERPLATE_SETTINGS_KEY_LED "Led"
-#define BOILERPLATE_SETTINGS_KEY_SPEAKER "Speaker"
-#define BOILERPLATE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings"
-
-void camera_suite_save_settings(void* context);
-
-void camera_suite_read_settings(void* context);

BIN
.modules/camera_suite/fap/icons/camera_suite.png


+ 0 - 20
.modules/camera_suite/fap/manifest.yml

@@ -1,20 +0,0 @@
-author: "@CodyTolene @Z4urce @leedave"
-category: "GPIO"
-changelog: "@./docs/CHANGELOG.md"
-description: "@./docs/README.md"
-icon: "icons/camera_suite.png"
-id: "camera_suite"
-name: "[ESP32] Camera Suite"
-screenshots:
-  - "screenshots/start_screen.png"
-  - "screenshots/main_menu.png"
-  - "screenshots/camera_preview.png"
-  - "screenshots/guide.png"
-  - "screenshots/settings.png"
-short_description: "A camera suite application for the Flipper Zero ESP32-CAM module."
-sourcecode:
-  location:
-    commit_sha: ...
-    origin: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite.git
-    subdir: fap
-  type: git

+ 0 - 30
.modules/camera_suite/fap/scenes/camera_suite_scene.c

@@ -1,30 +0,0 @@
-#include "camera_suite_scene.h"
-
-// Generate scene on_enter handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
-void (*const camera_suite_on_enter_handlers[])(void*) = {
-#include "camera_suite_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_event handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
-bool (*const camera_suite_on_event_handlers[])(void* context, SceneManagerEvent event) = {
-#include "camera_suite_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
-void (*const camera_suite_on_exit_handlers[])(void* context) = {
-#include "camera_suite_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Initialize scene handlers configuration structure
-const SceneManagerHandlers camera_suite_scene_handlers = {
-    .on_enter_handlers = camera_suite_on_enter_handlers,
-    .on_event_handlers = camera_suite_on_event_handlers,
-    .on_exit_handlers = camera_suite_on_exit_handlers,
-    .scene_num = CameraSuiteSceneNum,
-};

+ 0 - 29
.modules/camera_suite/fap/scenes/camera_suite_scene.h

@@ -1,29 +0,0 @@
-#pragma once
-
-#include <gui/scene_manager.h>
-
-// Generate scene id and total number
-#define ADD_SCENE(prefix, name, id) CameraSuiteScene##id,
-typedef enum {
-#include "camera_suite_scene_config.h"
-    CameraSuiteSceneNum,
-} CameraSuiteScene;
-#undef ADD_SCENE
-
-extern const SceneManagerHandlers camera_suite_scene_handlers;
-
-// Generate scene on_enter handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
-#include "camera_suite_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_event handlers declaration
-#define ADD_SCENE(prefix, name, id) \
-    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
-#include "camera_suite_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
-#include "camera_suite_scene_config.h"
-#undef ADD_SCENE

+ 0 - 52
.modules/camera_suite/fap/scenes/camera_suite_scene_camera.c

@@ -1,52 +0,0 @@
-#include "../camera_suite.h"
-#include "../helpers/camera_suite_custom_event.h"
-#include "../views/camera_suite_view_camera.h"
-
-void camera_suite_view_camera_callback(CameraSuiteCustomEvent event, void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, event);
-}
-
-void camera_suite_scene_camera_on_enter(void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    camera_suite_view_camera_set_callback(
-        app->camera_suite_view_camera, camera_suite_view_camera_callback, app);
-    view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdCamera);
-}
-
-bool camera_suite_scene_camera_on_event(void* context, SceneManagerEvent event) {
-    CameraSuite* app = context;
-    bool consumed = false;
-
-    if(event.type == SceneManagerEventTypeCustom) {
-        switch(event.event) {
-        case CameraSuiteCustomEventSceneCameraLeft:
-        case CameraSuiteCustomEventSceneCameraRight:
-        case CameraSuiteCustomEventSceneCameraUp:
-        case CameraSuiteCustomEventSceneCameraDown:
-        case CameraSuiteCustomEventSceneCameraOk:
-            // Do nothing.
-            break;
-        case CameraSuiteCustomEventSceneCameraBack:
-            notification_message(app->notification, &sequence_reset_red);
-            notification_message(app->notification, &sequence_reset_green);
-            notification_message(app->notification, &sequence_reset_blue);
-            if(!scene_manager_search_and_switch_to_previous_scene(
-                   app->scene_manager, CameraSuiteSceneMenu)) {
-                scene_manager_stop(app->scene_manager);
-                view_dispatcher_stop(app->view_dispatcher);
-            }
-            consumed = true;
-            break;
-        }
-    }
-
-    return consumed;
-}
-
-void camera_suite_scene_camera_on_exit(void* context) {
-    CameraSuite* app = context;
-    UNUSED(app);
-}

+ 0 - 5
.modules/camera_suite/fap/scenes/camera_suite_scene_config.h

@@ -1,5 +0,0 @@
-ADD_SCENE(camera_suite, start, Start)
-ADD_SCENE(camera_suite, menu, Menu)
-ADD_SCENE(camera_suite, camera, Camera)
-ADD_SCENE(camera_suite, guide, Guide)
-ADD_SCENE(camera_suite, settings, Settings)

+ 0 - 51
.modules/camera_suite/fap/scenes/camera_suite_scene_guide.c

@@ -1,51 +0,0 @@
-#include "../camera_suite.h"
-#include "../helpers/camera_suite_custom_event.h"
-#include "../views/camera_suite_view_guide.h"
-
-void camera_suite_view_guide_callback(CameraSuiteCustomEvent event, void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, event);
-}
-
-void camera_suite_scene_guide_on_enter(void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    camera_suite_view_guide_set_callback(
-        app->camera_suite_view_guide, camera_suite_view_guide_callback, app);
-    view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdGuide);
-}
-
-bool camera_suite_scene_guide_on_event(void* context, SceneManagerEvent event) {
-    CameraSuite* app = context;
-    bool consumed = false;
-
-    if(event.type == SceneManagerEventTypeCustom) {
-        switch(event.event) {
-        case CameraSuiteCustomEventSceneGuideLeft:
-        case CameraSuiteCustomEventSceneGuideRight:
-        case CameraSuiteCustomEventSceneGuideUp:
-        case CameraSuiteCustomEventSceneGuideDown:
-            // Do nothing.
-            break;
-        case CameraSuiteCustomEventSceneGuideBack:
-            notification_message(app->notification, &sequence_reset_red);
-            notification_message(app->notification, &sequence_reset_green);
-            notification_message(app->notification, &sequence_reset_blue);
-            if(!scene_manager_search_and_switch_to_previous_scene(
-                   app->scene_manager, CameraSuiteSceneMenu)) {
-                scene_manager_stop(app->scene_manager);
-                view_dispatcher_stop(app->view_dispatcher);
-            }
-            consumed = true;
-            break;
-        }
-    }
-
-    return consumed;
-}
-
-void camera_suite_scene_guide_on_exit(void* context) {
-    CameraSuite* app = context;
-    UNUSED(app);
-}

+ 0 - 73
.modules/camera_suite/fap/scenes/camera_suite_scene_menu.c

@@ -1,73 +0,0 @@
-#include "../camera_suite.h"
-
-enum SubmenuIndex {
-    /** Camera. */
-    SubmenuIndexSceneCamera = 10,
-    /** Guide/how-to. */
-    SubmenuIndexGuide,
-    /** Settings menu. */
-    SubmenuIndexSettings,
-};
-
-void camera_suite_scene_menu_submenu_callback(void* context, uint32_t index) {
-    CameraSuite* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, index);
-}
-
-void camera_suite_scene_menu_on_enter(void* context) {
-    CameraSuite* app = context;
-
-    submenu_add_item(
-        app->submenu,
-        "Open Camera",
-        SubmenuIndexSceneCamera,
-        camera_suite_scene_menu_submenu_callback,
-        app);
-    submenu_add_item(
-        app->submenu, "Guide", SubmenuIndexGuide, camera_suite_scene_menu_submenu_callback, app);
-    submenu_add_item(
-        app->submenu,
-        "Settings",
-        SubmenuIndexSettings,
-        camera_suite_scene_menu_submenu_callback,
-        app);
-
-    submenu_set_selected_item(
-        app->submenu, scene_manager_get_scene_state(app->scene_manager, CameraSuiteSceneMenu));
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdMenu);
-}
-
-bool camera_suite_scene_menu_on_event(void* context, SceneManagerEvent event) {
-    CameraSuite* app = context;
-    UNUSED(app);
-    if(event.type == SceneManagerEventTypeBack) {
-        // Exit application.
-        scene_manager_stop(app->scene_manager);
-        view_dispatcher_stop(app->view_dispatcher);
-        return true;
-    } else if(event.type == SceneManagerEventTypeCustom) {
-        if(event.event == SubmenuIndexSceneCamera) {
-            scene_manager_set_scene_state(
-                app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSceneCamera);
-            scene_manager_next_scene(app->scene_manager, CameraSuiteSceneCamera);
-            return true;
-        } else if(event.event == SubmenuIndexGuide) {
-            scene_manager_set_scene_state(
-                app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexGuide);
-            scene_manager_next_scene(app->scene_manager, CameraSuiteSceneGuide);
-            return true;
-        } else if(event.event == SubmenuIndexSettings) {
-            scene_manager_set_scene_state(
-                app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSettings);
-            scene_manager_next_scene(app->scene_manager, CameraSuiteSceneSettings);
-            return true;
-        }
-    }
-    return false;
-}
-
-void camera_suite_scene_menu_on_exit(void* context) {
-    CameraSuite* app = context;
-    submenu_reset(app->submenu);
-}

+ 0 - 226
.modules/camera_suite/fap/scenes/camera_suite_scene_settings.c

@@ -1,226 +0,0 @@
-#include "../camera_suite.h"
-#include <lib/toolbox/value_index.h>
-
-// Camera orientation, in degrees.
-const char* const orientation_text[4] = {
-    "0",
-    "90",
-    "180",
-    "270",
-};
-
-const uint32_t orientation_value[4] = {
-    CameraSuiteOrientation0,
-    CameraSuiteOrientation90,
-    CameraSuiteOrientation180,
-    CameraSuiteOrientation270,
-};
-
-// Possible dithering types for the camera.
-const char* const dither_text[28] = {
-    "Floyd-Steinberg",
-    "Stucki",
-    "Jarvis-Judice-Ninke",
-};
-
-const uint32_t dither_value[4] = {
-    CameraSuiteDitherFloydSteinberg,
-    CameraSuiteDitherStucki,
-    CameraSuiteDitherJarvisJudiceNinke,
-};
-
-const char* const flash_text[2] = {
-    "OFF",
-    "ON",
-};
-
-const uint32_t flash_value[2] = {
-    CameraSuiteFlashOff,
-    CameraSuiteFlashOn,
-};
-
-const char* const jpeg_text[2] = {
-    "OFF",
-    "ON",
-};
-
-const uint32_t jpeg_value[2] = {
-    CameraSuiteJpegOff,
-    CameraSuiteJpegOn,
-};
-
-const char* const haptic_text[2] = {
-    "OFF",
-    "ON",
-};
-
-const uint32_t haptic_value[2] = {
-    CameraSuiteHapticOff,
-    CameraSuiteHapticOn,
-};
-
-const char* const speaker_text[2] = {
-    "OFF",
-    "ON",
-};
-
-const uint32_t speaker_value[2] = {
-    CameraSuiteSpeakerOff,
-    CameraSuiteSpeakerOn,
-};
-
-const char* const led_text[2] = {
-    "OFF",
-    "ON",
-};
-
-const uint32_t led_value[2] = {
-    CameraSuiteLedOff,
-    CameraSuiteLedOn,
-};
-
-static void camera_suite_scene_settings_set_camera_orientation(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, orientation_text[index]);
-    app->orientation = orientation_value[index];
-}
-
-static void camera_suite_scene_settings_set_camera_dither(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, dither_text[index]);
-    app->dither = dither_value[index];
-}
-
-static void camera_suite_scene_settings_set_flash(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, flash_text[index]);
-    app->flash = flash_value[index];
-}
-
-static void camera_suite_scene_settings_set_jpeg(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, jpeg_text[index]);
-    app->jpeg = jpeg_value[index];
-}
-
-static void camera_suite_scene_settings_set_haptic(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, haptic_text[index]);
-    app->haptic = haptic_value[index];
-}
-
-static void camera_suite_scene_settings_set_speaker(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-    variable_item_set_current_value_text(item, speaker_text[index]);
-    app->speaker = speaker_value[index];
-}
-
-static void camera_suite_scene_settings_set_led(VariableItem* item) {
-    CameraSuite* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-    variable_item_set_current_value_text(item, led_text[index]);
-    app->led = led_value[index];
-}
-
-void camera_suite_scene_settings_submenu_callback(void* context, uint32_t index) {
-    CameraSuite* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, index);
-}
-
-void camera_suite_scene_settings_on_enter(void* context) {
-    CameraSuite* app = context;
-    VariableItem* item;
-    uint8_t value_index;
-
-    // Camera Orientation
-    item = variable_item_list_add(
-        app->variable_item_list,
-        "Orientation:",
-        4,
-        camera_suite_scene_settings_set_camera_orientation,
-        app);
-    value_index = value_index_uint32(app->orientation, orientation_value, 4);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, orientation_text[value_index]);
-
-    // Camera Dither Type
-    item = variable_item_list_add(
-        app->variable_item_list,
-        "Dithering Type:",
-        3,
-        camera_suite_scene_settings_set_camera_dither,
-        app);
-    value_index = value_index_uint32(app->dither, dither_value, 3);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, dither_text[value_index]);
-
-    // Flash ON/OFF
-    item = variable_item_list_add(
-        app->variable_item_list, "Flash:", 2, camera_suite_scene_settings_set_flash, app);
-    value_index = value_index_uint32(app->flash, flash_value, 2);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, flash_text[value_index]);
-
-    // @todo - Save picture to ESP32-CAM sd-card instead of Flipper Zero
-    // sd-card. This hides the setting for it, for now.
-    // Save JPEG to ESP32-CAM sd-card instead of Flipper Zero sd-card ON/OFF
-    // item = variable_item_list_add(
-    //     app->variable_item_list,
-    //     "Save JPEG to ext sdcard:",
-    //     2,
-    //     camera_suite_scene_settings_set_jpeg,
-    //     app);
-    // value_index = value_index_uint32(app->jpeg, jpeg_value, 2);
-    // variable_item_set_current_value_index(item, value_index);
-    // variable_item_set_current_value_text(item, jpeg_text[value_index]);
-    UNUSED(camera_suite_scene_settings_set_jpeg);
-
-    // Haptic FX ON/OFF
-    item = variable_item_list_add(
-        app->variable_item_list, "Haptic FX:", 2, camera_suite_scene_settings_set_haptic, app);
-    value_index = value_index_uint32(app->haptic, haptic_value, 2);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, haptic_text[value_index]);
-
-    // Sound FX ON/OFF
-    item = variable_item_list_add(
-        app->variable_item_list, "Sound FX:", 2, camera_suite_scene_settings_set_speaker, app);
-    value_index = value_index_uint32(app->speaker, speaker_value, 2);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, speaker_text[value_index]);
-
-    // LED FX ON/OFF
-    item = variable_item_list_add(
-        app->variable_item_list, "LED FX:", 2, camera_suite_scene_settings_set_led, app);
-    value_index = value_index_uint32(app->led, led_value, 2);
-    variable_item_set_current_value_index(item, value_index);
-    variable_item_set_current_value_text(item, led_text[value_index]);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdSettings);
-}
-
-bool camera_suite_scene_settings_on_event(void* context, SceneManagerEvent event) {
-    CameraSuite* app = context;
-    UNUSED(app);
-    bool consumed = false;
-    if(event.type == SceneManagerEventTypeCustom) {
-    }
-    return consumed;
-}
-
-void camera_suite_scene_settings_on_exit(void* context) {
-    CameraSuite* app = context;
-    variable_item_list_set_selected_item(app->variable_item_list, 0);
-    variable_item_list_reset(app->variable_item_list);
-}

+ 0 - 55
.modules/camera_suite/fap/scenes/camera_suite_scene_start.c

@@ -1,55 +0,0 @@
-#include "../camera_suite.h"
-#include "../helpers/camera_suite_custom_event.h"
-#include "../views/camera_suite_view_start.h"
-
-void camera_suite_scene_start_callback(CameraSuiteCustomEvent event, void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, event);
-}
-
-void camera_suite_scene_start_on_enter(void* context) {
-    furi_assert(context);
-    CameraSuite* app = context;
-    camera_suite_view_start_set_callback(
-        app->camera_suite_view_start, camera_suite_scene_start_callback, app);
-    view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdStartscreen);
-}
-
-bool camera_suite_scene_start_on_event(void* context, SceneManagerEvent event) {
-    CameraSuite* app = context;
-    bool consumed = false;
-
-    if(event.type == SceneManagerEventTypeCustom) {
-        switch(event.event) {
-        case CameraSuiteCustomEventStartLeft:
-        case CameraSuiteCustomEventStartRight:
-        case CameraSuiteCustomEventStartUp:
-        case CameraSuiteCustomEventStartDown:
-            // Do nothing.
-            break;
-        case CameraSuiteCustomEventStartOk:
-            scene_manager_next_scene(app->scene_manager, CameraSuiteSceneMenu);
-            consumed = true;
-            break;
-        case CameraSuiteCustomEventStartBack:
-            notification_message(app->notification, &sequence_reset_red);
-            notification_message(app->notification, &sequence_reset_green);
-            notification_message(app->notification, &sequence_reset_blue);
-            if(!scene_manager_search_and_switch_to_previous_scene(
-                   app->scene_manager, CameraSuiteSceneStart)) {
-                scene_manager_stop(app->scene_manager);
-                view_dispatcher_stop(app->view_dispatcher);
-            }
-            consumed = true;
-            break;
-        }
-    }
-
-    return consumed;
-}
-
-void camera_suite_scene_start_on_exit(void* context) {
-    CameraSuite* app = context;
-    UNUSED(app);
-}

BIN
.modules/camera_suite/fap/screenshots/camera_preview.png


BIN
.modules/camera_suite/fap/screenshots/guide.png


BIN
.modules/camera_suite/fap/screenshots/main_menu.png


BIN
.modules/camera_suite/fap/screenshots/settings.png


BIN
.modules/camera_suite/fap/screenshots/start_screen.png


+ 0 - 577
.modules/camera_suite/fap/views/camera_suite_view_camera.c

@@ -1,577 +0,0 @@
-#include "../camera_suite.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <input/input.h>
-#include <gui/elements.h>
-#include <dolphin/dolphin.h>
-#include "../helpers/camera_suite_haptic.h"
-#include "../helpers/camera_suite_speaker.h"
-#include "../helpers/camera_suite_led.h"
-
-static void draw_pixel_by_orientation(Canvas* canvas, uint8_t x, uint8_t y, uint8_t orientation) {
-    furi_assert(canvas);
-    furi_assert(x);
-    furi_assert(y);
-    furi_assert(orientation);
-
-    switch(orientation) {
-    default:
-    case 0: { // Camera rotated 0 degrees (right side up, default)
-        canvas_draw_dot(canvas, x, y);
-        break;
-    }
-    case 1: { // Camera rotated 90 degrees
-
-        canvas_draw_dot(canvas, y, FRAME_WIDTH - 1 - x);
-        break;
-    }
-    case 2: { // Camera rotated 180 degrees (upside down)
-        canvas_draw_dot(canvas, FRAME_WIDTH - 1 - x, FRAME_HEIGHT - 1 - y);
-        break;
-    }
-    case 3: { // Camera rotated 270 degrees
-        canvas_draw_dot(canvas, FRAME_HEIGHT - 1 - y, x);
-        break;
-    }
-    }
-}
-
-static void camera_suite_view_camera_draw(Canvas* canvas, void* model) {
-    furi_assert(canvas);
-    furi_assert(model);
-
-    UartDumpModel* uartDumpModel = model;
-
-    // Clear the screen.
-    canvas_set_color(canvas, ColorBlack);
-
-    // Draw the frame.
-    canvas_draw_frame(canvas, 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
-
-    for(size_t p = 0; p < FRAME_BUFFER_LENGTH; ++p) {
-        uint8_t x = p % ROW_BUFFER_LENGTH; // 0 .. 15
-        uint8_t y = p / ROW_BUFFER_LENGTH; // 0 .. 63
-
-        for(uint8_t i = 0; i < 8; ++i) {
-            if((uartDumpModel->pixels[p] & (1 << (7 - i))) != 0) {
-                draw_pixel_by_orientation(canvas, (x * 8) + i, y, uartDumpModel->orientation);
-            }
-        }
-    }
-
-    // Draw the guide if the camera is not initialized.
-    if(!uartDumpModel->initialized) {
-        canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48);
-        canvas_set_font(canvas, FontSecondary);
-        canvas_draw_str(canvas, 8, 12, "Connect the ESP32-CAM");
-        canvas_draw_str(canvas, 20, 24, "VCC - 3V3");
-        canvas_draw_str(canvas, 20, 34, "GND - GND");
-        canvas_draw_str(canvas, 20, 44, "U0R - TX");
-        canvas_draw_str(canvas, 20, 54, "U0T - RX");
-    }
-}
-
-static void save_image(void* model) {
-    furi_assert(model);
-
-    UartDumpModel* uartDumpModel = model;
-
-    // This pointer is used to access the storage.
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-
-    // This pointer is used to access the filesystem.
-    File* file = storage_file_alloc(storage);
-
-    // Store path in local variable.
-    const char* folderName = EXT_PATH("DCIM");
-
-    // Create the folder name for the image file if it does not exist.
-    if(storage_common_stat(storage, folderName, NULL) == FSE_NOT_EXIST) {
-        storage_simply_mkdir(storage, folderName);
-    }
-
-    // This pointer is used to access the file name.
-    FuriString* file_name = furi_string_alloc();
-
-    // Get the current date and time.
-    FuriHalRtcDateTime datetime = {0};
-    furi_hal_rtc_get_datetime(&datetime);
-
-    // Create the file name.
-    furi_string_printf(
-        file_name,
-        EXT_PATH("DCIM/%.4d%.2d%.2d-%.2d%.2d%.2d.bmp"),
-        datetime.year,
-        datetime.month,
-        datetime.day,
-        datetime.hour,
-        datetime.minute,
-        datetime.second);
-
-    // Open the file for writing. If the file does not exist (it shouldn't),
-    // create it.
-    bool result =
-        storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS);
-
-    // Free the file name after use.
-    furi_string_free(file_name);
-
-    if(!uartDumpModel->inverted) {
-        for(size_t i = 0; i < FRAME_BUFFER_LENGTH; ++i) {
-            uartDumpModel->pixels[i] = ~uartDumpModel->pixels[i];
-        }
-    }
-
-    // If the file was opened successfully, write the bitmap header and the
-    // image data.
-    if(result) {
-        // Write BMP Header
-        storage_file_write(file, bitmap_header, BITMAP_HEADER_LENGTH);
-
-        // @todo - Add a function for saving the image directly from the
-        // ESP32-CAM to the Flipper Zero SD card.
-
-        // Write locally to the Flipper Zero SD card in the DCIM folder.
-        int8_t row_buffer[ROW_BUFFER_LENGTH];
-
-        // @todo - Save image based on orientation.
-        for(size_t i = 64; i > 0; --i) {
-            for(size_t j = 0; j < ROW_BUFFER_LENGTH; ++j) {
-                row_buffer[j] = uartDumpModel->pixels[((i - 1) * ROW_BUFFER_LENGTH) + j];
-            }
-            storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH);
-        }
-    }
-
-    // Close the file.
-    storage_file_close(file);
-
-    // Free up memory.
-    storage_file_free(file);
-}
-
-static void
-    camera_suite_view_camera_model_init(UartDumpModel* const model, CameraSuite* instance_context) {
-    furi_assert(model);
-    furi_assert(instance_context);
-
-    for(size_t i = 0; i < FRAME_BUFFER_LENGTH; i++) {
-        model->pixels[i] = 0;
-    }
-
-    uint32_t orientation = instance_context->orientation;
-    model->flash = instance_context->flash;
-    model->inverted = false;
-    model->orientation = orientation;
-}
-
-static bool camera_suite_view_camera_input(InputEvent* event, void* context) {
-    furi_assert(context);
-    furi_assert(event);
-
-    CameraSuiteViewCamera* instance = context;
-
-    if(event->type == InputTypeRelease) {
-        switch(event->key) {
-        default: // Stop all sounds, reset the LED.
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    camera_suite_play_bad_bump(instance->context);
-                    camera_suite_stop_all_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 0);
-                },
-                true);
-            break;
-        }
-    } else if(event->type == InputTypePress) {
-        uint8_t data[1] = {'X'};
-        switch(event->key) {
-        // Camera: Stop stream.
-        case InputKeyBack: {
-            // Set the camera flash to off.
-            uint8_t flash_off = 'f';
-            furi_hal_uart_tx(UART_CH, &flash_off, 1);
-            furi_delay_ms(50);
-            // Stop camera stream.
-            uint8_t stop_camera = 's';
-            furi_hal_uart_tx(UART_CH, &stop_camera, 1);
-            // Go back to the main menu.
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    instance->callback(CameraSuiteCustomEventSceneCameraBack, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Toggle invert on the ESP32-CAM.
-        case InputKeyLeft: {
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    camera_suite_play_happy_bump(instance->context);
-                    camera_suite_play_input_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 255);
-                    if(model->inverted) {
-                        data[0] = 'i';
-                        model->inverted = false;
-                    } else {
-                        data[0] = 'I';
-                        model->inverted = true;
-                    }
-                    instance->callback(CameraSuiteCustomEventSceneCameraLeft, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Enable/disable dithering.
-        case InputKeyRight: {
-            data[0] = '>';
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    camera_suite_play_happy_bump(instance->context);
-                    camera_suite_play_input_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 255);
-                    instance->callback(CameraSuiteCustomEventSceneCameraRight, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Increase contrast.
-        case InputKeyUp: {
-            data[0] = 'C';
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    camera_suite_play_happy_bump(instance->context);
-                    camera_suite_play_input_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 255);
-                    instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Reduce contrast.
-        case InputKeyDown: {
-            data[0] = 'c';
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    UNUSED(model);
-                    camera_suite_play_happy_bump(instance->context);
-                    camera_suite_play_input_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 255);
-                    instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Take picture.
-        case InputKeyOk: {
-            with_view_model(
-                instance->view,
-                UartDumpModel * model,
-                {
-                    camera_suite_play_long_bump(instance->context);
-                    camera_suite_play_input_sound(instance->context);
-                    camera_suite_led_set_rgb(instance->context, 0, 0, 255);
-
-                    // Save picture directly to ESP32-CAM.
-                    // @todo - Add this functionality.
-                    // data[0] = 'P';
-                    // furi_hal_uart_tx(UART_CH, data, 1);
-
-                    // if(model->flash) {
-                    //     data[0] = 'F';
-                    //     furi_hal_uart_tx(UART_CH, data, 1);
-                    //     furi_delay_ms(50);
-                    // }
-
-                    // Take a picture.
-                    save_image(model);
-
-                    // if(model->flash) {
-                    //     data[0] = 'f';
-                    // }
-                    instance->callback(CameraSuiteCustomEventSceneCameraOk, instance->context);
-                },
-                true);
-            break;
-        }
-        // Camera: Do nothing.
-        case InputKeyMAX:
-        default: {
-            break;
-        }
-        }
-
-        if(data[0] != 'X') {
-            // Send `data` to the ESP32-CAM.
-            furi_hal_uart_tx(UART_CH, data, 1);
-        }
-    }
-    return true;
-}
-
-static void camera_suite_view_camera_exit(void* context) {
-    UNUSED(context);
-
-    // Set the camera flash to off.
-    uint8_t flash_off = 'f';
-    furi_hal_uart_tx(UART_CH, &flash_off, 1);
-    furi_delay_ms(50);
-
-    // Stop camera stream.
-    uint8_t stop_camera = 's';
-    furi_hal_uart_tx(UART_CH, &stop_camera, 1);
-    furi_delay_ms(50);
-}
-
-static void camera_suite_view_camera_enter(void* context) {
-    furi_assert(context);
-
-    // Get the camera suite instance context.
-    CameraSuiteViewCamera* instance = (CameraSuiteViewCamera*)context;
-
-    // Get the camera suite instance context.
-    CameraSuite* instance_context = instance->context;
-
-    // Start camera stream.
-    uint8_t start_camera = 'S';
-    furi_hal_uart_tx(UART_CH, &start_camera, 1);
-    furi_delay_ms(75);
-
-    // Get/set dither type.
-    uint8_t dither_type = instance_context->dither;
-    furi_hal_uart_tx(UART_CH, &dither_type, 1);
-    furi_delay_ms(75);
-
-    // Make sure the camera is not inverted.
-    uint8_t invert_camera = 'i';
-    furi_hal_uart_tx(UART_CH, &invert_camera, 1);
-    furi_delay_ms(75);
-
-    // Toggle flash on or off based on the current state. This will keep the
-    // flash on initially. However we're toggling it for now on input.
-    uint8_t flash_state = instance_context->flash ? 'F' : 'f';
-    furi_hal_uart_tx(UART_CH, &flash_state, 1);
-    furi_delay_ms(75);
-
-    // Make sure we start with the flash off.
-    // uint8_t flash_state = 'f';
-    // furi_hal_uart_tx(UART_CH, &flash_state, 1);
-    // furi_delay_ms(75);
-
-    with_view_model(
-        instance->view,
-        UartDumpModel * model,
-        { camera_suite_view_camera_model_init(model, instance_context); },
-        true);
-}
-
-static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* context) {
-    furi_assert(uartIrqEvent);
-    furi_assert(data);
-    furi_assert(context);
-
-    // Cast `context` to `CameraSuiteViewCamera*` and store it in `instance`.
-    CameraSuiteViewCamera* instance = context;
-
-    // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the
-    // `rx_stream` and set the `WorkerEventRx` flag.
-    if(uartIrqEvent == UartIrqEventRXNE) {
-        furi_stream_buffer_send(instance->rx_stream, &data, 1, 0);
-        furi_thread_flags_set(furi_thread_get_id(instance->worker_thread), WorkerEventRx);
-    }
-}
-
-static void process_ringbuffer(UartDumpModel* model, uint8_t const byte) {
-    furi_assert(model);
-    furi_assert(byte);
-
-    // The first HEADER_LENGTH bytes are reserved for header information.
-    if(model->ringbuffer_index < HEADER_LENGTH) {
-        // Validate the start of row characters 'Y' and ':'.
-        if(model->ringbuffer_index == 0 && byte != 'Y') {
-            // Incorrect start of frame; reset.
-            return;
-        }
-        if(model->ringbuffer_index == 1 && byte != ':') {
-            // Incorrect start of frame; reset.
-            model->ringbuffer_index = 0;
-            return;
-        }
-        if(model->ringbuffer_index == 2) {
-            // Assign the third byte as the row identifier.
-            model->row_identifier = byte;
-        }
-        model->ringbuffer_index++; // Increment index for the next byte.
-        return;
-    }
-
-    // Store pixel value directly after the header.
-    model->row_ringbuffer[model->ringbuffer_index - HEADER_LENGTH] = byte;
-    model->ringbuffer_index++; // Increment index for the next byte.
-
-    // Check whether the ring buffer is filled.
-    if(model->ringbuffer_index >= RING_BUFFER_LENGTH) {
-        model->ringbuffer_index = 0; // Reset the ring buffer index.
-        model->initialized = true; // Set the connection as successfully established.
-
-        // Compute the starting index for the row in the pixel buffer.
-        size_t row_start_index = model->row_identifier * ROW_BUFFER_LENGTH;
-
-        // Ensure the row start index is within the valid range.
-        if(row_start_index > LAST_ROW_INDEX) {
-            row_start_index = 0; // Reset to a safe value in case of an overflow.
-        }
-
-        // Flush the contents of the ring buffer to the pixel buffer.
-        for(size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) {
-            model->pixels[row_start_index + i] = model->row_ringbuffer[i];
-        }
-    }
-}
-
-static int32_t camera_worker(void* context) {
-    furi_assert(context);
-
-    CameraSuiteViewCamera* instance = context;
-
-    while(1) {
-        uint32_t events =
-            furi_thread_flags_wait(WORKER_EVENTS_MASK, FuriFlagWaitAny, FuriWaitForever);
-        furi_check((events & FuriFlagError) == 0);
-
-        if(events & WorkerEventStop) {
-            break;
-        } else if(events & WorkerEventRx) {
-            size_t length = 0;
-            do {
-                size_t intended_data_size = 64;
-                uint8_t data[intended_data_size];
-                length =
-                    furi_stream_buffer_receive(instance->rx_stream, data, intended_data_size, 0);
-
-                if(length > 0) {
-                    with_view_model(
-                        instance->view,
-                        UartDumpModel * model,
-                        {
-                            for(size_t i = 0; i < length; i++) {
-                                process_ringbuffer(model, data[i]);
-                            }
-                        },
-                        false);
-                }
-            } while(length > 0);
-
-            with_view_model(
-                instance->view, UartDumpModel * model, { UNUSED(model); }, true);
-        }
-    }
-
-    return 0;
-}
-
-CameraSuiteViewCamera* camera_suite_view_camera_alloc() {
-    // Allocate memory for the instance
-    CameraSuiteViewCamera* instance = malloc(sizeof(CameraSuiteViewCamera));
-
-    // Allocate the view object
-    instance->view = view_alloc();
-
-    // Allocate a stream buffer
-    instance->rx_stream = furi_stream_buffer_alloc(2048, 1);
-
-    // Allocate model
-    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(UartDumpModel));
-
-    // Set context for the view
-    view_set_context(instance->view, instance);
-
-    // Set draw callback
-    view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_camera_draw);
-
-    // Set input callback
-    view_set_input_callback(instance->view, camera_suite_view_camera_input);
-
-    // Set enter callback
-    view_set_enter_callback(instance->view, camera_suite_view_camera_enter);
-
-    // Set exit callback
-    view_set_exit_callback(instance->view, camera_suite_view_camera_exit);
-
-    // Allocate a thread for this camera to run on.
-    FuriThread* thread = furi_thread_alloc_ex("UsbUartWorker", 2048, camera_worker, instance);
-    instance->worker_thread = thread;
-    furi_thread_start(instance->worker_thread);
-
-    // Enable uart listener
-    if(UART_CH == UART_CH) {
-        furi_hal_console_disable();
-    } else if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_init(UART_CH, 230400);
-    }
-
-    // 115200 is the default baud rate for the ESP32-CAM.
-    furi_hal_uart_set_br(UART_CH, 230400);
-
-    // Enable UART1 and set the IRQ callback.
-    furi_hal_uart_set_irq_cb(UART_CH, camera_on_irq_cb, instance);
-
-    return instance;
-}
-
-void camera_suite_view_camera_free(CameraSuiteViewCamera* instance) {
-    furi_assert(instance);
-
-    // Remove the IRQ callback.
-    furi_hal_uart_set_irq_cb(UART_CH, NULL, NULL);
-
-    // Free the worker thread.
-    furi_thread_free(instance->worker_thread);
-
-    // Free the allocated stream buffer.
-    furi_stream_buffer_free(instance->rx_stream);
-
-    // Re-enable the console.
-    if(UART_CH == FuriHalUartIdLPUART1) {
-        furi_hal_uart_deinit(UART_CH);
-    } else {
-        furi_hal_console_enable();
-    }
-
-    with_view_model(
-        instance->view, UartDumpModel * model, { UNUSED(model); }, true);
-    view_free(instance->view);
-    free(instance);
-}
-
-View* camera_suite_view_camera_get_view(CameraSuiteViewCamera* instance) {
-    furi_assert(instance);
-    return instance->view;
-}
-
-void camera_suite_view_camera_set_callback(
-    CameraSuiteViewCamera* instance,
-    CameraSuiteViewCameraCallback callback,
-    void* context) {
-    furi_assert(instance);
-    furi_assert(callback);
-    instance->callback = callback;
-    instance->context = context;
-}

+ 0 - 81
.modules/camera_suite/fap/views/camera_suite_view_camera.h

@@ -1,81 +0,0 @@
-#pragma once
-
-#include "../helpers/camera_suite_custom_event.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <furi_hal_console.h>
-#include <furi_hal_uart.h>
-#include <gui/elements.h>
-#include <gui/gui.h>
-#include <gui/icon_i.h>
-#include <gui/modules/dialog_ex.h>
-#include <gui/view.h>
-#include <gui/view_dispatcher.h>
-#include <notification/notification.h>
-#include <notification/notification_messages.h>
-#include <storage/filesystem_api_defines.h>
-#include <storage/storage.h>
-
-#include <xtreme.h>
-
-#define UART_CH                                                                 \
-    (XTREME_SETTINGS()->uart_esp_channel == UARTDefault ? FuriHalUartIdUSART1 : \
-                                                          FuriHalUartIdLPUART1)
-
-#define BITMAP_HEADER_LENGTH 62
-#define FRAME_BIT_DEPTH 1
-#define FRAME_BUFFER_LENGTH 1024
-#define FRAME_HEIGHT 64
-#define FRAME_WIDTH 128
-#define HEADER_LENGTH 3 // 'Y', ':', and row identifier
-#define LAST_ROW_INDEX 1008
-#define RING_BUFFER_LENGTH 19
-#define ROW_BUFFER_LENGTH 16
-
-static const unsigned char bitmap_header[BITMAP_HEADER_LENGTH] = {
-    0x42, 0x4D, 0x3E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00,
-    0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00};
-
-extern const Icon I_DolphinCommon_56x48;
-typedef enum {
-    WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
-    WorkerEventStop = (1 << 1),
-    WorkerEventRx = (1 << 2),
-} WorkerEventFlags;
-
-#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
-
-// Forward declaration
-typedef void (*CameraSuiteViewCameraCallback)(CameraSuiteCustomEvent event, void* context);
-
-typedef struct CameraSuiteViewCamera {
-    CameraSuiteViewCameraCallback callback;
-    FuriStreamBuffer* rx_stream;
-    FuriThread* worker_thread;
-    NotificationApp* notification;
-    View* view;
-    void* context;
-} CameraSuiteViewCamera;
-
-typedef struct UartDumpModel {
-    bool flash;
-    bool initialized;
-    bool inverted;
-    int rotation_angle;
-    uint32_t orientation;
-    uint8_t pixels[FRAME_BUFFER_LENGTH];
-    uint8_t ringbuffer_index;
-    uint8_t row_identifier;
-    uint8_t row_ringbuffer[RING_BUFFER_LENGTH];
-} UartDumpModel;
-
-// Function Prototypes
-CameraSuiteViewCamera* camera_suite_view_camera_alloc();
-View* camera_suite_view_camera_get_view(CameraSuiteViewCamera* camera_suite_static);
-void camera_suite_view_camera_free(CameraSuiteViewCamera* camera_suite_static);
-void camera_suite_view_camera_set_callback(
-    CameraSuiteViewCamera* camera_suite_view_camera,
-    CameraSuiteViewCameraCallback callback,
-    void* context);

+ 0 - 119
.modules/camera_suite/fap/views/camera_suite_view_guide.c

@@ -1,119 +0,0 @@
-#include "../camera_suite.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <input/input.h>
-#include <gui/elements.h>
-#include <dolphin/dolphin.h>
-
-struct CameraSuiteViewGuide {
-    View* view;
-    CameraSuiteViewGuideCallback callback;
-    void* context;
-};
-
-typedef struct {
-    int some_value;
-} CameraSuiteViewGuideModel;
-
-void camera_suite_view_guide_set_callback(
-    CameraSuiteViewGuide* instance,
-    CameraSuiteViewGuideCallback callback,
-    void* context) {
-    furi_assert(instance);
-    furi_assert(callback);
-    instance->callback = callback;
-    instance->context = context;
-}
-
-void camera_suite_view_guide_draw(Canvas* canvas, CameraSuiteViewGuideModel* model) {
-    UNUSED(model);
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Guide");
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 0, 12, AlignLeft, AlignTop, "Left = Toggle invert");
-    canvas_draw_str_aligned(canvas, 0, 22, AlignLeft, AlignTop, "Right = Toggle dithering");
-    canvas_draw_str_aligned(canvas, 0, 32, AlignLeft, AlignTop, "Up = Contrast up");
-    canvas_draw_str_aligned(canvas, 0, 42, AlignLeft, AlignTop, "Down = Contrast down");
-    canvas_draw_str_aligned(canvas, 0, 52, AlignLeft, AlignTop, "Center = Take picture");
-}
-
-static void camera_suite_view_guide_model_init(CameraSuiteViewGuideModel* const model) {
-    model->some_value = 1;
-}
-
-bool camera_suite_view_guide_input(InputEvent* event, void* context) {
-    furi_assert(context);
-    CameraSuiteViewGuide* instance = context;
-    if(event->type == InputTypeRelease) {
-        switch(event->key) {
-        case InputKeyBack:
-            with_view_model(
-                instance->view,
-                CameraSuiteViewGuideModel * model,
-                {
-                    UNUSED(model);
-                    instance->callback(CameraSuiteCustomEventSceneGuideBack, instance->context);
-                },
-                true);
-            break;
-        case InputKeyLeft:
-        case InputKeyRight:
-        case InputKeyUp:
-        case InputKeyDown:
-        case InputKeyOk:
-        case InputKeyMAX:
-            // Do nothing.
-            break;
-        }
-    }
-    return true;
-}
-
-void camera_suite_view_guide_exit(void* context) {
-    furi_assert(context);
-}
-
-void camera_suite_view_guide_enter(void* context) {
-    furi_assert(context);
-    CameraSuiteViewGuide* instance = (CameraSuiteViewGuide*)context;
-    with_view_model(
-        instance->view,
-        CameraSuiteViewGuideModel * model,
-        { camera_suite_view_guide_model_init(model); },
-        true);
-}
-
-CameraSuiteViewGuide* camera_suite_view_guide_alloc() {
-    CameraSuiteViewGuide* instance = malloc(sizeof(CameraSuiteViewGuide));
-    instance->view = view_alloc();
-    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(CameraSuiteViewGuideModel));
-    view_set_context(instance->view, instance); // furi_assert crashes in events without this
-    view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_guide_draw);
-    view_set_input_callback(instance->view, camera_suite_view_guide_input);
-    view_set_enter_callback(instance->view, camera_suite_view_guide_enter);
-    view_set_exit_callback(instance->view, camera_suite_view_guide_exit);
-
-    with_view_model(
-        instance->view,
-        CameraSuiteViewGuideModel * model,
-        { camera_suite_view_guide_model_init(model); },
-        true);
-
-    return instance;
-}
-
-void camera_suite_view_guide_free(CameraSuiteViewGuide* instance) {
-    furi_assert(instance);
-
-    with_view_model(
-        instance->view, CameraSuiteViewGuideModel * model, { UNUSED(model); }, true);
-    view_free(instance->view);
-    free(instance);
-}
-
-View* camera_suite_view_guide_get_view(CameraSuiteViewGuide* instance) {
-    furi_assert(instance);
-    return instance->view;
-}

+ 0 - 19
.modules/camera_suite/fap/views/camera_suite_view_guide.h

@@ -1,19 +0,0 @@
-#pragma once
-
-#include <gui/view.h>
-#include "../helpers/camera_suite_custom_event.h"
-
-typedef struct CameraSuiteViewGuide CameraSuiteViewGuide;
-
-typedef void (*CameraSuiteViewGuideCallback)(CameraSuiteCustomEvent event, void* context);
-
-void camera_suite_view_guide_set_callback(
-    CameraSuiteViewGuide* camera_suite_view_guide,
-    CameraSuiteViewGuideCallback callback,
-    void* context);
-
-View* camera_suite_view_guide_get_view(CameraSuiteViewGuide* camera_suite_static);
-
-CameraSuiteViewGuide* camera_suite_view_guide_alloc();
-
-void camera_suite_view_guide_free(CameraSuiteViewGuide* camera_suite_static);

+ 0 - 126
.modules/camera_suite/fap/views/camera_suite_view_start.c

@@ -1,126 +0,0 @@
-#include "../camera_suite.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <input/input.h>
-#include <gui/elements.h>
-
-struct CameraSuiteViewStart {
-    View* view;
-    CameraSuiteViewStartCallback callback;
-    void* context;
-};
-
-typedef struct {
-    int some_value;
-} CameraSuiteViewStartModel;
-
-void camera_suite_view_start_set_callback(
-    CameraSuiteViewStart* instance,
-    CameraSuiteViewStartCallback callback,
-    void* context) {
-    furi_assert(instance);
-    furi_assert(callback);
-    instance->callback = callback;
-    instance->context = context;
-}
-
-void camera_suite_view_start_draw(Canvas* canvas, CameraSuiteViewStartModel* model) {
-    UNUSED(model);
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Camera Suite");
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Flipper Zero");
-    canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "ESP32 CAM");
-    elements_button_center(canvas, "Start");
-}
-
-static void camera_suite_view_start_model_init(CameraSuiteViewStartModel* const model) {
-    model->some_value = 1;
-}
-
-bool camera_suite_view_start_input(InputEvent* event, void* context) {
-    furi_assert(context);
-    CameraSuiteViewStart* instance = context;
-    if(event->type == InputTypeRelease) {
-        switch(event->key) {
-        case InputKeyBack:
-            // Exit application.
-            with_view_model(
-                instance->view,
-                CameraSuiteViewStartModel * model,
-                {
-                    UNUSED(model);
-                    instance->callback(CameraSuiteCustomEventStartBack, instance->context);
-                },
-                true);
-            break;
-        case InputKeyOk:
-            // Start the application.
-            with_view_model(
-                instance->view,
-                CameraSuiteViewStartModel * model,
-                {
-                    UNUSED(model);
-                    instance->callback(CameraSuiteCustomEventStartOk, instance->context);
-                },
-                true);
-            break;
-        case InputKeyMAX:
-        case InputKeyLeft:
-        case InputKeyRight:
-        case InputKeyUp:
-        case InputKeyDown:
-            // Do nothing.
-            break;
-        }
-    }
-    return true;
-}
-
-void camera_suite_view_start_exit(void* context) {
-    furi_assert(context);
-}
-
-void camera_suite_view_start_enter(void* context) {
-    furi_assert(context);
-    CameraSuiteViewStart* instance = (CameraSuiteViewStart*)context;
-    with_view_model(
-        instance->view,
-        CameraSuiteViewStartModel * model,
-        { camera_suite_view_start_model_init(model); },
-        true);
-}
-
-CameraSuiteViewStart* camera_suite_view_start_alloc() {
-    CameraSuiteViewStart* instance = malloc(sizeof(CameraSuiteViewStart));
-    instance->view = view_alloc();
-    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(CameraSuiteViewStartModel));
-    // furi_assert crashes in events without this
-    view_set_context(instance->view, instance);
-    view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_start_draw);
-    view_set_input_callback(instance->view, camera_suite_view_start_input);
-
-    with_view_model(
-        instance->view,
-        CameraSuiteViewStartModel * model,
-        { camera_suite_view_start_model_init(model); },
-        true);
-
-    return instance;
-}
-
-void camera_suite_view_start_free(CameraSuiteViewStart* instance) {
-    furi_assert(instance);
-
-    with_view_model(
-        instance->view, CameraSuiteViewStartModel * model, { UNUSED(model); }, true);
-    view_free(instance->view);
-    free(instance);
-}
-
-View* camera_suite_view_start_get_view(CameraSuiteViewStart* instance) {
-    furi_assert(instance);
-    return instance->view;
-}

+ 0 - 19
.modules/camera_suite/fap/views/camera_suite_view_start.h

@@ -1,19 +0,0 @@
-#pragma once
-
-#include <gui/view.h>
-#include "../helpers/camera_suite_custom_event.h"
-
-typedef struct CameraSuiteViewStart CameraSuiteViewStart;
-
-typedef void (*CameraSuiteViewStartCallback)(CameraSuiteCustomEvent event, void* context);
-
-void camera_suite_view_start_set_callback(
-    CameraSuiteViewStart* camera_suite_view_start,
-    CameraSuiteViewStartCallback callback,
-    void* context);
-
-View* camera_suite_view_start_get_view(CameraSuiteViewStart* camera_suite_static);
-
-CameraSuiteViewStart* camera_suite_view_start_alloc();
-
-void camera_suite_view_start_free(CameraSuiteViewStart* camera_suite_static);

+ 0 - 188
.modules/camera_suite/firmware-flash.bat

@@ -1,188 +0,0 @@
-@echo off
-setlocal EnableDelayedExpansion
-
-rem λ
-
-set CLI_FOUND_FOLLOW_UP=0
-set CLI_TEMP=%TEMP%\arduino-cli
-set COMPILE_FLAG=firmware\.compile.flag
-set CONFIG_FILE=--config-file .\arduino-cli.yaml
-set DEFAULT_BOARD_FQBN=esp32:esp32:esp32cam
-set FIRMWARE_SRC=firmware\firmware.ino
-set SELECTED_BOARD=%DEFAULT_BOARD_FQBN%
-
-chcp 65001 > nul
-echo ┏┓   ┓    ┏┳┓  ┓
-echo ┃ ┏┓┏┫┓┏   ┃ ┏┓┃┏┓┏┓┏┓
-echo ┗┛┗┛┗┻┗┫   ┻ ┗┛┗┗ ┛┗┗
-echo        ┛  https://github.com/CodyTolene
-echo.
-echo Flipper Zero - ESP32-CAM Firmware Flasher - Windows 10+
-echo https://github.com/CodyTolene/Flipper-Zero-Camera-Suite
-echo.
-echo ------------------------------------------------------------------------------
-echo Before you begin please make sure your Flipper Zero is plugged into your PC.
-echo Then on your Flipper Zero, open the GPIO menu and select USB-UART Bridge.
-echo ------------------------------------------------------------------------------
-echo.
-pause
-echo.
-echo Initializing...
-
-:checkCLI
-if not exist "arduino-cli.exe" (
-    echo.
-    echo The "arduino-cli.exe" file cannot be found. Please download it manually from the following link: 
-    echo https://arduino.github.io/arduino-cli/latest/installation/#download
-    echo Extract the "arduino-cli.exe" file to the same directory as this script, root of the project.
-    echo.
-    echo When the file is ready, press any key to check again.
-    set /a CLI_FOUND_FOLLOW_UP+=1
-    if %CLI_FOUND_FOLLOW_UP% geq 2 (
-        echo If you're still having issues, feel free to open a ticket at the following link:
-        echo https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues
-    )
-    pause
-    goto :checkCLI
-)
-if %CLI_FOUND_FOLLOW_UP% geq 1 (
-    echo File "arduino-cli.exe" found. Continuing...
-)
-
-echo Checking configs...
-arduino-cli %CONFIG_FILE% config set directories.data %CLI_TEMP%\data
-arduino-cli %CONFIG_FILE% config set directories.downloads %CLI_TEMP%\downloads
-arduino-cli %CONFIG_FILE% config set directories.user %CLI_TEMP%\user %*
-
-echo Fetching assets...
-set DATA_FLAG=0
-if not exist "%CLI_TEMP%\data" (
-    set /a "DATA_FLAG+=1"
-)
-if not exist "%CLI_TEMP%\downloads" (
-    set /a "DATA_FLAG+=1"
-)
-if %DATA_FLAG% gtr 0 (
-    arduino-cli %CONFIG_FILE% core update-index
-    arduino-cli %CONFIG_FILE% core install esp32:esp32
-) else (
-    echo Assets already installed. Skipping...
-)
-
-if not exist "%COMPILE_FLAG%" (
-    goto :compileFirmware
-)
-
-if exist "%COMPILE_FLAG%" (
-    echo.
-    set /p RECOMPILE="A previous firmware build was found, would you like to use it? (Y/N): "
-    if /i "!RECOMPILE!"=="N" (
-        goto :compileFirmware
-    )
-)
-:exitCompileFirmware
-
-echo.
-echo Firmware ready for serial installation...
-echo Fetching and displaying USB devices for upload...
-echo.
-arduino-cli board list
-echo Please find your Flipper Zero USB port name from the list above (may show as unknown).
-set /p PORT_NUMBER="Enter the port name here. For example 'COM3' capitalized with no quotes: "
-echo.
-echo Your ESP32-CAM is ready to be flashed. Please follow the instructions below:
-
-:uploadFirmware
-echo.
-echo 1. Remove ESP32-CAM. Ensure IO0 pin on ESP32-CAM is grounded to the proper GND pin.
-echo 2. Hold reset, and insert your ESP32-CAM; hold for a few seconds and release.
-echo 3. Try to time your release simultaneously with continuing to the next step.
-echo 4. ESP32-CAM should now be in flash mode; allow some time for firmware upload.
-echo 5. Failure is common; verify all connections if errors persist and try again.
-echo 6. Disconnecting and reconnecting USB between attempts may sometimes work.
-echo.
-pause
-
-set RETRY_COUNT=1
-
-:uploadLoop
-echo.
-echo Preparing firmware upload... Attempt number !RETRY_COUNT!...
-arduino-cli %CONFIG_FILE% upload -p %PORT_NUMBER% --fqbn !SELECTED_BOARD! %FIRMWARE_SRC%
-if !ERRORLEVEL! EQU 0 (
-    goto :uploadSuccess
-) else (
-    if !RETRY_COUNT! lss 5 (
-        set /a RETRY_COUNT+=1
-        goto :uploadLoop
-    ) else (
-        echo.
-        set /p UPLOAD_TRY_AGAIN="Upload failed after 5 attempts, dont give up friend. Would you like to try again? (Y/N): "
-        if /i "!UPLOAD_TRY_AGAIN!"=="Y" (
-            set RETRY_COUNT=1
-            goto :uploadFirmware
-        ) else (
-            echo.
-            echo If you're still having issues, feel free to open a ticket at the following link:
-            echo https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues
-            echo.
-            set /p DELETE_TEMP="Would you like to delete the temporary files? (Y/N): "
-            if /i "!DELETE_TEMP!"=="Y" (
-                rmdir /s /q %CLI_TEMP%
-            )
-            echo.
-            pause
-            exit /b
-        )
-    )
-)
-
-:uploadSuccess
-echo.
-echo Firmware upload was successful.
-echo Cleaning up...
-echo Restoring default configs...
-arduino-cli %CONFIG_FILE% config set directories.data C:\temp\arduino-cli\data
-arduino-cli %CONFIG_FILE% config set directories.downloads C:\temp\arduino-cli\staging
-arduino-cli %CONFIG_FILE% config set directories.user C:\temp\arduino-cli\user
-set /p DELETE_TEMP="Would you like to delete the temporary files? (Y/N): "
-if /i "!DELETE_TEMP!"=="Y" (
-    rmdir /s /q %CLI_TEMP%
-)
-echo.
-echo Fin. Happy programming friend.
-echo.
-pause
-exit /b
-
-:compileFirmware
-set /p USE_DEFAULT_BOARD="Install to default AI-Thinker ESP32-CAM board with FQBN '%DEFAULT_BOARD_FQBN%'? (Y/N): "
-if /i "%USE_DEFAULT_BOARD%"=="N" (
-    echo Warning - This script has not been tested with other boards. Please use at your own risk.
-    set /p SHOW_BOARDS="Display all possible ESP32 board names and FQBN's? (Y/N): "
-    if /i "!SHOW_BOARDS!"=="Y" (
-        echo.
-        arduino-cli board listall
-    )
-    set /p SELECTED_BOARD="Please enter your board FQBN. For example '%DEFAULT_BOARD_FQBN%' with no quotes: "
-)
-echo.
-echo Compiling firmware, this will take a moment...
-echo.
-arduino-cli %CONFIG_FILE% compile --fqbn !SELECTED_BOARD! %FIRMWARE_SRC%
-if %ERRORLEVEL% EQU 0 (
-    echo.
-    echo Firmware compiled successfully.
-    type nul > %COMPILE_FLAG%
-) else (
-    echo.
-    set /p TRY_COMPILE_AGAIN="Firmware failed to compile. Please see the error log above. Try again? (Y/N): "
-    echo.
-    if /i "!TRY_COMPILE_AGAIN!"=="Y" (
-        goto :compileFirmware
-    )
-    pause
-    exit /b
-)
-
-goto :exitCompileFirmware

+ 0 - 22
.modules/camera_suite/firmware/camera.h

@@ -1,22 +0,0 @@
-#ifndef INITIALIZE_CAMERA_H
-#define INITIALIZE_CAMERA_H
-
-#include <FS.h>
-#include <esp_camera.h>
-
-#include "camera_config.h"
-#include "camera_model.h"
-
-/** Initialize the camera. */
-void initialize_camera();
-
-/** Turn the flash off. */
-void toggle_flash_off();
-
-/** Turn the flash on. */
-void toggle_flash_on();
-
-/** If the flash state ever gets out of sync with the camera model, fix it. */
-void handle_flash_state();
-
-#endif

+ 0 - 47
.modules/camera_suite/firmware/camera.ino

@@ -1,47 +0,0 @@
-#include "camera.h"
-
-void initialize_camera() {
-    // Initialize camera.
-    esp_err_t err = esp_camera_init(&camera_config);
-    if (err != ESP_OK) {
-        return;
-    }
-
-    // Check if the flash is already on, if it is turn it off.
-    if (camera_model.isFlashEnabled) {
-        toggle_flash_off();
-    }
-
-    // Get the camera sensor reference.
-    sensor_t* cam = esp_camera_sensor_get();
-
-    cam->set_contrast(cam, 0); // Set initial contrast.
-    cam->set_vflip(cam, true); // Set initial vertical flip.
-
-    // cam->set_hmirror(cam, false); // Set initial horizontal mirror.
-    // cam->set_brightness(cam, 0);  // Set initial brightness.
-    // cam->set_saturation(cam, 0); // Set initial saturation.
-    // cam->set_sharpness(cam, 0); // Set initial sharpness.
-}
-
-void toggle_flash_off() {
-    pinMode(FLASH_GPIO_NUM, OUTPUT);
-    digitalWrite(FLASH_GPIO_NUM, LOW);
-    camera_model.isFlashEnabled = false;
-}
-
-void toggle_flash_on() {
-    pinMode(FLASH_GPIO_NUM, OUTPUT);
-    digitalWrite(FLASH_GPIO_NUM, HIGH);
-    camera_model.isFlashEnabled = true;
-}
-
-void handle_flash_state() {
-    // If the flash state ever gets out of sync with the camera model, fix it.
-    if (!camera_model.isFlashEnabled) {
-        int flashState = digitalRead(FLASH_GPIO_NUM);
-        if (flashState == HIGH) {
-            toggle_flash_off();
-        }
-    }
-}

+ 0 - 14
.modules/camera_suite/firmware/camera_config.h

@@ -1,14 +0,0 @@
-#ifndef CAMERA_CONFIG_H
-#define CAMERA_CONFIG_H
-
-#include <esp_camera.h>
-
-#include "pins.h"
-
-/** The camera configuration model. */
-extern camera_config_t camera_config;
-
-/** Initialize the camera configuration. */
-void initialize_camera_config();
-
-#endif

+ 0 - 30
.modules/camera_suite/firmware/camera_config.ino

@@ -1,30 +0,0 @@
-#include "camera_config.h"
-
-/** The camera configuration model. */
-camera_config_t camera_config;
-
-void initialize_camera_config() {
-    // Set initial camera configurations.
-    camera_config.ledc_channel = LEDC_CHANNEL_0;
-    camera_config.ledc_timer = LEDC_TIMER_0;
-    camera_config.pin_d0 = Y2_GPIO_NUM;
-    camera_config.pin_d1 = Y3_GPIO_NUM;
-    camera_config.pin_d2 = Y4_GPIO_NUM;
-    camera_config.pin_d3 = Y5_GPIO_NUM;
-    camera_config.pin_d4 = Y6_GPIO_NUM;
-    camera_config.pin_d5 = Y7_GPIO_NUM;
-    camera_config.pin_d6 = Y8_GPIO_NUM;
-    camera_config.pin_d7 = Y9_GPIO_NUM;
-    camera_config.pin_xclk = XCLK_GPIO_NUM;
-    camera_config.pin_pclk = PCLK_GPIO_NUM;
-    camera_config.pin_vsync = VSYNC_GPIO_NUM;
-    camera_config.pin_href = HREF_GPIO_NUM;
-    camera_config.pin_sscb_sda = SIOD_GPIO_NUM;
-    camera_config.pin_sscb_scl = SIOC_GPIO_NUM;
-    camera_config.pin_pwdn = PWDN_GPIO_NUM;
-    camera_config.pin_reset = RESET_GPIO_NUM;
-    camera_config.xclk_freq_hz = 20000000;
-    camera_config.pixel_format = PIXFORMAT_GRAYSCALE;
-    camera_config.frame_size = FRAMESIZE_QQVGA;
-    camera_config.fb_count = 1;
-}

+ 0 - 43
.modules/camera_suite/firmware/camera_model.h

@@ -1,43 +0,0 @@
-#ifndef CAMERA_MODEL_H
-#define CAMERA_MODEL_H
-
-#include <stdint.h>
-
-/**
- * The dithering algorithms available.
- */
-typedef enum {
-    FLOYD_STEINBERG,
-    JARVIS_JUDICE_NINKE,
-    STUCKI,
-} DitheringAlgorithm;
-
-typedef struct {
-    /**
-     * Flag to enable or disable dithering.
-     */
-    bool isDitheringEnabled;
-    /**
-     * Flag to represent the flash state when saving pictures to the Flipper.
-     */
-    bool isFlashEnabled;
-    /**
-     * Flag to invert pixel colors.
-     */
-    bool isInvertEnabled;
-    /**
-     * Flag to stop or start the stream.
-     */
-    bool isStreamEnabled;
-    /**
-     * Holds the currently selected dithering algorithm.
-     */
-    DitheringAlgorithm ditherAlgorithm;
-} CameraModel;
-
-/** The camera model. */
-extern CameraModel camera_model;
-
-void initialize_camera_model();
-
-#endif

+ 0 - 13
.modules/camera_suite/firmware/camera_model.ino

@@ -1,13 +0,0 @@
-#include "camera_model.h"
-
-/** The camera model. */
-CameraModel camera_model;
-
-void initialize_camera_model() {
-    // Set up camera model defaults.
-    camera_model.isDitheringEnabled = true;
-    camera_model.isFlashEnabled = false;
-    camera_model.isInvertEnabled = false;
-    camera_model.isStreamEnabled = true;
-    camera_model.ditherAlgorithm = FLOYD_STEINBERG;
-}

+ 0 - 11
.modules/camera_suite/firmware/dither_image.h

@@ -1,11 +0,0 @@
-#ifndef DITHER_IMAGE_H
-#define DITHER_IMAGE_H
-
-#include <esp_camera.h>
-
-#include "camera_model.h"
-
-/** Dither the image using the selected algorithm. */
-void dither_image(camera_fb_t* frame_buffer);
-
-#endif

+ 0 - 82
.modules/camera_suite/firmware/dither_image.ino

@@ -1,82 +0,0 @@
-#include "dither_image.h"
-
-void dither_image(camera_fb_t* frame_buffer) {
-    for (uint8_t y = 0; y < frame_buffer->height; ++y) {
-        for (uint8_t x = 0; x < frame_buffer->width; ++x) {
-            size_t current = (y * frame_buffer->width) + x;
-            uint8_t oldpixel = frame_buffer->buf[current];
-            uint8_t newpixel = oldpixel >= 128 ? 255 : 0;
-            frame_buffer->buf[current] = newpixel;
-            int8_t quant_error = oldpixel - newpixel;
-
-            // Apply error diffusion based on the selected algorithm
-            switch (camera_model.ditherAlgorithm) {
-            case JARVIS_JUDICE_NINKE:
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
-                    quant_error * 7 / 48;
-                frame_buffer->buf[(y * frame_buffer->width) + x + 2] +=
-                    quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] +=
-                    quant_error * 3 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
-                    quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
-                    quant_error * 7 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
-                    quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] +=
-                    quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] +=
-                    quant_error * 1 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] +=
-                    quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x] +=
-                    quant_error * 5 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] +=
-                    quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] +=
-                    quant_error * 1 / 48;
-                break;
-            case STUCKI:
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
-                    quant_error * 8 / 42;
-                frame_buffer->buf[(y * frame_buffer->width) + x + 2] +=
-                    quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] +=
-                    quant_error * 2 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
-                    quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
-                    quant_error * 8 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
-                    quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] +=
-                    quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] +=
-                    quant_error * 1 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] +=
-                    quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x] +=
-                    quant_error * 4 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] +=
-                    quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] +=
-                    quant_error * 1 / 42;
-                break;
-            case FLOYD_STEINBERG:
-            default:
-                // Default to Floyd-Steinberg dithering if an invalid
-                // algorithm is selected
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
-                    quant_error * 7 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
-                    quant_error * 3 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
-                    quant_error * 5 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
-                    quant_error * 1 / 16;
-                break;
-            }
-        }
-    }
-}

+ 0 - 12
.modules/camera_suite/firmware/firmware.h

@@ -1,12 +0,0 @@
-#ifndef FIRMWARE_H
-#define FIRMWARE_H
-
-#include <esp_camera.h>
-
-#include "camera.h"
-#include "camera_config.h"
-#include "camera_model.h"
-#include "process_image.h"
-#include "process_serial_commands.h"
-
-#endif

+ 0 - 30
.modules/camera_suite/firmware/firmware.ino

@@ -1,30 +0,0 @@
-#include "firmware.h"
-
-void setup() {
-    // Begin serial communication.
-    Serial.begin(230400); // 115200
-
-    // Initialize the camera model.
-    initialize_camera_model();
-
-    // Initialize the camera configuration.
-    initialize_camera_config();
-
-    // Initialize the camera.
-    initialize_camera();
-}
-
-// Main loop of the program.
-void loop() {
-    if (camera_model.isStreamEnabled) {
-        camera_fb_t* frame_buffer = esp_camera_fb_get();
-        if (frame_buffer) {
-            process_image(frame_buffer);
-            // Return the frame buffer back to the camera driver.
-            esp_camera_fb_return(frame_buffer);
-        }
-        delay(50);
-    }
-    handle_flash_state();
-    process_serial_commands();
-}

+ 0 - 23
.modules/camera_suite/firmware/pins.h

@@ -1,23 +0,0 @@
-#ifndef PINS_H
-#define PINS_H
-
-// Define Pin numbers used by the camera.
-#define FLASH_GPIO_NUM 4
-#define HREF_GPIO_NUM 23
-#define PCLK_GPIO_NUM 22
-#define PWDN_GPIO_NUM 32
-#define RESET_GPIO_NUM -1
-#define SIOC_GPIO_NUM 27
-#define SIOD_GPIO_NUM 26
-#define VSYNC_GPIO_NUM 25
-#define XCLK_GPIO_NUM 0
-#define Y2_GPIO_NUM 5
-#define Y3_GPIO_NUM 18
-#define Y4_GPIO_NUM 19
-#define Y5_GPIO_NUM 21
-#define Y6_GPIO_NUM 36
-#define Y7_GPIO_NUM 39
-#define Y8_GPIO_NUM 34
-#define Y9_GPIO_NUM 35
-
-#endif

+ 0 - 13
.modules/camera_suite/firmware/process_image.h

@@ -1,13 +0,0 @@
-#ifndef PROCESS_IMAGE_H
-#define PROCESS_IMAGE_H
-
-#include <FS.h>
-#include <esp_camera.h>
-
-#include "camera_model.h"
-#include "dither_image.h"
-
-/** Process and send grayscale images back to the Flipper Zero. */
-void process_image(camera_fb_t* frame_buffer);
-
-#endif

+ 0 - 54
.modules/camera_suite/firmware/process_image.ino

@@ -1,54 +0,0 @@
-#include "process_image.h"
-
-void process_image(camera_fb_t* frame_buffer) {
-    // If dithering is not disabled, perform dithering on the image. Dithering
-    // is the process of approximating the look of a high-resolution grayscale
-    // image in a lower resolution by binary values (black & white), thereby
-    // representing different shades of gray.
-    if (camera_model.isDitheringEnabled) {
-        // Invokes the dithering process on the frame buffer.
-        dither_image(frame_buffer);
-    }
-
-    uint8_t flipper_y = 0;
-
-    // Iterating over specific rows of the frame buffer.
-    for (uint8_t y = 28; y < 92; ++y) {
-        Serial.print("Y:");      // Print "Y:" for every new row.
-        Serial.write(flipper_y); // Send the row identifier as a byte.
-
-        // Calculate the actual y index in the frame buffer 1D array by
-        // multiplying the y value with the width of the frame buffer. This
-        // gives the starting index of the row in the 1D array.
-        size_t true_y = y * frame_buffer->width;
-
-        // Iterating over specific columns of each row in the frame buffer.
-        for (uint8_t x = 16; x < 144;
-             x += 8) { // step by 8 as we're packing 8 pixels per byte.
-            uint8_t packed_pixels = 0;
-            // Packing 8 pixel values into one byte.
-            for (uint8_t bit = 0; bit < 8; ++bit) {
-                // Check the invert flag and pack the pixels accordingly.
-                if (camera_model.isInvertEnabled) {
-                    // If invert is true, consider pixel as 1 if it's more than
-                    // 127.
-                    if (frame_buffer->buf[true_y + x + bit] > 127) {
-                        packed_pixels |= (1 << (7 - bit));
-                    }
-                } else {
-                    // If invert is false, consider pixel as 1 if it's less than
-                    // 127.
-                    if (frame_buffer->buf[true_y + x + bit] < 127) {
-                        packed_pixels |= (1 << (7 - bit));
-                    }
-                }
-            }
-            Serial.write(packed_pixels); // Sending packed pixel byte.
-        }
-        // Move to the next row.
-        ++flipper_y;
-        // Ensure all data in the Serial buffer is sent before moving to the
-        // next iteration.
-        Serial.flush();
-    }
-}

+ 0 - 13
.modules/camera_suite/firmware/process_serial_commands.h

@@ -1,13 +0,0 @@
-#ifndef PROCESS_SERIAL_COMMANDS_H
-#define PROCESS_SERIAL_COMMANDS_H
-
-#include <esp_camera.h>
-
-#include "camera.h"
-#include "camera_model.h"
-#include "pins.h"
-
-/** Handle the serial input commands coming from the Flipper Zero. */
-void process_serial_commands();
-
-#endif

+ 0 - 63
.modules/camera_suite/firmware/process_serial_commands.ino

@@ -1,63 +0,0 @@
-#include "process_serial_commands.h"
-
-void process_serial_commands() {
-    if (Serial.available() > 0) {
-        char input = Serial.read();
-        sensor_t* cam = esp_camera_sensor_get();
-
-        switch (input) {
-        case '>': // Toggle dithering.
-            camera_model.isDitheringEnabled = !camera_model.isDitheringEnabled;
-            break;
-        case 'i': // Turn invert off.
-            camera_model.isInvertEnabled = false;
-            break;
-        case 'I': // Turn invert on.
-            camera_model.isInvertEnabled = true;
-            break;
-        case 'b': // Remove brightness.
-            cam->set_contrast(cam, cam->status.brightness - 1);
-            break;
-        case 'B': // Add brightness.
-            cam->set_contrast(cam, cam->status.brightness + 1);
-            break;
-        case 'c': // Remove contrast.
-            cam->set_contrast(cam, cam->status.contrast - 1);
-            break;
-        case 'C': // Add contrast.
-            cam->set_contrast(cam, cam->status.contrast + 1);
-            break;
-        case 'f': // Turn the flash off.
-            toggle_flash_off();
-            break;
-        case 'F': // Turn the flash on.
-            toggle_flash_on();
-            break;
-        case 'P': // Save image to the onboard SD card.
-            // @todo - Future feature.
-            // save_picture_to_sd_card();
-            break;
-        case 'M': // Toggle Mirror.
-            cam->set_hmirror(cam, !cam->status.hmirror);
-            break;
-        case 's': // Stop stream.
-            camera_model.isStreamEnabled = false;
-            break;
-        case 'S': // Start stream.
-            camera_model.isStreamEnabled = true;
-            break;
-        case '0': // Use Floyd Steinberg dithering.
-            camera_model.ditherAlgorithm = FLOYD_STEINBERG;
-            break;
-        case '1': // Use Jarvis Judice dithering.
-            camera_model.ditherAlgorithm = JARVIS_JUDICE_NINKE;
-            break;
-        case '2': // Use Stucki dithering.
-            camera_model.ditherAlgorithm = STUCKI;
-            break;
-        default:
-            // Do nothing.
-            break;
-        }
-    }
-}

+ 0 - 13
.modules/camera_suite/firmware/save_picture_to_sd_card.h

@@ -1,13 +0,0 @@
-#ifndef SAVE_PICTURE_TO_SD_CARD_H
-#define SAVE_PICTURE_TO_SD_CARD_H
-
-#include <SD_MMC.h>
-#include <esp_camera.h>
-
-/**
- * Save the current picture to the onboard SD card.
- * @todo - Future feature.
- */
-void save_picture_to_sd_card();
-
-#endif

+ 0 - 58
.modules/camera_suite/firmware/save_picture_to_sd_card.ino

@@ -1,58 +0,0 @@
-#include "save_picture_to_sd_card.h"
-
-void save_picture_to_sd_card() {
-    sensor_t* cam = esp_camera_sensor_get();
-
-    // Check if the sensor is valid.
-    if (!cam) {
-        Serial.println("Failed to acquire camera sensor");
-        return;
-    }
-
-    // Set pixel format to JPEG for saving picture.
-    cam->set_pixformat(cam, PIXFORMAT_JPEG);
-
-    // Set frame size based on available PSRAM.
-    if (psramFound()) {
-        cam->set_framesize(cam, FRAMESIZE_UXGA);
-    } else {
-        cam->set_framesize(cam, FRAMESIZE_SVGA);
-    }
-
-    // Get a frame buffer from camera.
-    camera_fb_t* frame_buffer = esp_camera_fb_get();
-    if (!frame_buffer) {
-        // Camera capture failed
-        return;
-    }
-
-    if (!SD_MMC.begin()) {
-        // SD Card Mount Failed.
-        esp_camera_fb_return(frame_buffer);
-        return;
-    }
-
-    // Generate a unique filename.
-    String path = "/picture";
-    path += String(millis());
-    path += ".jpg";
-
-    fs::FS& fs = SD_MMC;
-    File file = fs.open(path.c_str(), FILE_WRITE);
-
-    if (!file) {
-        // Failed to open file in writing mode
-    } else {
-        if (file.write(frame_buffer->buf, frame_buffer->len) !=
-            frame_buffer->len) {
-            // Failed to write the image to the file
-        }
-        file.close(); // Close the file in any case.
-    }
-
-    // Update framesize back to the default.
-    cam->set_framesize(cam, FRAMESIZE_QQVGA);
-
-    // Return the frame buffer back to the camera driver.
-    esp_camera_fb_return(frame_buffer);
-}

+ 0 - 1
.modules/geiger/.gitremote

@@ -1 +0,0 @@
-https://github.com/nmrr/flipperzero-geigercounter main

+ 0 - 224
.modules/geiger/README.md

@@ -1,224 +0,0 @@
-# flipperzero-geigercounter
-☢☢ A geiger counter application for the Flipper Zero ☢☢
-
-![banner](https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/logo.jpg)
-(banner has been made with **Midjourney**)
-
-
-You need a **geiger counter** board to run this application, this board can be used: https://aliexpress.com/item/1005004074447209.html
-
-You also need jumper wires to connect the board on the **Flipper Zero**.
-
-**Note 1:** This board uses a **J305** geiger tube. According this [website](https://www.rhelectronics.store/j305-glassy-geiger-muller-tube-nuclear-radiation-sensor) gamma conversion factor is **0.0081** for this tube. This value has been declared in the header of the source file so you can change it easily if needed. Incorrect conversion factor will give false measurements when **Sv** or **Rad** is selected.
-
-**Note 2:** **J305** geiger tube is only sensible to **beta** and **gamma** rays. **Alpha** rays cannot be detected. 
-
-**Usable** radioactive sources: 
-- natural uranium (alpha, beta, gamma)
-- natural thorium (alpha, beta, gamma)
-- radium-226 (alpha, beta, gamma)
-- cobalt-60 (beta & gamma)
-- iodine-131 (beta & gamma)
-
-**Not really usable** radioactive sources (must be in contact with the geiger tube to be detected): 
-- americium-241 (alpha & low gamma, some strong beta/gamma rays are emitted during radioactive cascade or due to the presence of radioisotope impurities)
-- high purity metallic uranium/thorium (same as am241)
-
-
-**Totaly unusable** radioactive sources: 
-- polonium-210 (pure alpha)
-- tritium (very low beta)
-
-
-The geiger counter board can be powered with +5V power pin of the **Flipper Zero**. This pin will automatically be enabled when the program is launched. 
-
-Output pin for measure on arduino cannot be used on the **Flipper Zero** because output voltage is too low. You can use jack out port instead. Just cut audio jack cable and connect audio channel (left, right or both together) with a cut half male jumper wire to **A7** GPIO:
-
-<p align="center"><img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/jack.png" width=40% height=40%></p>
-
-Black wire is usually used for the ground (sleeve on the schematic). You can use a multimeter to be sure or simply test other wires.
-
-Global schema:
-
-<p align="center"><img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/schema.jpg" width=75% height=75%></p>
-
-UI of the application:
-
-<p align="center"><img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper3.png" width=33% height=33%></p>
-
-**CPS**: **c**ounts **p**er **s**econd (instantaneous measure of the radioactivity). CPS is alway displayed on the left corner.
-
-**CPM**: **c**ounts **p**er **m**inute (the sum of CPS over a period of one minute). Other units of measurement can be chosen with **Left/Right**.
-
-New CPS bar measure appears on the left every second.
-
-## Build the program
-
-Assuming the toolchain is already installed, copy **flipper_geiger** directory to **applications_user**
-
-Plug your **Flipper Zero** and build the geiger counter:
-```
-./fbt launch_app APPSRC=applications_user/flipper_geiger
-```
-
-The program will automatically be launched after compilation
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper1.png" width=25% height=25%>
-
-**A4** GPIO can be connected on **A7** GPIO to test this application without using a geiger tube. **A4** GPIO is generating a signal whose frequency changes every second.
-
-**Button assignments**: 
-
-button  | function
-------------- | -------------
-**Ok** *[long press]*  | Clear the graph
-**Left/Right** *[short press]* | Choose unit on the right corner (cpm, μSv/h, mSv/y, Rad/h, mRad/h, uRad/h), **cps** on the left is always displayed
-**Up** *[long press]*  | Enable/disable recording, led of **Flipper Zero** is colored in red when recording
-**Up/Down** *[short press]*  | Zoom/unzoom 
-**Down** *[long press]*  | Display version of the application
-**Back** *[long press]*  | Exit
-
-If you don't want to build this application, just simply copy **flipper_geiger.fap** on your **Flipper Zero** 
-
-Build has been made with official toolchain, **API Mismatch** error may appear if you are using custom firmware. You can bypass this error but the program may crash.
-
-## Use cases
-
-Ambient radioactivity (descendants of radon gas are detected, not radon itself):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper2.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper8.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper9.png" width=25% height=25%>
-
-Measure of uranium ore piece inside a lead container:
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper3.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper12.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper13.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper14.png" width=25% height=25%>
-
-**Note:** measures in **Sv** or **Rad** are not precise
-
-Measure of uranium ore piece (the most radioactive part):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper4.png" width=25% height=25%>
-
-Measure of radium dial pointers:
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper5.png" width=25% height=25%>
-
-All previous measures in a row (the scale of the graph is automatically adjusted):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper6.png" width=25% height=25%>
-
-Measure of uranium orange pottery:
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper10.png" width=25% height=25%>
-
-Measure of americium-241 button from a smoke detector (descendants of americium or radioisotope impurities are detected, not americium itself):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper11.png" width=25% height=25%>
-
-**A4** GPIO on **A7** GPIO (to test this program without a geiger tube):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/flipper7.png" width=25% height=25%>
-
-Zoom levels (the third picture is the default zoom):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/zoom0.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/zoom1.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/zoom2.png" width=25% height=25%> <img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/zoom3.png" width=25% height=25%>
-
-Version of the application (press down button during 1 sec to display version):
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/version.png" width=25% height=25%>
-
-## Recording function
-
-Output **CSV** files are stored at the root of SD card. Date & time are set in the name file (example: **geiger-2023-07-03--23-48-15.csv**)
-
-Data sample:
-
-epoch  | cps
-------------- | -------------
-0  | 10
-1  | 14
-2  | 8
-3  | 11
-4  | 9
-
-## Atomic Dice Roller
-
-<p align="center"><img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/dice.jpg" width=25% height=25%></p>
-
-I maintain another application that uses the **geiger board** to roll dice by using radioactivity: https://github.com/nmrr/flipperzero-atomicdiceroller
-
-## Gallery/video of the community
-
-[BRD8 [Reddit]](https://www.reddit.com/user/BRD8/) - https://www.reddit.com/r/flipperzero/comments/110062z/am_i_a_hacker_now_mom/: 
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/user/abQXuEz.jpg" width=50% height=50%>
-
-[Funbob235 [Reddit]](https://www.reddit.com/user/Funbob235/) - https://www.reddit.com/r/flipperzero/comments/13m1qly/testing_of_the_geiger_counter/: 
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/user/testing-of-the-geiger-counter-v0-3zv9gdq4nt0b1.jpg" width=50% height=50%>
-
-[Axewarior [Reddit]](https://www.reddit.com/user/axewarior/) - https://www.reddit.com/r/flipperzero/comments/14krjs2/gieger_counter/
-
-<img src="https://github.com/nmrr/flipperzero-geigercounter/blob/main/img/user/IMG-1552.jpg" width=50% height=50%>
-
-[Seanclark2409 [YouTube]](https://www.youtube.com/@seanclark2409) (click on the picture to see the video): 
-
-[![Watch the video](https://img.youtube.com/vi/JQB2jvY1oZ0/maxresdefault.jpg)](https://youtu.be/JQB2jvY1oZ0)
-
-[Boboso5676 [YouTube]](https://www.youtube.com/@boboso5676) (click on the picture to see the video):
-
-[![Watch the video](https://img.youtube.com/vi/jYQlC2NJScQ/maxresdefault.jpg)](https://youtu.be/jYQlC2NJScQ)
-
-[Talking Sasquach [YouTube]](https://www.youtube.com/@TalkingSasquach) (click on the picture to see the video):
-
-[![Watch the video](https://img.youtube.com/vi/-I57_S_AXYY/maxresdefault.jpg)](https://youtu.be/-I57_S_AXYY)
-
-## What's next ?
-
-Here are some nice ideas to improve this app:
-
-* ~~Save output data in XML / JSON file~~ **DONE !** Output data are stored in CSV (lighter than XML / JSON and easier to parse)
-* ~~Use the geiger board as random number generator~~ **DONE !** A separate project uses the same geiger board to roll dice: https://github.com/nmrr/flipperzero-atomicdiceroller
-* Send data on the air in real time to monitor remotly
-* Buzz when it gets dangerous like a dosimeter
-
-## Changelog
-
-* 2023-08-06
-  * Code optimization (shift operation on CPS array has been removed)
-  * Version section has been added
-
-* 2023-07-03
-  * Data recording function has been added
-
-* 2023-06-25
-  * Add zoom capability
-  * User gallery has been added
-
-* 2023-06-08
-  * Bug fix
-
-* 2023-04-11
-  * More usable/unusable sources
-  * Rad unit has been added
-  * Code refactoring by replacing old mutex call by new method
-
-* 2023-03-01
-  * Usable/unusable sources have been added
-
-* 2023-02-26
-  * More clarity about how to connect audio jack cable on A7 GPIO
-
-* 2023-02-02
-  * μSv/h and mSv/y have been added
-  * 5V pin is now automatically enabled when the program is launched
-
-* 2023-01-15
-  * Code fix & optimizations
-  * More events can be handled without any issue
-
-* 2023-01-09
-  * Code fix
-  * Global schema has been added
-
-* 2023-01-08
-  * Initial release

BIN
.modules/geiger/flipper_geiger.fap


+ 0 - 13
.modules/geiger/flipper_geiger/application.fam

@@ -1,13 +0,0 @@
-App(
-    appid="flipper_geiger",
-    name="[J305] Geiger Counter",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="flipper_geiger_app",
-    cdefines=["APP_GEIGER"],
-    requires=[
-        "gui",
-    ],
-    stack_size=2 * 1024,
-    fap_icon="geiger.png",
-    fap_category="GPIO",
-)

+ 0 - 383
.modules/geiger/flipper_geiger/flipper_geiger.c

@@ -1,383 +0,0 @@
-// CC0 1.0 Universal (CC0 1.0)
-// Public Domain Dedication
-// https://github.com/nmrr
-
-#include <stdio.h>
-#include <furi.h>
-#include <gui/gui.h>
-#include <input/input.h>
-#include <notification/notification_messages.h>
-#include <furi_hal_random.h>
-#include <furi_hal_pwm.h>
-#include <furi_hal_power.h>
-
-#include <storage/storage.h>
-#include <stream/buffered_file_stream.h>
-
-#include <locale/locale.h>
-
-#define SCREEN_SIZE_X 128
-#define SCREEN_SIZE_Y 64
-
-// FOR J305 GEIGER TUBE
-#define CONVERSION_FACTOR 0.0081
-
-typedef enum {
-    EventTypeInput,
-    ClockEventTypeTick,
-    EventGPIO,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} EventApp;
-
-typedef struct {
-    FuriMutex* mutex;
-    uint32_t cps, cpm;
-    uint32_t line[SCREEN_SIZE_X];
-    float coef;
-    uint8_t data;
-    uint8_t zoom;
-    uint8_t newLinePosition;
-    uint8_t version;
-} mutexStruct;
-
-static void draw_callback(Canvas* canvas, void* ctx) 
-{
-    furi_assert(ctx);
-
-    mutexStruct* mutexVal = ctx;
-    mutexStruct mutexDraw;
-    furi_mutex_acquire(mutexVal->mutex, FuriWaitForever);
-    memcpy(&mutexDraw, mutexVal, sizeof(mutexStruct));
-    furi_mutex_release(mutexVal->mutex);
-
-    if (mutexDraw.version == 0)
-    {
-        char buffer[32];
-        if (mutexDraw.data == 0) snprintf(buffer, sizeof(buffer), "%ld cps - %ld cpm", mutexDraw.cps, mutexDraw.cpm);
-        else if (mutexDraw.data == 1) snprintf(buffer, sizeof(buffer), "%ld cps - %.2f uSv/h", mutexDraw.cps, ((double)mutexDraw.cpm*(double)CONVERSION_FACTOR));
-        else if (mutexDraw.data == 2) snprintf(buffer, sizeof(buffer), "%ld cps - %.2f mSv/y", mutexDraw.cps, (((double)mutexDraw.cpm*(double)CONVERSION_FACTOR))*(double)8.76);
-        else if (mutexDraw.data == 3) snprintf(buffer, sizeof(buffer), "%ld cps - %.4f Rad/h", mutexDraw.cps, ((double)mutexDraw.cpm*(double)CONVERSION_FACTOR)/(double)10000);
-        else if (mutexDraw.data == 4) snprintf(buffer, sizeof(buffer), "%ld cps - %.2f mR/h", mutexDraw.cps, ((double)mutexDraw.cpm*(double)CONVERSION_FACTOR)/(double)10);
-        else snprintf(buffer, sizeof(buffer), "%ld cps - %.2f uR/h", mutexDraw.cps, ((double)mutexDraw.cpm*(double)CONVERSION_FACTOR)*(double)100);
-
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, buffer);
-
-        uint8_t linePosition = mutexDraw.newLinePosition;
-
-        if (mutexDraw.zoom == 0)
-        {
-            for (int i=0;i<SCREEN_SIZE_X;i+=8)
-            {
-                if (linePosition != 0) linePosition--;
-                else linePosition = SCREEN_SIZE_X - 1;
-
-                float Y = SCREEN_SIZE_Y-(mutexDraw.line[linePosition]*mutexDraw.coef);
-                for (int j=0;j<8;j++)canvas_draw_line(canvas, i+j, Y, i+j, SCREEN_SIZE_Y);
-            }
-        }
-        else if (mutexDraw.zoom == 1)
-        {
-            for (int i=0;i<SCREEN_SIZE_X;i+=4)
-            {
-                if (linePosition != 0) linePosition--;
-                else linePosition = SCREEN_SIZE_X - 1;
-
-                float Y = SCREEN_SIZE_Y-(mutexDraw.line[linePosition]*mutexDraw.coef);
-                for (int j=0;j<4;j++)canvas_draw_line(canvas, i+j, Y, i+j, SCREEN_SIZE_Y);
-            }
-        }
-        else if (mutexDraw.zoom == 2)
-        {
-            for (int i=0;i<SCREEN_SIZE_X;i+=2)
-            {
-                if (linePosition != 0) linePosition--;
-                else linePosition = SCREEN_SIZE_X - 1;
-
-                float Y = SCREEN_SIZE_Y-(mutexDraw.line[linePosition]*mutexDraw.coef);
-                for (int j=0;j<2;j++)canvas_draw_line(canvas, i+j, Y, i+j, SCREEN_SIZE_Y);
-            }
-        }
-        else if (mutexDraw.zoom == 3)
-        {
-            for (int i=0;i<SCREEN_SIZE_X;i++)
-            {
-                if (linePosition != 0) linePosition--;
-                else linePosition = SCREEN_SIZE_X - 1;
-
-                float Y = SCREEN_SIZE_Y-(mutexDraw.line[linePosition]*mutexDraw.coef);
-                canvas_draw_line(canvas, i, Y, i, SCREEN_SIZE_Y);
-            }
-        }
-    }
-    else
-    {
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignBottom, "Geiger Counter");
-        canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignBottom, "Version 20230806");
-        canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignBottom, "github.com/nmrr");
-    }
-}
-
-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);
-
-    uint32_t randomNumber = furi_hal_random_get();
-    randomNumber &= 0xFFF;
-    if (randomNumber == 0) randomNumber = 1;
-
-    furi_hal_pwm_set_params(FuriHalPwmOutputIdLptim2PA4, randomNumber, 50);
-
-    FuriMessageQueue* queue = ctx;
-    EventApp event = {.type = ClockEventTypeTick};
-    furi_message_queue_put(queue, &event, 0);
-}
-
-static void gpiocallback(void* ctx) {
-    furi_assert(ctx);
-    FuriMessageQueue* queue = ctx;
-    EventApp event = {.type = EventGPIO};
-    furi_message_queue_put(queue, &event, 0);
-}
-
-int32_t flipper_geiger_app() 
-{
-    EventApp event;
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp));
-
-    furi_hal_gpio_init(&gpio_ext_pa7, GpioModeInterruptFall, GpioPullUp, GpioSpeedVeryHigh);
-    furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, 5, 50);
-
-    mutexStruct mutexVal;
-    mutexVal.cps = 0;
-    mutexVal.cpm = 0;
-    for (int i=0;i<SCREEN_SIZE_X;i++) mutexVal.line[i] = 0;
-    mutexVal.coef = 1;
-    mutexVal.data = 0;
-    mutexVal.zoom = 2;
-    mutexVal.newLinePosition = 0;
-    mutexVal.version = 0;
-
-    uint32_t counter = 0;
-
-    mutexVal.mutex= furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!mutexVal.mutex) {
-        furi_message_queue_free(event_queue);
-        return 255;
-    }
-
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, draw_callback, &mutexVal.mutex);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    furi_hal_gpio_add_int_callback(&gpio_ext_pa7, gpiocallback, event_queue);
-
-    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);
-
-    // ENABLE 5V pin
-
-    // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering
-    uint8_t attempts = 0;
-    while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
-        furi_hal_power_enable_otg();
-        furi_delay_ms(10);
-    }
-
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    Stream* file_stream = buffered_file_stream_alloc(storage);
-    FuriString* dataString = furi_string_alloc();
-    uint32_t epoch = 0;
-    uint8_t recordData = 0;
-
-    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
-
-    while(1) 
-    {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever);
-        
-        uint8_t screenRefresh = 0;
-
-        if (event_status == FuriStatusOk)
-        {   
-            if(event.type == EventTypeInput) 
-            {
-                if(event.input.key == InputKeyBack && event.input.type == InputTypeLong) 
-                {
-                    break;
-                }
-                else if(event.input.key == InputKeyOk && event.input.type == InputTypeLong)
-                {
-                    counter = 0;
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-
-                    mutexVal.cps = 0;
-                    mutexVal.cpm = 0;
-                    for (uint8_t i=0;i<SCREEN_SIZE_X;i++) mutexVal.line[i] = 0;
-                    mutexVal.newLinePosition = 0;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-                }
-                else if(event.input.key == InputKeyUp && event.input.type == InputTypeLong)
-                {
-                    if (recordData == 0) 
-                    {
-                        notification_message(notification, &sequence_set_only_red_255);
-
-                        FuriHalRtcDateTime datetime;
-                        furi_hal_rtc_get_datetime(&datetime);
-
-                        char path[64];
-                        snprintf(path, sizeof(path), EXT_PATH("/geiger-%.4d-%.2d-%.2d--%.2d-%.2d-%.2d.csv"), datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second);
-
-                        buffered_file_stream_open(file_stream, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
-                        furi_string_printf(dataString, "epoch,cps\n");
-                        stream_write_string(file_stream, dataString);
-                        epoch = 0;
-                        recordData = 1;
-                    }
-                    else
-                    {
-                        buffered_file_stream_close(file_stream);
-                        notification_message(notification, &sequence_reset_red);
-                        recordData = 0;
-                    }
-                }
-                else if((event.input.key == InputKeyLeft && event.input.type == InputTypeShort))
-                {
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-
-                    if (mutexVal.data != 0) mutexVal.data--;
-                    else mutexVal.data = 5;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-                }
-                else if((event.input.key == InputKeyRight && event.input.type == InputTypeShort))
-                {
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-
-                    if (mutexVal.data != 5) mutexVal.data++;
-                    else mutexVal.data = 0;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-                }
-                else if((event.input.key == InputKeyUp && event.input.type == InputTypeShort))
-                {
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-                    if (mutexVal.zoom != 0) mutexVal.zoom--;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-
-                }
-                else if((event.input.key == InputKeyDown && event.input.type == InputTypeShort))
-                {
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-                    if (mutexVal.zoom != 3) mutexVal.zoom++;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-                }
-                else if((event.input.key == InputKeyDown && event.input.type == InputTypeLong))
-                {
-                    furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-                    if (mutexVal.version == 0) mutexVal.version = 1;
-                    else mutexVal.version = 0;
-
-                    screenRefresh = 1;
-                    furi_mutex_release(mutexVal.mutex);
-                }
-            }
-            else if (event.type == ClockEventTypeTick)
-            {
-                if (recordData == 1)
-                {
-                    furi_string_printf(dataString, "%lu,%lu\n", epoch++, counter);
-                    stream_write_string(file_stream, dataString);
-                }
-
-                furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
-
-                mutexVal.line[mutexVal.newLinePosition] = counter;
-                mutexVal.cps = counter;
-                counter = 0;
-
-                mutexVal.cpm = mutexVal.line[mutexVal.newLinePosition];
-                uint32_t max = mutexVal.line[mutexVal.newLinePosition];
-                uint8_t linePosition = mutexVal.newLinePosition;
-
-                for (int i=1;i<SCREEN_SIZE_X;i++)
-                {
-                    if (linePosition != 0) linePosition--;
-                    else linePosition = SCREEN_SIZE_X - 1;
-
-                    if (i < 60) mutexVal.cpm += mutexVal.line[linePosition];
-                    if (mutexVal.line[linePosition] > max) max = mutexVal.line[linePosition];
-                }
-
-                if (max > 0) mutexVal.coef = ((float)(SCREEN_SIZE_Y-15))/((float)max);
-                else mutexVal.coef = 1;
-
-                if (mutexVal.newLinePosition != SCREEN_SIZE_X - 1) mutexVal.newLinePosition++;
-                else mutexVal.newLinePosition = 0;
-
-                screenRefresh = 1;
-                furi_mutex_release(mutexVal.mutex);
-            }
-            else if (event.type == EventGPIO)
-            {
-                counter++;
-            }
-        }
-
-        if (screenRefresh == 1) view_port_update(view_port);
-    }
-
-    if (recordData == 1) 
-    {
-        buffered_file_stream_close(file_stream);
-        notification_message(notification, &sequence_reset_red);
-    }
-
-    furi_string_free(dataString);
-    furi_record_close(RECORD_NOTIFICATION);
-    stream_free(file_stream);
-    furi_record_close(RECORD_STORAGE);
-
-    // Disable 5v power
-    if(furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_disable_otg();
-    }
-
-    furi_hal_gpio_disable_int_callback(&gpio_ext_pa7);
-    furi_hal_gpio_remove_int_callback(&gpio_ext_pa7);
-    furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4);
-    furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(mutexVal.mutex);
-    gui_remove_view_port(gui, view_port);
-    view_port_free(view_port);
-    furi_timer_free(timer);
-    furi_record_close(RECORD_GUI);
-
-    return 0;
-}

BIN
.modules/geiger/flipper_geiger/geiger.png


BIN
.modules/geiger/img/dice.jpg


BIN
.modules/geiger/img/flipper1.png


BIN
.modules/geiger/img/flipper10.png


BIN
.modules/geiger/img/flipper11.png


BIN
.modules/geiger/img/flipper12.png


BIN
.modules/geiger/img/flipper13.png


BIN
.modules/geiger/img/flipper14.png


BIN
.modules/geiger/img/flipper2.png


BIN
.modules/geiger/img/flipper3.png


BIN
.modules/geiger/img/flipper4.png


BIN
.modules/geiger/img/flipper5.png


BIN
.modules/geiger/img/flipper6.png


BIN
.modules/geiger/img/flipper7.png


BIN
.modules/geiger/img/flipper8.png


BIN
.modules/geiger/img/flipper9.png


BIN
.modules/geiger/img/jack.png


BIN
.modules/geiger/img/logo.jpg


BIN
.modules/geiger/img/schema.jpg


BIN
.modules/geiger/img/user/IMG-1552.jpg


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است