├── .github └── workflows │ ├── build_firmware.yml │ └── build_release_firmware.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── air_firmware_esp32cam ├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── dependencies.lock ├── esp32-cam-fpv-esp32cam.code-workspace ├── logo2.png ├── main │ ├── CMakeLists.txt │ ├── component.mk │ └── dummy.cpp ├── partitions.csv ├── platformio.ini ├── platformio_upload.py ├── sdkconfig.defaults └── sdkconfig.esp32cam ├── air_firmware_esp32s3sense ├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── dependencies.lock ├── esp32-cam-fpv-esp32s3sense.code-workspace ├── logo2.png ├── main │ ├── CMakeLists.txt │ ├── component.mk │ └── dummy.cpp ├── partitions.csv ├── platformio.ini ├── platformio_upload.py ├── sdkconfig.defaults └── sdkconfig.esp32s3sense ├── air_firmware_esp32s3sense_ov5640 ├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── dependencies.lock ├── esp32-cam-fpv-esp32s3sense_ov5640.code-workspace ├── logo2.png ├── main │ ├── CMakeLists.txt │ ├── component.mk │ └── dummy.cpp ├── partitions.csv ├── platformio.ini ├── platformio_upload.py ├── sdkconfig.defaults └── sdkconfig.esp32s3sense ├── components ├── air │ ├── favicon.ico │ ├── file_server.cpp │ ├── index.html │ ├── main.cpp │ ├── main.h │ ├── msp.cpp │ ├── msp.h │ ├── nvs_args.cpp │ ├── nvs_args.h │ ├── osd.cpp │ ├── osd.h │ ├── python_test_server.py │ ├── queue.cpp │ ├── queue.h │ ├── temperature_sensor.cpp │ ├── temperature_sensor.h │ ├── upload_script.html │ ├── wifi.cpp │ └── wifi.h ├── common │ ├── CMakeLists.txt │ ├── avi.cpp │ ├── avi.h │ ├── circular_buffer.cpp │ ├── circular_buffer.h │ ├── component.mk │ ├── crc.cpp │ ├── crc.h │ ├── fec.cpp │ ├── fec.h │ ├── fec_codec.cpp │ ├── fec_codec.h │ ├── hx_mavlink_parser.cpp │ ├── hx_mavlink_parser.h │ ├── jpeg_parser.cpp │ ├── jpeg_parser.h │ ├── packet_filter.cpp │ ├── packet_filter.h │ ├── packets.cpp │ ├── packets.h │ ├── safe_printf.cpp │ ├── safe_printf.h │ ├── structures.cpp │ ├── structures.h │ ├── util.cpp │ ├── util.h │ ├── vcd_profiler.cpp │ └── vcd_profiler.h └── esp32-camera │ ├── .github │ └── workflows │ │ ├── build.yml │ │ ├── stale.yml │ │ └── upload_component.yml │ ├── .gitignore │ ├── CMakeLists.txt │ ├── Kconfig │ ├── LICENSE │ ├── README.md │ ├── component.mk │ ├── conversions │ ├── esp_jpg_decode.c │ ├── include │ │ ├── esp_jpg_decode.h │ │ └── img_converters.h │ ├── jpge.cpp │ ├── private_include │ │ ├── jpge.h │ │ └── yuv.h │ ├── to_bmp.c │ ├── to_jpg.cpp │ └── yuv.c │ ├── driver │ ├── cam_hal.c │ ├── esp_camera.c │ ├── include │ │ ├── esp_camera.h │ │ └── sensor.h │ ├── private_include │ │ ├── cam_hal.h │ │ ├── sccb.h │ │ └── xclk.h │ ├── sccb.c │ └── sensor.c │ ├── examples │ ├── CMakeLists.txt │ ├── Makefile │ ├── camera_example │ │ ├── CMakeLists.txt │ │ ├── main │ │ │ ├── CMakeLists.txt │ │ │ ├── idf_component.yml │ │ │ └── take_picture.c │ │ └── sdkconfig.defaults │ ├── main │ │ ├── CMakeLists.txt │ │ ├── component.mk │ │ └── take_picture.c │ └── sdkconfig.defaults │ ├── idf_component.yml │ ├── library.json │ ├── sensors │ ├── bf20a6.c │ ├── bf3005.c │ ├── gc0308.c │ ├── gc032a.c │ ├── gc2145.c │ ├── nt99141.c │ ├── ov2640.c │ ├── ov3660.c │ ├── ov5640.c │ ├── ov7670.c │ ├── ov7725.c │ ├── private_include │ │ ├── bf20a6.h │ │ ├── bf20a6_regs.h │ │ ├── bf20a6_settings.h │ │ ├── bf3005.h │ │ ├── bf3005_regs.h │ │ ├── gc0308.h │ │ ├── gc0308_regs.h │ │ ├── gc0308_settings.h │ │ ├── gc032a.h │ │ ├── gc032a_regs.h │ │ ├── gc032a_settings.h │ │ ├── gc2145.h │ │ ├── gc2145_regs.h │ │ ├── gc2145_settings.h │ │ ├── nt99141.h │ │ ├── nt99141_regs.h │ │ ├── nt99141_settings.h │ │ ├── ov2640.h │ │ ├── ov2640_regs.h │ │ ├── ov2640_settings.h │ │ ├── ov3660.h │ │ ├── ov3660_regs.h │ │ ├── ov3660_settings.h │ │ ├── ov5640.h │ │ ├── ov5640_regs.h │ │ ├── ov5640_settings.h │ │ ├── ov7670.h │ │ ├── ov7670_regs.h │ │ ├── ov7725.h │ │ ├── ov7725_regs.h │ │ ├── sc030iot.h │ │ ├── sc030iot_settings.h │ │ ├── sc031gs.h │ │ ├── sc031gs_settings.h │ │ ├── sc101iot.h │ │ └── sc101iot_settings.h │ ├── sc030iot.c │ ├── sc031gs.c │ └── sc101iot.c │ ├── target │ ├── esp32 │ │ └── ll_cam.c │ ├── esp32s2 │ │ ├── ll_cam.c │ │ ├── private_include │ │ │ └── tjpgd.h │ │ └── tjpgd.c │ ├── esp32s3 │ │ └── ll_cam.c │ ├── jpeg_include │ │ └── tjpgd.h │ ├── private_include │ │ └── ll_cam.h │ ├── tjpgd.c │ └── xclk.c │ └── test │ ├── CMakeLists.txt │ ├── component.mk │ ├── pictures │ ├── test_inside.jpeg │ ├── test_outside.jpeg │ └── testimg.jpeg │ └── test_camera.c ├── doc ├── adding_gs_software_to_ruby_sd_radxa3.md ├── adding_gs_software_to_ruby_sd_rpi.md ├── building_gs_sd_radxa_3w.md ├── building_gs_sd_rpi.md ├── composite_output.md ├── connecting_fan.md ├── datasheets │ ├── ESP32_CAM_V1.6.pdf │ ├── OV5640 SOC Auto Focus Application Notes R1.0.pdf │ ├── OV5640_Software_app_note_parallel.pdf │ ├── OV5640_datasheet.pdf │ ├── RTL8812AU-CG.pdf │ ├── RTL8812AU.Schematics.pdf │ ├── SKY85601.pdf │ ├── SKY85703.pdf │ ├── XIAO_ESP32S3_ExpBoard_v1.0_SCH.pdf │ └── XIAO_ESP32S3_SCH_v1.1.pdf ├── development.md ├── flashing_esp32_cam.md ├── flashing_esp32s3sense.md ├── images │ ├── 2dbi_dipole.jpg │ ├── comfast.jpg │ ├── debug_menu.jpg │ ├── dfminispirit.jpg │ ├── displayport_osd.jpg │ ├── esp32cam_led.jpg │ ├── esp32cam_pinout.png │ ├── esp32s3sense_j3.jpg │ ├── esp32s3sense_pinout.png │ ├── esp32s3sense_shell.jpg │ ├── esp32s3sense_shell1.jpg │ ├── esp32s3sense_shell2.jpg │ ├── esp32s3sense_shell3.jpg │ ├── esp32s3sense_shell_plane.jpg │ ├── espwebtool.png │ ├── espwebtool_s3sense.png │ ├── fan_pwm_buck_pcb.jpg │ ├── fan_pwm_buck_schematics.png │ ├── fan_pwm_simple_pcb.jpg │ ├── fan_pwm_simple_schematics.png │ ├── flash_download_tool_esp32.png │ ├── flash_download_tool_esp32s3.png │ ├── flash_download_tool_files.png │ ├── flash_download_tool_files_s3sense.png │ ├── gs.jpg │ ├── gs2_drawing.jpg │ ├── gs2_glasses.jpg │ ├── gs2_overview.jpg │ ├── gs2_wifi_usb.jpg │ ├── gs_drawing1.jpg │ ├── gs_drawing2.jpg │ ├── gs_glasses.jpg │ ├── gs_internal_wifi.jpg │ ├── gs_pinout.png │ ├── gs_pinout_radxa.png │ ├── joystick_pinout.png │ ├── latency.jpg │ ├── lens.jpg │ ├── long_flex_cable.jpg │ ├── mavlink2_rc.png │ ├── moxon.jpg │ ├── osd_elements.png │ ├── osd_menu.jpg │ ├── ov5640.jpg │ ├── ov5640_500w_pinout.png │ ├── ov5640_pinout1.jpg │ ├── ov5640_pinout2.png │ ├── pcb_antena.jpg │ ├── radxa3w_gs.jpg │ ├── radxa3w_gs1.jpg │ ├── radxa3w_gs2.jpg │ ├── radxa3w_gs3.jpg │ ├── radxa3w_gs4.jpg │ ├── radxa3w_gs5.jpg │ ├── radxa_gs_pinout.png │ ├── rpi2w_composite_pinout.png │ ├── rpi4_composite_pinout.png │ ├── rtl8812au.jpg │ ├── shell_14.jpg │ ├── shell_14_main.jpg │ ├── shell_14_tube.jpg │ ├── stats.jpg │ ├── vcd_profiling.png │ └── xiaoesp32s3sense.jpg ├── installing_fan_control_service.md ├── making_release_img_from_sd_radxa.md ├── making_release_img_from_sd_rpi.md ├── ov5640.md ├── prebuilt_gs_image.md ├── rpi_int_wifi_drivers │ ├── 4.14.79+ │ │ └── readme.md │ └── 5.10.103-v7+ │ │ ├── install.sh │ │ └── readme.md ├── running_gs_on_fedora.md ├── running_gs_on_ubuntu.md ├── software_for_radxa.md ├── software_for_rpi.md └── vs_code_remote_development.md ├── gs ├── .gitignore ├── .vscode │ └── settings.json ├── Makefile ├── assets │ └── osd_fonts │ │ ├── INAV_default_24.png │ │ ├── WS_ARDU_BLI_24.png │ │ ├── WS_ARDU_CON_24.png │ │ ├── WS_ARDU_SPH_24.png │ │ ├── WS_BFx1_Blinder_24.png │ │ ├── WS_BFx1_Europa_24.png │ │ ├── WS_BFx1_Hemi_24.png │ │ ├── WS_BFx1_Nexus_24.png │ │ ├── WS_BFx1_Sphere_24.png │ │ ├── WS_INAV_Europa_24.png │ │ ├── WS_IN_Blinder_24.png │ │ ├── WS_IN_Conthrax_24.png │ │ ├── WS_IN_Europa_24.png │ │ ├── WS_IN_Hemi_24.png │ │ ├── WS_IN_Nexus_24.png │ │ ├── WS_IN_Sphere_24.png │ │ ├── font_btfl.png │ │ └── user_ardu_24.png ├── gs.code-workspace ├── launch.sh └── src │ ├── Clock.h │ ├── Comms.cpp │ ├── Comms.h │ ├── IHAL.h │ ├── Log.h │ ├── PI_HAL.cpp │ ├── PI_HAL.h │ ├── Video_Decoder.cpp │ ├── Video_Decoder.h │ ├── cpu_temp.cpp │ ├── cpu_temp.h │ ├── droid_sans_font.cpp │ ├── fmt │ ├── args.h │ ├── chrono.h │ ├── color.h │ ├── compile.h │ ├── core.h │ ├── format-inl.h │ ├── format.cc │ ├── format.h │ ├── locale.h │ ├── os.cc │ ├── os.h │ ├── ostream.h │ ├── posix.h │ ├── printf.h │ └── ranges.h │ ├── fontwalksnail.cpp │ ├── fontwalksnail.h │ ├── gpio_buttons.cpp │ ├── gpio_buttons.h │ ├── main.cpp │ ├── main.h │ ├── osd.cpp │ ├── osd.h │ ├── osd_menu.cpp │ ├── osd_menu.h │ ├── socket.cpp │ ├── socket.h │ ├── stats.h │ └── utils │ ├── Pool.h │ ├── ini.h │ ├── lodepng.cpp │ ├── lodepng.h │ ├── radiotap │ ├── ieee80211_radiotap.h │ ├── radiotap.cpp │ └── radiotap.h │ ├── utils.cpp │ └── utils.h └── scripts ├── boot_selection.sh ├── fan_control.sh ├── install_on_ruby.sh ├── pishrink.sh └── zero_free_space.sh /.github/workflows/build_firmware.yml: -------------------------------------------------------------------------------- 1 | name: Build Firmware 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - development 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | project: [air_firmware_esp32cam, air_firmware_esp32s3sense, air_firmware_esp32s3sense_ov5640] 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | 21 | - name: Set up Python 22 | uses: actions/setup-python@v4 23 | with: 24 | python-version: '3.x' 25 | 26 | - name: Install required Python dependencies 27 | run: | 28 | python -m pip install --upgrade pip setuptools 29 | 30 | - name: Install PlatformIO lastest 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install platformio 34 | 35 | - name: Build firmware 36 | run: | 37 | platformio run -d ${{ matrix.project }} 38 | 39 | - name: Upload firmware binaries 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: ${{ matrix.project }} 43 | path: | 44 | ${{ matrix.project }}/.pio/build/**/bootloader.bin 45 | ${{ matrix.project }}/.pio/build/**/firmware.bin 46 | ${{ matrix.project }}/.pio/build/**/flash_args 47 | ${{ matrix.project }}/.pio/build/**/partitions.bin 48 | ${{ matrix.project }}/.pio/build/**/ota_data_initial.bin 49 | -------------------------------------------------------------------------------- /.github/workflows/build_release_firmware.yml: -------------------------------------------------------------------------------- 1 | name: Build Release Firmware 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | project: [air_firmware_esp32cam, air_firmware_esp32s3sense, air_firmware_esp32s3sense_ov5640] 13 | 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: '3.x' 22 | 23 | - name: Install required Python dependencies 24 | run: | 25 | python -m pip install --upgrade pip setuptools 26 | 27 | - name: Install PlatformIO latest 28 | run: | 29 | python -m pip install --upgrade pip 30 | pip install platformio 31 | 32 | - name: Build firmware 33 | run: | 34 | platformio run -d ${{ matrix.project }} 35 | 36 | - name: Create output directory 37 | run: mkdir -p release_zips 38 | 39 | - name: Zip firmware files 40 | run: | 41 | out="release_zips/${{ matrix.project }}.zip" 42 | zip -j "$out" \ 43 | ${{ matrix.project }}/.pio/build/**/bootloader.bin \ 44 | ${{ matrix.project }}/.pio/build/**/firmware.bin \ 45 | ${{ matrix.project }}/.pio/build/**/flash_args \ 46 | ${{ matrix.project }}/.pio/build/**/partitions.bin \ 47 | ${{ matrix.project }}/.pio/build/**/ota_data_initial.bin || true 48 | 49 | - name: Upload zip as artifact 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: ${{ matrix.project }}.zip 53 | path: release_zips/${{ matrix.project }}.zip 54 | 55 | release: 56 | needs: build 57 | runs-on: ubuntu-latest 58 | 59 | steps: 60 | - name: Download all artifacts 61 | uses: actions/download-artifact@v4 62 | 63 | - name: Create release tag 64 | id: tag 65 | run: echo "tag=release-$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV 66 | 67 | - name: Create GitHub draft release 68 | uses: softprops/action-gh-release@v1 69 | with: 70 | tag_name: ${{ env.tag }} 71 | name: Firmware Release ${{ env.tag }} 72 | draft: true 73 | files: | 74 | **/*.zip 75 | env: 76 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 77 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | *.mjpeg 35 | 36 | tasks.json 37 | build.sh 38 | deploy.sh 39 | .DS_Store 40 | sdkconfig.old 41 | air_firmware/build 42 | .vscode 43 | /air_firmware/sdkconfig.dev 44 | gs/gs.ini 45 | release 46 | components/build -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | [submodule "gs/src/imgui"] 3 | path = gs/src/imgui 4 | url = https://github.com/ocornut/imgui.git 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 jeanleflambeur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = false 9 | trim_trailing_whitespace = true 10 | 11 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .pioenvs 3 | .piolibdeps 4 | .vscode/.browse.c_cpp.db* 5 | .vscode/c_cpp_properties.json 6 | .vscode/launch.json 7 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | set(EXTRA_COMPONENT_DIRS "../components") 4 | set(COMPONENT_REQUIRES "common") 5 | 6 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 7 | project(air_firmware) 8 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/dependencies.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | idf: 3 | component_hash: null 4 | source: 5 | type: idf 6 | version: 5.3.1 7 | manifest_hash: 8c9ed1ee79e168fc798d5db5ef9ac5ba263464baa9235d488074bbda72ce922b 8 | target: esp32 9 | version: 1.0.0 10 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/esp32-cam-fpv-esp32cam.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "name": "components", 8 | "path": "../components/" 9 | } 10 | ], 11 | "settings": { 12 | "files.associations": { 13 | "array": "cpp", 14 | "string": "cpp", 15 | "string_view": "cpp", 16 | "initializer_list": "cpp", 17 | "utility": "cpp", 18 | "*.tcc": "cpp", 19 | "system_error": "cpp", 20 | "deque": "cpp", 21 | "unordered_map": "cpp", 22 | "vector": "cpp", 23 | "atomic": "cpp", 24 | "bit": "cpp", 25 | "cctype": "cpp", 26 | "clocale": "cpp", 27 | "cmath": "cpp", 28 | "compare": "cpp", 29 | "concepts": "cpp", 30 | "cstdarg": "cpp", 31 | "cstddef": "cpp", 32 | "cstdint": "cpp", 33 | "cstdio": "cpp", 34 | "cstdlib": "cpp", 35 | "cstring": "cpp", 36 | "cwchar": "cpp", 37 | "cwctype": "cpp", 38 | "map": "cpp", 39 | "set": "cpp", 40 | "exception": "cpp", 41 | "algorithm": "cpp", 42 | "functional": "cpp", 43 | "iterator": "cpp", 44 | "memory": "cpp", 45 | "memory_resource": "cpp", 46 | "numeric": "cpp", 47 | "random": "cpp", 48 | "tuple": "cpp", 49 | "type_traits": "cpp", 50 | "iosfwd": "cpp", 51 | "istream": "cpp", 52 | "limits": "cpp", 53 | "new": "cpp", 54 | "numbers": "cpp", 55 | "ostream": "cpp", 56 | "sstream": "cpp", 57 | "stdexcept": "cpp", 58 | "streambuf": "cpp", 59 | "cinttypes": "cpp", 60 | "typeinfo": "cpp" 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /air_firmware_esp32cam/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32cam/logo2.png -------------------------------------------------------------------------------- /air_firmware_esp32cam/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(srcs dummy.cpp 2 | ../../components/air/main.cpp 3 | ../../components/air/file_server.cpp 4 | ../../components/air/nvs_args.cpp 5 | ../../components/air/queue.cpp 6 | ../../components/air/wifi.cpp 7 | ../../components/air/osd.cpp 8 | ../../components/air/msp.cpp 9 | ../../components/air/temperature_sensor.cpp 10 | ) 11 | 12 | idf_component_register(SRCS "${srcs}" 13 | INCLUDE_DIRS "../../components/esp32-camera/target/private_include/" 14 | EMBED_FILES "../../components/air/favicon.ico" "../../components/air/index.html" 15 | REQUIRES esp_timer) 16 | 17 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/main/dummy.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32cam/main/dummy.cpp -------------------------------------------------------------------------------- /air_firmware_esp32cam/partitions.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | factory, app, factory, 0x10000, 0x150000, 7 | ota_0, app, ota_0, 0x160000, 0x150000, 8 | ota_1, app, ota_1, 0x2B0000, 0x150000, -------------------------------------------------------------------------------- /air_firmware_esp32cam/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | src_dir = main 13 | default_envs = esp32cam 14 | 15 | [env:esp32cam] 16 | platform = espressif32@ 6.9.0 17 | ;platform = espressif32@ 6.6.0 //fails to startup!!! 18 | ;platform = espressif32@ 6.5.0 //compiles with python 3.11 or below 19 | ;platform = espressif32@ ^5.4.0 20 | framework = espidf 21 | 22 | board=esp32cam 23 | 24 | build_flags = -DBOARD_ESP32CAM 25 | 26 | monitor_speed = 115200 27 | 28 | ;esp32 boot log coloring enable 29 | monitor_raw = yes 30 | 31 | ;esp32 crash log decoding 32 | ;monitor_filters = esp32_exception_decoder 33 | 34 | build_type = release 35 | lib_extra_dirs = 36 | ../components/air/ 37 | ../components/common/ 38 | ../components/esp32-camera/ 39 | 40 | board_build.partitions = partitions.csv 41 | 42 | board_build.embed_txtfiles = 43 | ../components/air/index.html 44 | ../components/air/favicon.ico 45 | 46 | ;for esp32cam-mb 47 | monitor_dtr = 0 48 | monitor_rts = 0 49 | 50 | ;OTA upload: 51 | ;extra_scripts = platformio_upload.py 52 | ;upload_protocol = custom 53 | ;upload_url = http://192.168.4.1/ota 54 | 55 | 56 | -------------------------------------------------------------------------------- /air_firmware_esp32cam/platformio_upload.py: -------------------------------------------------------------------------------- 1 | # Allows PlatformIO to upload directly to ElegantOTA 2 | # 3 | # To use: 4 | # - copy this script into the same folder as your platformio.ini 5 | # - set the following for your project in platformio.ini: 6 | # 7 | # extra_scripts = platformio_upload.py 8 | # upload_protocol = custom 9 | # upload_url = 10 | # 11 | # An example of an upload URL: 12 | # upload_url = http://192.168.1.123/update 13 | # also possible: upload_url = http://domainname/update 14 | 15 | import requests 16 | import hashlib 17 | from urllib.parse import urlparse 18 | import time 19 | import os 20 | Import("env") 21 | 22 | try: 23 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 24 | from tqdm import tqdm 25 | except ImportError: 26 | env.Execute("$PYTHONEXE -m pip install requests_toolbelt") 27 | env.Execute("$PYTHONEXE -m pip install tqdm") 28 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 29 | from tqdm import tqdm 30 | 31 | def on_upload(source, target, env): 32 | file_path = str(source[0]) 33 | # upload_url_compatibility = env.GetProjectOption('upload_url') 34 | # upload_url = upload_url_compatibility.replace("/update", "") 35 | 36 | upload_url = env.GetProjectOption('upload_url') 37 | 38 | print("Upload url: " + upload_url); 39 | print("Firmare path: " + file_path); 40 | 41 | file_size = os.path.getsize(file_path) 42 | print("File size: " + str(file_size) + " bytes") 43 | 44 | with open(file_path, 'rb') as firmware: 45 | parsed_url = urlparse(upload_url) 46 | host_ip = parsed_url.netloc 47 | 48 | # Führe die GET-Anfrage aus 49 | # start_url = f"{upload_url}/ota/start?mode=fr&hash={md5}" 50 | start_url = f"{upload_url}" 51 | start_headers = { 52 | 'Host': host_ip, 53 | 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0', 54 | 'Accept': '*/*', 55 | 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 56 | 'Accept-Encoding': 'gzip, deflate', 57 | 'Referer': f'{upload_url}/update', 58 | 'Connection': 'keep-alive' 59 | } 60 | 61 | print("Connecting..."); 62 | 63 | start_response = requests.get(start_url, headers=start_headers) 64 | 65 | if start_response.status_code != 200: 66 | print("\nUpload failed.") 67 | return 1 68 | 69 | file_data = firmware.read() 70 | 71 | # Define headers 72 | headers = { 73 | 'X-Requested-With': 'XMLHttpRequest', 74 | 'Content-Type': 'application/octet-stream', # Set the appropriate content type 75 | } 76 | 77 | print("Sending firmware..."); 78 | 79 | # Send the POST request with the MultipartEncoderMonitor 80 | response = requests.post(upload_url, data=file_data, headers=headers) 81 | 82 | time.sleep(0.1) 83 | 84 | if response.status_code != 200: 85 | print("\nUpload failed.\nServer response: " + response.text) 86 | else: 87 | print( "\nUpload successful."); 88 | 89 | 90 | env.Replace(UPLOADCMD=on_upload) 91 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = false 9 | trim_trailing_whitespace = true 10 | 11 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .pioenvs 3 | .piolibdeps 4 | .vscode/.browse.c_cpp.db* 5 | .vscode/c_cpp_properties.json 6 | .vscode/launch.json 7 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | set(EXTRA_COMPONENT_DIRS "../components") 4 | set(COMPONENT_REQUIRES "common") 5 | 6 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 7 | project(air_firmware) 8 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/dependencies.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | idf: 3 | component_hash: null 4 | source: 5 | type: idf 6 | version: 5.3.1 7 | manifest_hash: 8c9ed1ee79e168fc798d5db5ef9ac5ba263464baa9235d488074bbda72ce922b 8 | target: esp32s3 9 | version: 1.0.0 10 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/esp32-cam-fpv-esp32s3sense.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "name": "lib", 8 | "path": "../components/air/" 9 | }, 10 | { 11 | "name": "lib", 12 | "path": "../components/common/" 13 | }, 14 | { 15 | "name": "lib", 16 | "path": "../components/esp32-camera/" 17 | } 18 | ], 19 | "settings": { 20 | "files.associations": { 21 | "array": "cpp", 22 | "string": "cpp", 23 | "string_view": "cpp", 24 | "initializer_list": "cpp", 25 | "utility": "cpp", 26 | "functional": "cpp", 27 | "*.tcc": "cpp" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32s3sense/logo2.png -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(srcs 2 | dummy.cpp 3 | ../../components/air/main.cpp 4 | ../../components/air/file_server.cpp 5 | ../../components/air/nvs_args.cpp 6 | ../../components/air/queue.cpp 7 | ../../components/air/wifi.cpp 8 | ../../components/air/osd.cpp 9 | ../../components/air/msp.cpp 10 | ../../components/air/temperature_sensor.cpp 11 | ) 12 | 13 | idf_component_register(SRCS "${srcs}" 14 | INCLUDE_DIRS "../../components/esp32-camera/target/private_include/" 15 | EMBED_FILES "../../components/air/favicon.ico" "../../components/air/index.html" 16 | REQUIRES esp_timer) 17 | 18 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/main/dummy.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32s3sense/main/dummy.cpp -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/partitions.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | factory, app, factory, 0x10000, 0x150000, 7 | ota_0, app, ota_0, 0x160000, 0x150000, 8 | ota_1, app, ota_1, 0x2B0000, 0x150000, -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | src_dir = main 13 | 14 | [env:esp32s3sense] 15 | platform = espressif32@ 6.9.0 16 | ;platform = espressif32@ 6.9.0 //compiles with python 3.11 or lower 17 | framework = espidf 18 | 19 | board=seeed_xiao_esp32s3 20 | 21 | build_flags = -DBOARD_XIAOS3SENSE 22 | 23 | monitor_speed = 115200 24 | 25 | ;esp32 boot log coloring enable 26 | monitor_raw = yes 27 | 28 | ;esp32 crash log decoding 29 | ;monitor_filters = esp32_exception_decoder 30 | 31 | build_type = release 32 | lib_extra_dirs = 33 | ../components/air/ 34 | ../components/common/ 35 | ../components/esp32-camera/ 36 | 37 | board_build.partitions = partitions.csv 38 | 39 | board_build.embed_txtfiles = 40 | ../components/air/index.html 41 | ../components/air/favicon.ico 42 | 43 | ;for esp32cam-mb 44 | monitor_dtr = 0 45 | monitor_rts = 0 46 | 47 | ;OTA upload: 48 | ;extra_scripts = platformio_upload.py 49 | ;upload_protocol = custom 50 | ;upload_url = http://192.168.4.1/ota 51 | 52 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/platformio_upload.py: -------------------------------------------------------------------------------- 1 | # Allows PlatformIO to upload directly to ElegantOTA 2 | # 3 | # To use: 4 | # - copy this script into the same folder as your platformio.ini 5 | # - set the following for your project in platformio.ini: 6 | # 7 | # extra_scripts = platformio_upload.py 8 | # upload_protocol = custom 9 | # upload_url = 10 | # 11 | # An example of an upload URL: 12 | # upload_url = http://192.168.1.123/update 13 | # also possible: upload_url = http://domainname/update 14 | 15 | import requests 16 | import hashlib 17 | from urllib.parse import urlparse 18 | import time 19 | import os 20 | Import("env") 21 | 22 | try: 23 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 24 | from tqdm import tqdm 25 | except ImportError: 26 | env.Execute("$PYTHONEXE -m pip install requests_toolbelt") 27 | env.Execute("$PYTHONEXE -m pip install tqdm") 28 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 29 | from tqdm import tqdm 30 | 31 | def on_upload(source, target, env): 32 | file_path = str(source[0]) 33 | # upload_url_compatibility = env.GetProjectOption('upload_url') 34 | # upload_url = upload_url_compatibility.replace("/update", "") 35 | 36 | upload_url = env.GetProjectOption('upload_url') 37 | 38 | print("Upload url: " + upload_url); 39 | print("Firmare path: " + file_path); 40 | 41 | file_size = os.path.getsize(file_path) 42 | print("File size: " + str(file_size) + " bytes") 43 | 44 | with open(file_path, 'rb') as firmware: 45 | parsed_url = urlparse(upload_url) 46 | host_ip = parsed_url.netloc 47 | 48 | # Führe die GET-Anfrage aus 49 | # start_url = f"{upload_url}/ota/start?mode=fr&hash={md5}" 50 | start_url = f"{upload_url}" 51 | start_headers = { 52 | 'Host': host_ip, 53 | 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0', 54 | 'Accept': '*/*', 55 | 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 56 | 'Accept-Encoding': 'gzip, deflate', 57 | 'Referer': f'{upload_url}/update', 58 | 'Connection': 'keep-alive' 59 | } 60 | 61 | print("Connecting..."); 62 | 63 | start_response = requests.get(start_url, headers=start_headers) 64 | 65 | if start_response.status_code != 200: 66 | print("\nUpload failed.") 67 | return 1 68 | 69 | file_data = firmware.read() 70 | 71 | # Define headers 72 | headers = { 73 | 'X-Requested-With': 'XMLHttpRequest', 74 | 'Content-Type': 'application/octet-stream', # Set the appropriate content type 75 | } 76 | 77 | print("Sending firmware..."); 78 | 79 | # Send the POST request with the MultipartEncoderMonitor 80 | response = requests.post(upload_url, data=file_data, headers=headers) 81 | 82 | time.sleep(0.1) 83 | 84 | if response.status_code != 200: 85 | print("\nUpload failed.\nServer response: " + response.text) 86 | else: 87 | print( "\nUpload successful."); 88 | 89 | 90 | env.Replace(UPLOADCMD=on_upload) 91 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y 2 | 3 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y 4 | CONFIG_ESP32S3_SPIRAM_SUPPORT=y 5 | 6 | CONFIG_ESP32S3_DATA_CACHE_64KB=y 7 | CONFIG_ESP32S3_DATA_CACHE_8WAYS=y 8 | CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y 9 | 10 | CONFIG_CAMERA_MODULE_ESP_S3_EYE=y 11 | CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y 12 | CONFIG_ESPTOOLPY_NO_STUB=y 13 | CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y 14 | 15 | CONFIG_SPIRAM_MODE_OCT=y 16 | 17 | CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 18 | CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=16 19 | CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=4 20 | 21 | #adds ~8kb RAM 22 | CONFIG_ESP_WIFI_RX_IRAM_OPT=n 23 | 24 | #can free ~6kb 25 | #CONFIG_ESP_WIFI_IRAM_OPT=n 26 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = false 9 | trim_trailing_whitespace = true 10 | 11 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .pioenvs 3 | .piolibdeps 4 | .vscode/.browse.c_cpp.db* 5 | .vscode/c_cpp_properties.json 6 | .vscode/launch.json 7 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | set(EXTRA_COMPONENT_DIRS "../components") 4 | set(COMPONENT_REQUIRES "common") 5 | 6 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 7 | project(air_firmware) 8 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/dependencies.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | idf: 3 | component_hash: null 4 | source: 5 | type: idf 6 | version: 5.3.1 7 | manifest_hash: 8c9ed1ee79e168fc798d5db5ef9ac5ba263464baa9235d488074bbda72ce922b 8 | target: esp32s3 9 | version: 1.0.0 10 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/esp32-cam-fpv-esp32s3sense_ov5640.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "name": "lib", 8 | "path": "../components/air/" 9 | }, 10 | { 11 | "name": "lib", 12 | "path": "../components/common/" 13 | }, 14 | { 15 | "name": "lib", 16 | "path": "../components/esp32-camera/" 17 | } 18 | ], 19 | "settings": { 20 | "files.associations": { 21 | "array": "cpp", 22 | "string": "cpp", 23 | "string_view": "cpp", 24 | "initializer_list": "cpp", 25 | "utility": "cpp", 26 | "functional": "cpp", 27 | "*.tcc": "cpp", 28 | "stdint.h": "c", 29 | "random": "cpp", 30 | "ostream": "cpp", 31 | "cstdint": "cpp" 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32s3sense_ov5640/logo2.png -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set( 2 | srcs dummy.cpp 3 | ../../components/air/main.cpp 4 | ../../components/air/file_server.cpp 5 | ../../components/air/nvs_args.cpp 6 | ../../components/air/queue.cpp 7 | ../../components/air/wifi.cpp 8 | ../../components/air/osd.cpp 9 | ../../components/air/msp.cpp 10 | ../../components/air/temperature_sensor.cpp 11 | ) 12 | 13 | idf_component_register(SRCS "${srcs}" 14 | INCLUDE_DIRS "../../components/esp32-camera/target/private_include/" 15 | EMBED_FILES "../../components/air/favicon.ico" "../../components/air/index.html" 16 | REQUIRES esp_timer) 17 | 18 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/main/dummy.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/air_firmware_esp32s3sense_ov5640/main/dummy.cpp -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/partitions.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | factory, app, factory, 0x10000, 0x150000, 7 | ota_0, app, ota_0, 0x160000, 0x150000, 8 | ota_1, app, ota_1, 0x2B0000, 0x150000, -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | src_dir = main 13 | 14 | [env:esp32s3sense] 15 | platform = espressif32@ 6.9.0 16 | ;platform = espressif32@ 6.7.0 crashes on boot without any messages 17 | ;platform = espressif32@ 6.5.0 //compiles with python 3.11 or less 18 | framework = espidf 19 | 20 | board=seeed_xiao_esp32s3 21 | 22 | build_flags = -DBOARD_XIAOS3SENSE -DSENSOR_OV5640 23 | 24 | monitor_speed = 115200 25 | 26 | ;esp32 boot log coloring enable 27 | ;monitor_raw = yes 28 | 29 | ;esp32 crash log decoding 30 | monitor_filters = esp32_exception_decoder 31 | 32 | build_type = release 33 | lib_extra_dirs = 34 | ../components/air/ 35 | ../components/common/ 36 | ../components/esp32-camera/ 37 | 38 | board_build.partitions = partitions.csv 39 | 40 | board_build.embed_txtfiles = 41 | ../components/air/index.html 42 | ../components/air/favicon.ico 43 | 44 | ;for esp32cam-mb 45 | monitor_dtr = 0 46 | monitor_rts = 0 47 | 48 | ;OTA upload: 49 | ;extra_scripts = platformio_upload.py 50 | ;upload_protocol = custom 51 | ;upload_url = http://192.168.4.1/ota 52 | 53 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/platformio_upload.py: -------------------------------------------------------------------------------- 1 | # Allows PlatformIO to upload directly to ElegantOTA 2 | # 3 | # To use: 4 | # - copy this script into the same folder as your platformio.ini 5 | # - set the following for your project in platformio.ini: 6 | # 7 | # extra_scripts = platformio_upload.py 8 | # upload_protocol = custom 9 | # upload_url = 10 | # 11 | # An example of an upload URL: 12 | # upload_url = http://192.168.1.123/update 13 | # also possible: upload_url = http://domainname/update 14 | 15 | import requests 16 | import hashlib 17 | from urllib.parse import urlparse 18 | import time 19 | import os 20 | Import("env") 21 | 22 | try: 23 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 24 | from tqdm import tqdm 25 | except ImportError: 26 | env.Execute("$PYTHONEXE -m pip install requests_toolbelt") 27 | env.Execute("$PYTHONEXE -m pip install tqdm") 28 | from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor 29 | from tqdm import tqdm 30 | 31 | def on_upload(source, target, env): 32 | file_path = str(source[0]) 33 | # upload_url_compatibility = env.GetProjectOption('upload_url') 34 | # upload_url = upload_url_compatibility.replace("/update", "") 35 | 36 | upload_url = env.GetProjectOption('upload_url') 37 | 38 | print("Upload url: " + upload_url); 39 | print("Firmare path: " + file_path); 40 | 41 | file_size = os.path.getsize(file_path) 42 | print("File size: " + str(file_size) + " bytes") 43 | 44 | with open(file_path, 'rb') as firmware: 45 | parsed_url = urlparse(upload_url) 46 | host_ip = parsed_url.netloc 47 | 48 | # Führe die GET-Anfrage aus 49 | # start_url = f"{upload_url}/ota/start?mode=fr&hash={md5}" 50 | start_url = f"{upload_url}" 51 | start_headers = { 52 | 'Host': host_ip, 53 | 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0', 54 | 'Accept': '*/*', 55 | 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 56 | 'Accept-Encoding': 'gzip, deflate', 57 | 'Referer': f'{upload_url}/update', 58 | 'Connection': 'keep-alive' 59 | } 60 | 61 | print("Connecting..."); 62 | 63 | start_response = requests.get(start_url, headers=start_headers) 64 | 65 | if start_response.status_code != 200: 66 | print("\nUpload failed.") 67 | return 1 68 | 69 | file_data = firmware.read() 70 | 71 | # Define headers 72 | headers = { 73 | 'X-Requested-With': 'XMLHttpRequest', 74 | 'Content-Type': 'application/octet-stream', # Set the appropriate content type 75 | } 76 | 77 | print("Sending firmware..."); 78 | 79 | # Send the POST request with the MultipartEncoderMonitor 80 | response = requests.post(upload_url, data=file_data, headers=headers) 81 | 82 | time.sleep(0.1) 83 | 84 | if response.status_code != 200: 85 | print("\nUpload failed.\nServer response: " + response.text) 86 | else: 87 | print( "\nUpload successful."); 88 | 89 | 90 | env.Replace(UPLOADCMD=on_upload) 91 | -------------------------------------------------------------------------------- /air_firmware_esp32s3sense_ov5640/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y 2 | 3 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y 4 | CONFIG_ESP32S3_SPIRAM_SUPPORT=y 5 | 6 | CONFIG_ESP32S3_DATA_CACHE_64KB=y 7 | CONFIG_ESP32S3_DATA_CACHE_8WAYS=y 8 | CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y 9 | 10 | CONFIG_CAMERA_MODULE_ESP_S3_EYE=y 11 | CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y 12 | CONFIG_ESPTOOLPY_NO_STUB=y 13 | CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y 14 | 15 | CONFIG_SPIRAM_MODE_OCT=y 16 | 17 | CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 18 | CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=16 19 | CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=4 20 | 21 | #adds ~8kb RAM 22 | CONFIG_ESP_WIFI_RX_IRAM_OPT=n 23 | 24 | #can free ~6kb 25 | #CONFIG_ESP_WIFI_IRAM_OPT=n 26 | 27 | -------------------------------------------------------------------------------- /components/air/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/air/favicon.ico -------------------------------------------------------------------------------- /components/air/msp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef ESP_PLATFORM 6 | #include "freertos/FreeRTOS.h" 7 | #include "freertos/queue.h" 8 | #include "freertos/task.h" 9 | #include "freertos/semphr.h" 10 | #else 11 | #define IRAM_ATTR 12 | #endif 13 | 14 | #include "main.h" 15 | 16 | #ifdef UART_MSP_OSD 17 | 18 | #define MSP_API_VERSION 1 19 | 20 | #define MSP_FC_VERSION 3 21 | #define MSP_FC_VARIANT 2 22 | #define MSP_DISPLAYPORT 182 23 | 24 | #define MSP_SET_RAW_RC 200 25 | 26 | #define MSP_RC_CHANNELS_COUNT 18 27 | 28 | 29 | #define MAX_MSP_MESSAGE 1024 30 | 31 | typedef enum 32 | { 33 | DPDS_SUBCMD, 34 | DPDS_POSITION_Y, 35 | DPDS_POSITION_X, 36 | DPDS_STRING_INFO, 37 | DPDS_STRING 38 | } DPDState; 39 | 40 | #define DPSC_CLEAR_SCREEN 2 41 | #define DPSC_WRITE_STRING 3 42 | #define DPSC_DRAW_SCREEN 4 43 | #define DPSC_SET_OPTIONS 5 44 | 45 | //====================================================== 46 | //====================================================== 47 | class MSP 48 | { 49 | public: 50 | MSP(); 51 | ~MSP(); 52 | 53 | void loop(); 54 | 55 | bool sendCommand(uint16_t messageID, void * payload, uint16_t size); 56 | 57 | int64_t lastPing; 58 | int64_t lastLoop; 59 | int64_t lastRC; 60 | int64_t lastRealRC; 61 | 62 | bool gotRCChannels; 63 | uint16_t rcChannels[MSP_RC_CHANNELS_COUNT]; 64 | void setRCChannels(const uint16_t* data); //MSP_RC_CHANNELS_COUNT values 65 | 66 | private: 67 | 68 | typedef enum 69 | { 70 | DS_IDLE, 71 | DS_PROTO_IDENTIFIER, 72 | DS_DIRECTION_V1, 73 | DS_DIRECTION_V2, 74 | DS_FLAG_V2, 75 | DS_PAYLOAD_LENGTH_V1, 76 | DS_PAYLOAD_LENGTH_JUMBO_LOW, 77 | DS_PAYLOAD_LENGTH_JUMBO_HIGH, 78 | DS_PAYLOAD_LENGTH_V2_LOW, 79 | DS_PAYLOAD_LENGTH_V2_HIGH, 80 | DS_CODE_V1, 81 | DS_CODE_JUMBO_V1, 82 | DS_CODE_V2_LOW, 83 | DS_CODE_V2_HIGH, 84 | DS_PAYLOAD_V1, 85 | DS_PAYLOAD_V2, 86 | DS_CHECKSUM_V1, 87 | DS_CHECKSUM_V2, 88 | } TDecoderState; 89 | 90 | TDecoderState decoderState = DS_IDLE; 91 | 92 | uint8_t crc8_dvb_s2(uint8_t crc, unsigned char a); 93 | 94 | int portId; 95 | unsigned long probeTime; 96 | 97 | int unsupported; 98 | int message_direction; 99 | int message_length_expected; 100 | unsigned char message_buffer[MAX_MSP_MESSAGE]; 101 | int message_length_received; 102 | int code; 103 | uint8_t message_checksum; 104 | 105 | void decode(); 106 | void dispatchMessage(uint8_t expected_checksum); 107 | void processMessage(); 108 | void sendPing(); 109 | }; 110 | 111 | extern MSP g_msp; 112 | 113 | #endif // UART_MSP_OSD -------------------------------------------------------------------------------- /components/air/nvs_args.cpp: -------------------------------------------------------------------------------- 1 | #include "nvs_args.h" 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/semphr.h" 4 | 5 | nvs_handle_t nvs_handler; 6 | static SemaphoreHandle_t s_nvs_mux = NULL; 7 | 8 | //============================================================================================= 9 | //============================================================================================= 10 | esp_err_t nvs_args_init() 11 | { 12 | printf("Init NVS...\n"); 13 | 14 | s_nvs_mux = xSemaphoreCreateMutex(); 15 | 16 | esp_err_t ret = nvs_flash_init(); 17 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) 18 | { 19 | ESP_ERROR_CHECK(nvs_flash_erase()); 20 | ret = nvs_flash_init(); 21 | } 22 | ESP_ERROR_CHECK(ret); 23 | 24 | return nvs_open("storage", NVS_READWRITE, &nvs_handler); 25 | } 26 | 27 | //============================================================================================= 28 | //============================================================================================= 29 | uint32_t nvs_args_read(const char *key, uint32_t defaultValue) 30 | { 31 | uint32_t result = defaultValue; 32 | xSemaphoreTake(s_nvs_mux, portMAX_DELAY); 33 | nvs_get_u32(nvs_handler,key,&result); 34 | xSemaphoreGive(s_nvs_mux); 35 | return result; 36 | } 37 | 38 | //============================================================================================= 39 | //============================================================================================= 40 | esp_err_t nvs_args_set(const char *key,uint32_t value) 41 | { 42 | esp_err_t ret = 0; 43 | xSemaphoreTake(s_nvs_mux, portMAX_DELAY); 44 | ret = nvs_set_u32(nvs_handler,key,value); 45 | ret |= nvs_commit(nvs_handler); 46 | xSemaphoreGive(s_nvs_mux); 47 | return ret; 48 | } -------------------------------------------------------------------------------- /components/air/nvs_args.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "esp_wifi_types.h" 4 | #include "esp_heap_caps.h" 5 | #include "esp_log.h" 6 | #include "nvs_flash.h" 7 | 8 | esp_err_t nvs_args_init(); 9 | 10 | uint32_t nvs_args_read(const char *key, uint32_t defaultValue); 11 | esp_err_t nvs_args_set(const char *key,uint32_t value); 12 | -------------------------------------------------------------------------------- /components/air/osd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "esp_timer.h" 4 | 5 | #include "osd.h" 6 | 7 | OSD g_osd; 8 | 9 | //============================================================== 10 | //============================================================== 11 | OSD::OSD() 12 | { 13 | this->clear(); 14 | this->changed = true; 15 | this->lockCounter = 0; 16 | } 17 | 18 | //============================================================== 19 | //============================================================== 20 | void OSD::clear() 21 | { 22 | memset( &this->buffer, 0, OSD_BUFFER_SIZE ); 23 | this->lockCounter = 30; //lock for 30 frames max (30 fps update) 24 | } 25 | 26 | //============================================================== 27 | //============================================================== 28 | void OSD::commit() 29 | { 30 | this->changed = true; 31 | this->lockCounter = 0; 32 | } 33 | 34 | 35 | //============================================================== 36 | //============================================================== 37 | void OSD::writeString(unsigned int row, unsigned int col, int isExtChar, uint8_t* str, int len) 38 | { 39 | if ( row >= OSD_ROWS ) return; 40 | 41 | uint8_t flag = isExtChar ? 0xff : 0; 42 | 43 | uint8_t* pScreenLowRow = &(this->buffer.screenLow[row][0]); 44 | uint8_t* pScreenHighRow = &(this->buffer.screenHigh[row][0]); 45 | while ( (len > 0) && (col < OSD_COLS) ) 46 | { 47 | pScreenLowRow[col] = *str++; 48 | 49 | int col8 = col >> 3; 50 | int sh = col & 0x7; 51 | uint8_t m = 1 << sh; 52 | pScreenHighRow[col8] = (pScreenHighRow[col8] & ~m) | (m & flag); 53 | 54 | len--; 55 | col++; 56 | } 57 | } 58 | 59 | //============================================================== 60 | //============================================================== 61 | void* OSD::getBuffer() 62 | { 63 | return &this->buffer; 64 | } 65 | 66 | //============================================================== 67 | //============================================================== 68 | bool OSD::isChanged() 69 | { 70 | /* 71 | for ( int i = 0; i < 10; i++) 72 | { 73 | this->buffer.screenLow[10][10+i]++; 74 | } 75 | this->changed = true; 76 | */ 77 | 78 | bool res = this->changed; 79 | this->changed = false; 80 | return res; 81 | } 82 | 83 | //============================================================== 84 | //============================================================== 85 | bool OSD::isLocked() 86 | { 87 | if ( this->lockCounter == 0 ) return false; 88 | this->lockCounter--; 89 | return true; 90 | } -------------------------------------------------------------------------------- /components/air/osd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "packets.h" 5 | #include "main.h" 6 | 7 | 8 | #ifdef ESP_PLATFORM 9 | #include "freertos/FreeRTOS.h" 10 | #include "freertos/queue.h" 11 | #include "freertos/task.h" 12 | #include "freertos/semphr.h" 13 | #else 14 | #define IRAM_ATTR 15 | #endif 16 | 17 | class OSD 18 | { 19 | private: 20 | 21 | struct OSDBuffer buffer; 22 | bool changed; 23 | int lockCounter; //lock osd buffer after clear() untill the next draw() to prevent sending incomplete screen 24 | 25 | public: 26 | OSD(); 27 | IRAM_ATTR void* getBuffer(); 28 | IRAM_ATTR bool isChanged(); 29 | IRAM_ATTR bool isLocked(); //do not request buffer while locked 30 | void clear(); 31 | void commit(); 32 | void writeString(unsigned int row, unsigned int col, int isExtChar, uint8_t* str, int len); 33 | }; 34 | 35 | extern OSD g_osd; 36 | -------------------------------------------------------------------------------- /components/air/python_test_server.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify,render_template 2 | 3 | app = Flask(__name__) 4 | 5 | @app.route('/configs', methods=['GET','POST']) 6 | def configs(): 7 | if request.method == 'GET': 8 | return jsonify({'channel': '11',"default_dvr":"false"}) 9 | if request.method == 'POST': 10 | return jsonify(request.get_json()) 11 | 12 | @app.route('/file_list', methods=['GET']) 13 | def get_file_list(): 14 | if request.method == 'GET': 15 | result = [ 16 | {"name":"file1","size":"1024"}, 17 | {"name":"file2","size":"2048"}, 18 | {"name":"file3","size":"2048"}, 19 | {"name":"file4","size":"2048"}, 20 | ] 21 | return jsonify(result) 22 | 23 | @app.route('/delete', methods=['POST']) 24 | def delete(): 25 | if request.method == 'POST': 26 | return jsonify(request.get_json()) 27 | 28 | 29 | @app.route('/') 30 | def index(): 31 | with open("index.html") as f: 32 | return f.read() 33 | 34 | if __name__ == '__main__': 35 | app.run(host='0.0.0.0', port=8000) -------------------------------------------------------------------------------- /components/air/temperature_sensor.cpp: -------------------------------------------------------------------------------- 1 | #include "temperature_sensor.h" 2 | #include "driver/temperature_sensor.h" 3 | #include "esp_log.h" 4 | 5 | static const char *TAG = "temp_sensor"; 6 | static temperature_sensor_handle_t temp_handle = NULL; 7 | 8 | #ifdef BOARD_XIAOS3SENSE 9 | //===================================================================== 10 | //===================================================================== 11 | bool temperature_sensor_available() 12 | { 13 | return true; 14 | } 15 | 16 | //===================================================================== 17 | //===================================================================== 18 | void temperature_sensor_init(void) 19 | { 20 | ESP_LOGI(TAG, "Initializing temperature sensor"); 21 | 22 | temperature_sensor_config_t temp_sensor = { 23 | .range_min = 50, 24 | .range_max = 125, 25 | .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT 26 | }; 27 | 28 | esp_err_t ret = temperature_sensor_install(&temp_sensor, &temp_handle); 29 | if (ret != ESP_OK) { 30 | ESP_LOGE(TAG, "Failed to install temperature sensor"); 31 | return; 32 | } 33 | 34 | ret = temperature_sensor_enable(temp_handle); 35 | if (ret != ESP_OK) { 36 | ESP_LOGE(TAG, "Failed to enable temperature sensor"); 37 | return; 38 | } 39 | } 40 | 41 | //===================================================================== 42 | //===================================================================== 43 | void temperature_sensor_read(float *temperature) 44 | { 45 | if (temp_handle == NULL) { 46 | ESP_LOGE(TAG, "Temperature sensor not initialized"); 47 | return; 48 | } 49 | 50 | esp_err_t ret = temperature_sensor_get_celsius(temp_handle, temperature); 51 | if (ret != ESP_OK) { 52 | ESP_LOGE(TAG, "Failed to read temperature"); 53 | return; 54 | } 55 | 56 | ESP_LOGI(TAG, "Temperature: %.1f °C", *temperature); 57 | } 58 | 59 | #endif 60 | 61 | #ifdef BOARD_ESP32CAM 62 | 63 | //===================================================================== 64 | //===================================================================== 65 | bool temperature_sensor_available() 66 | { 67 | return false; 68 | } 69 | 70 | //===================================================================== 71 | //===================================================================== 72 | void temperature_sensor_init(void) 73 | { 74 | } 75 | 76 | //===================================================================== 77 | //===================================================================== 78 | void temperature_sensor_read(float *temperature) 79 | { 80 | *temperature = 0; 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /components/air/temperature_sensor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "esp_err.h" 4 | 5 | bool temperature_sensor_available(); 6 | void temperature_sensor_init(void); 7 | void temperature_sensor_read(float *temperature); 8 | 9 | -------------------------------------------------------------------------------- /components/air/upload_script.html: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
Column 1Column 2Column 3
Data 1Data 2Data 3
Data 4Data 5Data 6
37 | -------------------------------------------------------------------------------- /components/air/wifi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "esp_wifi_types.h" 4 | #include "esp_heap_caps.h" 5 | #include "esp_task_wdt.h" 6 | #include "esp_private/wifi.h" 7 | #include "esp_task_wdt.h" 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/queue.h" 10 | #include "freertos/task.h" 11 | #include "freertos/semphr.h" 12 | 13 | #include "queue.h" 14 | 15 | #include "packets.h" 16 | #include "stdint.h" 17 | //#define WIFI_AP 18 | 19 | #if defined WIFI_AP 20 | #define ESP_WIFI_MODE WIFI_MODE_AP 21 | #define ESP_WIFI_IF WIFI_IF_AP 22 | #else 23 | #define ESP_WIFI_MODE WIFI_MODE_STA 24 | #define ESP_WIFI_IF WIFI_IF_STA 25 | #endif 26 | 27 | extern SemaphoreHandle_t s_wlan_incoming_mux; 28 | extern SemaphoreHandle_t s_wlan_outgoing_mux; 29 | extern Ground2Air_Data_Packet s_ground2air_data_packet; 30 | extern Ground2Air_Config_Packet s_ground2air_config_packet; 31 | extern Ground2Air_Config_Packet s_ground2air_config_packet2; 32 | extern TaskHandle_t s_wifi_tx_task; 33 | extern TaskHandle_t s_wifi_rx_task; 34 | 35 | constexpr size_t WLAN_INCOMING_BUFFER_SIZE = 1024; 36 | 37 | //use as much memory as available 38 | //leave ~5k for SD library to initialize correctly 39 | #ifdef BOARD_XIAOS3SENSE 40 | constexpr size_t WLAN_OUTGOING_BUFFER_SIZE = 90000; 41 | #else 42 | constexpr size_t WLAN_OUTGOING_BUFFER_SIZE = 85000; 43 | #endif 44 | 45 | void setup_wifi(WIFI_Rate wifi_rate,uint8_t chn,float power_dbm,void (*packet_received_cb)(void* buf, wifi_promiscuous_pkt_type_t type)); 46 | 47 | void set_ground2air_config_packet_handler(void (*handler)(Ground2Air_Config_Packet& src)); 48 | void set_ground2air_connect_packet_handler(void (*handler)(Ground2Air_Config_Packet& src)); 49 | void set_ground2air_data_packet_handler(void (*handler)(Ground2Air_Data_Packet& src)); 50 | esp_err_t set_wifi_fixed_rate(WIFI_Rate value); 51 | esp_err_t set_wlan_power_dBm(float dBm); 52 | void setup_wifi_file_server(void); 53 | uint8_t getMaxWlanOutgoingQueueUsage(); 54 | uint8_t getMinWlanOutgoingQueueUsageSeen(); 55 | uint8_t getMaxWlanOutgoingQueueUsageFrame(); 56 | uint8_t getMinWlanOutgoingQueueUsageFrame(); 57 | 58 | //todo: global stats, not wifi only. Move to separate header. 59 | struct Stats 60 | { 61 | uint32_t wlan_data_sent = 0; 62 | uint32_t wlan_data_received = 0; 63 | uint16_t wlan_error_count = 0; 64 | uint16_t fec_spin_count = 0; 65 | uint16_t wlan_received_packets_dropped = 0; 66 | uint32_t video_data = 0; 67 | uint16_t video_frames = 0; 68 | //video_frames count is not valid if camera overflow happened. 69 | //We still need expected vmode capture fps 70 | //we estimate it as video_frames + ovf_count 71 | uint16_t video_frames_expected = 0; 72 | uint32_t sd_data = 0; 73 | uint32_t sd_drops = 0; 74 | 75 | uint32_t out_telemetry_data = 0; 76 | uint32_t in_telemetry_data = 0; 77 | 78 | uint16_t outPacketCounter = 0; 79 | uint16_t inPacketCounter = 0; 80 | uint16_t inRejectedPacketCounter = 0; 81 | 82 | uint8_t rssiDbm = 0; 83 | uint8_t noiseFloorDbm = 0; 84 | 85 | uint16_t camera_frame_size_min; 86 | uint16_t camera_frame_size_max; 87 | 88 | int RCPeriodMaxMS = -1; 89 | 90 | uint16_t wlan_received_packets_bad = 0; 91 | 92 | }; 93 | 94 | extern Stats s_stats; 95 | extern Stats s_last_stats; 96 | extern uint8_t s_wlan_outgoing_queue_usage; 97 | 98 | -------------------------------------------------------------------------------- /components/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(srcs fec_codec.cpp fec.cpp safe_printf.cpp structures.cpp crc.cpp circular_buffer.cpp vcd_profiler.cpp jpeg_parser.cpp avi.cpp util.cpp packets.cpp hx_mavlink_parser.cpp packet_filter.cpp) 2 | 3 | idf_component_register(SRCS "${srcs}" 4 | INCLUDE_DIRS . 5 | REQUIRES esp_timer ) 6 | 7 | -------------------------------------------------------------------------------- /components/common/avi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define AVI_HEADER_LEN 240 // AVI header length 7 | #define CHUNK_HDR 8 // bytes per jpeg hdr in AVI 8 | #define DVR_MAX_FRAMES 25000 //50fps ~ 8 minues 9 | 10 | 11 | extern const uint8_t dcBuf[]; // 00dc 12 | extern size_t moviSize; 13 | 14 | extern uint8_t aviHeader[AVI_HEADER_LEN]; 15 | 16 | extern void prepAviBuffers(); 17 | extern void prepAviIndex(); 18 | extern void finalizeAviIndex(uint16_t frameCnt); 19 | extern size_t writeAviIndex(uint8_t* clientBuf, size_t buffSize); 20 | extern void buildAviHdr(uint8_t FPS, int frameWidth, int frameHeight, uint16_t frameCnt); 21 | extern void buildAviIdx(size_t dataSize); 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /components/common/circular_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef ESP_PLATFORM 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/queue.h" 10 | #include "freertos/task.h" 11 | #include "freertos/semphr.h" 12 | #else 13 | #define IRAM_ATTR 14 | #endif 15 | 16 | class Circular_Buffer 17 | { 18 | public: 19 | Circular_Buffer(uint8_t* buffer, size_t capacity, size_t filledSize = 0) 20 | : m_data(buffer) 21 | , m_capacity(capacity) 22 | , m_size(filledSize) 23 | { 24 | } 25 | 26 | IRAM_ATTR size_t size() const; 27 | IRAM_ATTR bool empty() const; 28 | IRAM_ATTR size_t get_space_left() const; 29 | IRAM_ATTR size_t capacity() const; 30 | IRAM_ATTR void resize(size_t size); 31 | IRAM_ATTR bool write(const void* data, size_t size); 32 | IRAM_ATTR bool writeBytes(uint8_t b, size_t size); //write size bytes b 33 | IRAM_ATTR bool read(void* dst, size_t size); 34 | IRAM_ATTR bool skip(size_t size); 35 | IRAM_ATTR const void* start_reading(size_t& size); 36 | IRAM_ATTR void end_reading(size_t size); //call with the same size as the one returned by start_reading 37 | IRAM_ATTR void clear(); 38 | IRAM_ATTR uint8_t peek( size_t offset); 39 | 40 | private: 41 | uint8_t* m_data; 42 | size_t m_capacity; 43 | size_t m_start = 0; 44 | size_t m_size = 0; 45 | }; 46 | -------------------------------------------------------------------------------- /components/common/component.mk: -------------------------------------------------------------------------------- 1 | 2 | COMPONENT_SRCDIRS := . 3 | COMPONENT_ADD_INCLUDEDIRS := . 4 | 5 | -------------------------------------------------------------------------------- /components/common/crc.cpp: -------------------------------------------------------------------------------- 1 | #include "crc.h" 2 | 3 | static uint8_t s_crc8_table[256]; /* 8-bit table */ 4 | void init_crc8_table() 5 | { 6 | static constexpr uint8_t DI = 0x07; 7 | for (uint16_t i = 0; i < 256; i++) 8 | { 9 | uint8_t crc = (uint8_t)i; 10 | for (uint8_t j = 0; j < 8; j++) 11 | crc = (crc << 1) ^ ((crc & 0x80) ? DI : 0); 12 | s_crc8_table[i] = crc & 0xFF; 13 | } 14 | } 15 | 16 | IRAM_ATTR uint8_t crc8(uint8_t crc, const void *c_ptr, size_t len) 17 | { 18 | const uint8_t *c = reinterpret_cast(c_ptr); 19 | size_t n = (len + 7) >> 3; 20 | switch (len & 7) 21 | { 22 | case 0: 23 | do 24 | { 25 | crc = s_crc8_table[crc ^ (*c++)]; 26 | case 7: 27 | crc = s_crc8_table[crc ^ (*c++)]; 28 | case 6: 29 | crc = s_crc8_table[crc ^ (*c++)]; 30 | case 5: 31 | crc = s_crc8_table[crc ^ (*c++)]; 32 | case 4: 33 | crc = s_crc8_table[crc ^ (*c++)]; 34 | case 3: 35 | crc = s_crc8_table[crc ^ (*c++)]; 36 | case 2: 37 | crc = s_crc8_table[crc ^ (*c++)]; 38 | case 1: 39 | crc = s_crc8_table[crc ^ (*c++)]; 40 | } while (--n > 0); 41 | } 42 | return crc; 43 | } -------------------------------------------------------------------------------- /components/common/crc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef ESP_PLATFORM 7 | # include "esp_task_wdt.h" 8 | #else 9 | # define IRAM_ATTR 10 | #endif 11 | 12 | void init_crc8_table(); 13 | IRAM_ATTR uint8_t crc8(uint8_t crc, const void *c_ptr, size_t len); 14 | -------------------------------------------------------------------------------- /components/common/jpeg_parser.cpp: -------------------------------------------------------------------------------- 1 | #include "jpeg_parser.h" 2 | 3 | //============================================================================================= 4 | //============================================================================================= 5 | bool getJPEGDimensions(uint8_t* buffer, int& width, int& height, size_t maxSearchLength) 6 | { 7 | size_t i = 2; //skip ff d8 8 | 9 | while (true) 10 | { 11 | // Check for the 0xFF marker 12 | if (buffer[i] == 0xFF) 13 | { 14 | uint8_t marker = buffer[i + 1]; 15 | 16 | // Check if it's a start of frame marker (0xC0 - 0xC3) 17 | if (marker == 0xC0 || marker == 0xC1 || marker == 0xC2 || marker == 0xC3) 18 | { 19 | height = (buffer[i + 5] << 8) + buffer[i + 6]; 20 | width = (buffer[i + 7] << 8) + buffer[i + 8]; 21 | return true; 22 | } 23 | 24 | // Skip this marker segment 25 | uint16_t segmentLength = (buffer[i + 2] << 8) + buffer[i + 3]; 26 | i += 2 + segmentLength; 27 | } 28 | else 29 | { 30 | i++; 31 | } 32 | if ( i > maxSearchLength ) return false; 33 | } 34 | 35 | return false; 36 | } -------------------------------------------------------------------------------- /components/common/jpeg_parser.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern bool getJPEGDimensions(uint8_t* buffer, int& width, int& height, size_t maxSearchLength); 6 | -------------------------------------------------------------------------------- /components/common/packet_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "packet_filter.h" 2 | 3 | //============================================================================================= 4 | //============================================================================================= 5 | void PacketFilter::set_packet_header_data( uint16_t from_device_id, uint16_t to_device_id ) 6 | { 7 | m_from_device_id = from_device_id; 8 | m_to_device_id = to_device_id; 9 | } 10 | 11 | //============================================================================================= 12 | //============================================================================================= 13 | /*IRAM_ATTR*/ void PacketFilter::apply_packet_header_data( Packet_Header* packet ) 14 | { 15 | packet->packet_version = PACKET_VERSION; 16 | packet->packet_signature = PACKET_SIGNATURE; 17 | packet->fromDeviceId = this->m_from_device_id; 18 | packet->toDeviceId = this->m_to_device_id; 19 | } 20 | 21 | //============================================================================================= 22 | //============================================================================================= 23 | void PacketFilter::set_packet_filtering( uint16_t filter_from_device_id, uint16_t filter_to_device_id ) 24 | { 25 | m_filter_from_device_id = filter_from_device_id; 26 | m_filter_to_device_id = filter_to_device_id; 27 | } 28 | 29 | //============================================================================================= 30 | //============================================================================================= 31 | /*IRAM_ATTR*/ PacketFilter::PacketFilterResult PacketFilter::filter_packet( const void* data, size_t size ) 32 | { 33 | if ( size < sizeof(Packet_Header) ) 34 | { 35 | return PacketFilterResult::WrongStructure; 36 | } 37 | 38 | const Packet_Header* header = reinterpret_cast(data); 39 | 40 | if ( header->packet_signature != PACKET_SIGNATURE ) 41 | { 42 | return PacketFilterResult::WrongStructure; 43 | } 44 | 45 | if ( header->packet_version != PACKET_VERSION ) 46 | { 47 | return PacketFilterResult::WrongVersion; 48 | } 49 | 50 | if ( ( this->m_filter_from_device_id !=0 ) && ( header->fromDeviceId != this->m_filter_from_device_id ) ) 51 | { 52 | return PacketFilterResult::Drop; 53 | } 54 | 55 | if ( ( this->m_filter_to_device_id != 0 ) && ( header->toDeviceId != this->m_filter_to_device_id ) ) 56 | { 57 | return PacketFilterResult::Drop; 58 | } 59 | 60 | return PacketFilterResult::Pass; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /components/common/packet_filter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "fec.h" 5 | 6 | #ifdef ESP_PLATFORM 7 | #include "freertos/FreeRTOS.h" 8 | #include "freertos/queue.h" 9 | #include "freertos/task.h" 10 | #include "freertos/semphr.h" 11 | #else 12 | #define IRAM_ATTR 13 | #endif 14 | 15 | //=========================================================================================== 16 | //=========================================================================================== 17 | class PacketFilter 18 | { 19 | public: 20 | enum class PacketFilterResult 21 | { 22 | Pass, 23 | Drop, 24 | WrongStructure, 25 | WrongVersion 26 | }; 27 | 28 | void set_packet_header_data( uint16_t from_device_id, uint16_t to_device_id ); 29 | IRAM_ATTR void apply_packet_header_data( Packet_Header* packet ); 30 | void set_packet_filtering( uint16_t filter_from_device_id, uint16_t filter_to_device_id ); 31 | IRAM_ATTR PacketFilterResult filter_packet( const void* data, size_t size ); 32 | 33 | private: 34 | 35 | //values are set on outgoing packets 36 | uint16_t m_from_device_id = 0; 37 | uint16_t m_to_device_id = 0; 38 | 39 | //values are used to filter incoming packets. 0 - no filtering 40 | uint16_t m_filter_from_device_id = 0; 41 | uint16_t m_filter_to_device_id = 0; 42 | }; 43 | -------------------------------------------------------------------------------- /components/common/packets.cpp: -------------------------------------------------------------------------------- 1 | #include "packets.h" 2 | 3 | TVMode vmodes[] = { 4 | //QVGA, //320x240 5 | { 6 | 320,240,60,60,60,60 7 | }, 8 | //CIF, //400x296 9 | { 10 | 400,296,60,60,60,60 11 | }, 12 | //HVGA, //480x320 13 | { 14 | 480,320,30,30,30,30 15 | }, 16 | //VGA, //640x480 17 | { 18 | 640,480,30,30,40,50 19 | }, 20 | //VGA16, //640x360 21 | { 22 | 640,360,30,30,40,50 23 | }, 24 | //SVGA, //800x600 25 | { 26 | 800,600,30,30,30,30 27 | }, 28 | //SVGA16, //800x456 29 | { 30 | 800,456,30,30,40,50 31 | }, 32 | //XGA, //1024x768 33 | { 34 | 1024,768,12,30,12,30 35 | }, 36 | //XGA16, //1024x576 37 | { 38 | 1024,576,12,30,12,30 39 | }, 40 | //SXGA, //1280x960 41 | { 42 | 1280,960,12,30,12,30 43 | }, 44 | //HD, //1280x720 45 | { 46 | 1280,720,12,30,12,30 47 | }, 48 | //UXGA //1600x1200 49 | { 50 | 1600,1200,10,10,10,10 51 | } 52 | }; 53 | 54 | -------------------------------------------------------------------------------- /components/common/safe_printf.cpp: -------------------------------------------------------------------------------- 1 | #include "safe_printf.h" 2 | 3 | SemaphoreHandle_t s_safe_printf_mux = xSemaphoreCreateBinary(); 4 | 5 | static auto _init_result = []() -> bool 6 | { 7 | xSemaphoreGive(s_safe_printf_mux); 8 | return true; 9 | }(); 10 | 11 | 12 | -------------------------------------------------------------------------------- /components/common/safe_printf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/queue.h" 7 | #include "freertos/task.h" 8 | #include "freertos/semphr.h" 9 | 10 | #if CONFIG_IDF_TARGET_ESP32 11 | #include "esp32/rom/ets_sys.h" // will be removed in idf v5.0 12 | #elif CONFIG_IDF_TARGET_ESP32S2 13 | #include "esp32s2/rom/ets_sys.h" 14 | #elif CONFIG_IDF_TARGET_ESP32S3 15 | #include "esp32s3/rom/ets_sys.h" 16 | #endif 17 | 18 | extern SemaphoreHandle_t s_safe_printf_mux; 19 | 20 | #define SAFE_PRINTF(...) \ 21 | do { xSemaphoreTake(s_safe_printf_mux, portMAX_DELAY); \ 22 | ets_printf(__VA_ARGS__); \ 23 | xSemaphoreGive(s_safe_printf_mux); \ 24 | } while (false) 25 | 26 | -------------------------------------------------------------------------------- /components/common/structures.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/common/structures.cpp -------------------------------------------------------------------------------- /components/common/structures.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | /* 9 | constexpr uint8_t WLAN_IEEE_HEADER_AIR2GROUND[] = 10 | { 11 | 0x08, 0x01, 0x00, 0x00, 12 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 13 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 14 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 15 | 0x10, 0x86 16 | }; 17 | */ 18 | 19 | 20 | //first byte - frame control 21 | //https://www.geeksforgeeks.org/ieee-802-11-mac-frame/ 22 | //https://en.wikipedia.org/wiki/802.11_Frame_Types 23 | //each byte shifted from lower bits 24 | //08 = 00 version, 01 frame type, 0000 subtype 25 | constexpr uint8_t WLAN_IEEE_HEADER_AIR2GROUND[] = 26 | { 27 | 0x08, 0x00, 0x00, 0x00, 28 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 29 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 30 | 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 31 | 0x10, 0x86 32 | }; 33 | 34 | 35 | constexpr uint8_t WLAN_IEEE_HEADER_GROUND2AIR[] = 36 | { 37 | 0x08, 0x01, 0x00, 0x00, 38 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 39 | 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 40 | 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 41 | 0x10, 0x86 42 | }; 43 | 44 | constexpr size_t WLAN_IEEE_HEADER_SIZE = sizeof(WLAN_IEEE_HEADER_AIR2GROUND); 45 | constexpr size_t WLAN_MAX_PACKET_SIZE = 1500; 46 | constexpr size_t WLAN_MAX_PAYLOAD_SIZE = WLAN_MAX_PACKET_SIZE - WLAN_IEEE_HEADER_SIZE; 47 | 48 | static_assert(WLAN_IEEE_HEADER_SIZE == 24, ""); 49 | 50 | struct Wlan_Outgoing_Packet 51 | { 52 | uint8_t* ptr = nullptr; 53 | uint8_t* payload_ptr = nullptr; 54 | uint16_t size = 0; 55 | uint16_t offset = 0; 56 | }; 57 | 58 | struct Wlan_Incoming_Packet 59 | { 60 | uint8_t* ptr = nullptr; 61 | uint16_t size = 0; 62 | uint16_t offset = 0; 63 | }; 64 | 65 | //////////////////////////////////////////////////////////////////////////////////// 66 | 67 | 68 | -------------------------------------------------------------------------------- /components/common/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | //============================================================== 4 | //============================================================== 5 | int smallestPowerOfTwo(int value, int minValue) 6 | { 7 | if (value < minValue) 8 | { 9 | return minValue; 10 | } 11 | 12 | if (value < 2) 13 | { 14 | return 2; 15 | } 16 | 17 | int powerOfTwo = 1; 18 | while (powerOfTwo < value) 19 | { 20 | powerOfTwo <<= 1; 21 | } 22 | 23 | return powerOfTwo; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /components/common/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | T clamp(T value, T min, T max) 5 | { 6 | return (value < min) ? min : (value > max) ? max : value; 7 | } 8 | extern int smallestPowerOfTwo(int value, int minValue); 9 | -------------------------------------------------------------------------------- /components/common/vcd_profiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //=========================================================== 4 | //Uncomment to enable profiler 5 | #define PROFILE_CAMERA_DATA 6 | 7 | 8 | //uncomment to start profiling with button 9 | //#define START_PROFILER_WITH_BUTTON 10 | //=========================================================== 11 | 12 | //------------------------ 13 | #ifdef PROFILE_CAMERA_DATA 14 | 15 | #define ENABLE_PROFILER 16 | 17 | #define PF_CAMERA_DATA 0 18 | #define PF_CAMERA_FRAME_QUALITY 1 19 | #define PF_CAMERA_DATA_SIZE 2 20 | #define PF_CAMERA_FEC_POOL 3 21 | #define PF_CAMERA_FEC 4 22 | #define PF_CAMERA_WIFI_TX 5 23 | #define PF_CAMERA_WIFI_QUEUE 6 24 | #define PF_CAMERA_SD_FAST_BUF 7 25 | #define PF_CAMERA_SD_SLOW_BUF 8 26 | #define PF_CAMERA_FEC_SPIN 9 27 | #define PF_CAMERA_WIFI_SPIN 10 28 | #define PF_CAMERA_WIFI_DONE_CB 11 29 | #define PF_CAMERA_FEC_OVF 12 30 | #define PF_CAMERA_WIFI_OVF 13 31 | #define PF_CAMERA_OVF 14 32 | #define PF_CAMERA_SD_OVF 15 33 | 34 | #define PF0_NAME "cam_data" 35 | #define PF1_NAME "quality" 36 | #define PF2_NAME "data_size" 37 | #define PF3_NAME "fec_pool" 38 | #define PF4_NAME "fec" 39 | #define PF5_NAME "wifi_tx" 40 | #define PF6_NAME "wifi_queue" 41 | #define PF7_NAME "sd_fast_buf" 42 | #define PF8_NAME "sd_slow_buf" 43 | #define PF9_NAME "fec_spin" 44 | #define PF10_NAME "wifi_spin" 45 | #define PF11_NAME "wifi_done_cb" 46 | #define PF12_NAME "fec_ovf" 47 | #define PF13_NAME "wifi_ovf" 48 | #define PF14_NAME "cam_ovf" 49 | #define PF15_NAME "sd_ovf" 50 | 51 | 52 | #endif 53 | 54 | //=========================================================== 55 | #ifdef ENABLE_PROFILER 56 | 57 | #include 58 | #include 59 | #include 60 | 61 | #include "freertos/FreeRTOS.h" 62 | #include "freertos/queue.h" 63 | #include "freertos/task.h" 64 | #include "freertos/semphr.h" 65 | 66 | //=========================================================== 67 | //=========================================================== 68 | class VCDProfiler 69 | { 70 | public: 71 | VCDProfiler(); 72 | 73 | static const size_t BUFFER_SIZE = 500*1024; 74 | static const size_t MAX_SAMPLES = BUFFER_SIZE / 4; 75 | 76 | //16 * 65536*16 = ~16 seconds profiling max 77 | static const size_t MAX_TIMESTAMP_VALUE = 0xfffff; 78 | 79 | static const size_t CHANNELS_COUNT = 16; 80 | 81 | struct Descriptor 82 | { 83 | uint32_t timestamp:20; //16us unit 84 | //uint32_t core:1; 85 | uint32_t var:4; 86 | uint32_t value:8; 87 | }; 88 | 89 | bool init(); 90 | 91 | void start(int32_t duration_ms = (MAX_TIMESTAMP_VALUE << 4 / 1000) ); 92 | void set(int var, int val); 93 | void toggle(int var); 94 | 95 | void stop(); 96 | void save(); 97 | void clear(); 98 | 99 | bool full(); 100 | bool timedOut(); 101 | 102 | bool isActive(); 103 | 104 | private: 105 | 106 | bool active; 107 | int count; 108 | uint16_t regFlags; 109 | uint16_t lastVal; 110 | int64_t startTime; 111 | int32_t duration; 112 | 113 | SemaphoreHandle_t profiler_mux; 114 | Descriptor* buffer; 115 | }; 116 | 117 | 118 | extern VCDProfiler s_profiler; 119 | 120 | 121 | #endif -------------------------------------------------------------------------------- /components/esp32-camera/.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build examples 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | 8 | jobs: 9 | build-master: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | idf_target: ["esp32", "esp32s2", "esp32s3"] 14 | steps: 15 | - name: Checkout repo 16 | uses: actions/checkout@v2 17 | with: 18 | submodules: 'recursive' 19 | - name: esp-idf build 20 | uses: espressif/esp-idf-ci-action@main 21 | with: 22 | target: ${{ matrix.idf_target }} 23 | path: 'examples' 24 | 25 | build-release-v5_0: 26 | name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} 27 | runs-on: ubuntu-latest 28 | strategy: 29 | matrix: 30 | idf_ver: ["release-v5.0"] 31 | idf_target: ["esp32", "esp32s2", "esp32s3"] 32 | steps: 33 | - name: Checkout repo 34 | uses: actions/checkout@v2 35 | with: 36 | submodules: 'recursive' 37 | - name: esp-idf build 38 | uses: espressif/esp-idf-ci-action@main 39 | with: 40 | esp_idf_version: ${{ matrix.idf_ver }} 41 | target: ${{ matrix.idf_target }} 42 | path: 'examples' 43 | 44 | build-release-v4_4: 45 | name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} 46 | runs-on: ubuntu-latest 47 | strategy: 48 | matrix: 49 | idf_ver: ["v4.4"] 50 | idf_target: ["esp32", "esp32s2", "esp32s3"] 51 | steps: 52 | - name: Checkout repo 53 | uses: actions/checkout@v2 54 | with: 55 | submodules: 'recursive' 56 | - name: esp-idf build 57 | uses: espressif/esp-idf-ci-action@main 58 | with: 59 | esp_idf_version: ${{ matrix.idf_ver }} 60 | target: ${{ matrix.idf_target }} 61 | path: 'examples' 62 | 63 | build-release-v4_1: 64 | runs-on: ubuntu-latest 65 | steps: 66 | - name: Checkout repo 67 | uses: actions/checkout@v2 68 | with: 69 | submodules: 'recursive' 70 | - name: esp-idf build 71 | uses: espressif/esp-idf-ci-action@release-v4.1 72 | with: 73 | path: 'examples' 74 | 75 | build-release-v4_2: 76 | runs-on: ubuntu-latest 77 | steps: 78 | - name: Checkout repo 79 | uses: actions/checkout@v2 80 | with: 81 | submodules: 'recursive' 82 | - name: esp-idf build 83 | uses: espressif/esp-idf-ci-action@release-v4.2 84 | with: 85 | path: 'examples' 86 | 87 | build-release-v4_3: 88 | runs-on: ubuntu-latest 89 | steps: 90 | - name: Checkout repo 91 | uses: actions/checkout@v2 92 | with: 93 | submodules: 'recursive' 94 | - name: esp-idf build 95 | uses: espressif/esp-idf-ci-action@release-v4.3 96 | with: 97 | path: 'examples' 98 | -------------------------------------------------------------------------------- /components/esp32-camera/.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Mark stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | - cron: '20 9 * * *' 11 | 12 | jobs: 13 | stale: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | issues: write 18 | pull-requests: write 19 | 20 | steps: 21 | - uses: actions/stale@v3 22 | with: 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | stale-issue-message: 'This issue appears to be stale. Please close it if its no longer valid.' 25 | stale-pr-message: 'This pull request appears to be stale. Please close it if its no longer valid.' 26 | stale-issue-label: 'no-issue-activity' 27 | stale-pr-label: 'no-pr-activity' 28 | -------------------------------------------------------------------------------- /components/esp32-camera/.github/workflows/upload_component.yml: -------------------------------------------------------------------------------- 1 | name: Push component to https://components.espressif.com 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | jobs: 7 | upload_components: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@master 11 | with: 12 | submodules: "recursive" 13 | - name: Upload component to the component registry 14 | uses: espressif/github-actions/upload_components@master 15 | with: 16 | name: "esp32-camera" 17 | namespace: "espressif" 18 | version: ${{ github.ref_name }} 19 | api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} 20 | -------------------------------------------------------------------------------- /components/esp32-camera/.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | .vscode 3 | **/build 4 | **/sdkconfig 5 | **/sdkconfig.old -------------------------------------------------------------------------------- /components/esp32-camera/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # get IDF version for comparison 2 | set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") 3 | 4 | # set conversion sources 5 | set(COMPONENT_SRCS 6 | conversions/yuv.c 7 | conversions/to_jpg.cpp 8 | conversions/to_bmp.c 9 | conversions/jpge.cpp 10 | conversions/esp_jpg_decode.c 11 | ) 12 | 13 | set(COMPONENT_PRIV_INCLUDEDIRS 14 | conversions/private_include 15 | ) 16 | 17 | set(COMPONENT_ADD_INCLUDEDIRS 18 | driver/include 19 | conversions/include 20 | ) 21 | 22 | set(COMPONENT_REQUIRES driver) 23 | 24 | # set driver sources only for supported platforms 25 | if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") 26 | list(APPEND COMPONENT_SRCS 27 | driver/esp_camera.c 28 | driver/cam_hal.c 29 | driver/sccb.c 30 | driver/sensor.c 31 | sensors/ov2640.c 32 | sensors/ov3660.c 33 | sensors/ov5640.c 34 | sensors/ov7725.c 35 | sensors/ov7670.c 36 | sensors/nt99141.c 37 | sensors/gc0308.c 38 | sensors/gc2145.c 39 | sensors/gc032a.c 40 | sensors/bf3005.c 41 | sensors/bf20a6.c 42 | sensors/sc101iot.c 43 | sensors/sc030iot.c 44 | sensors/sc031gs.c 45 | ) 46 | 47 | list(APPEND COMPONENT_PRIV_INCLUDEDIRS 48 | driver/private_include 49 | sensors/private_include 50 | target/private_include 51 | ) 52 | 53 | if(IDF_TARGET STREQUAL "esp32") 54 | list(APPEND COMPONENT_SRCS 55 | target/xclk.c 56 | target/esp32/ll_cam.c 57 | ) 58 | endif() 59 | 60 | if(IDF_TARGET STREQUAL "esp32s2") 61 | list(APPEND COMPONENT_SRCS 62 | target/xclk.c 63 | target/esp32s2/ll_cam.c 64 | target/esp32s2/tjpgd.c 65 | ) 66 | 67 | list(APPEND COMPONENT_PRIV_INCLUDEDIRS 68 | target/esp32s2/private_include 69 | ) 70 | endif() 71 | 72 | if(IDF_TARGET STREQUAL "esp32s3") 73 | list(APPEND COMPONENT_SRCS 74 | target/esp32s3/ll_cam.c 75 | ) 76 | endif() 77 | 78 | set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) 79 | 80 | set(min_version_for_esp_timer "4.2") 81 | if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer) 82 | list(APPEND COMPONENT_PRIV_REQUIRES esp_timer) 83 | endif() 84 | 85 | endif() 86 | 87 | register_component() 88 | -------------------------------------------------------------------------------- /components/esp32-camera/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include 2 | COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include 3 | COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 4 | CXXFLAGS += -fno-rtti 5 | -------------------------------------------------------------------------------- /components/esp32-camera/conversions/include/esp_jpg_decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _ESP_JPG_DECODE_H_ 15 | #define _ESP_JPG_DECODE_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_err.h" 25 | 26 | typedef enum { 27 | JPG_SCALE_NONE, 28 | JPG_SCALE_2X, 29 | JPG_SCALE_4X, 30 | JPG_SCALE_8X, 31 | JPG_SCALE_MAX = JPG_SCALE_8X 32 | } jpg_scale_t; 33 | 34 | typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); 35 | typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); 36 | 37 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* _ESP_JPG_DECODE_H_ */ 44 | -------------------------------------------------------------------------------- /components/esp32-camera/conversions/private_include/yuv.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _CONVERSIONS_YUV_H_ 15 | #define _CONVERSIONS_YUV_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | 23 | void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* _CONVERSIONS_YUV_H_ */ 30 | -------------------------------------------------------------------------------- /components/esp32-camera/driver/private_include/cam_hal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_camera.h" 18 | 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Uninitialize the lcd_cam module 26 | * 27 | * @param handle Provide handle pointer to release resources 28 | * 29 | * @return 30 | * - ESP_OK Success 31 | * - ESP_FAIL Uninitialize fail 32 | */ 33 | esp_err_t cam_deinit(void); 34 | 35 | /** 36 | * @brief Initialize the lcd_cam module 37 | * 38 | * @param config Configurations - see lcd_cam_config_t struct 39 | * 40 | * @return 41 | * - ESP_OK Success 42 | * - ESP_ERR_INVALID_ARG Parameter error 43 | * - ESP_ERR_NO_MEM No memory to initialize lcd_cam 44 | * - ESP_FAIL Initialize fail 45 | */ 46 | esp_err_t cam_init(const camera_config_t *config); 47 | 48 | esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid); 49 | 50 | void cam_stop(void); 51 | 52 | void cam_start(void); 53 | 54 | camera_fb_t *cam_take(TickType_t timeout); 55 | 56 | void cam_give(camera_fb_t *dma_buffer); 57 | 58 | void cam_give_all(void); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /components/esp32-camera/driver/private_include/sccb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #ifndef __SCCB_H__ 10 | #define __SCCB_H__ 11 | #include 12 | int SCCB_Init(int pin_sda, int pin_scl); 13 | int SCCB_Use_Port(int sccb_i2c_port); 14 | int SCCB_Deinit(void); 15 | uint8_t SCCB_Probe(void); 16 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); 17 | int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); 18 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); 19 | int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); 20 | uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg); 21 | int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data); 22 | #endif // __SCCB_H__ 23 | -------------------------------------------------------------------------------- /components/esp32-camera/driver/private_include/xclk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "esp_system.h" 4 | #include "esp_camera.h" 5 | 6 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz); 7 | 8 | esp_err_t camera_enable_out_clock(const camera_config_t *config); 9 | 10 | void camera_disable_out_clock(void); 11 | -------------------------------------------------------------------------------- /components/esp32-camera/driver/sensor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sensor.h" 3 | 4 | const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { 5 | // The sequence must be consistent with camera_model_t 6 | {CAMERA_OV7725, "OV7725", OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA, false}, 7 | {CAMERA_OV2640, "OV2640", OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA, true}, 8 | {CAMERA_OV3660, "OV3660", OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA, true}, 9 | {CAMERA_OV5640, "OV5640", OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA, true}, 10 | {CAMERA_OV7670, "OV7670", OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA, false}, 11 | {CAMERA_NT99141, "NT99141", NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD, true}, 12 | {CAMERA_GC2145, "GC2145", GC2145_SCCB_ADDR, GC2145_PID, FRAMESIZE_UXGA, false}, 13 | {CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false}, 14 | {CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false}, 15 | {CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false}, 16 | {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false}, 17 | {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false}, 18 | {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false}, 19 | {CAMERA_SC031GS, "SC031GS", SC031GS_SCCB_ADDR, SC031GS_PID, FRAMESIZE_VGA, false}, 20 | }; 21 | 22 | const resolution_info_t resolution[FRAMESIZE_INVALID] = { 23 | { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ 24 | { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ 25 | { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ 26 | { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ 27 | { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ 28 | { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ 29 | { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ 30 | { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ 31 | { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ 32 | { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ 33 | { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ 34 | { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ 35 | { 1280, 960, ASPECT_RATIO_4X3 }, /* SXGA */ 36 | { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ 37 | // 3MP Sensors 38 | { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ 39 | { 800, 456, ASPECT_RATIO_16X9 }, /* Portrait HD changed to 800x456 */ 40 | { 640, 360, ASPECT_RATIO_16X9 }, /* Portrait 3MP changed to 640x360 */ 41 | { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ 42 | // 5MP Sensors 43 | { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ 44 | { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ 45 | { 1024, 576, ASPECT_RATIO_16X9 }, /* Portrait FHD chaged to 1024x576 */ 46 | { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ 47 | }; 48 | 49 | camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id) 50 | { 51 | for (int i = 0; i < CAMERA_MODEL_MAX; i++) { 52 | if (id->PID == camera_sensor[i].pid) { 53 | return (camera_sensor_info_t *)&camera_sensor[i]; 54 | } 55 | } 56 | return NULL; 57 | } 58 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | set(EXTRA_COMPONENT_DIRS "../") 6 | 7 | add_compile_options(-fdiagnostics-color=always) 8 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 9 | project(camera_example) -------------------------------------------------------------------------------- /components/esp32-camera/examples/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := camera_example 7 | 8 | EXTRA_COMPONENT_DIRS := ../ 9 | 10 | include $(IDF_PATH)/make/project.mk 11 | 12 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/camera_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | set(COMPONENTS main) 6 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 7 | project(camera_example) 8 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/camera_example/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS take_picture.c 2 | PRIV_INCLUDE_DIRS . 3 | PRIV_REQUIRES nvs_flash) 4 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/camera_example/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | espressif/esp32-camera: 3 | version: "*" 4 | override_path: "../../../" 5 | 6 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/camera_example/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 2 | CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y 3 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y 4 | 5 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 6 | CONFIG_PARTITION_TABLE_OFFSET=0x10000 7 | 8 | CONFIG_FREERTOS_HZ=1000 9 | CONFIG_ESPTOOLPY_FLASHFREQ_80M=y 10 | CONFIG_ESPTOOLPY_FLASHMODE_QIO=y 11 | 12 | CONFIG_SPIRAM_SUPPORT=y 13 | CONFIG_ESP32_SPIRAM_SUPPORT=y 14 | CONFIG_ESP32S2_SPIRAM_SUPPORT=y 15 | CONFIG_ESP32S3_SPIRAM_SUPPORT=y 16 | CONFIG_SPIRAM_SPEED_80M=y 17 | 18 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS take_picture.c) 2 | set(COMPONENT_ADD_INCLUDEDIRS .) 3 | register_component() -------------------------------------------------------------------------------- /components/esp32-camera/examples/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # "main" pseudo-component makefile. 3 | # 4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) 5 | 6 | -------------------------------------------------------------------------------- /components/esp32-camera/examples/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 2 | CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y 3 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y 4 | 5 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 6 | CONFIG_PARTITION_TABLE_OFFSET=0x10000 7 | 8 | CONFIG_FREERTOS_HZ=1000 9 | CONFIG_ESPTOOLPY_FLASHFREQ_80M=y 10 | CONFIG_ESPTOOLPY_FLASHMODE_QIO=y 11 | 12 | CONFIG_SPIRAM_SUPPORT=y 13 | CONFIG_ESP32_SPIRAM_SUPPORT=y 14 | CONFIG_ESP32S2_SPIRAM_SUPPORT=y 15 | CONFIG_ESP32S3_SPIRAM_SUPPORT=y 16 | CONFIG_SPIRAM_SPEED_80M=y 17 | 18 | -------------------------------------------------------------------------------- /components/esp32-camera/idf_component.yml: -------------------------------------------------------------------------------- 1 | description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors. 2 | url: https://github.com/espressif/esp32-camera 3 | -------------------------------------------------------------------------------- /components/esp32-camera/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esp32-camera", 3 | "version": "2.0.0", 4 | "keywords": "esp32, camera, espressif, esp32-cam", 5 | "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/espressif/esp32-camera" 9 | }, 10 | "frameworks": "espidf", 11 | "platforms": "*", 12 | "build": { 13 | "flags": [ 14 | "-Idriver/include", 15 | "-Iconversions/include", 16 | "-Idriver/private_include", 17 | "-Iconversions/private_include", 18 | "-Isensors/private_include", 19 | "-Itarget/private_include", 20 | "-fno-rtti" 21 | ], 22 | "includeDir": ".", 23 | "srcDir": ".", 24 | "srcFilter": ["-<*>", "+", "+", "+"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/bf20a6.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BF20A6_H__ 3 | #define __BF20A6_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int bf20a6_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int bf20a6_init(sensor_t *sensor); 26 | 27 | #endif // __BF20A6_H__ 28 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/bf20a6_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BF20A6 register definitions. 3 | */ 4 | #ifndef __BF20A6_REG_REGS_H__ 5 | #define __BF20A6_REG_REGS_H__ 6 | 7 | #define SENSOR_ID_HIGH 0XFC 8 | #define SENSOR_ID_LOW 0XFD 9 | #define RESET_RELATED 0XF2 10 | 11 | 12 | #endif //__BF20A6_REG_REGS_H__ 13 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/bf3005.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * BF3005 driver. 7 | * 8 | */ 9 | #ifndef __BF3005_H__ 10 | #define __BF3005_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int bf3005_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int bf3005_init(sensor_t *sensor); 32 | 33 | #endif // __BF3005_H__ -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/bf3005_regs.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/esp32-camera/sensors/private_include/bf3005_regs.h -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc0308.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sensor.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /** 10 | * @brief Detect sensor pid 11 | * 12 | * @param slv_addr SCCB address 13 | * @param id Detection result 14 | * @return 15 | * 0: Can't detect this sensor 16 | * Nonzero: This sensor has been detected 17 | */ 18 | int gc0308_detect(int slv_addr, sensor_id_t *id); 19 | 20 | /** 21 | * @brief initialize sensor function pointers 22 | * 23 | * @param sensor pointer of sensor 24 | * @return 25 | * Always 0 26 | */ 27 | int gc0308_init(sensor_t *sensor); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc0308_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC0308 register definitions. 3 | */ 4 | #ifndef __GC0308_REG_REGS_H__ 5 | #define __GC0308_REG_REGS_H__ 6 | 7 | #define RESET_RELATED 0xfe // Bit[7]: Software reset 8 | // Bit[6:5]: NA 9 | // Bit[4]: CISCTL_restart_n 10 | // Bit[3:1]: NA 11 | // Bit[0]: page select 12 | // 0:page0 13 | // 1:page1 14 | 15 | 16 | // page0: 17 | 18 | 19 | 20 | /** 21 | * @brief register value 22 | */ 23 | 24 | 25 | #endif // __GC0308_REG_REGS_H__ 26 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc032a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * GC032A driver. 4 | * 5 | */ 6 | #ifndef __GC032A_H__ 7 | #define __GC032A_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int gc032a_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int gc032a_init(sensor_t *sensor); 30 | 31 | #endif // __GC032A_H__ 32 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc032a_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC032A register definitions. 3 | */ 4 | #ifndef __GC032A_REG_REGS_H__ 5 | #define __GC032A_REG_REGS_H__ 6 | 7 | #define SENSOR_ID_HIGH 0XF0 8 | #define SENSOR_ID_LOW 0XF1 9 | #define PAD_VB_HIZ_MODE 0XF2 10 | #define SYNC_OUTPUT 0XF3 11 | #define I2C_CONFIG 0XF4 12 | #define PLL_MODE1 0XF7 13 | #define PLL_MODE2 0XF8 14 | #define CM_MODE 0XF9 15 | #define ISP_DIV_MODE 0XFA 16 | #define I2C_DEVICE_ID 0XFB 17 | #define ANALOG_PWC 0XFC 18 | #define ISP_DIV_MODE2 0XFD 19 | #define RESET_RELATED 0XFE // Bit[7]: Software reset 20 | // Bit[6]: cm reset 21 | // Bit[5]: spi reset 22 | // Bit[4]: CISCTL_restart_n 23 | // Bit[3]: PLL_rst 24 | // Bit[2:0]: page select 25 | // 000:page0 26 | // 001:page1 27 | // 010:page2 28 | // 011:page3 29 | 30 | //----page0----------------------------- 31 | #define P0_EXPOSURE_HIGH 0X03 32 | #define P0_EXPOSURE_LOW 0X04 33 | #define P0_HB_HIGH 0X05 34 | #define P0_HB_LOW 0X06 35 | #define P0_VB_HIGH 0X07 36 | #define P0_VB_LOW 0X08 37 | #define P0_ROW_START_HIGH 0X09 38 | #define P0_ROW_START_LOW 0X0A 39 | #define P0_COLUMN_START_HIGH 0X0B 40 | #define P0_COLUMN_START_LOW 0X0C 41 | #define P0_WINDOW_HEIGHT_HIGH 0X0D 42 | #define P0_WINDOW_HEIGHT_LOW 0X0E 43 | #define P0_WINDOW_WIDTH_HIGH 0X0F 44 | #define P0_WINDOW_WIDTH_LOW 0X10 45 | #define P0_SH_DELAY 0X11 46 | #define P0_VS_ST 0X12 47 | #define P0_VS_ET 0X13 48 | #define P0_CISCTL_MODE1 0X17 49 | 50 | #define P0_BLOCK_ENABLE_1 0X40 51 | #define P0_AAAA_ENABLE 0X42 52 | #define P0_SPECIAL_EFFECT 0X43 53 | #define P0_SYNC_MODE 0X46 54 | #define P0_GAIN_CODE 0X48 55 | #define P0_DEBUG_MODE2 0X4C 56 | #define P0_WIN_MODE 0X50 57 | #define P0_OUT_WIN_Y1_HIGH 0X51 58 | #define P0_OUT_WIN_Y1_LOW 0X52 59 | #define P0_OUT_WIN_X1_HIGH 0X53 60 | #define P0_OUT_WIN_X1_LOW 0X54 61 | #define P0_OUT_WIN_HEIGHT_HIGH 0X55 62 | #define P0_OUT_WIN_HEIGHT_LOW 0X56 63 | #define P0_OUT_WIN_WIDTH_HIGH 0X57 64 | #define P0_OUT_WIN_WIDTH_LOW 0X58 65 | 66 | #define P0_GLOBAL_SATURATION 0XD0 67 | #define P0_SATURATION_CB 0XD1 68 | #define P0_SATURATION_CR 0XD2 69 | #define P0_LUMA_CONTRAST 0XD3 70 | #define P0_CONTRAST_CENTER 0XD4 71 | #define P0_LUMA_OFFSET 0XD5 72 | #define P0_FIXED_CB 0XDA 73 | #define P0_FIXED_CR 0XDB 74 | 75 | //----page3----------------------------- 76 | #define P3_IMAGE_WIDTH_LOW 0X5B 77 | #define P3_IMAGE_WIDTH_HIGH 0X5C 78 | #define P3_IMAGE_HEIGHT_LOW 0X5D 79 | #define P3_IMAGE_HEIGHT_HIGH 0X5E 80 | 81 | 82 | #endif //__GC032A_REG_REGS_H__ 83 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc2145.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __GC2145_H__ 3 | #define __GC2145_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int gc2145_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int gc2145_init(sensor_t *sensor); 26 | 27 | #endif // __GC2145_H__ 28 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/gc2145_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC2145 register definitions. 3 | */ 4 | #ifndef __GC2145_REG_REGS_H__ 5 | #define __GC2145_REG_REGS_H__ 6 | 7 | #define CHIP_ID_HIGH 0XF0 8 | #define CHIP_ID_LOW 0XF1 9 | #define PLL_MODE1 0XF7 10 | #define PLL_MODE2 0XF8 11 | #define CM_MODE 0XF9 12 | #define CLK_DIV_MODE 0XFA 13 | #define RESET_RELATED 0xfe // Bit[7]: Software reset 14 | // Bit[6]: cm reset 15 | // Bit[5]: mipi reset 16 | // Bit[4]: CISCTL_restart_n 17 | // Bit[3]: NA 18 | // Bit[2:0]: page select 19 | // 000:page0 20 | // 001:page1 21 | // 010:page2 22 | // 011:page3 23 | 24 | //-page0---------------- 25 | 26 | #define P0_EXPOSURE_HIGH 0X03 27 | #define P0_EXPOSURE_LOW 0X04 28 | #define P0_HB_HIGH 0X05 29 | #define P0_HB_LOW 0X06 30 | #define P0_VB_HIGH 0X07 31 | #define P0_VB_LOW 0X08 32 | #define P0_ROW_START_HIGH 0X09 33 | #define P0_ROW_START_LOW 0X0A 34 | #define P0_COL_START_HIGH 0X0B 35 | #define P0_COL_START_LOW 0X0C 36 | 37 | #define P0_WIN_HEIGHT_HIGH 0X0D 38 | #define P0_WIN_HEIGHT_LOW 0X0E 39 | #define P0_WIN_WIDTH_HIGH 0X0F 40 | #define P0_WIN_WIDTH_LOW 0X10 41 | #define P0_ANALOG_MODE1 0X17 42 | #define P0_ANALOG_MODE2 0X18 43 | 44 | #define P0_SPECIAL_EFFECT 0X83 45 | #define P0_OUTPUT_FORMAT 0x84 // Format select 46 | // Bit[7]:YUV420 row switch 47 | // Bit[6]:YUV420 col switch 48 | // Bit[7]:YUV420_legacy 49 | // Bit[4:0]:output data mode 50 | // 5’h00 Cb Y Cr Y 51 | // 5’h01 Cr Y Cb Y 52 | // 5’h02 Y Cb Y Cr 53 | // 5’h03 Y Cr Y Cb 54 | // 5’h04 LSC bypass, C/Y 55 | // 5’h05 LSC bypass, Y/C 56 | // 5’h06 RGB 565 57 | // 5’h0f bypass 10bits 58 | // 5’h17 switch odd/even column /row to controls output Bayer pattern 59 | // 00 RGBG 60 | // 01 RGGB 61 | // 10 BGGR 62 | // 11 GBRG 63 | // 5'h18 DNDD out mode 64 | // 5'h19 LSC out mode 65 | // 5;h1b EEINTP out mode 66 | #define P0_FRAME_START 0X85 67 | #define P0_SYNC_MODE 0X86 68 | #define P0_MODULE_GATING 0X88 69 | #define P0_BYPASS_MODE 0X89 70 | #define P0_DEBUG_MODE2 0X8C 71 | #define P0_DEBUG_MODE3 0X8D 72 | #define P0_CROP_ENABLE 0X90 73 | #define P0_OUT_WIN_Y1_HIGH 0X91 74 | #define P0_OUT_WIN_Y1_LOW 0X92 75 | #define P0_OUT_WIN_X1_HIGH 0X93 76 | #define P0_OUT_WIN_X1_LOW 0X94 77 | #define P0_OUT_WIN_HEIGHT_HIGH 0X95 78 | #define P0_OUT_WIN_HEIGHT_LOW 0X96 79 | #define P0_OUT_WIN_WIDTH_HIGH 0X97 80 | #define P0_OUT_WIN_WIDTH_LOW 0X98 81 | #define P0_SUBSAMPLE 0X99 82 | #define P0_SUBSAMPLE_MODE 0X9A 83 | 84 | 85 | #endif // __GC2145_REG_REGS_H__ 86 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/nt99141.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * NT99141 driver. 7 | * 8 | */ 9 | #ifndef __NT99141_H__ 10 | #define __NT99141_H__ 11 | 12 | #include "sensor.h" 13 | 14 | /** 15 | * @brief Detect sensor pid 16 | * 17 | * @param slv_addr SCCB address 18 | * @param id Detection result 19 | * @return 20 | * 0: Can't detect this sensor 21 | * Nonzero: This sensor has been detected 22 | */ 23 | int nt99141_detect(int slv_addr, sensor_id_t *id); 24 | 25 | /** 26 | * @brief initialize sensor function pointers 27 | * 28 | * @param sensor pointer of sensor 29 | * @return 30 | * Always 0 31 | */ 32 | int nt99141_init(sensor_t *sensor); 33 | 34 | #endif // __NT99141_H__ 35 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/ov2640.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 driver. 7 | * 8 | */ 9 | #ifndef __OV2640_H__ 10 | #define __OV2640_H__ 11 | #include "sensor.h" 12 | /** 13 | * @brief Detect sensor pid 14 | * 15 | * @param slv_addr SCCB address 16 | * @param id Detection result 17 | * @return 18 | * 0: Can't detect this sensor 19 | * Nonzero: This sensor has been detected 20 | */ 21 | int ov2640_detect(int slv_addr, sensor_id_t *id); 22 | 23 | /** 24 | * @brief initialize sensor function pointers 25 | * 26 | * @param sensor pointer of sensor 27 | * @return 28 | * Always 0 29 | */ 30 | int ov2640_init(sensor_t *sensor); 31 | 32 | #endif // __OV2640_H__ 33 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/ov3660.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV3660 driver. 7 | * 8 | */ 9 | #ifndef __OV3660_H__ 10 | #define __OV3660_H__ 11 | 12 | #include "sensor.h" 13 | 14 | /** 15 | * @brief Detect sensor pid 16 | * 17 | * @param slv_addr SCCB address 18 | * @param id Detection result 19 | * @return 20 | * 0: Can't detect this sensor 21 | * Nonzero: This sensor has been detected 22 | */ 23 | int ov3660_detect(int slv_addr, sensor_id_t *id); 24 | 25 | /** 26 | * @brief initialize sensor function pointers 27 | * 28 | * @param sensor pointer of sensor 29 | * @return 30 | * Always 0 31 | */ 32 | int ov3660_init(sensor_t *sensor); 33 | 34 | #endif // __OV3660_H__ 35 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/ov5640.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __OV5640_H__ 3 | #define __OV5640_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int ov5640_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int ov5640_init(sensor_t *sensor); 26 | 27 | #endif // __OV5640_H__ 28 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/ov7670.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * author: Juan Schiavoni 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7670 driver. 7 | * 8 | */ 9 | #ifndef __OV7670_H__ 10 | #define __OV7670_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int ov7670_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int ov7670_init(sensor_t *sensor); 32 | 33 | #endif // __OV7670_H__ 34 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/ov7725.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7725 driver. 7 | * 8 | */ 9 | #ifndef __OV7725_H__ 10 | #define __OV7725_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int ov7725_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int ov7725_init(sensor_t *sensor); 32 | 33 | #endif // __OV7725_H__ 34 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/sc030iot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC030IOT DVP driver. 4 | * 5 | */ 6 | #ifndef __SC030IOT_H__ 7 | #define __SC030IOT_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc030iot_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc030iot_init(sensor_t *sensor); 30 | 31 | #endif // __SC030IOT_H__ 32 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/sc031gs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC031GS DVP driver. 4 | * 5 | */ 6 | #ifndef __SC031GS_H__ 7 | #define __SC030GS_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc031gs_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc031gs_init(sensor_t *sensor); 30 | 31 | #endif // __SC031GS_H__ 32 | -------------------------------------------------------------------------------- /components/esp32-camera/sensors/private_include/sc101iot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC101IOT DVP driver. 4 | * 5 | */ 6 | #ifndef __SC101IOT_H__ 7 | #define __SC101IOT_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc101iot_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc101iot_init(sensor_t *sensor); 30 | 31 | #endif // __SC101IOT_H__ 32 | -------------------------------------------------------------------------------- /components/esp32-camera/target/xclk.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include "driver/ledc.h" 3 | #include "esp_err.h" 4 | #include "esp_log.h" 5 | #include "esp_system.h" 6 | #include "xclk.h" 7 | #include "esp_camera.h" 8 | 9 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 10 | #include "esp32-hal-log.h" 11 | #else 12 | #include "esp_log.h" 13 | static const char* TAG = "camera_xclk"; 14 | #endif 15 | 16 | #define NO_CAMERA_LEDC_CHANNEL 0xFF 17 | static ledc_channel_t g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; 18 | 19 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) 20 | { 21 | ledc_timer_config_t timer_conf; 22 | timer_conf.duty_resolution = LEDC_TIMER_1_BIT; 23 | timer_conf.freq_hz = xclk_freq_hz; 24 | timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; 25 | 26 | #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) 27 | timer_conf.deconfigure = false; 28 | #endif 29 | 30 | #if ESP_IDF_VERSION_MAJOR >= 4 31 | timer_conf.clk_cfg = LEDC_AUTO_CLK; 32 | #endif 33 | timer_conf.timer_num = (ledc_timer_t)ledc_timer; 34 | esp_err_t err = ledc_timer_config(&timer_conf); 35 | if (err != ESP_OK) { 36 | ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); 37 | } 38 | return err; 39 | } 40 | 41 | esp_err_t camera_enable_out_clock(const camera_config_t* config) 42 | { 43 | esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); 44 | if (err != ESP_OK) { 45 | ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); 46 | return err; 47 | } 48 | 49 | g_ledc_channel = config->ledc_channel; 50 | ledc_channel_config_t ch_conf; 51 | ch_conf.gpio_num = config->pin_xclk; 52 | ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; 53 | ch_conf.channel = config->ledc_channel; 54 | ch_conf.intr_type = LEDC_INTR_DISABLE; 55 | ch_conf.timer_sel = config->ledc_timer; 56 | ch_conf.duty = 1; 57 | ch_conf.hpoint = 0; 58 | err = ledc_channel_config(&ch_conf); 59 | if (err != ESP_OK) { 60 | ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); 61 | return err; 62 | } 63 | return ESP_OK; 64 | } 65 | 66 | void camera_disable_out_clock() 67 | { 68 | if (g_ledc_channel != NO_CAMERA_LEDC_CHANNEL) { 69 | ledc_stop(LEDC_LOW_SPEED_MODE, g_ledc_channel, 0); 70 | g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /components/esp32-camera/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRC_DIRS . 2 | PRIV_INCLUDE_DIRS . 3 | PRIV_REQUIRES test_utils esp32-camera nvs_flash 4 | EMBED_TXTFILES pictures/testimg.jpeg pictures/test_outside.jpeg pictures/test_inside.jpeg) 5 | -------------------------------------------------------------------------------- /components/esp32-camera/test/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | #Component Makefile 3 | # 4 | 5 | COMPONENT_SRCDIRS += ./ 6 | COMPONENT_PRIV_INCLUDEDIRS += ./ 7 | 8 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive 9 | -------------------------------------------------------------------------------- /components/esp32-camera/test/pictures/test_inside.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/esp32-camera/test/pictures/test_inside.jpeg -------------------------------------------------------------------------------- /components/esp32-camera/test/pictures/test_outside.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/esp32-camera/test/pictures/test_outside.jpeg -------------------------------------------------------------------------------- /components/esp32-camera/test/pictures/testimg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/components/esp32-camera/test/pictures/testimg.jpeg -------------------------------------------------------------------------------- /doc/adding_gs_software_to_ruby_sd_radxa3.md: -------------------------------------------------------------------------------- 1 | # Adding hx-esp32-cam-fpv GS software to existing RubyFPV Radxa Zero 3W SD Card using script 2 | 3 | * Connect **Radxa Zero 3W** GS to LAN using **USB-LAN adapter** 4 | 5 | * Boot **RubyFPV** 6 | 7 | * Enable **ssh** in **RubyFPV** interface **Controller Settings\Local Network Settings\Enable SSH** 8 | 9 | * ssh to the running **RubyFPV** GS. Credentials are ```radxa/radxa``` 10 | 11 | * Actualise time: 12 | 13 | ```sudo timedatectl set-ntp true``` 14 | 15 | * Run ```rsetup```. Enable **/dev/ttyS3** overlay: **Overlays\Manage Overlays\Enable UART3-M0** 16 | 17 | * ```wget https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/refs/heads/release/scripts/install_on_ruby.sh``` 18 | 19 | * ```chmod +x install_on_ruby.sh``` 20 | 21 | * ```./install_on_ruby.sh``` 22 | 23 | * Wait until script finishes and reboots system to **hx-esp32-cam-fpv** GS software. 24 | 25 | ssh connection should stay alive untill reboot. 26 | 27 | See also: Installing fan control service [/doc/installing_fan_control_service.md ](/doc/installing_fan_control_service.md ) 28 | 29 | # Manually adding hx-esp32-cam-fpv GS software to existing RubyFPV SD Card 30 | 31 | The following steps describe what ```install_on_ruby.sh``` script does automatically. 32 | 33 | * Download lastest **RubyFPV** image for **Radxa Zero 3W**: https://rubyfpv.com/downloads.php 34 | 35 | * Write to SD card using **Raspberry PI Imager** (select **Other OS**). 36 | 37 | * Connect Radxa GS to network using USB-LAN adapter 38 | 39 | * Boot image on Radxa GS. Wait untill Ruby interface boots fully. 40 | 41 | * ssh to Radxa GS. Credentials are ```radxa/radxa``` 42 | 43 | * Actualise time: 44 | 45 | ```sudo timedatectl set-ntp true``` 46 | 47 | * Install required packages: 48 | 49 | ```sudo apt-get update``` 50 | 51 | ```sudo apt install --no-install-recommends -y libdrm-dev libgbm-dev libgles2-mesa-dev libpcap-dev libturbojpeg0-dev libts-dev libfreetype6-dev build-essential autoconf automake libtool libasound2-dev libudev-dev libdbus-1-dev libxext-dev libsdl2-dev dkms git aircrack-ng``` 52 | 53 | * Download **esp32-cam-fpv** repository: 54 | 55 | ```cd /home/radxa``` 56 | 57 | ```git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv``` 58 | 59 | * Build ground station software: 60 | 61 | ```cd esp32-cam-fpv``` 62 | 63 | ```cd gs``` 64 | 65 | ```make -j4``` 66 | 67 | * Modify launch script: 68 | 69 | ```sudo nano /root/.profile``` 70 | 71 | Comment out all lines starting from ```echo "Launching Ruby..."``` 72 | 73 | Add line: ```/home/radxa/esp32-cam-fpv/scripts/boot_selection.sh``` 74 | 75 | * Run ```rsetup```. Enable **/dev/ttyS3** overlay: **Overlays\Manage Overlays\Enable UART3-M0** 76 | 77 | * Save and reboot: 78 | 79 | ``` sudo reboot ``` 80 | 81 | 82 | 83 | # Updating groundstation image 84 | 85 | Connect Radxa GS to network using USB-LAN adapter 86 | 87 | To update groundstation software, pull updates from '''release''' branch: 88 | 89 | ```cd /home/radxa/``` 90 | 91 | ```cd esp32-cam-fpv``` 92 | 93 | ```git pull``` 94 | 95 | ```cd gs``` 96 | 97 | ```make``` 98 | 99 | # Development 100 | 101 | See notes on development with **RubyFPV** based image: [/doc/vs_code_remote_development.md ](/doc/vs_code_remote_development.md ) 102 | -------------------------------------------------------------------------------- /doc/building_gs_sd_radxa_3w.md: -------------------------------------------------------------------------------- 1 | 2 | DEPRECATED: Currently GS images are built based on RubyFPV images. 3 | 4 | # Building Ground Station image for Radxa Zero 3W 5 | 6 | We use Armbian because it provides OpenGL ES harware acceleration with KMSDRM without desktop (contrary to official Debian image for Radxa Zero 3W). 7 | 8 | We are using 22.04 with core 5.10.* because wifi driver require it. 9 | 10 | * Download distribution of Armbian, Ubuntu 22.04 (Jammy) Minimal/IOT, kernel 5.10. 11 | https://www.armbian.com/radxa-zero-3/ 12 | 13 | UPDATE: Armiban Ubuntu minimum 22.04 image is not available at Armbian site anymore. There seems to be 22.04 version here, https://joshua-riek.github.io/ubuntu-rockchip-download/boards/radxa-zero3.html , but it is not checked. 14 | 15 | * Write to SD card using Raspberry PI Imager (select **Other Os**). 16 | 17 | * Boot image. 18 | 19 | * Either use connected usb keyboard or ssh connect using putty. Find out ip address: ```ifconfig``` 20 | 21 | * Update: 22 | 23 | ```sudo apt-get update``` 24 | 25 | * start ```sudo armbian-config``` and change the following options: 26 | * Software -> Install headers 27 | * **TODO**: enable UART 28 | 29 | * Install required packages: 30 | 31 | ```sudo apt install --no-install-recommends -y libdrm-dev libgbm-dev libgles2-mesa-dev libpcap-dev libturbojpeg0-dev libts-dev libfreetype6-dev build-essential autoconf automake libtool libasound2-dev libudev-dev libdbus-1-dev libxext-dev libsdl2-dev dkms git aircrack-ng``` 32 | 33 | * Install rtl8812au driver: 34 | 35 | ```cd ~``` 36 | 37 | ```git clone -b v5.2.20-rssi-fix-but-sometimes-crash https://github.com/svpcom/rtl8812au/``` 38 | 39 | ```cd rtl8812au``` 40 | 41 | ```sudo ./dkms-install.sh``` 42 | 43 | * Download **esp32-cam-fpv** repository: 44 | 45 | ```cd ~``` 46 | 47 | ```git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv``` 48 | 49 | * Adding GPIO keys support: 50 | 51 | **TODO** 52 | 53 | * Build ground station software: 54 | 55 | ```cd ~``` 56 | 57 | ```cd esp32-cam-fpv``` 58 | 59 | ```cd gs``` 60 | 61 | ```make -j4``` 62 | 63 | * Check that everything works: 64 | 65 | ```sudo /home/radxa/esp32-cam-fpv/gs/launch.sh``` 66 | 67 | (exit using SPACE) 68 | 69 | * Add ground station software to autolaunch: 70 | 71 | ```sudo nano /etc/rc.local``` 72 | 73 | Add a line before before ```exit 0``` 74 | 75 | ```sudo /home/pi/esp32-cam-fpv/gs/launch.sh``` 76 | 77 | Exit and save (Ctrl+X): 78 | 79 | * Reboot, check if everything works: 80 | 81 | ```sudo reboot``` 82 | 83 | # Updating groundstation image 84 | 85 | Groundstation software is started automatically. Once it is started, wifi connection is disabled. To be able to reconfigure image, unplug external wifi card. Image will boot and will keep connection to access point using internal wifi card. 86 | 87 | To update groundstation software, pull updates from '''release''' branch: 88 | 89 | ```cd esp32-cam-fpv``` 90 | 91 | ```cd gs``` 92 | 93 | ```git pull``` 94 | 95 | ```make``` 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /doc/composite_output.md: -------------------------------------------------------------------------------- 1 | 2 | # Composite output on Raspberry PI 3 | 4 | It is possible to use Raspberry PI based ground station with FPV glasses which do not have HDMI input. 5 | 6 | By default, RPI image is configured to use HDMI output with option in ```config.txt```: 7 | 8 | ```hdmi_force_hotplug=1``` 9 | 10 | Composite output can be enabled either by running ```sudo raspi-config``` or by disabling this option: 11 | 12 | ```sudo nano /boot/config.txt``` (or edit ```config.txt``` on Windows PC). 13 | 14 | With ```hdmi_force_hotplug=0```, Pi will try to output via HDMI. If no HDMI device is detected, it will fall back to composite video. 15 | 16 | For Raspberry PI4 it is a little bit different. RPI4 has to be configured either for HDMI or Composite output with option: 17 | 18 | ```enable_tvout=1``` 19 | 20 | For composite output, default mode is NTSC. PAL mode can be enabled with: 21 | 22 | ```sdtv_mode=2``` 23 | 24 | If image does not fit screen properly, uncomment and use the following options to make adjustments: 25 | 26 | ``` 27 | # uncomment this if your display has a black border of unused pixels visible 28 | # and your display can output without overscan 29 | #disable_overscan=1 30 | 31 | # uncomment the following to adjust overscan. Use positive numbers if console 32 | # goes off screen, and negative if there is too much border 33 | #overscan_left=16 34 | #overscan_right=16 35 | #overscan_top=16 36 | #overscan_bottom=16 37 | ``` 38 | 39 | Note that NTSC is 720x480x60i and PAL is 720x576x50i (interlaced). Composite can not handle higher modes. "Progessive" modes (``sdtv_mode=16`` and ``sdtv_mode=18``) on RPI are 720x240p and 720x288p. 40 | 41 | So: 42 | 43 | 1) PAL is prefferable 44 | 2) There is no sense to use 1024x576 with composite output. 45 | 46 | # Pinout 47 | 48 | ## Raspberry PI Zero 2W 49 | 50 | Raspberry PI Zero 2W does not have composite video connector. It has to be soldered to pads: 51 | 52 | ![alt text](images/rpi2w_composite_pinout.png "rpi2w_composite_pinout.png") 53 | 54 | ## Raspberry PI 4 55 | 56 | Raspberry PI 4 requires specific connector: 57 | 58 | ![alt text](images/rpi4_composite_pinout.png "rpi4_composite_pinout.png") 59 | -------------------------------------------------------------------------------- /doc/connecting_fan.md: -------------------------------------------------------------------------------- 1 | # Connecting Fan 2 | 3 | See also: [Installing Fan Control Service](/doc/installing_fan_control_service.md ) 4 | 5 | To prevent overheating, it is recommended to install a cooling fan with adjustable speed control. 6 | 7 | Fan speed is controlled by a script, which also allows adjustment of the PWM signal frequency. 8 | 9 | # 4-wire fan 10 | 11 | 4-wire 5V fan with dedicated PWM wire does not need additonal schematcs and can be connected directly to +5V and FAN_PWM pin. 12 | 13 | Fan should be compatible with 3.3 PWM signal. 14 | 15 | How to Check Fan Compatibility: 16 | - Connect the fan to +5V power. 17 | - Measure the voltage on the PWM pin — it should be 3.3V or lower. 18 | - If the voltage is within range, connect the PWM wire to FAN_PWM pin and verify if the fan operates correctly. 19 | 20 | PWM frequency in the script should be set to 25Hz (default). 21 | 22 | # 2-wire fan 23 | 24 | A 2-wire fan (or a 3-wire fan with a speed sensor) can be connected in one of the following ways: 25 | - Direct connection to +5V or VBAT for continuous full-speed operation 26 | - Using a basic PWM circuit for simple speed control 27 | - Using an advanced PWM circuit for quiet operation 28 | 29 | ## Basic PWM Fan speed control schematics 30 | 31 | ![alt text](images/fan_pwm_simple_schematics.png "fan_pwm_simple_schematics.png") 32 | ![alt text](images/fan_pwm_simple_pcb.jpg "fan_pwm_simple_pcb.jpg") 33 | 34 | PWM frequency in the script should be set to 25Hz (default). 35 | Most fans do not operate reliably at PWM frequencies above 50 Hz. 36 | Due to the low frequency, some noise during operation may occur. 37 | 38 | ## Advanced PWM Fan speed control schematics 39 | 40 | ![alt text](images/fan_pwm_buck_schematics.png "fan_pwm_simple_schematics.png") 41 | ![alt text](images/fan_pwm_buck_pcb.jpg "fan_pwm_simple_pcb.jpg") 42 | 43 | PWM frequency in the script should be set to 30000 (30Khz). 44 | This configuration allows the fan to operate quietly. 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /doc/datasheets/ESP32_CAM_V1.6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/ESP32_CAM_V1.6.pdf -------------------------------------------------------------------------------- /doc/datasheets/OV5640 SOC Auto Focus Application Notes R1.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/OV5640 SOC Auto Focus Application Notes R1.0.pdf -------------------------------------------------------------------------------- /doc/datasheets/OV5640_Software_app_note_parallel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/OV5640_Software_app_note_parallel.pdf -------------------------------------------------------------------------------- /doc/datasheets/OV5640_datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/OV5640_datasheet.pdf -------------------------------------------------------------------------------- /doc/datasheets/RTL8812AU-CG.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/RTL8812AU-CG.pdf -------------------------------------------------------------------------------- /doc/datasheets/RTL8812AU.Schematics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/RTL8812AU.Schematics.pdf -------------------------------------------------------------------------------- /doc/datasheets/SKY85601.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/SKY85601.pdf -------------------------------------------------------------------------------- /doc/datasheets/SKY85703.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/SKY85703.pdf -------------------------------------------------------------------------------- /doc/datasheets/XIAO_ESP32S3_ExpBoard_v1.0_SCH.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/XIAO_ESP32S3_ExpBoard_v1.0_SCH.pdf -------------------------------------------------------------------------------- /doc/datasheets/XIAO_ESP32S3_SCH_v1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/datasheets/XIAO_ESP32S3_SCH_v1.1.pdf -------------------------------------------------------------------------------- /doc/development.md: -------------------------------------------------------------------------------- 1 | 2 | # Development 3 | 4 | Radxa Zero 3W or Raspberry Pi 4 is recommented for development. 5 | 6 | Building GS development image for Raspberry PI: [/doc/building_gs_image_rpi.md](/doc/building_gs_sd_rpi.md#building-ground-station-development-image-for-raspberry-pi) 7 | 8 | 9 | # Development UI 10 | 11 | Development UI is enabled with **d** key or **middle mouse click**. 12 | 13 | ![alt text](images/debug_menu.jpg "debugmenu") 14 | 15 | # Statistics 16 | 17 | Statistic can be enabled in development menu or in OSD menu. 18 | 19 | ![alt text](images/stats.jpg "stats.jpg") 20 | 21 | Graph | Description 22 | ------------------- | ------------- 23 | Frames | Big rectangle - frame received, small rectangle - frame is restored using FEC, emtpy space - frame is lost 24 | Parts | Number of frame blocks processed to decode the frame 25 | Period | Distance from previous decoded frame in ms 26 | Quality | Frame compression setting 27 | Datasize | Actual MJPEG stream bandwidth (without FEC encoding) 28 | Wifi load | Air unit wifi queue usage in % 29 | 30 | 31 | # Profiling 32 | 33 | ![alt text](images/vcd_profiling.png "vcd_profiling.png") 34 | 35 | Air unit code contains profiler which can write frame timing in VCD format to SD card. 36 | 37 | VCD file can than be viewed in tools like [Wavetrace](https://www.wavetrace.io/) (available as VSCode extension) or [VCDrom](https://vc.drom.io/). 38 | 39 | See corresponding [defines.](https://github.com/RomanLut/hx-esp32-cam-fpv/blob/master/components/common/vcd_profiler.h#L5) 40 | 41 | Profling is started from development UI with **[Profile]** buttons for 500ms or for 3 seconds. 42 | 43 | 44 | Data source | Description 45 | ------------------- | ------------- 46 | pf.cam_data | Activity of camera_data_available() callback 47 | pf.quality | The quaity setting of frame been captured. This data source Visually defines range of a frame on graph. 48 | pf.data_size | Size of frame JPEG data been received in Kb 49 | pf.fec_pool | Number of free blocks in FEC encoder pool 50 | pf.fec | Activity of FEC encoder thread 51 | pf.wifi_tx | Activity of wifi transmitter thread, including transmission completion waiting 52 | pf.wifi_queue | Size of wifi transmittion queue in Kb 53 | pf.fec_spin | FEC encoder thread is spinning because wifi tx thread is overloaded 54 | pf.wifi_ovf | Toggled every time Wifi tx thread overlows 55 | pf.wifi_spin | Wifi stack out of memory 56 | pf.fec_ovf | Toggled every time FEC input queue overflow 57 | pf.cam_ovf | Toggled every time camera interfacing error (frame start missing, VSYNC interrupt missing etc.) 58 | pf.sd_fast_buf | Size of SD card RAM queue in Kb 59 | pf.sd_slow_buf | Size of SD card PSRAM queue in % 60 | ps.sd_ovf | Toggled every time any SD card queue overflows 61 | 62 | 63 | # Considerations 64 | 65 | GS application is based on SDL2. Application uses OpenGL ES API. In environment without desktop, KMSDRM should provide hardware OpenGL ES acceleration. 66 | -------------------------------------------------------------------------------- /doc/flashing_esp32_cam.md: -------------------------------------------------------------------------------- 1 | # Flashing esp32cam 2 | 3 | **esp32-cam** with **esp32-cam-mb** adapter is recommended. 4 | 5 | Experienced users who connect **esp32cam** using USB-UART adapter should enter flashing mode by holding **Boot** button and pressing **Reset** button before starting flashing. 6 | 7 | ## Flashing using online tool 8 | 9 | * Download and uncompress prebuilt firmware files from https://github.com/RomanLut/hx-esp32-cam-fpv/releases 10 | * Navigate to https://esp.huhn.me/ 11 | * Connect esp32-cam-mb adapter to USB, click **[Connect]**, select USB UART of **esp32cam** 12 | * Add firmware files as shown on screenshot: 13 | 14 | ![alt text](images/espwebtool.png "espwebtool.png") 15 | 16 | * Make sure addresses are filled corectly 17 | * Click **[Program]** 18 | 19 | ## Flashing using Flash download tool 20 | 21 | * Download and uncompress prebuilt firmware files from https://github.com/RomanLut/hx-esp32-cam-fpv/releases 22 | * Download and uncommpress Flash Download tools https://www.espressif.com/en/support/download/other-tools 23 | * Start Flash Download Tools, select esp32: 24 | 25 | ![alt text](images/flash_download_tool_esp32.png "flash_download_tool_esp32.png") 26 | 27 | * Connect esp32-cam-mb adapter to USB 28 | * Add firmware files as shown on screenshot: 29 | 30 | ![alt text](images/flash_download_tool_files.png "flash_download_tool_files.png") 31 | 32 | * Make sure checkboxes are selected 33 | * Make sure addresses are filled corectly 34 | * Make sure files are selected in correct order 35 | * Click **[Start]** 36 | 37 | 38 | ## Building and Flashing using PlatformIO 39 | 40 | * Download and install PlatformIO https://platformio.org/ 41 | 42 | * Clone repository: ```git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv``` 43 | 44 | * Open project: **esp32-cam-fpv\air_firmware_esp32cam\esp32-cam-fpv-esp32cam.code-workspace** 45 | 46 | * Let **PlatformIO** to install all components 47 | 48 | * Connect **esp32cam** to USB 49 | 50 | * Click **[PlatformIO: Upload]** on bottom toolbar. 51 | 52 | # Over the Air update (OTA) 53 | 54 | When **esp32cam** is installed on UAV, it would require desoldering to update firmware. 55 | 56 | There is easie alternative way using **Over The Air update (OTA)**. 57 | 58 | Hold **REC** button while powering up to enter **OTA mode**. 59 | 60 | **OTA/Fileserver mode** is indicated by LED blinking with 2 Hz frequency. 61 | 62 | * Enter **OTA mode**. 63 | * Connect to **espvtx** access point. 64 | * Navigate to http://192.168.4.1/ota 65 | * Select **firmware.bin** file. 66 | * Click **Upload** 67 | 68 | 69 | -------------------------------------------------------------------------------- /doc/flashing_esp32s3sense.md: -------------------------------------------------------------------------------- 1 | # Flashing esp32s3sense 2 | 3 | ## Flashing using online tool 4 | 5 | * Download and uncompress prebuilt firmware files from https://github.com/RomanLut/hx-esp32-cam-fpv/releases 6 | * Navigate to [https://espressif.github.io/esptool-js/](https://espressif.github.io/esptool-js/) 7 | * Connect **esp32s3sense** to USB, click ```[Connect]```, select ```USB JTAG/serial debug unit``` of **esp32s3sense** 8 | * Add firmware files as shown on screenshot: 9 | 10 | ![alt text](images/espwebtool_s3sense.png "espwebtool_s3sense.png") 11 | 12 | * Make sure addresses are filled corectly 13 | * Click ```[Program]``` 14 | 15 | ## Flashing using Flash download tool 16 | 17 | * Download and uncompress prebuilt firmware files from https://github.com/RomanLut/hx-esp32-cam-fpv/releases 18 | * Download and uncompress **Flash Download tools** https://www.espressif.com/en/support/download/other-tools 19 | * Start **Flash Download Tools**, select ```ESP32-S3```: 20 | 21 | ![alt text](images/flash_download_tool_esp32s3.png "flash_download_tool_esp32s3.png") 22 | 23 | * Connect **esp32s3sense** to USB 24 | * Add firmware files as shown on screenshot: 25 | 26 | ![alt text](images/flash_download_tool_files_s3sense.png "flash_download_tool_files_s3sense.png") 27 | 28 | * Make sure checkboxes are selected 29 | * Make sure addresses are filled corectly 30 | * Make sure files are selected in correct order 31 | * Select correct COM port 32 | * Click ```[Start]``` 33 | 34 | 35 | ## Building and Flashing using PlatformIO 36 | 37 | * Download and install PlatformIO https://platformio.org/ 38 | 39 | * Clone repository: ```git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv``` 40 | 41 | * Open project: ```esp32-cam-fpv\air_firmware_esp32s3sense\esp32-cam-fpv-esp32s3sense.code-workspace``` (or other for ov5640) 42 | 43 | * Let **PlatformIO** to install all components 44 | 45 | * Connect **esp32s3sense** to USB 46 | 47 | * Click ```[PlatformIO: Upload]``` on bottom toolbar. 48 | 49 | 50 | # Solving constant reboot problem (unbricking) 51 | 52 | Sometimes after unsuccesfull flashing, **esp32s2sense** constantly reboots, and it is impossible to flash firmware because USB device disappears/appears in the system every two seconds. 53 | 54 | To resolve this problem: 55 | * Download and uncompress **Flash Download tools** https://www.espressif.com/en/support/download/other-tools 56 | * Start Flash Download Tools, select ```ESP32-S3``` 57 | * Connect **esp32s3sense** to USB while holding ```Boot```, release ```Boot``` button 58 | * Click ```[Erase]``` 59 | 60 | -------------------------------------------------------------------------------- /doc/images/2dbi_dipole.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/2dbi_dipole.jpg -------------------------------------------------------------------------------- /doc/images/comfast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/comfast.jpg -------------------------------------------------------------------------------- /doc/images/debug_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/debug_menu.jpg -------------------------------------------------------------------------------- /doc/images/dfminispirit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/dfminispirit.jpg -------------------------------------------------------------------------------- /doc/images/displayport_osd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/displayport_osd.jpg -------------------------------------------------------------------------------- /doc/images/esp32cam_led.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32cam_led.jpg -------------------------------------------------------------------------------- /doc/images/esp32cam_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32cam_pinout.png -------------------------------------------------------------------------------- /doc/images/esp32s3sense_j3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_j3.jpg -------------------------------------------------------------------------------- /doc/images/esp32s3sense_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_pinout.png -------------------------------------------------------------------------------- /doc/images/esp32s3sense_shell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_shell.jpg -------------------------------------------------------------------------------- /doc/images/esp32s3sense_shell1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_shell1.jpg -------------------------------------------------------------------------------- /doc/images/esp32s3sense_shell2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_shell2.jpg -------------------------------------------------------------------------------- /doc/images/esp32s3sense_shell3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_shell3.jpg -------------------------------------------------------------------------------- /doc/images/esp32s3sense_shell_plane.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/esp32s3sense_shell_plane.jpg -------------------------------------------------------------------------------- /doc/images/espwebtool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/espwebtool.png -------------------------------------------------------------------------------- /doc/images/espwebtool_s3sense.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/espwebtool_s3sense.png -------------------------------------------------------------------------------- /doc/images/fan_pwm_buck_pcb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/fan_pwm_buck_pcb.jpg -------------------------------------------------------------------------------- /doc/images/fan_pwm_buck_schematics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/fan_pwm_buck_schematics.png -------------------------------------------------------------------------------- /doc/images/fan_pwm_simple_pcb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/fan_pwm_simple_pcb.jpg -------------------------------------------------------------------------------- /doc/images/fan_pwm_simple_schematics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/fan_pwm_simple_schematics.png -------------------------------------------------------------------------------- /doc/images/flash_download_tool_esp32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/flash_download_tool_esp32.png -------------------------------------------------------------------------------- /doc/images/flash_download_tool_esp32s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/flash_download_tool_esp32s3.png -------------------------------------------------------------------------------- /doc/images/flash_download_tool_files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/flash_download_tool_files.png -------------------------------------------------------------------------------- /doc/images/flash_download_tool_files_s3sense.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/flash_download_tool_files_s3sense.png -------------------------------------------------------------------------------- /doc/images/gs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs.jpg -------------------------------------------------------------------------------- /doc/images/gs2_drawing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs2_drawing.jpg -------------------------------------------------------------------------------- /doc/images/gs2_glasses.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs2_glasses.jpg -------------------------------------------------------------------------------- /doc/images/gs2_overview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs2_overview.jpg -------------------------------------------------------------------------------- /doc/images/gs2_wifi_usb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs2_wifi_usb.jpg -------------------------------------------------------------------------------- /doc/images/gs_drawing1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_drawing1.jpg -------------------------------------------------------------------------------- /doc/images/gs_drawing2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_drawing2.jpg -------------------------------------------------------------------------------- /doc/images/gs_glasses.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_glasses.jpg -------------------------------------------------------------------------------- /doc/images/gs_internal_wifi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_internal_wifi.jpg -------------------------------------------------------------------------------- /doc/images/gs_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_pinout.png -------------------------------------------------------------------------------- /doc/images/gs_pinout_radxa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/gs_pinout_radxa.png -------------------------------------------------------------------------------- /doc/images/joystick_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/joystick_pinout.png -------------------------------------------------------------------------------- /doc/images/latency.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/latency.jpg -------------------------------------------------------------------------------- /doc/images/lens.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/lens.jpg -------------------------------------------------------------------------------- /doc/images/long_flex_cable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/long_flex_cable.jpg -------------------------------------------------------------------------------- /doc/images/mavlink2_rc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/mavlink2_rc.png -------------------------------------------------------------------------------- /doc/images/moxon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/moxon.jpg -------------------------------------------------------------------------------- /doc/images/osd_elements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/osd_elements.png -------------------------------------------------------------------------------- /doc/images/osd_menu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/osd_menu.jpg -------------------------------------------------------------------------------- /doc/images/ov5640.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/ov5640.jpg -------------------------------------------------------------------------------- /doc/images/ov5640_500w_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/ov5640_500w_pinout.png -------------------------------------------------------------------------------- /doc/images/ov5640_pinout1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/ov5640_pinout1.jpg -------------------------------------------------------------------------------- /doc/images/ov5640_pinout2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/ov5640_pinout2.png -------------------------------------------------------------------------------- /doc/images/pcb_antena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/pcb_antena.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs1.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs2.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs3.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs4.jpg -------------------------------------------------------------------------------- /doc/images/radxa3w_gs5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa3w_gs5.jpg -------------------------------------------------------------------------------- /doc/images/radxa_gs_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/radxa_gs_pinout.png -------------------------------------------------------------------------------- /doc/images/rpi2w_composite_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/rpi2w_composite_pinout.png -------------------------------------------------------------------------------- /doc/images/rpi4_composite_pinout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/rpi4_composite_pinout.png -------------------------------------------------------------------------------- /doc/images/rtl8812au.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/rtl8812au.jpg -------------------------------------------------------------------------------- /doc/images/shell_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/shell_14.jpg -------------------------------------------------------------------------------- /doc/images/shell_14_main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/shell_14_main.jpg -------------------------------------------------------------------------------- /doc/images/shell_14_tube.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/shell_14_tube.jpg -------------------------------------------------------------------------------- /doc/images/stats.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/stats.jpg -------------------------------------------------------------------------------- /doc/images/vcd_profiling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/vcd_profiling.png -------------------------------------------------------------------------------- /doc/images/xiaoesp32s3sense.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/doc/images/xiaoesp32s3sense.jpg -------------------------------------------------------------------------------- /doc/installing_fan_control_service.md: -------------------------------------------------------------------------------- 1 | # Installing Fan Control Service 2 | 3 | Boot, ssh, download script: 4 | 5 | * ```wget https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/refs/heads/release/scripts/fan_control.sh``` 6 | 7 | * ```chmod +x fan_control.sh``` 8 | 9 | ## Configure PWM channel: 10 | 11 | **Raspberry Pi**: Add ```dtoverlay=pwm-2chan,pin2=19,func2=2``` to the end of the file ```boot/config.txt``` 12 | 13 | **Radxa Zero 3W**: Enable **PWM14-M0** overlay in **rsetup**: **Overlays\Manager Overlays\Enable PWM14-M0** 14 | 15 | ## Adjust parameters 16 | Edit ```fan_control.sh```, adjust: 17 | - PWM frequency ```PWM_FREQUENCY=``` 18 | - minimum PWM duty ratio ```DUTY_MIN_PERCENT=``` - the minimum duty ratio at which fan still operates. 19 | - maximum PWM duty ratio ```DUTY_MAX_PERCENT``` - limit maximum fan speed. F.e when connecting 5V fan to 2S VBAT, set to 60%. 20 | 21 | ## Test: 22 | ```./fan_control.sh run``` 23 | 24 | ## Install service: 25 | 26 | ```./fan_control.sh install``` 27 | 28 | After installation, script path is ```/usr/local/bin/fan_control.sh```. 29 | 30 | To restart service after adjustments, use: ```sudo systemctl restart fan_control```. 31 | 32 | See also: [Connecting Fan](/doc/connecting_fan.md) 33 | 34 | -------------------------------------------------------------------------------- /doc/making_release_img_from_sd_radxa.md: -------------------------------------------------------------------------------- 1 | 2 | # Making image file from SD card for release (Radxa Zero 3W) 3 | - Create SD Card with Dualboot RubyFPV Image [/doc/adding_gs_software_to_ruby_sd_radxa3.md](/doc/adding_gs_software_to_ruby_sd_radxa3.md) on **8GB** SD Card 4 | 5 | - install fan control service [/doc/installing_fan_control_service.md ](/doc/installing_fan_control_service.md) 6 | 7 | - Boot **hx-esp32-cam-gs** software 8 | 9 | - Exit to shell 10 | 11 | - zero free space to make compressed image smaller: 12 | 13 | ```wget https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/release/scripts/zero_free_space.sh``` 14 | 15 | ```sudo chmod +x zero_free_space.sh``` 16 | 17 | ```./zero_free_space.sh``` 18 | 19 | - Check the mount point path of your USB drive by entering: 20 | 21 | ```lsblk``` 22 | 23 | - Insert **16+GB** Flash drive formatted to **NTFS**. Flash drive should have enough free space for **8GB** SD Card image. 24 | 25 | - Mount usb flash drive: 26 | 27 | ```sudo mkdir -p /mnt/usb1``` 28 | 29 | ```sudo mount /dev/sda1 /mnt/usb1``` 30 | 31 | _(note that it could be ```/dev/sdb1``` depending on USB port used)_ 32 | 33 | - force filesystem resize on first boot: 34 | 35 | ```sudo rm /etc/growroot-grown``` 36 | 37 | ```sudo rm /etc/resize2fs-done``` 38 | 39 | - remove boot count file to force system to resize filesystem and install drivers on the first boot: 40 | 41 | ```rm /home/radxa/ruby/config/boot_count.cfg``` 42 | 43 | - Create image from SD card to USB drive: 44 | 45 | ```sudo dd if=/dev/mmcblk1 of=/mnt/usb1/espvrx_dualboot_radxa3w.img bs=1M status=progress``` 46 | 47 | ```sudo umount /mnt/usb1``` 48 | 49 | Compress .img file on PC. 50 | -------------------------------------------------------------------------------- /doc/making_release_img_from_sd_rpi.md: -------------------------------------------------------------------------------- 1 | 2 | # Making image file from SD card for release 3 | - Build image on PRI4 https://github.com/RomanLut/hx-esp32-cam-fpv/blob/master/doc/building_gs_image.md on **16GB** or **32BG** SD Card 4 | 5 | - Insert SD card into PRI 2W and compile rtl8812au driver. 6 | 7 | - * start ```sudo raspi-config``` and change the following options: 8 | * **Advanced options -> GL Driver -> Fake KMS** 9 | * **Advanced options -> Compositor -> disable compositor** 10 | 11 | - Insert SD card into PRI4 or PRI2W. 12 | 13 | - Install modified pishrink.sh script and copy it to the ```/usr/local/bin``` folder by typing: 14 | 15 | ```wget https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/release/scripts/pishrink.sh``` 16 | 17 | ```sudo chmod +x pishrink.sh``` 18 | 19 | ```sudo mv pishrink.sh /usr/local/bin``` 20 | 21 | - Check the mount point path of your USB drive by entering: 22 | 23 | ```lsblk``` 24 | 25 | - Insert **64GB** Flash drive formatted to NTFS. We use 64GB flash drive, because it should have enought free space for 32GB SD Card image and a shrinked image. 26 | 27 | - Mount usbdrive: 28 | 29 | ```sudo mkdir -p /mnt/usb1``` 30 | 31 | ```sudo mount /dev/sda1 /mnt/usb1``` 32 | 33 | _(note that it could be ```/dev/sdb1``` depending on USB port used)_ 34 | 35 | - Create image from SD card to USB drive: 36 | 37 | ```sudo dd if=/dev/mmcblk0 of=/mnt/usb1/espvrx.img bs=1M status=progress``` 38 | 39 | ```sudo pishrink.sh -z -a /mnt/usb1/espvrx_rpi.img``` 40 | 41 | ```sudo umount /mnt/usb1``` 42 | 43 | # References 44 | 45 | How to Back Up Your Raspberry Pi as a Disk Image https://www.tomshardware.com/how-to/back-up-raspberry-pi-as-disk-image 46 | -------------------------------------------------------------------------------- /doc/ov5640.md: -------------------------------------------------------------------------------- 1 | 2 | # OV5640 compatibility issues 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /doc/prebuilt_gs_image.md: -------------------------------------------------------------------------------- 1 | 2 | # Preparing SD Card image for GS from prebuilt image 3 | 4 | * Download prebuilt image from release https://github.com/RomanLut/hx-esp32-cam-fpv/releases (choose correct image - for RPI or Radxa Zero 3W) 5 | 6 | * Write image to SD Card using **Raspberry Pi Imager** https://www.raspberrypi.com/software/ 7 | 8 | *Choose "Custom OS"...* 9 | 10 | * If dualboot image is unable to load correct drivers for wifi cards, boot into **RubyFPV** (by holding **REC GS** button on boot) and select **Factory Reset** in **RubyFPV** menu. 11 | 12 | * *Not for dualboot image*: Let it boot once into GS software or user prompt. Sometimes it can boot into user prompt on very first boot because wlan0 and wlan1 get allocated in incorrect order. If it happends - just reboot, it should correctly boot into GS software. 13 | 14 | 15 | -------------------------------------------------------------------------------- /doc/rpi_int_wifi_drivers/4.14.79+/readme.md: -------------------------------------------------------------------------------- 1 | Building image for Raspberry Pi Zero W with monitor mode support on internal wireless card(broadcom 43430) 2 | 3 | For Linux kernel 4.19.* only! 4 | 5 | Whole process will take ~1h. 6 | 7 | Installation 8 | - 9 | Download distribution of Raspbian Stretch with 4.14.79+ kernel: 10 | 11 | https://downloads.raspberrypi.org/raspbian/images/raspbian-2018-11-15/ 12 | 13 | Skip updtee step - we have to edit repository first. 14 | 15 | Update: 16 | 17 | Change your sources.list (https://forums.raspberrypi.com/viewtopic.php?t=356182) to http://legacy.raspbian.org/raspbian/: 18 | 19 | ```sudo nano /etc/apt/sources.list``` 20 | 21 | Edit, Ctrl+O, Enter, Ctrl+X. 22 | 23 | Update: 24 | 25 | ```sudo apt-get update``` 26 | ```sudo apt-get upgrade``` 27 | 28 | Check kernel version: 29 | 30 | ```uname -r``` 31 | 32 | It should be 4.19.66+. **It will not work for kernel versions other then 14.19! ** 33 | 34 | Install re4son kernel(https://re4son-kernel.com/re4son-pi-kernel/): 35 | 36 | ```wget -O re4son-kernel_current.tar.xz https://re4son-kernel.com/download/re4son-kernel-current/``` 37 | 38 | ```tar -xJf re4son-kernel_current.tar.xz``` 39 | 40 | ```cd re4son-kernel_4*``` 41 | 42 | ```sudo ./install.sh``` 43 | 44 | During install process, answer Yes to install kernel headers. 45 | 46 | Checking 47 | - 48 | ```sudo install airckrack-ng``` 49 | 50 | ```sudo install wireshark tcpdump``` 51 | 52 | ```sudo airmon-ng start wlan0``` 53 | 54 | (ignore error) 55 | 56 | ```iwconfig``` 57 | 58 | => ```wlan0mon``` should appear, started in monitor mode. 59 | 60 | ```sudo wireshark``` 61 | 62 | => use wireshark to capture packets on ```wlan0mon``` 63 | 64 | or ```tcpdump -i wlan0mon``` 65 | 66 | If no packets are received, uncomment other folder in script ad run again. 67 | 68 | Building for other kernel versions 69 | - 70 | 71 | The easiest way to get monitoring mode support is to install prebuilt re4son kerkel as describeda above. But it is also possible to build kernel yourself. 72 | 73 | Check supported cores versions in https://github.com/seemoo-lab/nexmon/tree/master/patches/driver 74 | 75 | For full building instructions check https://github.com/seemoo-lab/nexmon, this is what install.sh above is doing. 76 | -------------------------------------------------------------------------------- /doc/rpi_int_wifi_drivers/5.10.103-v7+/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt install raspberrypi-kernel-headers git libgmp3-dev gawk qpdf bison flex make autoconf libtool texinfo 3 | 4 | cd /home/pi/ 5 | git clone https://github.com/seemoo-lab/nexmon.git 6 | 7 | cd nexmon 8 | cd buildtools/isl-0.10 9 | ./configure 10 | make 11 | make install 12 | ln -s /usr/local/lib/libisl.so /usr/lib/arm-linux-gnueabihf/libisl.so.10 13 | 14 | cd /home/pi/ 15 | cd nexmon 16 | cd buildtools/mpfr-3.1.4 17 | autoreconf -f -i 18 | ./configure 19 | make 20 | make install 21 | ln -s /usr/local/lib/libmpfr.so /usr/lib/arm-linux-gnueabihf/libmpfr.so.4 22 | 23 | cd /home/pi/ 24 | cd nexmon 25 | source setup_env.sh 26 | make 27 | 28 | # driver 43430 1 29 | cd /home/pi/ 30 | cd nexmon 31 | #------------------------- Uncomment right version of the card here ---------------- 32 | #cd patches/bcm43430a1/7_45_41_26/nexmon/ 33 | cd patches/bcm43430a1/7_45_41_46/nexmon/ 34 | #cd patches/bcm43455c0/7_45_154/nexmon/ 35 | #cd patches/bcm43455c0/7_45_154/nexmon/ 36 | #cd patches/bcm43455c0/7_45_189/nexmon/ 37 | #cd patches/bcm43455c0/7_45_206/nexmon/ 38 | #cd patches/bcm43455c0/7_45_241/nexmon/ 39 | #cd patches/bcm43436b0/9_88_4_65/nexmon/ 40 | #cd patches/bcm43455c0/7_45_206/nexmon/ 41 | make 42 | make backup-firmware 43 | make install-firmware 44 | 45 | cd /home/pi/ 46 | cd nexmon 47 | cd utilities/nexutil/ 48 | make && make install 49 | 50 | sudo iw dev wlan0 set power_save off 51 | sudo cp /home/pi/nexmon/patches/driver/brcmfmac_5.10.y-nexmon/brcmfmac.ko /lib/modules/5.10.103-v7+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko 52 | sudo depmod -a 53 | 54 | 55 | -------------------------------------------------------------------------------- /doc/rpi_int_wifi_drivers/5.10.103-v7+/readme.md: -------------------------------------------------------------------------------- 1 | Building Buster 32bit image for Raspberry Pi Zero W / Zero 2W with monitor mode support on internal wireless card (broadcom 43430,43436,43455) 2 | 3 | For Linux kernel 5.10.103-v7+ only! 4 | 5 | Whole process will take ~2h. 6 | 7 | Installation 8 | - 9 | Download distribution of Rapberri Pi OS (Buster 32bit) with 5.10.17-v7+ kernel: 10 | 11 | https://downloads.raspberrypi.org/raspios_armhf/images/raspios_armhf-2021-05-28/ 12 | https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2021-05-28/ 13 | https://downloads.raspberrypi.org/raspios_full_armhf/images/raspios_full_armhf-2021-05-28/ 14 | 15 | Update to kernel 5.10.103-v7+: 16 | 17 | ```sudo apt-get update && apt-get upgrade``` 18 | 19 | Check kernel version: 20 | 21 | ```uname -r``` 22 | 23 | It should be 5.10.103-v7+. **It will not work for other kernel version.*** 24 | 25 | Check wifi card model: 26 | 27 | ```sudo apt-get install aircrack-ng``` 28 | 29 | ```sudo airmon-ng``` 30 | 31 | It should be ```43430``` or ```43436``` or ```43455```. 32 | 33 | Edit ```install.sh```, find section ```Uncomment right version of the card here``` and uncomment ```cd``` command for your card. 34 | 35 | This part a little bit misterios for me. It seems that there are multiple versions of firmware, and patches for the different firmwares overwrite the same binary file in the kernel. You have to build only correct one. 36 | ```bcm43430a1/7_45_41_46/``` worked for me. 37 | 38 | Current firmware version can be seen using: 39 | ```dmesg | grep brcmfmac``` 40 | You probably have to choose closest lower of higher version. 41 | 42 | 43 | ```./install.sh``` 44 | 45 | During installation, answer Yes to to install kernel headers. 46 | 47 | Check log if everything is went correctly. 48 | 49 | ```reboot```. 50 | 51 | 52 | modinfo -F filename brcmfmac 53 | xz /lib/modules/5.10.103-v7+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko 54 | 55 | Checking 56 | - 57 | ```sudo apt-ger install airckrack-ng``` 58 | 59 | ```sudo apt-get install wireshark tcpdump``` 60 | 61 | ```sudo airmon-ng start wlan0``` 62 | 63 | (ignore error) 64 | 65 | ```iwconfig``` 66 | 67 | => ```wlan0mon``` should appear, started in monitor mode. 68 | 69 | ```sudo wireshark``` 70 | 71 | => use wireshark to capture packets on ```wlan0mon``` 72 | 73 | or ```tcpdump -i wlan0mon``` 74 | 75 | If no packets are received, uncomment other folder in script and run again. 76 | 77 | Building for other kernel versions 78 | - 79 | 80 | Check supported cores versions in https://github.com/seemoo-lab/nexmon/tree/master/patches/driver 81 | 82 | For full building instructions check https://github.com/seemoo-lab/nexmon, this is what install.sh above is doing. 83 | -------------------------------------------------------------------------------- /doc/running_gs_on_fedora.md: -------------------------------------------------------------------------------- 1 | # Running Ground Station software on Fedora Workstation 2 | 3 | This instruction describes steps for running Ground Station on Fedora Workstation (f.e. on old x86_64 notebook). 4 | 5 | External Wifi card which supports monitor mode and injection is still required (rtl8812ua, ar9271). 6 | 7 | Internal wifi card may work or may not. Intel 6300 AGN card does not work for me; even though it works on Ubuntu. 8 | 9 | * Install required packages: 10 | 11 | ```sudo yum install SDL2-devel turbojpeg-devel freetype-devel libpcap-devel dkms aircrack-ng``` 12 | 13 | ```sudo dnf install "Development Tools" "C Development Tools and libraries" ``` 14 | 15 | * Install [rtl8812au driver](https://github.com/svpcom/rtl8812au/). 16 | 17 | * Download **esp32-cam-fpv** repository: 18 | 19 | ```cd ~``` 20 | 21 | ```git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv``` 22 | 23 | * Build ground station software: 24 | 25 | ```cd esp32-cam-fpv``` 26 | 27 | ```cd gs``` 28 | 29 | ```make -j4``` 30 | 31 | * Check name of Wifi card interface: 32 | 33 | ```sudo airmon-ng``` 34 | 35 | Note name of Wifi card **Interface**, f.e. **wlp3s0** 36 | 37 | * Launch Ground Station software: 38 | 39 | Kill NeworkManager: 40 | 41 | ```sudo airmon-ng check kill``` 42 | 43 | OR request NetworkManager to do not manage your adapter: 44 | 45 | ```nmcli dev set wlp3s0 managed no``` 46 | 47 | Switch interface to monitor mode: 48 | 49 | ```sudo airmon-ng start wlp3s0``` 50 | 51 | (on this step interface may be renamed to wlan0mon. If it does, use wlan0mon in the next steps) 52 | 53 | ```sudo ./gs -rx wlp3s0 -tx wlp3s0 -fullscreen 1``` 54 | 55 | * If it prints "Interface does not support monitor mode", try with ```-sm 1``` parameter: 56 | 57 | ```sudo ./gs -rx wlp3s0 -tx wlp3s0 -fullscreen 1 -sm 1``` 58 | 59 | Use ```./gs -help``` to see available command line parameters. 60 | -------------------------------------------------------------------------------- /doc/software_for_radxa.md: -------------------------------------------------------------------------------- 1 | # Preparing SD Card for Radxa Zero 3W 2 | 3 | Preparing SD Card for **Radxa Zero 3W GS** using pre-built image: [doc/prebuilt_gs_image.md](/doc/prebuilt_gs_image.md) 4 | 5 | Building dualboot **RubyFPV/hx-esp32-cam-fpv** image for **Radxa Zero 3W GS**: [/doc/adding_gs_software_to_ruby_sd_radxa3.md ](/doc/adding_gs_software_to_ruby_sd_radxa3.md ) 6 | 7 | 8 | Installing fan control service [/doc/installing_fan_control_service.md ](/doc/installing_fan_control_service.md ) 9 | -------------------------------------------------------------------------------- /doc/software_for_rpi.md: -------------------------------------------------------------------------------- 1 | # Preparing SD Card for Raspberry PI GS 2 | 3 | Preparing SD Card for **Raspberry PI GS** using pre-built image: [doc/prebuilt_gs_image.md](/doc/prebuilt_gs_image.md) 4 | 5 | Building **Raspberry PI GS** image : [/doc/building_gs_sd_rpi.md](/doc/building_gs_sd_rpi.md) 6 | 7 | Building dualboot **RubyFPV/hx-esp32-cam-fpv** image for **Raspberry PI GS**: [/doc/adding_gs_software_to_ruby_sd_rpi.md ](/doc/adding_gs_software_to_ruby_sd_rpi.md ) 8 | 9 | Installing fan control service [/doc/installing_fan_control_service.md ](/doc/installing_fan_control_service.md ) 10 | 11 | ***Note that RPI ground station is configured to output HDMI only by default, but can also output composite [/doc/composite_output.md](/doc/composite_output.md)*** 12 | 13 | ***Please use HDMI output next to USB C connector on RPI4.*** 14 | -------------------------------------------------------------------------------- /doc/vs_code_remote_development.md: -------------------------------------------------------------------------------- 1 | 2 | # Notes on Visual Studio Code Remote Development 3 | 4 | On **RubyFPV** based images, **VS Code** will fail installing **VS Code remote server** due to insufficiend space in /tmp folder, allocated in RAM. 5 | 6 | It can be solved executing the follwing command once, before connecting VS Code: 7 | 8 | - ```sudo mount -o remount,size=1G /tmp``` 9 | 10 | - Checking size of /tmp foder: 11 | 12 | - ```df -h /tmp``` 13 | 14 | 15 | Lastest working **VS Code** version for kernel **5.10** is **1.89.1**. If you want to use remote development, install this **VS Code** version manually and disable automatic agrades. 16 | 17 | In case if Git have problems, reassign all files in the folder to user pi (): 18 | 19 | ```sudo chown -R pi:pi esp32-cam-fpv``` 20 | -------------------------------------------------------------------------------- /gs/.gitignore: -------------------------------------------------------------------------------- 1 | gs 2 | imgui.ini 3 | ../.vscode/ 4 | -------------------------------------------------------------------------------- /gs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "chrono": "cpp", 4 | "array": "cpp", 5 | "iterator": "cpp", 6 | "string": "cpp", 7 | "string_view": "cpp", 8 | "vector": "cpp", 9 | "filesystem": "cpp", 10 | "__locale": "cpp", 11 | "ios": "cpp", 12 | "__bit_reference": "cpp", 13 | "__config": "cpp", 14 | "__debug": "cpp", 15 | "__errc": "cpp", 16 | "__functional_base": "cpp", 17 | "__hash_table": "cpp", 18 | "__mutex_base": "cpp", 19 | "__node_handle": "cpp", 20 | "__nullptr": "cpp", 21 | "__split_buffer": "cpp", 22 | "__string": "cpp", 23 | "__threading_support": "cpp", 24 | "__tuple": "cpp", 25 | "algorithm": "cpp", 26 | "atomic": "cpp", 27 | "bit": "cpp", 28 | "bitset": "cpp", 29 | "cctype": "cpp", 30 | "clocale": "cpp", 31 | "cmath": "cpp", 32 | "complex": "cpp", 33 | "cstdarg": "cpp", 34 | "cstddef": "cpp", 35 | "cstdint": "cpp", 36 | "cstdio": "cpp", 37 | "cstdlib": "cpp", 38 | "cstring": "cpp", 39 | "ctime": "cpp", 40 | "cwchar": "cpp", 41 | "cwctype": "cpp", 42 | "deque": "cpp", 43 | "exception": "cpp", 44 | "fstream": "cpp", 45 | "functional": "cpp", 46 | "future": "cpp", 47 | "initializer_list": "cpp", 48 | "iomanip": "cpp", 49 | "iosfwd": "cpp", 50 | "iostream": "cpp", 51 | "istream": "cpp", 52 | "limits": "cpp", 53 | "locale": "cpp", 54 | "memory": "cpp", 55 | "mutex": "cpp", 56 | "new": "cpp", 57 | "optional": "cpp", 58 | "ostream": "cpp", 59 | "ratio": "cpp", 60 | "sstream": "cpp", 61 | "stack": "cpp", 62 | "stdexcept": "cpp", 63 | "streambuf": "cpp", 64 | "system_error": "cpp", 65 | "thread": "cpp", 66 | "tuple": "cpp", 67 | "type_traits": "cpp", 68 | "typeinfo": "cpp", 69 | "unordered_map": "cpp", 70 | "utility": "cpp", 71 | "__tree": "cpp", 72 | "map": "cpp", 73 | "set": "cpp", 74 | "condition_variable": "cpp" 75 | } 76 | } -------------------------------------------------------------------------------- /gs/assets/osd_fonts/INAV_default_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/INAV_default_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_ARDU_BLI_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_ARDU_BLI_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_ARDU_CON_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_ARDU_CON_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_ARDU_SPH_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_ARDU_SPH_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_BFx1_Blinder_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_BFx1_Blinder_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_BFx1_Europa_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_BFx1_Europa_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_BFx1_Hemi_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_BFx1_Hemi_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_BFx1_Nexus_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_BFx1_Nexus_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_BFx1_Sphere_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_BFx1_Sphere_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_INAV_Europa_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_INAV_Europa_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Blinder_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Blinder_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Conthrax_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Conthrax_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Europa_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Europa_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Hemi_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Hemi_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Nexus_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Nexus_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/WS_IN_Sphere_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/WS_IN_Sphere_24.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/font_btfl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/font_btfl.png -------------------------------------------------------------------------------- /gs/assets/osd_fonts/user_ardu_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/gs/assets/osd_fonts/user_ardu_24.png -------------------------------------------------------------------------------- /gs/gs.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "name": "components", 8 | "path": "../components" 9 | } 10 | 11 | ], 12 | "settings": { 13 | "files.associations": { 14 | "chrono": "cpp", 15 | "array": "cpp", 16 | "iterator": "cpp", 17 | "string": "cpp", 18 | "string_view": "cpp", 19 | "vector": "cpp", 20 | "filesystem": "cpp", 21 | "__locale": "cpp", 22 | "ios": "cpp", 23 | "__bit_reference": "cpp", 24 | "__config": "cpp", 25 | "__debug": "cpp", 26 | "__errc": "cpp", 27 | "__functional_base": "cpp", 28 | "__hash_table": "cpp", 29 | "__mutex_base": "cpp", 30 | "__node_handle": "cpp", 31 | "__nullptr": "cpp", 32 | "__split_buffer": "cpp", 33 | "__string": "cpp", 34 | "__threading_support": "cpp", 35 | "__tuple": "cpp", 36 | "algorithm": "cpp", 37 | "atomic": "cpp", 38 | "bit": "cpp", 39 | "bitset": "cpp", 40 | "cctype": "cpp", 41 | "clocale": "cpp", 42 | "cmath": "cpp", 43 | "complex": "cpp", 44 | "cstdarg": "cpp", 45 | "cstddef": "cpp", 46 | "cstdint": "cpp", 47 | "cstdio": "cpp", 48 | "cstdlib": "cpp", 49 | "cstring": "cpp", 50 | "ctime": "cpp", 51 | "cwchar": "cpp", 52 | "cwctype": "cpp", 53 | "deque": "cpp", 54 | "exception": "cpp", 55 | "fstream": "cpp", 56 | "functional": "cpp", 57 | "future": "cpp", 58 | "initializer_list": "cpp", 59 | "iomanip": "cpp", 60 | "iosfwd": "cpp", 61 | "iostream": "cpp", 62 | "istream": "cpp", 63 | "limits": "cpp", 64 | "locale": "cpp", 65 | "memory": "cpp", 66 | "mutex": "cpp", 67 | "new": "cpp", 68 | "optional": "cpp", 69 | "ostream": "cpp", 70 | "ratio": "cpp", 71 | "sstream": "cpp", 72 | "stack": "cpp", 73 | "stdexcept": "cpp", 74 | "streambuf": "cpp", 75 | "system_error": "cpp", 76 | "thread": "cpp", 77 | "tuple": "cpp", 78 | "type_traits": "cpp", 79 | "typeinfo": "cpp", 80 | "unordered_map": "cpp", 81 | "utility": "cpp", 82 | "__tree": "cpp", 83 | "map": "cpp", 84 | "set": "cpp", 85 | "condition_variable": "cpp", 86 | "*.tcc": "cpp", 87 | "compare": "cpp", 88 | "concepts": "cpp", 89 | "memory_resource": "cpp", 90 | "numeric": "cpp", 91 | "random": "cpp", 92 | "numbers": "cpp", 93 | "semaphore": "cpp", 94 | "stop_token": "cpp", 95 | "cinttypes": "cpp", 96 | "codecvt": "cpp", 97 | "csignal": "cpp", 98 | "ranges": "cpp" 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /gs/launch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Variable to store detection result 4 | IS_RADXA=false 5 | 6 | # Path to the compatible file 7 | COMPATIBLE_FILE="/proc/device-tree/compatible" 8 | 9 | # Check if the compatible file exists 10 | if [ -f "$COMPATIBLE_FILE" ]; then 11 | # Read the content of the file 12 | COMPATIBLE_CONTENT=$(cat "$COMPATIBLE_FILE") 13 | 14 | # Check if the content contains "radxa,zero3" 15 | if echo "$COMPATIBLE_CONTENT" | grep -q "radxa,zero3w"; then 16 | IS_RADXA=true 17 | fi 18 | fi 19 | 20 | # Assign values to QABUTTON1, QABUTTON2, and HOME_DIRECTORY based on IS_RADXA 21 | if $IS_RADXA; then 22 | HOME_DIRECTORY="/home/radxa/" 23 | else 24 | HOME_DIRECTORY="/home/pi/" 25 | fi 26 | 27 | # Output the results 28 | echo "IS_RADXA=$IS_RADXA" 29 | 30 | # Function to check if X11 or any desktop environment is running 31 | is_desktop_running() { 32 | if pgrep -x "Xorg" > /dev/null || pgrep -x "lxsession" > /dev/null; then 33 | return 0 34 | else 35 | return 1 36 | fi 37 | } 38 | 39 | cd ~ 40 | cd ${HOME_DIRECTORY} 41 | 42 | cd esp32-cam-fpv 43 | cd gs 44 | sudo airmon-ng check kill 45 | 46 | if is_desktop_running; then 47 | sudo -E LD_LIBRARY_PATH=/usr/local/lib DISPLAY=:0 ./gs 48 | else 49 | sudo -E LD_LIBRARY_PATH=/usr/local/lib SDL_VIDEODRIVER=kmsdrm ./gs 50 | fi 51 | 52 | #let LAN card get ip address (required if dhcpcd service is disabled) 53 | sudo systemctl start dhcpcd & 54 | 55 | #reconnect wlan0 to access point 56 | sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf 57 | -------------------------------------------------------------------------------- /gs/src/Clock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef std::chrono::steady_clock Clock; 6 | -------------------------------------------------------------------------------- /gs/src/Comms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Clock.h" 9 | #include "packet_filter.h" 10 | 11 | #define MIN_TX_POWER 5 12 | #define DEFAULT_TX_POWER 45 13 | #define MAX_TX_POWER 63 14 | 15 | 16 | struct fec_t; 17 | 18 | //=================================================================================== 19 | //=================================================================================== 20 | class Comms 21 | { 22 | public: 23 | Comms(); 24 | ~Comms(); 25 | 26 | struct TX_Descriptor 27 | { 28 | std::string interface; 29 | uint32_t coding_k = 12; 30 | uint32_t coding_n = 20; 31 | size_t mtu = 1200; 32 | }; 33 | 34 | struct RX_Descriptor 35 | { 36 | std::vector interfaces; //this list may not contain TX interface 37 | Clock::duration max_latency = std::chrono::milliseconds(500); 38 | Clock::duration reset_duration = std::chrono::milliseconds(1000); 39 | uint32_t coding_k = 12; 40 | uint32_t coding_n = 20; 41 | size_t mtu = 1200; 42 | bool skip_mon_mode_cfg = true; 43 | }; 44 | 45 | bool init(RX_Descriptor const& rx_descriptor, TX_Descriptor const& tx_descriptor); 46 | 47 | void process(); 48 | 49 | void send(void const* data, size_t size, bool flush); 50 | //std::function on_data_received; 51 | bool receive(void* data, size_t& size, bool& restoredByFEC); 52 | 53 | void setChannel(int ch); 54 | void setTxPower(int txPower); //MIN_TX_POWER...MAX_TX_POWER 55 | void setMonitorMode(const std::vector interfaces); 56 | 57 | void setTxInterface(const std::string& interface); 58 | 59 | const RX_Descriptor& getRXDescriptor(); 60 | 61 | size_t get_data_rate() const; 62 | int get_input_dBm() const; 63 | 64 | //static std::vector enumerate_interfaces(); 65 | 66 | struct PCap; 67 | struct RX; 68 | struct TX; 69 | 70 | PacketFilter packetFilter; 71 | 72 | private: 73 | bool prepare_pcap(std::string const& interface, PCap& pcap, RX_Descriptor const& rx_descriptor); 74 | 75 | bool prepare_filter(PCap& pcap); 76 | void prepare_radiotap_header(size_t rate_hz); 77 | void prepare_tx_packet_header(uint8_t* buffer); 78 | bool process_rx_packet(PCap& pcap); 79 | void process_rx_packets(); 80 | 81 | void tx_thread_proc(); 82 | void rx_thread_proc(size_t index); 83 | 84 | TX_Descriptor m_tx_descriptor; 85 | RX_Descriptor m_rx_descriptor; 86 | 87 | struct Impl; 88 | std::unique_ptr m_impl; 89 | bool m_exit = false; 90 | 91 | size_t m_packet_header_offset = 0; 92 | size_t m_payload_offset = 0; 93 | 94 | std::atomic_int m_best_input_dBm = {0}; 95 | std::atomic_int m_latched_input_dBm = {0}; 96 | 97 | size_t m_data_stats_rate = 0; 98 | size_t m_data_stats_data_accumulated = 0; 99 | Clock::time_point m_data_stats_last_tp = Clock::now(); 100 | }; 101 | 102 | extern Comms s_comms; -------------------------------------------------------------------------------- /gs/src/IHAL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "imgui.h" 4 | #include 5 | 6 | class IHAL 7 | { 8 | public: 9 | virtual ~IHAL() = default; 10 | 11 | virtual bool init() = 0; 12 | virtual void shutdown() = 0; 13 | 14 | virtual void* get_window() = 0; 15 | virtual void* get_main_context() = 0; 16 | virtual void* lock_main_context() = 0; 17 | virtual void unlock_main_context() = 0; 18 | 19 | virtual ImVec2 get_display_size() const = 0; 20 | virtual void set_backlight(float brightness) = 0; //0..1 21 | virtual void set_video_channel(unsigned int id)=0; 22 | virtual void add_render_callback(std::function func)=0; 23 | virtual bool process() = 0; 24 | 25 | virtual void set_width( int w ) = 0; 26 | virtual void set_height( int h ) = 0; 27 | virtual void set_fullscreen( bool b ) = 0; 28 | virtual void set_vsync( bool b, bool apply ) = 0; 29 | }; 30 | -------------------------------------------------------------------------------- /gs/src/Log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "fmt/format.h" 5 | 6 | enum class LogLevel : uint8_t 7 | { 8 | DBG, //used to debug info. Disabled in Release 9 | INFO, //used to print usefull info both in Debug and Release 10 | WARNING, //used to print warnings that will not crash, both Debug and Release 11 | ERR //used for messages that will probably crash or seriously affect the game. Both Debug and Release 12 | }; 13 | 14 | template 15 | void logf(LogLevel level, char const* file, int line, Fmt const& fmt, Params&&... params) 16 | { 17 | const char* levelStr = ""; 18 | switch (level) 19 | { 20 | case LogLevel::DBG: levelStr = "D"; break; 21 | case LogLevel::INFO: levelStr = "I"; break; 22 | case LogLevel::WARNING: levelStr = "W"; break; 23 | case LogLevel::ERR: levelStr = "E"; break; 24 | } 25 | printf("(%s) %s: %d: %s\n", levelStr, file, line, fmt::format(fmt, std::forward(params)...).c_str()); 26 | } 27 | 28 | #define LOGD(fmt, ...) logf(LogLevel::DBG, __FILE__, __LINE__, fmt, ##__VA_ARGS__) 29 | #define LOGI(fmt, ...) logf(LogLevel::INFO, __FILE__, __LINE__, fmt, ##__VA_ARGS__) 30 | #define LOGW(fmt, ...) logf(LogLevel::WARNING, __FILE__, __LINE__, fmt, ##__VA_ARGS__) 31 | #define LOGE(fmt, ...) logf(LogLevel::ERR, __FILE__, __LINE__, fmt, ##__VA_ARGS__) -------------------------------------------------------------------------------- /gs/src/PI_HAL.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IHAL.h" 4 | #include 5 | #include 6 | #include 7 | 8 | class PI_HAL : virtual public IHAL 9 | { 10 | public: 11 | PI_HAL(); 12 | ~PI_HAL(); 13 | 14 | bool init() override; 15 | void shutdown() override; 16 | 17 | void* get_window() override; 18 | void* get_main_context() override; 19 | void* lock_main_context() override; 20 | void unlock_main_context() override; 21 | 22 | ImVec2 get_display_size() const override; 23 | void set_backlight(float brightness) override; //0..1 24 | void set_video_channel(unsigned int id); 25 | bool process() override; 26 | 27 | void add_render_callback(std::function func){ 28 | render_callbacks.push_back(func); 29 | } 30 | 31 | void set_width( int w ); 32 | void set_height( int h ); 33 | void set_fullscreen( bool b ); 34 | void set_vsync( bool b, bool apply ); 35 | 36 | private: 37 | struct Impl; 38 | std::unique_ptr m_impl; 39 | 40 | bool init_pigpio(); 41 | void shutdown_pigpio(); 42 | 43 | std::vector> render_callbacks; 44 | 45 | bool init_display_dispmanx(); 46 | bool init_display_sdl(); 47 | bool init_display(); 48 | 49 | void shutdown_display_dispmanx(); 50 | void shutdown_display_sdl(); 51 | void shutdown_display(); 52 | 53 | bool update_display(); 54 | 55 | bool init_ts(); 56 | void shutdown_ts(); 57 | void update_ts(); 58 | }; 59 | -------------------------------------------------------------------------------- /gs/src/Video_Decoder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "imgui.h" 5 | 6 | class IHAL; 7 | 8 | class Video_Decoder 9 | { 10 | public: 11 | Video_Decoder(); 12 | ~Video_Decoder(); 13 | 14 | bool decode_data(void const* data, size_t size); 15 | void inject_test_data(uint32_t value); 16 | 17 | bool init(IHAL& hal); 18 | 19 | size_t lock_output(); 20 | uint32_t get_video_texture_id() const; 21 | ImVec2 get_video_resolution() const; 22 | bool unlock_output(); 23 | 24 | bool isAspect16x9(); 25 | 26 | struct Impl; 27 | 28 | private: 29 | void decoder_thread_proc(size_t thread_index); 30 | 31 | IHAL* m_hal = nullptr; 32 | bool m_exit = false; 33 | ImVec2 m_resolution; 34 | uint32_t m_texture; 35 | uint32_t videoWidth; 36 | std::unique_ptr m_impl; 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /gs/src/cpu_temp.cpp: -------------------------------------------------------------------------------- 1 | #include "cpu_temp.h" 2 | #include 3 | #include 4 | 5 | //======================================================= 6 | //======================================================= 7 | CPUTemp::CPUTemp() 8 | { 9 | this->temperature = 0; 10 | this->last_update_tp = Clock::now(); 11 | } 12 | 13 | //======================================================= 14 | //======================================================= 15 | void CPUTemp::updateTemperature() 16 | { 17 | FILE *temperatureFile = fopen ("/sys/class/thermal/thermal_zone0/temp", "r"); 18 | if (!temperatureFile) return; 19 | float T; 20 | if ( fscanf (temperatureFile, "%f", &T) != 1 ) 21 | { 22 | fclose(temperatureFile); 23 | return; 24 | } 25 | this->temperature = T / 1000.0f; 26 | fclose (temperatureFile); 27 | 28 | //printf("CPU Temperature: %.2f°C\n", T); 29 | } 30 | 31 | //======================================================= 32 | //======================================================= 33 | void CPUTemp::process() 34 | { 35 | if (Clock::now() - this->last_update_tp >= std::chrono::milliseconds(3000)) 36 | { 37 | this->last_update_tp = Clock::now(); 38 | this->updateTemperature(); 39 | } 40 | } 41 | 42 | //======================================================= 43 | //======================================================= 44 | float CPUTemp::getTemperature() 45 | { 46 | return this->temperature; 47 | } 48 | 49 | 50 | CPUTemp g_CPUTemp; -------------------------------------------------------------------------------- /gs/src/cpu_temp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "main.h" 4 | #include "Clock.h" 5 | 6 | //======================================================= 7 | //======================================================= 8 | class CPUTemp 9 | { 10 | public: 11 | CPUTemp(); 12 | void process(); 13 | float getTemperature(); 14 | 15 | private: 16 | float temperature; 17 | void updateTemperature(); 18 | Clock::time_point last_update_tp; 19 | }; 20 | 21 | extern CPUTemp g_CPUTemp; 22 | -------------------------------------------------------------------------------- /gs/src/fmt/locale.h: -------------------------------------------------------------------------------- 1 | // Formatting library for C++ - std::locale support 2 | // 3 | // Copyright (c) 2012 - present, Victor Zverovich 4 | // All rights reserved. 5 | // 6 | // For the license information refer to format.h. 7 | 8 | #ifndef FMT_LOCALE_H_ 9 | #define FMT_LOCALE_H_ 10 | 11 | #include 12 | 13 | #include "format.h" 14 | 15 | FMT_BEGIN_NAMESPACE 16 | 17 | namespace detail { 18 | template 19 | std::basic_string vformat( 20 | const std::locale& loc, basic_string_view format_str, 21 | basic_format_args>> args) { 22 | basic_memory_buffer buffer; 23 | detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc)); 24 | return fmt::to_string(buffer); 25 | } 26 | } // namespace detail 27 | 28 | template > 29 | inline std::basic_string vformat( 30 | const std::locale& loc, const S& format_str, 31 | basic_format_args>> args) { 32 | return detail::vformat(loc, to_string_view(format_str), args); 33 | } 34 | 35 | template > 36 | inline std::basic_string format(const std::locale& loc, 37 | const S& format_str, Args&&... args) { 38 | return detail::vformat(loc, to_string_view(format_str), 39 | fmt::make_args_checked(format_str, args...)); 40 | } 41 | 42 | template , 44 | FMT_ENABLE_IF(detail::is_output_iterator::value)> 45 | inline OutputIt vformat_to( 46 | OutputIt out, const std::locale& loc, const S& format_str, 47 | basic_format_args>> args) { 48 | decltype(detail::get_buffer(out)) buf(detail::get_buffer_init(out)); 49 | vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc)); 50 | return detail::get_iterator(buf); 51 | } 52 | 53 | template >::value> 55 | inline auto format_to(OutputIt out, const std::locale& loc, const S& format_str, 56 | Args&&... args) -> 57 | typename std::enable_if::type { 58 | const auto& vargs = fmt::make_args_checked(format_str, args...); 59 | return vformat_to(out, loc, to_string_view(format_str), vargs); 60 | } 61 | 62 | FMT_END_NAMESPACE 63 | 64 | #endif // FMT_LOCALE_H_ 65 | -------------------------------------------------------------------------------- /gs/src/fmt/posix.h: -------------------------------------------------------------------------------- 1 | #include "os.h" 2 | #warning "fmt/posix.h is deprecated; use fmt/os.h instead" 3 | -------------------------------------------------------------------------------- /gs/src/fontwalksnail.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | //====================================================== 6 | //====================================================== 7 | class FontWalksnail 8 | { 9 | private: 10 | 11 | uint32_t fontTextureId = 0; 12 | 13 | 14 | unsigned int charWidth; 15 | unsigned int charHeight; 16 | 17 | unsigned int fontTextureWidth; 18 | unsigned int fontTextureHeight; 19 | 20 | void calculateTextureHeight(unsigned int imageWidth, unsigned int imageHeight); 21 | 22 | public: 23 | FontWalksnail(const char* fileName); 24 | ~FontWalksnail(); 25 | 26 | bool loaded; 27 | 28 | void drawChar(uint16_t code, int x1, int y1, int width, int height); 29 | 30 | void drawTest(); 31 | 32 | void destroy(); 33 | }; 34 | -------------------------------------------------------------------------------- /gs/src/gpio_buttons.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void gpio_buttons_start(); 4 | extern void gpio_buttons_stop(); 5 | -------------------------------------------------------------------------------- /gs/src/osd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "fontwalksnail.h" 6 | #include "packets.h" 7 | 8 | //====================================================== 9 | //====================================================== 10 | class OSD 11 | { 12 | private: 13 | FontWalksnail* font; 14 | OSDBuffer buffer; 15 | 16 | std::vector getFontsList(); 17 | 18 | public: 19 | char currentFontName[256]; 20 | std::vector fontsList; 21 | 22 | OSD(); 23 | void init(); 24 | void loadFont(const char* fontName); 25 | void draw(); 26 | void update(void* pScreen); 27 | bool isFontError(); 28 | }; 29 | 30 | extern OSD g_osd; 31 | 32 | 33 | -------------------------------------------------------------------------------- /gs/src/osd_menu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "main.h" 4 | #include "imgui.h" 5 | #include "packets.h" 6 | 7 | //======================================================= 8 | //======================================================= 9 | enum class OSDMenuId 10 | { 11 | Main, 12 | CameraSettings, 13 | Resolution, 14 | Brightness, 15 | Contrast, 16 | Exposure, 17 | Saturation, 18 | Sharpness, 19 | ExitToShell, 20 | Letterbox, 21 | WifiRate, 22 | WifiChannel, 23 | Restart, 24 | FEC, 25 | GSSettings, 26 | OSDFont, 27 | Search, 28 | GSTxPower, 29 | GSTxInterface, 30 | Image, 31 | CameraStopCH 32 | }; 33 | 34 | //======================================================= 35 | //======================================================= 36 | class OSDMenu 37 | { 38 | public: 39 | OSDMenu(); 40 | 41 | bool visible; 42 | 43 | void init(); 44 | void draw( Ground2Air_Config_Packet& config ); 45 | 46 | private: 47 | 48 | OSDMenuId menuId; 49 | int selectedItem; 50 | int itemsCount; 51 | int keyHandled; 52 | 53 | std::vector backMenuIds; 54 | std::vector backMenuItems; 55 | 56 | Clock::time_point search_tp = Clock::now(); 57 | bool searchDone; 58 | 59 | int bWidth; 60 | int sWidth; 61 | int bHeight; 62 | 63 | void drawMenuTitle( const char* caption ); 64 | bool drawMenuItem( const char* caption, int itemIndex, bool clip = false); 65 | void drawStatus( const char* caption ); 66 | 67 | bool exitKeyPressed(); 68 | 69 | void goForward(OSDMenuId newMenuId, int newItem); 70 | void goBack(); 71 | 72 | void drawMainMenu(Ground2Air_Config_Packet& config); 73 | void drawCameraSettingsMenu(Ground2Air_Config_Packet& config); 74 | void drawResolutionMenu(Ground2Air_Config_Packet& config); 75 | void drawBrightnessMenu(Ground2Air_Config_Packet& config); 76 | void drawContrastMenu(Ground2Air_Config_Packet& config); 77 | void drawExposureMenu(Ground2Air_Config_Packet& config); 78 | void drawSaturationMenu(Ground2Air_Config_Packet& config); 79 | void drawSharpnessMenu(Ground2Air_Config_Packet& config); 80 | void drawExitToShellMenu(Ground2Air_Config_Packet& config); 81 | void drawLetterboxMenu(Ground2Air_Config_Packet& config); 82 | void drawWifiRateMenu(Ground2Air_Config_Packet& config); 83 | void drawWifiChannelMenu(Ground2Air_Config_Packet& config); 84 | void drawRestartMenu(Ground2Air_Config_Packet& config); 85 | void drawFECMenu(Ground2Air_Config_Packet& config); 86 | void drawGSSettingsMenu(Ground2Air_Config_Packet& config); 87 | void drawOSDFontMenu(Ground2Air_Config_Packet& config); 88 | void drawSearchMenu(Ground2Air_Config_Packet& config); 89 | void drawGSTxPowerMenu(Ground2Air_Config_Packet& config); 90 | void drawGSTxInterfaceMenu(Ground2Air_Config_Packet& config); 91 | void searchNextWifiChannel(Ground2Air_Config_Packet& config); 92 | void drawImageSettingsMenu(Ground2Air_Config_Packet& config); 93 | void drawCameraStopCHMenu(Ground2Air_Config_Packet& config); 94 | }; 95 | 96 | extern OSDMenu g_osdMenu; 97 | -------------------------------------------------------------------------------- /gs/src/socket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stdint.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "Log.h" 15 | 16 | using namespace std; 17 | 18 | string string_format(const char *format, ...) 19 | { 20 | va_list args; 21 | va_start(args, format); 22 | size_t size = vsnprintf(nullptr, 0, format, args) + 1; // Extra space for '\0' 23 | va_end(args); 24 | unique_ptr buf(new char[size]); 25 | va_start(args, format); 26 | vsnprintf(buf.get(), size, format, args); 27 | va_end(args); 28 | return string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside 29 | } 30 | 31 | int udp_socket_init(const std::string &client_addr, int client_port) 32 | { 33 | struct sockaddr_in saddr; 34 | int fd = socket(AF_INET, SOCK_DGRAM, 0); 35 | if (fd < 0) throw std::runtime_error(string_format("Error opening socket: %s", strerror(errno))); 36 | 37 | bzero((char *) &saddr, sizeof(saddr)); 38 | saddr.sin_family = AF_INET; 39 | saddr.sin_addr.s_addr = inet_addr(client_addr.c_str()); 40 | saddr.sin_port = htons((unsigned short)client_port); 41 | 42 | if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) 43 | { 44 | throw std::runtime_error(string_format("Connect error: %s", strerror(errno))); 45 | } 46 | 47 | LOGI("UDP server start! fd:{}",fd); 48 | return fd; 49 | } 50 | 51 | void send_data_to_udp(int socketfd,uint8_t * buf, int len){ 52 | while(len>1024){ 53 | send(socketfd, buf, 1024, MSG_DONTWAIT); 54 | buf+=1024; 55 | len-=1024; 56 | } 57 | 58 | if(send(socketfd,buf,len,MSG_DONTWAIT)<0){ 59 | LOGE("error when sending!"); 60 | } 61 | 62 | } 63 | 64 | // int socket_init(){ 65 | // struct sockaddr_un saddr; 66 | // struct sockaddr_un saddr_remote; 67 | // int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); 68 | // if (fd < 0) throw std::runtime_error(string_format("Error opening socket: %s", strerror(errno))); 69 | 70 | // bzero((char *) &saddr, sizeof(saddr)); 71 | // saddr.sun_family = AF_UNIX; 72 | // strcpy(saddr.sun_path, "/home/ncer/testsocket"); 73 | 74 | // int len = strlen(saddr.sun_path) + sizeof(saddr.sun_family); 75 | // if( bind(fd, (struct sockaddr*)&saddr, len) != 0) 76 | // { 77 | // throw std::runtime_error(string_format("Connect error: %s", strerror(errno))); 78 | // } 79 | 80 | // if( listen(fd, 5) != 0 ) 81 | // { 82 | // throw std::runtime_error(string_format("Connect error: %s", strerror(errno))); 83 | // } 84 | 85 | 86 | // uint32_t temp=0; 87 | // int sockfd; 88 | // if( (sockfd = accept(fd, (struct sockaddr*)&saddr_remote, &temp)) != -1 ){ 89 | // printf("connected!\n"); 90 | // } 91 | // return sockfd; 92 | // } 93 | -------------------------------------------------------------------------------- /gs/src/socket.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | void send_data_to_udp(int socketfd,uint8_t * buf, int len); 6 | int udp_socket_init(const std::string &client_addr, int client_port); 7 | -------------------------------------------------------------------------------- /gs/src/stats.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #define STATS_SIZE 60 6 | 7 | class Stats 8 | { 9 | public: 10 | uint8_t data[STATS_SIZE]; 11 | int head = 0; 12 | uint32_t sum = 0; 13 | 14 | Stats() 15 | { 16 | memset( this->data, 0, STATS_SIZE ); 17 | } 18 | 19 | void add( uint8_t value ) 20 | { 21 | this->sum -= this->data[head]; 22 | this->sum += value; 23 | 24 | this->data[head++] = value; 25 | if ( head == STATS_SIZE ) head = 0; 26 | } 27 | 28 | void addMultiple( uint8_t value, int count ) 29 | { 30 | if ( count >= STATS_SIZE) count = STATS_SIZE; 31 | for ( int i = 0; i < count; i++ ) this->add(value); 32 | } 33 | 34 | int count() 35 | { 36 | return STATS_SIZE; 37 | } 38 | 39 | float average() 40 | { 41 | return this->sum / (float)STATS_SIZE; 42 | } 43 | 44 | uint8_t max() 45 | { 46 | uint8_t res = 0; 47 | for ( int i = 0; i < STATS_SIZE; i++ ) if ( this->data[i] > res) res = this->data[i]; 48 | return res; 49 | } 50 | 51 | static float getter(void* data, int idx) 52 | { 53 | const Stats* inst = (const Stats*)data; 54 | idx += inst->head; 55 | idx = idx % STATS_SIZE; 56 | return inst->data[idx]; 57 | } 58 | 59 | }; -------------------------------------------------------------------------------- /gs/src/utils/Pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | template struct Pool 13 | { 14 | std::function on_acquire; 15 | std::function on_release; 16 | 17 | typedef std::shared_ptr Ptr; 18 | Pool(); 19 | Ptr acquire(); 20 | 21 | private: 22 | std::function m_garbage_collector; 23 | std::mutex m_mutex; 24 | std::vector> m_items; 25 | 26 | int x_reused = 0; 27 | int x_new = 0; 28 | int x_returned = 0; 29 | }; 30 | 31 | 32 | template Pool::Pool() 33 | { 34 | m_garbage_collector = [this](T* t) 35 | { 36 | x_returned++; 37 | if (on_release) 38 | on_release(*t); 39 | 40 | std::lock_guard lg(m_mutex); 41 | m_items.emplace_back(static_cast(t)); //will create a unique pointer from the raw one 42 | // printf("%d// new:%d reused:%d returned:%d\n", this, x_new, x_reused, x_returned); 43 | }; 44 | } 45 | 46 | template auto Pool::acquire() -> Ptr 47 | { 48 | //this will be called when the last shared_ptr to T dies. We can safetly return the object to pur pool 49 | 50 | std::lock_guard lg(m_mutex); 51 | T* item = nullptr; 52 | if (!m_items.empty()) 53 | { 54 | x_reused++; 55 | item = m_items.back().release(); //release the raw ptr from the control of the unique ptr 56 | m_items.pop_back(); 57 | // printf("%d// new:%d reused:%d returned:%d\n", this, x_new, x_reused, x_returned); 58 | } 59 | else 60 | { 61 | x_new++; 62 | item = new T; 63 | // printf("%d// new:%d reused:%d returned:%d\n", this, x_new, x_reused, x_returned); 64 | } 65 | assert(item); 66 | 67 | if (on_acquire) 68 | on_acquire(static_cast(*item)); 69 | 70 | return Ptr(item, [this](T* item) { m_garbage_collector(item); }); 71 | } 72 | -------------------------------------------------------------------------------- /gs/src/utils/radiotap/radiotap.h: -------------------------------------------------------------------------------- 1 | #include "ieee80211_radiotap.h" 2 | 3 | /* Radiotap header iteration 4 | * implemented in net/wireless/radiotap.c 5 | * docs in Documentation/networking/radiotap-headers.txt 6 | */ 7 | /** 8 | * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args 9 | * @rtheader: pointer to the radiotap header we are walking through 10 | * @max_length: length of radiotap header in cpu byte ordering 11 | * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg 12 | * @this_arg: pointer to current radiotap arg 13 | * @arg_index: internal next argument index 14 | * @arg: internal next argument pointer 15 | * @next_bitmap: internal pointer to next present u32 16 | * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present 17 | */ 18 | 19 | struct ieee80211_radiotap_iterator { 20 | struct ieee80211_radiotap_header *rtheader; 21 | int max_length; 22 | int this_arg_index; 23 | uint8_t *this_arg; 24 | 25 | int arg_index; 26 | uint8_t *arg; 27 | __le32 *next_bitmap; 28 | uint32_t bitmap_shifter; 29 | }; 30 | 31 | extern int ieee80211_radiotap_iterator_init( 32 | struct ieee80211_radiotap_iterator *iterator, 33 | struct ieee80211_radiotap_header *radiotap_header, 34 | int max_length); 35 | 36 | extern int ieee80211_radiotap_iterator_next( 37 | struct ieee80211_radiotap_iterator *iterator); 38 | 39 | -------------------------------------------------------------------------------- /gs/src/utils/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static bool _isRadxaZeroChecked = false; 9 | static bool _isRadxaZero = false; 10 | 11 | //====================================================== 12 | //====================================================== 13 | bool isRadxaZero3() 14 | { 15 | if (_isRadxaZeroChecked) 16 | { 17 | return _isRadxaZero; 18 | } 19 | _isRadxaZeroChecked = true; 20 | 21 | std::ifstream compatibleFile("/proc/device-tree/compatible"); 22 | 23 | // Check /proc/device-tree/compatible for Radxa Zero 3W 24 | if (compatibleFile.is_open()) 25 | { 26 | std::ostringstream content; 27 | content << compatibleFile.rdbuf(); 28 | if (content.str().find("radxa,zero3w") != std::string::npos) 29 | { 30 | compatibleFile.close(); 31 | _isRadxaZero = true; 32 | return true; 33 | } 34 | compatibleFile.close(); 35 | } 36 | 37 | _isRadxaZero = false; 38 | return false; 39 | } -------------------------------------------------------------------------------- /gs/src/utils/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | extern bool isRadxaZero3(); 5 | -------------------------------------------------------------------------------- /scripts/boot_selection.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Variable to store detection result 4 | IS_RADXA=false 5 | 6 | # Path to the compatible file 7 | COMPATIBLE_FILE="/proc/device-tree/compatible" 8 | 9 | # Check if the compatible file exists 10 | if [ -f "$COMPATIBLE_FILE" ]; then 11 | # Read the content of the file 12 | COMPATIBLE_CONTENT=$(cat "$COMPATIBLE_FILE") 13 | 14 | # Check if the content contains "radxa,zero3" 15 | if echo "$COMPATIBLE_CONTENT" | grep -q "radxa,zero3w"; then 16 | IS_RADXA=true 17 | fi 18 | fi 19 | 20 | # Assign values to QABUTTON1, QABUTTON2, and HOME_DIRECTORY based on IS_RADXA 21 | if [ "$IS_RADXA" = true ]; then 22 | QABUTTON1=114 23 | QABUTTON2=102 24 | HOME_DIRECTORY="/home/radxa" 25 | 26 | # Automatically run resize2fs once if not already done 27 | if [ ! -f /etc/resize2fs-done ]; then 28 | echo "Resizing root filesystem..." 29 | ROOT_DEV=$(findmnt -n -o SOURCE /) 30 | resize2fs "$ROOT_DEV" && touch /etc/resize2fs-done 31 | fi 32 | 33 | else 34 | QABUTTON1=17 35 | QABUTTON2=4 36 | HOME_DIRECTORY="/home/pi" 37 | sudo raspi-gpio set 17 ip pd 38 | sudo raspi-gpio set 4 ip pd 39 | fi 40 | 41 | # Output the results 42 | echo "IS_RADXA=$IS_RADXA" 43 | echo "QABUTTON1=$QABUTTON1" 44 | echo "QABUTTON2=$QABUTTON2" 45 | 46 | 47 | #Launch Ruby on first boot to install drivers 48 | # Define the path to the file 49 | FILE="$HOME_DIRECTORY/ruby/config/boot_count.cfg" 50 | 51 | # Check if the file does not exist 52 | if [ ! -f "$FILE" ]; then 53 | echo "First boot" 54 | echo "Launching Ruby..." 55 | cd ${HOME_DIRECTORY}/ruby 56 | ./ruby_start 57 | exit 58 | fi 59 | 60 | 61 | # Export GPIOs as input 62 | sudo sh -c "echo $QABUTTON1 > /sys/class/gpio/export" 63 | sudo sh -c "echo in > /sys/class/gpio/gpio$QABUTTON1/direction" 64 | sudo sh -c "echo $QABUTTON2 > /sys/class/gpio/export" 65 | sudo sh -c "echo in > /sys/class/gpio/gpio$QABUTTON2/direction" 66 | 67 | # Check GPIO values and write to bootSelection.txt 68 | if [ $(sudo cat /sys/class/gpio/gpio$QABUTTON1/value) -eq 1 ]; then 69 | echo "esp32camfpv" | sudo tee bootSelection.txt > /dev/null 70 | fi 71 | 72 | if [ $(sudo cat /sys/class/gpio/gpio$QABUTTON2/value) -eq 1 ]; then 73 | echo "ruby" | sudo tee bootSelection.txt > /dev/null 74 | fi 75 | 76 | # Restore GPIOs 77 | sudo sh -c "echo $QABUTTON1 > /sys/class/gpio/unexport" 78 | sudo sh -c "echo $QABUTTON2 > /sys/class/gpio/unexport" 79 | 80 | # Check bootSelection.txt and execute appropriate script 81 | if [ -f "bootSelection.txt" ] && grep -q "ruby" bootSelection.txt; then 82 | echo "Launching Ruby..." 83 | cd ${HOME_DIRECTORY}/ruby 84 | ./ruby_start 85 | else 86 | echo "Launching esp32-cam-fpv..." 87 | cd ${HOME_DIRECTORY}/esp32-cam-fpv/gs 88 | ./launch.sh 89 | fi 90 | 91 | -------------------------------------------------------------------------------- /scripts/fan_control.sh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanLut/hx-esp32-cam-fpv/9324f7d0158b4ade05358c187a9c230cf9ec163e/scripts/fan_control.sh -------------------------------------------------------------------------------- /scripts/install_on_ruby.sh: -------------------------------------------------------------------------------- 1 | # Function to determine the number of make jobs based on free memory 2 | get_make_jobs() { 3 | local threshold="$1" 4 | local low_jobs="$2" 5 | local high_jobs="$3" 6 | 7 | FREE_MEMORY=$(free -m | awk '/^Mem:/{print $4}') 8 | if [ "$FREE_MEMORY" -lt "$threshold" ]; then 9 | echo "$low_jobs" 10 | else 11 | echo "$high_jobs" 12 | fi 13 | } 14 | 15 | sudo timedatectl set-ntp true 16 | 17 | IS_RADXA=false 18 | 19 | COMPATIBLE_FILE="/proc/device-tree/compatible" 20 | 21 | if [ -f "$COMPATIBLE_FILE" ]; then 22 | COMPATIBLE_CONTENT=$(cat "$COMPATIBLE_FILE") 23 | 24 | # Check if the content contains "radxa,zero3" 25 | if echo "$COMPATIBLE_CONTENT" | grep -q "radxa,zero3w"; then 26 | IS_RADXA=true 27 | fi 28 | fi 29 | 30 | if [ "$IS_RADXA" = true ]; then 31 | HOME_DIRECTORY="/home/radxa" 32 | else 33 | HOME_DIRECTORY="/home/pi" 34 | fi 35 | 36 | echo "HOME_DIRECTORY=$HOME_DIRECTORY" 37 | 38 | sudo apt update 39 | 40 | sudo apt install --no-install-recommends -y libdrm-dev libgbm-dev libgles2-mesa-dev libpcap-dev libturbojpeg0-dev libts-dev libfreetype6-dev build-essential autoconf automake libtool libasound2-dev libudev-dev libdbus-1-dev libxext-dev libsdl2-dev dkms git aircrack-ng 41 | 42 | if [ "$IS_RADXA" = true ]; then 43 | echo "Skipping SDL recompilation for Radxa." 44 | else 45 | cd "$HOME_DIRECTORY" 46 | wget https://www.libsdl.org/release/SDL2-2.0.18.tar.gz 47 | tar zxf SDL2-2.0.18.tar.gz 48 | rm SDL2-2.0.18.tar.gz 49 | 50 | cd SDL2-2.0.18 51 | ./autogen.sh 52 | ./configure --disable-video-rpi --enable-video-kmsdrm --enable-video-x11 --disable-video-opengl 53 | 54 | MAKE_JOBS=$(get_make_jobs 512 2 4) 55 | echo "MAKE_JOBS=$MAKE_JOBS" 56 | 57 | make -j"$MAKE_JOBS" 58 | sudo make install 59 | fi 60 | 61 | cd "$HOME_DIRECTORY" 62 | git clone -b release --recursive https://github.com/RomanLut/esp32-cam-fpv 63 | cd esp32-cam-fpv 64 | cd gs 65 | 66 | MAKE_JOBS=$(get_make_jobs 512 1 4) 67 | echo "MAKE_JOBS=$MAKE_JOBS" 68 | 69 | make -j"$MAKE_JOBS" 70 | 71 | PROFILE_FILE="/root/.profile" 72 | 73 | sudo sed -i \ 74 | -e 's|^\./ruby_start|#&|' \ 75 | -e 's|^echo "Launch done."|#&|' \ 76 | "$PROFILE_FILE" 77 | 78 | echo "$HOME_DIRECTORY/esp32-cam-fpv/scripts/boot_selection.sh" | sudo tee -a "$PROFILE_FILE" 79 | 80 | sudo reboot 81 | -------------------------------------------------------------------------------- /scripts/zero_free_space.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Filling empty space with zeroes..." 4 | sudo dd if=/dev/zero of=zerofill.tmp bs=1M status=progress || true 5 | sync 6 | sudo rm -f zerofill.tmp 7 | sync 8 | echo "Done." --------------------------------------------------------------------------------