diff --git a/.github/hooks/pre-commit b/.github/hooks/pre-commit new file mode 100644 index 00000000000..8e51b40a3ff --- /dev/null +++ b/.github/hooks/pre-commit @@ -0,0 +1,18 @@ +#!/bin/bash + +# Run ufbt lint in the "fap" folder +fap_folder="fap" + +# Change to the root directory of the repository +cd "$(git rev-parse --show-toplevel)" + +# Run ufbt lint in the "fap" folder +if ! (cd "$fap_folder" && ufbt lint); then + echo "Error: ufbt lint failed in the 'fap' folder. Please fix the issues before committing." + exit 1 +else + echo "ufbt lint passed in the 'fap' folder." +fi + +# If everything is okay, exit with a zero status +exit 0 diff --git a/.github/images/video_rechtsanwalt_okan_dogan.png b/.github/images/video_rechtsanwalt_okan_dogan.png new file mode 100644 index 00000000000..ed449d5e4f4 Binary files /dev/null and b/.github/images/video_rechtsanwalt_okan_dogan.png differ diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml new file mode 100644 index 00000000000..1f66c1c2883 --- /dev/null +++ b/.github/workflows/build-dev.yml @@ -0,0 +1,29 @@ +name: "Dev - Build & Upload FAP" +on: + push: + branches: + - dev +jobs: + ufbt-build-action: + runs-on: ubuntu-latest + name: "Build: Dev" + steps: + - name: "Checkout" + uses: actions/checkout@v3 + with: + submodules: recursive + + # Flipper Zero ufbt action + # https://github.com/flipperdevices/flipperzero-ufbt-action + - name: "Build" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 + id: build-app + with: + app-dir: ./fap + sdk-channel: dev + + - name: "Create FAP Download (dev)" + uses: actions/upload-artifact@v3 + with: + name: ${{ github.event.repository.name }}-dev-${{ steps.build-app.outputs.suffix }}.zip + path: ${{ steps.build-app.outputs.fap-artifacts }} diff --git a/.github/workflows/deploy-main.yml b/.github/workflows/build-release.yml similarity index 52% rename from .github/workflows/deploy-main.yml rename to .github/workflows/build-release.yml index 4c333960bb8..70375382483 100644 --- a/.github/workflows/deploy-main.yml +++ b/.github/workflows/build-release.yml @@ -1,44 +1,44 @@ -name: "Build + upload." +name: "Release - Build & Upload FAP" on: push: branches: - # Run on push to main. - main - schedule: - # Run every day at 00:00 UTC (midnight) + # Run every day at 00:00 UTC (midnight) to build the latest release + # for new and upcoming firmware. - cron: "0 0 * * *" - jobs: ufbt-build-action: runs-on: ubuntu-latest strategy: matrix: include: - # - name: dev - # sdk-channel: dev + - name: "dev" + sdk-channel: dev - - name: release - sdk-channel: release + - name: "rc" + sdk-channel: rc - # - name: rc - # sdk-channel: rc + - name: "release" + sdk-channel: release - name: "ufbt: Build for ${{ matrix.name }}" + name: "Build: ${{ matrix.name }}" steps: - - name: Checkout + - name: "Checkout" uses: actions/checkout@v3 with: submodules: recursive - - name: Build with ufbt - uses: flipperdevices/flipperzero-ufbt-action@v0.1.3 + # Flipper Zero ufbt action + # https://github.com/flipperdevices/flipperzero-ufbt-action + - name: "Build" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 id: build-app with: app-dir: ./fap sdk-channel: ${{ matrix.sdk-channel }} - - name: Upload app artifacts + - name: "Create FAP Downloads (dev/release/rc)" uses: actions/upload-artifact@v3 with: name: ${{ github.event.repository.name }}-${{ matrix.name }}-${{ steps.build-app.outputs.suffix }}.zip diff --git a/.github/workflows/lint-pull-request.yml b/.github/workflows/lint-pull-request.yml deleted file mode 100644 index 1a3aebade21..00000000000 --- a/.github/workflows/lint-pull-request.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: "Build test + lint." -on: pull_request -jobs: - ufbt-build-action: - runs-on: ubuntu-latest - name: "ufbt: Build for Release 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 - id: build-app - with: - app-dir: ./fap - sdk-channel: release - - - name: Lint sources - uses: flipperdevices/flipperzero-ufbt-action@v0.1 - with: - app-dir: ./fap - skip-setup: true - task: lint diff --git a/.github/workflows/pull-request-dev.yml b/.github/workflows/pull-request-dev.yml new file mode 100644 index 00000000000..35f5536f57c --- /dev/null +++ b/.github/workflows/pull-request-dev.yml @@ -0,0 +1,30 @@ +name: "Dev PR - Lint & Build Test" +on: + pull_request: + branches: + - dev +jobs: + ufbt-test-build-action: + runs-on: ubuntu-latest + name: "PR Build: dev" + steps: + - name: "Checkout" + uses: actions/checkout@v3 + with: + submodules: recursive + + # Flipper Zero ufbt action + # https://github.com/flipperdevices/flipperzero-ufbt-action + - name: "Build" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 + id: build-app + with: + app-dir: ./fap + sdk-channel: dev + + - name: "Lint" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 + with: + app-dir: ./fap + skip-setup: true + task: lint diff --git a/.github/workflows/pull-request-release.yml b/.github/workflows/pull-request-release.yml new file mode 100644 index 00000000000..1e466d02543 --- /dev/null +++ b/.github/workflows/pull-request-release.yml @@ -0,0 +1,49 @@ +name: "Release PR - Lint & Build Test" +on: + pull_request: + branches: + - main +jobs: + ufbt-test-build-action: + runs-on: ubuntu-latest + # The following builds must pass before release is accepted: + strategy: + matrix: + include: + - name: "dev" + sdk-channel: dev + + - name: "rc" + sdk-channel: rc + + - name: "release" + sdk-channel: release + + name: "PR Build: ${{ matrix.name }}" + steps: + - name: "Checkout" + uses: actions/checkout@v3 + with: + submodules: recursive + + # Flipper Zero ufbt action + # https://github.com/flipperdevices/flipperzero-ufbt-action + - name: "Build" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 + id: build-app + with: + app-dir: ./fap + sdk-channel: ${{ matrix.sdk-channel }} + + - name: "Lint" + uses: flipperdevices/flipperzero-ufbt-action@v0.1 + with: + app-dir: ./fap + skip-setup: true + task: lint + + - name: "Create FAP Download Pre Release (${{ matrix.name }})" + 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 }} diff --git a/README.md b/README.md index 7ded4575970..850da3a64b3 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## Table of Contents - [Introduction](#intro) -- [YouTube](#youtube) +- [Videos](#videos) - [Hardware Requirements](#hardware-requirements) - [Hardware Installation](#hardware-installation) - [Firmware Installation](#firmware-installation) @@ -46,9 +46,11 @@ There will be many more features added in the future! If you have any ideas or s

[ Back to top ]

-## YouTube +## Videos -This section is dedicated to all the fans that have made videos of this project! Thank you! If you have a video you'd like to share, please let me know by opening an issue [here][issues-link]. +This section is dedicated to all the fans that have made videos of this project! Thank you! + +If you have a video you'd like to share, please let me know by opening an issue [here][issues-link].
@@ -58,8 +60,16 @@ This section is dedicated to all the fans that have made videos of this project! **Flipper Zero ESP32 CAM Camera Module** - by TAKEAPART +[https://www.youtube.com/watch?v=cEl5UnWH_Ok](https://www.youtube.com/watch?v=cEl5UnWH_Ok) + [![Flipper Zero ESP32 CAM Camera Module - TAKEAPART](https://img.youtube.com/vi/cEl5UnWH_Ok/0.jpg)](https://www.youtube.com/watch?v=cEl5UnWH_Ok) +**Tech With Kids - Flipper Zero ESP32 Kamera** - by @rechtsanwalt.okan.dogan + +[https://www.instagram.com/reel/C4DrufKoKrb/](https://www.instagram.com/reel/C4DrufKoKrb/) + +[![Flipper Zero ESP32 CAM Camera Module - @rechtsanwalt.okan.dogan](.github/images/video_rechtsanwalt_okan_dogan.png)](https://www.instagram.com/reel/C4DrufKoKrb/) +

[ Back to top ]

@@ -228,6 +238,8 @@ A huge thanks to the following people and projects for making this possible: - This project is based on & forked from the [Flipper Zero Camera Application][flipperzero-camera] by [Z4urce][github-profile-z4urce]. Thanks Z4urce for the inspiration and the great work! - I based this projects application structure on the [Flipper Zero Boilerplate Application][flipper-zero-fap-boilerplate] by [leedave][github-profile-leedave]. Thanks leedave for the great boilerplate application that helped me learn how to structure a Flipper Zero application properly! +- [WillyJL][github-profile-willyjl] for your guidance and wisdom. +- [TalkingSasquach][github-profile-talkingsasquach] for all of your helpful [YouTube videos][youtube-talkingsasquach] and [Discord community][discord-squachtopia]. - The project images were drawn using the a application called "[lopaka][lopaka]" by [sbrin][github-profile-sbrin]. Thanks sbrin for your help in creating the images for this project! - The Flipper Zero community for all your support and feedback! @@ -243,14 +255,14 @@ To contribute to this project, please follow the steps below: 4. Request PR [here][pull-request-link], introduce work via your branch. 5. Wait for review and merge. -When developing the firmware, be sure to download the dependencies by running the `firmware-flash.bat` batch script at the root of this directory. This will download the ESP32-CAM firmware dependencies to the directories defined in the `arduino-cli.yaml` file post-run. Add these dependencies and their directories to your "Include path" in your IDE of choice. I prefer Visual Studio Code, there's a guide on how to get started with that workflow here: +When developing the firmware, be sure to download the dependencies by running the `firmware-assets.bat` batch script at the root of this directory. This will download the ESP32-CAM firmware dependencies (Arduino Build & Git Assets) to your Windows TEMP folder. You can run the same script over again later to remove the temporary files when you're done using them. Once installed, add these dependencies and their directories to your "Include path" in your IDE of choice. I prefer Visual Studio Code; there's a guide on how to get started with that workflow here: https://github.com/CodyTolene/Flipper-Zero-Development-Toolkit Example include path: ```markdown -C:/Users//AppData/Local/Temp/arduino-cli/** +C:/Users//AppData/Local/Temp/arduino-cli/**/** ``` Thank you for any and all contributions to this project, I'm looking forward to seeing what you come up with! If you have any questions, please let me know by opening an issue [here][issues-link]. @@ -283,13 +295,17 @@ Cody Tolene [arduino-ide]: https://www.arduino.cc/en/software [btc-address-link]: https://explorer.btc.com/btc/address/bc1qfx3lvspkj0q077u3gnrnxqkqwyvcku2nml86wmudy7yf2u8edmqq0a5vnt +[discord-squachtopia]: https://discord.gg/squachtopia [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-sbrin]: https://github.com/sbrin +[github-profile-talkingsasquach]: https://github.com/skizzophrenic +[github-profile-willyjl]: https://github.com/Willy-JL [github-profile-z4urce]: https://github.com/Z4urce [issues-link]: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/issues [lopaka]: https://github.com/sbrin/lopaka [pull-request-link]: https://github.com/CodyTolene/Flipper-Zero-Camera-Suite/pulls +[youtube-talkingsasquach]: https://www.youtube.com/@TalkingSasquach diff --git a/fap/assets/.gitkeep b/fap/assets/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/fap/camera_suite.c b/fap/camera_suite.c index 5b14eb81292..c8289d72eaf 100644 --- a/fap/camera_suite.c +++ b/fap/camera_suite.c @@ -1,5 +1,6 @@ #include "camera_suite.h" #include +#include bool camera_suite_custom_event_callback(void* context, uint32_t event) { furi_assert(context); @@ -71,12 +72,6 @@ CameraSuite* camera_suite_app_alloc() { CameraSuiteViewIdCamera, camera_suite_view_camera_get_view(app->camera_suite_view_camera)); - app->camera_suite_view_wifi_camera = camera_suite_view_wifi_camera_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - CameraSuiteViewIdWiFiCamera, - camera_suite_view_wifi_camera_get_view(app->camera_suite_view_wifi_camera)); - app->camera_suite_view_guide = camera_suite_view_guide_alloc(); view_dispatcher_add_view( app->view_dispatcher, @@ -110,7 +105,6 @@ void camera_suite_app_free(CameraSuite* app) { 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, CameraSuiteViewIdWiFiCamera); view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdGuide); view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdAppSettings); view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdCamSettings); @@ -122,7 +116,6 @@ void camera_suite_app_free(CameraSuite* app) { // 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_wifi_camera_free(app->camera_suite_view_wifi_camera); camera_suite_view_guide_free(app->camera_suite_view_guide); button_menu_free(app->button_menu); @@ -138,6 +131,11 @@ void camera_suite_app_free(CameraSuite* app) { /** Main entry point for initialization. */ int32_t camera_suite_app(void* p) { UNUSED(p); + + // Disable expansion protocol to avoid interference with UART Handle + Expansion* expansion = furi_record_open(RECORD_EXPANSION); + expansion_disable(expansion); + CameraSuite* app = camera_suite_app_alloc(); view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); // Init with start scene. @@ -147,5 +145,10 @@ int32_t camera_suite_app(void* p) { camera_suite_save_settings(app); furi_hal_power_suppress_charge_exit(); camera_suite_app_free(app); + + // Return previous state of expansion + expansion_enable(expansion); + furi_record_close(RECORD_EXPANSION); + return 0; } diff --git a/fap/camera_suite.h b/fap/camera_suite.h index 154b08597aa..47cccf963dc 100644 --- a/fap/camera_suite.h +++ b/fap/camera_suite.h @@ -16,7 +16,6 @@ #include "views/camera_suite_view_guide.h" #include "views/camera_suite_view_start.h" #include "views/camera_suite_view_camera.h" -#include "views/camera_suite_view_wifi_camera.h" #include "helpers/camera_suite_storage.h" #define TAG "Camera Suite" @@ -30,7 +29,6 @@ typedef struct { VariableItemList* variable_item_list; CameraSuiteViewStart* camera_suite_view_start; CameraSuiteViewCamera* camera_suite_view_camera; - CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera; CameraSuiteViewGuide* camera_suite_view_guide; uint32_t orientation; uint32_t dither; @@ -46,7 +44,6 @@ typedef enum { CameraSuiteViewIdStartscreen, CameraSuiteViewIdMenu, CameraSuiteViewIdCamera, - CameraSuiteViewIdWiFiCamera, CameraSuiteViewIdGuide, CameraSuiteViewIdAppSettings, CameraSuiteViewIdCamSettings, diff --git a/fap/docs/CHANGELOG.md b/fap/docs/CHANGELOG.md index 4a772567e9c..2638599e02b 100644 --- a/fap/docs/CHANGELOG.md +++ b/fap/docs/CHANGELOG.md @@ -5,6 +5,11 @@ - Full screen 90 degree and 270 degree fill (#6). - WiFi streaming/connection support (#35). +## v1.7 + +- Add support for new Flipper Zero Firmware UART updates. +- Remove staged WiFi streaming/connection support for now. Until I can fully test. + ## v1.6 - Add new splash/start screen. diff --git a/fap/helpers/camera_suite_custom_event.h b/fap/helpers/camera_suite_custom_event.h index eb545b7dbd2..4d472d577a9 100644 --- a/fap/helpers/camera_suite_custom_event.h +++ b/fap/helpers/camera_suite_custom_event.h @@ -15,13 +15,6 @@ typedef enum { CameraSuiteCustomEventSceneCameraRight, CameraSuiteCustomEventSceneCameraOk, CameraSuiteCustomEventSceneCameraBack, - // Scene events: WiFi Camera - CameraSuiteCustomEventSceneWiFiCameraUp, - CameraSuiteCustomEventSceneWiFiCameraDown, - CameraSuiteCustomEventSceneWiFiCameraLeft, - CameraSuiteCustomEventSceneWiFiCameraRight, - CameraSuiteCustomEventSceneWiFiCameraOk, - CameraSuiteCustomEventSceneWiFiCameraBack, // Scene events: Guide CameraSuiteCustomEventSceneGuideUp, CameraSuiteCustomEventSceneGuideDown, diff --git a/fap/helpers/camera_suite_storage.c b/fap/helpers/camera_suite_storage.c index cbc4cf3c608..712346d43b1 100644 --- a/fap/helpers/camera_suite_storage.c +++ b/fap/helpers/camera_suite_storage.c @@ -93,9 +93,9 @@ void camera_suite_read_settings(void* context) { FURI_LOG_E(TAG, "Missing Header Data"); camera_suite_close_config_file(fff_file); camera_suite_close_storage(); + furi_string_free(temp_str); return; } - furi_string_free(temp_str); if(file_version < BOILERPLATE_SETTINGS_FILE_VERSION) { diff --git a/fap/scenes/camera_suite_scene_config.h b/fap/scenes/camera_suite_scene_config.h index fce4c9e8cfa..a9f0e057aeb 100644 --- a/fap/scenes/camera_suite_scene_config.h +++ b/fap/scenes/camera_suite_scene_config.h @@ -1,7 +1,6 @@ ADD_SCENE(camera_suite, start, Start) ADD_SCENE(camera_suite, menu, Menu) ADD_SCENE(camera_suite, camera, Camera) -ADD_SCENE(camera_suite, wifi_camera, WiFiCamera) ADD_SCENE(camera_suite, guide, Guide) ADD_SCENE(camera_suite, app_settings, AppSettings) ADD_SCENE(camera_suite, cam_settings, CamSettings) diff --git a/fap/scenes/camera_suite_scene_menu.c b/fap/scenes/camera_suite_scene_menu.c index a1ca022922a..c6c88038bb4 100644 --- a/fap/scenes/camera_suite_scene_menu.c +++ b/fap/scenes/camera_suite_scene_menu.c @@ -3,8 +3,6 @@ enum SubmenuIndex { /** Camera. */ SubmenuIndexSceneCamera = 10, - /** WiFi Camera */ - SubmenuIndexSceneWiFiCamera, /** Cam settings menu. */ SubmenuIndexCamSettings, /** App settings menu. */ @@ -28,13 +26,6 @@ void camera_suite_scene_menu_on_enter(void* context) { camera_suite_scene_menu_submenu_callback, app); - submenu_add_item( - app->submenu, - "Stream Camera to WiFi", - SubmenuIndexSceneWiFiCamera, - camera_suite_scene_menu_submenu_callback, - app); - submenu_add_item( app->submenu, "Camera Settings", @@ -76,11 +67,6 @@ bool camera_suite_scene_menu_on_event(void* context, SceneManagerEvent event) { app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSceneCamera); scene_manager_next_scene(app->scene_manager, CameraSuiteSceneCamera); return true; - } else if(event.event == SubmenuIndexSceneWiFiCamera) { - scene_manager_set_scene_state( - app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexSceneWiFiCamera); - scene_manager_next_scene(app->scene_manager, CameraSuiteSceneWiFiCamera); - return true; } else if(event.event == SubmenuIndexAppSettings) { scene_manager_set_scene_state( app->scene_manager, CameraSuiteSceneMenu, SubmenuIndexAppSettings); diff --git a/fap/scenes/camera_suite_scene_wifi_camera.c b/fap/scenes/camera_suite_scene_wifi_camera.c deleted file mode 100644 index 2df3db81bf1..00000000000 --- a/fap/scenes/camera_suite_scene_wifi_camera.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "../camera_suite.h" -#include "../helpers/camera_suite_custom_event.h" -#include "../views/camera_suite_view_wifi_camera.h" - -void camera_suite_view_wifi_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_wifi_camera_on_enter(void* context) { - furi_assert(context); - CameraSuite* app = context; - camera_suite_view_wifi_camera_set_callback( - app->camera_suite_view_wifi_camera, camera_suite_view_wifi_camera_callback, app); - view_dispatcher_switch_to_view(app->view_dispatcher, CameraSuiteViewIdWiFiCamera); -} - -bool camera_suite_scene_wifi_camera_on_event(void* context, SceneManagerEvent event) { - CameraSuite* app = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - switch(event.event) { - case CameraSuiteCustomEventSceneWiFiCameraLeft: - case CameraSuiteCustomEventSceneWiFiCameraRight: - case CameraSuiteCustomEventSceneWiFiCameraUp: - case CameraSuiteCustomEventSceneWiFiCameraDown: - // Do nothing. - break; - case CameraSuiteCustomEventSceneWiFiCameraBack: - 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_wifi_camera_on_exit(void* context) { - CameraSuite* app = context; - UNUSED(app); -} \ No newline at end of file diff --git a/fap/views/camera_suite_view_camera.c b/fap/views/camera_suite_view_camera.c index 7d0ebe8a918..e01f6cd4729 100644 --- a/fap/views/camera_suite_view_camera.c +++ b/fap/views/camera_suite_view_camera.c @@ -179,19 +179,33 @@ static void save_image_to_flipper_sd_card(void* model) { 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); + + // Not supported in "Release" F0 build. + // TODO: Remove when DateTime is supported in "Release" F0 build. + // FuriHalRtcDateTime datetime = {0}; + + // Only supported in "RC" & "Dev" builds. + // TODO: Uncomment when DateTime is supported in "Release" F0 build. + // DateTime datetime = {0}; + + // TODO: Uncomment when DateTime is supported in "Release" F0 build. + // furi_hal_rtc_get_datetime(&datetime); + + // Create the file name using DateTime. + // TODO: Uncomment when DateTime is supported in "Release" F0 build. + // 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); + + // Just use a random number for now instead of DateTime. + int random_number = rand(); + furi_string_printf(file_name, EXT_PATH("DCIM/%d.bmp"), random_number); // Open the file for writing. If the file does not exist (it shouldn't), // create it. @@ -281,7 +295,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { UNUSED(model); // Stop camera stream. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'s'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'s'}, 1); furi_delay_ms(50); // Go back to the main menu. @@ -302,13 +316,13 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { if(model->is_inverted) { // Camera: Set invert to false on the ESP32-CAM. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'i'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'i'}, 1); furi_delay_ms(50); model->is_inverted = false; } else { // Camera: Set invert to true on the ESP32-CAM. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'I'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'I'}, 1); furi_delay_ms(50); model->is_inverted = true; @@ -331,13 +345,13 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { if(model->is_dithering_enabled) { // Camera: Disable dithering. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'d'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'d'}, 1); furi_delay_ms(50); model->is_dithering_enabled = false; } else { // Camera: Enable dithering. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'D'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'D'}, 1); furi_delay_ms(50); model->is_dithering_enabled = true; @@ -361,7 +375,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { camera_suite_led_set_rgb(instance->context, 0, 0, 255); // Camera: Increase contrast. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'C'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'C'}, 1); furi_delay_ms(50); instance->callback(CameraSuiteCustomEventSceneCameraUp, instance->context); @@ -382,7 +396,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { camera_suite_led_set_rgb(instance->context, 0, 0, 255); // Camera: Reduce contrast. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'c'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'c'}, 1); furi_delay_ms(50); instance->callback(CameraSuiteCustomEventSceneCameraDown, instance->context); @@ -401,7 +415,7 @@ static bool camera_suite_view_camera_input(InputEvent* event, void* context) { camera_suite_led_set_rgb(instance->context, 0, 0, 255); // @todo - Save picture directly to ESP32-CAM. - // furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'P'}, 1); + // furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'P'}, 1); // Save currently displayed image to the Flipper Zero SD card. save_image_to_flipper_sd_card(model); @@ -435,22 +449,22 @@ static void camera_suite_view_camera_enter(void* context) { CameraSuite* instance_context = instance->context; // Start camera stream. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'S'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'S'}, 1); furi_delay_ms(50); // Get/set dither type. uint8_t dither_type = instance_context->dither; - furi_hal_uart_tx(FuriHalUartIdUSART1, &dither_type, 1); + furi_hal_serial_tx(instance->serial_handle, &dither_type, 1); furi_delay_ms(50); // Make sure the camera is not inverted. - furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'i'}, 1); + furi_hal_serial_tx(instance->serial_handle, (uint8_t[]){'i'}, 1); furi_delay_ms(50); // Toggle flash on or off based on the current state. If the user has this // on the flash will stay on the entire time the user is in the camera view. uint8_t flash_state = instance_context->flash ? 'F' : 'f'; - furi_hal_uart_tx(FuriHalUartIdUSART1, &flash_state, 1); + furi_hal_serial_tx(instance->serial_handle, &flash_state, 1); furi_delay_ms(50); with_view_model( @@ -460,17 +474,16 @@ static void camera_suite_view_camera_enter(void* context) { true); } -static void camera_on_irq_cb(UartIrqEvent uartIrqEvent, uint8_t data, void* context) { - furi_assert(uartIrqEvent); - furi_assert(data); +static void + camera_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { + furi_assert(handle); furi_assert(context); // Cast `context` to `CameraSuiteViewCamera*` and store it in `instance`. CameraSuiteViewCamera* instance = context; - // If `uartIrqEvent` is `UartIrqEventRXNE`, send the data to the - // `camera_rx_stream` and set the `WorkerEventRx` flag. - if(uartIrqEvent == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(instance->camera_rx_stream, &data, 1, 0); furi_thread_flags_set(furi_thread_get_id(instance->camera_worker_thread), WorkerEventRx); } @@ -607,14 +620,13 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() { instance->camera_worker_thread = thread; furi_thread_start(instance->camera_worker_thread); - // Disable console. - furi_hal_console_disable(); + // Allocate the serial handle for the camera. + instance->serial_handle = furi_hal_serial_control_acquire(UART_CH); + furi_check(instance->serial_handle); + furi_hal_serial_init(instance->serial_handle, 230400); - // 115200 is the default baud rate for the ESP32-CAM. - furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400); - - // Enable UART1 and set the IRQ callback. - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, camera_on_irq_cb, instance); + // Start the asynchronous receive. + furi_hal_serial_async_rx_start(instance->serial_handle, camera_on_irq_cb, instance, false); return instance; } @@ -622,17 +634,17 @@ CameraSuiteViewCamera* camera_suite_view_camera_alloc() { void camera_suite_view_camera_free(CameraSuiteViewCamera* instance) { furi_assert(instance); - // Remove the IRQ callback. - furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL); - // Free the worker thread. + furi_thread_flags_set(furi_thread_get_id(instance->camera_worker_thread), WorkerEventStop); + furi_thread_join(instance->camera_worker_thread); furi_thread_free(instance->camera_worker_thread); // Free the allocated stream buffer. furi_stream_buffer_free(instance->camera_rx_stream); - // Re-enable the console. - // furi_hal_console_enable(); + // Deinitialize the serial handle and release the control. + furi_hal_serial_deinit(instance->serial_handle); + furi_hal_serial_control_release(instance->serial_handle); with_view_model( instance->view, UartDumpModel * model, { UNUSED(model); }, true); diff --git a/fap/views/camera_suite_view_camera.h b/fap/views/camera_suite_view_camera.h index d8143fdf614..40cc3c1cd60 100644 --- a/fap/views/camera_suite_view_camera.h +++ b/fap/views/camera_suite_view_camera.h @@ -2,7 +2,8 @@ #include #include -#include +#include +#include #include #include #include @@ -16,6 +17,27 @@ #include "../helpers/camera_suite_custom_event.h" +#ifdef xtreme_settings +/** + * Enable the following line for "Xtreme Firmware" & "Xtreme Apps" (Flipper-XFW). + * + * @see https://github.com/Flipper-XFW/Xtreme-Firmware + * @see https://github.com/Flipper-XFW/Xtreme-Apps +*/ +#define UART_CH (xtreme_settings.uart_esp_channel) +#elif defined momentum_settings +/** + * Enable the following line for "Momentum Firmware" & "Momentum Apps". + * + * @see https://github.com/Next-Flip/Momentum-Firmware + * @see https://github.com/Next-Flip/Momentum-Apps +*/ +#include +#define UART_CH (momentum_settings.uart_esp_channel) +#else +#define UART_CH (FuriHalSerialIdUsart) +#endif + #define BITMAP_HEADER_LENGTH 62 #define FRAME_BIT_DEPTH 1 #define FRAME_BUFFER_LENGTH 1024 @@ -46,6 +68,7 @@ typedef void (*CameraSuiteViewCameraCallback)(CameraSuiteCustomEvent event, void typedef struct CameraSuiteViewCamera { CameraSuiteViewCameraCallback callback; FuriStreamBuffer* camera_rx_stream; + FuriHalSerialHandle* serial_handle; FuriThread* camera_worker_thread; NotificationApp* notification; View* view; diff --git a/fap/views/camera_suite_view_wifi_camera.c b/fap/views/camera_suite_view_wifi_camera.c deleted file mode 100644 index ce0da794706..00000000000 --- a/fap/views/camera_suite_view_wifi_camera.c +++ /dev/null @@ -1,170 +0,0 @@ -#include "../camera_suite.h" -#include -#include -#include -#include -#include -#include "../helpers/camera_suite_haptic.h" -#include "../helpers/camera_suite_speaker.h" -#include "../helpers/camera_suite_led.h" - -void camera_suite_view_wifi_camera_set_callback( - CameraSuiteViewWiFiCamera* instance, - CameraSuiteViewWiFiCameraCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - instance->callback = callback; - instance->context = context; -} - -static void camera_suite_view_wifi_camera_draw(Canvas* canvas, void* model) { - furi_assert(canvas); - furi_assert(model); - - CameraSuiteViewWiFiCameraModel* instance = model; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - canvas_draw_frame(canvas, 0, 0, FRAME_WIDTH, FRAME_HEIGHT); - - canvas_draw_str_aligned(canvas, 3, 3, AlignLeft, AlignTop, "Feature coming soon!"); - - // Draw log from camera. - canvas_draw_str_aligned( - canvas, 3, 13, AlignLeft, AlignTop, furi_string_get_cstr(instance->log)); -} - -static bool camera_suite_view_wifi_camera_input(InputEvent* event, void* context) { - furi_assert(context); - furi_assert(event); - - CameraSuiteViewWiFiCamera* instance = context; - - if(event->type == InputTypeRelease) { - switch(event->key) { - default: - with_view_model( - instance->view, - CameraSuiteViewWiFiCameraModel * model, - { - UNUSED(model); - // Stop all sounds, reset the LED. - 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) { - switch(event->key) { - case InputKeyBack: { - with_view_model( - instance->view, - CameraSuiteViewWiFiCameraModel * model, - { - UNUSED(model); - - // Stop camera WiFi stream. - // furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'w'}, 1); - // furi_delay_ms(50); - - // Go back to the main menu. - instance->callback(CameraSuiteCustomEventSceneCameraBack, instance->context); - }, - true); - break; - } - case InputKeyLeft: - case InputKeyRight: - case InputKeyUp: - case InputKeyDown: - case InputKeyOk: - case InputKeyMAX: - default: { - break; - } - } - } - - return false; -} - -static void camera_suite_view_wifi_camera_exit(void* context) { - furi_assert(context); -} - -static void camera_suite_view_wifi_camera_model_init(CameraSuiteViewWiFiCameraModel* const model) { - model->log = furi_string_alloc(); - furi_string_reserve(model->log, 4096); -} - -static void camera_suite_view_wifi_camera_enter(void* context) { - furi_assert(context); - - // Get the camera suite instance context. - CameraSuiteViewWiFiCamera* instance = (CameraSuiteViewWiFiCamera*)context; - - // Start wifi camera stream. - // furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[]){'W'}, 1); - - with_view_model( - instance->view, - CameraSuiteViewWiFiCameraModel * model, - { camera_suite_view_wifi_camera_model_init(model); }, - true); -} - -CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc() { - // Allocate memory for the instance - CameraSuiteViewWiFiCamera* instance = malloc(sizeof(CameraSuiteViewWiFiCamera)); - - // Allocate the view object - instance->view = view_alloc(); - - // Allocate model - view_allocate_model( - instance->view, ViewModelTypeLocking, sizeof(CameraSuiteViewWiFiCameraModel)); - - // Set context for the view (furi_assert crashes in events without this) - view_set_context(instance->view, instance); - - // Set draw callback - view_set_draw_callback(instance->view, (ViewDrawCallback)camera_suite_view_wifi_camera_draw); - - // Set input callback - view_set_input_callback(instance->view, camera_suite_view_wifi_camera_input); - - // Set enter callback - view_set_enter_callback(instance->view, camera_suite_view_wifi_camera_enter); - - // Set exit callback - view_set_exit_callback(instance->view, camera_suite_view_wifi_camera_exit); - - with_view_model( - instance->view, - CameraSuiteViewWiFiCameraModel * model, - { camera_suite_view_wifi_camera_model_init(model); }, - true); - - return instance; -} - -void camera_suite_view_wifi_camera_free(CameraSuiteViewWiFiCamera* instance) { - furi_assert(instance); - - with_view_model( - instance->view, - CameraSuiteViewWiFiCameraModel * model, - { furi_string_free(model->log); }, - true); - view_free(instance->view); - free(instance); -} - -View* camera_suite_view_wifi_camera_get_view(CameraSuiteViewWiFiCamera* instance) { - furi_assert(instance); - return instance->view; -} diff --git a/fap/views/camera_suite_view_wifi_camera.h b/fap/views/camera_suite_view_wifi_camera.h deleted file mode 100644 index 64c6285784a..00000000000 --- a/fap/views/camera_suite_view_wifi_camera.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../helpers/camera_suite_custom_event.h" - -typedef void (*CameraSuiteViewWiFiCameraCallback)(CameraSuiteCustomEvent event, void* context); - -typedef struct CameraSuiteViewWiFiCamera { - View* view; - CameraSuiteViewCameraCallback callback; - void* context; -} CameraSuiteViewWiFiCamera; - -typedef struct { - FuriString* log; -} CameraSuiteViewWiFiCameraModel; - -CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera_alloc(); - -View* camera_suite_view_wifi_camera_get_view(CameraSuiteViewWiFiCamera* camera_suite_static); - -void camera_suite_view_wifi_camera_free(CameraSuiteViewWiFiCamera* camera_suite_static); - -void camera_suite_view_wifi_camera_set_callback( - CameraSuiteViewWiFiCamera* camera_suite_view_wifi_camera, - CameraSuiteViewWiFiCameraCallback callback, - void* context); diff --git a/firmware-assets.bat b/firmware-assets.bat new file mode 100644 index 00000000000..0a52a4be331 --- /dev/null +++ b/firmware-assets.bat @@ -0,0 +1,117 @@ +@echo off +setlocal EnableDelayedExpansion + +rem λ + +set CLI_TEMP=%TEMP%\arduino-cli +set ARDUINO_CLI_CONFIG_FILE=--config-file %CD%\firmware\arduino-cli.yaml +set CLI_FOUND_FOLLOW_UP=0 +set GITHUB_HOOKS_FOLDER=%CD%\.github\hooks +set GIT_HOOKS_FOLDER=%CD%\.git\hooks + +chcp 65001 > nul +echo ┏┓ ┓ ┏┳┓ ┓ +echo ┃ ┏┓┏┫┓┏ ┃ ┏┓┃┏┓┏┓┏┓ +echo ┗┛┗┛┗┻┗┫ ┻ ┗┛┗┗ ┛┗┗ +echo ┛ https://github.com/CodyTolene +echo. +echo Flipper Zero - ESP32-CAM Development Assets - Windows 10+ +echo https://github.com/CodyTolene/Flipper-Zero-Camera-Suite +echo. +echo ------------------------------------------------------------------------------ +echo This will install all assets needed to get you started with ESP32-CAM firmware +echo development. These files will be installed to the following directory: +echo. +echo "%CLI_TEMP%" +echo. +echo Once installed you can add them to the "Include path" in your IDE of choice. +echo. +echo Notes: +echo - Development asset files will take up approx. 3.5GB of storage space. +echo - You can reinstall or delete the asset files by re-running this script. +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. + 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 are 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 successfully. Continuing... +) + +echo Checking and setting arduino-cli config... +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.data %CLI_TEMP%\data +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.downloads %CLI_TEMP%\downloads +arduino-cli %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 not exist "%CLI_TEMP%\user" ( + set /a "DATA_FLAG+=1" +) +if %DATA_FLAG% gtr 0 ( + :installAssets + arduino-cli %ARDUINO_CLI_CONFIG_FILE% core update-index + arduino-cli %ARDUINO_CLI_CONFIG_FILE% core install esp32:esp32 + goto :wrapUp +) else ( + set /p SHOULD_REINSTALL="Assets already installed. Reinstall? (Y/N): " + if /i "!SHOULD_REINSTALL!"=="Y" ( + rmdir /s /q %CLI_TEMP% + goto :installAssets + ) + set /p DELETE_TEMP="Would you like to remove the previously installed dependencies? (Y/N): " + if /i "!DELETE_TEMP!"=="Y" ( + rmdir /s /q %CLI_TEMP% + goto :end + ) +) + +:wrapUp +echo Configuring Git pre-commit hook... +copy /Y "%GITHUB_HOOKS_FOLDER%" "%GIT_HOOKS_FOLDER%" +echo Resetting arduino-cli config back to defaults... +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.data C:\temp\arduino-cli\data +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.downloads C:\temp\arduino-cli\staging +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.user C:\temp\arduino-cli\user + +echo. +echo The ESP32-CAM development dependencies were installed successfully. +echo. +echo ------------------------------------------------------------------------------ +echo. +echo You can now add the following path to your IDEs "Include path" setting: +echo. +echo "%CLI_TEMP%\**" +echo. + +:end +echo ------------------------------------------------------------------------------ +echo. +echo Fin - Happy programming friend. +echo. +pause +exit /b diff --git a/firmware-flash.bat b/firmware-flash.bat index e1be4307666..5f956985982 100644 --- a/firmware-flash.bat +++ b/firmware-flash.bat @@ -5,10 +5,10 @@ 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 COMPILE_FLAG=%CLI_TEMP%\.compile.flag +set ARDUINO_CLI_CONFIG_FILE=--config-file %CD%\firmware\arduino-cli.yaml set DEFAULT_BOARD_FQBN=esp32:esp32:esp32cam -set FIRMWARE_SRC=firmware\firmware.ino +set FIRMWARE_SRC=%CD%\firmware\firmware.ino set SELECTED_BOARD=%DEFAULT_BOARD_FQBN% chcp 65001 > nul @@ -22,12 +22,16 @@ 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. In -echo the USB-UART Bridge config menu, make sure the following configuration is set: +echo Then on your Flipper Zero open the GPIO menu and select USB-UART Bridge. In +echo the USB-UART Bridge config menu make sure the following configuration is set: echo - USB Channel = 1 (on newer firmware) echo - Baudrate = Host -echo - UART Pins = 13,14 +echo - UART Pins = 13 and 14 echo - RTS/DTR Pins = None +echo. +echo Notes: +echo - Temporary installation files will take up approx. 3.5GB of storage space. +echo - You will have the option to delete the temporary files on completion. echo ------------------------------------------------------------------------------ echo. pause @@ -39,27 +43,28 @@ 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 Extract the "arduino-cli.exe" file to the same directory as this script. echo. - echo When the file is ready, press any key to check again. + 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 If you are 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 File "arduino-cli.exe" found successfully. 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 Checking and setting arduino-cli configs... +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.data %CLI_TEMP%\data +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.downloads %CLI_TEMP%\downloads +arduino-cli %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" @@ -67,9 +72,12 @@ if not exist "%CLI_TEMP%\data" ( if not exist "%CLI_TEMP%\downloads" ( set /a "DATA_FLAG+=1" ) +if not exist "%CLI_TEMP%\user" ( + 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 + arduino-cli %ARDUINO_CLI_CONFIG_FILE% core update-index + arduino-cli %ARDUINO_CLI_CONFIG_FILE% core install esp32:esp32 ) else ( echo Assets already installed. Skipping... ) @@ -100,7 +108,7 @@ 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 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. @@ -113,7 +121,7 @@ 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% +arduino-cli %ARDUINO_CLI_CONFIG_FILE% upload -p %PORT_NUMBER% --fqbn !SELECTED_BOARD! %FIRMWARE_SRC% if !ERRORLEVEL! EQU 0 ( goto :uploadSuccess ) else ( @@ -128,7 +136,7 @@ if !ERRORLEVEL! EQU 0 ( goto :uploadFirmware ) else ( echo. - echo If you're still having issues, feel free to open a ticket at the following link: + echo If you are 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): " @@ -146,16 +154,16 @@ if !ERRORLEVEL! EQU 0 ( 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 +echo Resetting arduino-cli config back to defaults... +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.data C:\temp\arduino-cli\data +arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.downloads C:\temp\arduino-cli\staging +arduino-cli %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 Fin - Happy programming friend. echo. pause exit /b @@ -172,9 +180,9 @@ if /i "%USE_DEFAULT_BOARD%"=="N" ( 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 Compiling firmware - this will take a moment... echo. -arduino-cli %CONFIG_FILE% compile --fqbn !SELECTED_BOARD! %FIRMWARE_SRC% +arduino-cli %ARDUINO_CLI_CONFIG_FILE% compile --fqbn !SELECTED_BOARD! %FIRMWARE_SRC% if %ERRORLEVEL% EQU 0 ( echo. echo Firmware compiled successfully. @@ -187,15 +195,16 @@ if %ERRORLEVEL% EQU 0 ( goto :compileFirmware ) 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 + echo Resetting arduino-cli config back to defaults... + arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.data C:\temp\arduino-cli\data + arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.downloads C:\temp\arduino-cli\staging + arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set directories.user C:\temp\arduino-cli\user + arduino-cli %ARDUINO_CLI_CONFIG_FILE% config set library.enable_unsafe_install false 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 Cleanup completed, press any key to exit. + echo Cleanup completed - press any key to exit. echo. pause exit /b diff --git a/arduino-cli.yaml b/firmware/arduino-cli.yaml similarity index 100% rename from arduino-cli.yaml rename to firmware/arduino-cli.yaml diff --git a/firmware/camera.cpp b/firmware/camera.cpp index 32b1695403f..cd2861b689f 100644 --- a/firmware/camera.cpp +++ b/firmware/camera.cpp @@ -9,7 +9,7 @@ void initialize_camera() { } } -void set_camera_defaults(CameraFunction camera_function) { +void set_camera_defaults() { // Get the camera sensor reference. sensor_t *cam = esp_camera_sensor_get(); @@ -19,12 +19,6 @@ void set_camera_defaults(CameraFunction camera_function) { cam->set_sharpness(cam, 0); // Set initial sharpness. cam->set_vflip(cam, true); // Set initial vertical flip. cam->set_hmirror(cam, false); // Set initial horizontal mirror. - - if (camera_function == CAMERA_FUNCTION_SERIAL) { - // TODO - } else if (camera_function == CAMERA_FUNCTION_WIFI) { - // TODO - } } void turn_flash_off() { diff --git a/firmware/camera.h b/firmware/camera.h index f5362b6e597..fa2f727762b 100644 --- a/firmware/camera.h +++ b/firmware/camera.h @@ -11,7 +11,7 @@ void initialize_camera(); /** Reset the camera to the default settings. */ -void set_camera_defaults(CameraFunction camera_function); +void set_camera_defaults(); /** Turn the flash off. */ void turn_flash_off(); diff --git a/firmware/camera_config.cpp b/firmware/camera_config.cpp index 3c8f38afda8..614c8e744e1 100644 --- a/firmware/camera_config.cpp +++ b/firmware/camera_config.cpp @@ -3,7 +3,7 @@ /** The camera configuration model. */ camera_config_t camera_config; -void set_camera_config_defaults(CameraFunction camera_function) { +void set_camera_config_defaults() { camera_config.ledc_channel = LEDC_CHANNEL_0; camera_config.ledc_timer = LEDC_TIMER_0; camera_config.pin_d0 = Y2_GPIO_NUM; @@ -24,16 +24,8 @@ void set_camera_config_defaults(CameraFunction camera_function) { camera_config.pin_reset = RESET_GPIO_NUM; camera_config.xclk_freq_hz = 20000000; - if (camera_function == CAMERA_FUNCTION_SERIAL) { - camera_config.pixel_format = PIXFORMAT_GRAYSCALE; - camera_config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; - camera_config.fb_count = 1; - camera_config.frame_size = FRAMESIZE_QQVGA; - } else if (camera_function == CAMERA_FUNCTION_WIFI) { - camera_config.pixel_format = PIXFORMAT_JPEG; - camera_config.jpeg_quality = 8; - camera_config.fb_count = 1; - camera_config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; - camera_config.frame_size = FRAMESIZE_SVGA; - } + camera_config.pixel_format = PIXFORMAT_GRAYSCALE; + camera_config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; + camera_config.fb_count = 1; + camera_config.frame_size = FRAMESIZE_QQVGA; } diff --git a/firmware/camera_config.h b/firmware/camera_config.h index 76a89c56de6..22fef227d87 100644 --- a/firmware/camera_config.h +++ b/firmware/camera_config.h @@ -9,7 +9,7 @@ /** The camera configuration model. */ extern camera_config_t camera_config; -/** Set the camera configuration defaults based on camera function. */ -void set_camera_config_defaults(CameraFunction camera_function); +/** Set the camera configuration defaults. */ +void set_camera_config_defaults(); #endif diff --git a/firmware/camera_model.cpp b/firmware/camera_model.cpp index 88d8718ba50..164ba07d666 100644 --- a/firmware/camera_model.cpp +++ b/firmware/camera_model.cpp @@ -3,16 +3,9 @@ /** The camera model. */ CameraModel camera_model; -void set_camera_model_defaults(CameraFunction camera_function) { - if (camera_function == CAMERA_FUNCTION_SERIAL) { - camera_model.isDitheringEnabled = true; - } else if (camera_function == CAMERA_FUNCTION_WIFI) { - camera_model.isDitheringEnabled = false; - } - +void set_camera_model_defaults() { + camera_model.isDitheringEnabled = true; camera_model.isFlashEnabled = false; camera_model.isInvertEnabled = false; - camera_model.isStreamToSerialEnabled = false; - camera_model.isStreamToWiFiEnabled = false; camera_model.ditherAlgorithm = FLOYD_STEINBERG; } diff --git a/firmware/camera_model.h b/firmware/camera_model.h index 8f85f2e60a1..dbf741e7198 100644 --- a/firmware/camera_model.h +++ b/firmware/camera_model.h @@ -10,11 +10,6 @@ typedef enum { STUCKI, } DitheringAlgorithm; -typedef enum { - CAMERA_FUNCTION_SERIAL, - CAMERA_FUNCTION_WIFI, -} CameraFunction; - typedef struct { /** Flag to enable or disable dithering. */ bool isDitheringEnabled; @@ -24,8 +19,6 @@ typedef struct { bool isInvertEnabled; /** Flag to stop or start the stream to the Flipper Zero. */ bool isStreamToSerialEnabled; - /** Flag to stop or start the stream to WiFi. */ - bool isStreamToWiFiEnabled; /** Holds the currently selected dithering algorithm. */ DitheringAlgorithm ditherAlgorithm; } CameraModel; @@ -33,7 +26,7 @@ typedef struct { /** The camera model. */ extern CameraModel camera_model; -/** Set the camera model to the default values depending on the camera use. */ -void set_camera_model_defaults(CameraFunction camera_function); +/** Set the camera model to the default values. */ +void set_camera_model_defaults(); #endif diff --git a/firmware/firmware.h b/firmware/firmware.h index 376ffc146f1..ed9c1b63e01 100644 --- a/firmware/firmware.h +++ b/firmware/firmware.h @@ -7,7 +7,6 @@ #include "camera_config.h" #include "camera_model.h" #include "stream_to_serial.h" -#include "stream_to_wifi.h" #include "process_serial_input.h" void setup(); diff --git a/firmware/firmware.ino b/firmware/firmware.ino index 3f9f139a22a..9c73b7776b7 100644 --- a/firmware/firmware.ino +++ b/firmware/firmware.ino @@ -1,20 +1,22 @@ #include "firmware.h" void setup() { + camera_model.isStreamToSerialEnabled = false; + // Begin serial communication. Serial.begin(230400); // Set initial camera configs for serial streaming. - set_camera_config_defaults(CAMERA_FUNCTION_SERIAL); + set_camera_config_defaults(); // Set initial camera model for serial streaming. - set_camera_model_defaults(CAMERA_FUNCTION_SERIAL); + set_camera_model_defaults(); // Initialize the camera. initialize_camera(); // Set initial camera settings for serial streaming. - set_camera_defaults(CAMERA_FUNCTION_SERIAL); + set_camera_defaults(); } // Main loop of the program. @@ -24,9 +26,6 @@ void loop() { if (camera_model.isStreamToSerialEnabled) { // Process the camera image and output to serial. stream_to_serial(); - } else if (camera_model.isStreamToWiFiEnabled) { - // Stream the camera output to WiFi. - stream_to_wifi(); } else if (camera_model.isFlashEnabled) { // Not currently streaming, turn the flash off if it's enabled. turn_flash_off(); diff --git a/firmware/process_serial_input.cpp b/firmware/process_serial_input.cpp index 590f82e3d16..22e3c69a1b6 100644 --- a/firmware/process_serial_input.cpp +++ b/firmware/process_serial_input.cpp @@ -36,24 +36,12 @@ void process_serial_input() { case 'I': set_inverted(true); break; - case 'P': - // @todo - // save_picture_to_sd_card(); - break; case 's': stop_serial_stream(); break; case 'S': start_serial_stream(); break; - case 'w': - // @todo - // stop_wifi_stream(); - break; - case 'W': - // @todo - // start_wifi_stream(); - break; case '0': set_dithering_algorithm(FLOYD_STEINBERG); break; diff --git a/firmware/process_serial_input.h b/firmware/process_serial_input.h index 0da95eb57c4..6316bc21704 100644 --- a/firmware/process_serial_input.h +++ b/firmware/process_serial_input.h @@ -7,7 +7,6 @@ #include "camera_model.h" #include "pins.h" #include "stream_to_serial.h" -#include "stream_to_wifi.h" /** Handle the serial input commands coming from the Flipper Zero. */ void process_serial_input(); diff --git a/firmware/stream_to_serial.cpp b/firmware/stream_to_serial.cpp index 04889c2b406..92e23ffe752 100644 --- a/firmware/stream_to_serial.cpp +++ b/firmware/stream_to_serial.cpp @@ -59,10 +59,9 @@ void stream_to_serial() { } void start_serial_stream() { - camera_model.isStreamToWiFiEnabled = false; - set_camera_config_defaults(CAMERA_FUNCTION_SERIAL); - set_camera_model_defaults(CAMERA_FUNCTION_SERIAL); - set_camera_defaults(CAMERA_FUNCTION_SERIAL); + set_camera_config_defaults(); + set_camera_model_defaults(); + set_camera_defaults(); camera_model.isStreamToSerialEnabled = true; } diff --git a/firmware/stream_to_wifi.cpp b/firmware/stream_to_wifi.cpp deleted file mode 100644 index 12681c1c6ed..00000000000 --- a/firmware/stream_to_wifi.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "stream_to_wifi.h" - -const char *ssid = "ESP"; -const char *password = "test123"; -bool is_wifi_streaming = false; - -void stream_to_wifi() { - if (!is_wifi_streaming) { - WiFi.mode(WIFI_AP); - WiFi.softAP(ssid, password); - WiFi.setSleep(false); - - while (WiFi.status() != WL_CONNECTED) { - delay(500); - Serial.print("."); - } - - Serial.println("WiFi connected"); - - start_server(); - - Serial.print("Camera Ready! Use 'http://"); - Serial.print(WiFi.softAPIP()); - Serial.println("' to connect"); - - Serial.flush(); - - is_wifi_streaming = true; - } -} - -// Todo -void start_server() { - // server.on("/", HTTP_GET, []() { - // if (!camera_model.isStreamToWiFiEnabled) { - // start_wifi_stream(); - // } - // server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - // server.sendHeader("Pragma", "no-cache"); - // server.sendHeader("Expires", "-1"); - // server.setContentLength(CONTENT_LENGTH_UNKNOWN); - // server.send(200, "text/html", ""); - // server.sendContent(""); - // server.sendContent(""); - // server.sendContent(""); - // }); - // server.on("/stream", HTTP_GET, []() { - // if (!camera_model.isStreamToWiFiEnabled) { - // start_wifi_stream(); - // } - // String boundary = "ESP32CAM"; - // String header = "--" + boundary + "\r\nContent-Type: image/jpeg\r\nContent-Length: "; - // String jpeg = dither_image(); - // String response = header + jpeg.length() + "\r\n\r\n" + jpeg + "\r\n"; - // server.send(200, "multipart/x-mixed-replace; boundary=" + boundary, response); - // }); - // server.begin(); -} - -void start_wifi_stream() { - turn_flash_on(); // Physical test indicator that we're streaming. - camera_model.isStreamToSerialEnabled = false; - set_camera_config_defaults(CAMERA_FUNCTION_WIFI); - set_camera_model_defaults(CAMERA_FUNCTION_WIFI); - set_camera_defaults(CAMERA_FUNCTION_WIFI); - // @todo - Dynamically set ssid and password via prompts. - camera_model.isStreamToWiFiEnabled = true; - turn_flash_off(); -} - -void stop_wifi_stream() { - if (is_wifi_streaming) { - WiFi.softAPdisconnect(true); - is_wifi_streaming = false; - camera_model.isStreamToWiFiEnabled = false; - } -} diff --git a/firmware/stream_to_wifi.h b/firmware/stream_to_wifi.h deleted file mode 100644 index aab970eab43..00000000000 --- a/firmware/stream_to_wifi.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef STREAM_TO_WIFI_H -#define STREAM_TO_WIFI_H - -// #include "ESPAsyncWebServer.h" -// #include -// #include - -#include -#include -#include - -#include "camera.h" -#include "camera_model.h" -#include "dither_image.h" - -/** Start the WiFi camera stream. */ -void stream_to_wifi(); - -/** Start the WiFi camera stream. */ -void start_wifi_stream(); - -/** Start the WiFi server. */ -void start_server(); - -/** Stop the WiFi camera stream. */ -void stop_wifi_stream(); - -#endif