From 302913f237746f490c1df0b962b1972a44c9d07a Mon Sep 17 00:00:00 2001 From: fbez Date: Tue, 19 Sep 2023 15:53:45 +0200 Subject: [PATCH 01/14] first commit --- .../esp-eye-qrcode/.devcontainer/Dockerfile | 48 + .../.devcontainer/devcontainer.json | 47 + quirc/examples/esp-eye-qrcode/CMakeLists.txt | 8 + quirc/examples/esp-eye-qrcode/README.md | 35 + .../esp32-camera/.github/workflows/build.yml | 57 + .../esp32-camera/.github/workflows/stale.yml | 27 + .../.github/workflows/upload_component.yml | 19 + .../components/esp32-camera/.gitignore | 6 + .../components/esp32-camera/CMakeLists.txt | 98 ++ .../components/esp32-camera/Kconfig | 213 ++++ .../components/esp32-camera/LICENSE | 202 +++ .../components/esp32-camera/README.md | 373 ++++++ .../components/esp32-camera/component.mk | 4 + .../esp32-camera/conversions/esp_jpg_decode.c | 134 ++ .../conversions/include/esp_jpg_decode.h | 43 + .../conversions/include/img_converters.h | 130 ++ .../esp32-camera/conversions/jpge.cpp | 728 +++++++++++ .../conversions/private_include/jpge.h | 142 +++ .../conversions/private_include/yuv.h | 29 + .../esp32-camera/conversions/to_bmp.c | 397 ++++++ .../esp32-camera/conversions/to_jpg.cpp | 235 ++++ .../components/esp32-camera/conversions/yuv.c | 298 +++++ .../components/esp32-camera/driver/cam_hal.c | 514 ++++++++ .../esp32-camera/driver/esp_camera.c | 486 +++++++ .../esp32-camera/driver/include/esp_camera.h | 251 ++++ .../esp32-camera/driver/include/sensor.h | 261 ++++ .../driver/private_include/cam_hal.h | 62 + .../driver/private_include/sccb.h | 22 + .../driver/private_include/xclk.h | 10 + .../components/esp32-camera/driver/sccb.c | 260 ++++ .../components/esp32-camera/driver/sensor.c | 57 + .../esp32-camera/examples/CMakeLists.txt | 9 + .../components/esp32-camera/examples/Makefile | 11 + .../esp32-camera/examples/main/CMakeLists.txt | 3 + .../esp32-camera/examples/main/component.mk | 5 + .../esp32-camera/examples/main/take_picture.c | 167 +++ .../esp32-camera/examples/sdkconfig.defaults | 17 + .../components/esp32-camera/idf_component.yml | 2 + .../components/esp32-camera/library.json | 26 + .../components/esp32-camera/sensors/bf20a6.c | 410 ++++++ .../components/esp32-camera/sensors/bf3005.c | 541 ++++++++ .../components/esp32-camera/sensors/gc0308.c | 468 +++++++ .../components/esp32-camera/sensors/gc032a.c | 391 ++++++ .../components/esp32-camera/sensors/gc2145.c | 477 +++++++ .../components/esp32-camera/sensors/nt99141.c | 1022 +++++++++++++++ .../components/esp32-camera/sensors/ov2640.c | 612 +++++++++ .../components/esp32-camera/sensors/ov3660.c | 1053 +++++++++++++++ .../components/esp32-camera/sensors/ov5640.c | 1130 +++++++++++++++++ .../components/esp32-camera/sensors/ov7670.c | 457 +++++++ .../components/esp32-camera/sensors/ov7725.c | 575 +++++++++ .../sensors/private_include/bf20a6.h | 27 + .../sensors/private_include/bf20a6_regs.h | 12 + .../sensors/private_include/bf20a6_settings.h | 158 +++ .../sensors/private_include/bf3005.h | 33 + .../sensors/private_include/bf3005_regs.h | 337 +++++ .../sensors/private_include/gc0308.h | 31 + .../sensors/private_include/gc0308_regs.h | 25 + .../sensors/private_include/gc0308_settings.h | 258 ++++ .../sensors/private_include/gc032a.h | 31 + .../sensors/private_include/gc032a_regs.h | 82 ++ .../sensors/private_include/gc032a_settings.h | 401 ++++++ .../sensors/private_include/gc2145.h | 27 + .../sensors/private_include/gc2145_regs.h | 85 ++ .../sensors/private_include/gc2145_settings.h | 719 +++++++++++ .../sensors/private_include/nt99141.h | 34 + .../sensors/private_include/nt99141_regs.h | 211 +++ .../private_include/nt99141_settings.h | 825 ++++++++++++ .../sensors/private_include/ov2640.h | 32 + .../sensors/private_include/ov2640_regs.h | 216 ++++ .../sensors/private_include/ov2640_settings.h | 485 +++++++ .../sensors/private_include/ov3660.h | 34 + .../sensors/private_include/ov3660_regs.h | 211 +++ .../sensors/private_include/ov3660_settings.h | 318 +++++ .../sensors/private_include/ov5640.h | 27 + .../sensors/private_include/ov5640_regs.h | 213 ++++ .../sensors/private_include/ov5640_settings.h | 335 +++++ .../sensors/private_include/ov7670.h | 33 + .../sensors/private_include/ov7670_regs.h | 354 ++++++ .../sensors/private_include/ov7725.h | 33 + .../sensors/private_include/ov7725_regs.h | 335 +++++ .../sensors/private_include/sc030iot.h | 31 + .../private_include/sc030iot_settings.h | 491 +++++++ .../sensors/private_include/sc031gs.h | 31 + .../private_include/sc031gs_settings.h | 202 +++ .../sensors/private_include/sc101iot.h | 31 + .../private_include/sc101iot_settings.h | 257 ++++ .../esp32-camera/sensors/sc030iot.c | 335 +++++ .../components/esp32-camera/sensors/sc031gs.c | 346 +++++ .../esp32-camera/sensors/sc101iot.c | 342 +++++ .../esp32-camera/target/esp32/ll_cam.c | 539 ++++++++ .../esp32-camera/target/esp32s2/ll_cam.c | 414 ++++++ .../target/esp32s2/private_include/tjpgd.h | 99 ++ .../esp32-camera/target/esp32s3/ll_cam.c | 538 ++++++++ .../esp32-camera/target/jpeg_include/tjpgd.h | 99 ++ .../target/private_include/ll_cam.h | 147 +++ .../components/esp32-camera/target/tjpgd.c | 970 ++++++++++++++ .../components/esp32-camera/target/xclk.c | 72 ++ .../esp32-camera/test/CMakeLists.txt | 4 + .../components/esp32-camera/test/component.mk | 8 + .../test/pictures/test_inside.jpeg | Bin 0 -> 18832 bytes .../test/pictures/test_outside.jpeg | Bin 0 -> 81744 bytes .../esp32-camera/test/pictures/testimg.jpeg | Bin 0 -> 5764 bytes .../esp32-camera/test/test_camera.c | 535 ++++++++ .../esp-eye-qrcode/main/CMakeLists.txt | 6 + quirc/examples/esp-eye-qrcode/main/app_main.c | 85 ++ .../esp-eye-qrcode/main/app_peripherals.c | 65 + .../esp-eye-qrcode/main/idf_component.yml | 10 + .../main/include/app_peripherals.h | 248 ++++ .../esp-eye-qrcode/sdkconfig.defaults | 6 + .../esp-eye-qrcode/sdkconfig.defaults.esp32 | 4 + .../esp-eye-qrcode/sdkconfig.defaults.esp32s2 | 8 + .../esp-eye-qrcode/sdkconfig.defaults.esp32s3 | 13 + 112 files changed, 24430 insertions(+) create mode 100644 quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile create mode 100644 quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json create mode 100644 quirc/examples/esp-eye-qrcode/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/README.md create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/testimg.jpeg create mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/test_camera.c create mode 100644 quirc/examples/esp-eye-qrcode/main/CMakeLists.txt create mode 100644 quirc/examples/esp-eye-qrcode/main/app_main.c create mode 100644 quirc/examples/esp-eye-qrcode/main/app_peripherals.c create mode 100644 quirc/examples/esp-eye-qrcode/main/idf_component.yml create mode 100644 quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h create mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults create mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 create mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 create mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 diff --git a/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile b/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile new file mode 100644 index 0000000000..f146d1d888 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile @@ -0,0 +1,48 @@ +FROM espressif/idf + +ARG DEBIAN_FRONTEND=nointeractive +ARG CONTAINER_USER=esp +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +RUN apt-get update \ + && apt install -y -q \ + cmake \ + git \ + hwdata \ + libglib2.0-0 \ + libnuma1 \ + libpixman-1-0 \ + linux-tools-virtual \ + && rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20 + +# QEMU +ENV QEMU_REL=esp-develop-20220919 +ENV QEMU_SHA256=f6565d3f0d1e463a63a7f81aec94cce62df662bd42fc7606de4b4418ed55f870 +ENV QEMU_DIST=qemu-${QEMU_REL}.tar.bz2 +ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/${QEMU_REL}/${QEMU_DIST} + +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +RUN wget --no-verbose ${QEMU_URL} \ + && echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \ + && tar -xf $QEMU_DIST -C /opt \ + && rm ${QEMU_DIST} + +ENV PATH=/opt/qemu/bin:${PATH} + +RUN groupadd --gid $USER_GID $CONTAINER_USER \ + && adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \ + && usermod -a -G dialout $CONTAINER_USER +USER ${CONTAINER_USER} +ENV USER=${CONTAINER_USER} +WORKDIR /home/${CONTAINER_USER} + +RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc + +ENTRYPOINT [ "/opt/esp/entrypoint.sh" ] + +CMD ["/bin/bash", "-c"] \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json b/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..e7b65465f0 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json @@ -0,0 +1,47 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.183.0/containers/ubuntu +{ + "name": "ESP-IDF QEMU", + "build": { + "dockerfile": "Dockerfile" + }, + // Add the IDs of extensions you want installed when the container is created + "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", + /* the path of workspace folder to be opened after container is running + */ + "workspaceFolder": "${localWorkspaceFolder}", + "mounts": [ + "source=extensionCache,target=/root/.vscode-server/extensions,type=volume" + ], + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "idf.espIdfPath": "/opt/esp/idf", + "idf.customExtraPaths": "", + "idf.pythonBinPath": "/opt/esp/python_env/idf5.1_py3.8_env/bin/python", + "idf.toolsPath": "/opt/esp", + "idf.gitPath": "/usr/bin/git" + }, + "extensions": [ + "ms-vscode.cpptools", + "espressif.esp-idf-extension" + ], + }, + "codespaces": { + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "idf.espIdfPath": "/opt/esp/idf", + "idf.customExtraPaths": "", + "idf.pythonBinPath": "/opt/esp/python_env/idf5.1_py3.8_env/bin/python", + "idf.toolsPath": "/opt/esp", + "idf.gitPath": "/usr/bin/git" + }, + "extensions": [ + "ms-vscode.cpptools", + "espressif.esp-idf-extension" + ], + } + }, + "runArgs": ["--privileged"] +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/CMakeLists.txt new file mode 100644 index 0000000000..efb143f8d3 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(app_main) diff --git a/quirc/examples/esp-eye-qrcode/README.md b/quirc/examples/esp-eye-qrcode/README.md new file mode 100644 index 0000000000..c53eca8f79 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/README.md @@ -0,0 +1,35 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | + +# _Sample project_ + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This is the simplest buildable example. The example is used by command `idf.py create-project` +that copies the project to user specified path and set it's name. For more information follow the [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project) + + + +## How to use example +We encourage the users to use the example as a template for the new projects. +A recommended way is to follow the instructions on a [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project). + +## Example folder contents + +The project **sample_project** contains one source file in C language [main.c](main/main.c). The file is located in folder [main](main). + +ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` +files that provide set of directives and instructions describing the project's source files and targets +(executable, library, or both). + +Below is short explanation of remaining files in the project folder. + +``` +├── CMakeLists.txt +├── main +│   ├── CMakeLists.txt +│   └── main.c +└── README.md This is the file you are currently reading +``` +Additionally, the sample project contains Makefile and component.mk files, used for the legacy Make based build system. +They are not used or needed when building with CMake and idf.py. diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml new file mode 100644 index 0000000000..bd35672a7d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml @@ -0,0 +1,57 @@ +name: Build examples +on: + push: + branches: + - master + pull_request: + +jobs: + build-examples: + name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} + runs-on: ubuntu-latest + strategy: + matrix: + idf_ver: ["release-v4.1", "release-v4.2", "release-v4.3"] + idf_target: ["esp32", "esp32s2"] + exclude: + - idf_ver: "release-v4.1" + idf_target: esp32s2 # ESP32S2 support started with version 4.2 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - uses: actions/checkout@v1 + with: + submodules: 'true' + - name: esp-idf build + env: + IDF_TARGET: ${{ matrix.idf_target }} + shell: bash + working-directory: examples + run: | + . ${IDF_PATH}/export.sh + idf.py build + build-examples-pedantic: + name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} + runs-on: ubuntu-latest + strategy: + matrix: + idf_ver: ["release-v4.4", "release-v5.0", "release-v5.1", "latest"] + idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3"] + exclude: + - idf_ver: "release-v4.4" + idf_target: esp32c2 # ESP32C2 support started with version 5.0 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - uses: actions/checkout@v1 + with: + submodules: 'true' + - name: esp-idf build + env: + IDF_TARGET: ${{ matrix.idf_target }} + shell: bash + working-directory: examples + run: | + . ${IDF_PATH}/export.sh + export PEDANTIC_FLAGS="-DIDF_CI_BUILD -Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" + export EXTRA_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" + export EXTRA_CXXFLAGS="${PEDANTIC_FLAGS}" + idf.py build diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml new file mode 100644 index 0000000000..a601f26337 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml @@ -0,0 +1,27 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '20 9 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue appears to be stale. Please close it if its no longer valid.' + stale-pr-message: 'This pull request appears to be stale. Please close it if its no longer valid.' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml new file mode 100644 index 0000000000..f550e696de --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml @@ -0,0 +1,19 @@ +name: Push component to https://components.espressif.com +on: + push: + tags: + - v* +jobs: + upload_components: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + with: + submodules: "recursive" + - name: Upload component to the component registry + uses: espressif/github-actions/upload_components@master + with: + name: "esp32-camera" + namespace: "espressif" + version: ${{ github.ref_name }} + api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore new file mode 100644 index 0000000000..f39d5fda1b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore @@ -0,0 +1,6 @@ +*.DS_Store +.vscode +**/build +**/sdkconfig +**/sdkconfig.old +**/dependencies.lock \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt new file mode 100644 index 0000000000..65e46aef60 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt @@ -0,0 +1,98 @@ +# get IDF version for comparison +set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") + +# set conversion sources +set(COMPONENT_SRCS + conversions/yuv.c + conversions/to_jpg.cpp + conversions/to_bmp.c + conversions/jpge.cpp + conversions/esp_jpg_decode.c + ) + +set(COMPONENT_PRIV_INCLUDEDIRS + conversions/private_include + ) + +set(COMPONENT_ADD_INCLUDEDIRS + driver/include + conversions/include + ) + +set(COMPONENT_REQUIRES driver) + +# set driver sources only for supported platforms +if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") + list(APPEND COMPONENT_SRCS + driver/esp_camera.c + driver/cam_hal.c + driver/sccb.c + driver/sensor.c + sensors/ov2640.c + sensors/ov3660.c + sensors/ov5640.c + sensors/ov7725.c + sensors/ov7670.c + sensors/nt99141.c + sensors/gc0308.c + sensors/gc2145.c + sensors/gc032a.c + sensors/bf3005.c + sensors/bf20a6.c + sensors/sc101iot.c + sensors/sc030iot.c + sensors/sc031gs.c + ) + + list(APPEND COMPONENT_PRIV_INCLUDEDIRS + driver/private_include + sensors/private_include + target/private_include + ) + + if(IDF_TARGET STREQUAL "esp32") + list(APPEND COMPONENT_SRCS + target/xclk.c + target/esp32/ll_cam.c + ) + endif() + + if(IDF_TARGET STREQUAL "esp32s2") + list(APPEND COMPONENT_SRCS + target/xclk.c + target/esp32s2/ll_cam.c + target/tjpgd.c + ) + + list(APPEND COMPONENT_PRIV_INCLUDEDIRS + target/esp32s2/private_include + ) + endif() + + if(IDF_TARGET STREQUAL "esp32s3") + list(APPEND COMPONENT_SRCS + target/esp32s3/ll_cam.c + ) + endif() + + set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) + + set(min_version_for_esp_timer "4.2") + if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer) + list(APPEND COMPONENT_PRIV_REQUIRES esp_timer) + endif() + +endif() + +# CONFIG_ESP_ROM_HAS_JPEG_DECODE is available from IDF v4.4 but +# previous IDF supported chips already support JPEG decoder, hence okay to use this +if(idf_version VERSION_GREATER_EQUAL "4.4" AND NOT CONFIG_ESP_ROM_HAS_JPEG_DECODE) + list(APPEND COMPONENT_SRCS + target/tjpgd.c + ) + list(APPEND COMPONENT_PRIV_INCLUDEDIRS + target/jpeg_include/ + ) +endif() + +register_component() diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig b/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig new file mode 100644 index 0000000000..2632c8235f --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig @@ -0,0 +1,213 @@ +menu "Camera configuration" + + config OV7670_SUPPORT + bool "Support OV7670 VGA" + default y + help + Enable this option if you want to use the OV7670. + Disable this option to save memory. + + config OV7725_SUPPORT + bool "Support OV7725 VGA" + default y + help + Enable this option if you want to use the OV7725. + Disable this option to save memory. + + config NT99141_SUPPORT + bool "Support NT99141 HD" + default y + help + Enable this option if you want to use the NT99141. + Disable this option to save memory. + + config OV2640_SUPPORT + bool "Support OV2640 2MP" + default y + help + Enable this option if you want to use the OV2640. + Disable this option to save memory. + + config OV3660_SUPPORT + bool "Support OV3660 3MP" + default y + help + Enable this option if you want to use the OV3360. + Disable this option to save memory. + + config OV5640_SUPPORT + bool "Support OV5640 5MP" + default y + help + Enable this option if you want to use the OV5640. + Disable this option to save memory. + + config GC2145_SUPPORT + bool "Support GC2145 2MP" + default y + help + Enable this option if you want to use the GC2145. + Disable this option to save memory. + + config GC032A_SUPPORT + bool "Support GC032A VGA" + default y + help + Enable this option if you want to use the GC032A. + Disable this option to save memory. + + config GC0308_SUPPORT + bool "Support GC0308 VGA" + default y + help + Enable this option if you want to use the GC0308. + Disable this option to save memory. + + config BF3005_SUPPORT + bool "Support BF3005(BYD3005) VGA" + default y + help + Enable this option if you want to use the BF3005. + Disable this option to save memory. + + config BF20A6_SUPPORT + bool "Support BF20A6(BYD20A6) VGA" + default y + help + Enable this option if you want to use the BF20A6. + Disable this option to save memory. + + config SC101IOT_SUPPORT + bool "Support SC101IOT HD" + default n + help + Enable this option if you want to use the SC101IOT. + Disable this option to save memory. + + choice SC101_REGS_SELECT + prompt "SC101iot default regs" + default SC101IOT_720P_15FPS_ENABLED + depends on SC101IOT_SUPPORT + help + Currently SC010iot has several register sets available. + Select the one that matches your needs. + + config SC101IOT_720P_15FPS_ENABLED + bool "xclk20M_720p_15fps" + help + Select this option means that when xclk is 20M, the frame rate is 15fps at 720p resolution. + config SC101IOT_VGA_25FPS_ENABLED + bool "xclk20M_VGA_25fps" + help + Select this option means that when xclk is 20M, the frame rate is 25fps at VGA resolution. + endchoice + + config SC030IOT_SUPPORT + bool "Support SC030IOT VGA" + default y + help + Enable this option if you want to use the SC030IOT. + Disable this option to save memory. + + config SC031GS_SUPPORT + bool "Support SC031GS VGA" + default n + help + SC031GS is a global shutter CMOS sensor with high frame rate and single-frame HDR. + Enable this option if you want to use the SC031GS. + Disable this option to save memory. + + choice SCCB_HARDWARE_I2C_PORT + bool "I2C peripheral to use for SCCB" + default SCCB_HARDWARE_I2C_PORT1 + + config SCCB_HARDWARE_I2C_PORT0 + bool "I2C0" + config SCCB_HARDWARE_I2C_PORT1 + bool "I2C1" + + endchoice + + config SCCB_CLK_FREQ + int "SCCB clk frequency" + default 100000 + range 100000 400000 + help + Increasing this value can reduce the initialization time of the sensor. + Please refer to the relevant instructions of the sensor to adjust the value. + + choice GC_SENSOR_WINDOW_MODE + bool "GalaxyCore Sensor Window Mode" + depends on (GC2145_SUPPORT || GC032A_SUPPORT || GC0308_SUPPORT) + default GC_SENSOR_SUBSAMPLE_MODE + help + This option determines how to reduce the output size when the resolution you set is less than the maximum resolution. + SUBSAMPLE_MODE has a bigger perspective and WINDOWING_MODE has a higher frame rate. + + config GC_SENSOR_WINDOWING_MODE + bool "Windowing Mode" + config GC_SENSOR_SUBSAMPLE_MODE + bool "Subsample Mode" + endchoice + + config CAMERA_TASK_STACK_SIZE + int "CAM task stack size" + default 2048 + help + Camera task stack size + + choice CAMERA_TASK_PINNED_TO_CORE + bool "Camera task pinned to core" + default CAMERA_CORE0 + help + Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. + + config CAMERA_CORE0 + bool "CORE0" + config CAMERA_CORE1 + bool "CORE1" + config CAMERA_NO_AFFINITY + bool "NO_AFFINITY" + + endchoice + + config CAMERA_DMA_BUFFER_SIZE_MAX + int "DMA buffer size" + range 8192 32768 + default 32768 + help + Maximum value of DMA buffer + Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent. + + config CAMERA_CONVERTER_ENABLED + bool "Enable camera RGB/YUV converter" + depends on IDF_TARGET_ESP32S3 + default n + help + Enable this option if you want to use RGB565/YUV422/YUV420/YUV411 format conversion. + + choice CAMERA_CONV_PROTOCOL + bool "Camera converter protocol" + depends on CAMERA_CONVERTER_ENABLED + default LCD_CAM_CONV_BT601_ENABLED + help + Supports format conversion under both BT601 and BT709 standards. + + config LCD_CAM_CONV_BT601_ENABLED + bool "BT601" + config LCD_CAM_CONV_BT709_ENABLED + bool "BT709" + endchoice + + config LCD_CAM_CONV_FULL_RANGE_ENABLED + bool "Camera converter full range mode" + depends on CAMERA_CONVERTER_ENABLED + default y + help + Supports format conversion under both full color range mode and limited color range mode. + If full color range mode is selected, the color range of RGB or YUV is 0~255. + If limited color range mode is selected, the color range of RGB is 16~240, and the color range of YUV is Y[16~240], UV[16~235]. + Full color range mode has a wider color range, so details in the image show more clearly. + Please confirm the color range mode of the current camera sensor, incorrect color range mode may cause color difference in the final converted image. + Full range mode is used by default. If this option is not selected, the format conversion function will be done using the limited range mode. +endmenu diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE b/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md b/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md new file mode 100644 index 0000000000..792f657565 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md @@ -0,0 +1,373 @@ +# ESP32 Camera Driver + +[![Build examples](https://github.com/espressif/esp32-camera/actions/workflows/build.yml/badge.svg)](https://github.com/espressif/esp32-camera/actions/workflows/build.yml) [![Component Registry](https://components.espressif.com/components/espressif/esp32-camera/badge.svg)](https://components.espressif.com/components/espressif/esp32-camera) +## General Information + +This repository hosts ESP32 series Soc compatible driver for image sensors. Additionally it provides a few tools, which allow converting the captured frame data to the more common BMP and JPEG formats. + +### Supported Soc + +- ESP32 +- ESP32-S2 +- ESP32-S3 + +### Supported Sensor + +| model | max resolution | color type | output format | Len Size | +| ------- | -------------- | ---------- | ------------------------------------------------------------ | -------- | +| OV2640 | 1600 x 1200 | color | YUV(422/420)/YCbCr422
RGB565/555
8-bit compressed data
8/10-bit Raw RGB data | 1/4" | +| OV3660 | 2048 x 1536 | color | raw RGB data
RGB565/555/444
CCIR656
YCbCr422
compression | 1/5" | +| OV5640 | 2592 x 1944 | color | RAW RGB
RGB565/555/444
CCIR656
YUV422/420
YCbCr422
compression | 1/4" | +| OV7670 | 640 x 480 | color | Raw Bayer RGB
Processed Bayer RGB
YUV/YCbCr422
GRB422
RGB565/555 | 1/6" | +| OV7725 | 640 x 480 | color | Raw RGB
GRB 422
RGB565/555/444
YCbCr 422 | 1/4" | +| NT99141 | 1280 x 720 | color | YCbCr 422
RGB565/555/444
Raw
CCIR656
JPEG compression | 1/4" | +| GC032A | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/10" | +| GC0308 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/6.5" | +| GC2145 | 1600 x 1200 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/5" | +| BF3005 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/4" | +| BF20A6 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
Only Y | 1/10" | +| SC101IOT| 1280 x 720 | color | YUV/YCbCr422
Raw RGB | 1/4.2" | +| SC030IOT| 640 x 480 | color | YUV/YCbCr422
RAW Bayer | 1/6.5" | +| SC031GS | 640 x 480 | monochrome | RAW MONO
Grayscale | 1/6" | + +## Important to Remember + +- Except when using CIF or lower resolution with JPEG, the driver requires PSRAM to be installed and activated. +- Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using `fmt2rgb888` or `fmt2bmp`/`frame2bmp`. +- When 1 frame buffer is used, the driver will wait for the current frame to finish (VSYNC) and start I2S DMA. After the frame is acquired, I2S will be stopped and the frame buffer returned to the application. This approach gives more control over the system, but results in longer time to get the frame. +- When 2 or more frame bufers are used, I2S is running in continuous mode and each frame is pushed to a queue that the application can access. This approach puts more strain on the CPU/Memory, but allows for double the frame rate. Please use only with JPEG. + +## Installation Instructions + + +### Using esp-idf + +- Clone or download and extract the repository to the components folder of your ESP-IDF project +- Enable PSRAM in `menuconfig` (also set Flash and PSRAM frequiencies to 80MHz) +- Include `esp_camera.h` in your code + +### Using PlatformIO + +The easy way -- on the `env` section of `platformio.ini`, add the following: + +```ini +[env] +lib_deps = + esp32-camera +``` + +Now the `esp_camera.h` is available to be included: + +```c +#include "esp_camera.h" +``` + +Enable PSRAM on `menuconfig` or type it direclty on `sdkconfig`. Check the [official doc](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support) for more info. + +``` +CONFIG_ESP32_SPIRAM_SUPPORT=y +``` + +***Arduino*** The easy-way (content above) only seems to work if you're using `framework=arduino` which seems to take a bunch of the guesswork out (thanks Arduino!) but also suck up a lot more memory and flash, almost crippling the performance. If you plan to use the `framework=espidf` then read the sections below carefully!! + +## Platform.io lib/submodule (for framework=espidf) + +It's probably easier to just skip the platform.io library registry version and link the git repo as a submodule. (i.e. using code outside the platform.io library management). In this example we will install this as a submodule inside the platform.io $project/lib folder: +``` +cd $project\lib +git submodule add -b master https://github.com/espressif/esp32-camera.git +``` + +Then in `platformio.ini` file +``` +build_flags = + -I../lib/esp32-camera +``` +After that `#include "esp_camera.h"` statement will be available. Now the module is included, and you're hopefully back to the same place as the easy-Arduino way. + +**Warning about platform.io/espidf and fresh (not initialized) git repos** +There is a sharp-edge on you'll discover in the platform.io build process (in espidf v3.3 & 4.0.1) where a project which has only had `git init` but nothing committed will crash platform.io build process with highly non-useful output. The cause is due to lack of a version (making you think you did something wrong, when you didn't at all) - the output is horribly non-descript. Solution: the devs want you to create a file called version.txt with a number in it, or simply commit any file to the projects git repo and use git. This happens because platform.io build process tries to be too clever and determine the build version number from the git repo - it's a sharp edge you'll only encounter if you're experimenting on a new project with no commits .. like wtf is my camera not working let's try a 'clean project'?! + +## Platform.io Kconfig +Kconfig is used by the platform.io menuconfig (accessed by running: `pio run -t menuconfig`) to interactively manage the various #ifdef statements throughout the espidf and supporting libraries (i.e. this repo: esp32-camera and arduino-esp32.git). The menuconfig process generates the `sdkconfig` file which is ultimately used behind the scenes by espidf compile+build process. + +**Make sure to append or symlink** [this `Kconfig`](./Kconfig) content into the `Kconfig` of your project. + +You symlink (or copy) the included Kconfig into your platform.io projects src directory. The file should be named `Kconfig.projbuild` in your projects src\ directory or you could also add the library path to a CMakefile.txt and hope the `Kconfig` (or `Kconfig.projbuild`) gets discovered by the menuconfig process, though this unpredictable for me. + +The unpredictable wonky behavior in platform.io build process around Kconfig naming (Kconfig vs. Kconfig.projbuild) occurs between espidf versions 3.3 and 4.0 - but if you don't see "Camera configuration" in your `pio run -t menuconfig` then there is no point trying to test camera code (it may compile, but it probably won't work!) and it seems the platform.io devs (when they built their wrapper around the espidf menuconfig) didn't implement it properly. You've probably already figured out you can't use the espidf build tools since the files are in totally different locations and also different versions with sometimes different syntax. This is one of those times you might consider changing the `platformio.ini` from `platform=espressif32` to `platform=https://github.com/platformio/platform-espressif32.git#develop` to get a more recent version of the espidf 4.0 tools. + +However with a bit of patience and experimenting you'll figure the Kconfig out. Once Kconfig (or Kconfig.projbuild) is working then you will be able to choose the configurations according to your setup or the camera libraries will be compiled. Although you might also need to delete your .pio/build directory before the options appear .. again, the `pio run -t menuconfig` doens't always notice the new Kconfig files! + +If you miss-skip-ignore this critical step the camera module will compile but camera logic inside the library will be 'empty' because the Kconfig sets the proper #ifdef statements during the build process to initialize the selected cameras. It's very not optional! + + +## Examples + +### Initialization + +```c +#include "esp_camera.h" + +//WROVER-KIT PIN Map +#define CAM_PIN_PWDN -1 //power down is not used +#define CAM_PIN_RESET -1 //software reset will be performed +#define CAM_PIN_XCLK 21 +#define CAM_PIN_SIOD 26 +#define CAM_PIN_SIOC 27 + +#define CAM_PIN_D7 35 +#define CAM_PIN_D6 34 +#define CAM_PIN_D5 39 +#define CAM_PIN_D4 36 +#define CAM_PIN_D3 19 +#define CAM_PIN_D2 18 +#define CAM_PIN_D1 5 +#define CAM_PIN_D0 4 +#define CAM_PIN_VSYNC 25 +#define CAM_PIN_HREF 23 +#define CAM_PIN_PCLK 22 + +static camera_config_t camera_config = { + .pin_pwdn = CAM_PIN_PWDN, + .pin_reset = CAM_PIN_RESET, + .pin_xclk = CAM_PIN_XCLK, + .pin_sccb_sda = CAM_PIN_SIOD, + .pin_sccb_scl = CAM_PIN_SIOC, + + .pin_d7 = CAM_PIN_D7, + .pin_d6 = CAM_PIN_D6, + .pin_d5 = CAM_PIN_D5, + .pin_d4 = CAM_PIN_D4, + .pin_d3 = CAM_PIN_D3, + .pin_d2 = CAM_PIN_D2, + .pin_d1 = CAM_PIN_D1, + .pin_d0 = CAM_PIN_D0, + .pin_vsync = CAM_PIN_VSYNC, + .pin_href = CAM_PIN_HREF, + .pin_pclk = CAM_PIN_PCLK, + + .xclk_freq_hz = 20000000,//EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + + .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG + .frame_size = FRAMESIZE_UXGA,//QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. + + .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality + .fb_count = 1, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. + .grab_mode = CAMERA_GRAB_WHEN_EMPTY//CAMERA_GRAB_LATEST. Sets when buffers should be filled +}; + +esp_err_t camera_init(){ + //power up the camera if PWDN pin is defined + if(CAM_PIN_PWDN != -1){ + pinMode(CAM_PIN_PWDN, OUTPUT); + digitalWrite(CAM_PIN_PWDN, LOW); + } + + //initialize the camera + esp_err_t err = esp_camera_init(&camera_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera Init Failed"); + return err; + } + + return ESP_OK; +} + +esp_err_t camera_capture(){ + //acquire a frame + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera Capture Failed"); + return ESP_FAIL; + } + //replace this with your own function + process_image(fb->width, fb->height, fb->format, fb->buf, fb->len); + + //return the frame buffer back to the driver for reuse + esp_camera_fb_return(fb); + return ESP_OK; +} +``` + +### JPEG HTTP Capture + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +typedef struct { + httpd_req_t *req; + size_t len; +} jpg_chunking_t; + +static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ + jpg_chunking_t *j = (jpg_chunking_t *)arg; + if(!index){ + j->len = 0; + } + if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){ + return 0; + } + j->len += len; + return len; +} + +esp_err_t jpg_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + size_t fb_len = 0; + int64_t fr_start = esp_timer_get_time(); + + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + res = httpd_resp_set_type(req, "image/jpeg"); + if(res == ESP_OK){ + res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); + } + + if(res == ESP_OK){ + if(fb->format == PIXFORMAT_JPEG){ + fb_len = fb->len; + res = httpd_resp_send(req, (const char *)fb->buf, fb->len); + } else { + jpg_chunking_t jchunk = {req, 0}; + res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL; + httpd_resp_send_chunk(req, NULL, 0); + fb_len = jchunk.len; + } + } + esp_camera_fb_return(fb); + int64_t fr_end = esp_timer_get_time(); + ESP_LOGI(TAG, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000)); + return res; +} +``` + +### JPEG HTTP Stream + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +#define PART_BOUNDARY "123456789000000000000987654321" +static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; + +esp_err_t jpg_stream_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + size_t _jpg_buf_len; + uint8_t * _jpg_buf; + char * part_buf[64]; + static int64_t last_frame = 0; + if(!last_frame) { + last_frame = esp_timer_get_time(); + } + + res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); + if(res != ESP_OK){ + return res; + } + + while(true){ + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + res = ESP_FAIL; + break; + } + if(fb->format != PIXFORMAT_JPEG){ + bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); + if(!jpeg_converted){ + ESP_LOGE(TAG, "JPEG compression failed"); + esp_camera_fb_return(fb); + res = ESP_FAIL; + } + } else { + _jpg_buf_len = fb->len; + _jpg_buf = fb->buf; + } + + if(res == ESP_OK){ + res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); + } + if(res == ESP_OK){ + size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); + + res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); + } + if(res == ESP_OK){ + res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); + } + if(fb->format != PIXFORMAT_JPEG){ + free(_jpg_buf); + } + esp_camera_fb_return(fb); + if(res != ESP_OK){ + break; + } + int64_t fr_end = esp_timer_get_time(); + int64_t frame_time = fr_end - last_frame; + last_frame = fr_end; + frame_time /= 1000; + ESP_LOGI(TAG, "MJPG: %uKB %ums (%.1ffps)", + (uint32_t)(_jpg_buf_len/1024), + (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time); + } + + last_frame = 0; + return res; +} +``` + +### BMP HTTP Capture + +```c +#include "esp_camera.h" +#include "esp_http_server.h" +#include "esp_timer.h" + +esp_err_t bmp_httpd_handler(httpd_req_t *req){ + camera_fb_t * fb = NULL; + esp_err_t res = ESP_OK; + int64_t fr_start = esp_timer_get_time(); + + fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Camera capture failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + + uint8_t * buf = NULL; + size_t buf_len = 0; + bool converted = frame2bmp(fb, &buf, &buf_len); + esp_camera_fb_return(fb); + if(!converted){ + ESP_LOGE(TAG, "BMP conversion failed"); + httpd_resp_send_500(req); + return ESP_FAIL; + } + + res = httpd_resp_set_type(req, "image/x-windows-bmp") + || httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.bmp") + || httpd_resp_send(req, (const char *)buf, buf_len); + free(buf); + int64_t fr_end = esp_timer_get_time(); + ESP_LOGI(TAG, "BMP: %uKB %ums", (uint32_t)(buf_len/1024), (uint32_t)((fr_end - fr_start)/1000)); + return res; +} +``` + + + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk new file mode 100644 index 0000000000..8db15eb883 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk @@ -0,0 +1,4 @@ +COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include +COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include +COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 +CXXFLAGS += -fno-rtti diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c new file mode 100644 index 0000000000..168325baf5 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c @@ -0,0 +1,134 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "esp_jpg_decode.h" + +#include "esp_system.h" +#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ +#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 +#include "esp32/rom/tjpgd.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/tjpgd.h" +#elif CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/rom/tjpgd.h" +#elif CONFIG_ESP_ROM_HAS_JPEG_DECODE // available since IDF 4.4 +#include "rom/tjpgd.h" // latest IDFs have `rom/` includes available +#else +#include "tjpgd.h" // using software decoder +#endif +#else // ESP32 Before IDF 4.0 +#include "rom/tjpgd.h" +#endif + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define TAG "" +#else +#include "esp_log.h" +static const char* TAG = "esp_jpg_decode"; +#endif + +typedef struct { + jpg_scale_t scale; + jpg_reader_cb reader; + jpg_writer_cb writer; + void * arg; + size_t len; + size_t index; +} esp_jpg_decoder_t; + +static const char * jd_errors[] = { + "Succeeded", + "Interrupted by output function", + "Device error or wrong termination of input stream", + "Insufficient memory pool for the image", + "Insufficient stream input buffer", + "Parameter error", + "Data format error", + "Right format but not supported", + "Not supported JPEG standard" +}; + +static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) +{ + uint16_t x = rect->left; + uint16_t y = rect->top; + uint16_t w = rect->right + 1 - x; + uint16_t h = rect->bottom + 1 - y; + uint8_t *data = (uint8_t *)bitmap; + + esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; + + if (jpeg->writer) { + return jpeg->writer(jpeg->arg, x, y, w, h, data); + } + return 0; +} + +static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len) +{ + esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; + if (jpeg->len && len > (jpeg->len - jpeg->index)) { + len = jpeg->len - jpeg->index; + } + if (len) { + len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); + if (!len) { + ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); + } + jpeg->index += len; + } + return len; +} + +esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) +{ + static uint8_t work[3100]; + JDEC decoder; + esp_jpg_decoder_t jpeg; + + jpeg.len = len; + jpeg.reader = reader; + jpeg.writer = writer; + jpeg.arg = arg; + jpeg.scale = scale; + jpeg.index = 0; + + JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); + if(jres != JDR_OK){ + ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); + return ESP_FAIL; + } + + uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); + uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); + + //output start + writer(arg, 0, 0, output_width, output_height, NULL); + //output write + jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); + //output end + writer(arg, output_width, output_height, output_width, output_height, NULL); + + if (jres != JDR_OK) { + ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); + return ESP_FAIL; + } + //check if all data has been consumed. + if (len && jpeg.index < len) { + _jpg_read(&decoder, NULL, len - jpeg.index); + } + + return ESP_OK; +} + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h new file mode 100644 index 0000000000..f13536edf4 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h @@ -0,0 +1,43 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP_JPG_DECODE_H_ +#define _ESP_JPG_DECODE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "esp_err.h" + +typedef enum { + JPG_SCALE_NONE, + JPG_SCALE_2X, + JPG_SCALE_4X, + JPG_SCALE_8X, + JPG_SCALE_MAX = JPG_SCALE_8X +} jpg_scale_t; + +typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); +typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); + +esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); + +#ifdef __cplusplus +} +#endif + +#endif /* _ESP_JPG_DECODE_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h new file mode 100644 index 0000000000..f736200a9b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h @@ -0,0 +1,130 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _IMG_CONVERTERS_H_ +#define _IMG_CONVERTERS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include "esp_camera.h" +#include "esp_jpg_decode.h" + +typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); + +/** + * @brief Convert image buffer to JPEG + * + * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format + * @param src_len Length in bytes of the source buffer + * @param width Width in pixels of the source image + * @param height Height in pixels of the source image + * @param format Format of the source image + * @param quality JPEG quality of the resulting image + * @param cp Callback to be called to write the bytes of the output JPEG + * @param arg Pointer to be passed to the callback + * + * @return true on success + */ +bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); + +/** + * @brief Convert camera frame buffer to JPEG + * + * @param fb Source camera frame buffer + * @param quality JPEG quality of the resulting image + * @param cp Callback to be called to write the bytes of the output JPEG + * @param arg Pointer to be passed to the callback + * + * @return true on success + */ +bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); + +/** + * @brief Convert image buffer to JPEG buffer + * + * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format + * @param src_len Length in bytes of the source buffer + * @param width Width in pixels of the source image + * @param height Height in pixels of the source image + * @param format Format of the source image + * @param quality JPEG quality of the resulting image + * @param out Pointer to be populated with the address of the resulting buffer. + * You MUST free the pointer once you are done with it. + * @param out_len Pointer to be populated with the length of the output buffer + * + * @return true on success + */ +bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); + +/** + * @brief Convert camera frame buffer to JPEG buffer + * + * @param fb Source camera frame buffer + * @param quality JPEG quality of the resulting image + * @param out Pointer to be populated with the address of the resulting buffer + * @param out_len Pointer to be populated with the length of the output buffer + * + * @return true on success + */ +bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); + +/** + * @brief Convert image buffer to BMP buffer + * + * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format + * @param src_len Length in bytes of the source buffer + * @param width Width in pixels of the source image + * @param height Height in pixels of the source image + * @param format Format of the source image + * @param out Pointer to be populated with the address of the resulting buffer + * @param out_len Pointer to be populated with the length of the output buffer + * + * @return true on success + */ +bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); + +/** + * @brief Convert camera frame buffer to BMP buffer + * + * @param fb Source camera frame buffer + * @param out Pointer to be populated with the address of the resulting buffer + * @param out_len Pointer to be populated with the length of the output buffer + * + * @return true on success + */ +bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); + +/** + * @brief Convert image buffer to RGB888 buffer (used for face detection) + * + * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format + * @param src_len Length in bytes of the source buffer + * @param format Format of the source image + * @param rgb_buf Pointer to the output buffer (width * height * 3) + * + * @return true on success + */ +bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); + +bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); + +#ifdef __cplusplus +} +#endif + +#endif /* _IMG_CONVERTERS_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp new file mode 100644 index 0000000000..dd6790e63b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp @@ -0,0 +1,728 @@ +// jpge.cpp - C++ class for JPEG compression. +// Public domain, Rich Geldreich +// v1.01, Dec. 18, 2010 - Initial release +// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.) +// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc. +// Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03). +// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug. +// Code tweaks to fix VS2008 static code analysis warnings (all looked harmless). +// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02. + +#include "jpge.h" + +#include +#include +#include +#include +#include +#include +#include +#include "esp_heap_caps.h" + +#define JPGE_MAX(a,b) (((a)>(b))?(a):(b)) +#define JPGE_MIN(a,b) (((a)<(b))?(a):(b)) + +namespace jpge { + + static inline void *jpge_malloc(size_t nSize) { + void * b = malloc(nSize); + if(b){ + return b; + } + // check if SPIRAM is enabled and allocate on SPIRAM if allocatable +#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) + return heap_caps_malloc(nSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +#else + return NULL; +#endif + } + static inline void jpge_free(void *p) { free(p); } + + // Various JPEG enums and tables. + enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 }; + enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 }; + + static const uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 }; + static const int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 }; + static const int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 }; + static const uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 }; + static const uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; + static const uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d }; + static const uint8 s_ac_lum_val[AC_LUM_CODES] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, + 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, + 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + }; + static const uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; + static const uint8 s_dc_chroma_val[DC_CHROMA_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; + static const uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 }; + static const uint8 s_ac_chroma_val[AC_CHROMA_CODES] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, + 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, + 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, + 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, + 0xf9,0xfa + }; + + const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329; + + static int32 m_last_quality = 0; + static int32 m_quantization_tables[2][64]; + + static bool m_huff_initialized = false; + static uint m_huff_codes[4][256]; + static uint8 m_huff_code_sizes[4][256]; + static uint8 m_huff_bits[4][17]; + static uint8 m_huff_val[4][256]; + + static inline uint8 clamp(int i) { + if (i < 0) { + i = 0; + } else if (i > 255){ + i = 255; + } + return static_cast(i); + } + + static void RGB_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels) { + for ( ; num_pixels; pDst += 3, pSrc += 3, num_pixels--) { + const int r = pSrc[0], g = pSrc[1], b = pSrc[2]; + pDst[0] = static_cast((r * YR + g * YG + b * YB + 32768) >> 16); + pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16)); + pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16)); + } + } + + static void RGB_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels) { + for ( ; num_pixels; pDst++, pSrc += 3, num_pixels--) { + pDst[0] = static_cast((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16); + } + } + + static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels) { + for( ; num_pixels; pDst += 3, pSrc++, num_pixels--) { + pDst[0] = pSrc[0]; + pDst[1] = 128; + pDst[2] = 128; + } + } + + // Forward DCT - DCT derived from jfdctint. + enum { CONST_BITS = 13, ROW_BITS = 2 }; +#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n)) +#define DCT_MUL(var, c) (static_cast(var) * static_cast(c)) +#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \ + int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \ + int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \ + int32 u1 = DCT_MUL(t12 + t13, 4433); \ + s2 = u1 + DCT_MUL(t13, 6270); \ + s6 = u1 + DCT_MUL(t12, -15137); \ + u1 = t4 + t7; \ + int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \ + int32 z5 = DCT_MUL(u3 + u4, 9633); \ + t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \ + t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \ + u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \ + u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \ + u3 += z5; u4 += z5; \ + s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3; + + static void DCT2D(int32 *p) { + int32 c, *q = p; + for (c = 7; c >= 0; c--, q += 8) { + int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7]; + DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); + q[0] = s0 << ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS); + q[4] = s4 << ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS); + } + for (q = p, c = 7; c >= 0; c--, q++) { + int32 s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8]; + DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); + q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3); + q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3); + } + } + + // Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays. + static void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val) + { + int i, l, last_p, si; + static uint8 huff_size[257]; + static uint huff_code[257]; + uint code; + + int p = 0; + for (l = 1; l <= 16; l++) { + for (i = 1; i <= bits[l]; i++) { + huff_size[p++] = (char)l; + } + } + + huff_size[p] = 0; + last_p = p; // write sentinel + + code = 0; si = huff_size[0]; p = 0; + + while (huff_size[p]) { + while (huff_size[p] == si) { + huff_code[p++] = code++; + } + code <<= 1; + si++; + } + + memset(codes, 0, sizeof(codes[0])*256); + memset(code_sizes, 0, sizeof(code_sizes[0])*256); + for (p = 0; p < last_p; p++) { + codes[val[p]] = huff_code[p]; + code_sizes[val[p]] = huff_size[p]; + } + } + + void jpeg_encoder::flush_output_buffer() + { + if (m_out_buf_left != JPGE_OUT_BUF_SIZE) { + m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left); + } + m_pOut_buf = m_out_buf; + m_out_buf_left = JPGE_OUT_BUF_SIZE; + } + + void jpeg_encoder::emit_byte(uint8 i) + { + *m_pOut_buf++ = i; + if (--m_out_buf_left == 0) { + flush_output_buffer(); + } + } + + void jpeg_encoder::put_bits(uint bits, uint len) + { + uint8 c = 0; + m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len))); + while (m_bits_in >= 8) { + c = (uint8)((m_bit_buffer >> 16) & 0xFF); + emit_byte(c); + if (c == 0xFF) { + emit_byte(0); + } + m_bit_buffer <<= 8; + m_bits_in -= 8; + } + } + + void jpeg_encoder::emit_word(uint i) + { + emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF)); + } + + // JPEG marker generation. + void jpeg_encoder::emit_marker(int marker) + { + emit_byte(uint8(0xFF)); emit_byte(uint8(marker)); + } + + // Emit JFIF marker + void jpeg_encoder::emit_jfif_app0() + { + emit_marker(M_APP0); + emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); + emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */ + emit_byte(0); + emit_byte(1); /* Major version */ + emit_byte(1); /* Minor version */ + emit_byte(0); /* Density unit */ + emit_word(1); + emit_word(1); + emit_byte(0); /* No thumbnail image */ + emit_byte(0); + } + + // Emit quantization tables + void jpeg_encoder::emit_dqt() + { + for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++) + { + emit_marker(M_DQT); + emit_word(64 + 1 + 2); + emit_byte(static_cast(i)); + for (int j = 0; j < 64; j++) + emit_byte(static_cast(m_quantization_tables[i][j])); + } + } + + // Emit start of frame marker + void jpeg_encoder::emit_sof() + { + emit_marker(M_SOF0); /* baseline */ + emit_word(3 * m_num_components + 2 + 5 + 1); + emit_byte(8); /* precision */ + emit_word(m_image_y); + emit_word(m_image_x); + emit_byte(m_num_components); + for (int i = 0; i < m_num_components; i++) + { + emit_byte(static_cast(i + 1)); /* component ID */ + emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]); /* h and v sampling */ + emit_byte(i > 0); /* quant. table num */ + } + } + + // Emit Huffman table. + void jpeg_encoder::emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag) + { + emit_marker(M_DHT); + + int length = 0; + for (int i = 1; i <= 16; i++) + length += bits[i]; + + emit_word(length + 2 + 1 + 16); + emit_byte(static_cast(index + (ac_flag << 4))); + + for (int i = 1; i <= 16; i++) + emit_byte(bits[i]); + + for (int i = 0; i < length; i++) + emit_byte(val[i]); + } + + // Emit all Huffman tables. + void jpeg_encoder::emit_dhts() + { + emit_dht(m_huff_bits[0+0], m_huff_val[0+0], 0, false); + emit_dht(m_huff_bits[2+0], m_huff_val[2+0], 0, true); + if (m_num_components == 3) { + emit_dht(m_huff_bits[0+1], m_huff_val[0+1], 1, false); + emit_dht(m_huff_bits[2+1], m_huff_val[2+1], 1, true); + } + } + + // emit start of scan + void jpeg_encoder::emit_sos() + { + emit_marker(M_SOS); + emit_word(2 * m_num_components + 2 + 1 + 3); + emit_byte(m_num_components); + for (int i = 0; i < m_num_components; i++) + { + emit_byte(static_cast(i + 1)); + if (i == 0) + emit_byte((0 << 4) + 0); + else + emit_byte((1 << 4) + 1); + } + emit_byte(0); /* spectral selection */ + emit_byte(63); + emit_byte(0); + } + + void jpeg_encoder::load_block_8_8_grey(int x) + { + uint8 *pSrc; + sample_array_t *pDst = m_sample_array; + x <<= 3; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc = m_mcu_lines[i] + x; + pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128; + pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128; + } + } + + void jpeg_encoder::load_block_8_8(int x, int y, int c) + { + uint8 *pSrc; + sample_array_t *pDst = m_sample_array; + x = (x * (8 * 3)) + c; + y <<= 3; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc = m_mcu_lines[y + i] + x; + pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128; + pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128; + } + } + + void jpeg_encoder::load_block_16_8(int x, int c) + { + uint8 *pSrc1, *pSrc2; + sample_array_t *pDst = m_sample_array; + x = (x * (16 * 3)) + c; + int a = 0, b = 2; + for (int i = 0; i < 16; i += 2, pDst += 8) + { + pSrc1 = m_mcu_lines[i + 0] + x; + pSrc2 = m_mcu_lines[i + 1] + x; + pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3] + pSrc2[ 0 * 3] + pSrc2[ 1 * 3] + a) >> 2) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3] + pSrc2[ 2 * 3] + pSrc2[ 3 * 3] + b) >> 2) - 128; + pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3] + pSrc2[ 4 * 3] + pSrc2[ 5 * 3] + a) >> 2) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3] + pSrc2[ 6 * 3] + pSrc2[ 7 * 3] + b) >> 2) - 128; + pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3] + pSrc2[ 8 * 3] + pSrc2[ 9 * 3] + a) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + b) >> 2) - 128; + pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + a) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + b) >> 2) - 128; + int temp = a; a = b; b = temp; + } + } + + void jpeg_encoder::load_block_16_8_8(int x, int c) + { + uint8 *pSrc1; + sample_array_t *pDst = m_sample_array; + x = (x * (16 * 3)) + c; + for (int i = 0; i < 8; i++, pDst += 8) + { + pSrc1 = m_mcu_lines[i + 0] + x; + pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3]) >> 1) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3]) >> 1) - 128; + pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3]) >> 1) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3]) >> 1) - 128; + pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3]) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3]) >> 1) - 128; + pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3]) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3]) >> 1) - 128; + } + } + + void jpeg_encoder::load_quantized_coefficients(int component_num) + { + int32 *q = m_quantization_tables[component_num > 0]; + int16 *pDst = m_coefficient_array; + for (int i = 0; i < 64; i++) + { + sample_array_t j = m_sample_array[s_zag[i]]; + if (j < 0) + { + if ((j = -j + (*q >> 1)) < *q) + *pDst++ = 0; + else + *pDst++ = static_cast(-(j / *q)); + } + else + { + if ((j = j + (*q >> 1)) < *q) + *pDst++ = 0; + else + *pDst++ = static_cast((j / *q)); + } + q++; + } + } + + void jpeg_encoder::code_coefficients_pass_two(int component_num) + { + int i, j, run_len, nbits, temp1, temp2; + int16 *pSrc = m_coefficient_array; + uint *codes[2]; + uint8 *code_sizes[2]; + + if (component_num == 0) + { + codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0]; + code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0]; + } + else + { + codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1]; + code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1]; + } + + temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num]; + m_last_dc_val[component_num] = pSrc[0]; + + if (temp1 < 0) + { + temp1 = -temp1; temp2--; + } + + nbits = 0; + while (temp1) + { + nbits++; temp1 >>= 1; + } + + put_bits(codes[0][nbits], code_sizes[0][nbits]); + if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits); + + for (run_len = 0, i = 1; i < 64; i++) + { + if ((temp1 = m_coefficient_array[i]) == 0) + run_len++; + else + { + while (run_len >= 16) + { + put_bits(codes[1][0xF0], code_sizes[1][0xF0]); + run_len -= 16; + } + if ((temp2 = temp1) < 0) + { + temp1 = -temp1; + temp2--; + } + nbits = 1; + while (temp1 >>= 1) + nbits++; + j = (run_len << 4) + nbits; + put_bits(codes[1][j], code_sizes[1][j]); + put_bits(temp2 & ((1 << nbits) - 1), nbits); + run_len = 0; + } + } + if (run_len) + put_bits(codes[1][0], code_sizes[1][0]); + } + + void jpeg_encoder::code_block(int component_num) + { + DCT2D(m_sample_array); + load_quantized_coefficients(component_num); + code_coefficients_pass_two(component_num); + } + + void jpeg_encoder::process_mcu_row() + { + if (m_num_components == 1) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8_grey(i); code_block(0); + } + } + else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2); + } + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); + load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2); + } + } + else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2)) + { + for (int i = 0; i < m_mcus_per_row; i++) + { + load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); + load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0); + load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2); + } + } + } + + void jpeg_encoder::load_mcu(const void *pSrc) + { + const uint8* Psrc = reinterpret_cast(pSrc); + + uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst + + if (m_num_components == 1) { + if (m_image_bpp == 3) + RGB_to_Y(pDst, Psrc, m_image_x); + else + memcpy(pDst, Psrc, m_image_x); + } else { + if (m_image_bpp == 3) + RGB_to_YCC(pDst, Psrc, m_image_x); + else + Y_to_YCC(pDst, Psrc, m_image_x); + } + + // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16 + if (m_num_components == 1) + memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x); + else + { + const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2]; + uint8 *q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt; + for (int i = m_image_x; i < m_image_x_mcu; i++) + { + *q++ = y; *q++ = cb; *q++ = cr; + } + } + + if (++m_mcu_y_ofs == m_mcu_y) + { + process_mcu_row(); + m_mcu_y_ofs = 0; + } + } + + // Quantization table generation. + void jpeg_encoder::compute_quant_table(int32 *pDst, const int16 *pSrc) + { + int32 q; + if (m_params.m_quality < 50) + q = 5000 / m_params.m_quality; + else + q = 200 - m_params.m_quality * 2; + for (int i = 0; i < 64; i++) + { + int32 j = *pSrc++; j = (j * q + 50L) / 100L; + *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255); + } + } + + // Higher-level methods. + bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels) + { + m_num_components = 3; + switch (m_params.m_subsampling) + { + case Y_ONLY: + { + m_num_components = 1; + m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; + m_mcu_x = 8; m_mcu_y = 8; + break; + } + case H1V1: + { + m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 8; m_mcu_y = 8; + break; + } + case H2V1: + { + m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 16; m_mcu_y = 8; + break; + } + case H2V2: + { + m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2; + m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; + m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; + m_mcu_x = 16; m_mcu_y = 16; + } + } + + m_image_x = p_x_res; m_image_y = p_y_res; + m_image_bpp = src_channels; + m_image_bpl = m_image_x * src_channels; + m_image_x_mcu = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1)); + m_image_y_mcu = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1)); + m_image_bpl_xlt = m_image_x * m_num_components; + m_image_bpl_mcu = m_image_x_mcu * m_num_components; + m_mcus_per_row = m_image_x_mcu / m_mcu_x; + + if ((m_mcu_lines[0] = static_cast(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) { + return false; + } + for (int i = 1; i < m_mcu_y; i++) + m_mcu_lines[i] = m_mcu_lines[i-1] + m_image_bpl_mcu; + + if(m_last_quality != m_params.m_quality){ + m_last_quality = m_params.m_quality; + compute_quant_table(m_quantization_tables[0], s_std_lum_quant); + compute_quant_table(m_quantization_tables[1], s_std_croma_quant); + } + + if(!m_huff_initialized){ + m_huff_initialized = true; + + memcpy(m_huff_bits[0+0], s_dc_lum_bits, 17); memcpy(m_huff_val[0+0], s_dc_lum_val, DC_LUM_CODES); + memcpy(m_huff_bits[2+0], s_ac_lum_bits, 17); memcpy(m_huff_val[2+0], s_ac_lum_val, AC_LUM_CODES); + memcpy(m_huff_bits[0+1], s_dc_chroma_bits, 17); memcpy(m_huff_val[0+1], s_dc_chroma_val, DC_CHROMA_CODES); + memcpy(m_huff_bits[2+1], s_ac_chroma_bits, 17); memcpy(m_huff_val[2+1], s_ac_chroma_val, AC_CHROMA_CODES); + + compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0], m_huff_val[0+0]); + compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0], m_huff_val[2+0]); + compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1], m_huff_val[0+1]); + compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1], m_huff_val[2+1]); + } + + m_out_buf_left = JPGE_OUT_BUF_SIZE; + m_pOut_buf = m_out_buf; + m_bit_buffer = 0; + m_bits_in = 0; + m_mcu_y_ofs = 0; + m_pass_num = 2; + memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0])); + + // Emit all markers at beginning of image file. + emit_marker(M_SOI); + emit_jfif_app0(); + emit_dqt(); + emit_sof(); + emit_dhts(); + emit_sos(); + + return m_all_stream_writes_succeeded; + } + + bool jpeg_encoder::process_end_of_image() + { + if (m_mcu_y_ofs) { + if (m_mcu_y_ofs < 16) { // check here just to shut up static analysis + for (int i = m_mcu_y_ofs; i < m_mcu_y; i++) { + memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu); + } + } + process_mcu_row(); + } + + put_bits(0x7F, 7); + emit_marker(M_EOI); + flush_output_buffer(); + m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(NULL, 0); + m_pass_num++; // purposely bump up m_pass_num, for debugging + return true; + } + + void jpeg_encoder::clear() + { + m_mcu_lines[0] = NULL; + m_pass_num = 0; + m_all_stream_writes_succeeded = true; + } + + jpeg_encoder::jpeg_encoder() + { + clear(); + } + + jpeg_encoder::~jpeg_encoder() + { + deinit(); + } + + bool jpeg_encoder::init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params) + { + deinit(); + if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check())) return false; + m_pStream = pStream; + m_params = comp_params; + return jpg_open(width, height, src_channels); + } + + void jpeg_encoder::deinit() + { + jpge_free(m_mcu_lines[0]); + clear(); + } + + bool jpeg_encoder::process_scanline(const void* pScanline) + { + if ((m_pass_num < 1) || (m_pass_num > 2)) { + return false; + } + if (m_all_stream_writes_succeeded) { + if (!pScanline) { + if (!process_end_of_image()) { + return false; + } + } else { + load_mcu(pScanline); + } + } + return m_all_stream_writes_succeeded; + } + +} // namespace jpge diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h new file mode 100644 index 0000000000..aa295c8af0 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h @@ -0,0 +1,142 @@ +// jpge.h - C++ class for JPEG compression. +// Public domain, Rich Geldreich +// Alex Evans: Added RGBA support, linear memory allocator. +#ifndef JPEG_ENCODER_H +#define JPEG_ENCODER_H + +namespace jpge +{ + typedef unsigned char uint8; + typedef signed short int16; + typedef signed int int32; + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef unsigned int uint; + + // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. + enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; + + // JPEG compression parameters structure. + struct params { + inline params() : m_quality(85), m_subsampling(H2V2) { } + + inline bool check() const { + if ((m_quality < 1) || (m_quality > 100)) { + return false; + } + if ((uint)m_subsampling > (uint)H2V2) { + return false; + } + return true; + } + + // Quality: 1-100, higher is better. Typical values are around 50-95. + int m_quality; + + // m_subsampling: + // 0 = Y (grayscale) only + // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) + // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) + // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) + subsampling_t m_subsampling; + }; + + // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. + // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. + class output_stream { + public: + virtual ~output_stream() { }; + virtual bool put_buf(const void* Pbuf, int len) = 0; + virtual uint get_size() const = 0; + }; + + // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. + class jpeg_encoder { + public: + jpeg_encoder(); + ~jpeg_encoder(); + + // Initializes the compressor. + // pStream: The stream object to use for writing compressed data. + // params - Compression parameters structure, defined above. + // width, height - Image dimensions. + // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. + // Returns false on out of memory or if a stream write fails. + bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); + + // Call this method with each source scanline. + // width * src_channels bytes per scanline is expected (RGB or Y format). + // You must call with NULL after all scanlines are processed to finish compression. + // Returns false on out of memory or if a stream write fails. + bool process_scanline(const void* pScanline); + + // Deinitializes the compressor, freeing any allocated memory. May be called at any time. + void deinit(); + + private: + jpeg_encoder(const jpeg_encoder &); + jpeg_encoder &operator =(const jpeg_encoder &); + + typedef int32 sample_array_t; + enum { JPGE_OUT_BUF_SIZE = 512 }; + + output_stream *m_pStream; + params m_params; + uint8 m_num_components; + uint8 m_comp_h_samp[3], m_comp_v_samp[3]; + int m_image_x, m_image_y, m_image_bpp, m_image_bpl; + int m_image_x_mcu, m_image_y_mcu; + int m_image_bpl_xlt, m_image_bpl_mcu; + int m_mcus_per_row; + int m_mcu_x, m_mcu_y; + uint8 *m_mcu_lines[16]; + uint8 m_mcu_y_ofs; + sample_array_t m_sample_array[64]; + int16 m_coefficient_array[64]; + + int m_last_dc_val[3]; + uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; + uint8 *m_pOut_buf; + uint m_out_buf_left; + uint32 m_bit_buffer; + uint m_bits_in; + uint8 m_pass_num; + bool m_all_stream_writes_succeeded; + + bool jpg_open(int p_x_res, int p_y_res, int src_channels); + + void flush_output_buffer(); + void put_bits(uint bits, uint len); + + void emit_byte(uint8 i); + void emit_word(uint i); + void emit_marker(int marker); + + void emit_jfif_app0(); + void emit_dqt(); + void emit_sof(); + void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); + void emit_dhts(); + void emit_sos(); + + void compute_quant_table(int32 *dst, const int16 *src); + void load_quantized_coefficients(int component_num); + + void load_block_8_8_grey(int x); + void load_block_8_8(int x, int y, int c); + void load_block_16_8(int x, int c); + void load_block_16_8_8(int x, int c); + + void code_coefficients_pass_two(int component_num); + void code_block(int component_num); + + void process_mcu_row(); + bool process_end_of_image(); + void load_mcu(const void* src); + void clear(); + void init(); + }; + +} // namespace jpge + +#endif // JPEG_ENCODER diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h new file mode 100644 index 0000000000..c5a0577ef8 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h @@ -0,0 +1,29 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _CONVERSIONS_YUV_H_ +#define _CONVERSIONS_YUV_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); + +#ifdef __cplusplus +} +#endif + +#endif /* _CONVERSIONS_YUV_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c new file mode 100644 index 0000000000..27072f7113 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c @@ -0,0 +1,397 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "img_converters.h" +#include "soc/efuse_reg.h" +#include "esp_heap_caps.h" +#include "yuv.h" +#include "sdkconfig.h" +#include "esp_jpg_decode.h" + +#include "esp_system.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define TAG "" +#else +#include "esp_log.h" +static const char* TAG = "to_bmp"; +#endif + +static const int BMP_HEADER_LEN = 54; + +typedef struct { + uint32_t filesize; + uint32_t reserved; + uint32_t fileoffset_to_pixelarray; + uint32_t dibheadersize; + int32_t width; + int32_t height; + uint16_t planes; + uint16_t bitsperpixel; + uint32_t compression; + uint32_t imagesize; + uint32_t ypixelpermeter; + uint32_t xpixelpermeter; + uint32_t numcolorspallette; + uint32_t mostimpcolor; +} bmp_header_t; + +typedef struct { + uint16_t width; + uint16_t height; + uint16_t data_offset; + const uint8_t *input; + uint8_t *output; +} rgb_jpg_decoder; + +static void *_malloc(size_t size) +{ + // check if SPIRAM is enabled and allocate on SPIRAM if allocatable +#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +#endif + // try allocating in internal memory + return malloc(size); +} + +//output buffer and image width +static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data) +{ + rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; + if(!data){ + if(x == 0 && y == 0){ + //write start + jpeg->width = w; + jpeg->height = h; + //if output is null, this is BMP + if(!jpeg->output){ + jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset); + if(!jpeg->output){ + return false; + } + } + } else { + //write end + } + return true; + } + + size_t jw = jpeg->width*3; + size_t t = y * jw; + size_t b = t + (h * jw); + size_t l = x * 3; + uint8_t *out = jpeg->output+jpeg->data_offset; + uint8_t *o = out; + size_t iy, ix; + + w = w * 3; + + for(iy=t; iywidth = w; + jpeg->height = h; + //if output is null, this is BMP + if(!jpeg->output){ + jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset); + if(!jpeg->output){ + return false; + } + } + } else { + //write end + } + return true; + } + + size_t jw = jpeg->width*3; + size_t jw2 = jpeg->width*2; + size_t t = y * jw; + size_t t2 = y * jw2; + size_t b = t + (h * jw); + size_t l = x * 2; + uint8_t *out = jpeg->output+jpeg->data_offset; + uint8_t *o = out; + size_t iy, iy2, ix, ix2; + + w = w * 3; + + for(iy=t, iy2=t2; iy> 3); + o[ix2+1] = c>>8; + o[ix2] = c&0xff; + } + data+=w; + } + return true; +} + +//input buffer +static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len) +{ + rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; + if(buf) { + memcpy(buf, jpeg->input + index, len); + } + return len; +} + +static bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale) +{ + rgb_jpg_decoder jpeg; + jpeg.width = 0; + jpeg.height = 0; + jpeg.input = src; + jpeg.output = out; + jpeg.data_offset = 0; + + if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){ + return false; + } + return true; +} + +bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale) +{ + rgb_jpg_decoder jpeg; + jpeg.width = 0; + jpeg.height = 0; + jpeg.input = src; + jpeg.output = out; + jpeg.data_offset = 0; + + if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb565_write, (void*)&jpeg) != ESP_OK){ + return false; + } + return true; +} + +bool jpg2bmp(const uint8_t *src, size_t src_len, uint8_t ** out, size_t * out_len) +{ + + rgb_jpg_decoder jpeg; + jpeg.width = 0; + jpeg.height = 0; + jpeg.input = src; + jpeg.output = NULL; + jpeg.data_offset = BMP_HEADER_LEN; + + if(esp_jpg_decode(src_len, JPG_SCALE_NONE, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){ + return false; + } + + size_t output_size = jpeg.width*jpeg.height*3; + + jpeg.output[0] = 'B'; + jpeg.output[1] = 'M'; + bmp_header_t * bitmap = (bmp_header_t*)&jpeg.output[2]; + bitmap->reserved = 0; + bitmap->filesize = output_size+BMP_HEADER_LEN; + bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN; + bitmap->dibheadersize = 40; + bitmap->width = jpeg.width; + bitmap->height = -jpeg.height;//set negative for top to bottom + bitmap->planes = 1; + bitmap->bitsperpixel = 24; + bitmap->compression = 0; + bitmap->imagesize = output_size; + bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI + bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI + bitmap->numcolorspallette = 0; + bitmap->mostimpcolor = 0; + + *out = jpeg.output; + *out_len = output_size+BMP_HEADER_LEN; + + return true; +} + +bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf) +{ + int pix_count = 0; + if(format == PIXFORMAT_JPEG) { + return jpg2rgb888(src_buf, src_len, rgb_buf, JPG_SCALE_NONE); + } else if(format == PIXFORMAT_RGB888) { + memcpy(rgb_buf, src_buf, src_len); + } else if(format == PIXFORMAT_RGB565) { + int i; + uint8_t hb, lb; + pix_count = src_len / 2; + for(i=0; i> 3; + *rgb_buf++ = hb & 0xF8; + } + } else if(format == PIXFORMAT_GRAYSCALE) { + int i; + uint8_t b; + pix_count = src_len; + for(i=0; ireserved = 0; + bitmap->filesize = out_size; + bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN + palette_size; + bitmap->dibheadersize = 40; + bitmap->width = width; + bitmap->height = -height;//set negative for top to bottom + bitmap->planes = 1; + bitmap->bitsperpixel = bpp * 8; + bitmap->compression = 0; + bitmap->imagesize = pix_count * bpp; + bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI + bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI + bitmap->numcolorspallette = 0; + bitmap->mostimpcolor = 0; + + uint8_t * palette_buf = out_buf + BMP_HEADER_LEN; + uint8_t * pix_buf = palette_buf + palette_size; + uint8_t * src_buf = src; + + if (palette_size > 0) { + // Grayscale palette + for (int i = 0; i < 256; ++i) { + for (int j = 0; j < 3; ++j) { + *palette_buf = i; + palette_buf++; + } + // Reserved / alpha channel. + *palette_buf = 0; + palette_buf++; + } + } + + //convert data to RGB888 + if(format == PIXFORMAT_RGB888) { + memcpy(pix_buf, src_buf, pix_count*3); + } else if(format == PIXFORMAT_RGB565) { + int i; + uint8_t hb, lb; + for(i=0; i> 3; + *pix_buf++ = hb & 0xF8; + } + } else if(format == PIXFORMAT_GRAYSCALE) { + memcpy(pix_buf, src_buf, pix_count); + } else if(format == PIXFORMAT_YUV422) { + int i, maxi = pix_count / 2; + uint8_t y0, y1, u, v; + uint8_t r, g, b; + for(i=0; ibuf, fb->len, fb->width, fb->height, fb->format, out, out_len); +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp new file mode 100644 index 0000000000..24cc2989cd --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp @@ -0,0 +1,235 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include "esp_attr.h" +#include "soc/efuse_reg.h" +#include "esp_heap_caps.h" +#include "esp_camera.h" +#include "img_converters.h" +#include "jpge.h" +#include "yuv.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define TAG "" +#else +#include "esp_log.h" +static const char* TAG = "to_jpg"; +#endif + +static void *_malloc(size_t size) +{ + void * res = malloc(size); + if(res) { + return res; + } + + // check if SPIRAM is enabled and is allocatable +#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +#endif + return NULL; +} + +static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line) +{ + int i=0, o=0, l=0; + if(format == PIXFORMAT_GRAYSCALE) { + memcpy(dst, src + line * width, width); + } else if(format == PIXFORMAT_RGB888) { + l = width * 3; + src += l * line; + for(i=0; i> 3; + dst[o++] = (src[i+1] & 0x1F) << 3; + } + } else if(format == PIXFORMAT_YUV422) { + uint8_t y0, y1, u, v; + uint8_t r, g, b; + l = width * 2; + src += l * line; + for(i=0; i 100) { + quality = 100; + } + + jpge::params comp_params = jpge::params(); + comp_params.m_subsampling = subsampling; + comp_params.m_quality = quality; + + jpge::jpeg_encoder dst_image; + + if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) { + ESP_LOGE(TAG, "JPG encoder init failed"); + return false; + } + + uint8_t* line = (uint8_t*)_malloc(width * num_channels); + if(!line) { + ESP_LOGE(TAG, "Scan line malloc failed"); + return false; + } + + for (int i = 0; i < height; i++) { + convert_line_format(src, format, line, width, num_channels, i); + if (!dst_image.process_scanline(line)) { + ESP_LOGE(TAG, "JPG process line %u failed", i); + free(line); + return false; + } + } + free(line); + + if (!dst_image.process_scanline(NULL)) { + ESP_LOGE(TAG, "JPG image finish failed"); + return false; + } + dst_image.deinit(); + return true; +} + +class callback_stream : public jpge::output_stream { +protected: + jpg_out_cb ocb; + void * oarg; + size_t index; + +public: + callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { } + virtual ~callback_stream() { } + virtual bool put_buf(const void* data, int len) + { + index += ocb(oarg, index, data, len); + return true; + } + virtual size_t get_size() const + { + return index; + } +}; + +bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg) +{ + callback_stream dst_stream(cb, arg); + return convert_image(src, width, height, format, quality, &dst_stream); +} + +bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg) +{ + return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg); +} + + + +class memory_stream : public jpge::output_stream { +protected: + uint8_t *out_buf; + size_t max_len, index; + +public: + memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast(pBuf)), max_len(buf_size), index(0) { } + + virtual ~memory_stream() { } + + virtual bool put_buf(const void* pBuf, int len) + { + if (!pBuf) { + //end of image + return true; + } + if ((size_t)len > (max_len - index)) { + //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len); + len = max_len - index; + } + if (len) { + memcpy(out_buf + index, pBuf, len); + index += len; + } + return true; + } + + virtual size_t get_size() const + { + return index; + } +}; + +bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len) +{ + //todo: allocate proper buffer for holding JPEG data + //this should be enough for CIF frame size + int jpg_buf_len = 128*1024; + + + uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len); + if(jpg_buf == NULL) { + ESP_LOGE(TAG, "JPG buffer malloc failed"); + return false; + } + memory_stream dst_stream(jpg_buf, jpg_buf_len); + + if(!convert_image(src, width, height, format, quality, &dst_stream)) { + free(jpg_buf); + return false; + } + + *out = jpg_buf; + *out_len = dst_stream.get_size(); + return true; +} + +bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len) +{ + return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len); +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c new file mode 100644 index 0000000000..46034cc868 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c @@ -0,0 +1,298 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "yuv.h" +#include "esp_attr.h" + +typedef struct { + int16_t vY; + int16_t vVr; + int16_t vVg; + int16_t vUg; + int16_t vUb; +} yuv_table_row; + +static const yuv_table_row yuv_table[256] = { + // Y Vr Vg Ug Ub // # + { -18, -204, 50, 104, -258 }, // 0 + { -17, -202, 49, 103, -256 }, // 1 + { -16, -201, 49, 102, -254 }, // 2 + { -15, -199, 48, 101, -252 }, // 3 + { -13, -197, 48, 100, -250 }, // 4 + { -12, -196, 48, 99, -248 }, // 5 + { -11, -194, 47, 99, -246 }, // 6 + { -10, -193, 47, 98, -244 }, // 7 + { -9, -191, 46, 97, -242 }, // 8 + { -8, -189, 46, 96, -240 }, // 9 + { -6, -188, 46, 95, -238 }, // 10 + { -5, -186, 45, 95, -236 }, // 11 + { -4, -185, 45, 94, -234 }, // 12 + { -3, -183, 44, 93, -232 }, // 13 + { -2, -181, 44, 92, -230 }, // 14 + { -1, -180, 44, 91, -228 }, // 15 + { 0, -178, 43, 91, -226 }, // 16 + { 1, -177, 43, 90, -223 }, // 17 + { 2, -175, 43, 89, -221 }, // 18 + { 3, -173, 42, 88, -219 }, // 19 + { 4, -172, 42, 87, -217 }, // 20 + { 5, -170, 41, 86, -215 }, // 21 + { 6, -169, 41, 86, -213 }, // 22 + { 8, -167, 41, 85, -211 }, // 23 + { 9, -165, 40, 84, -209 }, // 24 + { 10, -164, 40, 83, -207 }, // 25 + { 11, -162, 39, 82, -205 }, // 26 + { 12, -161, 39, 82, -203 }, // 27 + { 13, -159, 39, 81, -201 }, // 28 + { 15, -158, 38, 80, -199 }, // 29 + { 16, -156, 38, 79, -197 }, // 30 + { 17, -154, 37, 78, -195 }, // 31 + { 18, -153, 37, 78, -193 }, // 32 + { 19, -151, 37, 77, -191 }, // 33 + { 20, -150, 36, 76, -189 }, // 34 + { 22, -148, 36, 75, -187 }, // 35 + { 23, -146, 35, 74, -185 }, // 36 + { 24, -145, 35, 73, -183 }, // 37 + { 25, -143, 35, 73, -181 }, // 38 + { 26, -142, 34, 72, -179 }, // 39 + { 27, -140, 34, 71, -177 }, // 40 + { 29, -138, 34, 70, -175 }, // 41 + { 30, -137, 33, 69, -173 }, // 42 + { 31, -135, 33, 69, -171 }, // 43 + { 32, -134, 32, 68, -169 }, // 44 + { 33, -132, 32, 67, -167 }, // 45 + { 34, -130, 32, 66, -165 }, // 46 + { 36, -129, 31, 65, -163 }, // 47 + { 37, -127, 31, 65, -161 }, // 48 + { 38, -126, 30, 64, -159 }, // 49 + { 39, -124, 30, 63, -157 }, // 50 + { 40, -122, 30, 62, -155 }, // 51 + { 41, -121, 29, 61, -153 }, // 52 + { 43, -119, 29, 60, -151 }, // 53 + { 44, -118, 28, 60, -149 }, // 54 + { 45, -116, 28, 59, -147 }, // 55 + { 46, -114, 28, 58, -145 }, // 56 + { 47, -113, 27, 57, -143 }, // 57 + { 48, -111, 27, 56, -141 }, // 58 + { 50, -110, 26, 56, -139 }, // 59 + { 51, -108, 26, 55, -137 }, // 60 + { 52, -106, 26, 54, -135 }, // 61 + { 53, -105, 25, 53, -133 }, // 62 + { 54, -103, 25, 52, -131 }, // 63 + { 55, -102, 25, 52, -129 }, // 64 + { 57, -100, 24, 51, -127 }, // 65 + { 58, -98, 24, 50, -125 }, // 66 + { 59, -97, 23, 49, -123 }, // 67 + { 60, -95, 23, 48, -121 }, // 68 + { 61, -94, 23, 47, -119 }, // 69 + { 62, -92, 22, 47, -117 }, // 70 + { 64, -90, 22, 46, -115 }, // 71 + { 65, -89, 21, 45, -113 }, // 72 + { 66, -87, 21, 44, -110 }, // 73 + { 67, -86, 21, 43, -108 }, // 74 + { 68, -84, 20, 43, -106 }, // 75 + { 69, -82, 20, 42, -104 }, // 76 + { 71, -81, 19, 41, -102 }, // 77 + { 72, -79, 19, 40, -100 }, // 78 + { 73, -78, 19, 39, -98 }, // 79 + { 74, -76, 18, 39, -96 }, // 80 + { 75, -75, 18, 38, -94 }, // 81 + { 76, -73, 17, 37, -92 }, // 82 + { 77, -71, 17, 36, -90 }, // 83 + { 79, -70, 17, 35, -88 }, // 84 + { 80, -68, 16, 34, -86 }, // 85 + { 81, -67, 16, 34, -84 }, // 86 + { 82, -65, 16, 33, -82 }, // 87 + { 83, -63, 15, 32, -80 }, // 88 + { 84, -62, 15, 31, -78 }, // 89 + { 86, -60, 14, 30, -76 }, // 90 + { 87, -59, 14, 30, -74 }, // 91 + { 88, -57, 14, 29, -72 }, // 92 + { 89, -55, 13, 28, -70 }, // 93 + { 90, -54, 13, 27, -68 }, // 94 + { 91, -52, 12, 26, -66 }, // 95 + { 93, -51, 12, 26, -64 }, // 96 + { 94, -49, 12, 25, -62 }, // 97 + { 95, -47, 11, 24, -60 }, // 98 + { 96, -46, 11, 23, -58 }, // 99 + { 97, -44, 10, 22, -56 }, // 100 + { 98, -43, 10, 21, -54 }, // 101 + { 100, -41, 10, 21, -52 }, // 102 + { 101, -39, 9, 20, -50 }, // 103 + { 102, -38, 9, 19, -48 }, // 104 + { 103, -36, 8, 18, -46 }, // 105 + { 104, -35, 8, 17, -44 }, // 106 + { 105, -33, 8, 17, -42 }, // 107 + { 107, -31, 7, 16, -40 }, // 108 + { 108, -30, 7, 15, -38 }, // 109 + { 109, -28, 7, 14, -36 }, // 110 + { 110, -27, 6, 13, -34 }, // 111 + { 111, -25, 6, 13, -32 }, // 112 + { 112, -23, 5, 12, -30 }, // 113 + { 114, -22, 5, 11, -28 }, // 114 + { 115, -20, 5, 10, -26 }, // 115 + { 116, -19, 4, 9, -24 }, // 116 + { 117, -17, 4, 8, -22 }, // 117 + { 118, -15, 3, 8, -20 }, // 118 + { 119, -14, 3, 7, -18 }, // 119 + { 121, -12, 3, 6, -16 }, // 120 + { 122, -11, 2, 5, -14 }, // 121 + { 123, -9, 2, 4, -12 }, // 122 + { 124, -7, 1, 4, -10 }, // 123 + { 125, -6, 1, 3, -8 }, // 124 + { 126, -4, 1, 2, -6 }, // 125 + { 128, -3, 0, 1, -4 }, // 126 + { 129, -1, 0, 0, -2 }, // 127 + { 130, 0, 0, 0, 0 }, // 128 + { 131, 1, 0, 0, 2 }, // 129 + { 132, 3, 0, -1, 4 }, // 130 + { 133, 4, -1, -2, 6 }, // 131 + { 135, 6, -1, -3, 8 }, // 132 + { 136, 7, -1, -4, 10 }, // 133 + { 137, 9, -2, -4, 12 }, // 134 + { 138, 11, -2, -5, 14 }, // 135 + { 139, 12, -3, -6, 16 }, // 136 + { 140, 14, -3, -7, 18 }, // 137 + { 142, 15, -3, -8, 20 }, // 138 + { 143, 17, -4, -8, 22 }, // 139 + { 144, 19, -4, -9, 24 }, // 140 + { 145, 20, -5, -10, 26 }, // 141 + { 146, 22, -5, -11, 28 }, // 142 + { 147, 23, -5, -12, 30 }, // 143 + { 148, 25, -6, -13, 32 }, // 144 + { 150, 27, -6, -13, 34 }, // 145 + { 151, 28, -7, -14, 36 }, // 146 + { 152, 30, -7, -15, 38 }, // 147 + { 153, 31, -7, -16, 40 }, // 148 + { 154, 33, -8, -17, 42 }, // 149 + { 155, 35, -8, -17, 44 }, // 150 + { 157, 36, -8, -18, 46 }, // 151 + { 158, 38, -9, -19, 48 }, // 152 + { 159, 39, -9, -20, 50 }, // 153 + { 160, 41, -10, -21, 52 }, // 154 + { 161, 43, -10, -21, 54 }, // 155 + { 162, 44, -10, -22, 56 }, // 156 + { 164, 46, -11, -23, 58 }, // 157 + { 165, 47, -11, -24, 60 }, // 158 + { 166, 49, -12, -25, 62 }, // 159 + { 167, 51, -12, -26, 64 }, // 160 + { 168, 52, -12, -26, 66 }, // 161 + { 169, 54, -13, -27, 68 }, // 162 + { 171, 55, -13, -28, 70 }, // 163 + { 172, 57, -14, -29, 72 }, // 164 + { 173, 59, -14, -30, 74 }, // 165 + { 174, 60, -14, -30, 76 }, // 166 + { 175, 62, -15, -31, 78 }, // 167 + { 176, 63, -15, -32, 80 }, // 168 + { 178, 65, -16, -33, 82 }, // 169 + { 179, 67, -16, -34, 84 }, // 170 + { 180, 68, -16, -34, 86 }, // 171 + { 181, 70, -17, -35, 88 }, // 172 + { 182, 71, -17, -36, 90 }, // 173 + { 183, 73, -17, -37, 92 }, // 174 + { 185, 75, -18, -38, 94 }, // 175 + { 186, 76, -18, -39, 96 }, // 176 + { 187, 78, -19, -39, 98 }, // 177 + { 188, 79, -19, -40, 100 }, // 178 + { 189, 81, -19, -41, 102 }, // 179 + { 190, 82, -20, -42, 104 }, // 180 + { 192, 84, -20, -43, 106 }, // 181 + { 193, 86, -21, -43, 108 }, // 182 + { 194, 87, -21, -44, 110 }, // 183 + { 195, 89, -21, -45, 113 }, // 184 + { 196, 90, -22, -46, 115 }, // 185 + { 197, 92, -22, -47, 117 }, // 186 + { 199, 94, -23, -47, 119 }, // 187 + { 200, 95, -23, -48, 121 }, // 188 + { 201, 97, -23, -49, 123 }, // 189 + { 202, 98, -24, -50, 125 }, // 190 + { 203, 100, -24, -51, 127 }, // 191 + { 204, 102, -25, -52, 129 }, // 192 + { 206, 103, -25, -52, 131 }, // 193 + { 207, 105, -25, -53, 133 }, // 194 + { 208, 106, -26, -54, 135 }, // 195 + { 209, 108, -26, -55, 137 }, // 196 + { 210, 110, -26, -56, 139 }, // 197 + { 211, 111, -27, -56, 141 }, // 198 + { 213, 113, -27, -57, 143 }, // 199 + { 214, 114, -28, -58, 145 }, // 200 + { 215, 116, -28, -59, 147 }, // 201 + { 216, 118, -28, -60, 149 }, // 202 + { 217, 119, -29, -60, 151 }, // 203 + { 218, 121, -29, -61, 153 }, // 204 + { 219, 122, -30, -62, 155 }, // 205 + { 221, 124, -30, -63, 157 }, // 206 + { 222, 126, -30, -64, 159 }, // 207 + { 223, 127, -31, -65, 161 }, // 208 + { 224, 129, -31, -65, 163 }, // 209 + { 225, 130, -32, -66, 165 }, // 210 + { 226, 132, -32, -67, 167 }, // 211 + { 228, 134, -32, -68, 169 }, // 212 + { 229, 135, -33, -69, 171 }, // 213 + { 230, 137, -33, -69, 173 }, // 214 + { 231, 138, -34, -70, 175 }, // 215 + { 232, 140, -34, -71, 177 }, // 216 + { 233, 142, -34, -72, 179 }, // 217 + { 235, 143, -35, -73, 181 }, // 218 + { 236, 145, -35, -73, 183 }, // 219 + { 237, 146, -35, -74, 185 }, // 220 + { 238, 148, -36, -75, 187 }, // 221 + { 239, 150, -36, -76, 189 }, // 222 + { 240, 151, -37, -77, 191 }, // 223 + { 242, 153, -37, -78, 193 }, // 224 + { 243, 154, -37, -78, 195 }, // 225 + { 244, 156, -38, -79, 197 }, // 226 + { 245, 158, -38, -80, 199 }, // 227 + { 246, 159, -39, -81, 201 }, // 228 + { 247, 161, -39, -82, 203 }, // 229 + { 249, 162, -39, -82, 205 }, // 230 + { 250, 164, -40, -83, 207 }, // 231 + { 251, 165, -40, -84, 209 }, // 232 + { 252, 167, -41, -85, 211 }, // 233 + { 253, 169, -41, -86, 213 }, // 234 + { 254, 170, -41, -86, 215 }, // 235 + { 256, 172, -42, -87, 217 }, // 236 + { 257, 173, -42, -88, 219 }, // 237 + { 258, 175, -43, -89, 221 }, // 238 + { 259, 177, -43, -90, 223 }, // 239 + { 260, 178, -43, -91, 226 }, // 240 + { 261, 180, -44, -91, 228 }, // 241 + { 263, 181, -44, -92, 230 }, // 242 + { 264, 183, -44, -93, 232 }, // 243 + { 265, 185, -45, -94, 234 }, // 244 + { 266, 186, -45, -95, 236 }, // 245 + { 267, 188, -46, -95, 238 }, // 246 + { 268, 189, -46, -96, 240 }, // 247 + { 270, 191, -46, -97, 242 }, // 248 + { 271, 193, -47, -98, 244 }, // 249 + { 272, 194, -47, -99, 246 }, // 250 + { 273, 196, -48, -99, 248 }, // 251 + { 274, 197, -48, -100, 250 }, // 252 + { 275, 199, -48, -101, 252 }, // 253 + { 277, 201, -49, -102, 254 }, // 254 + { 278, 202, -49, -103, 256 } // 255 +}; + +#define YUYV_CONSTRAIN(v) ((v)<0)?0:(((v)>255)?255:(v)) + +void IRAM_ATTR yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b) +{ + int16_t ri, gi, bi; + + ri = yuv_table[y].vY + yuv_table[v].vVr; + gi = yuv_table[y].vY + yuv_table[u].vUg + yuv_table[v].vVg; + bi = yuv_table[y].vY + yuv_table[u].vUb; + + *r = YUYV_CONSTRAIN(ri); + *g = YUYV_CONSTRAIN(gi); + *b = YUYV_CONSTRAIN(bi); +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c new file mode 100644 index 0000000000..d9bb7cf680 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c @@ -0,0 +1,514 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "esp_heap_caps.h" +#include "ll_cam.h" +#include "cam_hal.h" + +#if (ESP_IDF_VERSION_MAJOR == 3) && (ESP_IDF_VERSION_MINOR == 3) +#include "rom/ets_sys.h" +#else +#include "esp_timer.h" +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0 +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/ets_sys.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/ets_sys.h" +#endif +#endif // ESP_IDF_VERSION_MAJOR +#define ESP_CAMERA_ETS_PRINTF ets_printf + +#if CONFIG_CAMERA_TASK_STACK_SIZE +#define CAM_TASK_STACK CONFIG_CAMERA_TASK_STACK_SIZE +#else +#define CAM_TASK_STACK (2*1024) +#endif + +static const char *TAG = "cam_hal"; +static cam_obj_t *cam_obj = NULL; + +static const uint32_t JPEG_SOI_MARKER = 0xFFD8FF; // written in little-endian for esp32 +static const uint16_t JPEG_EOI_MARKER = 0xD9FF; // written in little-endian for esp32 + +static int cam_verify_jpeg_soi(const uint8_t *inbuf, uint32_t length) +{ + for (uint32_t i = 0; i < length; i++) { + if (memcmp(&inbuf[i], &JPEG_SOI_MARKER, 3) == 0) { + //ESP_LOGW(TAG, "SOI: %d", (int) i); + return i; + } + } + ESP_LOGW(TAG, "NO-SOI"); + return -1; +} + +static int cam_verify_jpeg_eoi(const uint8_t *inbuf, uint32_t length) +{ + int offset = -1; + uint8_t *dptr = (uint8_t *)inbuf + length - 2; + while (dptr > inbuf) { + if (memcmp(dptr, &JPEG_EOI_MARKER, 2) == 0) { + offset = dptr - inbuf; + //ESP_LOGW(TAG, "EOI: %d", length - (offset + 2)); + return offset; + } + dptr--; + } + return -1; +} + +static bool cam_get_next_frame(int * frame_pos) +{ + if(!cam_obj->frames[*frame_pos].en){ + for (int x = 0; x < cam_obj->frame_cnt; x++) { + if (cam_obj->frames[x].en) { + *frame_pos = x; + return true; + } + } + } else { + return true; + } + return false; +} + +static bool cam_start_frame(int * frame_pos) +{ + if (cam_get_next_frame(frame_pos)) { + if(ll_cam_start(cam_obj, *frame_pos)){ + // Vsync the frame manually + ll_cam_do_vsync(cam_obj); + uint64_t us = (uint64_t)esp_timer_get_time(); + cam_obj->frames[*frame_pos].fb.timestamp.tv_sec = us / 1000000UL; + cam_obj->frames[*frame_pos].fb.timestamp.tv_usec = us % 1000000UL; + return true; + } + } + return false; +} + +void IRAM_ATTR ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken) +{ + if (xQueueSendFromISR(cam->event_queue, (void *)&cam_event, HPTaskAwoken) != pdTRUE) { + ll_cam_stop(cam); + cam->state = CAM_STATE_IDLE; + ESP_CAMERA_ETS_PRINTF(DRAM_STR("cam_hal: EV-%s-OVF\r\n"), cam_event==CAM_IN_SUC_EOF_EVENT ? DRAM_STR("EOF") : DRAM_STR("VSYNC")); + } +} + +//Copy fram from DMA dma_buffer to fram dma_buffer +static void cam_task(void *arg) +{ + int cnt = 0; + int frame_pos = 0; + cam_obj->state = CAM_STATE_IDLE; + cam_event_t cam_event = 0; + + xQueueReset(cam_obj->event_queue); + + while (1) { + xQueueReceive(cam_obj->event_queue, (void *)&cam_event, portMAX_DELAY); + DBG_PIN_SET(1); + switch (cam_obj->state) { + + case CAM_STATE_IDLE: { + if (cam_event == CAM_VSYNC_EVENT) { + //DBG_PIN_SET(1); + if(cam_start_frame(&frame_pos)){ + cam_obj->frames[frame_pos].fb.len = 0; + cam_obj->state = CAM_STATE_READ_BUF; + } + cnt = 0; + } + } + break; + + case CAM_STATE_READ_BUF: { + camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb; + size_t pixels_per_dma = (cam_obj->dma_half_buffer_size * cam_obj->fb_bytes_per_pixel) / (cam_obj->dma_bytes_per_item * cam_obj->in_bytes_per_pixel); + + if (cam_event == CAM_IN_SUC_EOF_EVENT) { + if(!cam_obj->psram_mode){ + if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) { + ESP_LOGW(TAG, "FB-OVF"); + ll_cam_stop(cam_obj); + DBG_PIN_SET(0); + continue; + } + frame_buffer_event->len += ll_cam_memcpy(cam_obj, + &frame_buffer_event->buf[frame_buffer_event->len], + &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size], + cam_obj->dma_half_buffer_size); + } + //Check for JPEG SOI in the first buffer. stop if not found + if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) { + ll_cam_stop(cam_obj); + cam_obj->state = CAM_STATE_IDLE; + } + cnt++; + + } else if (cam_event == CAM_VSYNC_EVENT) { + //DBG_PIN_SET(1); + ll_cam_stop(cam_obj); + + if (cnt || !cam_obj->jpeg_mode || cam_obj->psram_mode) { + if (cam_obj->jpeg_mode) { + if (!cam_obj->psram_mode) { + if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) { + ESP_LOGW(TAG, "FB-OVF"); + cnt--; + } else { + frame_buffer_event->len += ll_cam_memcpy(cam_obj, + &frame_buffer_event->buf[frame_buffer_event->len], + &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size], + cam_obj->dma_half_buffer_size); + } + } + cnt++; + } + + cam_obj->frames[frame_pos].en = 0; + + if (cam_obj->psram_mode) { + if (cam_obj->jpeg_mode) { + frame_buffer_event->len = cnt * cam_obj->dma_half_buffer_size; + } else { + frame_buffer_event->len = cam_obj->recv_size; + } + } else if (!cam_obj->jpeg_mode) { + if (frame_buffer_event->len != cam_obj->fb_size) { + cam_obj->frames[frame_pos].en = 1; + ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, (unsigned) cam_obj->fb_size); + } + } + //send frame + if(!cam_obj->frames[frame_pos].en && xQueueSend(cam_obj->frame_buffer_queue, (void *)&frame_buffer_event, 0) != pdTRUE) { + //pop frame buffer from the queue + camera_fb_t * fb2 = NULL; + if(xQueueReceive(cam_obj->frame_buffer_queue, &fb2, 0) == pdTRUE) { + //push the new frame to the end of the queue + if (xQueueSend(cam_obj->frame_buffer_queue, (void *)&frame_buffer_event, 0) != pdTRUE) { + cam_obj->frames[frame_pos].en = 1; + ESP_LOGE(TAG, "FBQ-SND"); + } + //free the popped buffer + cam_give(fb2); + } else { + //queue is full and we could not pop a frame from it + cam_obj->frames[frame_pos].en = 1; + ESP_LOGE(TAG, "FBQ-RCV"); + } + } + } + + if(!cam_start_frame(&frame_pos)){ + cam_obj->state = CAM_STATE_IDLE; + } else { + cam_obj->frames[frame_pos].fb.len = 0; + } + cnt = 0; + } + } + break; + } + DBG_PIN_SET(0); + } +} + +static lldesc_t * allocate_dma_descriptors(uint32_t count, uint16_t size, uint8_t * buffer) +{ + lldesc_t *dma = (lldesc_t *)heap_caps_malloc(count * sizeof(lldesc_t), MALLOC_CAP_DMA); + if (dma == NULL) { + return dma; + } + + for (int x = 0; x < count; x++) { + dma[x].size = size; + dma[x].length = 0; + dma[x].sosf = 0; + dma[x].eof = 0; + dma[x].owner = 1; + dma[x].buf = (buffer + size * x); + dma[x].empty = (uint32_t)&dma[(x + 1) % count]; + } + return dma; +} + +static esp_err_t cam_dma_config(const camera_config_t *config) +{ + bool ret = ll_cam_dma_sizes(cam_obj); + if (0 == ret) { + return ESP_FAIL; + } + + cam_obj->dma_node_cnt = (cam_obj->dma_buffer_size) / cam_obj->dma_node_buffer_size; // Number of DMA nodes + cam_obj->frame_copy_cnt = cam_obj->recv_size / cam_obj->dma_half_buffer_size; // Number of interrupted copies, ping-pong copy + + ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d", + (int) cam_obj->dma_buffer_size, (int) cam_obj->dma_half_buffer_size, (int) cam_obj->dma_node_buffer_size, + (int) cam_obj->dma_node_cnt, (int) cam_obj->frame_copy_cnt); + + cam_obj->dma_buffer = NULL; + cam_obj->dma = NULL; + + cam_obj->frames = (cam_frame_t *)heap_caps_calloc(1, cam_obj->frame_cnt * sizeof(cam_frame_t), MALLOC_CAP_DEFAULT); + CAM_CHECK(cam_obj->frames != NULL, "frames malloc failed", ESP_FAIL); + + uint8_t dma_align = 0; + size_t fb_size = cam_obj->fb_size; + if (cam_obj->psram_mode) { + dma_align = ll_cam_get_dma_align(cam_obj); + if (cam_obj->fb_size < cam_obj->recv_size) { + fb_size = cam_obj->recv_size; + } + } + + /* Allocate memory for frame buffer */ + size_t alloc_size = fb_size * sizeof(uint8_t) + dma_align; + uint32_t _caps = MALLOC_CAP_8BIT; + if (CAMERA_FB_IN_DRAM == config->fb_location) { + _caps |= MALLOC_CAP_INTERNAL; + } else { + _caps |= MALLOC_CAP_SPIRAM; + } + for (int x = 0; x < cam_obj->frame_cnt; x++) { + cam_obj->frames[x].dma = NULL; + cam_obj->frames[x].fb_offset = 0; + cam_obj->frames[x].en = 0; + ESP_LOGI(TAG, "Allocating %d Byte frame buffer in %s", alloc_size, _caps & MALLOC_CAP_SPIRAM ? "PSRAM" : "OnBoard RAM"); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) + // In IDF v4.2 and earlier, memory returned by heap_caps_aligned_alloc must be freed using heap_caps_aligned_free. + // And heap_caps_aligned_free is deprecated on v4.3. + cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_aligned_alloc(16, alloc_size, _caps); +#else + cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(alloc_size, _caps); +#endif + CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL); + if (cam_obj->psram_mode) { + //align PSRAM buffer. TODO: save the offset so proper address can be freed later + cam_obj->frames[x].fb_offset = dma_align - ((uint32_t)cam_obj->frames[x].fb.buf & (dma_align - 1)); + cam_obj->frames[x].fb.buf += cam_obj->frames[x].fb_offset; + ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (unsigned) cam_obj->frames[x].fb.buf); + cam_obj->frames[x].dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->frames[x].fb.buf); + CAM_CHECK(cam_obj->frames[x].dma != NULL, "frame dma malloc failed", ESP_FAIL); + } + cam_obj->frames[x].en = 1; + } + + if (!cam_obj->psram_mode) { + cam_obj->dma_buffer = (uint8_t *)heap_caps_malloc(cam_obj->dma_buffer_size * sizeof(uint8_t), MALLOC_CAP_DMA); + if(NULL == cam_obj->dma_buffer) { + ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__, + (int) cam_obj->dma_buffer_size, (int) heap_caps_get_largest_free_block(MALLOC_CAP_DMA)); + return ESP_FAIL; + } + + cam_obj->dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->dma_buffer); + CAM_CHECK(cam_obj->dma != NULL, "dma malloc failed", ESP_FAIL); + } + + return ESP_OK; +} + +esp_err_t cam_init(const camera_config_t *config) +{ + CAM_CHECK(NULL != config, "config pointer is invalid", ESP_ERR_INVALID_ARG); + + esp_err_t ret = ESP_OK; + cam_obj = (cam_obj_t *)heap_caps_calloc(1, sizeof(cam_obj_t), MALLOC_CAP_DMA); + CAM_CHECK(NULL != cam_obj, "lcd_cam object malloc error", ESP_ERR_NO_MEM); + + cam_obj->swap_data = 0; + cam_obj->vsync_pin = config->pin_vsync; + cam_obj->vsync_invert = true; + + ll_cam_set_pin(cam_obj, config); + ret = ll_cam_config(cam_obj, config); + CAM_CHECK_GOTO(ret == ESP_OK, "ll_cam initialize failed", err); + +#if CAMERA_DBG_PIN_ENABLE + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[DBG_PIN_NUM], PIN_FUNC_GPIO); + gpio_set_direction(DBG_PIN_NUM, GPIO_MODE_OUTPUT); + gpio_set_pull_mode(DBG_PIN_NUM, GPIO_FLOATING); +#endif + + ESP_LOGI(TAG, "cam init ok"); + return ESP_OK; + +err: + free(cam_obj); + cam_obj = NULL; + return ESP_FAIL; +} + +esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid) +{ + CAM_CHECK(NULL != config, "config pointer is invalid", ESP_ERR_INVALID_ARG); + esp_err_t ret = ESP_OK; + + ret = ll_cam_set_sample_mode(cam_obj, (pixformat_t)config->pixel_format, config->xclk_freq_hz, sensor_pid); + + cam_obj->jpeg_mode = config->pixel_format == PIXFORMAT_JPEG; +#if CONFIG_IDF_TARGET_ESP32 + cam_obj->psram_mode = false; +#else + cam_obj->psram_mode = (config->xclk_freq_hz == 16000000); +#endif + cam_obj->frame_cnt = config->fb_count; + cam_obj->width = resolution[frame_size].width; + cam_obj->height = resolution[frame_size].height; + + if(cam_obj->jpeg_mode){ + cam_obj->recv_size = cam_obj->width * cam_obj->height / 5; + cam_obj->fb_size = cam_obj->recv_size; + } else { + cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel; + cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel; + } + + ret = cam_dma_config(config); + CAM_CHECK_GOTO(ret == ESP_OK, "cam_dma_config failed", err); + + size_t queue_size = cam_obj->dma_half_buffer_cnt - 1; + if (queue_size == 0) { + queue_size = 1; + } + cam_obj->event_queue = xQueueCreate(queue_size, sizeof(cam_event_t)); + CAM_CHECK_GOTO(cam_obj->event_queue != NULL, "event_queue create failed", err); + + size_t frame_buffer_queue_len = cam_obj->frame_cnt; + if (config->grab_mode == CAMERA_GRAB_LATEST && cam_obj->frame_cnt > 1) { + frame_buffer_queue_len = cam_obj->frame_cnt - 1; + } + cam_obj->frame_buffer_queue = xQueueCreate(frame_buffer_queue_len, sizeof(camera_fb_t*)); + CAM_CHECK_GOTO(cam_obj->frame_buffer_queue != NULL, "frame_buffer_queue create failed", err); + + ret = ll_cam_init_isr(cam_obj); + CAM_CHECK_GOTO(ret == ESP_OK, "cam intr alloc failed", err); + + +#if CONFIG_CAMERA_CORE0 + xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0); +#elif CONFIG_CAMERA_CORE1 + xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1); +#else + xTaskCreate(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle); +#endif + + ESP_LOGI(TAG, "cam config ok"); + return ESP_OK; + +err: + cam_deinit(); + return ESP_FAIL; +} + +esp_err_t cam_deinit(void) +{ + if (!cam_obj) { + return ESP_FAIL; + } + + cam_stop(); + if (cam_obj->task_handle) { + vTaskDelete(cam_obj->task_handle); + } + if (cam_obj->event_queue) { + vQueueDelete(cam_obj->event_queue); + } + if (cam_obj->frame_buffer_queue) { + vQueueDelete(cam_obj->frame_buffer_queue); + } + + ll_cam_deinit(cam_obj); + + if (cam_obj->dma) { + free(cam_obj->dma); + } + if (cam_obj->dma_buffer) { + free(cam_obj->dma_buffer); + } + if (cam_obj->frames) { + for (int x = 0; x < cam_obj->frame_cnt; x++) { + free(cam_obj->frames[x].fb.buf - cam_obj->frames[x].fb_offset); + if (cam_obj->frames[x].dma) { + free(cam_obj->frames[x].dma); + } + } + free(cam_obj->frames); + } + + free(cam_obj); + cam_obj = NULL; + return ESP_OK; +} + +void cam_stop(void) +{ + ll_cam_vsync_intr_enable(cam_obj, false); + ll_cam_stop(cam_obj); +} + +void cam_start(void) +{ + ll_cam_vsync_intr_enable(cam_obj, true); +} + +camera_fb_t *cam_take(TickType_t timeout) +{ + camera_fb_t *dma_buffer = NULL; + TickType_t start = xTaskGetTickCount(); + xQueueReceive(cam_obj->frame_buffer_queue, (void *)&dma_buffer, timeout); + if (dma_buffer) { + if(cam_obj->jpeg_mode){ + // find the end marker for JPEG. Data after that can be discarded + int offset_e = cam_verify_jpeg_eoi(dma_buffer->buf, dma_buffer->len); + if (offset_e >= 0) { + // adjust buffer length + dma_buffer->len = offset_e + sizeof(JPEG_EOI_MARKER); + return dma_buffer; + } else { + ESP_LOGW(TAG, "NO-EOI"); + cam_give(dma_buffer); + return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!! + } + } else if(cam_obj->psram_mode && cam_obj->in_bytes_per_pixel != cam_obj->fb_bytes_per_pixel){ + //currently this is used only for YUV to GRAYSCALE + dma_buffer->len = ll_cam_memcpy(cam_obj, dma_buffer->buf, dma_buffer->buf, dma_buffer->len); + } + return dma_buffer; + } else { + ESP_LOGW(TAG, "Failed to get the frame on time!"); + } + return NULL; +} + +void cam_give(camera_fb_t *dma_buffer) +{ + for (int x = 0; x < cam_obj->frame_cnt; x++) { + if (&cam_obj->frames[x].fb == dma_buffer) { + cam_obj->frames[x].en = 1; + break; + } + } +} + +void cam_give_all(void) { + for (int x = 0; x < cam_obj->frame_cnt; x++) { + cam_obj->frames[x].en = 1; + } +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c new file mode 100644 index 0000000000..4b7e906a57 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c @@ -0,0 +1,486 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include +#include "time.h" +#include "sys/time.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "sensor.h" +#include "sccb.h" +#include "cam_hal.h" +#include "esp_camera.h" +#include "xclk.h" +#if CONFIG_OV2640_SUPPORT +#include "ov2640.h" +#endif +#if CONFIG_OV7725_SUPPORT +#include "ov7725.h" +#endif +#if CONFIG_OV3660_SUPPORT +#include "ov3660.h" +#endif +#if CONFIG_OV5640_SUPPORT +#include "ov5640.h" +#endif +#if CONFIG_NT99141_SUPPORT +#include "nt99141.h" +#endif +#if CONFIG_OV7670_SUPPORT +#include "ov7670.h" +#endif +#if CONFIG_GC2145_SUPPORT +#include "gc2145.h" +#endif +#if CONFIG_GC032A_SUPPORT +#include "gc032a.h" +#endif +#if CONFIG_GC0308_SUPPORT +#include "gc0308.h" +#endif +#if CONFIG_BF3005_SUPPORT +#include "bf3005.h" +#endif +#if CONFIG_BF20A6_SUPPORT +#include "bf20a6.h" +#endif +#if CONFIG_SC101IOT_SUPPORT +#include "sc101iot.h" +#endif +#if CONFIG_SC030IOT_SUPPORT +#include "sc030iot.h" +#endif +#if CONFIG_SC031GS_SUPPORT +#include "sc031gs.h" +#endif + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#define TAG "" +#else +#include "esp_log.h" +static const char *TAG = "camera"; +#endif + +typedef struct { + sensor_t sensor; + camera_fb_t fb; +} camera_state_t; + +static const char *CAMERA_SENSOR_NVS_KEY = "sensor"; +static const char *CAMERA_PIXFORMAT_NVS_KEY = "pixformat"; +static camera_state_t *s_state = NULL; + +#if CONFIG_IDF_TARGET_ESP32S3 // LCD_CAM module of ESP32-S3 will generate xclk +#define CAMERA_ENABLE_OUT_CLOCK(v) +#define CAMERA_DISABLE_OUT_CLOCK() +#else +#define CAMERA_ENABLE_OUT_CLOCK(v) camera_enable_out_clock((v)) +#define CAMERA_DISABLE_OUT_CLOCK() camera_disable_out_clock() +#endif + +typedef struct { + int (*detect)(int slv_addr, sensor_id_t *id); + int (*init)(sensor_t *sensor); +} sensor_func_t; + +static const sensor_func_t g_sensors[] = { +#if CONFIG_OV7725_SUPPORT + {ov7725_detect, ov7725_init}, +#endif +#if CONFIG_OV7670_SUPPORT + {ov7670_detect, ov7670_init}, +#endif +#if CONFIG_OV2640_SUPPORT + {ov2640_detect, ov2640_init}, +#endif +#if CONFIG_OV3660_SUPPORT + {ov3660_detect, ov3660_init}, +#endif +#if CONFIG_OV5640_SUPPORT + {ov5640_detect, ov5640_init}, +#endif +#if CONFIG_NT99141_SUPPORT + {nt99141_detect, nt99141_init}, +#endif +#if CONFIG_GC2145_SUPPORT + {gc2145_detect, gc2145_init}, +#endif +#if CONFIG_GC032A_SUPPORT + {gc032a_detect, gc032a_init}, +#endif +#if CONFIG_GC0308_SUPPORT + {gc0308_detect, gc0308_init}, +#endif +#if CONFIG_BF3005_SUPPORT + {bf3005_detect, bf3005_init}, +#endif +#if CONFIG_BF20A6_SUPPORT + {bf20a6_detect, bf20a6_init}, +#endif +#if CONFIG_SC101IOT_SUPPORT + {sc101iot_detect, sc101iot_init}, +#endif +#if CONFIG_SC030IOT_SUPPORT + {sc030iot_detect, sc030iot_init}, +#endif +#if CONFIG_SC031GS_SUPPORT + {sc031gs_detect, sc031gs_init}, +#endif +}; + +static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model) +{ + esp_err_t ret = ESP_OK; + *out_camera_model = CAMERA_NONE; + if (s_state != NULL) { + return ESP_ERR_INVALID_STATE; + } + + s_state = (camera_state_t *) calloc(sizeof(camera_state_t), 1); + if (!s_state) { + return ESP_ERR_NO_MEM; + } + + if (config->pin_xclk >= 0) { + ESP_LOGD(TAG, "Enabling XCLK output"); + CAMERA_ENABLE_OUT_CLOCK(config); + } + + if (config->pin_sccb_sda != -1) { + ESP_LOGD(TAG, "Initializing SCCB"); + ret = SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl); + } else { + ESP_LOGD(TAG, "Using existing I2C port"); + ret = SCCB_Use_Port(config->sccb_i2c_port); + } + + if(ret != ESP_OK) { + ESP_LOGE(TAG, "sccb init err"); + goto err; + } + + if (config->pin_pwdn >= 0) { + ESP_LOGD(TAG, "Resetting camera by power down line"); + gpio_config_t conf = { 0 }; + conf.pin_bit_mask = 1LL << config->pin_pwdn; + conf.mode = GPIO_MODE_OUTPUT; + gpio_config(&conf); + + // carefull, logic is inverted compared to reset pin + gpio_set_level(config->pin_pwdn, 1); + vTaskDelay(10 / portTICK_PERIOD_MS); + gpio_set_level(config->pin_pwdn, 0); + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + if (config->pin_reset >= 0) { + ESP_LOGD(TAG, "Resetting camera"); + gpio_config_t conf = { 0 }; + conf.pin_bit_mask = 1LL << config->pin_reset; + conf.mode = GPIO_MODE_OUTPUT; + gpio_config(&conf); + + gpio_set_level(config->pin_reset, 0); + vTaskDelay(10 / portTICK_PERIOD_MS); + gpio_set_level(config->pin_reset, 1); + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + ESP_LOGD(TAG, "Searching for camera address"); + vTaskDelay(10 / portTICK_PERIOD_MS); + + uint8_t slv_addr = SCCB_Probe(); + + if (slv_addr == 0) { + ret = ESP_ERR_NOT_FOUND; + goto err; + } + + ESP_LOGI(TAG, "Detected camera at address=0x%02x", slv_addr); + s_state->sensor.slv_addr = slv_addr; + s_state->sensor.xclk_freq_hz = config->xclk_freq_hz; + + /** + * Read sensor ID and then initialize sensor + * Attention: Some sensors have the same SCCB address. Therefore, several attempts may be made in the detection process + */ + sensor_id_t *id = &s_state->sensor.id; + for (size_t i = 0; i < sizeof(g_sensors) / sizeof(sensor_func_t); i++) { + if (g_sensors[i].detect(slv_addr, id)) { + camera_sensor_info_t *info = esp_camera_sensor_get_info(id); + if (NULL != info) { + *out_camera_model = info->model; + ESP_LOGI(TAG, "Detected %s camera", info->name); + g_sensors[i].init(&s_state->sensor); + break; + } + } + } + + if (CAMERA_NONE == *out_camera_model) { //If no supported sensors are detected + ESP_LOGE(TAG, "Detected camera not supported."); + ret = ESP_ERR_NOT_SUPPORTED; + goto err; + } + + ESP_LOGI(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x", + id->PID, id->VER, id->MIDH, id->MIDL); + + ESP_LOGD(TAG, "Doing SW reset of sensor"); + vTaskDelay(10 / portTICK_PERIOD_MS); + + return s_state->sensor.reset(&s_state->sensor); +err : + CAMERA_DISABLE_OUT_CLOCK(); + return ret; +} + +#if CONFIG_CAMERA_CONVERTER_ENABLED +static pixformat_t get_output_data_format(camera_conv_mode_t conv_mode) +{ + pixformat_t format = PIXFORMAT_RGB565; + switch (conv_mode) { + case YUV422_TO_YUV420: + format = PIXFORMAT_YUV420; + break; + case YUV422_TO_RGB565: // default format is RGB565 + default: + break; + } + ESP_LOGD(TAG, "Convert to %d format enabled", format); + return format; +} +#endif + +esp_err_t esp_camera_init(const camera_config_t *config) +{ + esp_err_t err; + err = cam_init(config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); + return err; + } + + camera_model_t camera_model = CAMERA_NONE; + err = camera_probe(config, &camera_model); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera probe failed with error 0x%x(%s)", err, esp_err_to_name(err)); + goto fail; + } + + framesize_t frame_size = (framesize_t) config->frame_size; + pixformat_t pix_format = (pixformat_t) config->pixel_format; + + if (PIXFORMAT_JPEG == pix_format && (!camera_sensor[camera_model].support_jpeg)) { + ESP_LOGE(TAG, "JPEG format is not supported on this sensor"); + err = ESP_ERR_NOT_SUPPORTED; + goto fail; + } + + if (frame_size > camera_sensor[camera_model].max_size) { + ESP_LOGW(TAG, "The frame size exceeds the maximum for this sensor, it will be forced to the maximum possible value"); + frame_size = camera_sensor[camera_model].max_size; + } + + err = cam_config(config, frame_size, s_state->sensor.id.PID); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera config failed with error 0x%x", err); + goto fail; + } + + s_state->sensor.status.framesize = frame_size; + s_state->sensor.pixformat = pix_format; + + ESP_LOGD(TAG, "Setting frame size to %dx%d", resolution[frame_size].width, resolution[frame_size].height); + if (s_state->sensor.set_framesize(&s_state->sensor, frame_size) != 0) { + ESP_LOGE(TAG, "Failed to set frame size"); + err = ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE; + goto fail; + } + s_state->sensor.set_pixformat(&s_state->sensor, pix_format); +#if CONFIG_CAMERA_CONVERTER_ENABLED + if(config->conv_mode) { + s_state->sensor.pixformat = get_output_data_format(config->conv_mode); // If conversion enabled, change the out data format by conversion mode + } +#endif + + if (s_state->sensor.id.PID == OV2640_PID) { + s_state->sensor.set_gainceiling(&s_state->sensor, GAINCEILING_2X); + s_state->sensor.set_bpc(&s_state->sensor, false); + s_state->sensor.set_wpc(&s_state->sensor, true); + s_state->sensor.set_lenc(&s_state->sensor, true); + } + + if (pix_format == PIXFORMAT_JPEG) { + s_state->sensor.set_quality(&s_state->sensor, config->jpeg_quality); + } + s_state->sensor.init_status(&s_state->sensor); + + cam_start(); + + return ESP_OK; + +fail: + esp_camera_deinit(); + return err; +} + +esp_err_t esp_camera_deinit() +{ + esp_err_t ret = cam_deinit(); + CAMERA_DISABLE_OUT_CLOCK(); + if (s_state) { + SCCB_Deinit(); + + free(s_state); + s_state = NULL; + } + + return ret; +} + +#define FB_GET_TIMEOUT (4000 / portTICK_PERIOD_MS) + +camera_fb_t *esp_camera_fb_get() +{ + if (s_state == NULL) { + return NULL; + } + camera_fb_t *fb = cam_take(FB_GET_TIMEOUT); + //set the frame properties + if (fb) { + fb->width = resolution[s_state->sensor.status.framesize].width; + fb->height = resolution[s_state->sensor.status.framesize].height; + fb->format = s_state->sensor.pixformat; + } + return fb; +} + +void esp_camera_fb_return(camera_fb_t *fb) +{ + if (s_state == NULL) { + return; + } + cam_give(fb); +} + +sensor_t *esp_camera_sensor_get() +{ + if (s_state == NULL) { + return NULL; + } + return &s_state->sensor; +} + +esp_err_t esp_camera_save_to_nvs(const char *key) +{ +#if ESP_IDF_VERSION_MAJOR > 3 + nvs_handle_t handle; +#else + nvs_handle handle; +#endif + esp_err_t ret = nvs_open(key, NVS_READWRITE, &handle); + + if (ret == ESP_OK) { + sensor_t *s = esp_camera_sensor_get(); + if (s != NULL) { + ret = nvs_set_blob(handle, CAMERA_SENSOR_NVS_KEY, &s->status, sizeof(camera_status_t)); + if (ret == ESP_OK) { + uint8_t pf = s->pixformat; + ret = nvs_set_u8(handle, CAMERA_PIXFORMAT_NVS_KEY, pf); + } + return ret; + } else { + return ESP_ERR_CAMERA_NOT_DETECTED; + } + nvs_close(handle); + return ret; + } else { + return ret; + } +} + +esp_err_t esp_camera_load_from_nvs(const char *key) +{ +#if ESP_IDF_VERSION_MAJOR > 3 + nvs_handle_t handle; +#else + nvs_handle handle; +#endif + uint8_t pf; + + esp_err_t ret = nvs_open(key, NVS_READWRITE, &handle); + + if (ret == ESP_OK) { + sensor_t *s = esp_camera_sensor_get(); + camera_status_t st; + if (s != NULL) { + size_t size = sizeof(camera_status_t); + ret = nvs_get_blob(handle, CAMERA_SENSOR_NVS_KEY, &st, &size); + if (ret == ESP_OK) { + s->set_ae_level(s, st.ae_level); + s->set_aec2(s, st.aec2); + s->set_aec_value(s, st.aec_value); + s->set_agc_gain(s, st.agc_gain); + s->set_awb_gain(s, st.awb_gain); + s->set_bpc(s, st.bpc); + s->set_brightness(s, st.brightness); + s->set_colorbar(s, st.colorbar); + s->set_contrast(s, st.contrast); + s->set_dcw(s, st.dcw); + s->set_denoise(s, st.denoise); + s->set_exposure_ctrl(s, st.aec); + s->set_framesize(s, st.framesize); + s->set_gain_ctrl(s, st.agc); + s->set_gainceiling(s, st.gainceiling); + s->set_hmirror(s, st.hmirror); + s->set_lenc(s, st.lenc); + s->set_quality(s, st.quality); + s->set_raw_gma(s, st.raw_gma); + s->set_saturation(s, st.saturation); + s->set_sharpness(s, st.sharpness); + s->set_special_effect(s, st.special_effect); + s->set_vflip(s, st.vflip); + s->set_wb_mode(s, st.wb_mode); + s->set_whitebal(s, st.awb); + s->set_wpc(s, st.wpc); + } + ret = nvs_get_u8(handle, CAMERA_PIXFORMAT_NVS_KEY, &pf); + if (ret == ESP_OK) { + s->set_pixformat(s, pf); + } + } else { + return ESP_ERR_CAMERA_NOT_DETECTED; + } + nvs_close(handle); + return ret; + } else { + ESP_LOGW(TAG, "Error (%d) opening nvs key \"%s\"", ret, key); + return ret; + } +} + +void esp_camera_return_all(void) { + if (s_state == NULL) { + return; + } + cam_give_all(); +} + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h new file mode 100644 index 0000000000..ce031c88d4 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h @@ -0,0 +1,251 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* + * Example Use + * + static camera_config_t camera_example_config = { + .pin_pwdn = PIN_PWDN, + .pin_reset = PIN_RESET, + .pin_xclk = PIN_XCLK, + .pin_sccb_sda = PIN_SIOD, + .pin_sccb_scl = PIN_SIOC, + .pin_d7 = PIN_D7, + .pin_d6 = PIN_D6, + .pin_d5 = PIN_D5, + .pin_d4 = PIN_D4, + .pin_d3 = PIN_D3, + .pin_d2 = PIN_D2, + .pin_d1 = PIN_D1, + .pin_d0 = PIN_D0, + .pin_vsync = PIN_VSYNC, + .pin_href = PIN_HREF, + .pin_pclk = PIN_PCLK, + + .xclk_freq_hz = 20000000, + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + .pixel_format = PIXFORMAT_JPEG, + .frame_size = FRAMESIZE_SVGA, + .jpeg_quality = 10, + .fb_count = 2, + .grab_mode = CAMERA_GRAB_WHEN_EMPTY + }; + + esp_err_t camera_example_init(){ + return esp_camera_init(&camera_example_config); + } + + esp_err_t camera_example_capture(){ + //capture a frame + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAG, "Frame buffer could not be acquired"); + return ESP_FAIL; + } + + //replace this with your own function + display_image(fb->width, fb->height, fb->pixformat, fb->buf, fb->len); + + //return the frame buffer back to be reused + esp_camera_fb_return(fb); + + return ESP_OK; + } +*/ + +#pragma once + +#include "esp_err.h" +#include "driver/ledc.h" +#include "sensor.h" +#include "sys/time.h" +#include "sdkconfig.h" + +/** + * @brief define for if chip supports camera + */ +#define ESP_CAMERA_SUPPORTED (CONFIG_IDF_TARGET_ESP32 | CONFIG_IDF_TARGET_ESP32S3 | \ + CONFIG_IDF_TARGET_ESP32S2) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configuration structure for camera initialization + */ +typedef enum { + CAMERA_GRAB_WHEN_EMPTY, /*!< Fills buffers when they are empty. Less resources but first 'fb_count' frames might be old */ + CAMERA_GRAB_LATEST /*!< Except when 1 frame buffer is used, queue will always contain the last 'fb_count' frames */ +} camera_grab_mode_t; + +/** + * @brief Camera frame buffer location + */ +typedef enum { + CAMERA_FB_IN_PSRAM, /*!< Frame buffer is placed in external PSRAM */ + CAMERA_FB_IN_DRAM /*!< Frame buffer is placed in internal DRAM */ +} camera_fb_location_t; + +#if CONFIG_CAMERA_CONVERTER_ENABLED +/** + * @brief Camera RGB\YUV conversion mode + */ +typedef enum { + CONV_DISABLE, + RGB565_TO_YUV422, + + YUV422_TO_RGB565, + YUV422_TO_YUV420 +} camera_conv_mode_t; +#endif + +/** + * @brief Configuration structure for camera initialization + */ +typedef struct { + int pin_pwdn; /*!< GPIO pin for camera power down line */ + int pin_reset; /*!< GPIO pin for camera reset line */ + int pin_xclk; /*!< GPIO pin for camera XCLK line */ + union { + int pin_sccb_sda; /*!< GPIO pin for camera SDA line */ + int pin_sscb_sda __attribute__((deprecated("please use pin_sccb_sda instead"))); /*!< GPIO pin for camera SDA line (legacy name) */ + }; + union { + int pin_sccb_scl; /*!< GPIO pin for camera SCL line */ + int pin_sscb_scl __attribute__((deprecated("please use pin_sccb_scl instead"))); /*!< GPIO pin for camera SCL line (legacy name) */ + }; + int pin_d7; /*!< GPIO pin for camera D7 line */ + int pin_d6; /*!< GPIO pin for camera D6 line */ + int pin_d5; /*!< GPIO pin for camera D5 line */ + int pin_d4; /*!< GPIO pin for camera D4 line */ + int pin_d3; /*!< GPIO pin for camera D3 line */ + int pin_d2; /*!< GPIO pin for camera D2 line */ + int pin_d1; /*!< GPIO pin for camera D1 line */ + int pin_d0; /*!< GPIO pin for camera D0 line */ + int pin_vsync; /*!< GPIO pin for camera VSYNC line */ + int pin_href; /*!< GPIO pin for camera HREF line */ + int pin_pclk; /*!< GPIO pin for camera PCLK line */ + + int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode */ + + ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */ + ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */ + + pixformat_t pixel_format; /*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */ + framesize_t frame_size; /*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */ + + int jpeg_quality; /*!< Quality of JPEG output. 0-63 lower means higher quality */ + size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */ + camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */ + camera_grab_mode_t grab_mode; /*!< When buffers should be filled */ +#if CONFIG_CAMERA_CONVERTER_ENABLED + camera_conv_mode_t conv_mode; /*!< RGB<->YUV Conversion mode */ +#endif + + int sccb_i2c_port; /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */ +} camera_config_t; + +/** + * @brief Data structure of camera frame buffer + */ +typedef struct { + uint8_t * buf; /*!< Pointer to the pixel data */ + size_t len; /*!< Length of the buffer in bytes */ + size_t width; /*!< Width of the buffer in pixels */ + size_t height; /*!< Height of the buffer in pixels */ + pixformat_t format; /*!< Format of the pixel data */ + struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */ +} camera_fb_t; + +#define ESP_ERR_CAMERA_BASE 0x20000 +#define ESP_ERR_CAMERA_NOT_DETECTED (ESP_ERR_CAMERA_BASE + 1) +#define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2) +#define ESP_ERR_CAMERA_FAILED_TO_SET_OUT_FORMAT (ESP_ERR_CAMERA_BASE + 3) +#define ESP_ERR_CAMERA_NOT_SUPPORTED (ESP_ERR_CAMERA_BASE + 4) + +/** + * @brief Initialize the camera driver + * + * @note call camera_probe before calling this function + * + * This function detects and configures camera over I2C interface, + * allocates framebuffer and DMA buffers, + * initializes parallel I2S input, and sets up DMA descriptors. + * + * Currently this function can only be called once and there is + * no way to de-initialize this module. + * + * @param config Camera configuration parameters + * + * @return ESP_OK on success + */ +esp_err_t esp_camera_init(const camera_config_t* config); + +/** + * @brief Deinitialize the camera driver + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet + */ +esp_err_t esp_camera_deinit(void); + +/** + * @brief Obtain pointer to a frame buffer. + * + * @return pointer to the frame buffer + */ +camera_fb_t* esp_camera_fb_get(void); + +/** + * @brief Return the frame buffer to be reused again. + * + * @param fb Pointer to the frame buffer + */ +void esp_camera_fb_return(camera_fb_t * fb); + +/** + * @brief Get a pointer to the image sensor control structure + * + * @return pointer to the sensor + */ +sensor_t * esp_camera_sensor_get(void); + +/** + * @brief Save camera settings to non-volatile-storage (NVS) + * + * @param key A unique nvs key name for the camera settings + */ +esp_err_t esp_camera_save_to_nvs(const char *key); + +/** + * @brief Load camera settings from non-volatile-storage (NVS) + * + * @param key A unique nvs key name for the camera settings + */ +esp_err_t esp_camera_load_from_nvs(const char *key); + +/** + * @brief Return all frame buffers to be reused again. + */ +void esp_camera_return_all(void); + + +#ifdef __cplusplus +} +#endif + +#include "img_converters.h" + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h new file mode 100644 index 0000000000..6ab12a21aa --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h @@ -0,0 +1,261 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Sensor abstraction layer. + * + */ +#ifndef __SENSOR_H__ +#define __SENSOR_H__ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + OV9650_PID = 0x96, + OV7725_PID = 0x77, + OV2640_PID = 0x26, + OV3660_PID = 0x3660, + OV5640_PID = 0x5640, + OV7670_PID = 0x76, + NT99141_PID = 0x1410, + GC2145_PID = 0x2145, + GC032A_PID = 0x232a, + GC0308_PID = 0x9b, + BF3005_PID = 0x30, + BF20A6_PID = 0x20a6, + SC101IOT_PID = 0xda4a, + SC030IOT_PID = 0x9a46, + SC031GS_PID = 0x0031, +} camera_pid_t; + +typedef enum { + CAMERA_OV7725, + CAMERA_OV2640, + CAMERA_OV3660, + CAMERA_OV5640, + CAMERA_OV7670, + CAMERA_NT99141, + CAMERA_GC2145, + CAMERA_GC032A, + CAMERA_GC0308, + CAMERA_BF3005, + CAMERA_BF20A6, + CAMERA_SC101IOT, + CAMERA_SC030IOT, + CAMERA_SC031GS, + CAMERA_MODEL_MAX, + CAMERA_NONE, +} camera_model_t; + +typedef enum { + OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1 + OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1 + OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1 + OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1 + NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1 + GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1 + GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1 + GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1 + BF3005_SCCB_ADDR = 0x6E, + BF20A6_SCCB_ADDR = 0x6E, + SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 + SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 + SC031GS_SCCB_ADDR = 0x30, +} camera_sccb_addr_t; + +typedef enum { + PIXFORMAT_RGB565, // 2BPP/RGB565 + PIXFORMAT_YUV422, // 2BPP/YUV422 + PIXFORMAT_YUV420, // 1.5BPP/YUV420 + PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE + PIXFORMAT_JPEG, // JPEG/COMPRESSED + PIXFORMAT_RGB888, // 3BPP/RGB888 + PIXFORMAT_RAW, // RAW + PIXFORMAT_RGB444, // 3BP2P/RGB444 + PIXFORMAT_RGB555, // 3BP2P/RGB555 +} pixformat_t; + +typedef enum { + FRAMESIZE_96X96, // 96x96 + FRAMESIZE_QQVGA, // 160x120 + FRAMESIZE_QCIF, // 176x144 + FRAMESIZE_HQVGA, // 240x176 + FRAMESIZE_240X240, // 240x240 + FRAMESIZE_QVGA, // 320x240 + FRAMESIZE_CIF, // 400x296 + FRAMESIZE_HVGA, // 480x320 + FRAMESIZE_VGA, // 640x480 + FRAMESIZE_SVGA, // 800x600 + FRAMESIZE_XGA, // 1024x768 + FRAMESIZE_HD, // 1280x720 + FRAMESIZE_SXGA, // 1280x1024 + FRAMESIZE_UXGA, // 1600x1200 + // 3MP Sensors + FRAMESIZE_FHD, // 1920x1080 + FRAMESIZE_P_HD, // 720x1280 + FRAMESIZE_P_3MP, // 864x1536 + FRAMESIZE_QXGA, // 2048x1536 + // 5MP Sensors + FRAMESIZE_QHD, // 2560x1440 + FRAMESIZE_WQXGA, // 2560x1600 + FRAMESIZE_P_FHD, // 1080x1920 + FRAMESIZE_QSXGA, // 2560x1920 + FRAMESIZE_INVALID +} framesize_t; + +typedef struct { + const camera_model_t model; + const char *name; + const camera_sccb_addr_t sccb_addr; + const camera_pid_t pid; + const framesize_t max_size; + const bool support_jpeg; +} camera_sensor_info_t; + +typedef enum { + ASPECT_RATIO_4X3, + ASPECT_RATIO_3X2, + ASPECT_RATIO_16X10, + ASPECT_RATIO_5X3, + ASPECT_RATIO_16X9, + ASPECT_RATIO_21X9, + ASPECT_RATIO_5X4, + ASPECT_RATIO_1X1, + ASPECT_RATIO_9X16 +} aspect_ratio_t; + +typedef enum { + GAINCEILING_2X, + GAINCEILING_4X, + GAINCEILING_8X, + GAINCEILING_16X, + GAINCEILING_32X, + GAINCEILING_64X, + GAINCEILING_128X, +} gainceiling_t; + +typedef struct { + uint16_t max_width; + uint16_t max_height; + uint16_t start_x; + uint16_t start_y; + uint16_t end_x; + uint16_t end_y; + uint16_t offset_x; + uint16_t offset_y; + uint16_t total_x; + uint16_t total_y; +} ratio_settings_t; + +typedef struct { + const uint16_t width; + const uint16_t height; + const aspect_ratio_t aspect_ratio; +} resolution_info_t; + +// Resolution table (in sensor.c) +extern const resolution_info_t resolution[]; +// camera sensor table (in sensor.c) +extern const camera_sensor_info_t camera_sensor[]; + +typedef struct { + uint8_t MIDH; + uint8_t MIDL; + uint16_t PID; + uint8_t VER; +} sensor_id_t; + +typedef struct { + framesize_t framesize;//0 - 10 + bool scale; + bool binning; + uint8_t quality;//0 - 63 + int8_t brightness;//-2 - 2 + int8_t contrast;//-2 - 2 + int8_t saturation;//-2 - 2 + int8_t sharpness;//-2 - 2 + uint8_t denoise; + uint8_t special_effect;//0 - 6 + uint8_t wb_mode;//0 - 4 + uint8_t awb; + uint8_t awb_gain; + uint8_t aec; + uint8_t aec2; + int8_t ae_level;//-2 - 2 + uint16_t aec_value;//0 - 1200 + uint8_t agc; + uint8_t agc_gain;//0 - 30 + uint8_t gainceiling;//0 - 6 + uint8_t bpc; + uint8_t wpc; + uint8_t raw_gma; + uint8_t lenc; + uint8_t hmirror; + uint8_t vflip; + uint8_t dcw; + uint8_t colorbar; +} camera_status_t; + +typedef struct _sensor sensor_t; +typedef struct _sensor { + sensor_id_t id; // Sensor ID. + uint8_t slv_addr; // Sensor I2C slave address. + pixformat_t pixformat; + camera_status_t status; + int xclk_freq_hz; + + // Sensor function pointers + int (*init_status) (sensor_t *sensor); + int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful + int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat); + int (*set_framesize) (sensor_t *sensor, framesize_t framesize); + int (*set_contrast) (sensor_t *sensor, int level); + int (*set_brightness) (sensor_t *sensor, int level); + int (*set_saturation) (sensor_t *sensor, int level); + int (*set_sharpness) (sensor_t *sensor, int level); + int (*set_denoise) (sensor_t *sensor, int level); + int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling); + int (*set_quality) (sensor_t *sensor, int quality); + int (*set_colorbar) (sensor_t *sensor, int enable); + int (*set_whitebal) (sensor_t *sensor, int enable); + int (*set_gain_ctrl) (sensor_t *sensor, int enable); + int (*set_exposure_ctrl) (sensor_t *sensor, int enable); + int (*set_hmirror) (sensor_t *sensor, int enable); + int (*set_vflip) (sensor_t *sensor, int enable); + + int (*set_aec2) (sensor_t *sensor, int enable); + int (*set_awb_gain) (sensor_t *sensor, int enable); + int (*set_agc_gain) (sensor_t *sensor, int gain); + int (*set_aec_value) (sensor_t *sensor, int gain); + + int (*set_special_effect) (sensor_t *sensor, int effect); + int (*set_wb_mode) (sensor_t *sensor, int mode); + int (*set_ae_level) (sensor_t *sensor, int level); + + int (*set_dcw) (sensor_t *sensor, int enable); + int (*set_bpc) (sensor_t *sensor, int enable); + int (*set_wpc) (sensor_t *sensor, int enable); + + int (*set_raw_gma) (sensor_t *sensor, int enable); + int (*set_lenc) (sensor_t *sensor, int enable); + + int (*get_reg) (sensor_t *sensor, int reg, int mask); + int (*set_reg) (sensor_t *sensor, int reg, int mask, int value); + int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning); + int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk); + int (*set_xclk) (sensor_t *sensor, int timer, int xclk); +} sensor_t; + +camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id); + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_H__ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h new file mode 100644 index 0000000000..cd0d3aaeec --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h @@ -0,0 +1,62 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "esp_camera.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Uninitialize the lcd_cam module + * + * @param handle Provide handle pointer to release resources + * + * @return + * - ESP_OK Success + * - ESP_FAIL Uninitialize fail + */ +esp_err_t cam_deinit(void); + +/** + * @brief Initialize the lcd_cam module + * + * @param config Configurations - see lcd_cam_config_t struct + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM No memory to initialize lcd_cam + * - ESP_FAIL Initialize fail + */ +esp_err_t cam_init(const camera_config_t *config); + +esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid); + +void cam_stop(void); + +void cam_start(void); + +camera_fb_t *cam_take(TickType_t timeout); + +void cam_give(camera_fb_t *dma_buffer); + +void cam_give_all(void); + +#ifdef __cplusplus +} +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h new file mode 100644 index 0000000000..f000fba112 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h @@ -0,0 +1,22 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * SCCB (I2C like) driver. + * + */ +#ifndef __SCCB_H__ +#define __SCCB_H__ +#include +int SCCB_Init(int pin_sda, int pin_scl); +int SCCB_Use_Port(int sccb_i2c_port); +int SCCB_Deinit(void); +uint8_t SCCB_Probe(void); +uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); +int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); +uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); +int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); +uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg); +int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data); +#endif // __SCCB_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h new file mode 100644 index 0000000000..922cd7029d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h @@ -0,0 +1,10 @@ +#pragma once + +#include "esp_system.h" +#include "esp_camera.h" + +esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz); + +esp_err_t camera_enable_out_clock(const camera_config_t *config); + +void camera_disable_out_clock(void); diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c new file mode 100644 index 0000000000..307166d0fb --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c @@ -0,0 +1,260 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * SCCB (I2C like) driver. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "sensor.h" +#include +#include "sdkconfig.h" +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "sccb"; +#endif + +#define LITTLETOBIG(x) ((x<<8)|(x>>8)) + +#include "driver/i2c.h" + +// support IDF 5.x +#ifndef portTICK_RATE_MS +#define portTICK_RATE_MS portTICK_PERIOD_MS +#endif + +#define SCCB_FREQ CONFIG_SCCB_CLK_FREQ /*!< I2C master frequency*/ +#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ +#define READ_BIT I2C_MASTER_READ /*!< I2C master read */ +#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ +#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ +#define ACK_VAL 0x0 /*!< I2C ack value */ +#define NACK_VAL 0x1 /*!< I2C nack value */ +#if CONFIG_SCCB_HARDWARE_I2C_PORT1 +const int SCCB_I2C_PORT_DEFAULT = 1; +#else +const int SCCB_I2C_PORT_DEFAULT = 0; +#endif + +static int sccb_i2c_port; +static bool sccb_owns_i2c_port; + +int SCCB_Init(int pin_sda, int pin_scl) +{ + ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); + i2c_config_t conf; + esp_err_t ret; + + memset(&conf, 0, sizeof(i2c_config_t)); + + sccb_i2c_port = SCCB_I2C_PORT_DEFAULT; + sccb_owns_i2c_port = true; + ESP_LOGI(TAG, "sccb_i2c_port=%d", sccb_i2c_port); + + conf.mode = I2C_MODE_MASTER; + conf.sda_io_num = pin_sda; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + conf.scl_io_num = pin_scl; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + conf.master.clk_speed = SCCB_FREQ; + + if ((ret = i2c_param_config(sccb_i2c_port, &conf)) != ESP_OK) { + return ret; + } + + return i2c_driver_install(sccb_i2c_port, conf.mode, 0, 0, 0); +} + +int SCCB_Use_Port(int i2c_num) { // sccb use an already initialized I2C port + if (sccb_owns_i2c_port) { + SCCB_Deinit(); + } + if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) { + return ESP_ERR_INVALID_ARG; + } + sccb_i2c_port = i2c_num; + return ESP_OK; +} + +int SCCB_Deinit(void) +{ + if (!sccb_owns_i2c_port) { + return ESP_OK; + } + sccb_owns_i2c_port = false; + return i2c_driver_delete(sccb_i2c_port); +} + +uint8_t SCCB_Probe(void) +{ + uint8_t slave_addr = 0x0; + + for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { + if (slave_addr == camera_sensor[i].sccb_addr) { + continue; + } + slave_addr = camera_sensor[i].sccb_addr; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_stop(cmd); + esp_err_t ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if( ret == ESP_OK) { + return slave_addr; + } + } + return 0; +} + +uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) +{ + uint8_t data=0; + esp_err_t ret = ESP_FAIL; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) return -1; + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); + i2c_master_read_byte(cmd, &data, NACK_VAL); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); + } + return data; +} + +int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) +{ + esp_err_t ret = ESP_FAIL; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); + i2c_master_write_byte(cmd, data, ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); + } + return ret == ESP_OK ? 0 : -1; +} + +uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) +{ + uint8_t data=0; + esp_err_t ret = ESP_FAIL; + uint16_t reg_htons = LITTLETOBIG(reg); + uint8_t *reg_u8 = (uint8_t *)®_htons; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) return -1; + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); + i2c_master_read_byte(cmd, &data, NACK_VAL); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); + } + return data; +} + +int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) +{ + static uint16_t i = 0; + esp_err_t ret = ESP_FAIL; + uint16_t reg_htons = LITTLETOBIG(reg); + uint8_t *reg_u8 = (uint8_t *)®_htons; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); + i2c_master_write_byte(cmd, data, ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); + } + return ret == ESP_OK ? 0 : -1; +} + +uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg) +{ + uint16_t data = 0; + uint8_t *data_u8 = (uint8_t *)&data; + esp_err_t ret = ESP_FAIL; + uint16_t reg_htons = LITTLETOBIG(reg); + uint8_t *reg_u8 = (uint8_t *)®_htons; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) return -1; + + cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); + i2c_master_read_byte(cmd, &data_u8[1], ACK_VAL); + i2c_master_read_byte(cmd, &data_u8[0], NACK_VAL); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); + } + return data; +} + +int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data) +{ + esp_err_t ret = ESP_FAIL; + uint16_t reg_htons = LITTLETOBIG(reg); + uint8_t *reg_u8 = (uint8_t *)®_htons; + uint16_t data_htons = LITTLETOBIG(data); + uint8_t *data_u8 = (uint8_t *)&data_htons; + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); + i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); + i2c_master_write_byte(cmd, data_u8[0], ACK_CHECK_EN); + i2c_master_write_byte(cmd, data_u8[1], ACK_CHECK_EN); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); + i2c_cmd_link_delete(cmd); + if(ret != ESP_OK) { + ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); + } + return ret == ESP_OK ? 0 : -1; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c new file mode 100644 index 0000000000..23071f6c2c --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c @@ -0,0 +1,57 @@ +#include +#include "sensor.h" + +const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { + // The sequence must be consistent with camera_model_t + {CAMERA_OV7725, "OV7725", OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA, false}, + {CAMERA_OV2640, "OV2640", OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA, true}, + {CAMERA_OV3660, "OV3660", OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA, true}, + {CAMERA_OV5640, "OV5640", OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA, true}, + {CAMERA_OV7670, "OV7670", OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA, false}, + {CAMERA_NT99141, "NT99141", NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD, true}, + {CAMERA_GC2145, "GC2145", GC2145_SCCB_ADDR, GC2145_PID, FRAMESIZE_UXGA, false}, + {CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false}, + {CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false}, + {CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false}, + {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false}, + {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false}, + {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false}, + {CAMERA_SC031GS, "SC031GS", SC031GS_SCCB_ADDR, SC031GS_PID, FRAMESIZE_VGA, false}, +}; + +const resolution_info_t resolution[FRAMESIZE_INVALID] = { + { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ + { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ + { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ + { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ + { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ + { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ + { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ + { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ + { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ + { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ + { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ + { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ + { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ + { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ + // 3MP Sensors + { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ + { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ + { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ + { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ + // 5MP Sensors + { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ + { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ + { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ + { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ +}; + +camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id) +{ + for (int i = 0; i < CAMERA_MODEL_MAX; i++) { + if (id->PID == camera_sensor[i].pid) { + return (camera_sensor_info_t *)&camera_sensor[i]; + } + } + return NULL; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt new file mode 100644 index 0000000000..0a03968845 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt @@ -0,0 +1,9 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS "../") + +add_compile_options(-fdiagnostics-color=always) +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(camera_example) \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile new file mode 100644 index 0000000000..f06df0ecc9 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile @@ -0,0 +1,11 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := camera_example + +EXTRA_COMPONENT_DIRS := ../ + +include $(IDF_PATH)/make/project.mk + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt new file mode 100644 index 0000000000..1735fb184b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt @@ -0,0 +1,3 @@ +set(COMPONENT_SRCS take_picture.c) +set(COMPONENT_ADD_INCLUDEDIRS .) +register_component() \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk new file mode 100644 index 0000000000..0b9d7585e7 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c new file mode 100644 index 0000000000..3a243d2554 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c @@ -0,0 +1,167 @@ +/** + * This example takes a picture every 5s and print its size on serial monitor. + */ + +// =============================== SETUP ====================================== + +// 1. Board setup (Uncomment): +// #define BOARD_WROVER_KIT +// #define BOARD_ESP32CAM_AITHINKER + +/** + * 2. Kconfig setup + * + * If you have a Kconfig file, copy the content from + * https://github.com/espressif/esp32-camera/blob/master/Kconfig into it. + * In case you haven't, copy and paste this Kconfig file inside the src directory. + * This Kconfig file has definitions that allows more control over the camera and + * how it will be initialized. + */ + +/** + * 3. Enable PSRAM on sdkconfig: + * + * CONFIG_ESP32_SPIRAM_SUPPORT=y + * + * More info on + * https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support + */ + +// ================================ CODE ====================================== + +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +// support IDF 5.x +#ifndef portTICK_RATE_MS +#define portTICK_RATE_MS portTICK_PERIOD_MS +#endif + +#include "esp_camera.h" + +#define BOARD_WROVER_KIT 1 + +// WROVER-KIT PIN Map +#ifdef BOARD_WROVER_KIT + +#define CAM_PIN_PWDN -1 //power down is not used +#define CAM_PIN_RESET -1 //software reset will be performed +#define CAM_PIN_XCLK 21 +#define CAM_PIN_SIOD 26 +#define CAM_PIN_SIOC 27 + +#define CAM_PIN_D7 35 +#define CAM_PIN_D6 34 +#define CAM_PIN_D5 39 +#define CAM_PIN_D4 36 +#define CAM_PIN_D3 19 +#define CAM_PIN_D2 18 +#define CAM_PIN_D1 5 +#define CAM_PIN_D0 4 +#define CAM_PIN_VSYNC 25 +#define CAM_PIN_HREF 23 +#define CAM_PIN_PCLK 22 + +#endif + +// ESP32Cam (AiThinker) PIN Map +#ifdef BOARD_ESP32CAM_AITHINKER + +#define CAM_PIN_PWDN 32 +#define CAM_PIN_RESET -1 //software reset will be performed +#define CAM_PIN_XCLK 0 +#define CAM_PIN_SIOD 26 +#define CAM_PIN_SIOC 27 + +#define CAM_PIN_D7 35 +#define CAM_PIN_D6 34 +#define CAM_PIN_D5 39 +#define CAM_PIN_D4 36 +#define CAM_PIN_D3 21 +#define CAM_PIN_D2 19 +#define CAM_PIN_D1 18 +#define CAM_PIN_D0 5 +#define CAM_PIN_VSYNC 25 +#define CAM_PIN_HREF 23 +#define CAM_PIN_PCLK 22 + +#endif + +static const char *TAG = "example:take_picture"; + +#if ESP_CAMERA_SUPPORTED +static camera_config_t camera_config = { + .pin_pwdn = CAM_PIN_PWDN, + .pin_reset = CAM_PIN_RESET, + .pin_xclk = CAM_PIN_XCLK, + .pin_sccb_sda = CAM_PIN_SIOD, + .pin_sccb_scl = CAM_PIN_SIOC, + + .pin_d7 = CAM_PIN_D7, + .pin_d6 = CAM_PIN_D6, + .pin_d5 = CAM_PIN_D5, + .pin_d4 = CAM_PIN_D4, + .pin_d3 = CAM_PIN_D3, + .pin_d2 = CAM_PIN_D2, + .pin_d1 = CAM_PIN_D1, + .pin_d0 = CAM_PIN_D0, + .pin_vsync = CAM_PIN_VSYNC, + .pin_href = CAM_PIN_HREF, + .pin_pclk = CAM_PIN_PCLK, + + //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) + .xclk_freq_hz = 20000000, + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + + .pixel_format = PIXFORMAT_RGB565, //YUV422,GRAYSCALE,RGB565,JPEG + .frame_size = FRAMESIZE_QVGA, //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. + + .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality + .fb_count = 1, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. + .grab_mode = CAMERA_GRAB_WHEN_EMPTY, +}; + +static esp_err_t init_camera(void) +{ + //initialize the camera + esp_err_t err = esp_camera_init(&camera_config); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "Camera Init Failed"); + return err; + } + + return ESP_OK; +} +#endif + +void app_main(void) +{ +#if ESP_CAMERA_SUPPORTED + if(ESP_OK != init_camera()) { + return; + } + + while (1) + { + ESP_LOGI(TAG, "Taking picture..."); + camera_fb_t *pic = esp_camera_fb_get(); + + // use pic->buf to access the image + ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len); + esp_camera_fb_return(pic); + + vTaskDelay(5000 / portTICK_RATE_MS); + } +#else + ESP_LOGE(TAG, "Camera support is not available for this chip"); + return; +#endif +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults new file mode 100644 index 0000000000..e5ac4557ac --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults @@ -0,0 +1,17 @@ +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y + +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_PARTITION_TABLE_OFFSET=0x10000 + +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y + +CONFIG_SPIRAM_SUPPORT=y +CONFIG_ESP32_SPIRAM_SUPPORT=y +CONFIG_ESP32S2_SPIRAM_SUPPORT=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_SPEED_80M=y + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml new file mode 100644 index 0000000000..2b98f8d06c --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml @@ -0,0 +1,2 @@ +description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors. +url: https://github.com/espressif/esp32-camera diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json b/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json new file mode 100644 index 0000000000..1b367ee04b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json @@ -0,0 +1,26 @@ +{ + "name": "esp32-camera", + "version": "2.0.0", + "keywords": "esp32, camera, espressif, esp32-cam", + "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", + "repository": { + "type": "git", + "url": "https://github.com/espressif/esp32-camera" + }, + "frameworks": "espidf", + "platforms": "*", + "build": { + "flags": [ + "-Idriver/include", + "-Iconversions/include", + "-Idriver/private_include", + "-Iconversions/private_include", + "-Isensors/private_include", + "-Itarget/private_include", + "-fno-rtti" + ], + "includeDir": ".", + "srcDir": ".", + "srcFilter": ["-<*>", "+", "+", "+"] + } +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c new file mode 100644 index 0000000000..f8eb127d54 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c @@ -0,0 +1,410 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sccb.h" +#include "bf20a6.h" +#include "bf20a6_regs.h" +#include "bf20a6_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "bf20a6"; +#endif + +#define H8(v) ((v)>>8) +#define L8(v) ((v)&0xff) + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read(slv_addr, reg); + // ESP_LOGI(TAG, "READ Register 0x%02x VALUE: 0x%02x", reg, ret); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = SCCB_Write(slv_addr, reg, value); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +#ifdef DEBUG_PRINT_REG +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static void print_regs(uint8_t slv_addr) +{ + vTaskDelay(pdMS_TO_TICKS(100)); + ESP_LOGI(TAG, "REG list look ======================"); + for (size_t i = 0xf0; i <= 0xfe; i++) { + ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 0 ==="); + write_reg(slv_addr, 0xfe, 0x00); // page 0 + for (size_t i = 0x03; i <= 0x24; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + for (size_t i = 0x40; i <= 0x95; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 3 ==="); + write_reg(slv_addr, 0xfe, 0x03); // page 3 + for (size_t i = 0x01; i <= 0x43; i++) { + ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } +} + +static int read_regs(uint8_t slv_addr, const uint16_t(*regs)[2]) +{ + int i = 0, ret = 0; + while (regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = read_reg(slv_addr, regs[i][0]); + } + i++; + } + return ret; +} +#endif + +static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + + ret = SCCB_Read(sensor->slv_addr, reg); + if (ret < 0) { + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t(*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static int reset(sensor_t *sensor) +{ + int ret; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, RESET_RELATED, 0x01); + if (ret) { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + + ret = write_regs(sensor->slv_addr, bf20a6_default_init_regs); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + // int test_value = read_regs(sensor->slv_addr, bf20a6_default_init_regs); + + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + switch (pixformat) { + case PIXFORMAT_YUV422: + set_reg_bits(sensor, 0x12, 0, 1, 0); + break; + case PIXFORMAT_RAW: + set_reg_bits(sensor, 0x12, 0, 1, 0x1); + break; + case PIXFORMAT_GRAYSCALE: + write_reg(sensor->slv_addr, 0x12, 0x23); + write_reg(sensor->slv_addr, 0x3a, 0x00); + write_reg(sensor->slv_addr, 0xe1, 0x92); + write_reg(sensor->slv_addr, 0xe3, 0x02); + break; + default: + ESP_LOGW(TAG, "set_pix unsupport format"); + ret = -1; + break; + } + if (ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + if (framesize > FRAMESIZE_VGA) { + return -1; + } + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + + sensor->status.framesize = framesize; + + // Write MSBs + ret |= SCCB_Write(sensor->slv_addr, 0x17, 0); + ret |= SCCB_Write(sensor->slv_addr, 0x18, w >> 2); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, 0); + ret |= SCCB_Write(sensor->slv_addr, 0x1a, h >> 2); + + // Write LSBs + ret |= SCCB_Write(sensor->slv_addr, 0x1b, 0); + + if ((w <= 320) && (h <= 240)) { + ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 4)); + ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 4)); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 4)); + + ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 4)); + + } else if ((w <= 640) && (h <= 480)) { + ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 8)); + ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 8)); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 8)); + + ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 8)); + } + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + //ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor, 0x4a, 3, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + //ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor, 0x4a, 2, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int value) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, 0xb6, value); + if (ret == 0) { + sensor->status.colorbar = value; + ESP_LOGD(TAG, "Set colorbar to: %d", value); + } + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x70, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set sharpness to: %d", level); + sensor->status.sharpness = level; + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret > 0) { + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret < 0) { + return ret; + } + value = (ret & ~mask) | (value & mask); + + if (mask > 0xFF) { + + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + // write_reg(sensor->slv_addr, 0xfe, 0x00); + sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x6f); + sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0xd6); + sensor->status.saturation = 0; + sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70); + sensor->status.denoise = 0; + sensor->status.ae_level = 0; + sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x13); + sensor->status.awb = 0; + sensor->status.dcw = 0; + sensor->status.agc = 0; + sensor->status.aec = 0; + sensor->status.hmirror = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01); + sensor->status.vflip = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02); + sensor->status.colorbar = 0; + sensor->status.bpc = 0; + sensor->status.wpc = 0; + sensor->status.raw_gma = 0; + sensor->status.lenc = 0; + sensor->status.quality = 0; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = 0; + sensor->status.agc_gain = 0; + sensor->status.aec_value = 0; + sensor->status.aec2 = 0; + return 0; +} + +static int set_dummy(sensor_t *sensor, int val) +{ + ESP_LOGW(TAG, "dummy Unsupported"); + return -1; +} +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) +{ + ESP_LOGW(TAG, "gainceiling Unsupported"); + return -1; +} + +int bf20a6_detect(int slv_addr, sensor_id_t *id) +{ + if (BF20A6_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW); + uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH); + uint16_t PID = MIDH << 8 | MIDL; + if (BF20A6_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int bf20a6_init(sensor_t *sensor) +{ + sensor->init_status = init_status; + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_dummy; + sensor->set_brightness = set_dummy; + sensor->set_saturation = set_dummy; + sensor->set_sharpness = set_sharpness; + sensor->set_denoise = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_quality = set_dummy; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_dummy; + sensor->set_gain_ctrl = set_dummy; + sensor->set_exposure_ctrl = set_dummy; + sensor->set_hmirror = set_hmirror; // set_hmirror; + sensor->set_vflip = set_vflip; // set_vflip; + + sensor->set_aec2 = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_aec_value = set_dummy; + + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = NULL; + sensor->set_pll = NULL; + sensor->set_xclk = NULL; + + ESP_LOGD(TAG, "BF20A6 Attached"); + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c new file mode 100644 index 0000000000..2da7594a70 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c @@ -0,0 +1,541 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * BF3005 driver. + * + * Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "bf3005.h" +#include "bf3005_regs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "bf3005"; +#endif + +static const uint8_t default_regs[][2] = { + {0x12, 0x40}, //soft reset + {0xff, 0xff}, //delay + {0xff, 0xff}, //delay + {0xff, 0xff}, //delay + {0xff, 0xff}, //delay + {0x13, 0x10}, + {0x8c, 0x00}, + {0x8d, 0x64}, + {0x87, 0x10}, + {0x13, 0x17}, + {0x00, 0x20}, + {0x01, 0x1a}, + {0x02, 0x22}, + {0x09, 0x03}, + {0x0c, 0x80}, + {0x0d, 0x24}, + {0x0e, 0x21}, + {0x0f, 0x28}, + {0x11, 0x08}, + {0x15, 0x10}, // 0X10 + {0x16, 0x03}, + {0x1e, 0x30}, + {0x20, 0x8a}, + {0x21, 0x03}, + {0x23, 0x55}, + {0x24, 0x68}, + {0x25, 0x78}, + {0x2a, 0x00}, + {0x2b, 0x00}, + {0x2d, 0x4f}, + {0x2e, 0x98}, + {0x2f, 0x04}, + {0x30, 0xad}, + {0x31, 0x17}, + {0x32, 0x6e}, + {0x33, 0x20}, + {0x35, 0xa6}, + {0x3b, 0x00}, + {0x3e, 0x00}, + {0x3f, 0xA8}, + {0x40, 0x38}, + {0x41, 0x32}, + {0x42, 0x2b}, + {0x43, 0x26}, + {0x44, 0x1a}, + {0x45, 0x16}, + {0x46, 0x10}, + {0x47, 0x0f}, + {0x48, 0x0c}, + {0x49, 0x0a}, + {0x4b, 0x09}, + {0x4c, 0x08}, + {0x4d, 0x3c}, + {0x4e, 0x06}, + {0x4f, 0x05}, + {0x50, 0x03}, + {0x51, 0x25}, + {0x52, 0x88}, + {0x53, 0x03}, + {0x63, 0x20}, + {0x64, 0x02}, + {0x65, 0xa6}, + {0x66, 0xb6}, + {0x69, 0x00}, + {0x70, 0xFF}, + {0x71, 0xa6}, + {0x72, 0x2f}, + {0x73, 0x2f}, + {0x74, 0x2F}, + {0x75, 0x0e}, + {0x76, 0x1e}, + {0x77, 0x00}, + {0x78, 0x1e}, + {0x79, 0x8a}, + {0x7d, 0xe2}, + {0x80, 0x44}, + {0x81, 0x00}, + {0x82, 0x18}, + {0x83, 0x1b}, + {0x84, 0x24}, + {0x85, 0x2a}, + {0x86, 0x4f}, + {0x89, 0x82}, //0x82 + {0x8b, 0x02}, + {0x8e, 0x03}, + {0x8f, 0xFC}, + {0x9d, 0x4d}, + {0x9e, 0x41}, + {0xa1, 0x21}, + {0xa2, 0x12}, + {0xa3, 0x32}, + {0xa4, 0x05}, + {0xa5, 0x32}, + {0xa6, 0x04}, + {0xa7, 0x7f}, + {0xa8, 0x7f}, + {0xa9, 0x21}, + {0xaa, 0x21}, + {0xab, 0x21}, + {0xac, 0x0a}, + {0xad, 0xf0}, + {0xae, 0xff}, + {0xaf, 0x1d}, + {0xb0, 0x94}, + {0xb1, 0xc0}, + {0xb2, 0xc0}, + {0xd2, 0x30}, + {0xe0, 0x0d}, + {0xe1, 0x44}, + {0xe7, 0x7c}, + {0xe8, 0x89}, + {0xe9, 0x01}, + {0xea, 0x01}, + {0xf0, 0x01}, + {0xf3, 0x49}, + {0xf4, 0xff}, + {0xf5, 0x01}, + {0xf6, 0xf2}, + {0xf7, 0x6f}, + {0x1b, 0x80}, + {0x00, 0x00}, +}; + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); + return ret; +} + +static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); + return ret; +} + +static int get_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + return (ret & mask) >> offset; +} + + +static int reset(sensor_t *sensor) +{ + int i=0; + const uint8_t (*regs)[2]; + + // Write default regsiters + for (i=0, regs = default_regs; regs[i][0]; i++) { + SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); + } + + // Delay + vTaskDelay(50 / portTICK_PERIOD_MS); + + return 0; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret=0; + sensor->pixformat = pixformat; + + switch (pixformat) { + case PIXFORMAT_RGB565: + set_reg_bits(sensor, 0x12, 2, 1, 1); + break; + case PIXFORMAT_RAW: + set_reg_bits(sensor, 0x12, 0, 3, 0x4); + break; + case PIXFORMAT_YUV422: + case PIXFORMAT_GRAYSCALE: + set_reg_bits(sensor, 0x12, 2, 1, 0); + break; + default: + return -1; + } + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret=0; + if (framesize > FRAMESIZE_VGA) { + return -1; + } + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + // uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); + + sensor->status.framesize = framesize; + + // Write MSBs + ret |= SCCB_Write(sensor->slv_addr, 0x17, 0); + ret |= SCCB_Write(sensor->slv_addr, 0x18, w>>2); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, 0); + ret |= SCCB_Write(sensor->slv_addr, 0x1a, h>>2); + + // Write LSBs + ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); + printf("%s %d\r\n", __func__, __LINE__); + if((w<=320)&&(h<=240)) + { + printf("%s %d\r\n", __func__, __LINE__); + // Enable auto-scaling/zooming factors + //ret |= SCCB_Write(sensor->slv_addr, 0x12, 0x50); + set_reg_bits(sensor, 0x12, 4, 1, 1); + + ret |= SCCB_Write(sensor->slv_addr, 0x17, (80-w/4)); + ret |= SCCB_Write(sensor->slv_addr, 0x18, (80+w/4)); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, (60-h/4)); + + ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60+h/4)); + ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); + + } else if((w<=640)&&(h<=480)) + { + // Enable auto-scaling/zooming factors + //ret |= SCCB_Write(sensor->slv_addr, 0x12, 0x40); + set_reg_bits(sensor, 0x12, 4, 1, 0); + + ret |= SCCB_Write(sensor->slv_addr, 0x17, (80-w/8)); + ret |= SCCB_Write(sensor->slv_addr, 0x18, (80+w/8)); + + ret |= SCCB_Write(sensor->slv_addr, 0x19, (60-h/8)); + + ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60+h/8)); + ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); + } + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int value) +{ + int ret=0; + sensor->status.colorbar = value; + + ret |= SCCB_Write(sensor->slv_addr, 0xb9, value); + + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, 0x13, 1, 1, enable) >= 0){ + sensor->status.awb = !!enable; + } + return sensor->status.awb; +} + + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, 0x13, 2, 1, enable) >= 0){ + sensor->status.agc = !!enable; + } + return sensor->status.agc; +} + + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, 0x13, 0, 1, enable) >= 0){ + sensor->status.aec = !!enable; + } + return sensor->status.aec; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, 0x1e, 5, 1, enable) >= 0){ + sensor->status.hmirror = !!enable; + } + return sensor->status.hmirror; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, 0x1e, 4, 1, enable) >= 0){ + sensor->status.vflip = !!enable; + } + return sensor->status.vflip; +} + +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0xf1, 1, 1, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set raw_gma to: %d", !enable); + sensor->status.raw_gma = !enable; + } + return ret; +} + + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0xf1, 0, 1, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set lenc to: %d", !enable); + sensor->status.lenc = !enable; + } + return ret; +} + +static int set_agc_gain(sensor_t *sensor, int option) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x13, 4, 1, !!option); + if (ret == 0) { + ESP_LOGD(TAG, "Set gain to: %d", !!option); + sensor->status.agc_gain = !!option; + } + return ret; +} + +static int set_awb_gain_dsp(sensor_t *sensor, int value) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0xa6, value); + if (ret == 0) { + ESP_LOGD(TAG, "Set awb gain threthold to: %d", value); + sensor->status.awb_gain = value; + } + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x55, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set brightness to: %d", level); + sensor->status.brightness = level; + } + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x56, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set contrast to: %d", level); + sensor->status.contrast = level; + } + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x70, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set sharpness to: %d", level); + sensor->status.sharpness = level; + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x55); + sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0x56); + sensor->status.saturation = 0; + sensor->status.ae_level = 0; + + sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x87); + sensor->status.awb = get_reg_bits(sensor, 0x13, 1, 1); + sensor->status.awb_gain = SCCB_Read(sensor->slv_addr, 0xa6); + sensor->status.aec = get_reg_bits(sensor, 0x13, 0, 1); + + sensor->status.agc = get_reg_bits(sensor, 0x13, 2, 1); + + sensor->status.raw_gma = get_reg_bits(sensor, 0xf1, 1, 1); + sensor->status.lenc = get_reg_bits(sensor, 0xf1, 0, 1); + sensor->status.hmirror = get_reg_bits(sensor, 0x1e, 5, 1); + sensor->status.vflip = get_reg_bits(sensor, 0x1e, 4, 1); + + sensor->status.colorbar = SCCB_Read(sensor->slv_addr, 0xb9); + sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70); + + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning){return -1;} +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div){return -1;} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int bf3005_detect(int slv_addr, sensor_id_t *id) +{ + if (BF3005_SCCB_ADDR == slv_addr) { + uint16_t PID = SCCB_Read(slv_addr, 0xFC); + if (BF3005_PID == PID) { + id->PID = PID; + id->VER = SCCB_Read(slv_addr, 0xFD); + id->MIDL = SCCB_Read(slv_addr, 0xFC); + id->MIDH = SCCB_Read(slv_addr, 0xFD); + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int bf3005_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_brightness = set_brightness; + sensor->set_contrast = set_contrast; + + sensor->set_colorbar = set_colorbar; + + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + sensor->set_whitebal = set_whitebal; + + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + + sensor->set_sharpness = set_sharpness; + //not supported + sensor->set_saturation= set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_quality = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + + ESP_LOGD(TAG, "BF3005 Attached"); + + return 0; +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c new file mode 100644 index 0000000000..f19025ebb3 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c @@ -0,0 +1,468 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sccb.h" +#include "gc0308.h" +#include "gc0308_regs.h" +#include "gc0308_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "gc0308"; +#endif + +#define H8(v) ((v)>>8) +#define L8(v) ((v)&0xff) + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) { + return old_value; + } + if ((uint8_t)old_value != value) { + ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write(slv_addr, reg, value);//maybe not? + } + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if (ret < 0) { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint8_t (*regs)[2], size_t regs_size) +{ + int i = 0, ret = 0; + while (!ret && (i < regs_size)) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static void print_regs(uint8_t slv_addr) +{ +#ifdef DEBUG_PRINT_REG + ESP_LOGI(TAG, "REG list look ======================"); + for (size_t i = 0xf0; i <= 0xfe; i++) { + ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 0 ==="); + write_reg(slv_addr, 0xfe, 0x00); // page 0 + for (size_t i = 0x03; i <= 0xa2; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + + ESP_LOGI(TAG, "\npage 3 ==="); + write_reg(slv_addr, 0xfe, 0x03); // page 3 + for (size_t i = 0x01; i <= 0x43; i++) { + ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } +#endif +} + +static int reset(sensor_t *sensor) +{ + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); + if (ret) { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + + vTaskDelay(80 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs, sizeof(gc0308_sensor_default_regs)/(sizeof(uint8_t) * 2)); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(80 / portTICK_PERIOD_MS); + write_reg(sensor->slv_addr, 0xfe, 0x00); +#ifdef CONFIG_IDF_TARGET_ESP32 + set_reg_bits(sensor->slv_addr, 0x28, 4, 0x07, 1); //frequency division for esp32, ensure pclk <= 15MHz +#endif + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + + switch (pixformat) { + case PIXFORMAT_RGB565: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 6); //RGB565 + break; + + case PIXFORMAT_YUV422: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 2); //yuv422 Y Cb Y Cr + break; + default: + ESP_LOGW(TAG, "unsupport format"); + ret = -1; + break; + } + + if (ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + if (framesize > FRAMESIZE_VGA) { + ESP_LOGW(TAG, "Invalid framesize: %u", framesize); + framesize = FRAMESIZE_VGA; + } + sensor->status.framesize = framesize; + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; + uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; + (void)row_s; + (void)col_s; + +#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE + struct subsample_cfg { + uint16_t ratio_numerator; + uint16_t ratio_denominator; + uint8_t reg0x54; + uint8_t reg0x56; + uint8_t reg0x57; + uint8_t reg0x58; + uint8_t reg0x59; + }; + const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio + {84, 420, 0x55, 0x00, 0x00, 0x00, 0x00}, //1/5 + {105, 420, 0x44, 0x00, 0x00, 0x00, 0x00},//1/4 + {140, 420, 0x33, 0x00, 0x00, 0x00, 0x00},//1/3 + {210, 420, 0x22, 0x00, 0x00, 0x00, 0x00},//1/2 + {240, 420, 0x77, 0x02, 0x46, 0x02, 0x46},//4/7 + {252, 420, 0x55, 0x02, 0x04, 0x02, 0x04},//3/5 + {280, 420, 0x33, 0x02, 0x00, 0x02, 0x00},//2/3 + {420, 420, 0x11, 0x00, 0x00, 0x00, 0x00},//1/1 + }; + uint16_t win_w = 640; + uint16_t win_h = 480; + const struct subsample_cfg *cfg = NULL; + /** + * Strategy: try to keep the maximum perspective + */ + for (size_t i = 0; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { + cfg = &subsample_cfgs[i]; + if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { + win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; + win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; + row_s = (resolution[FRAMESIZE_VGA].height - win_h) / 2; + col_s = (resolution[FRAMESIZE_VGA].width - win_w) / 2; + ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); + break; + } + } + + write_reg(sensor->slv_addr, 0xfe, 0x00); + + write_reg(sensor->slv_addr, 0x05, H8(row_s)); + write_reg(sensor->slv_addr, 0x06, L8(row_s)); + write_reg(sensor->slv_addr, 0x07, H8(col_s)); + write_reg(sensor->slv_addr, 0x08, L8(col_s)); + write_reg(sensor->slv_addr, 0x09, H8(win_h + 8)); + write_reg(sensor->slv_addr, 0x0a, L8(win_h + 8)); + write_reg(sensor->slv_addr, 0x0b, H8(win_w + 8)); + write_reg(sensor->slv_addr, 0x0c, L8(win_w + 8)); + + write_reg(sensor->slv_addr, 0xfe, 0x01); + set_reg_bits(sensor->slv_addr, 0x53, 7, 0x01, 1); + set_reg_bits(sensor->slv_addr, 0x55, 0, 0x01, 1); + write_reg(sensor->slv_addr, 0x54, cfg->reg0x54); + write_reg(sensor->slv_addr, 0x56, cfg->reg0x56); + write_reg(sensor->slv_addr, 0x57, cfg->reg0x57); + write_reg(sensor->slv_addr, 0x58, cfg->reg0x58); + write_reg(sensor->slv_addr, 0x59, cfg->reg0x59); + + write_reg(sensor->slv_addr, 0xfe, 0x00); + +#elif CONFIG_GC_SENSOR_WINDOWING_MODE + write_reg(sensor->slv_addr, 0xfe, 0x00); + + write_reg(sensor->slv_addr, 0xf7, col_s / 4); + write_reg(sensor->slv_addr, 0xf8, row_s / 4); + write_reg(sensor->slv_addr, 0xf9, (col_s + h) / 4); + write_reg(sensor->slv_addr, 0xfa, (row_s + w) / 4); + + write_reg(sensor->slv_addr, 0x05, H8(row_s)); + write_reg(sensor->slv_addr, 0x06, L8(row_s)); + write_reg(sensor->slv_addr, 0x07, H8(col_s)); + write_reg(sensor->slv_addr, 0x08, L8(col_s)); + + write_reg(sensor->slv_addr, 0x09, H8(h + 8)); + write_reg(sensor->slv_addr, 0x0a, L8(h + 8)); + write_reg(sensor->slv_addr, 0x0b, H8(w + 8)); + write_reg(sensor->slv_addr, 0x0c, L8(w + 8)); + +#endif + if (ret == 0) { + ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); + } + return 0; +} + +static int set_contrast(sensor_t *sensor, int contrast) +{ + if (contrast != 0) { + write_reg(sensor->slv_addr, 0xfe, 0x00); + write_reg(sensor->slv_addr, 0xb3, contrast); + } + return 0; +} + +static int set_global_gain(sensor_t *sensor, int gain_level) +{ + if (gain_level != 0) { + write_reg(sensor->slv_addr, 0xfe, 0x00); + write_reg(sensor->slv_addr, 0x50, gain_level); + } + return 0; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, 0x14, 0, 0x01, enable != 0); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, 0x14, 1, 0x01, enable != 0); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, 0x2e, 0, 0x01, enable); + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret > 0) { + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret < 0) { + return ret; + } + value = (ret & ~mask) | (value & mask); + + if (mask > 0xFF) { + + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + write_reg(sensor->slv_addr, 0xfe, 0x00); + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = 0; + sensor->status.denoise = 0; + sensor->status.ae_level = 0; + sensor->status.gainceiling = 0; + sensor->status.awb = 0; + sensor->status.dcw = 0; + sensor->status.agc = 0; + sensor->status.aec = 0; + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, 0x14, 0x01); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, 0x14, 0x02); + sensor->status.colorbar = 0; + sensor->status.bpc = 0; + sensor->status.wpc = 0; + sensor->status.raw_gma = 0; + sensor->status.lenc = 0; + sensor->status.quality = 0; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = 0; + sensor->status.agc_gain = 0; + sensor->status.aec_value = 0; + sensor->status.aec2 = 0; + + print_regs(sensor->slv_addr); + return 0; +} + +static int set_dummy(sensor_t *sensor, int val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} + +int gc0308_detect(int slv_addr, sensor_id_t *id) +{ + if (GC0308_SCCB_ADDR == slv_addr) { + write_reg(slv_addr, 0xfe, 0x00); + uint8_t PID = SCCB_Read(slv_addr, 0x00); + if (GC0308_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int gc0308_init(sensor_t *sensor) +{ + sensor->init_status = init_status; + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_contrast; + sensor->set_brightness = set_dummy; + sensor->set_saturation = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_quality = set_dummy; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_dummy; + sensor->set_gain_ctrl = set_global_gain; + sensor->set_exposure_ctrl = set_dummy; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + sensor->set_aec2 = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_aec_value = set_dummy; + + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = NULL; + sensor->set_pll = NULL; + sensor->set_xclk = NULL; + + ESP_LOGD(TAG, "GC0308 Attached"); + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c new file mode 100644 index 0000000000..612e17b1ed --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c @@ -0,0 +1,391 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sccb.h" +#include "gc032a.h" +#include "gc032a_regs.h" +#include "gc032a_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "gc032a"; +#endif + +#define H8(v) ((v)>>8) +#define L8(v) ((v)&0xff) + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) { + return old_value; + } + if ((uint8_t)old_value != value) { + ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write(slv_addr, reg, value);//maybe not? + } + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static void print_regs(uint8_t slv_addr) +{ +#ifdef DEBUG_PRINT_REG + vTaskDelay(pdMS_TO_TICKS(100)); + ESP_LOGI(TAG, "REG list look ======================"); + for (size_t i = 0xf0; i <= 0xfe; i++) { + ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 0 ==="); + write_reg(slv_addr, 0xfe, 0x00); // page 0 + for (size_t i = 0x03; i <= 0x24; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + for (size_t i = 0x40; i <= 0x95; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 3 ==="); + write_reg(slv_addr, 0xfe, 0x03); // page 3 + for (size_t i = 0x01; i <= 0x43; i++) { + ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } +#endif +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if (ret < 0) { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static int reset(sensor_t *sensor) +{ + int ret; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); + if (ret) { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + + ret = write_regs(sensor->slv_addr, gc032a_default_regs); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(100 / portTICK_PERIOD_MS); + write_reg(sensor->slv_addr, 0xfe, 0x00); + set_reg_bits(sensor->slv_addr, 0xf7, 1, 0x01, 1); // PLL_mode1:div2en + set_reg_bits(sensor->slv_addr, 0xf7, 7, 0x01, 1); // PLL_mode1:dvp mode + set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 8); //PLL_mode2 :divx4 + set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); //vlk div mode :divide_by + } + + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + switch (pixformat) { + case PIXFORMAT_RGB565: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 6); //RGB565 + break; + + case PIXFORMAT_YUV422: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 3); + break; + default: + ESP_LOGW(TAG, "unsupport format"); + ret = -1; + break; + } + if (ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + ESP_LOGI(TAG, "set_framesize"); + int ret = 0; + if (framesize > FRAMESIZE_VGA) { + ESP_LOGW(TAG, "Invalid framesize: %u", framesize); + framesize = FRAMESIZE_VGA; + } + sensor->status.framesize = framesize; + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; + uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; + + write_reg(sensor->slv_addr, 0xfe, 0x00); + write_reg(sensor->slv_addr, P0_ROW_START_HIGH, H8(row_s)); // Row_start[8] + write_reg(sensor->slv_addr, P0_ROW_START_LOW, L8(row_s)); // Row_start[7:0] + write_reg(sensor->slv_addr, P0_COLUMN_START_HIGH, H8(col_s)); // Column_start[9:8] + write_reg(sensor->slv_addr, P0_COLUMN_START_LOW, L8(col_s)); // Column_start[7:0] + write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_HIGH, H8(h + 8)); //window_height [8] + write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_LOW, L8(h + 8)); //window_height [7:0] + write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_HIGH, H8(w + 8)); //window_width [9:8] + write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_LOW, L8(w + 8)); //window_width [7:0] + + write_reg(sensor->slv_addr, P0_WIN_MODE, 0x01); + write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_HIGH, H8(h)); + write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_LOW, L8(h)); + write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_HIGH, H8(w)); + write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_LOW, L8(w)); + + if (ret == 0) { + ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); + } + print_regs(sensor->slv_addr); + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 0, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 1, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE2, 3, 0x01, enable); + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret > 0) { + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret < 0) { + return ret; + } + value = (ret & ~mask) | (value & mask); + + if (mask > 0xFF) { + + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + write_reg(sensor->slv_addr, 0xfe, 0x00); + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = 0; + sensor->status.denoise = 0; + sensor->status.ae_level = 0; + sensor->status.gainceiling = 0; + sensor->status.awb = 0; + sensor->status.dcw = 0; + sensor->status.agc = 0; + sensor->status.aec = 0; + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02); + sensor->status.colorbar = 0; + sensor->status.bpc = 0; + sensor->status.wpc = 0; + sensor->status.raw_gma = 0; + sensor->status.lenc = 0; + sensor->status.quality = 0; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = 0; + sensor->status.agc_gain = 0; + sensor->status.aec_value = 0; + sensor->status.aec2 = 0; + return 0; +} + +static int set_dummy(sensor_t *sensor, int val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} + +int gc032a_detect(int slv_addr, sensor_id_t *id) +{ + if (GC032A_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW); + uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH); + uint16_t PID = MIDH << 8 | MIDL; + if (GC032A_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int gc032a_init(sensor_t *sensor) +{ + sensor->init_status = init_status; + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_dummy; + sensor->set_brightness = set_dummy; + sensor->set_saturation = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_quality = set_dummy; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_dummy; + sensor->set_gain_ctrl = set_dummy; + sensor->set_exposure_ctrl = set_dummy; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + sensor->set_aec2 = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_aec_value = set_dummy; + + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = NULL; + sensor->set_pll = NULL; + sensor->set_xclk = NULL; + + ESP_LOGD(TAG, "GC032A Attached"); + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c new file mode 100644 index 0000000000..3a066cd941 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c @@ -0,0 +1,477 @@ +// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sccb.h" +#include "gc2145.h" +#include "gc2145_regs.h" +#include "gc2145_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "gc2145"; +#endif + +#define H8(v) ((v)>>8) +#define L8(v) ((v)&0xff) + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) { + return old_value; + } + if ((uint8_t)old_value != value) { + ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write(slv_addr, reg, value);//maybe not? + } + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if (ret < 0) { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static void print_regs(uint8_t slv_addr) +{ +#ifdef DEBUG_PRINT_REG + vTaskDelay(pdMS_TO_TICKS(100)); + ESP_LOGI(TAG, "REG list look ======================"); + for (size_t i = 0xf0; i <= 0xfe; i++) { + ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 0 ==="); + write_reg(slv_addr, 0xfe, 0x00); // page 0 + for (size_t i = 0x03; i <= 0x24; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + for (size_t i = 0x80; i <= 0xa2; i++) { + ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } + ESP_LOGI(TAG, "\npage 3 ==="); + write_reg(slv_addr, 0xfe, 0x03); // page 3 + for (size_t i = 0x01; i <= 0x43; i++) { + ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); + } +#endif +} + +static int reset(sensor_t *sensor) +{ + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xe0); + if (ret) { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, gc2145_default_init_regs); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(100 / portTICK_PERIOD_MS); +#ifdef CONFIG_IDF_TARGET_ESP32 + write_reg(sensor->slv_addr, 0xfe, 0x00); + //ensure pclk <= 15MHz for esp32 + set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 2); // divx4 + set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); // divide_by +#endif + + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + + switch (pixformat) { + case PIXFORMAT_RGB565: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 6); //RGB565 + break; + + case PIXFORMAT_YUV422: + write_reg(sensor->slv_addr, 0xfe, 0x00); + ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 2); //yuv422 + break; + default: + ESP_LOGW(TAG, "unsupport format"); + ret = -1; + break; + } + + if (ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + if (framesize > FRAMESIZE_UXGA) { + ESP_LOGW(TAG, "Invalid framesize: %u", framesize); + framesize = FRAMESIZE_UXGA; + } + sensor->status.framesize = framesize; + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + uint16_t row_s = (resolution[FRAMESIZE_UXGA].height - h) / 2; + uint16_t col_s = (resolution[FRAMESIZE_UXGA].width - w) / 2; + (void)row_s; + (void)col_s; + +#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE + struct subsample_cfg { + uint16_t ratio_numerator; + uint16_t ratio_denominator; + uint8_t reg0x99; + uint8_t reg0x9b; + uint8_t reg0x9c; + uint8_t reg0x9d; + uint8_t reg0x9e; + uint8_t reg0x9f; + uint8_t reg0xa0; + uint8_t reg0xa1; + uint8_t reg0xa2; + }; + const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio + // {60, 420, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/7 // A smaller ratio brings a larger view, but it reduces the frame rate + // {84, 420, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/5 + // {105, 420, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/4 + {140, 420, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/3 + {210, 420, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/2 + {240, 420, 0x77, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46},//4/7 + {252, 420, 0x55, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04},//3/5 + {280, 420, 0x33, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},//2/3 + {420, 420, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/1 + }; + uint16_t win_w = resolution[FRAMESIZE_UXGA].width; + uint16_t win_h = resolution[FRAMESIZE_UXGA].height; + const struct subsample_cfg *cfg = NULL; + /** + * Strategy: try to keep the maximum perspective + */ + uint8_t i = 0; + if (framesize >= FRAMESIZE_QVGA) { + i = 1; + } + for (; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { + cfg = &subsample_cfgs[i]; + if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { + win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; + win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; + row_s = (resolution[FRAMESIZE_UXGA].height - win_h) / 2; + col_s = (resolution[FRAMESIZE_UXGA].width - win_w) / 2; + ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); + break; + } + } + + write_reg(sensor->slv_addr, 0xfe, 0x00); + write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); + write_reg(sensor->slv_addr, 0x09, H8(row_s)); + write_reg(sensor->slv_addr, 0x0a, L8(row_s)); + write_reg(sensor->slv_addr, 0x0b, H8(col_s)); + write_reg(sensor->slv_addr, 0x0c, L8(col_s)); + write_reg(sensor->slv_addr, 0x0d, H8(win_h + 8)); + write_reg(sensor->slv_addr, 0x0e, L8(win_h + 8)); + write_reg(sensor->slv_addr, 0x0f, H8(win_w + 16)); + write_reg(sensor->slv_addr, 0x10, L8(win_w + 16)); + + write_reg(sensor->slv_addr, 0x99, cfg->reg0x99); + write_reg(sensor->slv_addr, 0x9b, cfg->reg0x9b); + write_reg(sensor->slv_addr, 0x9c, cfg->reg0x9c); + write_reg(sensor->slv_addr, 0x9d, cfg->reg0x9d); + write_reg(sensor->slv_addr, 0x9e, cfg->reg0x9e); + write_reg(sensor->slv_addr, 0x9f, cfg->reg0x9f); + write_reg(sensor->slv_addr, 0xa0, cfg->reg0xa0); + write_reg(sensor->slv_addr, 0xa1, cfg->reg0xa1); + write_reg(sensor->slv_addr, 0xa2, cfg->reg0xa2); + + write_reg(sensor->slv_addr, 0x95, H8(h)); + write_reg(sensor->slv_addr, 0x96, L8(h)); + write_reg(sensor->slv_addr, 0x97, H8(w)); + write_reg(sensor->slv_addr, 0x98, L8(w)); + + +#elif CONFIG_GC_SENSOR_WINDOWING_MODE + write_reg(sensor->slv_addr, 0xfe, 0x00); + + write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); + // write_reg(sensor->slv_addr, 0xec, col_s / 8); //measure window + // write_reg(sensor->slv_addr, 0xed, row_s / 8); + // write_reg(sensor->slv_addr, 0xee, (col_s + h) / 8); + // write_reg(sensor->slv_addr, 0xef, (row_s + w) / 8); + + write_reg(sensor->slv_addr, 0x09, H8(row_s)); + write_reg(sensor->slv_addr, 0x0a, L8(row_s)); + write_reg(sensor->slv_addr, 0x0b, H8(col_s)); + write_reg(sensor->slv_addr, 0x0c, L8(col_s)); + write_reg(sensor->slv_addr, 0x0d, H8(h + 8)); + write_reg(sensor->slv_addr, 0x0e, L8(h + 8)); + write_reg(sensor->slv_addr, 0x0f, H8(w + 8)); + write_reg(sensor->slv_addr, 0x10, L8(w + 8)); + + write_reg(sensor->slv_addr, 0x95, H8(h)); + write_reg(sensor->slv_addr, 0x96, L8(h)); + write_reg(sensor->slv_addr, 0x97, H8(w)); + write_reg(sensor->slv_addr, 0x98, L8(w)); + +#endif + + if (ret == 0) { + ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); + } + return ret; + +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 0, 0x01, enable != 0); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 1, 0x01, enable != 0); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + // ret = write_reg(sensor->slv_addr, 0xfe, 0x00); + // ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE3, 3, 0x01, enable); + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret > 0) { + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + if (mask > 0xFF) { + ESP_LOGE(TAG, "mask should not more than 0xff"); + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if (ret < 0) { + return ret; + } + value = (ret & ~mask) | (value & mask); + + if (mask > 0xFF) { + + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + write_reg(sensor->slv_addr, 0xfe, 0x00); + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = 0; + sensor->status.denoise = 0; + sensor->status.ae_level = 0; + sensor->status.gainceiling = 0; + sensor->status.awb = 0; + sensor->status.dcw = 0; + sensor->status.agc = 0; + sensor->status.aec = 0; + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x01); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x02); + sensor->status.colorbar = 0; + sensor->status.bpc = 0; + sensor->status.wpc = 0; + sensor->status.raw_gma = 0; + sensor->status.lenc = 0; + sensor->status.quality = 0; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = 0; + sensor->status.agc_gain = 0; + sensor->status.aec_value = 0; + sensor->status.aec2 = 0; + + print_regs(sensor->slv_addr); + return 0; +} + +static int set_dummy(sensor_t *sensor, int val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) +{ + ESP_LOGW(TAG, "Unsupported"); + return -1; +} + +int gc2145_detect(int slv_addr, sensor_id_t *id) +{ + if (GC2145_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read(slv_addr, CHIP_ID_LOW); + uint8_t MIDH = SCCB_Read(slv_addr, CHIP_ID_HIGH); + uint16_t PID = MIDH << 8 | MIDL; + if (GC2145_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int gc2145_init(sensor_t *sensor) +{ + sensor->init_status = init_status; + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_dummy; + sensor->set_brightness = set_dummy; + sensor->set_saturation = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_quality = set_dummy; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_dummy; + sensor->set_gain_ctrl = set_dummy; + sensor->set_exposure_ctrl = set_dummy; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + sensor->set_aec2 = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_aec_value = set_dummy; + + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = NULL; + sensor->set_pll = NULL; + sensor->set_xclk = NULL; + + ESP_LOGD(TAG, "GC2145 Attached"); + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c new file mode 100644 index 0000000000..86a8b8a0b5 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c @@ -0,0 +1,1022 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * NT99141 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "nt99141.h" +#include "nt99141_regs.h" +#include "nt99141_settings.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "NT99141"; +#endif + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg) +{ + int ret = SCCB_Read16(slv_addr, reg); +#ifdef REG_DEBUG_ON + + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } + +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) +{ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int read_reg16(uint8_t slv_addr, const uint16_t reg) +{ + int ret = 0, ret2 = 0; + ret = read_reg(slv_addr, reg); + + if (ret >= 0) { + ret = (ret & 0xFF) << 8; + ret2 = read_reg(slv_addr, reg + 1); + + if (ret2 < 0) { + ret = ret2; + } else { + ret |= ret2 & 0xFF; + } + } + + return ret; +} + + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) +{ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write16(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + + if (old_value < 0) { + return old_value; + } + + if ((uint8_t)old_value != value) { + ESP_LOGD(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write16(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write16(slv_addr, reg, value);//maybe not? + } + + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } + +#endif + return ret; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + + if (ret < 0) { + return ret; + } + + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + + i++; + } + + return ret; +} + +static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) +{ + if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { + return -1; + } + + return 0; +} + +static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) +{ + if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { + return -1; + } + + return 0; +} + +#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, enable?mask:0) + +static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t seld5, bool pclk_manual, uint8_t pclk_div) +{ + return -1; +} + +static int set_ae_level(sensor_t *sensor, int level); + +static int reset(sensor_t *sensor) +{ + + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x01); + + if (ret) { + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + + vTaskDelay(100 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, sensor_default_regs); //re-initial + + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + ret = set_ae_level(sensor, 0); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + const uint16_t (*regs)[2]; + + switch (pixformat) { + case PIXFORMAT_YUV422: + regs = sensor_fmt_yuv422; + break; + + case PIXFORMAT_GRAYSCALE: + regs = sensor_fmt_grayscale; + break; + + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + regs = sensor_fmt_rgb565; + break; + + case PIXFORMAT_JPEG: + regs = sensor_fmt_jpeg; + break; + + case PIXFORMAT_RAW: + regs = sensor_fmt_raw; + break; + + default: + ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); + return -1; + } + + ret = write_regs(sensor->slv_addr, regs); + + if (ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + + return ret; +} + +static int set_image_options(sensor_t *sensor) +{ + int ret = 0; + uint8_t reg20 = 0; + uint8_t reg21 = 0; + uint8_t reg4514 = 0; + uint8_t reg4514_test = 0; + + // V-Flip + if (sensor->status.vflip) { + reg20 |= 0x01; + reg4514_test |= 1; + } + + // H-Mirror + if (sensor->status.hmirror) { + reg21 |= 0x02; + reg4514_test |= 2; + } + + switch (reg4514_test) { + + } + + if (write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20 | reg21)) { + ESP_LOGE(TAG, "Setting Image Options Failed"); + ret = -1; + } + + ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", + sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + + sensor->status.framesize = framesize; + ret = write_regs(sensor->slv_addr, sensor_default_regs); + + if (framesize == FRAMESIZE_QVGA) { + ESP_LOGD(TAG, "Set FRAMESIZE_QVGA"); + ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA); +#if CONFIG_NT99141_SUPPORT_XSKIP + ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: xskip mode"); + ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA_xskip); +#elif CONFIG_NT99141_SUPPORT_CROP + ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: crop mode"); + ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA_crop); +#endif + } else if (framesize == FRAMESIZE_VGA) { + ESP_LOGD(TAG, "Set FRAMESIZE_VGA"); + // ret = write_regs(sensor->slv_addr, sensor_framesize_VGA); + ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_xyskip);// Resolution:640*360 This configuration is equally-scaled without deforming +#ifdef CONFIG_NT99141_SUPPORT_XSKIP + ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: xskip mode"); + ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_xskip); +#elif CONFIG_NT99141_SUPPORT_CROP + ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: crop mode"); + ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_crop); +#endif + } else if (framesize >= FRAMESIZE_HD) { + ESP_LOGD(TAG, "Set FRAMESIZE_HD"); + ret = write_regs(sensor->slv_addr, sensor_framesize_HD); + } else { + ESP_LOGD(TAG, "Dont suppost this size, Set FRAMESIZE_VGA"); + ret = write_regs(sensor->slv_addr, sensor_framesize_VGA); + } + + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = set_image_options(sensor); + + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = set_image_options(sensor); + + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + + return ret; +} + +static int set_quality(sensor_t *sensor, int qs) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); + + if (ret == 0) { + sensor->status.quality = qs; + ESP_LOGD(TAG, "Set quality to: %d", qs); + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); + + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + + return ret; +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x32bb, 0x87, enable); + + if (ret == 0) { + ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); + sensor->status.agc = enable; + } + + return ret; +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + int data = 0; + // ret = write_reg_bits(sensor->slv_addr, 0x32bb, 0x87, enable); + data = read_reg(sensor->slv_addr, 0x3201); + ESP_LOGD(TAG, "set_exposure_ctrl:enable"); + if (enable) { + ESP_LOGD(TAG, "set_exposure_ctrl:enable"); + ret = write_reg(sensor->slv_addr, 0x3201, (1 << 5) | data); + } else { + ESP_LOGD(TAG, "set_exposure_ctrl:disable"); + ret = write_reg(sensor->slv_addr, 0x3201, (~(1 << 5)) & data); + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); + sensor->status.aec = enable; + } + + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set awb to: %d", enable); + sensor->status.awb = enable; + } + + return ret; +} + +//Advanced AWB +static int set_dcw_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set dcw to: %d", enable); + sensor->status.dcw = enable; + } + + return ret; +} + +//night mode enable +static int set_aec2(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set aec2 to: %d", enable); + sensor->status.aec2 = enable; + } + + return ret; +} + +static int set_bpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set bpc to: %d", enable); + sensor->status.bpc = enable; + } + + return ret; +} + +static int set_wpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set wpc to: %d", enable); + sensor->status.wpc = enable; + } + + return ret; +} + +//Gamma enable +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set raw_gma to: %d", enable); + sensor->status.raw_gma = enable; + } + + return ret; +} + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + + if (ret == 0) { + ESP_LOGD(TAG, "Set lenc to: %d", enable); + sensor->status.lenc = enable; + } + + return ret; +} + +static int get_agc_gain(sensor_t *sensor) +{ + ESP_LOGD(TAG, "get_agc_gain can not be configured at present"); + return 0; +} + +//real gain +static int set_agc_gain(sensor_t *sensor, int gain) +{ + ESP_LOGD(TAG, "set_agc_gain can not be configured at present"); + // ESP_LOGD(TAG, "GAIN = %d\n", gain); + int cnt = gain / 2; + + switch (cnt) { + case 0: + ESP_LOGD(TAG, "set_agc_gain: 1x"); + write_reg(sensor->slv_addr, 0X301D, 0X00); + break; + + case 1: + ESP_LOGD(TAG,"set_agc_gain: 2x"); + write_reg(sensor->slv_addr, 0X301D, 0X0F); + break; + + case 2: + ESP_LOGD(TAG,"set_agc_gain: 4x"); + write_reg(sensor->slv_addr, 0X301D, 0X2F); + break; + + case 3: + ESP_LOGD(TAG,"set_agc_gain: 6x"); + write_reg(sensor->slv_addr, 0X301D, 0X37); + break; + + case 4: + ESP_LOGD(TAG,"set_agc_gain: 8x"); + write_reg(sensor->slv_addr, 0X301D, 0X3F); + break; + + default: + ESP_LOGD(TAG,"fail set_agc_gain"); + break; + } + + return 0; +} + +static int get_aec_value(sensor_t *sensor) +{ + ESP_LOGD(TAG, "get_aec_value can not be configured at present"); + return 0; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + ESP_LOGD(TAG, "set_aec_value can not be configured at present"); + int ret = 0; + // ESP_LOGD(TAG, " set_aec_value to: %d", value); + ret = write_reg_bits(sensor->slv_addr, 0x3012, 0x00, (value >> 8) & 0xff); + ret = write_reg_bits(sensor->slv_addr, 0x3013, 0x01, value & 0xff); + + if (ret == 0) { + ESP_LOGD(TAG, " set_aec_value to: %d", value); + // sensor->status.aec = enable; + } + + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level) +{ + ESP_LOGD(TAG, "set_ae_level can not be configured at present"); + int ret = 0; + + if (level < 0) { + level = 0; + } else if (level > 9) { + level = 9; + } + + for (int i = 0; i < 5; i++) { + ret += write_reg(sensor->slv_addr, sensor_ae_level[ 5 * level + i ][0], sensor_ae_level[5 * level + i ][1]); + } + + if (ret) { + ESP_LOGE(TAG, " fail to set ae level: %d", ret); + } + + return 0; +} + +static int set_wb_mode(sensor_t *sensor, int mode) +{ + int ret = 0; + + if (mode < 0 || mode > 4) { + return -1; + } + + ret = write_reg(sensor->slv_addr, 0x3201, (mode != 0)); + + if (ret) { + return ret; + } + + switch (mode) { + case 1://Sunny + ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) + || write_reg16(sensor->slv_addr, 0x3291, 0x38) + || write_reg16(sensor->slv_addr, 0x3296, 0x01) + || write_reg16(sensor->slv_addr, 0x3297, 0x68) + || write_reg16(sensor->slv_addr, 0x3060, 0x01); + + break; + + case 2://Cloudy + + ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) + || write_reg16(sensor->slv_addr, 0x3291, 0x51) + || write_reg16(sensor->slv_addr, 0x3296, 0x01) + || write_reg16(sensor->slv_addr, 0x3297, 0x00) + || write_reg16(sensor->slv_addr, 0x3060, 0x01); + break; + + case 3://INCANDESCENCE] + ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) + || write_reg16(sensor->slv_addr, 0x3291, 0x30) + || write_reg16(sensor->slv_addr, 0x3296, 0x01) + || write_reg16(sensor->slv_addr, 0x3297, 0xCB) + || write_reg16(sensor->slv_addr, 0x3060, 0x01); + break; + + case 4://FLUORESCENT + ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) + || write_reg16(sensor->slv_addr, 0x3291, 0x70) + || write_reg16(sensor->slv_addr, 0x3296, 0x01) + || write_reg16(sensor->slv_addr, 0x3297, 0xFF) + || write_reg16(sensor->slv_addr, 0x3060, 0x01); + break; + + default://AUTO + break; + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set wb_mode to: %d", mode); + sensor->status.wb_mode = mode; + } + + return ret; +} + +static int set_awb_gain_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + int old_mode = sensor->status.wb_mode; + int mode = enable ? old_mode : 0; + + ret = set_wb_mode(sensor, mode); + + if (ret == 0) { + sensor->status.wb_mode = old_mode; + ESP_LOGD(TAG, "Set awb_gain to: %d", enable); + sensor->status.awb_gain = enable; + } + + return ret; +} + +static int set_special_effect(sensor_t *sensor, int effect) +{ + int ret = 0; + + if (effect < 0 || effect > 6) { + return -1; + } + + uint8_t *regs = (uint8_t *)sensor_special_effects[effect]; + ret = write_reg(sensor->slv_addr, 0x32F1, regs[0]) + || write_reg(sensor->slv_addr, 0x32F4, regs[1]) + || write_reg(sensor->slv_addr, 0x32F5, regs[2]) + || write_reg(sensor->slv_addr, 0x3060, regs[3]); + + if (ret == 0) { + ESP_LOGD(TAG, "Set special_effect to: %d", effect); + sensor->status.special_effect = effect; + } + + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + uint8_t value = 0; + + switch (level) { + case 3: + value = 0xA0; + break; + + case 2: + value = 0x90; + break; + + case 1: + value = 0x88; + break; + + case -1: + value = 0x78; + break; + + case -2: + value = 0x70; + break; + + case -3: + value = 0x60; + break; + + default: // 0 + break; + } + + ret = write_reg(sensor->slv_addr, 0x32F2, value); + + if (ret == 0) { + ESP_LOGD(TAG, "Set brightness to: %d", level); + sensor->status.brightness = level; + } + + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + uint8_t value1 = 0, value2 = 0 ; + + switch (level) { + case 3: + value1 = 0xD0; + value2 = 0xB0; + break; + + case 2: + value1 = 0xE0; + value2 = 0xA0; + break; + + case 1: + value1 = 0xF0; + value2 = 0x90; + break; + + case 0: + value1 = 0x00; + value2 = 0x80; + break; + + case -1: + value1 = 0x10; + value2 = 0x70; + break; + + case -2: + value1 = 0x20; + value2 = 0x60; + break; + + case -3: + value1 = 0x30; + value2 = 0x50; + break; + + default: // 0 + break; + } + + ret = write_reg(sensor->slv_addr, 0x32FC, value1); + ret = write_reg(sensor->slv_addr, 0x32F2, value2); + ret = write_reg(sensor->slv_addr, 0x3060, 0x01); + + if (ret == 0) { + ESP_LOGD(TAG, "Set contrast to: %d", level); + sensor->status.contrast = level; + } + + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret = 0; + + if (level > 4 || level < -4) { + return -1; + } + + uint8_t *regs = (uint8_t *)sensor_saturation_levels[level + 4]; + { + ret = write_reg(sensor->slv_addr, 0x32F3, regs[0]); + + if (ret) { + return ret; + } + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set saturation to: %d", level); + sensor->status.saturation = level; + } + + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + + if (level > 3 || level < -3) { + return -1; + } + + uint8_t mt_offset_2 = (level + 3) * 8; + uint8_t mt_offset_1 = mt_offset_2 + 1; + + ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto + || write_reg(sensor->slv_addr, 0x5300, 0x10) + || write_reg(sensor->slv_addr, 0x5301, 0x10) + || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) + || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) + || write_reg(sensor->slv_addr, 0x5309, 0x10) + || write_reg(sensor->slv_addr, 0x530a, 0x10) + || write_reg(sensor->slv_addr, 0x530b, 0x04) + || write_reg(sensor->slv_addr, 0x530c, 0x06); + + if (ret == 0) { + ESP_LOGD(TAG, "Set sharpness to: %d", level); + sensor->status.sharpness = level; + } + + return ret; +} + +static int set_gainceiling(sensor_t *sensor, gainceiling_t level) +{ + ESP_LOGD(TAG, "set_gainceiling can not be configured at present"); + return 0; +} + +static int get_denoise(sensor_t *sensor) +{ + + return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; +} + +static int set_denoise(sensor_t *sensor, int level) +{ + ESP_LOGD(TAG, "set_denoise can not be configured at present"); + return 0; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0, ret2 = 0; + + if (mask > 0xFF) { + ret = read_reg16(sensor->slv_addr, reg); + + if (ret >= 0 && mask > 0xFFFF) { + ret2 = read_reg(sensor->slv_addr, reg + 2); + + if (ret2 >= 0) { + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + + if (ret > 0) { + ret &= mask; + } + + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0, ret2 = 0; + + if (mask > 0xFF) { + ret = read_reg16(sensor->slv_addr, reg); + + if (ret >= 0 && mask > 0xFFFF) { + ret2 = read_reg(sensor->slv_addr, reg + 2); + + if (ret2 >= 0) { + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + + if (ret < 0) { + return ret; + } + + value = (ret & ~mask) | (value & mask); + + if (mask > 0xFFFF) { + ret = write_reg16(sensor->slv_addr, reg, value >> 8); + + if (ret >= 0) { + ret = write_reg(sensor->slv_addr, reg + 2, value & 0xFF); + } + } else if (mask > 0xFF) { + ret = write_reg16(sensor->slv_addr, reg, value); + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + + return ret; +} + +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) +{ + int ret = 0; + ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) + || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) + || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) + || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY); + + if (!ret) { + sensor->status.scale = scale; + sensor->status.binning = binning; + ret = set_image_options(sensor); + } + + return ret; +} + +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) +{ + return set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); +} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + if (xclk > 10) + { + ESP_LOGE(TAG, "only XCLK under 10MHz is supported, and XCLK is now set to 10M"); + xclk = 10; + } + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int nt99141_detect(int slv_addr, sensor_id_t *id) +{ + if (NT99141_SCCB_ADDR == slv_addr) { + SCCB_Write16(slv_addr, 0x3008, 0x01);//bank sensor + uint16_t h = SCCB_Read16(slv_addr, 0x3000); + uint16_t l = SCCB_Read16(slv_addr, 0x3001); + uint16_t PID = (h<<8) | l; + if (NT99141_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x3301)); + sensor->status.denoise = get_denoise(sensor); + sensor->status.ae_level = 0; + sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x32F0) & 0xFF; + sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x10); + sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); + sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); + sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); + sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); + sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); + sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); + sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); + sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); + sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3000, 0x01); + sensor->status.agc_gain = get_agc_gain(sensor); + sensor->status.aec_value = get_aec_value(sensor); + sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3000, 0x04); + return 0; +} + +int nt99141_init(sensor_t *sensor) +{ + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_contrast; + sensor->set_brightness = set_brightness; + sensor->set_saturation = set_saturation; + sensor->set_sharpness = set_sharpness; + sensor->set_gainceiling = set_gainceiling; + sensor->set_quality = set_quality; + sensor->set_colorbar = set_colorbar; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_whitebal = set_whitebal; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->init_status = init_status; + sensor->set_aec2 = set_aec2; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = set_special_effect; + sensor->set_wb_mode = set_wb_mode; + sensor->set_ae_level = set_ae_level; + sensor->set_dcw = set_dcw_dsp; + sensor->set_bpc = set_bpc_dsp; + sensor->set_wpc = set_wpc_dsp; + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + sensor->set_denoise = set_denoise; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c new file mode 100644 index 0000000000..7e3d77174d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c @@ -0,0 +1,612 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV2640 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "ov2640.h" +#include "ov2640_regs.h" +#include "ov2640_settings.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "ov2640"; +#endif + +static volatile ov2640_bank_t reg_bank = BANK_MAX; +static int set_bank(sensor_t *sensor, ov2640_bank_t bank) +{ + int res = 0; + if (bank != reg_bank) { + reg_bank = bank; + res = SCCB_Write(sensor->slv_addr, BANK_SEL, bank); + } + return res; +} + +static int write_regs(sensor_t *sensor, const uint8_t (*regs)[2]) +{ + int i=0, res = 0; + while (regs[i][0]) { + if (regs[i][0] == BANK_SEL) { + res = set_bank(sensor, regs[i][1]); + } else { + res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); + } + if (res) { + return res; + } + i++; + } + return res; +} + +static int write_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg, uint8_t value) +{ + int ret = set_bank(sensor, bank); + if(!ret) { + ret = SCCB_Write(sensor->slv_addr, reg, value); + } + return ret; +} + +static int set_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + + ret = set_bank(sensor, bank); + if(ret) { + return ret; + } + c_value = SCCB_Read(sensor->slv_addr, reg); + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = SCCB_Write(sensor->slv_addr, reg, new_value); + return ret; +} + +static int read_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg) +{ + if(set_bank(sensor, bank)){ + return 0; + } + return SCCB_Read(sensor->slv_addr, reg); +} + +static uint8_t get_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask) +{ + return (read_reg(sensor, bank, reg) >> offset) & mask; +} + +static int write_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t mask, int enable) +{ + return set_reg_bits(sensor, bank, reg, 0, mask, enable?mask:0); +} + +#define WRITE_REGS_OR_RETURN(regs) ret = write_regs(sensor, regs); if(ret){return ret;} +#define WRITE_REG_OR_RETURN(bank, reg, val) ret = write_reg(sensor, bank, reg, val); if(ret){return ret;} +#define SET_REG_BITS_OR_RETURN(bank, reg, offset, mask, val) ret = set_reg_bits(sensor, bank, reg, offset, mask, val); if(ret){return ret;} + +static int reset(sensor_t *sensor) +{ + int ret = 0; + WRITE_REG_OR_RETURN(BANK_SENSOR, COM7, COM7_SRST); + vTaskDelay(10 / portTICK_PERIOD_MS); + WRITE_REGS_OR_RETURN(ov2640_settings_cif); + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + sensor->pixformat = pixformat; + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + WRITE_REGS_OR_RETURN(ov2640_settings_rgb565); + break; + case PIXFORMAT_YUV422: + case PIXFORMAT_GRAYSCALE: + WRITE_REGS_OR_RETURN(ov2640_settings_yuv422); + break; + case PIXFORMAT_JPEG: + WRITE_REGS_OR_RETURN(ov2640_settings_jpeg3); + break; + default: + ret = -1; + break; + } + if(!ret) { + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + return ret; +} + +static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x, int offset_y, int max_x, int max_y, int w, int h){ + int ret = 0; + const uint8_t (*regs)[2]; + ov2640_clk_t c; + c.reserved = 0; + + max_x /= 4; + max_y /= 4; + w /= 4; + h /= 4; + uint8_t win_regs[][2] = { + {BANK_SEL, BANK_DSP}, + {HSIZE, max_x & 0xFF}, + {VSIZE, max_y & 0xFF}, + {XOFFL, offset_x & 0xFF}, + {YOFFL, offset_y & 0xFF}, + {VHYX, ((max_y >> 1) & 0X80) | ((offset_y >> 4) & 0X70) | ((max_x >> 5) & 0X08) | ((offset_x >> 8) & 0X07)}, + {TEST, (max_x >> 2) & 0X80}, + {ZMOW, (w)&0xFF}, + {ZMOH, (h)&0xFF}, + {ZMHH, ((h>>6)&0x04)|((w>>8)&0x03)}, + {0, 0} + }; + + if (sensor->pixformat == PIXFORMAT_JPEG) { + c.clk_2x = 0; + c.clk_div = 0; + c.pclk_auto = 0; + c.pclk_div = 8; + if(mode == OV2640_MODE_UXGA) { + c.pclk_div = 12; + } + // if (sensor->xclk_freq_hz == 16000000) { + // c.pclk_div = c.pclk_div / 2; + // } + } else { +#if CONFIG_IDF_TARGET_ESP32 + c.clk_2x = 0; +#else + c.clk_2x = 1; +#endif + c.clk_div = 7; + c.pclk_auto = 1; + c.pclk_div = 8; + if (mode == OV2640_MODE_CIF) { + c.clk_div = 3; + } else if(mode == OV2640_MODE_UXGA) { + c.pclk_div = 12; + } + } + ESP_LOGI(TAG, "Set PLL: clk_2x: %u, clk_div: %u, pclk_auto: %u, pclk_div: %u", c.clk_2x, c.clk_div, c.pclk_auto, c.pclk_div); + + if (mode == OV2640_MODE_CIF) { + regs = ov2640_settings_to_cif; + } else if (mode == OV2640_MODE_SVGA) { + regs = ov2640_settings_to_svga; + } else { + regs = ov2640_settings_to_uxga; + } + + WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS); + WRITE_REGS_OR_RETURN(regs); + WRITE_REGS_OR_RETURN(win_regs); + WRITE_REG_OR_RETURN(BANK_SENSOR, CLKRC, c.clk); + WRITE_REG_OR_RETURN(BANK_DSP, R_DVP_SP, c.pclk); + WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_EN); + + vTaskDelay(10 / portTICK_PERIOD_MS); + //required when changing resolution + set_pixformat(sensor, sensor->pixformat); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + aspect_ratio_t ratio = resolution[framesize].aspect_ratio; + uint16_t max_x = ratio_table[ratio].max_x; + uint16_t max_y = ratio_table[ratio].max_y; + uint16_t offset_x = ratio_table[ratio].offset_x; + uint16_t offset_y = ratio_table[ratio].offset_y; + ov2640_sensor_mode_t mode = OV2640_MODE_UXGA; + + sensor->status.framesize = framesize; + + + + if (framesize <= FRAMESIZE_CIF) { + mode = OV2640_MODE_CIF; + max_x /= 4; + max_y /= 4; + offset_x /= 4; + offset_y /= 4; + if(max_y > 296){ + max_y = 296; + } + } else if (framesize <= FRAMESIZE_SVGA) { + mode = OV2640_MODE_SVGA; + max_x /= 2; + max_y /= 2; + offset_x /= 2; + offset_y /= 2; + } + + ret = set_window(sensor, mode, offset_x, offset_y, max_x, max_y, w, h); + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret=0; + level += 3; + if (level <= 0 || level > NUM_CONTRAST_LEVELS) { + return -1; + } + sensor->status.contrast = level-3; + for (int i=0; i<7; i++) { + WRITE_REG_OR_RETURN(BANK_DSP, contrast_regs[0][i], contrast_regs[level][i]); + } + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret=0; + level += 3; + if (level <= 0 || level > NUM_BRIGHTNESS_LEVELS) { + return -1; + } + sensor->status.brightness = level-3; + for (int i=0; i<5; i++) { + WRITE_REG_OR_RETURN(BANK_DSP, brightness_regs[0][i], brightness_regs[level][i]); + } + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret=0; + level += 3; + if (level <= 0 || level > NUM_SATURATION_LEVELS) { + return -1; + } + sensor->status.saturation = level-3; + for (int i=0; i<5; i++) { + WRITE_REG_OR_RETURN(BANK_DSP, saturation_regs[0][i], saturation_regs[level][i]); + } + return ret; +} + +static int set_special_effect(sensor_t *sensor, int effect) +{ + int ret=0; + effect++; + if (effect <= 0 || effect > NUM_SPECIAL_EFFECTS) { + return -1; + } + sensor->status.special_effect = effect-1; + for (int i=0; i<5; i++) { + WRITE_REG_OR_RETURN(BANK_DSP, special_effects_regs[0][i], special_effects_regs[effect][i]); + } + return ret; +} + +static int set_wb_mode(sensor_t *sensor, int mode) +{ + int ret=0; + if (mode < 0 || mode > NUM_WB_MODES) { + return -1; + } + sensor->status.wb_mode = mode; + SET_REG_BITS_OR_RETURN(BANK_DSP, 0XC7, 6, 1, mode?1:0); + if(mode) { + for (int i=0; i<3; i++) { + WRITE_REG_OR_RETURN(BANK_DSP, wb_modes_regs[0][i], wb_modes_regs[mode][i]); + } + } + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level) +{ + int ret=0; + level += 3; + if (level <= 0 || level > NUM_AE_LEVELS) { + return -1; + } + sensor->status.ae_level = level-3; + for (int i=0; i<3; i++) { + WRITE_REG_OR_RETURN(BANK_SENSOR, ae_levels_regs[0][i], ae_levels_regs[level][i]); + } + return ret; +} + +static int set_quality(sensor_t *sensor, int quality) +{ + if(quality < 0) { + quality = 0; + } else if(quality > 63) { + quality = 63; + } + sensor->status.quality = quality; + return write_reg(sensor, BANK_DSP, QS, quality); +} + +static int set_agc_gain(sensor_t *sensor, int gain) +{ + if(gain < 0) { + gain = 0; + } else if(gain > 30) { + gain = 30; + } + sensor->status.agc_gain = gain; + return write_reg(sensor, BANK_SENSOR, GAIN, agc_gain_tbl[gain]); +} + +static int set_gainceiling_sensor(sensor_t *sensor, gainceiling_t gainceiling) +{ + sensor->status.gainceiling = gainceiling; + //return write_reg(sensor, BANK_SENSOR, COM9, COM9_AGC_SET(gainceiling)); + return set_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7, gainceiling); +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + if(value < 0) { + value = 0; + } else if(value > 1200) { + value = 1200; + } + sensor->status.aec_value = value; + return set_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3, value & 0x3) + || write_reg(sensor, BANK_SENSOR, AEC, (value >> 2) & 0xFF) + || set_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F, value >> 10); +} + +static int set_aec2(sensor_t *sensor, int enable) +{ + sensor->status.aec2 = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1, enable?0:1); +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + sensor->status.colorbar = enable; + return write_reg_bits(sensor, BANK_SENSOR, COM7, COM7_COLOR_BAR, enable?1:0); +} + +static int set_agc_sensor(sensor_t *sensor, int enable) +{ + sensor->status.agc = enable; + return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AGC_EN, enable?1:0); +} + +static int set_aec_sensor(sensor_t *sensor, int enable) +{ + sensor->status.aec = enable; + return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AEC_EN, enable?1:0); +} + +static int set_hmirror_sensor(sensor_t *sensor, int enable) +{ + sensor->status.hmirror = enable; + return write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_HFLIP_IMG, enable?1:0); +} + +static int set_vflip_sensor(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VREF_EN, enable?1:0); + return ret & write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VFLIP_IMG, enable?1:0); +} + +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + sensor->status.raw_gma = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1, enable?1:0); +} + +static int set_awb_dsp(sensor_t *sensor, int enable) +{ + sensor->status.awb = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1, enable?1:0); +} + +static int set_awb_gain_dsp(sensor_t *sensor, int enable) +{ + sensor->status.awb_gain = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1, enable?1:0); +} + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + sensor->status.lenc = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1, enable?1:0); +} + +static int set_dcw_dsp(sensor_t *sensor, int enable) +{ + sensor->status.dcw = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1, enable?1:0); +} + +static int set_bpc_dsp(sensor_t *sensor, int enable) +{ + sensor->status.bpc = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1, enable?1:0); +} + +static int set_wpc_dsp(sensor_t *sensor, int enable) +{ + sensor->status.wpc = enable; + return set_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1, enable?1:0); +} + +//unsupported +static int set_sharpness(sensor_t *sensor, int level) +{ + return -1; +} + +static int set_denoise(sensor_t *sensor, int level) +{ + return -1; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF); + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF); + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + ret = write_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF, value); + return ret; +} + +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) +{ + return set_window(sensor, (ov2640_sensor_mode_t)startX, offsetX, offsetY, totalX, totalY, outputX, outputY); +} + +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) +{ + return -1; +} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +static int init_status(sensor_t *sensor){ + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.ae_level = 0; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + + sensor->status.agc_gain = 30; + int agc_gain = read_reg(sensor, BANK_SENSOR, GAIN); + for (int i=0; i<30; i++){ + if(agc_gain >= agc_gain_tbl[i] && agc_gain < agc_gain_tbl[i+1]){ + sensor->status.agc_gain = i; + break; + } + } + + sensor->status.aec_value = ((uint16_t)get_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F) << 10) + | ((uint16_t)read_reg(sensor, BANK_SENSOR, AEC) << 2) + | get_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3);//0 - 1200 + sensor->status.quality = read_reg(sensor, BANK_DSP, QS); + sensor->status.gainceiling = get_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7); + + sensor->status.awb = get_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1); + sensor->status.awb_gain = get_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1); + sensor->status.aec = get_reg_bits(sensor, BANK_SENSOR, COM8, 0, 1); + sensor->status.aec2 = get_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1); + sensor->status.agc = get_reg_bits(sensor, BANK_SENSOR, COM8, 2, 1); + sensor->status.bpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1); + sensor->status.wpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1); + sensor->status.raw_gma = get_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1); + sensor->status.lenc = get_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1); + sensor->status.hmirror = get_reg_bits(sensor, BANK_SENSOR, REG04, 7, 1); + sensor->status.vflip = get_reg_bits(sensor, BANK_SENSOR, REG04, 6, 1); + sensor->status.dcw = get_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1); + sensor->status.colorbar = get_reg_bits(sensor, BANK_SENSOR, COM7, 1, 1); + + sensor->status.sharpness = 0;//not supported + sensor->status.denoise = 0; + return 0; +} + +int ov2640_detect(int slv_addr, sensor_id_t *id) +{ + if (OV2640_SCCB_ADDR == slv_addr) { + SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor + uint16_t PID = SCCB_Read(slv_addr, 0x0A); + if (OV2640_PID == PID) { + id->PID = PID; + id->VER = SCCB_Read(slv_addr, REG_VER); + id->MIDL = SCCB_Read(slv_addr, REG_MIDL); + id->MIDH = SCCB_Read(slv_addr, REG_MIDH); + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int ov2640_init(sensor_t *sensor) +{ + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_contrast; + sensor->set_brightness= set_brightness; + sensor->set_saturation= set_saturation; + + sensor->set_quality = set_quality; + sensor->set_colorbar = set_colorbar; + + sensor->set_gainceiling = set_gainceiling_sensor; + sensor->set_gain_ctrl = set_agc_sensor; + sensor->set_exposure_ctrl = set_aec_sensor; + sensor->set_hmirror = set_hmirror_sensor; + sensor->set_vflip = set_vflip_sensor; + + sensor->set_whitebal = set_awb_dsp; + sensor->set_aec2 = set_aec2; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = set_special_effect; + sensor->set_wb_mode = set_wb_mode; + sensor->set_ae_level = set_ae_level; + + sensor->set_dcw = set_dcw_dsp; + sensor->set_bpc = set_bpc_dsp; + sensor->set_wpc = set_wpc_dsp; + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + + //not supported + sensor->set_sharpness = set_sharpness; + sensor->set_denoise = set_denoise; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + ESP_LOGD(TAG, "OV2640 Attached"); + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c new file mode 100644 index 0000000000..b9ebdba3ba --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c @@ -0,0 +1,1053 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV3660 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "ov3660.h" +#include "ov3660_regs.h" +#include "ov3660_settings.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "ov3660"; +#endif + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg){ + int ret = SCCB_Read16(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask){ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int read_reg16(uint8_t slv_addr, const uint16_t reg){ + int ret = 0, ret2 = 0; + ret = read_reg(slv_addr, reg); + if (ret >= 0) { + ret = (ret & 0xFF) << 8; + ret2 = read_reg(slv_addr, reg+1); + if (ret2 < 0) { + ret = ret2; + } else { + ret |= ret2 & 0xFF; + } + } + return ret; +} + + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value){ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write16(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) { + return old_value; + } + if ((uint8_t)old_value != value) { + ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write16(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write16(slv_addr, reg, value);//maybe not? + } + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if(ret < 0) { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) +{ + if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { + return -1; + } + return 0; +} + +static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) +{ + if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { + return -1; + } + return 0; +} + +#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, enable?mask:0) + +static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pll_pre_div, bool pll_root_2x, int pll_seld5, bool pclk_manual, int pclk_div) +{ + const int pll_pre_div2x_map[] = { 2, 3, 4, 6 };//values are multiplied by two to avoid floats + const int pll_seld52x_map[] = { 2, 2, 4, 5 }; + + if(!pll_sys_div) { + pll_sys_div = 1; + } + + int pll_pre_div2x = pll_pre_div2x_map[pll_pre_div]; + int pll_root_div = pll_root_2x?2:1; + int pll_seld52x = pll_seld52x_map[pll_seld5]; + + int VCO = (xclk / 1000) * pll_multiplier * pll_root_div * 2 / pll_pre_div2x; + int PLLCLK = pll_bypass?(xclk):(VCO * 1000 * 2 / pll_sys_div / pll_seld52x); + int PCLK = PLLCLK / 2 / ((pclk_manual && pclk_div)?pclk_div:1); + int SYSCLK = PLLCLK / 4; + + ESP_LOGI(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK); + return SYSCLK; +} + +static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t seld5, bool pclk_manual, uint8_t pclk_div){ + int ret = 0; + if(multiplier > 31 || sys_div > 15 || pre_div > 3 || pclk_div > 31 || seld5 > 3){ + ESP_LOGE(TAG, "Invalid arguments"); + return -1; + } + + calc_sysclk(sensor->xclk_freq_hz, bypass, multiplier, sys_div, pre_div, root_2x, seld5, pclk_manual, pclk_div); + + ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL0, bypass?0x80:0x00); + if (ret == 0) { + ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL1, multiplier & 0x1f); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL2, 0x10 | (sys_div & 0x0f)); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL3, (pre_div & 0x3) << 4 | seld5 | (root_2x?0x40:0x00)); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, PCLK_RATIO, pclk_div & 0x1f); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, VFIFO_CTRL0C, pclk_manual?0x22:0x20); + } + if(ret){ + ESP_LOGE(TAG, "set_sensor_pll FAILED!"); + } + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level); + +static int reset(sensor_t *sensor) +{ + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x82); + if(ret){ + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, sensor_default_regs); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + ret = set_ae_level(sensor, 0); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + const uint16_t (*regs)[2]; + + switch (pixformat) { + case PIXFORMAT_YUV422: + regs = sensor_fmt_yuv422; + break; + + case PIXFORMAT_GRAYSCALE: + regs = sensor_fmt_grayscale; + break; + + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + regs = sensor_fmt_rgb565; + break; + + case PIXFORMAT_JPEG: + regs = sensor_fmt_jpeg; + break; + + case PIXFORMAT_RAW: + regs = sensor_fmt_raw; + break; + + default: + ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); + return -1; + } + + ret = write_regs(sensor->slv_addr, regs); + if(ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + return ret; +} + +static int set_image_options(sensor_t *sensor) +{ + int ret = 0; + uint8_t reg20 = 0; + uint8_t reg21 = 0; + uint8_t reg4514 = 0; + uint8_t reg4514_test = 0; + + // compression + if (sensor->pixformat == PIXFORMAT_JPEG) { + reg21 |= 0x20; + } + + // binning + if (sensor->status.binning) { + reg20 |= 0x01; + reg21 |= 0x01; + reg4514_test |= 4; + } else { + reg20 |= 0x40; + } + + // V-Flip + if (sensor->status.vflip) { + reg20 |= 0x06; + reg4514_test |= 1; + } + + // H-Mirror + if (sensor->status.hmirror) { + reg21 |= 0x06; + reg4514_test |= 2; + } + + switch (reg4514_test) { + //no binning + case 0: reg4514 = 0x88; break;//normal + case 1: reg4514 = 0x88; break;//v-flip + case 2: reg4514 = 0xbb; break;//h-mirror + case 3: reg4514 = 0xbb; break;//v-flip+h-mirror + //binning + case 4: reg4514 = 0xaa; break;//normal + case 5: reg4514 = 0xbb; break;//v-flip + case 6: reg4514 = 0xbb; break;//h-mirror + case 7: reg4514 = 0xaa; break;//v-flip+h-mirror + } + + if(write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20) + || write_reg(sensor->slv_addr, TIMING_TC_REG21, reg21) + || write_reg(sensor->slv_addr, 0x4514, reg4514)){ + ESP_LOGE(TAG, "Setting Image Options Failed"); + ret = -1; + } + + if (sensor->status.binning) { + ret = write_reg(sensor->slv_addr, 0x4520, 0x0b) + || write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1 + || write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1 + } else { + ret = write_reg(sensor->slv_addr, 0x4520, 0xb0) + || write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1 + || write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1 + } + + ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", + sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + + if(framesize > FRAMESIZE_QXGA){ + ESP_LOGW(TAG, "Invalid framesize: %u", framesize); + framesize = FRAMESIZE_QXGA; + } + framesize_t old_framesize = sensor->status.framesize; + sensor->status.framesize = framesize; + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + aspect_ratio_t ratio = resolution[sensor->status.framesize].aspect_ratio; + ratio_settings_t settings = ratio_table[ratio]; + + sensor->status.binning = (w <= (settings.max_width / 2) && h <= (settings.max_height / 2)); + sensor->status.scale = !((w == settings.max_width && h == settings.max_height) + || (w == (settings.max_width / 2) && h == (settings.max_height / 2))); + + ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, settings.start_x, settings.start_y) + || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, settings.end_x, settings.end_y) + || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, w, h); + + if (ret) { + goto fail; + } + + if (sensor->status.binning) { + ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, (settings.total_y / 2) + 1) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, 8, 2); + } else { + ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, settings.total_y) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, 16, 6); + } + + if (ret == 0) { + ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, sensor->status.scale); + } + + if (ret == 0) { + ret = set_image_options(sensor); + } + + if (ret) { + goto fail; + } + + if (sensor->pixformat == PIXFORMAT_JPEG) { + if (framesize == FRAMESIZE_QXGA || sensor->xclk_freq_hz == 16000000) { + //40MHz SYSCLK and 10MHz PCLK + ret = set_pll(sensor, false, 24, 1, 3, false, 0, true, 8); + } else { + //50MHz SYSCLK and 10MHz PCLK + ret = set_pll(sensor, false, 30, 1, 3, false, 0, true, 10); + } + } else { + //tuned for 16MHz XCLK and 8MHz PCLK + if (framesize > FRAMESIZE_HVGA) { + //8MHz SYSCLK and 8MHz PCLK (4.44 FPS) + ret = set_pll(sensor, false, 4, 1, 0, false, 2, true, 2); + } else if (framesize >= FRAMESIZE_QVGA) { + //16MHz SYSCLK and 8MHz PCLK (10.25 FPS) + ret = set_pll(sensor, false, 8, 1, 0, false, 2, true, 4); + } else { + //32MHz SYSCLK and 8MHz PCLK (17.77 FPS) + ret = set_pll(sensor, false, 8, 1, 0, false, 0, true, 8); + } + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); + } + return ret; + +fail: + sensor->status.framesize = old_framesize; + ESP_LOGE(TAG, "Setting framesize to: %ux%u failed", w, h); + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = set_image_options(sensor); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = set_image_options(sensor); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_quality(sensor_t *sensor, int qs) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); + if (ret == 0) { + sensor->status.quality = qs; + ESP_LOGD(TAG, "Set quality to: %d", qs); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + return ret; +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); + sensor->status.agc = enable; + } + return ret; +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); + sensor->status.aec = enable; + } + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set awb to: %d", enable); + sensor->status.awb = enable; + } + return ret; +} + +//Advanced AWB +static int set_dcw_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5183, 0x80, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set dcw to: %d", enable); + sensor->status.dcw = enable; + } + return ret; +} + +//night mode enable +static int set_aec2(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x3a00, 0x04, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set aec2 to: %d", enable); + sensor->status.aec2 = enable; + } + return ret; +} + +static int set_bpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x04, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set bpc to: %d", enable); + sensor->status.bpc = enable; + } + return ret; +} + +static int set_wpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x02, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set wpc to: %d", enable); + sensor->status.wpc = enable; + } + return ret; +} + +//Gamma enable +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x20, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set raw_gma to: %d", enable); + sensor->status.raw_gma = enable; + } + return ret; +} + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x80, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set lenc to: %d", enable); + sensor->status.lenc = enable; + } + return ret; +} + +static int get_agc_gain(sensor_t *sensor) +{ + int ra = read_reg(sensor->slv_addr, 0x350a); + if (ra < 0) { + return 0; + } + int rb = read_reg(sensor->slv_addr, 0x350b); + if (rb < 0) { + return 0; + } + int res = (rb & 0xF0) >> 4 | (ra & 0x03) << 4; + if (rb & 0x0F) { + res += 1; + } + return res; +} + +//real gain +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + if(gain < 0) { + gain = 0; + } else if(gain > 64) { + gain = 64; + } + + //gain value is 6.4 bits float + //in order to use the max range, we deduct 1/16 + int gainv = gain << 4; + if(gainv){ + gainv -= 1; + } + + ret = write_reg(sensor->slv_addr, 0x350a, gainv >> 8) || write_reg(sensor->slv_addr, 0x350b, gainv & 0xff); + if (ret == 0) { + ESP_LOGD(TAG, "Set agc_gain to: %d", gain); + sensor->status.agc_gain = gain; + } + return ret; +} + +static int get_aec_value(sensor_t *sensor) +{ + int ra = read_reg(sensor->slv_addr, 0x3500); + if (ra < 0) { + return 0; + } + int rb = read_reg(sensor->slv_addr, 0x3501); + if (rb < 0) { + return 0; + } + int rc = read_reg(sensor->slv_addr, 0x3502); + if (rc < 0) { + return 0; + } + int res = (ra & 0x0F) << 12 | (rb & 0xFF) << 4 | (rc & 0xF0) >> 4; + return res; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0, max_val = 0; + max_val = read_reg16(sensor->slv_addr, 0x380e); + if (max_val < 0) { + ESP_LOGE(TAG, "Could not read max aec_value"); + return -1; + } + if (value > max_val) { + value =max_val; + } + + ret = write_reg(sensor->slv_addr, 0x3500, (value >> 12) & 0x0F) + || write_reg(sensor->slv_addr, 0x3501, (value >> 4) & 0xFF) + || write_reg(sensor->slv_addr, 0x3502, (value << 4) & 0xF0); + + if (ret == 0) { + ESP_LOGD(TAG, "Set aec_value to: %d / %d", value, max_val); + sensor->status.aec_value = value; + } + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level) +{ + int ret = 0; + if (level < -5 || level > 5) { + return -1; + } + //good targets are between 5 and 115 + int target_level = ((level + 5) * 10) + 5; + + int level_high, level_low; + int fast_high, fast_low; + + level_low = target_level * 23 / 25; //0.92 (0.46) + level_high = target_level * 27 / 25; //1.08 (2.08) + + fast_low = level_low >> 1; + fast_high = level_high << 1; + + if(fast_high>255) { + fast_high = 255; + } + + ret = write_reg(sensor->slv_addr, 0x3a0f, level_high) + || write_reg(sensor->slv_addr, 0x3a10, level_low) + || write_reg(sensor->slv_addr, 0x3a1b, level_high) + || write_reg(sensor->slv_addr, 0x3a1e, level_low) + || write_reg(sensor->slv_addr, 0x3a11, fast_high) + || write_reg(sensor->slv_addr, 0x3a1f, fast_low); + + if (ret == 0) { + ESP_LOGD(TAG, "Set ae_level to: %d", level); + sensor->status.ae_level = level; + } + return ret; +} + +static int set_wb_mode(sensor_t *sensor, int mode) +{ + int ret = 0; + if (mode < 0 || mode > 4) { + return -1; + } + + ret = write_reg(sensor->slv_addr, 0x3406, (mode != 0)); + if (ret) { + return ret; + } + switch (mode) { + case 1://Sunny + ret = write_reg16(sensor->slv_addr, 0x3400, 0x5e0) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x540);//AWB B GAIN + break; + case 2://Cloudy + ret = write_reg16(sensor->slv_addr, 0x3400, 0x650) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x4f0);//AWB B GAIN + break; + case 3://Office + ret = write_reg16(sensor->slv_addr, 0x3400, 0x520) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x660);//AWB B GAIN + break; + case 4://HOME + ret = write_reg16(sensor->slv_addr, 0x3400, 0x420) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x3f0) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x710);//AWB B GAIN + break; + default://AUTO + break; + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set wb_mode to: %d", mode); + sensor->status.wb_mode = mode; + } + return ret; +} + +static int set_awb_gain_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + int old_mode = sensor->status.wb_mode; + int mode = enable?old_mode:0; + + ret = set_wb_mode(sensor, mode); + + if (ret == 0) { + sensor->status.wb_mode = old_mode; + ESP_LOGD(TAG, "Set awb_gain to: %d", enable); + sensor->status.awb_gain = enable; + } + return ret; +} + +static int set_special_effect(sensor_t *sensor, int effect) +{ + int ret=0; + if (effect < 0 || effect > 6) { + return -1; + } + + uint8_t * regs = (uint8_t *)sensor_special_effects[effect]; + ret = write_reg(sensor->slv_addr, 0x5580, regs[0]) + || write_reg(sensor->slv_addr, 0x5583, regs[1]) + || write_reg(sensor->slv_addr, 0x5584, regs[2]) + || write_reg(sensor->slv_addr, 0x5003, regs[3]); + + if (ret == 0) { + ESP_LOGD(TAG, "Set special_effect to: %d", effect); + sensor->status.special_effect = effect; + } + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + uint8_t value = 0; + bool negative = false; + + switch (level) { + case 3: + value = 0x30; + break; + case 2: + value = 0x20; + break; + case 1: + value = 0x10; + break; + case -1: + value = 0x10; + negative = true; + break; + case -2: + value = 0x20; + negative = true; + break; + case -3: + value = 0x30; + negative = true; + break; + default: // 0 + break; + } + + ret = write_reg(sensor->slv_addr, 0x5587, value); + if (ret == 0) { + ret = write_reg_bits(sensor->slv_addr, 0x5588, 0x08, negative); + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set brightness to: %d", level); + sensor->status.brightness = level; + } + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 3 || level < -3) { + return -1; + } + ret = write_reg(sensor->slv_addr, 0x5586, (level + 4) << 3); + + if (ret == 0) { + ESP_LOGD(TAG, "Set contrast to: %d", level); + sensor->status.contrast = level; + } + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 4 || level < -4) { + return -1; + } + + uint8_t * regs = (uint8_t *)sensor_saturation_levels[level+4]; + for(int i=0; i<11; i++) { + ret = write_reg(sensor->slv_addr, 0x5381 + i, regs[i]); + if (ret) { + break; + } + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set saturation to: %d", level); + sensor->status.saturation = level; + } + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 3 || level < -3) { + return -1; + } + + uint8_t mt_offset_2 = (level + 3) * 8; + uint8_t mt_offset_1 = mt_offset_2 + 1; + + ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto + || write_reg(sensor->slv_addr, 0x5300, 0x10) + || write_reg(sensor->slv_addr, 0x5301, 0x10) + || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) + || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) + || write_reg(sensor->slv_addr, 0x5309, 0x10) + || write_reg(sensor->slv_addr, 0x530a, 0x10) + || write_reg(sensor->slv_addr, 0x530b, 0x04) + || write_reg(sensor->slv_addr, 0x530c, 0x06); + + if (ret == 0) { + ESP_LOGD(TAG, "Set sharpness to: %d", level); + sensor->status.sharpness = level; + } + return ret; +} + +static int set_gainceiling(sensor_t *sensor, gainceiling_t level) +{ + int ret = 0, l = (int)level; + + ret = write_reg(sensor->slv_addr, 0x3A18, (l >> 8) & 3) + || write_reg(sensor->slv_addr, 0x3A19, l & 0xFF); + + if (ret == 0) { + ESP_LOGD(TAG, "Set gainceiling to: %d", l); + sensor->status.gainceiling = l; + } + return ret; +} + +static int get_denoise(sensor_t *sensor) +{ + if (!check_reg_mask(sensor->slv_addr, 0x5308, 0x10)) { + return 0; + } + return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; +} + +static int set_denoise(sensor_t *sensor, int level) +{ + int ret = 0; + if (level < 0 || level > 8) { + return -1; + } + + ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x10, level > 0); + if (ret == 0 && level > 0) { + ret = write_reg(sensor->slv_addr, 0x5306, (level - 1) * 4); + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set denoise to: %d", level); + sensor->status.denoise = level; + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0, ret2 = 0; + if(mask > 0xFF){ + ret = read_reg16(sensor->slv_addr, reg); + if(ret >= 0 && mask > 0xFFFF){ + ret2 = read_reg(sensor->slv_addr, reg+2); + if(ret2 >= 0){ + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0, ret2 = 0; + if(mask > 0xFF){ + ret = read_reg16(sensor->slv_addr, reg); + if(ret >= 0 && mask > 0xFFFF){ + ret2 = read_reg(sensor->slv_addr, reg+2); + if(ret2 >= 0){ + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + if(mask > 0xFFFF){ + ret = write_reg16(sensor->slv_addr, reg, value >> 8); + if(ret >= 0){ + ret = write_reg(sensor->slv_addr, reg+2, value & 0xFF); + } + } else if(mask > 0xFF){ + ret = write_reg16(sensor->slv_addr, reg, value); + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) +{ + int ret = 0; + ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) + || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) + || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) + || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY) + || write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, scale); + if(!ret){ + sensor->status.scale = scale; + sensor->status.binning = binning; + ret = set_image_options(sensor); + } + return ret; +} + +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) +{ + return set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); +} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x5303) / 8) - 3; + sensor->status.denoise = get_denoise(sensor); + sensor->status.ae_level = 0; + sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x3A18) & 0x3FF; + sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x01); + sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); + sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); + sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); + sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); + sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); + sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); + sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); + sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); + sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3406, 0x01); + sensor->status.agc_gain = get_agc_gain(sensor); + sensor->status.aec_value = get_aec_value(sensor); + sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3a00, 0x04); + return 0; +} + +int ov3660_detect(int slv_addr, sensor_id_t *id) +{ + if (OV3660_SCCB_ADDR == slv_addr) { + uint8_t h = SCCB_Read16(slv_addr, 0x300A); + uint8_t l = SCCB_Read16(slv_addr, 0x300B); + uint16_t PID = (h<<8) | l; + if (OV3660_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int ov3660_init(sensor_t *sensor) +{ + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_contrast; + sensor->set_brightness = set_brightness; + sensor->set_saturation = set_saturation; + sensor->set_sharpness = set_sharpness; + sensor->set_gainceiling = set_gainceiling; + sensor->set_quality = set_quality; + sensor->set_colorbar = set_colorbar; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_whitebal = set_whitebal; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->init_status = init_status; + sensor->set_aec2 = set_aec2; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = set_special_effect; + sensor->set_wb_mode = set_wb_mode; + sensor->set_ae_level = set_ae_level; + sensor->set_dcw = set_dcw_dsp; + sensor->set_bpc = set_bpc_dsp; + sensor->set_wpc = set_wpc_dsp; + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + sensor->set_denoise = set_denoise; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c new file mode 100644 index 0000000000..a32b374f54 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c @@ -0,0 +1,1130 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV3660 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "ov5640.h" +#include "ov5640_regs.h" +#include "ov5640_settings.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char *TAG = "ov5640"; +#endif + +//#define REG_DEBUG_ON + +static int read_reg(uint8_t slv_addr, const uint16_t reg){ + int ret = SCCB_Read16(slv_addr, reg); +#ifdef REG_DEBUG_ON + if (ret < 0) { + ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask){ + return (read_reg(slv_addr, reg) & mask) == mask; +} + +static int read_reg16(uint8_t slv_addr, const uint16_t reg){ + int ret = 0, ret2 = 0; + ret = read_reg(slv_addr, reg); + if (ret >= 0) { + ret = (ret & 0xFF) << 8; + ret2 = read_reg(slv_addr, reg+1); + if (ret2 < 0) { + ret = ret2; + } else { + ret |= ret2 & 0xFF; + } + } + return ret; +} + +//static void dump_reg(sensor_t *sensor, const uint16_t reg){ +// int v = SCCB_Read16(sensor->slv_addr, reg); +// if(v < 0){ +// ets_printf(" 0x%04x: FAIL[%d]\n", reg, v); +// } else { +// ets_printf(" 0x%04x: 0x%02X\n", reg, v); +// } +//} +// +//static void dump_range(sensor_t *sensor, const char * name, const uint16_t start_reg, const uint16_t end_reg){ +// ets_printf("%s: 0x%04x - 0x%04X\n", name, start_reg, end_reg); +// for(uint16_t reg = start_reg; reg <= end_reg; reg++){ +// dump_reg(sensor, reg); +// } +//} +// +//static void dump_regs(sensor_t *sensor){ +//// dump_range(sensor, "All Regs", 0x3000, 0x6100); +//// dump_range(sensor, "system and IO pad control", 0x3000, 0x3052); +//// dump_range(sensor, "SCCB control", 0x3100, 0x3108); +//// dump_range(sensor, "SRB control", 0x3200, 0x3211); +//// dump_range(sensor, "AWB gain control", 0x3400, 0x3406); +//// dump_range(sensor, "AEC/AGC control", 0x3500, 0x350D); +//// dump_range(sensor, "VCM control", 0x3600, 0x3606); +//// dump_range(sensor, "timing control", 0x3800, 0x3821); +//// dump_range(sensor, "AEC/AGC power down domain control", 0x3A00, 0x3A25); +//// dump_range(sensor, "strobe control", 0x3B00, 0x3B0C); +//// dump_range(sensor, "50/60Hz detector control", 0x3C00, 0x3C1E); +//// dump_range(sensor, "OTP control", 0x3D00, 0x3D21); +//// dump_range(sensor, "MC control", 0x3F00, 0x3F0D); +//// dump_range(sensor, "BLC control", 0x4000, 0x4033); +//// dump_range(sensor, "frame control", 0x4201, 0x4202); +//// dump_range(sensor, "format control", 0x4300, 0x430D); +//// dump_range(sensor, "JPEG control", 0x4400, 0x4431); +//// dump_range(sensor, "VFIFO control", 0x4600, 0x460D); +//// dump_range(sensor, "DVP control", 0x4709, 0x4745); +//// dump_range(sensor, "MIPI control", 0x4800, 0x4837); +//// dump_range(sensor, "ISP frame control", 0x4901, 0x4902); +//// dump_range(sensor, "ISP top control", 0x5000, 0x5063); +//// dump_range(sensor, "AWB control", 0x5180, 0x51D0); +//// dump_range(sensor, "CIP control", 0x5300, 0x530F); +//// dump_range(sensor, "CMX control", 0x5380, 0x538B); +//// dump_range(sensor, "gamma control", 0x5480, 0x5490); +//// dump_range(sensor, "SDE control", 0x5580, 0x558C); +//// dump_range(sensor, "scale control", 0x5600, 0x5606); +//// dump_range(sensor, "AVG control", 0x5680, 0x56A2); +//// dump_range(sensor, "LENC control", 0x5800, 0x5849); +//// dump_range(sensor, "AFC control", 0x6000, 0x603F); +//} + +static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value){ + int ret = 0; +#ifndef REG_DEBUG_ON + ret = SCCB_Write16(slv_addr, reg, value); +#else + int old_value = read_reg(slv_addr, reg); + if (old_value < 0) { + return old_value; + } + if ((uint8_t)old_value != value) { + ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); + ret = SCCB_Write16(slv_addr, reg, value); + } else { + ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); + ret = SCCB_Write16(slv_addr, reg, value);//maybe not? + } + if (ret < 0) { + ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); + } +#endif + return ret; +} + +static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + int ret = 0; + uint8_t c_value, new_value; + ret = read_reg(slv_addr, reg); + if(ret < 0) { + return ret; + } + c_value = ret; + new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); + ret = write_reg(slv_addr, reg, new_value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) +{ + int i = 0, ret = 0; + while (!ret && regs[i][0] != REGLIST_TAIL) { + if (regs[i][0] == REG_DLY) { + vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); + } else { + ret = write_reg(slv_addr, regs[i][0], regs[i][1]); + } + i++; + } + return ret; +} + +static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) +{ + if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { + return -1; + } + return 0; +} + +static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) +{ + if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { + return -1; + } + return 0; +} + +#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, (enable)?(mask):0) + +static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pre_div, bool root_2x, int pclk_root_div, bool pclk_manual, int pclk_div) +{ + const float pll_pre_div2x_map[] = { 1, 1, 2, 3, 4, 1.5, 6, 2.5, 8}; + const int pll_pclk_root_div_map[] = { 1, 2, 4, 8 }; + + if(!pll_sys_div) { + pll_sys_div = 1; + } + + float pll_pre_div = pll_pre_div2x_map[pre_div]; + unsigned int root_2x_div = root_2x?2:1; + unsigned int pll_pclk_root_div = pll_pclk_root_div_map[pclk_root_div]; + + unsigned int REFIN = xclk / pll_pre_div; + + unsigned int VCO = REFIN * pll_multiplier / root_2x_div; + + unsigned int PLL_CLK = pll_bypass?(xclk):(VCO / pll_sys_div * 2 / 5);//5 here is 10bit mode / 2, for 8bit it should be 4 (reg 0x3034) + + unsigned int PCLK = PLL_CLK / pll_pclk_root_div / ((pclk_manual && pclk_div)?pclk_div:2); + + unsigned int SYSCLK = PLL_CLK / 4; + + ESP_LOGI(TAG, "Calculated XVCLK: %d Hz, REFIN: %u Hz, VCO: %u Hz, PLL_CLK: %u Hz, SYSCLK: %u Hz, PCLK: %u Hz", xclk, REFIN, VCO, PLL_CLK, SYSCLK, PCLK); + return SYSCLK; +} + +static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t pclk_root_div, bool pclk_manual, uint8_t pclk_div){ + int ret = 0; + if(multiplier > 252 || multiplier < 4 || sys_div > 15 || pre_div > 8 || pclk_div > 31 || pclk_root_div > 3){ + ESP_LOGE(TAG, "Invalid arguments"); + return -1; + } + if(multiplier > 127){ + multiplier &= 0xFE;//only even integers above 127 + } + ESP_LOGI(TAG, "Set PLL: bypass: %u, multiplier: %u, sys_div: %u, pre_div: %u, root_2x: %u, pclk_root_div: %u, pclk_manual: %u, pclk_div: %u", bypass, multiplier, sys_div, pre_div, root_2x, pclk_root_div, pclk_manual, pclk_div); + + calc_sysclk(sensor->xclk_freq_hz, bypass, multiplier, sys_div, pre_div, root_2x, pclk_root_div, pclk_manual, pclk_div); + + ret = write_reg(sensor->slv_addr, 0x3039, bypass?0x80:0x00); + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3034, 0x1A);//10bit mode + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3035, 0x01 | ((sys_div & 0x0f) << 4)); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3036, multiplier & 0xff); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3037, (pre_div & 0xf) | (root_2x?0x10:0x00)); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3108, (pclk_root_div & 0x3) << 4 | 0x06); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3824, pclk_div & 0x1f); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x460C, pclk_manual?0x22:0x20); + } + if (ret == 0) { + ret = write_reg(sensor->slv_addr, 0x3103, 0x13);// system clock from pll, bit[1] + } + if(ret){ + ESP_LOGE(TAG, "set_sensor_pll FAILED!"); + } + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level); + +static int reset(sensor_t *sensor) +{ + //dump_regs(sensor); + vTaskDelay(100 / portTICK_PERIOD_MS); + int ret = 0; + // Software Reset: clear all registers and reset them to their default values + ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x82); + if(ret){ + ESP_LOGE(TAG, "Software Reset FAILED!"); + return ret; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + ret = write_regs(sensor->slv_addr, sensor_default_regs); + if (ret == 0) { + ESP_LOGD(TAG, "Camera defaults loaded"); + vTaskDelay(100 / portTICK_PERIOD_MS); + //write_regs(sensor->slv_addr, sensor_regs_awb0); + //write_regs(sensor->slv_addr, sensor_regs_gamma1); + } + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret = 0; + const uint16_t (*regs)[2]; + + switch (pixformat) { + case PIXFORMAT_YUV422: + regs = sensor_fmt_yuv422; + break; + + case PIXFORMAT_GRAYSCALE: + regs = sensor_fmt_grayscale; + break; + + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + regs = sensor_fmt_rgb565; + break; + + case PIXFORMAT_JPEG: + regs = sensor_fmt_jpeg; + break; + + case PIXFORMAT_RAW: + regs = sensor_fmt_raw; + break; + + default: + ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); + return -1; + } + + ret = write_regs(sensor->slv_addr, regs); + if(ret == 0) { + sensor->pixformat = pixformat; + ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); + } + return ret; +} + +static int set_image_options(sensor_t *sensor) +{ + int ret = 0; + uint8_t reg20 = 0; + uint8_t reg21 = 0; + uint8_t reg4514 = 0; + uint8_t reg4514_test = 0; + + // compression + if (sensor->pixformat == PIXFORMAT_JPEG) { + reg21 |= 0x20; + } + + // binning + if (!sensor->status.binning) { + reg20 |= 0x40; + } else { + reg20 |= 0x01; + reg21 |= 0x01; + reg4514_test |= 4; + } + + // V-Flip + if (sensor->status.vflip) { + reg20 |= 0x06; + reg4514_test |= 1; + } + + // H-Mirror + if (sensor->status.hmirror) { + reg21 |= 0x06; + reg4514_test |= 2; + } + + switch (reg4514_test) { + //no binning + case 0: reg4514 = 0x88; break;//normal + case 1: reg4514 = 0x00; break;//v-flip + case 2: reg4514 = 0xbb; break;//h-mirror + case 3: reg4514 = 0x00; break;//v-flip+h-mirror + //binning + case 4: reg4514 = 0xaa; break;//normal + case 5: reg4514 = 0xbb; break;//v-flip + case 6: reg4514 = 0xbb; break;//h-mirror + case 7: reg4514 = 0xaa; break;//v-flip+h-mirror + } + + if(write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20) + || write_reg(sensor->slv_addr, TIMING_TC_REG21, reg21) + || write_reg(sensor->slv_addr, 0x4514, reg4514)){ + ESP_LOGE(TAG, "Setting Image Options Failed"); + return -1; + } + + if (!sensor->status.binning) { + ret = write_reg(sensor->slv_addr, 0x4520, 0x10) + || write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1 + || write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1 + } else { + ret = write_reg(sensor->slv_addr, 0x4520, 0x0b) + || write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1 + || write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1 + } + + ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", + sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret = 0; + framesize_t old_framesize = sensor->status.framesize; + sensor->status.framesize = framesize; + + if(framesize > FRAMESIZE_QSXGA){ + ESP_LOGE(TAG, "Invalid framesize: %u", framesize); + return -1; + } + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + aspect_ratio_t ratio = resolution[framesize].aspect_ratio; + ratio_settings_t settings = ratio_table[ratio]; + + sensor->status.binning = (w <= (settings.max_width / 2) && h <= (settings.max_height / 2)); + sensor->status.scale = !((w == settings.max_width && h == settings.max_height) + || (w == (settings.max_width / 2) && h == (settings.max_height / 2))); + + ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, settings.start_x, settings.start_y) + || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, settings.end_x, settings.end_y) + || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, w, h); + + if (ret) { + goto fail; + } + + if (!sensor->status.binning) { + ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, settings.total_y) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, settings.offset_x, settings.offset_y); + } else { + if (w > 920) { + ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x - 200, settings.total_y / 2); + } else { + ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, 2060, settings.total_y / 2); + } + if (ret == 0) { + ret = write_addr_reg(sensor->slv_addr, X_OFFSET_H, settings.offset_x / 2, settings.offset_y / 2); + } + } + + if (ret == 0) { + ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, sensor->status.scale); + } + + if (ret == 0) { + ret = set_image_options(sensor); + } + + if (ret) { + goto fail; + } + + if (sensor->pixformat == PIXFORMAT_JPEG) { + //10MHz PCLK + uint8_t sys_mul = 200; + if(framesize < FRAMESIZE_QVGA || sensor->xclk_freq_hz == 16000000){ + sys_mul = 160; + } else if(framesize < FRAMESIZE_XGA){ + sys_mul = 180; + } + ret = set_pll(sensor, false, sys_mul, 4, 2, false, 2, true, 4); + //Set PLL: bypass: 0, multiplier: sys_mul, sys_div: 4, pre_div: 2, root_2x: 0, pclk_root_div: 2, pclk_manual: 1, pclk_div: 4 + } else { + //ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4); + if (framesize > FRAMESIZE_HVGA) { + ret = set_pll(sensor, false, 10, 1, 2, false, 1, true, 2); + } else if (framesize >= FRAMESIZE_QVGA) { + ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4); + } else { + ret = set_pll(sensor, false, 20, 1, 1, false, 1, true, 8); + } + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); + } + return ret; + +fail: + sensor->status.framesize = old_framesize; + ESP_LOGE(TAG, "Setting framesize to: %ux%u failed", w, h); + return ret; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.hmirror = enable; + ret = set_image_options(sensor); + if (ret == 0) { + ESP_LOGD(TAG, "Set h-mirror to: %d", enable); + } + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + sensor->status.vflip = enable; + ret = set_image_options(sensor); + if (ret == 0) { + ESP_LOGD(TAG, "Set v-flip to: %d", enable); + } + return ret; +} + +static int set_quality(sensor_t *sensor, int qs) +{ + int ret = 0; + ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); + if (ret == 0) { + sensor->status.quality = qs; + ESP_LOGD(TAG, "Set quality to: %d", qs); + } + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); + if (ret == 0) { + sensor->status.colorbar = enable; + ESP_LOGD(TAG, "Set colorbar to: %d", enable); + } + return ret; +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); + sensor->status.agc = enable; + } + return ret; +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); + sensor->status.aec = enable; + } + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x01, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set awb to: %d", enable); + sensor->status.awb = enable; + } + return ret; +} + +//Advanced AWB +static int set_dcw_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5183, 0x80, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set dcw to: %d", enable); + sensor->status.dcw = enable; + } + return ret; +} + +//night mode enable +static int set_aec2(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x3a00, 0x04, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set aec2 to: %d", enable); + sensor->status.aec2 = enable; + } + return ret; +} + +static int set_bpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x04, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set bpc to: %d", enable); + sensor->status.bpc = enable; + } + return ret; +} + +static int set_wpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x02, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set wpc to: %d", enable); + sensor->status.wpc = enable; + } + return ret; +} + +//Gamma enable +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x20, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set raw_gma to: %d", enable); + sensor->status.raw_gma = enable; + } + return ret; +} + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x80, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set lenc to: %d", enable); + sensor->status.lenc = enable; + } + return ret; +} + +static int get_agc_gain(sensor_t *sensor) +{ + int ra = read_reg(sensor->slv_addr, 0x350a); + if (ra < 0) { + return 0; + } + int rb = read_reg(sensor->slv_addr, 0x350b); + if (rb < 0) { + return 0; + } + int res = (rb & 0xF0) >> 4 | (ra & 0x03) << 4; + if (rb & 0x0F) { + res += 1; + } + return res; +} + +//real gain +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + if(gain < 0) { + gain = 0; + } else if(gain > 64) { + gain = 64; + } + + //gain value is 6.4 bits float + //in order to use the max range, we deduct 1/16 + int gainv = gain << 4; + if(gainv){ + gainv -= 1; + } + + ret = write_reg(sensor->slv_addr, 0x350a, gainv >> 8) || write_reg(sensor->slv_addr, 0x350b, gainv & 0xff); + if (ret == 0) { + ESP_LOGD(TAG, "Set agc_gain to: %d", gain); + sensor->status.agc_gain = gain; + } + return ret; +} + +static int get_aec_value(sensor_t *sensor) +{ + int ra = read_reg(sensor->slv_addr, 0x3500); + if (ra < 0) { + return 0; + } + int rb = read_reg(sensor->slv_addr, 0x3501); + if (rb < 0) { + return 0; + } + int rc = read_reg(sensor->slv_addr, 0x3502); + if (rc < 0) { + return 0; + } + int res = (ra & 0x0F) << 12 | (rb & 0xFF) << 4 | (rc & 0xF0) >> 4; + return res; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0, max_val = 0; + max_val = read_reg16(sensor->slv_addr, 0x380e); + if (max_val < 0) { + ESP_LOGE(TAG, "Could not read max aec_value"); + return -1; + } + if (value > max_val) { + value =max_val; + } + + ret = write_reg(sensor->slv_addr, 0x3500, (value >> 12) & 0x0F) + || write_reg(sensor->slv_addr, 0x3501, (value >> 4) & 0xFF) + || write_reg(sensor->slv_addr, 0x3502, (value << 4) & 0xF0); + + if (ret == 0) { + ESP_LOGD(TAG, "Set aec_value to: %d / %d", value, max_val); + sensor->status.aec_value = value; + } + return ret; +} + +static int set_ae_level(sensor_t *sensor, int level) +{ + int ret = 0; + if (level < -5 || level > 5) { + return -1; + } + //good targets are between 5 and 115 + int target_level = ((level + 5) * 10) + 5; + + int level_high, level_low; + int fast_high, fast_low; + + level_low = target_level * 23 / 25; //0.92 (0.46) + level_high = target_level * 27 / 25; //1.08 (2.08) + + fast_low = level_low >> 1; + fast_high = level_high << 1; + + if(fast_high>255) { + fast_high = 255; + } + + ret = write_reg(sensor->slv_addr, 0x3a0f, level_high) + || write_reg(sensor->slv_addr, 0x3a10, level_low) + || write_reg(sensor->slv_addr, 0x3a1b, level_high) + || write_reg(sensor->slv_addr, 0x3a1e, level_low) + || write_reg(sensor->slv_addr, 0x3a11, fast_high) + || write_reg(sensor->slv_addr, 0x3a1f, fast_low); + + if (ret == 0) { + ESP_LOGD(TAG, "Set ae_level to: %d", level); + sensor->status.ae_level = level; + } + return ret; +} + +static int set_wb_mode(sensor_t *sensor, int mode) +{ + int ret = 0; + if (mode < 0 || mode > 4) { + return -1; + } + + ret = write_reg(sensor->slv_addr, 0x3406, (mode != 0)); + if (ret) { + return ret; + } + switch (mode) { + case 1://Sunny + ret = write_reg16(sensor->slv_addr, 0x3400, 0x5e0) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x540);//AWB B GAIN + break; + case 2://Cloudy + ret = write_reg16(sensor->slv_addr, 0x3400, 0x650) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x4f0);//AWB B GAIN + break; + case 3://Office + ret = write_reg16(sensor->slv_addr, 0x3400, 0x520) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x660);//AWB B GAIN + break; + case 4://HOME + ret = write_reg16(sensor->slv_addr, 0x3400, 0x420) //AWB R GAIN + || write_reg16(sensor->slv_addr, 0x3402, 0x3f0) //AWB G GAIN + || write_reg16(sensor->slv_addr, 0x3404, 0x710);//AWB B GAIN + break; + default://AUTO + break; + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set wb_mode to: %d", mode); + sensor->status.wb_mode = mode; + } + return ret; +} + +static int set_awb_gain_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + int old_mode = sensor->status.wb_mode; + int mode = enable?old_mode:0; + + ret = set_wb_mode(sensor, mode); + + if (ret == 0) { + sensor->status.wb_mode = old_mode; + ESP_LOGD(TAG, "Set awb_gain to: %d", enable); + sensor->status.awb_gain = enable; + } + return ret; +} + +static int set_special_effect(sensor_t *sensor, int effect) +{ + int ret=0; + if (effect < 0 || effect > 6) { + return -1; + } + + uint8_t * regs = (uint8_t *)sensor_special_effects[effect]; + ret = write_reg(sensor->slv_addr, 0x5580, regs[0]) + || write_reg(sensor->slv_addr, 0x5583, regs[1]) + || write_reg(sensor->slv_addr, 0x5584, regs[2]) + || write_reg(sensor->slv_addr, 0x5003, regs[3]); + + if (ret == 0) { + ESP_LOGD(TAG, "Set special_effect to: %d", effect); + sensor->status.special_effect = effect; + } + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + uint8_t value = 0; + bool negative = false; + + switch (level) { + case 3: + value = 0x30; + break; + case 2: + value = 0x20; + break; + case 1: + value = 0x10; + break; + case -1: + value = 0x10; + negative = true; + break; + case -2: + value = 0x20; + negative = true; + break; + case -3: + value = 0x30; + negative = true; + break; + default: // 0 + break; + } + + ret = write_reg(sensor->slv_addr, 0x5587, value); + if (ret == 0) { + ret = write_reg_bits(sensor->slv_addr, 0x5588, 0x08, negative); + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set brightness to: %d", level); + sensor->status.brightness = level; + } + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 3 || level < -3) { + return -1; + } + ret = write_reg(sensor->slv_addr, 0x5586, (level + 4) << 3); + + if (ret == 0) { + ESP_LOGD(TAG, "Set contrast to: %d", level); + sensor->status.contrast = level; + } + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 4 || level < -4) { + return -1; + } + + uint8_t * regs = (uint8_t *)sensor_saturation_levels[level+4]; + for(int i=0; i<11; i++) { + ret = write_reg(sensor->slv_addr, 0x5381 + i, regs[i]); + if (ret) { + break; + } + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set saturation to: %d", level); + sensor->status.saturation = level; + } + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + if(level > 3 || level < -3) { + return -1; + } + + uint8_t mt_offset_2 = (level + 3) * 8; + uint8_t mt_offset_1 = mt_offset_2 + 1; + + ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto + || write_reg(sensor->slv_addr, 0x5300, 0x10) + || write_reg(sensor->slv_addr, 0x5301, 0x10) + || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) + || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) + || write_reg(sensor->slv_addr, 0x5309, 0x10) + || write_reg(sensor->slv_addr, 0x530a, 0x10) + || write_reg(sensor->slv_addr, 0x530b, 0x04) + || write_reg(sensor->slv_addr, 0x530c, 0x06); + + if (ret == 0) { + ESP_LOGD(TAG, "Set sharpness to: %d", level); + sensor->status.sharpness = level; + } + return ret; +} + +static int set_gainceiling(sensor_t *sensor, gainceiling_t level) +{ + int ret = 0, l = (int)level; + + ret = write_reg(sensor->slv_addr, 0x3A18, (l >> 8) & 3) + || write_reg(sensor->slv_addr, 0x3A19, l & 0xFF); + + if (ret == 0) { + ESP_LOGD(TAG, "Set gainceiling to: %d", l); + sensor->status.gainceiling = l; + } + return ret; +} + +static int get_denoise(sensor_t *sensor) +{ + if (!check_reg_mask(sensor->slv_addr, 0x5308, 0x10)) { + return 0; + } + return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; +} + +static int set_denoise(sensor_t *sensor, int level) +{ + int ret = 0; + if (level < 0 || level > 8) { + return -1; + } + + ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x10, level > 0); + if (ret == 0 && level > 0) { + ret = write_reg(sensor->slv_addr, 0x5306, (level - 1) * 4); + } + + if (ret == 0) { + ESP_LOGD(TAG, "Set denoise to: %d", level); + sensor->status.denoise = level; + } + return ret; +} + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0, ret2 = 0; + if(mask > 0xFF){ + ret = read_reg16(sensor->slv_addr, reg); + if(ret >= 0 && mask > 0xFFFF){ + ret2 = read_reg(sensor->slv_addr, reg+2); + if(ret2 >= 0){ + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0, ret2 = 0; + if(mask > 0xFF){ + ret = read_reg16(sensor->slv_addr, reg); + if(ret >= 0 && mask > 0xFFFF){ + ret2 = read_reg(sensor->slv_addr, reg+2); + if(ret2 >= 0){ + ret = (ret << 8) | ret2 ; + } else { + ret = ret2; + } + } + } else { + ret = read_reg(sensor->slv_addr, reg); + } + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + if(mask > 0xFFFF){ + ret = write_reg16(sensor->slv_addr, reg, value >> 8); + if(ret >= 0){ + ret = write_reg(sensor->slv_addr, reg+2, value & 0xFF); + } + } else if(mask > 0xFF){ + ret = write_reg16(sensor->slv_addr, reg, value); + } else { + ret = write_reg(sensor->slv_addr, reg, value); + } + return ret; +} + +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) +{ + int ret = 0; + ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) + || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) + || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) + || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) + || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY) + || write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, scale); + if(!ret){ + sensor->status.scale = scale; + sensor->status.binning = binning; + ret = set_image_options(sensor); + } + return ret; +} + +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) +{ + int ret = 0; + ret = set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); + return ret; +} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = 0; + sensor->status.contrast = 0; + sensor->status.saturation = 0; + sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x5303) / 8) - 3; + sensor->status.denoise = get_denoise(sensor); + sensor->status.ae_level = 0; + sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x3A18) & 0x3FF; + sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x01); + sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); + sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); + sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); + sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); + sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); + sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); + sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); + sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); + sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); + sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); + sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; + sensor->status.special_effect = 0; + sensor->status.wb_mode = 0; + sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3406, 0x01); + sensor->status.agc_gain = get_agc_gain(sensor); + sensor->status.aec_value = get_aec_value(sensor); + sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3a00, 0x04); + return 0; +} + +int ov5640_detect(int slv_addr, sensor_id_t *id) +{ + if (OV5640_SCCB_ADDR == slv_addr) { + uint8_t h = SCCB_Read16(slv_addr, 0x300A); + uint8_t l = SCCB_Read16(slv_addr, 0x300B); + uint16_t PID = (h<<8) | l; + if (OV5640_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int ov5640_init(sensor_t *sensor) +{ + sensor->reset = reset; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_contrast = set_contrast; + sensor->set_brightness = set_brightness; + sensor->set_saturation = set_saturation; + sensor->set_sharpness = set_sharpness; + sensor->set_gainceiling = set_gainceiling; + sensor->set_quality = set_quality; + sensor->set_colorbar = set_colorbar; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_whitebal = set_whitebal; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->init_status = init_status; + sensor->set_aec2 = set_aec2; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = set_special_effect; + sensor->set_wb_mode = set_wb_mode; + sensor->set_ae_level = set_ae_level; + sensor->set_dcw = set_dcw_dsp; + sensor->set_bpc = set_bpc_dsp; + sensor->set_wpc = set_wpc_dsp; + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + sensor->set_denoise = set_denoise; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c new file mode 100644 index 0000000000..c683eda041 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c @@ -0,0 +1,457 @@ +/* + * This file is part of the OpenMV project. + * author: Juan Schiavoni + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7725 driver. + * + */ +#include +#include +#include +#include "sccb.h" +#include "ov7670.h" +#include "ov7670_regs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "ov7760"; +#endif + +static int ov7670_clkrc = 0x01; + +/* + * The default register settings, as obtained from OmniVision. There + * is really no making sense of most of these - lots of "reserved" values + * and such. + * + * These settings give VGA YUYV. + */ +struct regval_list { + uint8_t reg_num; + uint8_t value; +}; + +static struct regval_list ov7670_default_regs[] = { + /* Sensor automatically sets output window when resolution changes. */ + {TSLB, 0x04}, + + /* Frame rate 30 fps at 12 Mhz clock */ + {CLKRC, 0x00}, + {DBLV, 0x4A}, + + {COM10, COM10_VSYNC_NEG | COM10_PCLK_FREE}, + + /* Improve white balance */ + {COM4, 0x40}, + + /* Improve color */ + {RSVD_B0, 0x84}, + + /* Enable 50/60 Hz auto detection */ + {COM11, COM11_EXP|COM11_HZAUTO}, + + /* Disable some delays */ + {HSYST, 0}, + {HSYEN, 0}, + + {MVFP, MVFP_SUN}, + + /* More reserved magic, some of which tweaks white balance */ + {AWBC1, 0x0a}, + {AWBC2, 0xf0}, + {AWBC3, 0x34}, + {AWBC4, 0x58}, + {AWBC5, 0x28}, + {AWBC6, 0x3a}, + + {AWBCTR3, 0x0a}, + {AWBCTR2, 0x55}, + {AWBCTR1, 0x11}, + {AWBCTR0, 0x9e}, + + {COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN}, + + /* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */ + {0xFF, 0xFF}, +}; + +static struct regval_list ov7670_fmt_yuv422[] = { + { COM7, 0x0 }, /* Selects YUV mode */ + { RGB444, 0 }, /* No RGB444 please */ + { COM1, 0 }, /* CCIR601 */ + { COM15, COM15_R00FF }, + { MVFP, MVFP_SUN }, + { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ + { MTX1, 0x80 }, /* "matrix coefficient 1" */ + { MTX2, 0x80 }, /* "matrix coefficient 2" */ + { MTX3, 0 }, /* vb */ + { MTX4, 0x22 }, /* "matrix coefficient 4" */ + { MTX5, 0x5e }, /* "matrix coefficient 5" */ + { MTX6, 0x80 }, /* "matrix coefficient 6" */ + { COM13, COM13_UVSAT }, + { 0xff, 0xff }, /* END MARKER */ +}; + +static struct regval_list ov7670_fmt_rgb565[] = { + { COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */ + { RGB444, 0 }, /* No RGB444 please */ + { COM1, 0x0 }, /* CCIR601 */ + { COM15, COM15_RGB565 |COM15_R00FF }, + { MVFP, MVFP_SUN }, + { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ + { MTX1, 0xb3 }, /* "matrix coefficient 1" */ + { MTX2, 0xb3 }, /* "matrix coefficient 2" */ + { MTX3, 0 }, /* vb */ + { MTX4, 0x3d }, /* "matrix coefficient 4" */ + { MTX5, 0xa7 }, /* "matrix coefficient 5" */ + { MTX6, 0xe4 }, /* "matrix coefficient 6" */ + { COM13, COM13_UVSAT }, + { 0xff, 0xff }, /* END MARKER */ +}; + + +static struct regval_list ov7670_vga[] = { + { COM3, 0x00 }, + { COM14, 0x00 }, + { SCALING_XSC, 0x3A }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x11 }, + { SCALING_PCLK_DIV, 0xF0 }, + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +static struct regval_list ov7670_qvga[] = { + { COM3, 0x04 }, + { COM14, 0x19 }, + { SCALING_XSC, 0x3A }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x11 }, + { SCALING_PCLK_DIV, 0xF1 }, + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +static struct regval_list ov7670_qqvga[] = { + { COM3, 0x04 }, //DCW enable + { COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register + { SCALING_XSC, 0x3a }, + { SCALING_YSC, 0x35 }, + { SCALING_DCWCTR, 0x22 }, //downsample by 4 + { SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4 + { SCALING_PCLK_DELAY, 0x02 }, + { 0xff, 0xff }, +}; + +/* + * Write a list of register settings; ff/ff stops the process. + */ +static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals) +{ +int ret = 0; + + while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) { + ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value); + + ESP_LOGD(TAG, "reset reg %02X, W(%02X) R(%02X)", vals->reg_num, + vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) ); + + vals++; + } + + return ret; +} + +/* + * Calculate the frame control registers. + */ +static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop) +{ + struct regval_list frame[7]; + + frame[0].reg_num = HSTART; + frame[0].value = (hstart >> 3); + + frame[1].reg_num = HSTOP; + frame[1].value = (hstop >> 3); + + frame[2].reg_num = HREF; + frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07)); + + frame[3].reg_num = VSTART; + frame[3].value = (vstart >> 2); + + frame[4].reg_num = VSTOP; + frame[4].value = (vstop >> 2); + + frame[5].reg_num = VREF; + frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02)); + + /* End mark */ + frame[6].reg_num = 0xFF; + frame[6].value = 0xFF; + + return ov7670_write_array(sensor, frame); +} + +static int reset(sensor_t *sensor) +{ + int ret; + + // Reset all registers + SCCB_Write(sensor->slv_addr, COM7, COM7_RESET); + + // Delay 10 ms + vTaskDelay(10 / portTICK_PERIOD_MS); + + ret = ov7670_write_array(sensor, ov7670_default_regs); + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ +int ret; + + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_RGB888: + ret = ov7670_write_array(sensor, ov7670_fmt_rgb565); + break; + + case PIXFORMAT_YUV422: + case PIXFORMAT_GRAYSCALE: + default: + ret = ov7670_write_array(sensor, ov7670_fmt_yuv422); + break; + } + + vTaskDelay(30 / portTICK_PERIOD_MS); + + /* + * If we're running RGB565, we must rewrite clkrc after setting + * the other parameters or the image looks poor. If we're *not* + * doing RGB565, we must not rewrite clkrc or the image looks + * *really* poor. + * + * (Update) Now that we retain clkrc state, we should be able + * to write it unconditionally, and that will make the frame + * rate persistent too. + */ + if (pixformat == PIXFORMAT_RGB565) { + ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc); + } + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret; + + // store clkrc before changing window settings... + ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC); + + switch (framesize){ + case FRAMESIZE_VGA: + if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 10, 490); + } + break; + case FRAMESIZE_QVGA: + if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 10, 490); + } + break; + case FRAMESIZE_QQVGA: + if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) { + /* These values from Omnivision */ + ret = ov7670_frame_control(sensor, 158, 14, 12, 490); + } + break; + + default: + ret = -1; + } + + vTaskDelay(30 / portTICK_PERIOD_MS); + + if (ret == 0) { + sensor->status.framesize = framesize; + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + uint8_t ret = 0; + // Read register scaling_xsc + uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC); + + // Pattern to set color bar bit[0]=0 in every case + reg = SCALING_XSC_CBAR(reg); + + // Write pattern to SCALING_XSC + ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg); + + // Read register scaling_ysc + reg = SCCB_Read(sensor->slv_addr, SCALING_YSC); + + // Pattern to set color bar bit[0]=0 in every case + reg = SCALING_YSC_CBAR(reg, enable); + + // Write pattern to SCALING_YSC + ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg); + + // return 0 or 0xFF + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AWB(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AGC(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + // Read register COM8 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); + + // Set white bal on/off + reg = COM8_SET_AEC(reg, enable); + + // Write back register COM8 + return SCCB_Write(sensor->slv_addr, COM8, reg); +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + // Read register MVFP + uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); + + // Set mirror on/off + reg = MVFP_SET_MIRROR(reg, enable); + + // Write back register MVFP + return SCCB_Write(sensor->slv_addr, MVFP, reg); +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + // Read register MVFP + uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); + + // Set mirror on/off + reg = MVFP_SET_FLIP(reg, enable); + + // Write back register MVFP + return SCCB_Write(sensor->slv_addr, MVFP, reg); +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.awb = 0; + sensor->status.aec = 0; + sensor->status.agc = 0; + sensor->status.hmirror = 0; + sensor->status.vflip = 0; + sensor->status.colorbar = 0; + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } + +int ov7670_detect(int slv_addr, sensor_id_t *id) +{ + if (OV7670_SCCB_ADDR == slv_addr) { + SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor + uint16_t PID = SCCB_Read(slv_addr, 0x0A); + if (OV7670_PID == PID) { + id->PID = PID; + id->VER = SCCB_Read(slv_addr, REG_VER); + id->MIDL = SCCB_Read(slv_addr, REG_MIDL); + id->MIDH = SCCB_Read(slv_addr, REG_MIDH); + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int ov7670_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_whitebal; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + //not supported + sensor->set_brightness= set_dummy; + sensor->set_saturation= set_dummy; + sensor->set_quality = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + sensor->set_aec2 = set_dummy; + sensor->set_aec_value = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + sensor->set_dcw = set_dummy; + sensor->set_bpc = set_dummy; + sensor->set_wpc = set_dummy; + sensor->set_awb_gain = set_dummy; + sensor->set_agc_gain = set_dummy; + sensor->set_raw_gma = set_dummy; + sensor->set_lenc = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + + // Retrieve sensor's signature + sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH); + sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL); + sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID); + sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER); + + ESP_LOGD(TAG, "OV7670 Attached"); + + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c new file mode 100644 index 0000000000..9418a82f3f --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c @@ -0,0 +1,575 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7725 driver. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "ov7725.h" +#include "ov7725_regs.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "ov7725"; +#endif + + +static const uint8_t default_regs[][2] = { + {COM3, COM3_SWAP_YUV}, + {COM7, COM7_RES_QVGA | COM7_FMT_YUV}, + + {COM4, 0x01 | 0x00}, /* bypass PLL (0x00:off, 0x40:4x, 0x80:6x, 0xC0:8x) */ + {CLKRC, 0x80 | 0x03}, /* Res/Bypass pre-scalar (0x40:bypass, 0x00-0x3F:prescaler PCLK=XCLK/(prescaler + 1)/2 ) */ + + // QVGA Window Size + {HSTART, 0x3F}, + {HSIZE, 0x50}, + {VSTART, 0x03}, + {VSIZE, 0x78}, + {HREF, 0x00}, + + // Scale down to QVGA Resolution + {HOUTSIZE, 0x50}, + {VOUTSIZE, 0x78}, + {EXHCH, 0x00}, + + {COM12, 0x03}, + {TGT_B, 0x7F}, + {FIXGAIN, 0x09}, + {AWB_CTRL0, 0xE0}, + {DSP_CTRL1, 0xFF}, + + {DSP_CTRL2, DSP_CTRL2_VDCW_EN | DSP_CTRL2_HDCW_EN | DSP_CTRL2_HZOOM_EN | DSP_CTRL2_VZOOM_EN}, + + {DSP_CTRL3, 0x00}, + {DSP_CTRL4, 0x00}, + {DSPAUTO, 0xFF}, + + {COM8, 0xF0}, + {COM6, 0xC5}, + {COM9, 0x11}, + {COM10, COM10_VSYNC_NEG | COM10_PCLK_FREE}, //Invert VSYNC and MASK PCLK + {BDBASE, 0x7F}, + {DBSTEP, 0x03}, + {AEW, 0x75}, + {AEB, 0x64}, + {VPT, 0xA1}, + {EXHCL, 0x00}, + {AWB_CTRL3, 0xAA}, + {COM8, 0xFF}, + + //Gamma + {GAM1, 0x0C}, + {GAM2, 0x16}, + {GAM3, 0x2A}, + {GAM4, 0x4E}, + {GAM5, 0x61}, + {GAM6, 0x6F}, + {GAM7, 0x7B}, + {GAM8, 0x86}, + {GAM9, 0x8E}, + {GAM10, 0x97}, + {GAM11, 0xA4}, + {GAM12, 0xAF}, + {GAM13, 0xC5}, + {GAM14, 0xD7}, + {GAM15, 0xE8}, + + {SLOP, 0x20}, + {EDGE1, 0x05}, + {EDGE2, 0x03}, + {EDGE3, 0x00}, + {DNSOFF, 0x01}, + + {MTX1, 0xB0}, + {MTX2, 0x9D}, + {MTX3, 0x13}, + {MTX4, 0x16}, + {MTX5, 0x7B}, + {MTX6, 0x91}, + {MTX_CTRL, 0x1E}, + + {BRIGHTNESS, 0x08}, + {CONTRAST, 0x30}, + {UVADJ0, 0x81}, + {SDE, (SDE_CONT_BRIGHT_EN | SDE_SATURATION_EN)}, + + // For 30 fps/60Hz + {DM_LNL, 0x00}, + {DM_LNH, 0x00}, + {BDBASE, 0x7F}, + {DBSTEP, 0x03}, + + // Lens Correction, should be tuned with real camera module + {LC_RADI, 0x10}, + {LC_COEF, 0x10}, + {LC_COEFB, 0x14}, + {LC_COEFR, 0x17}, + {LC_CTR, 0x05}, + {COM5, 0xF5}, //0x65 + + {0x00, 0x00}, +}; + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); + return ret; +} + +static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); + return ret; +} + +static int get_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length) +{ + int ret = 0; + ret = SCCB_Read(sensor->slv_addr, reg); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + return (ret & mask) >> offset; +} + + +static int reset(sensor_t *sensor) +{ + int i=0; + const uint8_t (*regs)[2]; + + // Reset all registers + SCCB_Write(sensor->slv_addr, COM7, COM7_RESET); + + // Delay 10 ms + vTaskDelay(10 / portTICK_PERIOD_MS); + + // Write default regsiters + for (i=0, regs = default_regs; regs[i][0]; i++) { + SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); + } + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return 0; +} + + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret=0; + sensor->pixformat = pixformat; + // Read register COM7 + uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); + + switch (pixformat) { + case PIXFORMAT_RGB565: + reg = COM7_SET_RGB(reg, COM7_FMT_RGB565); + break; + case PIXFORMAT_YUV422: + case PIXFORMAT_GRAYSCALE: + reg = COM7_SET_FMT(reg, COM7_FMT_YUV); + break; + default: + return -1; + } + + // Write back register COM7 + ret = SCCB_Write(sensor->slv_addr, COM7, reg); + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + int ret=0; + if (framesize > FRAMESIZE_VGA) { + return -1; + } + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); + + sensor->status.framesize = framesize; + + // Write MSBs + ret |= SCCB_Write(sensor->slv_addr, HOUTSIZE, w>>2); + ret |= SCCB_Write(sensor->slv_addr, VOUTSIZE, h>>1); + + ret |= SCCB_Write(sensor->slv_addr, HSIZE, w>>2); + ret |= SCCB_Write(sensor->slv_addr, VSIZE, h>>1); + + // Write LSBs + ret |= SCCB_Write(sensor->slv_addr, HREF, ((w&0x3) | ((h&0x1) << 2))); + + if (framesize < FRAMESIZE_VGA) { + // Enable auto-scaling/zooming factors + ret |= SCCB_Write(sensor->slv_addr, DSPAUTO, 0xFF); + + ret |= SCCB_Write(sensor->slv_addr, HSTART, 0x3F); + ret |= SCCB_Write(sensor->slv_addr, VSTART, 0x03); + + ret |= SCCB_Write(sensor->slv_addr, COM7, reg | COM7_RES_QVGA); + + ret |= SCCB_Write(sensor->slv_addr, CLKRC, 0x80 | 0x01); + + } else { + // Disable auto-scaling/zooming factors + ret |= SCCB_Write(sensor->slv_addr, DSPAUTO, 0xF3); + + // Clear auto-scaling/zooming factors + ret |= SCCB_Write(sensor->slv_addr, SCAL0, 0x00); + ret |= SCCB_Write(sensor->slv_addr, SCAL1, 0x00); + ret |= SCCB_Write(sensor->slv_addr, SCAL2, 0x00); + + ret |= SCCB_Write(sensor->slv_addr, HSTART, 0x23); + ret |= SCCB_Write(sensor->slv_addr, VSTART, 0x07); + + ret |= SCCB_Write(sensor->slv_addr, COM7, reg & ~COM7_RES_QVGA); + + ret |= SCCB_Write(sensor->slv_addr, CLKRC, 0x80 | 0x03); + } + + // Delay + vTaskDelay(30 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret=0; + uint8_t reg; + sensor->status.colorbar = enable; + + // Read reg COM3 + reg = SCCB_Read(sensor->slv_addr, COM3); + // Enable colorbar test pattern output + reg = COM3_SET_CBAR(reg, enable); + // Write back COM3 + ret |= SCCB_Write(sensor->slv_addr, COM3, reg); + + // Read reg DSP_CTRL3 + reg = SCCB_Read(sensor->slv_addr, DSP_CTRL3); + // Enable DSP colorbar output + reg = DSP_CTRL3_SET_CBAR(reg, enable); + // Write back DSP_CTRL3 + ret |= SCCB_Write(sensor->slv_addr, DSP_CTRL3, reg); + + return ret; +} + +static int set_whitebal(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, COM8, 1, 1, enable) >= 0){ + sensor->status.awb = !!enable; + } + return sensor->status.awb; +} + +static int set_gain_ctrl(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, COM8, 2, 1, enable) >= 0){ + sensor->status.agc = !!enable; + } + return sensor->status.agc; +} + +static int set_exposure_ctrl(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, COM8, 0, 1, enable) >= 0){ + sensor->status.aec = !!enable; + } + return sensor->status.aec; +} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, COM3, 6, 1, enable) >= 0){ + sensor->status.hmirror = !!enable; + } + return sensor->status.hmirror; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + if(set_reg_bits(sensor, COM3, 7, 1, enable) >= 0){ + sensor->status.vflip = !!enable; + } + return sensor->status.vflip; +} + +static int set_dcw_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x65, 2, 1, !enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set dcw to: %d", enable); + sensor->status.dcw = enable; + } + return ret; +} + +static int set_aec2(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, COM8, 7, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set aec2 to: %d", enable); + sensor->status.aec2 = enable; + } + return ret; +} + +static int set_bpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x64, 1, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set bpc to: %d", enable); + sensor->status.bpc = enable; + } + return ret; +} + +static int set_wpc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x64, 0, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set wpc to: %d", enable); + sensor->status.wpc = enable; + } + return ret; +} + +static int set_raw_gma_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x64, 2, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set raw_gma to: %d", enable); + sensor->status.raw_gma = enable; + } + return ret; +} + +static int set_lenc_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, LC_CTR, 0, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set lenc to: %d", enable); + sensor->status.lenc = enable; + } + return ret; +} + +//real gain +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + ret = set_reg_bits(sensor, COM9, 4, 3, gain % 5); + if (ret == 0) { + ESP_LOGD(TAG, "Set gain to: %d", gain); + sensor->status.agc_gain = gain; + } + return ret; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, AEC, value & 0xff) | SCCB_Write(sensor->slv_addr, AECH, value >> 8); + if (ret == 0) { + ESP_LOGD(TAG, "Set aec_value to: %d", value); + sensor->status.aec_value = value; + } + return ret; +} + +static int set_awb_gain_dsp(sensor_t *sensor, int enable) +{ + int ret = 0; + ret = set_reg_bits(sensor, 0x63, 7, 1, enable); + if (ret == 0) { + ESP_LOGD(TAG, "Set awb_gain to: %d", enable); + sensor->status.awb_gain = enable; + } + return ret; +} + +static int set_brightness(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x9B, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set brightness to: %d", level); + sensor->status.brightness = level; + } + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + ret = SCCB_Write(sensor->slv_addr, 0x9C, level); + if (ret == 0) { + ESP_LOGD(TAG, "Set contrast to: %d", level); + sensor->status.contrast = level; + } + return ret; +} + +static int init_status(sensor_t *sensor) +{ + sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x9B); + sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0x9C); + sensor->status.saturation = 0; + sensor->status.ae_level = 0; + sensor->status.special_effect = get_reg_bits(sensor, 0x64, 5, 1); + sensor->status.wb_mode = get_reg_bits(sensor, 0x6B, 7, 1); + sensor->status.agc_gain = get_reg_bits(sensor, COM9, 4, 3); + sensor->status.aec_value = SCCB_Read(sensor->slv_addr, AEC) | (SCCB_Read(sensor->slv_addr, AECH) << 8); + sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x00); + sensor->status.awb = get_reg_bits(sensor, COM8, 1, 1); + sensor->status.awb_gain = get_reg_bits(sensor, 0x63, 7, 1); + sensor->status.aec = get_reg_bits(sensor, COM8, 0, 1); + sensor->status.aec2 = get_reg_bits(sensor, COM8, 7, 1); + sensor->status.agc = get_reg_bits(sensor, COM8, 2, 1); + sensor->status.bpc = get_reg_bits(sensor, 0x64, 1, 1); + sensor->status.wpc = get_reg_bits(sensor, 0x64, 0, 1); + sensor->status.raw_gma = get_reg_bits(sensor, 0x64, 2, 1); + sensor->status.lenc = get_reg_bits(sensor, LC_CTR, 0, 1); + sensor->status.hmirror = get_reg_bits(sensor, COM3, 6, 1); + sensor->status.vflip = get_reg_bits(sensor, COM3, 7, 1); + sensor->status.dcw = get_reg_bits(sensor, 0x65, 2, 1); + sensor->status.colorbar = get_reg_bits(sensor, COM3, 0, 1); + sensor->status.sharpness = get_reg_bits(sensor, EDGE0, 0, 5); + sensor->status.denoise = SCCB_Read(sensor->slv_addr, 0x8E); + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } +static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } +static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning){return -1;} +static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div){return -1;} + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int ov7725_detect(int slv_addr, sensor_id_t *id) +{ + if (OV7725_SCCB_ADDR == slv_addr) { + SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor + uint16_t PID = SCCB_Read(slv_addr, 0x0A); + if (OV7725_PID == PID) { + id->PID = PID; + id->VER = SCCB_Read(slv_addr, REG_VER); + id->MIDL = SCCB_Read(slv_addr, REG_MIDL); + id->MIDH = SCCB_Read(slv_addr, REG_MIDH); + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int ov7725_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_colorbar = set_colorbar; + sensor->set_whitebal = set_whitebal; + sensor->set_gain_ctrl = set_gain_ctrl; + sensor->set_exposure_ctrl = set_exposure_ctrl; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + + sensor->set_brightness = set_brightness; + sensor->set_contrast = set_contrast; + sensor->set_aec2 = set_aec2; + sensor->set_aec_value = set_aec_value; + sensor->set_awb_gain = set_awb_gain_dsp; + sensor->set_agc_gain = set_agc_gain; + sensor->set_dcw = set_dcw_dsp; + sensor->set_bpc = set_bpc_dsp; + sensor->set_wpc = set_wpc_dsp; + sensor->set_raw_gma = set_raw_gma_dsp; + sensor->set_lenc = set_lenc_dsp; + + //not supported + sensor->set_saturation= set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_quality = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + sensor->set_gainceiling = set_gainceiling_dummy; + + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_res_raw = set_res_raw; + sensor->set_pll = _set_pll; + sensor->set_xclk = set_xclk; + + // Retrieve sensor's signature + sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH); + sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL); + sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID); + sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER); + + ESP_LOGD(TAG, "OV7725 Attached"); + + return 0; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h new file mode 100644 index 0000000000..8c925eb5e5 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h @@ -0,0 +1,27 @@ + +#ifndef __BF20A6_H__ +#define __BF20A6_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int bf20a6_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int bf20a6_init(sensor_t *sensor); + +#endif // __BF20A6_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h new file mode 100644 index 0000000000..ab1ff69e94 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h @@ -0,0 +1,12 @@ +/* + * BF20A6 register definitions. + */ +#ifndef __BF20A6_REG_REGS_H__ +#define __BF20A6_REG_REGS_H__ + +#define SENSOR_ID_HIGH 0XFC +#define SENSOR_ID_LOW 0XFD +#define RESET_RELATED 0XF2 + + +#endif //__BF20A6_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h new file mode 100644 index 0000000000..0414bbacd6 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h @@ -0,0 +1,158 @@ + +#include + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0xffff /* Array end token */ + +static const uint16_t bf20a6_default_init_regs[][2] = { + {0xf2,0x01}, + {0x12,0x20}, + {0x3a,0x00}, + {0xe1,0x92}, + {0xe3,0x12},// PLL Control, important for framerate(choice: 0x02\0x12\0x22\0x32\0x82) + {0xe0,0x00}, + {0x2a,0x98}, + {0xcd,0x17}, + {0xc0,0x10}, + {0xc6,0x1d}, + {0x10,0x35}, + {0xe2,0x09}, + {0xe4,0x72}, + {0xe5,0x22}, + {0xe6,0x24}, + {0xe7,0x64}, + {0xe8,0xa2}, // DVP:a2}, SPI:f2 VDDIO=1.8V,E8[2]=1},VDDIO=2.8V,E8[2]=0}, + {0x4a,0x00}, + {0x00,0x03}, + {0x1f,0x02}, + {0x22,0x02}, + {0x0c,0x31}, + + {0x00,0x00}, + {0x60,0x81}, + {0x61,0x81}, + + {0xa0,0x08}, + {0x01,0x1a}, + // {0x01,0x1a}, + // {0x01,0x1a}, + // {0x02,0x15}, + // {0x02,0x15}, + {0x02,0x15}, + {0x13,0x08}, + {0x8a,0x96}, + {0x8b,0x06}, + {0x87,0x18}, + + + {0x34,0x48}, // lens + {0x35,0x40}, + {0x36,0x40}, + + {0x71,0x44}, + {0x72,0x48}, + {0x74,0xa2}, + {0x75,0xa9}, + {0x78,0x12}, + {0x79,0xa0}, + {0x7a,0x94}, + {0x7c,0x97}, + {0x40,0x30}, + {0x41,0x30}, + {0x42,0x28}, + {0x43,0x1f}, + {0x44,0x1c}, + {0x45,0x16}, + {0x46,0x13}, + {0x47,0x10}, + {0x48,0x0D}, + {0x49,0x0C}, + {0x4B,0x0A}, + {0x4C,0x0B}, + {0x4E,0x09}, + {0x4F,0x08}, + {0x50,0x08}, + + + {0x5f,0x29}, + {0x23,0x33}, + {0xa1,0x10}, // AWB + {0xa2,0x0d}, + {0xa3,0x30}, + {0xa4,0x06}, + {0xa5,0x22}, + {0xa6,0x56}, + {0xa7,0x18}, + {0xa8,0x1a}, + {0xa9,0x12}, + {0xaa,0x12}, + {0xab,0x16}, + {0xac,0xb1}, + {0xba,0x12}, + {0xbb,0x12}, + {0xad,0x12}, + {0xae,0x56}, + {0xaf,0x0a}, + {0x3b,0x30}, + {0x3c,0x12}, + {0x3d,0x22}, + {0x3e,0x3f}, + {0x3f,0x28}, + {0xb8,0xc3}, + {0xb9,0xa3}, + {0x39,0x47}, // pure color threshold + {0x26,0x13}, + {0x27,0x16}, + {0x28,0x14}, + {0x29,0x18}, + {0xee,0x0d}, + + + {0x13,0x05}, + {0x24,0x3C}, + {0x81,0x20}, + {0x82,0x40}, + {0x83,0x30}, + {0x84,0x58}, + {0x85,0x30}, + {0x92,0x08}, + {0x86,0x80}, + {0x8a,0x96}, + {0x91,0xff}, + {0x94,0x62}, + {0x9a,0x18}, // outdoor threshold + {0xf0,0x45}, // integral time control, important for framerate(choice: 0x46\0x45\0x44..) + {0x51,0x17}, // color normal + {0x52,0x03}, + {0x53,0x5F}, + {0x54,0x47}, + {0x55,0x66}, + {0x56,0x0F}, + {0x7e,0x14}, + {0x57,0x36}, // color + {0x58,0x2A}, + {0x59,0xAA}, + {0x5a,0xA8}, + {0x5b,0x43}, + {0x5c,0x10}, + {0x5d,0x00}, + {0x7d,0x36}, + {0x5e,0x10}, + + {0xd6,0x88}, // contrast + {0xd5,0x20}, // bright + {0xb0,0x84}, // low light ctrl in gray section + {0xb5,0x08}, // the threshold of GLB_GAIN + {0xb1,0xc8}, // saturation + {0xb2,0xc0}, + {0xb3,0xd0}, + {0xb4,0xB0}, + + {0x32,0x10}, + // {0x8a,0x00}, + // {0x8b,0x10}, + {0xa0,0x09}, + {0x00,0x03}, + {0x0b,0x02}, + {REGLIST_TAIL, 0x00}, +}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h new file mode 100644 index 0000000000..6524a1d495 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h @@ -0,0 +1,33 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * BF3005 driver. + * + */ +#ifndef __BF3005_H__ +#define __BF3005_H__ +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int bf3005_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int bf3005_init(sensor_t *sensor); + +#endif // __BF3005_H__ \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h new file mode 100644 index 0000000000..0bf0d37a7c --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h @@ -0,0 +1,337 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * BF3005 register definitions. + */ +#ifndef __REG_REGS_H__ +#define __REG_REGS_H__ +#if 0 +#define GAIN 0x00 /* AGC C Gain control gain setting */ +#define BLUE 0x01 /* AWB C Blue channel gain setting */ +#define RED 0x02 /* AWB C Red channel gain setting */ +#define GREEN 0x03 /* AWB C Green channel gain setting */ +#define BAVG 0x05 /* U/B Average Level */ +#define GAVG 0x06 /* Y/Gb Average Level */ +#define RAVG 0x07 /* V/R Average Level */ +#define AECH 0x08 /* Exposure Value C AEC MSBs */ + +#define COM2 0x09 /* Common Control 2 */ +#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ +#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ +#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ +#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ +#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ + +#define REG_PID 0x0A /* Product ID Number MSB */ +#define REG_VER 0x0B /* Product ID Number LSB */ + +#define COM3 0x0C /* Common Control 3 */ +#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */ +#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */ +#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */ +#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */ +#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */ +#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */ +#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */ +#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */ +#define COM3_SET_CBAR(r, x) ((r&0xFE)|((x&1)<<0)) +#define COM3_SET_MIRROR(r, x) ((r&0xBF)|((x&1)<<6)) +#define COM3_SET_FLIP(r, x) ((r&0x7F)|((x&1)<<7)) + +#define COM4 0x0D /* Common Control 4 */ +#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ +#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ +#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ +#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ +#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ +#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ +#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ +#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ + +#define COM5 0x0E /* Common Control 5 */ +#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ +#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ +#define COM5_AFR_0 0x00 /* No reduction of frame rate */ +#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ +#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ +#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ +#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ +#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ +#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ +#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ + +#define COM6 0x0F /* Common Control 6 */ +#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ + +#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ +#define CLKRC 0x11 /* Internal Clock */ + +#define COM7 0x12 /* Common Control 7 */ +#define COM7_RESET 0x80 /* SCCB Register Reset */ +#define COM7_RES_VGA 0x00 /* Resolution VGA */ +#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ +#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ +#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ +#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ +#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ +#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ +#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ +#define COM7_FMT_YUV 0x00 /* Output format YUV */ +#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ +#define COM7_FMT_RGB 0x02 /* Output format RGB */ +#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ +#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x3)<<0)) +#define COM7_SET_RGB(r, x) ((r&0xF0)|(x&0x0C)|COM7_FMT_RGB) + +#define COM8 0x13 /* Common Control 8 */ +#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ +#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ +#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ +#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ +#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ +#define COM8_AGC_EN 0x04 /* AGC Enable */ +#define COM8_AWB_EN 0x02 /* AWB Enable */ +#define COM8_AEC_EN 0x01 /* AEC Enable */ +#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) +#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) +#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) + +#define COM9 0x14 /* Common Control 9 */ +#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ +#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ +#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ +#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ +#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ +#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ +#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ +#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ +#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) + +#define COM10 0x15 /* Common Control 10 */ +#define COM10_NEGATIVE 0x80 /* Output negative data */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ +#define COM10_PCLK_REV 0x10 /* PCLK reverse */ +#define COM10_HREF_REV 0x08 /* HREF reverse */ +#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ +#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ +#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ + +#define REG16 0x16 /* Register 16 */ +#define REG16_BIT_SHIFT 0x80 /* Bit shift test pattern options */ +#define HSTART 0x17 /* Horizontal Frame (HREF column) Start 8 MSBs (2 LSBs are at HREF[5:4]) */ +#define HSIZE 0x18 /* Horizontal Sensor Size (2 LSBs are at HREF[1:0]) */ +#define VSTART 0x19 /* Vertical Frame (row) Start 8 MSBs (1 LSB is at HREF[6]) */ +#define VSIZE 0x1A /* Vertical Sensor Size (1 LSB is at HREF[2]) */ +#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ +#define REG_MIDH 0x1C /* Manufacturer ID Byte C High */ +#define REG_MIDL 0x1D /* Manufacturer ID Byte C Low */ +#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period */ + +#define COM11 0x20 /* Common Control 11 */ +#define COM11_SNGL_FRAME_EN 0x02 /* Single frame ON/OFF selection */ +#define COM11_SNGL_XFR_TRIG 0x01 /* Single frame transfer trigger */ + +#define BDBASE 0x22 /* Banding Filter Minimum AEC Value */ +#define DBSTEP 0x23 /* Banding Filter Maximum Step */ +#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ +#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ +#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ +#define REG28 0x28 /* Selection on the number of dummy rows, N */ +#define HOUTSIZE 0x29 /* Horizontal Data Output Size MSBs (2 LSBs at register EXHCH[1:0]) */ +#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ +#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ +#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */ +#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ +#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ +#define YAVE 0x2F /* Y/G Channel Average Value */ +#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance High Level Threshold */ +#define LUMLTH 0x31 /* Histogram AEC/AGC Luminance Low Level Threshold */ +#define HREF 0x32 /* Image Start and Size Control */ +#define DM_LNL 0x33 /* Dummy Row Low 8 Bits */ +#define DM_LNH 0x34 /* Dummy Row High 8 Bits */ +#define ADOFF_B 0x35 /* AD Offset Compensation Value for B Channel */ +#define ADOFF_R 0x36 /* AD Offset Compensation Value for R Channel */ +#define ADOFF_GB 0x37 /* AD Offset Compensation Value for GB Channel */ +#define ADOFF_GR 0x38 /* AD Offset Compensation Value for GR Channel */ +#define OFF_B 0x39 /* AD Offset Compensation Value for B Channel */ +#define OFF_R 0x3A /* AD Offset Compensation Value for R Channel */ +#define OFF_GB 0x3B /* AD Offset Compensation Value for GB Channel */ +#define OFF_GR 0x3C /* AD Offset Compensation Value for GR Channel */ +#define COM12 0x3D /* DC offset compensation for analog process */ + +#define COM13 0x3E /* Common Control 13 */ +#define COM13_BLC_EN 0x80 /* BLC enable */ +#define COM13_ADC_EN 0x40 /* ADC channel BLC ON/OFF control */ +#define COM13_ANALOG_BLC 0x20 /* Analog processing channel BLC ON/OFF control */ +#define COM13_ABLC_GAIN_EN 0x04 /* ABLC gain trigger enable */ + +#define COM14 0x3F /* Common Control 14 */ +#define COM15 0x40 /* Common Control 15 */ +#define COM16 0x41 /* Common Control 16 */ +#define TGT_B 0x42 /* BLC Blue Channel Target Value */ +#define TGT_R 0x43 /* BLC Red Channel Target Value */ +#define TGT_GB 0x44 /* BLC Gb Channel Target Value */ +#define TGT_GR 0x45 /* BLC Gr Channel Target Value */ + +#define LC_CTR 0x46 /* Lens Correction Control */ +#define LC_CTR_RGB_COMP_1 0x00 /* R, G, and B channel compensation coefficient is set by LC_COEF (0x49) */ +#define LC_CTR_RGB_COMP_3 0x04 /* R, G, and B channel compensation coefficient is set by registers + LC_COEFB (0x4B), LC_COEF (0x49), and LC_COEFR (0x4C), respectively */ +#define LC_CTR_EN 0x01 /* Lens correction enable */ +#define LC_XC 0x47 /* X Coordinate of Lens Correction Center Relative to Array Center */ +#define LC_YC 0x48 /* Y Coordinate of Lens Correction Center Relative to Array Center */ +#define LC_COEF 0x49 /* Lens Correction Coefficient */ +#define LC_RADI 0x4A /* Lens Correction Radius */ +#define LC_COEFB 0x4B /* Lens Correction B Channel Compensation Coefficient */ +#define LC_COEFR 0x4C /* Lens Correction R Channel Compensation Coefficient */ + +#define FIXGAIN 0x4D /* Analog Fix Gain Amplifier */ +#define AREF0 0x4E /* Sensor Reference Control */ +#define AREF1 0x4F /* Sensor Reference Current Control */ +#define AREF2 0x50 /* Analog Reference Control */ +#define AREF3 0x51 /* ADC Reference Control */ +#define AREF4 0x52 /* ADC Reference Control */ +#define AREF5 0x53 /* ADC Reference Control */ +#define AREF6 0x54 /* Analog Reference Control */ +#define AREF7 0x55 /* Analog Reference Control */ +#define UFIX 0x60 /* U Channel Fixed Value Output */ +#define VFIX 0x61 /* V Channel Fixed Value Output */ +#define AWBB_BLK 0x62 /* AWB Option for Advanced AWB */ + +#define AWB_CTRL0 0x63 /* AWB Control Byte 0 */ +#define AWB_CTRL0_GAIN_EN 0x80 /* AWB gain enable */ +#define AWB_CTRL0_CALC_EN 0x40 /* AWB calculate enable */ +#define AWB_CTRL0_WBC_MASK 0x0F /* WBC threshold 2 */ + +#define DSP_CTRL1 0x64 /* DSP Control Byte 1 */ +#define DSP_CTRL1_FIFO_EN 0x80 /* FIFO enable/disable selection */ +#define DSP_CTRL1_UV_EN 0x40 /* UV adjust function ON/OFF selection */ +#define DSP_CTRL1_SDE_EN 0x20 /* SDE enable */ +#define DSP_CTRL1_MTRX_EN 0x10 /* Color matrix ON/OFF selection */ +#define DSP_CTRL1_INTRP_EN 0x08 /* Interpolation ON/OFF selection */ +#define DSP_CTRL1_GAMMA_EN 0x04 /* Gamma function ON/OFF selection */ +#define DSP_CTRL1_BLACK_EN 0x02 /* Black defect auto correction ON/OFF */ +#define DSP_CTRL1_WHITE_EN 0x01 /* White defect auto correction ON/OFF */ + +#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */ +#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */ +#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */ +#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */ +#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */ + +#define DSP_CTRL3 0x66 /* DSP Control Byte 3 */ +#define DSP_CTRL3_UV_EN 0x80 /* UV output sequence option */ +#define DSP_CTRL3_CBAR_EN 0x20 /* DSP color bar ON/OFF selection */ +#define DSP_CTRL3_FIFO_EN 0x08 /* FIFO power down ON/OFF selection */ +#define DSP_CTRL3_SCAL1_PWDN 0x04 /* Scaling module power down control 1 */ +#define DSP_CTRL3_SCAL2_PWDN 0x02 /* Scaling module power down control 2 */ +#define DSP_CTRL3_INTRP_PWDN 0x01 /* Interpolation module power down control */ +#define DSP_CTRL3_SET_CBAR(r, x) ((r&0xDF)|((x&1)<<5)) + + +#define DSP_CTRL4 0x67 /* DSP Control Byte 4 */ +#define DSP_CTRL4_YUV_RGB 0x00 /* Output selection YUV or RGB */ +#define DSP_CTRL4_RAW8 0x02 /* Output selection RAW8 */ +#define DSP_CTRL4_RAW10 0x03 /* Output selection RAW10 */ + + +#define AWB_BIAS 0x68 /* AWB BLC Level Clip */ +#define AWB_CTRL1 0x69 /* AWB Control 1 */ +#define AWB_CTRL2 0x6A /* AWB Control 2 */ + +#define AWB_CTRL3 0x6B /* AWB Control 3 */ +#define AWB_CTRL3_ADVANCED 0x80 /* AWB mode select - Advanced AWB */ +#define AWB_CTRL3_SIMPLE 0x00 /* AWB mode select - Simple AWB */ + +#define AWB_CTRL4 0x6C /* AWB Control 4 */ +#define AWB_CTRL5 0x6D /* AWB Control 5 */ +#define AWB_CTRL6 0x6E /* AWB Control 6 */ +#define AWB_CTRL7 0x6F /* AWB Control 7 */ +#define AWB_CTRL8 0x70 /* AWB Control 8 */ +#define AWB_CTRL9 0x71 /* AWB Control 9 */ +#define AWB_CTRL10 0x72 /* AWB Control 10 */ +#define AWB_CTRL11 0x73 /* AWB Control 11 */ +#define AWB_CTRL12 0x74 /* AWB Control 12 */ +#define AWB_CTRL13 0x75 /* AWB Control 13 */ +#define AWB_CTRL14 0x76 /* AWB Control 14 */ +#define AWB_CTRL15 0x77 /* AWB Control 15 */ +#define AWB_CTRL16 0x78 /* AWB Control 16 */ +#define AWB_CTRL17 0x79 /* AWB Control 17 */ +#define AWB_CTRL18 0x7A /* AWB Control 18 */ +#define AWB_CTRL19 0x7B /* AWB Control 19 */ +#define AWB_CTRL20 0x7C /* AWB Control 20 */ +#define AWB_CTRL21 0x7D /* AWB Control 21 */ +#define GAM1 0x7E /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ +#define GAM2 0x7F /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ +#define GAM3 0x80 /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ +#define GAM4 0x81 /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ +#define GAM5 0x82 /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ +#define GAM6 0x83 /* Gamma Curve 6th Segment Input End Point 0x30 Output Value */ +#define GAM7 0x84 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ +#define GAM8 0x85 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ +#define GAM9 0x86 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ +#define GAM10 0x87 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ +#define GAM11 0x88 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ +#define GAM12 0x89 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ +#define GAM13 0x8A /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ +#define GAM14 0x8B /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ +#define GAM15 0x8C /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ +#define SLOP 0x8D /* Gamma Curve Highest Segment Slope */ +#define DNSTH 0x8E /* De-noise Threshold */ +#define EDGE0 0x8F /* Edge Enhancement Strength Control */ +#define EDGE1 0x90 /* Edge Enhancement Threshold Control */ +#define DNSOFF 0x91 /* Auto De-noise Threshold Control */ +#define EDGE2 0x92 /* Edge Enhancement Strength Upper Limit */ +#define EDGE3 0x93 /* Edge Enhancement Strength Upper Limit */ +#define MTX1 0x94 /* Matrix Coefficient 1 */ +#define MTX2 0x95 /* Matrix Coefficient 2 */ +#define MTX3 0x96 /* Matrix Coefficient 3 */ +#define MTX4 0x97 /* Matrix Coefficient 4 */ +#define MTX5 0x98 /* Matrix Coefficient 5 */ +#define MTX6 0x99 /* Matrix Coefficient 6 */ + +#define MTX_CTRL 0x9A /* Matrix Control */ +#define MTX_CTRL_DBL_EN 0x80 /* Matrix double ON/OFF selection */ + +#define BRIGHTNESS 0x9B /* Brightness Control */ +#define CONTRAST 0x9C /* Contrast Gain */ +#define UVADJ0 0x9E /* Auto UV Adjust Control 0 */ +#define UVADJ1 0x9F /* Auto UV Adjust Control 1 */ +#define SCAL0 0xA0 /* DCW Ratio Control */ +#define SCAL1 0xA1 /* Horizontal Zoom Out Control */ +#define SCAL2 0xA2 /* Vertical Zoom Out Control */ +#define FIFODLYM 0xA3 /* FIFO Manual Mode Delay Control */ +#define FIFODLYA 0xA4 /* FIFO Auto Mode Delay Control */ + +#define SDE 0xA6 /* Special Digital Effect Control */ +#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */ +#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */ +#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */ +#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */ +#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */ +#define SDE_SATURATION_EN 0x02 /* Saturation enable */ +#define SDE_HUE_EN 0x01 /* Hue enable */ + +#define USAT 0xA7 /* U Component Saturation Gain */ +#define VSAT 0xA8 /* V Component Saturation Gain */ +#define HUECOS 0xA9 /* Cosine value 0x80 */ +#define HUESIN 0xAA /* Sine value 0x80 */ +#define SIGN_BIT 0xAB /* Sign Bit for Hue and Brightness */ + +#define DSPAUTO 0xAC /* DSP Auto Function ON/OFF Control */ +#define DSPAUTO_AWB_EN 0x80 /* AWB auto threshold control */ +#define DSPAUTO_DENOISE_EN 0x40 /* De-noise auto threshold control */ +#define DSPAUTO_EDGE_EN 0x20 /* Sharpness (edge enhancement) auto strength control */ +#define DSPAUTO_UV_EN 0x10 /* UV adjust auto slope control */ +#define DSPAUTO_SCAL0_EN 0x08 /* Auto scaling factor control (register SCAL0 (0xA0)) */ +#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2))*/ +#define SET_REG(reg, x) (##reg_DEFAULT|x) +#endif //__REG_REGS_H__ +#endif \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h new file mode 100644 index 0000000000..edffca1e00 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h @@ -0,0 +1,31 @@ +#pragma once + +#include "sensor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int gc0308_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int gc0308_init(sensor_t *sensor); + +#ifdef __cplusplus +} +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h new file mode 100644 index 0000000000..f1cb4532b7 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h @@ -0,0 +1,25 @@ +/* + * GC0308 register definitions. + */ +#ifndef __GC0308_REG_REGS_H__ +#define __GC0308_REG_REGS_H__ + +#define RESET_RELATED 0xfe // Bit[7]: Software reset + // Bit[6:5]: NA + // Bit[4]: CISCTL_restart_n + // Bit[3:1]: NA + // Bit[0]: page select + // 0:page0 + // 1:page1 + + +// page0: + + + +/** + * @brief register value + */ + + +#endif // __GC0308_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h new file mode 100644 index 0000000000..adf5f28d76 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h @@ -0,0 +1,258 @@ +#ifndef _GC0308_SETTINGS_H_ +#define _GC0308_SETTINGS_H_ + +#include + +#define REG_DLY 0xff + +static const uint8_t gc0308_sensor_default_regs[][2] = { + {0xfe, 0x00}, + {0xec, 0x20}, + {0x05, 0x00}, + {0x06, 0x00}, + {0x07, 0x00}, + {0x08, 0x00}, + {0x09, 0x01}, + {0x0a, 0xe8}, + {0x0b, 0x02}, + {0x0c, 0x88}, + {0x0d, 0x02}, + {0x0e, 0x02}, + {0x10, 0x26}, + {0x11, 0x0d}, + {0x12, 0x2a}, + {0x13, 0x00}, + {0x14, 0x11}, + {0x15, 0x0a}, + {0x16, 0x05}, + {0x17, 0x01}, + {0x18, 0x44}, + {0x19, 0x44}, + {0x1a, 0x2a}, + {0x1b, 0x00}, + {0x1c, 0x49}, + {0x1d, 0x9a}, + {0x1e, 0x61}, + {0x1f, 0x00}, //pad drv <=24MHz, use 0x00 is ok + {0x20, 0x7f}, + {0x21, 0xfa}, + {0x22, 0x57}, + {0x24, 0xa2}, //YCbYCr + {0x25, 0x0f}, + {0x26, 0x03}, // 0x01 + {0x28, 0x00}, + {0x2d, 0x0a}, + {0x2f, 0x01}, + {0x30, 0xf7}, + {0x31, 0x50}, + {0x32, 0x00}, + {0x33, 0x28}, + {0x34, 0x2a}, + {0x35, 0x28}, + {0x39, 0x04}, + {0x3a, 0x20}, + {0x3b, 0x20}, + {0x3c, 0x00}, + {0x3d, 0x00}, + {0x3e, 0x00}, + {0x3f, 0x00}, + {0x50, 0x14}, // 0x14 + {0x52, 0x41}, + {0x53, 0x80}, + {0x54, 0x80}, + {0x55, 0x80}, + {0x56, 0x80}, + {0x8b, 0x20}, + {0x8c, 0x20}, + {0x8d, 0x20}, + {0x8e, 0x14}, + {0x8f, 0x10}, + {0x90, 0x14}, + {0x91, 0x3c}, + {0x92, 0x50}, +//{0x8b,0x10}, +//{0x8c,0x10}, +//{0x8d,0x10}, +//{0x8e,0x10}, +//{0x8f,0x10}, +//{0x90,0x10}, +//{0x91,0x3c}, +//{0x92,0x50}, + {0x5d, 0x12}, + {0x5e, 0x1a}, + {0x5f, 0x24}, + {0x60, 0x07}, + {0x61, 0x15}, + {0x62, 0x08}, // 0x08 + {0x64, 0x03}, // 0x03 + {0x66, 0xe8}, + {0x67, 0x86}, + {0x68, 0x82}, + {0x69, 0x18}, + {0x6a, 0x0f}, + {0x6b, 0x00}, + {0x6c, 0x5f}, + {0x6d, 0x8f}, + {0x6e, 0x55}, + {0x6f, 0x38}, + {0x70, 0x15}, + {0x71, 0x33}, + {0x72, 0xdc}, + {0x73, 0x00}, + {0x74, 0x02}, + {0x75, 0x3f}, + {0x76, 0x02}, + {0x77, 0x38}, // 0x47 + {0x78, 0x88}, + {0x79, 0x81}, + {0x7a, 0x81}, + {0x7b, 0x22}, + {0x7c, 0xff}, + {0x93, 0x48}, //color matrix default + {0x94, 0x02}, + {0x95, 0x07}, + {0x96, 0xe0}, + {0x97, 0x40}, + {0x98, 0xf0}, + {0xb1, 0x40}, + {0xb2, 0x40}, + {0xb3, 0x40}, //0x40 + {0xb6, 0xe0}, + {0xbd, 0x38}, + {0xbe, 0x36}, + {0xd0, 0xCB}, + {0xd1, 0x10}, + {0xd2, 0x90}, + {0xd3, 0x48}, + {0xd5, 0xF2}, + {0xd6, 0x16}, + {0xdb, 0x92}, + {0xdc, 0xA5}, + {0xdf, 0x23}, + {0xd9, 0x00}, + {0xda, 0x00}, + {0xe0, 0x09}, + {0xed, 0x04}, + {0xee, 0xa0}, + {0xef, 0x40}, + {0x80, 0x03}, + + {0x9F, 0x10}, + {0xA0, 0x20}, + {0xA1, 0x38}, + {0xA2, 0x4e}, + {0xA3, 0x63}, + {0xA4, 0x76}, + {0xA5, 0x87}, + {0xA6, 0xa2}, + {0xA7, 0xb8}, + {0xA8, 0xca}, + {0xA9, 0xd8}, + {0xAA, 0xe3}, + {0xAB, 0xeb}, + {0xAC, 0xf0}, + {0xAD, 0xF8}, + {0xAE, 0xFd}, + {0xAF, 0xFF}, + + {0xc0, 0x00}, + {0xc1, 0x10}, + {0xc2, 0x1c}, + {0xc3, 0x30}, + {0xc4, 0x43}, + {0xc5, 0x54}, + {0xc6, 0x65}, + {0xc7, 0x75}, + {0xc8, 0x93}, + {0xc9, 0xB0}, + {0xca, 0xCB}, + {0xcb, 0xE6}, + {0xcc, 0xFF}, + {0xf0, 0x02}, + {0xf1, 0x01}, + {0xf2, 0x02}, + {0xf3, 0x30}, + {0xf7, 0x04}, + {0xf8, 0x02}, + {0xf9, 0x9f}, + {0xfa, 0x78}, + {0xfe, 0x01}, + {0x00, 0xf5}, + {0x02, 0x20}, + {0x04, 0x10}, + {0x05, 0x08}, + {0x06, 0x20}, + {0x08, 0x0a}, + {0x0a, 0xa0}, + {0x0b, 0x60}, + {0x0c, 0x08}, + {0x0e, 0x44}, + {0x0f, 0x32}, + {0x10, 0x41}, + {0x11, 0x37}, + {0x12, 0x22}, + {0x13, 0x19}, + {0x14, 0x44}, + {0x15, 0x44}, + {0x16, 0xc2}, + {0x17, 0xA8}, + {0x18, 0x18}, + {0x19, 0x50}, + {0x1a, 0xd8}, + {0x1b, 0xf5}, + {0x70, 0x40}, + {0x71, 0x58}, + {0x72, 0x30}, + {0x73, 0x48}, + {0x74, 0x20}, + {0x75, 0x60}, + {0x77, 0x20}, + {0x78, 0x32}, + {0x30, 0x03}, + {0x31, 0x40}, + {0x32, 0x10}, + {0x33, 0xe0}, + {0x34, 0xe0}, + {0x35, 0x00}, + {0x36, 0x80}, + {0x37, 0x00}, + {0x38, 0x04}, + {0x39, 0x09}, + {0x3a, 0x12}, + {0x3b, 0x1C}, + {0x3c, 0x28}, + {0x3d, 0x31}, + {0x3e, 0x44}, + {0x3f, 0x57}, + {0x40, 0x6C}, + {0x41, 0x81}, + {0x42, 0x94}, + {0x43, 0xA7}, + {0x44, 0xB8}, + {0x45, 0xD6}, + {0x46, 0xEE}, + {0x47, 0x0d}, + {0x62, 0xf7}, + {0x63, 0x68}, + {0x64, 0xd3}, + {0x65, 0xd3}, + {0x66, 0x60}, + {0xfe, 0x00}, + + {0x01, 0x32}, //frame setting + {0x02, 0x0c}, + {0x0f, 0x01}, + {0xe2, 0x00}, + {0xe3, 0x78}, + {0xe4, 0x00}, + {0xe5, 0xfe}, + {0xe6, 0x01}, + {0xe7, 0xe0}, + {0xe8, 0x01}, + {0xe9, 0xe0}, + {0xea, 0x01}, + {0xeb, 0xe0}, + {0xfe, 0x00}, +}; + +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h new file mode 100644 index 0000000000..7679f07089 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h @@ -0,0 +1,31 @@ +/* + * + * GC032A driver. + * + */ +#ifndef __GC032A_H__ +#define __GC032A_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int gc032a_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int gc032a_init(sensor_t *sensor); + +#endif // __GC032A_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h new file mode 100644 index 0000000000..5de59d1d26 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h @@ -0,0 +1,82 @@ +/* + * GC032A register definitions. + */ +#ifndef __GC032A_REG_REGS_H__ +#define __GC032A_REG_REGS_H__ + +#define SENSOR_ID_HIGH 0XF0 +#define SENSOR_ID_LOW 0XF1 +#define PAD_VB_HIZ_MODE 0XF2 +#define SYNC_OUTPUT 0XF3 +#define I2C_CONFIG 0XF4 +#define PLL_MODE1 0XF7 +#define PLL_MODE2 0XF8 +#define CM_MODE 0XF9 +#define ISP_DIV_MODE 0XFA +#define I2C_DEVICE_ID 0XFB +#define ANALOG_PWC 0XFC +#define ISP_DIV_MODE2 0XFD +#define RESET_RELATED 0XFE // Bit[7]: Software reset + // Bit[6]: cm reset + // Bit[5]: spi reset + // Bit[4]: CISCTL_restart_n + // Bit[3]: PLL_rst + // Bit[2:0]: page select + // 000:page0 + // 001:page1 + // 010:page2 + // 011:page3 + +//----page0----------------------------- +#define P0_EXPOSURE_HIGH 0X03 +#define P0_EXPOSURE_LOW 0X04 +#define P0_HB_HIGH 0X05 +#define P0_HB_LOW 0X06 +#define P0_VB_HIGH 0X07 +#define P0_VB_LOW 0X08 +#define P0_ROW_START_HIGH 0X09 +#define P0_ROW_START_LOW 0X0A +#define P0_COLUMN_START_HIGH 0X0B +#define P0_COLUMN_START_LOW 0X0C +#define P0_WINDOW_HEIGHT_HIGH 0X0D +#define P0_WINDOW_HEIGHT_LOW 0X0E +#define P0_WINDOW_WIDTH_HIGH 0X0F +#define P0_WINDOW_WIDTH_LOW 0X10 +#define P0_SH_DELAY 0X11 +#define P0_VS_ST 0X12 +#define P0_VS_ET 0X13 +#define P0_CISCTL_MODE1 0X17 + +#define P0_BLOCK_ENABLE_1 0X40 +#define P0_AAAA_ENABLE 0X42 +#define P0_SPECIAL_EFFECT 0X43 +#define P0_SYNC_MODE 0X46 +#define P0_GAIN_CODE 0X48 +#define P0_DEBUG_MODE2 0X4C +#define P0_WIN_MODE 0X50 +#define P0_OUT_WIN_Y1_HIGH 0X51 +#define P0_OUT_WIN_Y1_LOW 0X52 +#define P0_OUT_WIN_X1_HIGH 0X53 +#define P0_OUT_WIN_X1_LOW 0X54 +#define P0_OUT_WIN_HEIGHT_HIGH 0X55 +#define P0_OUT_WIN_HEIGHT_LOW 0X56 +#define P0_OUT_WIN_WIDTH_HIGH 0X57 +#define P0_OUT_WIN_WIDTH_LOW 0X58 + +#define P0_GLOBAL_SATURATION 0XD0 +#define P0_SATURATION_CB 0XD1 +#define P0_SATURATION_CR 0XD2 +#define P0_LUMA_CONTRAST 0XD3 +#define P0_CONTRAST_CENTER 0XD4 +#define P0_LUMA_OFFSET 0XD5 +#define P0_FIXED_CB 0XDA +#define P0_FIXED_CR 0XDB + +//----page3----------------------------- +#define P3_IMAGE_WIDTH_LOW 0X5B +#define P3_IMAGE_WIDTH_HIGH 0X5C +#define P3_IMAGE_HEIGHT_LOW 0X5D +#define P3_IMAGE_HEIGHT_HIGH 0X5E + + +#endif //__GC032A_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h new file mode 100644 index 0000000000..a19ffc7c6d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h @@ -0,0 +1,401 @@ +#ifndef _GC032A_SETTINGS_H_ +#define _GC032A_SETTINGS_H_ + +#include +#include +#include "esp_attr.h" +#include "gc032a_regs.h" + + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0x0000 + + +/* + * The default register settings, as obtained from OmniVision. There + * is really no making sense of most of these - lots of "reserved" values + * and such. + * + */ +static const uint16_t gc032a_default_regs[][2] = { + /*System*/ + {0xf3, 0xff}, + {0xf5, 0x06}, + {0xf7, 0x01}, + {0xf8, 0x03}, + {0xf9, 0xce}, + {0xfa, 0x00}, + {0xfc, 0x02}, + {0xfe, 0x02}, + {0x81, 0x03}, + + {0xfe, 0x00}, + {0x77, 0x64}, + {0x78, 0x40}, + {0x79, 0x60}, + /*ANALOG & CISCTL*/ + {0xfe, 0x00}, + {0x03, 0x01}, + {0x04, 0xce}, + {0x05, 0x01}, + {0x06, 0xad}, + {0x07, 0x00}, + {0x08, 0x10}, + {0x0a, 0x00}, + {0x0c, 0x00}, + {0x0d, 0x01}, + {0x0e, 0xe8}, // height 488 + {0x0f, 0x02}, + {0x10, 0x88}, // width 648 + {0x17, 0x54}, + {0x19, 0x08}, + {0x1a, 0x0a}, + {0x1f, 0x40}, + {0x20, 0x30}, + {0x2e, 0x80}, + {0x2f, 0x2b}, + {0x30, 0x1a}, + {0xfe, 0x02}, + {0x03, 0x02}, + {0x05, 0xd7}, + {0x06, 0x60}, + {0x08, 0x80}, + {0x12, 0x89}, + + /*blk*/ + {0xfe, 0x00}, + {0x18, 0x02}, + {0xfe, 0x02}, + {0x40, 0x22}, + {0x45, 0x00}, + {0x46, 0x00}, + {0x49, 0x20}, + {0x4b, 0x3c}, + {0x50, 0x20}, + {0x42, 0x10}, + + /*isp*/ + {0xfe, 0x01}, + {0x0a, 0xc5}, + {0x45, 0x00}, + {0xfe, 0x00}, + {0x40, 0xff}, + {0x41, 0x25}, + {0x42, 0xcf}, + {0x43, 0x10}, + {0x44, 0x83}, + {0x46, 0x23}, + {0x49, 0x03}, + {0x52, 0x02}, + {0x54, 0x00}, + {0xfe, 0x02}, + {0x22, 0xf6}, + + /*Shading*/ + {0xfe, 0x01}, + {0xc1, 0x38}, + {0xc2, 0x4c}, + {0xc3, 0x00}, + {0xc4, 0x32}, + {0xc5, 0x24}, + {0xc6, 0x16}, + {0xc7, 0x08}, + {0xc8, 0x08}, + {0xc9, 0x00}, + {0xca, 0x20}, + {0xdc, 0x8a}, + {0xdd, 0xa0}, + {0xde, 0xa6}, + {0xdf, 0x75}, + + /*AWB*/ + {0xfe, 0x01}, + {0x7c, 0x09}, + {0x65, 0x06}, + {0x7c, 0x08}, + {0x56, 0xf4}, + {0x66, 0x0f}, + {0x67, 0x84}, + {0x6b, 0x80}, + {0x6d, 0x12}, + {0x6e, 0xb0}, + {0x86, 0x00}, + {0x87, 0x00}, + {0x88, 0x00}, + {0x89, 0x00}, + {0x8a, 0x00}, + {0x8b, 0x00}, + {0x8c, 0x00}, + {0x8d, 0x00}, + {0x8e, 0x00}, + {0x8f, 0x00}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x92, 0xf4}, + {0x93, 0xd5}, + {0x94, 0x50}, + {0x95, 0x0f}, + {0x96, 0xf4}, + {0x97, 0x2d}, + {0x98, 0x0f}, + {0x99, 0xa6}, + {0x9a, 0x2d}, + {0x9b, 0x0f}, + {0x9c, 0x59}, + {0x9d, 0x2d}, + {0x9e, 0xaa}, + {0x9f, 0x67}, + {0xa0, 0x59}, + {0xa1, 0x00}, + {0xa2, 0x00}, + {0xa3, 0x0a}, + {0xa4, 0x00}, + {0xa5, 0x00}, + {0xa6, 0xd4}, + {0xa7, 0x9f}, + {0xa8, 0x55}, + {0xa9, 0xd4}, + {0xaa, 0x9f}, + {0xab, 0xac}, + {0xac, 0x9f}, + {0xad, 0x55}, + {0xae, 0xd4}, + {0xaf, 0xac}, + {0xb0, 0xd4}, + {0xb1, 0xa3}, + {0xb2, 0x55}, + {0xb3, 0xd4}, + {0xb4, 0xac}, + {0xb5, 0x00}, + {0xb6, 0x00}, + {0xb7, 0x05}, + {0xb8, 0xd6}, + {0xb9, 0x8c}, + + /*CC*/ + {0xfe, 0x01}, + {0xd0, 0x40}, + {0xd1, 0xf8}, + {0xd2, 0x00}, + {0xd3, 0xfa}, + {0xd4, 0x45}, + {0xd5, 0x02}, + + {0xd6, 0x30}, + {0xd7, 0xfa}, + {0xd8, 0x08}, + {0xd9, 0x08}, + {0xda, 0x58}, + {0xdb, 0x02}, + {0xfe, 0x00}, + + /*Gamma*/ + {0xfe, 0x00}, + {0xba, 0x00}, + {0xbb, 0x04}, + {0xbc, 0x0a}, + {0xbd, 0x0e}, + {0xbe, 0x22}, + {0xbf, 0x30}, + {0xc0, 0x3d}, + {0xc1, 0x4a}, + {0xc2, 0x5d}, + {0xc3, 0x6b}, + {0xc4, 0x7a}, + {0xc5, 0x85}, + {0xc6, 0x90}, + {0xc7, 0xa5}, + {0xc8, 0xb5}, + {0xc9, 0xc2}, + {0xca, 0xcc}, + {0xcb, 0xd5}, + {0xcc, 0xde}, + {0xcd, 0xea}, + {0xce, 0xf5}, + {0xcf, 0xff}, + + /*Auto Gamma*/ + {0xfe, 0x00}, + {0x5a, 0x08}, + {0x5b, 0x0f}, + {0x5c, 0x15}, + {0x5d, 0x1c}, + {0x5e, 0x28}, + {0x5f, 0x36}, + {0x60, 0x45}, + {0x61, 0x51}, + {0x62, 0x6a}, + {0x63, 0x7d}, + {0x64, 0x8d}, + {0x65, 0x98}, + {0x66, 0xa2}, + {0x67, 0xb5}, + {0x68, 0xc3}, + {0x69, 0xcd}, + {0x6a, 0xd4}, + {0x6b, 0xdc}, + {0x6c, 0xe3}, + {0x6d, 0xf0}, + {0x6e, 0xf9}, + {0x6f, 0xff}, + + /*Gain*/ + {0xfe, 0x00}, + {0x70, 0x50}, + + /*AEC*/ + {0xfe, 0x00}, + {0x4f, 0x01}, + {0xfe, 0x01}, + {0x0d, 0x00}, + {0x12, 0xa0}, + {0x13, 0x3a}, + {0x44, 0x04}, + {0x1f, 0x30}, + {0x20, 0x40}, + {0x26, 0x9a}, + {0x3e, 0x20}, + {0x3f, 0x2d}, + {0x40, 0x40}, + {0x41, 0x5b}, + {0x42, 0x82}, + {0x43, 0xb7}, + {0x04, 0x0a}, + {0x02, 0x79}, + {0x03, 0xc0}, + + /*measure window*/ + {0xfe, 0x01}, + {0xcc, 0x08}, + {0xcd, 0x08}, + {0xce, 0xa4}, + {0xcf, 0xec}, + + /*DNDD*/ + {0xfe, 0x00}, + {0x81, 0xb8}, + {0x82, 0x12}, + {0x83, 0x0a}, + {0x84, 0x01}, + {0x86, 0x50}, + {0x87, 0x18}, + {0x88, 0x10}, + {0x89, 0x70}, + {0x8a, 0x20}, + {0x8b, 0x10}, + {0x8c, 0x08}, + {0x8d, 0x0a}, + + /*Intpee*/ + {0xfe, 0x00}, + {0x8f, 0xaa}, + {0x90, 0x9c}, + {0x91, 0x52}, + {0x92, 0x03}, + {0x93, 0x03}, + {0x94, 0x08}, + {0x95, 0x44}, + {0x97, 0x00}, + {0x98, 0x00}, + + /*ASDE*/ + {0xfe, 0x00}, + {0xa1, 0x30}, + {0xa2, 0x41}, + {0xa4, 0x30}, + {0xa5, 0x20}, + {0xaa, 0x30}, + {0xac, 0x32}, + + /*YCP*/ + {0xfe, 0x00}, + {0xd1, 0x3c}, + {0xd2, 0x3c}, + {0xd3, 0x38}, + {0xd6, 0xf4}, + {0xd7, 0x1d}, + {0xdd, 0x73}, + {0xde, 0x84}, + + /*Banding*/ + {0xfe, 0x00}, + {0x05, 0x01}, + {0x06, 0xad}, + {0x07, 0x00}, + {0x08, 0x10}, + + {0xfe, 0x01}, + {0x25, 0x00}, + {0x26, 0x9a}, + + {0x27, 0x01}, + {0x28, 0xce}, + {0x29, 0x02}, + {0x2a, 0x68}, + {0x2b, 0x02}, + {0x2c, 0x68}, + {0x2d, 0x07}, + {0x2e, 0xd2}, + {0x2f, 0x0b}, + {0x30, 0x6e}, + {0x31, 0x0e}, + {0x32, 0x70}, + {0x33, 0x12}, + {0x34, 0x0c}, + {0x3c, 0x30}, + + /*Analog&Cisctl*/ + {0xfe, 0x00}, + {0x05, 0x01}, + {0x06, 0xa0}, + {0x07, 0x00}, + {0x08, 0x20}, + {0x0a, 0x78}, + {0x0c, 0xa0}, + {0x0d, 0x00}, //window_height [8] + {0x0e, 0xf8}, //window_height [7:0] 248 + {0x0f, 0x01}, //window_width [9:8] + {0x10, 0x48}, //window_width [7:0] 328 + + {0x55, 0x00}, + {0x56, 0xf0}, // 240 + {0x57, 0x01}, + {0x58, 0x40}, // 320 + + /*SPI*/ + {0xfe, 0x03}, + {0x5b, 0x40}, + {0x5c, 0x01}, + {0x5d, 0xf0}, + {0x5e, 0x00}, + + /*AEC*/ + {0xfe, 0x01}, + {0x25, 0x00}, //step + {0x26, 0x63}, + {0x27, 0x01}, + {0x28, 0x29}, + {0x29, 0x01}, + {0x2a, 0x29}, + {0x2b, 0x01}, + {0x2c, 0x29}, + {0x2d, 0x01}, + {0x2e, 0x29}, + {0x2f, 0x01}, + {0x30, 0x29}, + {0x31, 0x01}, + {0x32, 0x29}, + {0x33, 0x01}, + {0x34, 0x29}, + {0x3c, 0x00}, + + /*measure window*/ + {0xfe, 0x01}, + {0xcc, 0x04}, + {0xcd, 0x04}, + {0xce, 0x72}, + {0xcf, 0x52}, + {REGLIST_TAIL, 0x00}, +}; + +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h new file mode 100644 index 0000000000..6c5b60f703 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h @@ -0,0 +1,27 @@ + +#ifndef __GC2145_H__ +#define __GC2145_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int gc2145_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int gc2145_init(sensor_t *sensor); + +#endif // __GC2145_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h new file mode 100644 index 0000000000..b034a16898 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h @@ -0,0 +1,85 @@ +/* + * GC2145 register definitions. + */ +#ifndef __GC2145_REG_REGS_H__ +#define __GC2145_REG_REGS_H__ + +#define CHIP_ID_HIGH 0XF0 +#define CHIP_ID_LOW 0XF1 +#define PLL_MODE1 0XF7 +#define PLL_MODE2 0XF8 +#define CM_MODE 0XF9 +#define CLK_DIV_MODE 0XFA +#define RESET_RELATED 0xfe // Bit[7]: Software reset + // Bit[6]: cm reset + // Bit[5]: mipi reset + // Bit[4]: CISCTL_restart_n + // Bit[3]: NA + // Bit[2:0]: page select + // 000:page0 + // 001:page1 + // 010:page2 + // 011:page3 + +//-page0---------------- + +#define P0_EXPOSURE_HIGH 0X03 +#define P0_EXPOSURE_LOW 0X04 +#define P0_HB_HIGH 0X05 +#define P0_HB_LOW 0X06 +#define P0_VB_HIGH 0X07 +#define P0_VB_LOW 0X08 +#define P0_ROW_START_HIGH 0X09 +#define P0_ROW_START_LOW 0X0A +#define P0_COL_START_HIGH 0X0B +#define P0_COL_START_LOW 0X0C + +#define P0_WIN_HEIGHT_HIGH 0X0D +#define P0_WIN_HEIGHT_LOW 0X0E +#define P0_WIN_WIDTH_HIGH 0X0F +#define P0_WIN_WIDTH_LOW 0X10 +#define P0_ANALOG_MODE1 0X17 +#define P0_ANALOG_MODE2 0X18 + +#define P0_SPECIAL_EFFECT 0X83 +#define P0_OUTPUT_FORMAT 0x84 // Format select + // Bit[7]:YUV420 row switch + // Bit[6]:YUV420 col switch + // Bit[7]:YUV420_legacy + // Bit[4:0]:output data mode + // 5’h00 Cb Y Cr Y + // 5’h01 Cr Y Cb Y + // 5’h02 Y Cb Y Cr + // 5’h03 Y Cr Y Cb + // 5’h04 LSC bypass, C/Y + // 5’h05 LSC bypass, Y/C + // 5’h06 RGB 565 + // 5’h0f bypass 10bits + // 5’h17 switch odd/even column /row to controls output Bayer pattern + // 00 RGBG + // 01 RGGB + // 10 BGGR + // 11 GBRG + // 5'h18 DNDD out mode + // 5'h19 LSC out mode + // 5;h1b EEINTP out mode +#define P0_FRAME_START 0X85 +#define P0_SYNC_MODE 0X86 +#define P0_MODULE_GATING 0X88 +#define P0_BYPASS_MODE 0X89 +#define P0_DEBUG_MODE2 0X8C +#define P0_DEBUG_MODE3 0X8D +#define P0_CROP_ENABLE 0X90 +#define P0_OUT_WIN_Y1_HIGH 0X91 +#define P0_OUT_WIN_Y1_LOW 0X92 +#define P0_OUT_WIN_X1_HIGH 0X93 +#define P0_OUT_WIN_X1_LOW 0X94 +#define P0_OUT_WIN_HEIGHT_HIGH 0X95 +#define P0_OUT_WIN_HEIGHT_LOW 0X96 +#define P0_OUT_WIN_WIDTH_HIGH 0X97 +#define P0_OUT_WIN_WIDTH_LOW 0X98 +#define P0_SUBSAMPLE 0X99 +#define P0_SUBSAMPLE_MODE 0X9A + + +#endif // __GC2145_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h new file mode 100644 index 0000000000..879fd53b33 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h @@ -0,0 +1,719 @@ + +#include + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0x0000 /* Array end token */ + +static const uint16_t gc2145_default_init_regs[][2] = { + {0xfe, 0xf0}, + {0xfe, 0xf0}, + {0xfe, 0xf0}, + + {0xfc, 0x06}, + {0xf6, 0x00}, + + {0xf7, 0x1d}, //37 //17 //37 //1d//05 + {0xf8, 0x83}, //87 //83 //82 + {0xfa, 0x00}, + {0xf9, 0xfe}, //ff + {0xfd, 0x00}, + {0xc2, 0x00}, + {0xf2, 0x0f}, +////////////////////////////////////////////////////// +//////////////////// Analog & Cisctl //////////////// +////////////////////////////////////////////////////// + {0xfe, 0x00}, + + {0x03, 0x04}, //exp time + {0x04, 0x62}, //exp time + + {0x05, 0x01}, //00 //hb[11:8] + {0x06, 0x3b}, //0b //hb + + {0x09, 0x00}, //row start + {0x0a, 0x00}, // + {0x0b, 0x00}, //col start + {0x0c, 0x00}, + {0x0d, 0x04}, //height + {0x0e, 0xc0}, + {0x0f, 0x06}, //width + {0x10, 0x52}, + + {0x12, 0x2e}, //sh_delay 太短 YUV出图异常 + {0x17, 0x14}, //CISCTL Mode1 [1:0]mirror flip + {0x18, 0x22}, //sdark mode + {0x19, 0x0f}, // AD pipe number + {0x1a, 0x01}, //AD manual switch mode + + {0x1b, 0x4b}, //48 restg Width,SH width + {0x1c, 0x07}, //06 帧率快后,横条纹 //12 //TX Width,Space Width + {0x1d, 0x10}, //double reset + {0x1e, 0x88}, //90//98 //fix 竖线//Analog Mode1,TX high,Coln_r + {0x1f, 0x78}, //78 //38 //18 //Analog Mode2,txlow + {0x20, 0x03}, //07 //Analog Mode3,comv,ad_clk mode + {0x21, 0x40}, //10//20//40 //fix 灯管横条纹 + {0x22, 0xa0}, //d0//f0 //a2 //Vref vpix FPN严重 + {0x24, 0x1e}, + {0x25, 0x01}, //col sel + {0x26, 0x10}, //Analog PGA gain1 + {0x2d, 0x60}, //40//40 //txl drv mode + {0x30, 0x01}, //Analog Mode4 + {0x31, 0x90}, //b0//70 // Analog Mode7 [7:5]rsgh_r灯管横条纹[4:3]isp_g + {0x33, 0x06}, //03//02//01 //EQ_hstart_width + {0x34, 0x01}, +// +/////////////////////////////////////////////////// +//////////////////// ISP reg ////////////////////// +////////////////////////////////////////////////////// + {0x80, 0xff}, //outdoor gamma_en, GAMMA_en, CC_en, EE_en, INTP_en, DN_en, DD_en,LSC_en + {0x81, 0x24}, //26//24 //BLK dither mode, ll_y_en ,skin_en, edge SA, new_skin_mode, autogray_en,ll_gamma_en,BFF test image + {0x82, 0xfa}, //FA //auto_SA, auto_EE, auto_DN, auto_DD, auto_LSC, ABS_en, AWB_en, NA + {0x83, 0x00}, //special_effect + {0x84, 0x02}, //output format + {0x86, 0x03}, //c2 //46 //c2 //sync mode + {0x88, 0x03}, //[1]ctl_auto_gating [0]out_auto_gating + {0x89, 0x03}, //bypass disable + {0x85, 0x30}, //60//frame start cut + {0x8a, 0x00}, //ISP_quiet_mode,close aaa pclk,BLK gate mode,exception,close first pipe clock,close dndd clock,close intp clock,DIV_gatedclk_en + {0x8b, 0x00}, //[7:6]BFF_gate_mode,[5]BLK switch gain,[4]protect exp,[3:2]pipe gate mode,[1]not split sram,[0]dark current update + + {0xb0, 0x55}, //60 //global gain + {0xc3, 0x00}, //[7:4]auto_exp_gamma_th1[11:8],[3:0]auto_exp_gamma_th2[11:8] + {0xc4, 0x80}, //auto_exp_gamma_th1[7:0] into + {0xc5, 0x90}, //auto_exp_gamma_th2[7:0] out //outdoor gamma + {0xc6, 0x38}, //auto_gamma_th1 + {0xc7, 0x40}, //auto_gamma_th2 + + {0xec, 0x06}, //measure window + {0xed, 0x04}, + {0xee, 0x60}, //16 col + {0xef, 0x90}, //8 row + + {0xb6, 0x01}, //[0]aec en + + {0x90, 0x01}, //crop + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, //08 + {0x95, 0x04}, + {0x96, 0xb0}, + {0x97, 0x06}, + {0x98, 0x40}, + +/////////////////////////////////////////////// +/////////// BLK //////////////////////// +/////////////////////////////////////////////// + {0x18, 0x02}, + {0x40, 0x42}, //2b //27 + {0x41, 0x00}, //80 //dark row sel + {0x43, 0x54}, //[7:4]BLK start not smooth [3:0]output start frame + + {0x5e, 0x00}, //00//10 //18 + {0x5f, 0x00}, //00//10 //18 + {0x60, 0x00}, //00//10 //18 + {0x61, 0x00}, //00///10 //18 + {0x62, 0x00}, //00//10 //18 + {0x63, 0x00}, //00//10 //18 + {0x64, 0x00}, //00/10 //18 + {0x65, 0x00}, //00//10 //18 + {0x66, 0x20}, //1e + {0x67, 0x20}, //1e + {0x68, 0x20}, //1e + {0x69, 0x20}, //1e + + + {0x76, 0x00}, //0f + + {0x6a, 0x00}, //06 + {0x6b, 0x00}, //06 + {0x6c, 0x3e}, //06 + {0x6d, 0x3e}, //06 + {0x6e, 0x3f}, //06 + {0x6f, 0x3f}, //06 + {0x70, 0x00}, //06 + {0x71, 0x00}, //06 //manual offset + + {0x76, 0x00}, //1f//add offset + {0x72, 0xf0}, //[7:4]BLK DD th [3:0]BLK various th + {0x7e, 0x3c}, //ndark + {0x7f, 0x00}, + + {0xfe, 0x02}, + {0x48, 0x15}, + {0x49, 0x00}, //04//04 //ASDE OFFSET SLOPE + {0x4b, 0x0b}, //ASDE y OFFSET SLOPE + {0xfe, 0x00}, + +/////////////////////////////////////////////// +/////////// AEC //////////////////////// +/////////////////////////////////////////////// + {0xfe, 0x01}, + + {0x01, 0x04}, //AEC X1 + {0x02, 0xc0}, //AEC X2 + {0x03, 0x04}, //AEC Y1 + {0x04, 0x90}, //AEC Y2 + {0x05, 0x30}, //20 //AEC center X1 + {0x06, 0x90}, //40 //AEC center X2 + {0x07, 0x20}, //30 //AEC center Y1 + {0x08, 0x70}, //60 //AEC center Y2 + + {0x09, 0x00}, //AEC show mode + {0x0a, 0xc2}, //[7]col gain enable + {0x0b, 0x11}, //AEC every N + {0x0c, 0x10}, //AEC_mode3 center weight + {0x13, 0x40}, //2a //AEC Y target + {0x17, 0x00}, //AEC ignore mode + {0x1c, 0x11}, // + {0x1e, 0x61}, // + {0x1f, 0x30}, //40//50 //max pre gain + {0x20, 0x40}, //60//40 //max post gain + {0x22, 0x80}, //AEC outdoor THD + {0x23, 0x20}, //target_Y_low_limit + {0xfe, 0x02}, + {0x0f, 0x04}, //05 + {0xfe, 0x01}, + + {0x12, 0x35}, //35 //[5:4]group_size [3]slope_disable [2]outdoor_enable [0]histogram_enable + {0x15, 0x50}, //target_Y_high_limit + {0x10, 0x31}, //num_thd_high + {0x3e, 0x28}, //num_thd_low + {0x3f, 0xe0}, //luma_thd + {0x40, 0x20}, //luma_slope + {0x41, 0x0f}, //color_diff + + {0xfe, 0x02}, + {0x0f, 0x05}, //max_col_level +/////////////////////////// +////// INTPEE ///////////// +/////////////////////////// + {0xfe, 0x02}, //page2 + {0x90, 0x6c}, //ac //eeintp mode1 + {0x91, 0x03}, //02 ////eeintp mode2 + {0x92, 0xc8}, //44 //low criteria for direction + {0x94, 0x66}, + {0x95, 0xb5}, + {0x97, 0x64}, //78 ////edge effect + {0xa2, 0x11}, //fix direction + {0xfe, 0x00}, + +///////////////////////////// +//////// DNDD/////////////// +///////////////////////////// + {0xfe, 0x02}, + {0x80, 0xc1}, //c1 //[7]share mode [6]skin mode [5]is 5x5 mode [1:0]noise value select 0:2 1:2.5 2:3 3:4 + {0x81, 0x08}, // + {0x82, 0x08}, //signal a 0.6 + {0x83, 0x08}, //04 //signal b 2.5 + + {0x84, 0x0a}, //10 //05 dark_DD_TH + {0x86, 0xf0}, //a0 Y_value_dd_th2 + {0x87, 0x50}, //90 Y_value_dd_th3 + {0x88, 0x15}, //60 Y_value_dd_th4 + + {0x89, 0x50}, //80 // asde th2 + {0x8a, 0x30}, //60 // asde th3 + {0x8b, 0x10}, //30 // asde th4 + +///////////////////////////////////////////////// +///////////// ASDE //////////////////////// +///////////////////////////////////////////////// + {0xfe, 0x01}, //page 1 + {0x21, 0x14}, //luma_value_div_sel(分频,与0xef呈2倍关系,增大1,0xef的值减小1倍) +//ff ef luma_value read_only + + {0xfe, 0x02}, //page2 + {0xa3, 0x40}, //ASDE_low_luma_value_LSC_th_H + {0xa4, 0x20}, //ASDE_low_luma_value_LSC_th_L + + {0xa5, 0x40}, //80 //ASDE_LSC_gain_dec_slope_H + {0xa6, 0x80}, // 80 //ASDE_LSC_gain_dec_slope_L +//ff a7 ASDE_LSC_gain_dec //read only + + {0xab, 0x40}, //50 //ASDE_low_luma_value_OT_th + + {0xae, 0x0c}, //[3]EE1_effect_inc_or_dec_high,[2]EE2_effect_inc_or_dec_high, + //[1]EE1_effect_inc_or_dec_low,[0]EE2_effect_inc_or_dec_low, 1:inc 0:dec + + {0xb3, 0x34}, //44 //ASDE_EE1_effect_slope_low,ASDE_EE2_effect_slope_low + {0xb4, 0x44}, //12 //ASDE_EE1_effect_slope_high,ASDE_EE2_effect_slope_high + + {0xb6, 0x38}, //40//40 //ASDE_auto_saturation_dec_slope + {0xb7, 0x02}, //04 //ASDE_sub_saturation_slope + {0xb9, 0x30}, //[7:0]ASDE_auto_saturation_low_limit + {0x3c, 0x08}, //[3:0]auto gray_dec_slope + {0x3d, 0x30}, //[7:0]auto gray_dec_th + + + {0x4b, 0x0d}, //y offset slope + {0x4c, 0x20}, //y offset limit + + {0xfe, 0x00}, +// +///////////////////gamma1//////////////////// +////Gamma + {0xfe, 0x02}, + {0x10, 0x10}, + {0x11, 0x15}, + {0x12, 0x1a}, + {0x13, 0x1f}, + {0x14, 0x2c}, + {0x15, 0x39}, + {0x16, 0x45}, + {0x17, 0x54}, + {0x18, 0x69}, + {0x19, 0x7d}, + {0x1a, 0x8f}, + {0x1b, 0x9d}, + {0x1c, 0xa9}, + {0x1d, 0xbd}, + {0x1e, 0xcd}, + {0x1f, 0xd9}, + {0x20, 0xe3}, + {0x21, 0xea}, + {0x22, 0xef}, + {0x23, 0xf5}, + {0x24, 0xf9}, + {0x25, 0xff}, + +/////auto gamma///// + {0xfe, 0x02}, + {0x26, 0x0f}, + {0x27, 0x14}, + {0x28, 0x19}, + {0x29, 0x1e}, + {0x2a, 0x27}, + {0x2b, 0x33}, + {0x2c, 0x3b}, + {0x2d, 0x45}, + {0x2e, 0x59}, + {0x2f, 0x69}, + {0x30, 0x7c}, + {0x31, 0x89}, + {0x32, 0x98}, + {0x33, 0xae}, + {0x34, 0xc0}, + {0x35, 0xcf}, + {0x36, 0xda}, + {0x37, 0xe2}, + {0x38, 0xe9}, + {0x39, 0xf3}, + {0x3a, 0xf9}, + {0x3b, 0xff}, + +/////////////////////////////////////////////// +/////////// YCP /////////////////////// +/////////////////////////////////////////////// + {0xfe, 0x02}, + {0xd1, 0x30}, //32 // + {0xd2, 0x30}, //32 // + {0xd3, 0x45}, + {0xdd, 0x14}, //edge sa + {0xde, 0x86}, //asde auto gray + {0xed, 0x01}, // + {0xee, 0x28}, + {0xef, 0x30}, + {0xd8, 0xd8}, //autogray protecy + +//////////////////////////// +//////// LSC 0.8/////////////// +//////////////////////////// + {0xfe, 0x01}, + {0xa1, 0x80}, // center_row + {0xa2, 0x80}, // center_col + {0xa4, 0x00}, // sign of b1 + {0xa5, 0x00}, // sign of b1 + {0xa6, 0x70}, // sign of b4 + {0xa7, 0x00}, // sign of b4 + {0xa8, 0x77}, // sign of b22 + {0xa9, 0x77}, // sign of b22 + {0xaa, 0x1f}, // Q1_b1 of R + {0xab, 0x0d}, // Q1_b1 of G + {0xac, 0x19}, // Q1_b1 of B + {0xad, 0x24}, // Q2_b1 of R + {0xae, 0x0e}, // Q2_b1 of G + {0xaf, 0x1d}, // Q2_b1 of B + {0xb0, 0x12}, // Q3_b1 of R + {0xb1, 0x0c}, // Q3_b1 of G + {0xb2, 0x06}, // Q3_b1 of B + {0xb3, 0x13}, // Q4_b1 of R + {0xb4, 0x10}, // Q4_b1 of G + {0xb5, 0x0c}, // Q4_b1 of B + {0xb6, 0x6a}, // right_b2 of R + {0xb7, 0x46}, // right_b2 of G + {0xb8, 0x40}, // right_b2 of B + {0xb9, 0x0b}, // right_b4 of R + {0xba, 0x04}, // right_b4 of G + {0xbb, 0x00}, // right_b4 of B + {0xbc, 0x53}, // left_b2 of R + {0xbd, 0x37}, // left_b2 of G + {0xbe, 0x2d}, // left_b2 of B + {0xbf, 0x0a}, // left_b4 of R + {0xc0, 0x0a}, // left_b4 of G + {0xc1, 0x14}, // left_b4 of B + {0xc2, 0x34}, // up_b2 of R + {0xc3, 0x22}, // up_b2 of G + {0xc4, 0x18}, // up_b2 of B + {0xc5, 0x23}, // up_b4 of R + {0xc6, 0x0f}, // up_b4 of G + {0xc7, 0x3c}, // up_b4 of B + {0xc8, 0x20}, // down_b2 of R + {0xc9, 0x1f}, // down_b2 of G + {0xca, 0x17}, // down_b2 of B + {0xcb, 0x2d}, // down_b4 of R + {0xcc, 0x12}, // down_b4 of G + {0xcd, 0x20}, // down_b4 of B + {0xd0, 0x61}, // right_up_b22 of R + {0xd1, 0x2f}, // right_up_b22 of G + {0xd2, 0x39}, // right_up_b22 of B + {0xd3, 0x45}, // right_down_b22 of R + {0xd4, 0x2c}, // right_down_b22 of G + {0xd5, 0x21}, // right_down_b22 of B + {0xd6, 0x64}, // left_up_b22 of R + {0xd7, 0x2d}, // left_up_b22 of G + {0xd8, 0x30}, // left_up_b22 of B + {0xd9, 0x42}, // left_down_b22 of R + {0xda, 0x27}, // left_down_b22 of G + {0xdb, 0x13}, // left_down_b22 of B + {0xfe, 0x00}, + +///////////////////////////////////////////////// +///////////// AWB //////////////////////// +///////////////////////////////////////////////// + {0xfe, 0x01}, + + {0x4f, 0x00}, + {0x4f, 0x00}, + {0x4b, 0x01}, + {0x4f, 0x00}, + + + {0x4c, 0x01}, + {0x4d, 0x6f}, + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0x70}, + + {0x4e, 0x02}, + {0x4c, 0x01}, + {0x4d, 0x8f}, + {0x4e, 0x02}, + + {0x4c, 0x01}, + {0x4d, 0x90}, + {0x4e, 0x02}, //light + + + {0x4c, 0x01}, + {0x4d, 0xed}, + {0x4e, 0x33}, //light + {0x4c, 0x01}, + {0x4d, 0xcd}, + {0x4e, 0x33}, //light + {0x4c, 0x01}, + {0x4d, 0xec}, + {0x4e, 0x03}, //light + + {0x4c, 0x01}, + {0x4d, 0x6c}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x6d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x6e}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8c}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0x8e}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xab}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xac}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xad}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xae}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xcb}, + {0x4e, 0x03}, + + {0x4c, 0x01}, + {0x4d, 0xcc}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xce}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xeb}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xec}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xee}, + {0x4e, 0x03}, + {0x4c, 0x02}, + {0x4d, 0x0c}, + {0x4e, 0x03}, + {0x4c, 0x02}, + {0x4d, 0x0d}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xea}, + {0x4e, 0x03}, + {0x4c, 0x01}, + {0x4d, 0xaf}, + {0x4e, 0x03}, //dark + {0x4c, 0x01}, + {0x4d, 0xcf}, + {0x4e, 0x03}, //dark + + {0x4c, 0x01}, + {0x4d, 0xca}, + {0x4e, 0x04}, //light + {0x4c, 0x02}, + {0x4d, 0x0b}, + {0x4e, 0x05}, //light + {0x4c, 0x02}, + {0x4d, 0xc8}, + {0x4e, 0x06}, //light 100lux + {0x4c, 0x02}, + {0x4d, 0xa8}, + + {0x4e, 0x06}, //light + {0x4c, 0x02}, + {0x4d, 0xa9}, + {0x4e, 0x06}, //light + + + {0x4c, 0x02}, + {0x4d, 0x89}, + {0x4e, 0x06}, //400lux + {0x4c, 0x02}, + {0x4d, 0x69}, + {0x4e, 0x06}, //f12 + {0x4c, 0x02}, + {0x4d, 0x6a}, + {0x4e, 0x06}, //f12 + {0x4c, 0x02}, + {0x4d, 0xc7}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xe7}, + {0x4e, 0x07}, //100lux + {0x4c, 0x03}, + {0x4d, 0x07}, + {0x4e, 0x07}, //light + + {0x4c, 0x02}, + {0x4d, 0xe8}, + {0x4e, 0x07}, + {0x4c, 0x02}, + {0x4d, 0xe9}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x08}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x09}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x27}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x28}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x29}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x47}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x48}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x49}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x67}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x68}, + {0x4e, 0x07}, + {0x4c, 0x03}, + {0x4d, 0x69}, + {0x4e, 0x07}, + + {0x4f, 0x01}, + {0xfe, 0x01}, + {0x50, 0x80}, //AWB_PRE_mode + {0x51, 0xa8}, //AWB_pre_THD_min[7:0] + {0x52, 0x57}, //AWB_pre_THD_min[15:8] Dominiate luma 0.25=639c 0.22=57a8 + {0x53, 0x38}, //AWB_pre_THD_min_MIX[7:0] + {0x54, 0xc7}, //AWB_pre_THD_min_MIX[15:8] Mix luma 0.5 + + {0x56, 0x0e}, //AWB_tone mode + {0x58, 0x08}, //AWB_C_num_sel,AWB_D_num_sel + {0x5b, 0x00}, //AWB_mix_mode + + {0x5c, 0x74}, //green_num0[7:0] + {0x5d, 0x8b}, //green_num0[15:8] 0.35 + + {0x61, 0xd3}, //R2G_stand0 + {0x62, 0xb5}, //B2G_stand0 + {0x63, 0x00}, //88//a4 //AWB gray mode [7]enable + {0x65, 0x04}, //AWB margin + + {0x67, 0xb2}, //R2G_stand3[7:0] FF/CWF + {0x68, 0xac}, //B2G_stand3[7:0] + {0x69, 0x00}, //R2G_stand4[9:8] B2G_stand4[9:8] R2G_stand3[9:8] B2G_stand3[9:8] + {0x6a, 0xb2}, //R2G_stand4[7:0] TL84/TL84&CWF + {0x6b, 0xac}, //B2G_stand4[7:0] + {0x6c, 0xb2}, //R2G_stand5[7:0] A + {0x6d, 0xac}, //B2G_stand5[7:0] + {0x6e, 0x40}, //AWB_skin_weight R2G_stand5[9:8] B2G_stand5[9:8] + {0x6f, 0x18}, //AWB_indoor_THD (0x21=17 caculate) + {0x73, 0x00}, //AWB_indoor_mode + + {0x70, 0x10}, //AWB low luma TH + {0x71, 0xe8}, //AWB outdoor TH + {0x72, 0xc0}, //outdoor mode + {0x74, 0x01}, //[2:0]AWB skip mode 2x2,4x4,4x8,8x8 + {0x75, 0x01}, //[1:0]AWB_every_N + {0x7f, 0x08}, //[3]gray world frame start + + {0x76, 0x70}, //R limit + {0x77, 0x58}, //G limit + {0x78, 0xa0}, //d8 //B limit + + {0xfe, 0x00}, +// +////////////////////////////////////////// +/////////// CC //////////////////////// +////////////////////////////////////////// + {0xfe, 0x02}, + + {0xc0, 0x01}, //[5:4] CC mode [0]CCT enable + + {0xC1, 0x50}, //D50/D65 + {0xc2, 0xF9}, + {0xc3, 0x00}, //0 + {0xc4, 0xe8}, //e0 + {0xc5, 0x48}, + {0xc6, 0xf0}, + + + {0xC7, 0x50}, + {0xc8, 0xf2}, + {0xc9, 0x00}, + {0xcA, 0xE0}, + {0xcB, 0x45}, + {0xcC, 0xec}, + + {0xCd, 0x45}, + {0xce, 0xf0}, + {0xcf, 0x00}, + {0xe3, 0xf0}, + {0xe4, 0x45}, + {0xe5, 0xe8}, + + + {0xfe, 0x00}, + + {0xf2, 0x0f}, + + +//////////////frame rate 50Hz + {0xfe, 0x00}, + + {0xf7, 0x1d}, + {0xf8, 0x84}, + {0xfa, 0x00}, + + {0x05, 0x01}, //hb + {0x06, 0x3b}, + {0x07, 0x01}, //Vb + {0x08, 0x0b}, + + {0xfe, 0x01}, + {0x25, 0x01}, + {0x26, 0x32}, //step + {0x27, 0x03}, //8.15fps + {0x28, 0x96}, + {0x29, 0x03}, //8.15fps + {0x2a, 0x96}, + {0x2b, 0x03}, //8.15fps + {0x2c, 0x96}, + {0x2d, 0x04}, //8.15fps + {0x2e, 0x62}, + {0x3c, 0x00}, + {0xfe, 0x00}, + +/////////dark sun////// + {0xfe, 0x00}, + {0x18, 0x22}, + {0xfe, 0x02}, + {0x40, 0xbf}, + {0x46, 0xcf}, + {0xfe, 0x00}, + + {0xfe, 0x00}, + + {0xf7, 0x1d}, + {0xf8, 0x84}, + {0xfa, 0x10}, + + {0x05, 0x01}, //hb + {0x06, 0x18}, + {0x07, 0x00}, //Vb + {0x08, 0x2e}, + + {0xfe, 0x01}, + {0x25, 0x00}, + {0x26, 0xa2}, //step + {0x27, 0x01}, + {0x28, 0xe6}, + {0x29, 0x01}, + {0x2a, 0xe6}, + {0x2b, 0x01}, + {0x2c, 0xe6}, + {0x2d, 0x04}, // AEC_exp_level4[12:8] + {0x2e, 0x62}, // AEC_exp_level4[7:0] + {0x3c, 0x00}, + {0xfe, 0x00}, + + {0x09, 0x01}, //row start + {0x0a, 0xd0}, // + {0x0b, 0x02}, //col start + {0x0c, 0x70}, + {0x0d, 0x01}, //height + {0x0e, 0x00}, + {0x0f, 0x01}, //width + {0x10, 0x50}, + + {0x90, 0x01}, //crop + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x00}, + {0x96, 0xf0}, + {0x97, 0x01}, + {0x98, 0x40}, + + + {REGLIST_TAIL, 0x00}, +}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h new file mode 100644 index 0000000000..8b0c562b94 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h @@ -0,0 +1,34 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * NT99141 driver. + * + */ +#ifndef __NT99141_H__ +#define __NT99141_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int nt99141_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int nt99141_init(sensor_t *sensor); + +#endif // __NT99141_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h new file mode 100644 index 0000000000..8301db901a --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h @@ -0,0 +1,211 @@ +/* + * NT99141 register definitions. + */ +#ifndef __NT99141_REG_REGS_H__ +#define __NT99141_REG_REGS_H__ + +/* system control registers */ +#define SYSTEM_CTROL0 0x3021 // Bit[7]: Software reset + // Bit[6]: Software power down + // Bit[5]: Reserved + // Bit[4]: SRB clock SYNC enable + // Bit[3]: Isolation suspend select + // Bit[2:0]: Not used + +/* output format control registers */ +#define FORMAT_CTRL 0x501F // Format select + // Bit[2:0]: + // 000: YUV422 + // 001: RGB + // 010: Dither + // 011: RAW after DPC + // 101: RAW after CIP + +/* format control registers */ +#define FORMAT_CTRL00 0x4300 + +/* frame control registers */ +#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // Bit[3:0]: Frame ON number +#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // BIT[3:0]: Frame OFF number + +/* ISP top control registers */ +#define PRE_ISP_TEST_SETTING_1 0x3025 // Bit[7]: Test enable + // 0: Test disable + // 1: Color bar enable + // Bit[6]: Rolling + // Bit[5]: Transparent + // Bit[4]: Square black and white + // Bit[3:2]: Color bar style + // 00: Standard 8 color bar + // 01: Gradual change at vertical mode 1 + // 10: Gradual change at horizontal + // 11: Gradual change at vertical mode 2 + // Bit[1:0]: Test select + // 00: Color bar + // 01: Random data + // 10: Square data + // 11: Black image + +//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW + +/* AEC/AGC control functions */ +#define AEC_PK_MANUAL 0x3201 // AEC Manual Mode Control + // Bit[7:6]: Reserved + // Bit[5]: Gain delay option + // Valid when 0x3503[4]=1’b0 + // 0: Delay one frame latch + // 1: One frame latch + // Bit[4:2]: Reserved + // Bit[1]: AGC manual + // 0: Auto enable + // 1: Manual enable + // Bit[0]: AEC manual + // 0: Auto enable + // 1: Manual enable + +//gain = {0x350A[1:0], 0x350B[7:0]} / 16 + +/* mirror and flip registers */ +#define TIMING_TC_REG20 0x3022 // Timing Control Register + // Bit[2:1]: Vertical flip enable + // 00: Normal + // 11: Vertical flip + // Bit[0]: Vertical binning enable +#define TIMING_TC_REG21 0x3022 // Timing Control Register + // Bit[5]: Compression Enable + // Bit[2:1]: Horizontal mirror enable + // 00: Normal + // 11: Horizontal mirror + // Bit[0]: Horizontal binning enable + +#define CLOCK_POL_CONTROL 0x3024// Bit[5]: PCLK polarity 0: active low + // 1: active high + // Bit[3]: Gate PCLK under VSYNC + // Bit[2]: Gate PCLK under HREF + // Bit[1]: HREF polarity + // 0: active low + // 1: active high + // Bit[0] VSYNC polarity + // 0: active low + // 1: active high +#define DRIVE_CAPABILITY 0x306a // Bit[7:6]: + // 00: 1x + // 01: 2x + // 10: 3x + // 11: 4x + + +#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] +#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] +#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] +#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] +#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] +#define X_ADDR_END_L 0x3805 //Bit[7:0]: +#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] +#define Y_ADDR_END_L 0x3807 //Bit[7:0]: +// Size after scaling +#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] +#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: +#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] +#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: +#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] +#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: +#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] +#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: +#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] +#define X_OFFSET_L 0x3811 //Bit[7:0]: +#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] +#define Y_OFFSET_L 0x3813 //Bit[7:0]: +#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment + //Bit[3:0]: Horizontal even subsample increment +#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment + //Bit[3:0]: Vertical even subsample increment +// Size before scaling +//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) +//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) + +#define ISP_CONTROL_01 0x3021 // Bit[5]: Scale enable + // 0: Disable + // 1: Enable + +#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + // Bit[2:0]: VDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + +#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits +#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits +#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits +#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits +#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset + +#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual +#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable + // 0: Auto + // 1: Manual by PCLK_RATIO + +#define VFIFO_X_SIZE_H 0x4602 +#define VFIFO_X_SIZE_L 0x4603 +#define VFIFO_Y_SIZE_H 0x4604 +#define VFIFO_Y_SIZE_L 0x4605 + +#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass +#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier +#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control + // Bit[3:0]: PLLS system divider +#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider + // 00: 1 + // 01: 1.5 + // 10: 2 + // 11: 3 + // Bit[2]: PLLS root-divider - 1 + // Bit[1:0]: PLLS seld5 + // 00: 1 + // 01: 1 + // 10: 2 + // 11: 2.5 + +#define COMPRESSION_CTRL00 0x4400 // +#define COMPRESSION_CTRL01 0x4401 // +#define COMPRESSION_CTRL02 0x4402 // +#define COMPRESSION_CTRL03 0x4403 // +#define COMPRESSION_CTRL04 0x4404 // +#define COMPRESSION_CTRL05 0x4405 // +#define COMPRESSION_CTRL06 0x4406 // +#define COMPRESSION_CTRL07 0x3401 // Bit[5:0]: QS +#define COMPRESSION_ISI_CTRL 0x4408 // +#define COMPRESSION_CTRL09 0x4409 // +#define COMPRESSION_CTRL0a 0x440a // +#define COMPRESSION_CTRL0b 0x440b // +#define COMPRESSION_CTRL0c 0x440c // +#define COMPRESSION_CTRL0d 0x440d // +#define COMPRESSION_CTRL0E 0x440e // + +/** + * @brief register value + */ +#define TEST_COLOR_BAR 0x02 /* Enable Color Bar roling Test */ + +#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ +#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ + +#define TIMING_TC_REG20_VFLIP 0x01 /* Vertical flip enable */ +#define TIMING_TC_REG21_HMIRROR 0x02 /* Horizontal mirror enable */ + +#endif // __NT99141_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h new file mode 100644 index 0000000000..1ffec20539 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h @@ -0,0 +1,825 @@ +#ifndef _NT99141_SETTINGS_H_ +#define _NT99141_SETTINGS_H_ + +#include +#include +#include "esp_attr.h" +#include "nt99141_regs.h" + +static const ratio_settings_t ratio_table[] = { + // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty + { 1280, 720, 0, 4, 1283, 723, 0, 4, 1660, 963 }, + +}; + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0x0000 + +static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { + //initial +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x3109, 0x04}, +{0x3040, 0x04}, +{0x3041, 0x02}, +{0x3042, 0xFF}, +{0x3043, 0x08}, +{0x3052, 0xE0}, +{0x305F, 0x33}, +{0x3100, 0x07}, +{0x3106, 0x03}, +{0x3105, 0x01}, +{0x3108, 0x05}, +{0x3110, 0x22}, +{0x3111, 0x57}, +{0x3112, 0x22}, +{0x3113, 0x55}, +{0x3114, 0x05}, +{0x3135, 0x00}, +{0x32F0, 0x01}, +{0x3290, 0x01}, +{0x3291, 0x80}, +{0x3296, 0x01}, +{0x3297, 0x73}, +{0x3250, 0x80}, +{0x3251, 0x03}, +{0x3252, 0xFF}, +{0x3253, 0x00}, +{0x3254, 0x03}, +{0x3255, 0xFF}, +{0x3256, 0x00}, +{0x3257, 0x50}, +{0x3270, 0x00}, +{0x3271, 0x0C}, +{0x3272, 0x18}, +{0x3273, 0x32}, +{0x3274, 0x44}, +{0x3275, 0x54}, +{0x3276, 0x70}, +{0x3277, 0x88}, +{0x3278, 0x9D}, +{0x3279, 0xB0}, +{0x327A, 0xCF}, +{0x327B, 0xE2}, +{0x327C, 0xEF}, +{0x327D, 0xF7}, +{0x327E, 0xFF}, +{0x3302, 0x00}, +{0x3303, 0x40}, +{0x3304, 0x00}, +{0x3305, 0x96}, +{0x3306, 0x00}, +{0x3307, 0x29}, +{0x3308, 0x07}, +{0x3309, 0xBA}, +{0x330A, 0x06}, +{0x330B, 0xF5}, +{0x330C, 0x01}, +{0x330D, 0x51}, +{0x330E, 0x01}, +{0x330F, 0x30}, +{0x3310, 0x07}, +{0x3311, 0x16}, +{0x3312, 0x07}, +{0x3313, 0xBA}, +{0x3326, 0x02}, +{0x32F6, 0x0F}, +{0x32F9, 0x42}, +{0x32FA, 0x24}, +{0x3325, 0x4A}, +{0x3330, 0x00}, +{0x3331, 0x0A}, +{0x3332, 0xFF}, +{0x3338, 0x30}, +{0x3339, 0x84}, +{0x333A, 0x48}, +{0x333F, 0x07}, +{0x3360, 0x10}, +{0x3361, 0x18}, +{0x3362, 0x1f}, +{0x3363, 0x37}, +{0x3364, 0x80}, +{0x3365, 0x80}, +{0x3366, 0x68}, +{0x3367, 0x60}, +{0x3368, 0x30}, +{0x3369, 0x28}, +{0x336A, 0x20}, +{0x336B, 0x10}, +{0x336C, 0x00}, +{0x336D, 0x20}, +{0x336E, 0x1C}, +{0x336F, 0x18}, +{0x3370, 0x10}, +{0x3371, 0x38}, +{0x3372, 0x3C}, +{0x3373, 0x3F}, +{0x3374, 0x3F}, +{0x338A, 0x34}, +{0x338B, 0x7F}, +{0x338C, 0x10}, +{0x338D, 0x23}, +{0x338E, 0x7F}, +{0x338F, 0x14}, +{0x3375, 0x08}, +{0x3376, 0x0C}, +{0x3377, 0x18}, +{0x3378, 0x20}, +{0x3012, 0x02}, +{0x3013, 0xD0}, +{0x3025, 0x02}, //colorbar +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { + {0x32F0, 0x70}, // YUV422 + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { + {0x32F0, 0x50}, // RAW + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { + {0x32F1, 0x01}, + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { + {0x32F0, 0x00}, // YUV422 + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { + {0x32F0, 0x01}, // RGB + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint8_t sensor_saturation_levels[9][1] = { + {0x60},//-4 + {0x68},//-3 + {0x70},//-2 + {0x78},//-1 + {0x80},//0 + {0x88},//+1 + {0x90},//+2 + {0x98},//+3 + {0xA0},//+4 +}; + +static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { + {0x00, 0x80, 0x80, 0x01},//Normal + {0x03, 0x80, 0x80, 0x01},//Negative + {0x01, 0x80, 0x80, 0x01},//Grayscale + {0x05, 0x2A, 0xF0, 0x01},//Red Tint + {0x05, 0x60, 0x20, 0x01},//Green Tint + {0x05, 0xF0, 0x80, 0x01},//Blue Tint + {0x02, 0x80, 0x80, 0x01},//Sepia + +}; + +// AE LEVEL +static const DRAM_ATTR uint16_t sensor_ae_level[][2] = { + +// 1. [AE_Target : 0x24] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x29 }, + {0x32B9, 0x1F }, + {0x32BC, 0x24 }, + {0x32BD, 0x27 }, + {0x32BE, 0x21 }, +//------------------------------------------------------------------------ +// 2. [AE_Target : 0x28] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x2D }, + {0x32B9, 0x23 }, + {0x32BC, 0x28 }, + {0x32BD, 0x2B }, + {0x32BE, 0x25 }, +//------------------------------------------------------------------------ +// 3. [AE_Target : 0x2C] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x32 }, + {0x32B9, 0x26 }, + {0x32BC, 0x2C }, + {0x32BD, 0x2F }, + {0x32BE, 0x29 }, +//------------------------------------------------------------------------ +// 4, [AE_Target : 0x30] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x36 }, + {0x32B9, 0x2A }, + {0x32BC, 0x30 }, + {0x32BD, 0x33 }, + {0x32BE, 0x2D }, +//------------------------------------------------------------------------ +// 5. [AE_Target : 0x34] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x3B }, + {0x32B9, 0x2D }, + {0x32BC, 0x34 }, + {0x32BD, 0x38 }, + {0x32BE, 0x30 }, +//------------------------------------------------------------------------ +// 6. [AE_Target : 0x38] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x3F }, + {0x32B9, 0x31 }, + {0x32BC, 0x38 }, + {0x32BD, 0x3C }, + {0x32BE, 0x34 }, +//------------------------------------------------------------------------ +// 7. [AE_Target : 0x3D] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x44 }, + {0x32B9, 0x34 }, + {0x32BC, 0x3C }, + {0x32BD, 0x40 }, + {0x32BE, 0x38 }, +//------------------------------------------------------------------------ +// 8. [AE_Target : 0x40] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x48 }, + {0x32B9, 0x38 }, + {0x32BC, 0x40 }, + {0x32BD, 0x44 }, + {0x32BE, 0x3C }, +//------------------------------------------------------------------------ +// 9. [AE_Target : 0x44] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 + {0x32B8, 0x4D }, + {0x32B9, 0x3B }, + {0x32BC, 0x44 }, + {0x32BD, 0x49 }, + {0x32BE, 0x3F }, +}; + +static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = { +//[JPEG_1280x720_8.18_8.18_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x3C}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x5E}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x24}, +{0x3002, 0x00}, +{0x3003, 0x04}, +{0x3004, 0x00}, +{0x3005, 0x04}, +{0x3006, 0x05}, +{0x3007, 0x03}, +{0x3008, 0x02}, +{0x3009, 0xD3}, +{0x300A, 0x06}, +{0x300B, 0x7C}, +{0x300C, 0x02}, +{0x300D, 0xE0}, +{0x300E, 0x05}, +{0x300F, 0x00}, +{0x3010, 0x02}, +{0x3011, 0xD0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x3F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = { +//[JPEG_640x480_10.14_10.14_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x4B}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x62}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x32E0, 0x02}, +{0x32E1, 0x80}, +{0x32E2, 0x01}, +{0x32E3, 0xE0}, +{0x32E4, 0x00}, +{0x32E5, 0x80}, +{0x32E6, 0x00}, +{0x32E7, 0x80}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x24}, +{0x3002, 0x00}, +{0x3003, 0xA4}, +{0x3004, 0x00}, +{0x3005, 0x04}, +{0x3006, 0x04}, +{0x3007, 0x63}, +{0x3008, 0x02}, +{0x3009, 0xD3}, +{0x300A, 0x05}, +{0x300B, 0x3C}, +{0x300C, 0x02}, +{0x300D, 0xE0}, +{0x300E, 0x03}, +{0x300F, 0xC0}, +{0x3010, 0x02}, +{0x3011, 0xD0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x7F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = { +//[JPEG_320x240_10.14_10.14_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x4B}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x62}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x32E0, 0x01}, +{0x32E1, 0x40}, +{0x32E2, 0x00}, +{0x32E3, 0xF0}, +{0x32E4, 0x02}, +{0x32E5, 0x02}, +{0x32E6, 0x02}, +{0x32E7, 0x03}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x24}, +{0x3002, 0x00}, +{0x3003, 0xA4}, +{0x3004, 0x00}, +{0x3005, 0x04}, +{0x3006, 0x04}, +{0x3007, 0x63}, +{0x3008, 0x02}, +{0x3009, 0xD3}, +{0x300A, 0x05}, +{0x300B, 0x3C}, +{0x300C, 0x02}, +{0x300D, 0xE0}, +{0x300E, 0x03}, +{0x300F, 0xC0}, +{0x3010, 0x02}, +{0x3011, 0xD0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x7F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_VGA_xyskip[][2] = { +// [JPEG_640x360_20.00_25.01_Fps_XY_Skip] +// Set_Device_Format = FORMAT_16_8 +// SET_Device_Addr = 0x54 +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60 }, +{0x320A, 0xB2 }, +{0x32C0, 0x64 }, +{0x32C1, 0x64 }, +{0x32C2, 0x64 }, +{0x32C3, 0x00 }, +{0x32C4, 0x20 }, +{0x32C5, 0x20 }, +{0x32C6, 0x20 }, +{0x32C7, 0x00 }, +{0x32C8, 0x62 }, +{0x32C9, 0x64 }, +{0x32CA, 0x84 }, +{0x32CB, 0x84 }, +{0x32CC, 0x84 }, +{0x32CD, 0x84 }, +{0x32DB, 0x68 }, +{0x32F0, 0x70 }, +{0x3400, 0x08 }, +{0x3400, 0x00 }, +{0x3401, 0x4E }, +{0x3404, 0x00 }, +{0x3405, 0x00 }, +{0x3410, 0x00 }, +{0x3200, 0x3E }, +{0x3201, 0x0F }, +{0x3028, 0x0F }, +{0x3029, 0x00 }, +{0x302A, 0x08 }, +{0x3022, 0x24 }, +{0x3023, 0x6C }, +{0x3002, 0x00 }, +{0x3003, 0x04 }, +{0x3004, 0x00 }, +{0x3005, 0x04 }, +{0x3006, 0x05 }, +{0x3007, 0x03 }, +{0x3008, 0x02 }, +{0x3009, 0xD3 }, +{0x300A, 0x03 }, +{0x300B, 0xFC }, +{0x300C, 0x01 }, +{0x300D, 0x88 }, +{0x300E, 0x02 }, +{0x300F, 0x80 }, +{0x3010, 0x01 }, +{0x3011, 0x68 }, +{0x32B8, 0x3F }, +{0x32B9, 0x31 }, +{0x32BB, 0x87 }, +{0x32BC, 0x38 }, +{0x32BD, 0x3C }, +{0x32BE, 0x34 }, +{0x3201, 0x3F }, +{0x3025, 0x00 }, //normal +{0x3021, 0x06 }, +{0x3400, 0x01 }, +{0x3060, 0x01 }, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_VGA_xskip[][2] = { +//[JPEG_640x480_Xskip_13.32_13.32_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x62}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x68}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x32E0, 0x02}, +{0x32E1, 0x80}, +{0x32E2, 0x01}, +{0x32E3, 0xE0}, +{0x32E4, 0x00}, +{0x32E5, 0x00}, +{0x32E6, 0x00}, +{0x32E7, 0x80}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x2C}, +{0x3002, 0x00}, +{0x3003, 0x04}, +{0x3004, 0x00}, +{0x3005, 0x04}, +{0x3006, 0x05}, +{0x3007, 0x03}, +{0x3008, 0x02}, +{0x3009, 0xD3}, +{0x300A, 0x03}, +{0x300B, 0xFC}, +{0x300C, 0x02}, +{0x300D, 0xE0}, +{0x300E, 0x02}, +{0x300F, 0x80}, +{0x3010, 0x02}, +{0x3011, 0xD0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x7F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QVGA_xskip[][2] = { +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +//[JPEG_320x240_Xskip_13.32_13.32_Fps] +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x62}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x68}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x32E0, 0x01}, +{0x32E1, 0x40}, +{0x32E2, 0x00}, +{0x32E3, 0xF0}, +{0x32E4, 0x01}, +{0x32E5, 0x01}, +{0x32E6, 0x02}, +{0x32E7, 0x03}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x2C}, +{0x3002, 0x00}, +{0x3003, 0x04}, +{0x3004, 0x00}, +{0x3005, 0x04}, +{0x3006, 0x05}, +{0x3007, 0x03}, +{0x3008, 0x02}, +{0x3009, 0xD3}, +{0x300A, 0x03}, +{0x300B, 0xFC}, +{0x300C, 0x02}, +{0x300D, 0xE0}, +{0x300E, 0x02}, +{0x300F, 0x80}, +{0x3010, 0x02}, +{0x3011, 0xD0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x7F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + + +static const DRAM_ATTR uint16_t sensor_framesize_VGA_crop[][2] = { +//[JPEG_640x480_Crop_19.77_19.77_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x62}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x68}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x24}, +{0x3002, 0x01}, +{0x3003, 0x44}, +{0x3004, 0x00}, +{0x3005, 0x7C}, +{0x3006, 0x03}, +{0x3007, 0xC3}, +{0x3008, 0x02}, +{0x3009, 0x5B}, +{0x300A, 0x03}, +{0x300B, 0xFC}, +{0x300C, 0x01}, +{0x300D, 0xF0}, +{0x300E, 0x02}, +{0x300F, 0x80}, +{0x3010, 0x01}, +{0x3011, 0xE0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x3F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_framesize_QVGA_crop[][2] = { +//[JPEG_320x240_Crop_19.77_19.77_Fps] +{0x3021, 0x00}, +{REG_DLY, 100}, // delay 100ms +{0x32BF, 0x60}, +{0x32C0, 0x5A}, +{0x32C1, 0x5A}, +{0x32C2, 0x5A}, +{0x32C3, 0x00}, +{0x32C4, 0x20}, +{0x32C5, 0x20}, +{0x32C6, 0x20}, +{0x32C7, 0x00}, +{0x32C8, 0x62}, +{0x32C9, 0x5A}, +{0x32CA, 0x7A}, +{0x32CB, 0x7A}, +{0x32CC, 0x7A}, +{0x32CD, 0x7A}, +{0x32DB, 0x68}, +{0x32F0, 0x70}, +{0x3400, 0x08}, +{0x3400, 0x00}, +{0x3401, 0x4E}, +{0x3404, 0x00}, +{0x3405, 0x00}, +{0x3410, 0x00}, +{0x32E0, 0x01}, +{0x32E1, 0x40}, +{0x32E2, 0x00}, +{0x32E3, 0xF0}, +{0x32E4, 0x01}, +{0x32E5, 0x01}, +{0x32E6, 0x01}, +{0x32E7, 0x02}, +{0x3200, 0x3E}, +{0x3201, 0x0F}, +{0x3028, 0x0F}, +{0x3029, 0x00}, +{0x302A, 0x08}, +{0x3022, 0x24}, +{0x3023, 0x24}, +{0x3002, 0x01}, +{0x3003, 0x44}, +{0x3004, 0x00}, +{0x3005, 0x7C}, +{0x3006, 0x03}, +{0x3007, 0xC3}, +{0x3008, 0x02}, +{0x3009, 0x5B}, +{0x300A, 0x03}, +{0x300B, 0xFC}, +{0x300C, 0x01}, +{0x300D, 0xF0}, +{0x300E, 0x02}, +{0x300F, 0x80}, +{0x3010, 0x01}, +{0x3011, 0xE0}, +{0x32B8, 0x3F}, +{0x32B9, 0x31}, +{0x32BB, 0x87}, +{0x32BC, 0x38}, +{0x32BD, 0x3C}, +{0x32BE, 0x34}, +{0x3201, 0x7F}, +{0x3021, 0x06}, +{0x3025, 0x00}, //normal +{0x3400, 0x01}, +{0x3060, 0x01}, +{REGLIST_TAIL, 0x00}, // tail +}; + +#endif + + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h new file mode 100644 index 0000000000..342ab21328 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h @@ -0,0 +1,32 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV2640 driver. + * + */ +#ifndef __OV2640_H__ +#define __OV2640_H__ +#include "sensor.h" +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov2640_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov2640_init(sensor_t *sensor); + +#endif // __OV2640_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h new file mode 100644 index 0000000000..8f47333fa9 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h @@ -0,0 +1,216 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV2640 register definitions. + */ +#ifndef __REG_REGS_H__ +#define __REG_REGS_H__ +/* DSP register bank FF=0x00*/ +#define R_BYPASS 0x05 +#define QS 0x44 +#define CTRLI 0x50 +#define HSIZE 0x51 +#define VSIZE 0x52 +#define XOFFL 0x53 +#define YOFFL 0x54 +#define VHYX 0x55 +#define DPRP 0x56 +#define TEST 0x57 +#define ZMOW 0x5A +#define ZMOH 0x5B +#define ZMHH 0x5C +#define BPADDR 0x7C +#define BPDATA 0x7D +#define CTRL2 0x86 +#define CTRL3 0x87 +#define SIZEL 0x8C +#define HSIZE8 0xC0 +#define VSIZE8 0xC1 +#define CTRL0 0xC2 +#define CTRL1 0xC3 +#define R_DVP_SP 0xD3 +#define IMAGE_MODE 0xDA +#define RESET 0xE0 +#define MS_SP 0xF0 +#define SS_ID 0xF7 +#define SS_CTRL 0xF7 +#define MC_BIST 0xF9 +#define MC_AL 0xFA +#define MC_AH 0xFB +#define MC_D 0xFC +#define P_CMD 0xFD +#define P_STATUS 0xFE +#define BANK_SEL 0xFF + +#define CTRLI_LP_DP 0x80 +#define CTRLI_ROUND 0x40 + +#define CTRL0_AEC_EN 0x80 +#define CTRL0_AEC_SEL 0x40 +#define CTRL0_STAT_SEL 0x20 +#define CTRL0_VFIRST 0x10 +#define CTRL0_YUV422 0x08 +#define CTRL0_YUV_EN 0x04 +#define CTRL0_RGB_EN 0x02 +#define CTRL0_RAW_EN 0x01 + +#define CTRL2_DCW_EN 0x20 +#define CTRL2_SDE_EN 0x10 +#define CTRL2_UV_ADJ_EN 0x08 +#define CTRL2_UV_AVG_EN 0x04 +#define CTRL2_CMX_EN 0x01 + +#define CTRL3_BPC_EN 0x80 +#define CTRL3_WPC_EN 0x40 + +#define R_DVP_SP_AUTO_MODE 0x80 + +#define R_BYPASS_DSP_EN 0x00 +#define R_BYPASS_DSP_BYPAS 0x01 + +#define IMAGE_MODE_Y8_DVP_EN 0x40 +#define IMAGE_MODE_JPEG_EN 0x10 +#define IMAGE_MODE_YUV422 0x00 +#define IMAGE_MODE_RAW10 0x04 +#define IMAGE_MODE_RGB565 0x08 +#define IMAGE_MODE_HREF_VSYNC 0x02 +#define IMAGE_MODE_LBYTE_FIRST 0x01 + +#define RESET_MICROC 0x40 +#define RESET_SCCB 0x20 +#define RESET_JPEG 0x10 +#define RESET_DVP 0x04 +#define RESET_IPU 0x02 +#define RESET_CIF 0x01 + +#define MC_BIST_RESET 0x80 +#define MC_BIST_BOOT_ROM_SEL 0x40 +#define MC_BIST_12KB_SEL 0x20 +#define MC_BIST_12KB_MASK 0x30 +#define MC_BIST_512KB_SEL 0x08 +#define MC_BIST_512KB_MASK 0x0C +#define MC_BIST_BUSY_BIT_R 0x02 +#define MC_BIST_MC_RES_ONE_SH_W 0x02 +#define MC_BIST_LAUNCH 0x01 + + +typedef enum { + BANK_DSP, BANK_SENSOR, BANK_MAX +} ov2640_bank_t; + +/* Sensor register bank FF=0x01*/ +#define GAIN 0x00 +#define COM1 0x03 +#define REG04 0x04 +#define REG08 0x08 +#define COM2 0x09 +#define REG_PID 0x0A +#define REG_VER 0x0B +#define COM3 0x0C +#define COM4 0x0D +#define AEC 0x10 +#define CLKRC 0x11 +#define COM7 0x12 +#define COM8 0x13 +#define COM9 0x14 /* AGC gain ceiling */ +#define COM10 0x15 +#define HSTART 0x17 +#define HSTOP 0x18 +#define VSTART 0x19 +#define VSTOP 0x1A +#define REG_MIDH 0x1C +#define REG_MIDL 0x1D +#define AEW 0x24 +#define AEB 0x25 +#define VV 0x26 +#define REG2A 0x2A +#define FRARL 0x2B +#define ADDVSL 0x2D +#define ADDVSH 0x2E +#define YAVG 0x2F +#define HSDY 0x30 +#define HEDY 0x31 +#define REG32 0x32 +#define ARCOM2 0x34 +#define REG45 0x45 +#define FLL 0x46 +#define FLH 0x47 +#define COM19 0x48 +#define ZOOMS 0x49 +#define COM22 0x4B +#define COM25 0x4E +#define BD50 0x4F +#define BD60 0x50 +#define REG5D 0x5D +#define REG5E 0x5E +#define REG5F 0x5F +#define REG60 0x60 +#define HISTO_LOW 0x61 +#define HISTO_HIGH 0x62 + +#define REG04_DEFAULT 0x28 +#define REG04_HFLIP_IMG 0x80 +#define REG04_VFLIP_IMG 0x40 +#define REG04_VREF_EN 0x10 +#define REG04_HREF_EN 0x08 +#define REG04_SET(x) (REG04_DEFAULT|x) + +#define COM2_STDBY 0x10 +#define COM2_OUT_DRIVE_1x 0x00 +#define COM2_OUT_DRIVE_2x 0x01 +#define COM2_OUT_DRIVE_3x 0x02 +#define COM2_OUT_DRIVE_4x 0x03 + +#define COM3_DEFAULT 0x38 +#define COM3_BAND_50Hz 0x04 +#define COM3_BAND_60Hz 0x00 +#define COM3_BAND_AUTO 0x02 +#define COM3_BAND_SET(x) (COM3_DEFAULT|x) + +#define COM7_SRST 0x80 +#define COM7_RES_UXGA 0x00 /* UXGA */ +#define COM7_RES_SVGA 0x40 /* SVGA */ +#define COM7_RES_CIF 0x20 /* CIF */ +#define COM7_ZOOM_EN 0x04 /* Enable Zoom */ +#define COM7_COLOR_BAR 0x02 /* Enable Color Bar Test */ + +#define COM8_DEFAULT 0xC0 +#define COM8_BNDF_EN 0x20 /* Enable Banding filter */ +#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ +#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ +#define COM8_SET(x) (COM8_DEFAULT|x) + +#define COM9_DEFAULT 0x08 +#define COM9_AGC_GAIN_2x 0x00 /* AGC: 2x */ +#define COM9_AGC_GAIN_4x 0x01 /* AGC: 4x */ +#define COM9_AGC_GAIN_8x 0x02 /* AGC: 8x */ +#define COM9_AGC_GAIN_16x 0x03 /* AGC: 16x */ +#define COM9_AGC_GAIN_32x 0x04 /* AGC: 32x */ +#define COM9_AGC_GAIN_64x 0x05 /* AGC: 64x */ +#define COM9_AGC_GAIN_128x 0x06 /* AGC: 128x */ +#define COM9_AGC_SET(x) (COM9_DEFAULT|(x<<5)) + +#define COM10_HREF_EN 0x80 /* HSYNC changes to HREF */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x20 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_EDGE 0x10 /* Data is updated at the rising edge of PCLK */ +#define COM10_HREF_NEG 0x08 /* HREF negative */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_HSYNC_NEG 0x01 /* HSYNC negative */ + +#define CTRL1_AWB 0x08 /* Enable AWB */ + +#define VV_AGC_TH_SET(h,l) ((h<<4)|(l&0x0F)) + +#define REG32_UXGA 0x36 +#define REG32_SVGA 0x09 +#define REG32_CIF 0x89 + +#define CLKRC_2X 0x80 +#define CLKRC_2X_UXGA (0x01 | CLKRC_2X) +#define CLKRC_2X_SVGA CLKRC_2X +#define CLKRC_2X_CIF CLKRC_2X + +#endif //__REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h new file mode 100644 index 0000000000..f151f0a428 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h @@ -0,0 +1,485 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _OV2640_SETTINGS_H_ +#define _OV2640_SETTINGS_H_ + +#include +#include +#include "esp_attr.h" +#include "ov2640_regs.h" + +typedef enum { + OV2640_MODE_UXGA, OV2640_MODE_SVGA, OV2640_MODE_CIF, OV2640_MODE_MAX +} ov2640_sensor_mode_t; + +typedef struct { + union { + struct { + uint8_t pclk_div:7; + uint8_t pclk_auto:1; + }; + uint8_t pclk; + }; + union { + struct { + uint8_t clk_div:6; + uint8_t reserved:1; + uint8_t clk_2x:1; + }; + uint8_t clk; + }; +} ov2640_clk_t; + +typedef struct { + uint16_t offset_x; + uint16_t offset_y; + uint16_t max_x; + uint16_t max_y; +} ov2640_ratio_settings_t; + +static const DRAM_ATTR ov2640_ratio_settings_t ratio_table[] = { + // ox, oy, mx, my + { 0, 0, 1600, 1200 }, //4x3 + { 8, 72, 1584, 1056 }, //3x2 + { 0, 100, 1600, 1000 }, //16x10 + { 0, 120, 1600, 960 }, //5x3 + { 0, 150, 1600, 900 }, //16x9 + { 2, 258, 1596, 684 }, //21x9 + { 50, 0, 1500, 1200 }, //5x4 + { 200, 0, 1200, 1200 }, //1x1 + { 462, 0, 676, 1200 } //9x16 +}; + +// 30fps@24MHz +const DRAM_ATTR uint8_t ov2640_settings_cif[][2] = { + {BANK_SEL, BANK_DSP}, + {0x2c, 0xff}, + {0x2e, 0xdf}, + {BANK_SEL, BANK_SENSOR}, + {0x3c, 0x32}, + {CLKRC, 0x01}, + {COM2, COM2_OUT_DRIVE_3x}, + {REG04, REG04_DEFAULT}, + {COM8, COM8_DEFAULT | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN}, + {COM9, COM9_AGC_SET(COM9_AGC_GAIN_8x)}, + {0x2c, 0x0c}, + {0x33, 0x78}, + {0x3a, 0x33}, + {0x3b, 0xfB}, + {0x3e, 0x00}, + {0x43, 0x11}, + {0x16, 0x10}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {ARCOM2, 0xc0}, + {0x06, 0x88}, + {0x07, 0xc0}, + {COM4, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {0x4a, 0x81}, + {0x21, 0x99}, + {AEW, 0x40}, + {AEB, 0x38}, + {VV, VV_AGC_TH_SET(8,2)}, + {0x5c, 0x00}, + {0x63, 0x00}, + {HISTO_LOW, 0x70}, + {HISTO_HIGH, 0x80}, + {0x7c, 0x05}, + {0x20, 0x80}, + {0x28, 0x30}, + {0x6c, 0x00}, + {0x6d, 0x80}, + {0x6e, 0x00}, + {0x70, 0x02}, + {0x71, 0x94}, + {0x73, 0xc1}, + {0x3d, 0x34}, + {0x5a, 0x57}, + {BD50, 0xbb}, + {BD60, 0x9c}, + {COM7, COM7_RES_CIF}, + {HSTART, 0x11}, + {HSTOP, 0x43}, + {VSTART, 0x00}, + {VSTOP, 0x25}, + {REG32, 0x89}, + {0x37, 0xc0}, + {BD50, 0xca}, + {BD60, 0xa8}, + {0x6d, 0x00}, + {0x3d, 0x38}, + {BANK_SEL, BANK_DSP}, + {0xe5, 0x7f}, + {MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL}, + {0x41, 0x24}, + {RESET, RESET_JPEG | RESET_DVP}, + {0x76, 0xff}, + {0x33, 0xa0}, + {0x42, 0x20}, + {0x43, 0x18}, + {0x4c, 0x00}, + {CTRL3, CTRL3_WPC_EN | 0x10 }, + {0x88, 0x3f}, + {0xd7, 0x03}, + {0xd9, 0x10}, + {R_DVP_SP, R_DVP_SP_AUTO_MODE | 0x02}, + {0xc8, 0x08}, + {0xc9, 0x80}, + {BPADDR, 0x00}, + {BPDATA, 0x00}, + {BPADDR, 0x03}, + {BPDATA, 0x48}, + {BPDATA, 0x48}, + {BPADDR, 0x08}, + {BPDATA, 0x20}, + {BPDATA, 0x10}, + {BPDATA, 0x0e}, + {0x90, 0x00}, + {0x91, 0x0e}, + {0x91, 0x1a}, + {0x91, 0x31}, + {0x91, 0x5a}, + {0x91, 0x69}, + {0x91, 0x75}, + {0x91, 0x7e}, + {0x91, 0x88}, + {0x91, 0x8f}, + {0x91, 0x96}, + {0x91, 0xa3}, + {0x91, 0xaf}, + {0x91, 0xc4}, + {0x91, 0xd7}, + {0x91, 0xe8}, + {0x91, 0x20}, + {0x92, 0x00}, + {0x93, 0x06}, + {0x93, 0xe3}, + {0x93, 0x05}, + {0x93, 0x05}, + {0x93, 0x00}, + {0x93, 0x04}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x96, 0x00}, + {0x97, 0x08}, + {0x97, 0x19}, + {0x97, 0x02}, + {0x97, 0x0c}, + {0x97, 0x24}, + {0x97, 0x30}, + {0x97, 0x28}, + {0x97, 0x26}, + {0x97, 0x02}, + {0x97, 0x98}, + {0x97, 0x80}, + {0x97, 0x00}, + {0x97, 0x00}, + {0xa4, 0x00}, + {0xa8, 0x00}, + {0xc5, 0x11}, + {0xc6, 0x51}, + {0xbf, 0x80}, + {0xc7, 0x10}, + {0xb6, 0x66}, + {0xb8, 0xA5}, + {0xb7, 0x64}, + {0xb9, 0x7C}, + {0xb3, 0xaf}, + {0xb4, 0x97}, + {0xb5, 0xFF}, + {0xb0, 0xC5}, + {0xb1, 0x94}, + {0xb2, 0x0f}, + {0xc4, 0x5c}, + {CTRL1, 0xfd}, + {0x7f, 0x00}, + {0xe5, 0x1f}, + {0xe1, 0x67}, + {0xdd, 0x7f}, + {IMAGE_MODE, 0x00}, + {RESET, 0x00}, + {R_BYPASS, R_BYPASS_DSP_EN}, + {0, 0} +}; + +const DRAM_ATTR uint8_t ov2640_settings_to_cif[][2] = { + {BANK_SEL, BANK_SENSOR}, + {COM7, COM7_RES_CIF}, + + //Set the sensor output window + {COM1, 0x0A}, + {REG32, REG32_CIF}, + {HSTART, 0x11}, + {HSTOP, 0x43}, + {VSTART, 0x00}, + {VSTOP, 0x25}, + + //{CLKRC, 0x00}, + {BD50, 0xca}, + {BD60, 0xa8}, + {0x5a, 0x23}, + {0x6d, 0x00}, + {0x3d, 0x38}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {ARCOM2, 0xc0}, + {0x06, 0x88}, + {0x07, 0xc0}, + {COM4, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {BANK_SEL, BANK_DSP}, + {RESET, RESET_DVP}, + + //Set the sensor resolution (UXGA, SVGA, CIF) + {HSIZE8, 0x32}, + {VSIZE8, 0x25}, + {SIZEL, 0x00}, + + //Set the image window size >= output size + {HSIZE, 0x64}, + {VSIZE, 0x4a}, + {XOFFL, 0x00}, + {YOFFL, 0x00}, + {VHYX, 0x00}, + {TEST, 0x00}, + + {CTRL2, CTRL2_DCW_EN | 0x1D}, + {CTRLI, CTRLI_LP_DP | 0x00}, + //{R_DVP_SP, 0x08}, + {0, 0} +}; + +const DRAM_ATTR uint8_t ov2640_settings_to_svga[][2] = { + {BANK_SEL, BANK_SENSOR}, + {COM7, COM7_RES_SVGA}, + + //Set the sensor output window + {COM1, 0x0A}, + {REG32, REG32_SVGA}, + {HSTART, 0x11}, + {HSTOP, 0x43}, + {VSTART, 0x00}, + {VSTOP, 0x4b}, + + //{CLKRC, 0x00}, + {0x37, 0xc0}, + {BD50, 0xca}, + {BD60, 0xa8}, + {0x5a, 0x23}, + {0x6d, 0x00}, + {0x3d, 0x38}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {ARCOM2, 0xc0}, + {0x06, 0x88}, + {0x07, 0xc0}, + {COM4, 0x87}, + {0x0e, 0x41}, + {0x42, 0x03}, + {0x4c, 0x00}, + {BANK_SEL, BANK_DSP}, + {RESET, RESET_DVP}, + + //Set the sensor resolution (UXGA, SVGA, CIF) + {HSIZE8, 0x64}, + {VSIZE8, 0x4B}, + {SIZEL, 0x00}, + + //Set the image window size >= output size + {HSIZE, 0xC8}, + {VSIZE, 0x96}, + {XOFFL, 0x00}, + {YOFFL, 0x00}, + {VHYX, 0x00}, + {TEST, 0x00}, + + {CTRL2, CTRL2_DCW_EN | 0x1D}, + {CTRLI, CTRLI_LP_DP | 0x00}, + //{R_DVP_SP, 0x08}, + {0, 0} +}; + +const DRAM_ATTR uint8_t ov2640_settings_to_uxga[][2] = { + {BANK_SEL, BANK_SENSOR}, + {COM7, COM7_RES_UXGA}, + + //Set the sensor output window + {COM1, 0x0F}, + {REG32, REG32_UXGA}, + {HSTART, 0x11}, + {HSTOP, 0x75}, + {VSTART, 0x01}, + {VSTOP, 0x97}, + + //{CLKRC, 0x00}, + {0x3d, 0x34}, + {BD50, 0xbb}, + {BD60, 0x9c}, + {0x5a, 0x57}, + {0x6d, 0x80}, + {0x39, 0x82}, + {0x23, 0x00}, + {0x07, 0xc0}, + {0x4c, 0x00}, + {0x35, 0x88}, + {0x22, 0x0a}, + {0x37, 0x40}, + {ARCOM2, 0xa0}, + {0x06, 0x02}, + {COM4, 0xb7}, + {0x0e, 0x01}, + {0x42, 0x83}, + {BANK_SEL, BANK_DSP}, + {RESET, RESET_DVP}, + + //Set the sensor resolution (UXGA, SVGA, CIF) + {HSIZE8, 0xc8}, + {VSIZE8, 0x96}, + {SIZEL, 0x00}, + + //Set the image window size >= output size + {HSIZE, 0x90}, + {VSIZE, 0x2c}, + {XOFFL, 0x00}, + {YOFFL, 0x00}, + {VHYX, 0x88}, + {TEST, 0x00}, + + {CTRL2, CTRL2_DCW_EN | 0x1d}, + {CTRLI, 0x00}, + //{R_DVP_SP, 0x06}, + {0, 0} +}; + +const DRAM_ATTR uint8_t ov2640_settings_jpeg3[][2] = { + {BANK_SEL, BANK_DSP}, + {RESET, RESET_JPEG | RESET_DVP}, + {IMAGE_MODE, IMAGE_MODE_JPEG_EN | IMAGE_MODE_HREF_VSYNC}, + {0xD7, 0x03}, + {0xE1, 0x77}, + {0xE5, 0x1F}, + {0xD9, 0x10}, + {0xDF, 0x80}, + {0x33, 0x80}, + {0x3C, 0x10}, + {0xEB, 0x30}, + {0xDD, 0x7F}, + {RESET, 0x00}, + {0, 0} +}; + +static const uint8_t ov2640_settings_yuv422[][2] = { + {BANK_SEL, BANK_DSP}, + {RESET, RESET_DVP}, + {IMAGE_MODE, IMAGE_MODE_YUV422}, + {0xD7, 0x01}, + {0xE1, 0x67}, + {RESET, 0x00}, + {0, 0}, +}; + +static const uint8_t ov2640_settings_rgb565[][2] = { + {BANK_SEL, BANK_DSP}, + {RESET, RESET_DVP}, + {IMAGE_MODE, IMAGE_MODE_RGB565}, + {0xD7, 0x03}, + {0xE1, 0x77}, + {RESET, 0x00}, + {0, 0}, +}; + +#define NUM_BRIGHTNESS_LEVELS (5) +static const uint8_t brightness_regs[NUM_BRIGHTNESS_LEVELS + 1][5] = { + {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, + {0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */ + {0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */ + {0x00, 0x04, 0x09, 0x20, 0x00 }, /* 0 */ + {0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */ + {0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */ +}; + +#define NUM_CONTRAST_LEVELS (5) +static const uint8_t contrast_regs[NUM_CONTRAST_LEVELS + 1][7] = { + {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA, BPDATA, BPDATA }, + {0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */ + {0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */ + {0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /* 0 */ + {0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */ + {0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */ +}; + +#define NUM_SATURATION_LEVELS (5) +static const uint8_t saturation_regs[NUM_SATURATION_LEVELS + 1][5] = { + {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, + {0x00, 0x02, 0x03, 0x28, 0x28 }, /* -2 */ + {0x00, 0x02, 0x03, 0x38, 0x38 }, /* -1 */ + {0x00, 0x02, 0x03, 0x48, 0x48 }, /* 0 */ + {0x00, 0x02, 0x03, 0x58, 0x58 }, /* +1 */ + {0x00, 0x02, 0x03, 0x68, 0x68 }, /* +2 */ +}; + +#define NUM_SPECIAL_EFFECTS (7) +static const uint8_t special_effects_regs[NUM_SPECIAL_EFFECTS + 1][5] = { + {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, + {0x00, 0X00, 0x05, 0X80, 0X80 }, /* no effect */ + {0x00, 0X40, 0x05, 0X80, 0X80 }, /* negative */ + {0x00, 0X18, 0x05, 0X80, 0X80 }, /* black and white */ + {0x00, 0X18, 0x05, 0X40, 0XC0 }, /* reddish */ + {0x00, 0X18, 0x05, 0X40, 0X40 }, /* greenish */ + {0x00, 0X18, 0x05, 0XA0, 0X40 }, /* blue */ + {0x00, 0X18, 0x05, 0X40, 0XA6 }, /* retro */ +}; + +#define NUM_WB_MODES (4) +static const uint8_t wb_modes_regs[NUM_WB_MODES + 1][3] = { + {0XCC, 0XCD, 0XCE }, + {0x5E, 0X41, 0x54 }, /* sunny */ + {0x65, 0X41, 0x4F }, /* cloudy */ + {0x52, 0X41, 0x66 }, /* office */ + {0x42, 0X3F, 0x71 }, /* home */ +}; + +#define NUM_AE_LEVELS (5) +static const uint8_t ae_levels_regs[NUM_AE_LEVELS + 1][3] = { + { AEW, AEB, VV }, + {0x20, 0X18, 0x60 }, + {0x34, 0X1C, 0x00 }, + {0x3E, 0X38, 0x81 }, + {0x48, 0X40, 0x81 }, + {0x58, 0X50, 0x92 }, +}; + +const uint8_t agc_gain_tbl[31] = { + 0x00, 0x10, 0x18, 0x30, 0x34, 0x38, 0x3C, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E, 0xF0, + 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF +}; + +#endif /* _OV2640_SETTINGS_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h new file mode 100644 index 0000000000..341d688616 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h @@ -0,0 +1,34 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV3660 driver. + * + */ +#ifndef __OV3660_H__ +#define __OV3660_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov3660_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov3660_init(sensor_t *sensor); + +#endif // __OV3660_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h new file mode 100644 index 0000000000..b5cf30a5b1 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h @@ -0,0 +1,211 @@ +/* + * OV3660 register definitions. + */ +#ifndef __OV3660_REG_REGS_H__ +#define __OV3660_REG_REGS_H__ + +/* system control registers */ +#define SYSTEM_CTROL0 0x3008 // Bit[7]: Software reset + // Bit[6]: Software power down + // Bit[5]: Reserved + // Bit[4]: SRB clock SYNC enable + // Bit[3]: Isolation suspend select + // Bit[2:0]: Not used + +/* output format control registers */ +#define FORMAT_CTRL 0x501F // Format select + // Bit[2:0]: + // 000: YUV422 + // 001: RGB + // 010: Dither + // 011: RAW after DPC + // 101: RAW after CIP + +/* format control registers */ +#define FORMAT_CTRL00 0x4300 + +/* frame control registers */ +#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // Bit[3:0]: Frame ON number +#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // BIT[3:0]: Frame OFF number + +/* ISP top control registers */ +#define PRE_ISP_TEST_SETTING_1 0x503D // Bit[7]: Test enable + // 0: Test disable + // 1: Color bar enable + // Bit[6]: Rolling + // Bit[5]: Transparent + // Bit[4]: Square black and white + // Bit[3:2]: Color bar style + // 00: Standard 8 color bar + // 01: Gradual change at vertical mode 1 + // 10: Gradual change at horizontal + // 11: Gradual change at vertical mode 2 + // Bit[1:0]: Test select + // 00: Color bar + // 01: Random data + // 10: Square data + // 11: Black image + +//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW + +/* AEC/AGC control functions */ +#define AEC_PK_MANUAL 0x3503 // AEC Manual Mode Control + // Bit[7:6]: Reserved + // Bit[5]: Gain delay option + // Valid when 0x3503[4]=1’b0 + // 0: Delay one frame latch + // 1: One frame latch + // Bit[4:2]: Reserved + // Bit[1]: AGC manual + // 0: Auto enable + // 1: Manual enable + // Bit[0]: AEC manual + // 0: Auto enable + // 1: Manual enable + +//gain = {0x350A[1:0], 0x350B[7:0]} / 16 + +/* mirror and flip registers */ +#define TIMING_TC_REG20 0x3820 // Timing Control Register + // Bit[2:1]: Vertical flip enable + // 00: Normal + // 11: Vertical flip + // Bit[0]: Vertical binning enable +#define TIMING_TC_REG21 0x3821 // Timing Control Register + // Bit[5]: Compression Enable + // Bit[2:1]: Horizontal mirror enable + // 00: Normal + // 11: Horizontal mirror + // Bit[0]: Horizontal binning enable + +#define CLOCK_POL_CONTROL 0x4740// Bit[5]: PCLK polarity 0: active low + // 1: active high + // Bit[3]: Gate PCLK under VSYNC + // Bit[2]: Gate PCLK under HREF + // Bit[1]: HREF polarity + // 0: active low + // 1: active high + // Bit[0] VSYNC polarity + // 0: active low + // 1: active high +#define DRIVE_CAPABILITY 0x302c // Bit[7:6]: + // 00: 1x + // 01: 2x + // 10: 3x + // 11: 4x + + +#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] +#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] +#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] +#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] +#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] +#define X_ADDR_END_L 0x3805 //Bit[7:0]: +#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] +#define Y_ADDR_END_L 0x3807 //Bit[7:0]: +// Size after scaling +#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] +#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: +#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] +#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: +#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] +#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: +#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] +#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: +#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] +#define X_OFFSET_L 0x3811 //Bit[7:0]: +#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] +#define Y_OFFSET_L 0x3813 //Bit[7:0]: +#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment + //Bit[3:0]: Horizontal even subsample increment +#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment + //Bit[3:0]: Vertical even subsample increment +// Size before scaling +//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) +//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) + +#define ISP_CONTROL_01 0x5001 // Bit[5]: Scale enable + // 0: Disable + // 1: Enable + +#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + // Bit[2:0]: VDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + +#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits +#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits +#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits +#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits +#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset + +#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual +#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable + // 0: Auto + // 1: Manual by PCLK_RATIO + +#define VFIFO_X_SIZE_H 0x4602 +#define VFIFO_X_SIZE_L 0x4603 +#define VFIFO_Y_SIZE_H 0x4604 +#define VFIFO_Y_SIZE_L 0x4605 + +#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass +#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier +#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control + // Bit[3:0]: PLLS system divider +#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider + // 00: 1 + // 01: 1.5 + // 10: 2 + // 11: 3 + // Bit[2]: PLLS root-divider - 1 + // Bit[1:0]: PLLS seld5 + // 00: 1 + // 01: 1 + // 10: 2 + // 11: 2.5 + +#define COMPRESSION_CTRL00 0x4400 // +#define COMPRESSION_CTRL01 0x4401 // +#define COMPRESSION_CTRL02 0x4402 // +#define COMPRESSION_CTRL03 0x4403 // +#define COMPRESSION_CTRL04 0x4404 // +#define COMPRESSION_CTRL05 0x4405 // +#define COMPRESSION_CTRL06 0x4406 // +#define COMPRESSION_CTRL07 0x4407 // Bit[5:0]: QS +#define COMPRESSION_ISI_CTRL 0x4408 // +#define COMPRESSION_CTRL09 0x4409 // +#define COMPRESSION_CTRL0a 0x440a // +#define COMPRESSION_CTRL0b 0x440b // +#define COMPRESSION_CTRL0c 0x440c // +#define COMPRESSION_CTRL0d 0x440d // +#define COMPRESSION_CTRL0E 0x440e // + +/** + * @brief register value + */ +#define TEST_COLOR_BAR 0xC0 /* Enable Color Bar roling Test */ + +#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ +#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ + +#define TIMING_TC_REG20_VFLIP 0x06 /* Vertical flip enable */ +#define TIMING_TC_REG21_HMIRROR 0x06 /* Horizontal mirror enable */ + +#endif // __OV3660_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h new file mode 100644 index 0000000000..97c4e03b66 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h @@ -0,0 +1,318 @@ +#ifndef _OV3660_SETTINGS_H_ +#define _OV3660_SETTINGS_H_ + +#include +#include +#include "esp_attr.h" +#include "ov3660_regs.h" + +static const ratio_settings_t ratio_table[] = { + // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty + { 2048, 1536, 0, 0, 2079, 1547, 16, 6, 2300, 1564 }, //4x3 + { 1920, 1280, 64, 128, 2015, 1419, 16, 6, 2172, 1436 }, //3x2 + { 2048, 1280, 0, 128, 2079, 1419, 16, 6, 2300, 1436 }, //16x10 + { 1920, 1152, 64, 192, 2015, 1355, 16, 6, 2172, 1372 }, //5x3 + { 1920, 1080, 64, 242, 2015, 1333, 16, 6, 2172, 1322 }, //16x9 + { 2048, 880, 0, 328, 2079, 1219, 16, 6, 2300, 1236 }, //21x9 + { 1920, 1536, 64, 0, 2015, 1547, 16, 6, 2172, 1564 }, //5x4 + { 1536, 1536, 256, 0, 1823, 1547, 16, 6, 2044, 1564 }, //1x1 + { 864, 1536, 592, 0, 1487, 1547, 16, 6, 2044, 1564 } //9x16 +}; + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0x0000 + +static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { + {SYSTEM_CTROL0, 0x82}, // software reset + {REG_DLY, 10}, // delay 10ms + + {0x3103, 0x13}, + {SYSTEM_CTROL0, 0x42}, + {0x3017, 0xff}, + {0x3018, 0xff}, + {DRIVE_CAPABILITY, 0xc3}, + {CLOCK_POL_CONTROL, 0x21}, + + {0x3611, 0x01}, + {0x3612, 0x2d}, + + {0x3032, 0x00}, + {0x3614, 0x80}, + {0x3618, 0x00}, + {0x3619, 0x75}, + {0x3622, 0x80}, + {0x3623, 0x00}, + {0x3624, 0x03}, + {0x3630, 0x52}, + {0x3632, 0x07}, + {0x3633, 0xd2}, + {0x3704, 0x80}, + {0x3708, 0x66}, + {0x3709, 0x12}, + {0x370b, 0x12}, + {0x3717, 0x00}, + {0x371b, 0x60}, + {0x371c, 0x00}, + {0x3901, 0x13}, + + {0x3600, 0x08}, + {0x3620, 0x43}, + {0x3702, 0x20}, + {0x3739, 0x48}, + {0x3730, 0x20}, + {0x370c, 0x0c}, + + {0x3a18, 0x00}, + {0x3a19, 0xf8}, + + {0x3000, 0x10}, + {0x3004, 0xef}, + + {0x6700, 0x05}, + {0x6701, 0x19}, + {0x6702, 0xfd}, + {0x6703, 0xd1}, + {0x6704, 0xff}, + {0x6705, 0xff}, + + {0x3c01, 0x80}, + {0x3c00, 0x04}, + {0x3a08, 0x00}, {0x3a09, 0x62}, //50Hz Band Width Step (10bit) + {0x3a0e, 0x08}, //50Hz Max Bands in One Frame (6 bit) + {0x3a0a, 0x00}, {0x3a0b, 0x52}, //60Hz Band Width Step (10bit) + {0x3a0d, 0x09}, //60Hz Max Bands in One Frame (6 bit) + + {0x3a00, 0x3a},//night mode off + {0x3a14, 0x09}, + {0x3a15, 0x30}, + {0x3a02, 0x09}, + {0x3a03, 0x30}, + + {COMPRESSION_CTRL0E, 0x08}, + {0x4520, 0x0b}, + {0x460b, 0x37}, + {0x4713, 0x02}, + {0x471c, 0xd0}, + {0x5086, 0x00}, + + {0x5002, 0x00}, + {0x501f, 0x00}, + + {SYSTEM_CTROL0, 0x02}, + + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x16}, + {0x5187, 0x16}, + {0x5188, 0x16}, + {0x5189, 0x68}, + {0x518a, 0x60}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x35}, + {0x518f, 0x56}, + {0x5190, 0x56}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, + + {0x5381, 0x1d}, + {0x5382, 0x60}, + {0x5383, 0x03}, + {0x5384, 0x0c}, + {0x5385, 0x78}, + {0x5386, 0x84}, + {0x5387, 0x7d}, + {0x5388, 0x6b}, + {0x5389, 0x12}, + {0x538a, 0x01}, + {0x538b, 0x98}, + + {0x5480, 0x01}, +// {0x5481, 0x05}, +// {0x5482, 0x09}, +// {0x5483, 0x10}, +// {0x5484, 0x3a}, +// {0x5485, 0x4c}, +// {0x5486, 0x5a}, +// {0x5487, 0x68}, +// {0x5488, 0x74}, +// {0x5489, 0x80}, +// {0x548a, 0x8e}, +// {0x548b, 0xa4}, +// {0x548c, 0xb4}, +// {0x548d, 0xc8}, +// {0x548e, 0xde}, +// {0x548f, 0xf0}, +// {0x5490, 0x15}, + + {0x5000, 0xa7}, + {0x5800, 0x0C}, + {0x5801, 0x09}, + {0x5802, 0x0C}, + {0x5803, 0x0C}, + {0x5804, 0x0D}, + {0x5805, 0x17}, + {0x5806, 0x06}, + {0x5807, 0x05}, + {0x5808, 0x04}, + {0x5809, 0x06}, + {0x580a, 0x09}, + {0x580b, 0x0E}, + {0x580c, 0x05}, + {0x580d, 0x01}, + {0x580e, 0x01}, + {0x580f, 0x01}, + {0x5810, 0x05}, + {0x5811, 0x0D}, + {0x5812, 0x05}, + {0x5813, 0x01}, + {0x5814, 0x01}, + {0x5815, 0x01}, + {0x5816, 0x05}, + {0x5817, 0x0D}, + {0x5818, 0x08}, + {0x5819, 0x06}, + {0x581a, 0x05}, + {0x581b, 0x07}, + {0x581c, 0x0B}, + {0x581d, 0x0D}, + {0x581e, 0x12}, + {0x581f, 0x0D}, + {0x5820, 0x0E}, + {0x5821, 0x10}, + {0x5822, 0x10}, + {0x5823, 0x1E}, + {0x5824, 0x53}, + {0x5825, 0x15}, + {0x5826, 0x05}, + {0x5827, 0x14}, + {0x5828, 0x54}, + {0x5829, 0x25}, + {0x582a, 0x33}, + {0x582b, 0x33}, + {0x582c, 0x34}, + {0x582d, 0x16}, + {0x582e, 0x24}, + {0x582f, 0x41}, + {0x5830, 0x50}, + {0x5831, 0x42}, + {0x5832, 0x15}, + {0x5833, 0x25}, + {0x5834, 0x34}, + {0x5835, 0x33}, + {0x5836, 0x24}, + {0x5837, 0x26}, + {0x5838, 0x54}, + {0x5839, 0x25}, + {0x583a, 0x15}, + {0x583b, 0x25}, + {0x583c, 0x53}, + {0x583d, 0xCF}, + + {0x3a0f, 0x30}, + {0x3a10, 0x28}, + {0x3a1b, 0x30}, + {0x3a1e, 0x28}, + {0x3a11, 0x60}, + {0x3a1f, 0x14}, + + {0x5302, 0x28}, + {0x5303, 0x20}, + + {0x5306, 0x1c}, //de-noise offset 1 + {0x5307, 0x28}, //de-noise offset 2 + + {0x4002, 0xc5}, + {0x4003, 0x81}, + {0x4005, 0x12}, + + {0x5688, 0x11}, + {0x5689, 0x11}, + {0x568a, 0x11}, + {0x568b, 0x11}, + {0x568c, 0x11}, + {0x568d, 0x11}, + {0x568e, 0x11}, + {0x568f, 0x11}, + + {0x5580, 0x06}, + {0x5588, 0x00}, + {0x5583, 0x40}, + {0x5584, 0x2c}, + + {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x30}, // YUYV + {0x3002, 0x00},//0x1c to 0x00 !!! + {0x3006, 0xff},//0xc3 to 0xff !!! + {0x471c, 0x50},//0xd0 to 0x50 !!! + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { + {FORMAT_CTRL00, 0x00}, // RAW + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x10}, // Y8 + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x30}, // YUYV + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { + {FORMAT_CTRL, 0x01}, // RGB + {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { + {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 + {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 + {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 + {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 + {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 + {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 + {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 + {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 + {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 +}; + +static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { + {0x06, 0x40, 0x2c, 0x08},//Normal + {0x46, 0x40, 0x28, 0x08},//Negative + {0x1e, 0x80, 0x80, 0x08},//Grayscale + {0x1e, 0x80, 0xc0, 0x08},//Red Tint + {0x1e, 0x60, 0x60, 0x08},//Green Tint + {0x1e, 0xa0, 0x40, 0x08},//Blue Tint + {0x1e, 0x40, 0xa0, 0x08},//Sepia +}; + +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h new file mode 100644 index 0000000000..120ae72054 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h @@ -0,0 +1,27 @@ + +#ifndef __OV5640_H__ +#define __OV5640_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov5640_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov5640_init(sensor_t *sensor); + +#endif // __OV5640_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h new file mode 100644 index 0000000000..c28d80f5bb --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h @@ -0,0 +1,213 @@ +/* + * OV5640 register definitions. + */ +#ifndef __OV5640_REG_REGS_H__ +#define __OV5640_REG_REGS_H__ + +/* system control registers */ +#define SYSTEM_CTROL0 0x3008 // Bit[7]: Software reset + // Bit[6]: Software power down + // Bit[5]: Reserved + // Bit[4]: SRB clock SYNC enable + // Bit[3]: Isolation suspend select + // Bit[2:0]: Not used + +#define DRIVE_CAPABILITY 0x302c // Bit[7:6]: + // 00: 1x + // 01: 2x + // 10: 3x + // 11: 4x + +#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass +#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier +#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control + // Bit[3:0]: PLLS system divider +#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider + // 00: 1 + // 01: 1.5 + // 10: 2 + // 11: 3 + // Bit[2]: PLLS root-divider - 1 + // Bit[1:0]: PLLS seld5 + // 00: 1 + // 01: 1 + // 10: 2 + // 11: 2.5 + +/* AEC/AGC control functions */ +#define AEC_PK_MANUAL 0x3503 // AEC Manual Mode Control + // Bit[7:6]: Reserved + // Bit[5]: Gain delay option + // Valid when 0x3503[4]=1’b0 + // 0: Delay one frame latch + // 1: One frame latch + // Bit[4:2]: Reserved + // Bit[1]: AGC manual + // 0: Auto enable + // 1: Manual enable + // Bit[0]: AEC manual + // 0: Auto enable + // 1: Manual enable + +//gain = {0x350A[1:0], 0x350B[7:0]} / 16 + + +#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] +#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] +#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] +#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] +#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] +#define X_ADDR_END_L 0x3805 //Bit[7:0]: +#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] +#define Y_ADDR_END_L 0x3807 //Bit[7:0]: +// Size after scaling +#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] +#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: +#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] +#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: +#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] +#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: +#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] +#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: +#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] +#define X_OFFSET_L 0x3811 //Bit[7:0]: +#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] +#define Y_OFFSET_L 0x3813 //Bit[7:0]: +#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment + //Bit[3:0]: Horizontal even subsample increment +#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment + //Bit[3:0]: Vertical even subsample increment +// Size before scaling +//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) +//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) + +/* mirror and flip registers */ +#define TIMING_TC_REG20 0x3820 // Timing Control Register + // Bit[2:1]: Vertical flip enable + // 00: Normal + // 11: Vertical flip + // Bit[0]: Vertical binning enable +#define TIMING_TC_REG21 0x3821 // Timing Control Register + // Bit[5]: Compression Enable + // Bit[2:1]: Horizontal mirror enable + // 00: Normal + // 11: Horizontal mirror + // Bit[0]: Horizontal binning enable + +#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual + +/* frame control registers */ +#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // Bit[3:0]: Frame ON number +#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode + // Bit[7:4]: Not used + // BIT[3:0]: Frame OFF number + +/* format control registers */ +#define FORMAT_CTRL00 0x4300 + +#define CLOCK_POL_CONTROL 0x4740// Bit[5]: PCLK polarity 0: active low + // 1: active high + // Bit[3]: Gate PCLK under VSYNC + // Bit[2]: Gate PCLK under HREF + // Bit[1]: HREF polarity + // 0: active low + // 1: active high + // Bit[0] VSYNC polarity + // 0: active low + // 1: active high + +#define ISP_CONTROL_01 0x5001 // Bit[5]: Scale enable + // 0: Disable + // 1: Enable + +/* output format control registers */ +#define FORMAT_CTRL 0x501F // Format select + // Bit[2:0]: + // 000: YUV422 + // 001: RGB + // 010: Dither + // 011: RAW after DPC + // 101: RAW after CIP + +/* ISP top control registers */ +#define PRE_ISP_TEST_SETTING_1 0x503D // Bit[7]: Test enable + // 0: Test disable + // 1: Color bar enable + // Bit[6]: Rolling + // Bit[5]: Transparent + // Bit[4]: Square black and white + // Bit[3:2]: Color bar style + // 00: Standard 8 color bar + // 01: Gradual change at vertical mode 1 + // 10: Gradual change at horizontal + // 11: Gradual change at vertical mode 2 + // Bit[1:0]: Test select + // 00: Color bar + // 01: Random data + // 10: Square data + // 11: Black image + +//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW + +#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + // Bit[2:0]: VDIV RW + // DCW scale times + // 000: DCW 1 time + // 001: DCW 2 times + // 010: DCW 4 times + // 100: DCW 8 times + // 101: DCW 16 times + // Others: DCW 16 times + +#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits +#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits +#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits +#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits +#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset + +#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable + // 0: Auto + // 1: Manual by PCLK_RATIO + +#define VFIFO_X_SIZE_H 0x4602 +#define VFIFO_X_SIZE_L 0x4603 +#define VFIFO_Y_SIZE_H 0x4604 +#define VFIFO_Y_SIZE_L 0x4605 + +#define COMPRESSION_CTRL00 0x4400 // +#define COMPRESSION_CTRL01 0x4401 // +#define COMPRESSION_CTRL02 0x4402 // +#define COMPRESSION_CTRL03 0x4403 // +#define COMPRESSION_CTRL04 0x4404 // +#define COMPRESSION_CTRL05 0x4405 // +#define COMPRESSION_CTRL06 0x4406 // +#define COMPRESSION_CTRL07 0x4407 // Bit[5:0]: QS +#define COMPRESSION_ISI_CTRL 0x4408 // +#define COMPRESSION_CTRL09 0x4409 // +#define COMPRESSION_CTRL0a 0x440a // +#define COMPRESSION_CTRL0b 0x440b // +#define COMPRESSION_CTRL0c 0x440c // +#define COMPRESSION_CTRL0d 0x440d // +#define COMPRESSION_CTRL0E 0x440e // + +/** + * @brief register value + */ +#define TEST_COLOR_BAR 0xC0 /* Enable Color Bar roling Test */ + +#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ +#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ + +#define TIMING_TC_REG20_VFLIP 0x06 /* Vertical flip enable */ +#define TIMING_TC_REG21_HMIRROR 0x06 /* Horizontal mirror enable */ + +#endif // __OV3660_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h new file mode 100644 index 0000000000..f52572fa2b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h @@ -0,0 +1,335 @@ +#ifndef _OV5640_SETTINGS_H_ +#define _OV5640_SETTINGS_H_ + +#include +#include +#include "esp_attr.h" +#include "ov5640_regs.h" + +static const ratio_settings_t ratio_table[] = { + // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty + { 2560, 1920, 0, 0, 2623, 1951, 32, 16, 2844, 1968 }, //4x3 + { 2560, 1704, 0, 110, 2623, 1843, 32, 16, 2844, 1752 }, //3x2 + { 2560, 1600, 0, 160, 2623, 1791, 32, 16, 2844, 1648 }, //16x10 + { 2560, 1536, 0, 192, 2623, 1759, 32, 16, 2844, 1584 }, //5x3 + { 2560, 1440, 0, 240, 2623, 1711, 32, 16, 2844, 1488 }, //16x9 + { 2560, 1080, 0, 420, 2623, 1531, 32, 16, 2844, 1128 }, //21x9 + { 2400, 1920, 80, 0, 2543, 1951, 32, 16, 2684, 1968 }, //5x4 + { 1920, 1920, 320, 0, 2543, 1951, 32, 16, 2684, 1968 }, //1x1 + { 1088, 1920, 736, 0, 1887, 1951, 32, 16, 1884, 1968 } //9x16 +}; + +#define REG_DLY 0xffff +#define REGLIST_TAIL 0x0000 + +static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { + {SYSTEM_CTROL0, 0x82}, // software reset + {REG_DLY, 10}, // delay 10ms + {SYSTEM_CTROL0, 0x42}, // power down + + //enable pll + {0x3103, 0x13}, + + //io direction + {0x3017, 0xff}, + {0x3018, 0xff}, + + {DRIVE_CAPABILITY, 0xc3}, + {CLOCK_POL_CONTROL, 0x21}, + + {0x4713, 0x02},//jpg mode select + + {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE + + //sys reset + {0x3000, 0x20}, // reset MCU + {REG_DLY, 10}, // delay 10ms + {0x3002, 0x1c}, + + //clock enable + {0x3004, 0xff}, + {0x3006, 0xc3}, + + //isp control + {0x5000, 0xa7}, + {ISP_CONTROL_01, 0xa3},//+scaling? + {0x5003, 0x08},//special_effect + + //unknown + {0x370c, 0x02},//!!IMPORTANT + {0x3634, 0x40},//!!IMPORTANT + + //AEC/AGC + {0x3a02, 0x03}, + {0x3a03, 0xd8}, + {0x3a08, 0x01}, + {0x3a09, 0x27}, + {0x3a0a, 0x00}, + {0x3a0b, 0xf6}, + {0x3a0d, 0x04}, + {0x3a0e, 0x03}, + {0x3a0f, 0x30},//ae_level + {0x3a10, 0x28},//ae_level + {0x3a11, 0x60},//ae_level + {0x3a13, 0x43}, + {0x3a14, 0x03}, + {0x3a15, 0xd8}, + {0x3a18, 0x00},//gainceiling + {0x3a19, 0xf8},//gainceiling + {0x3a1b, 0x30},//ae_level + {0x3a1e, 0x26},//ae_level + {0x3a1f, 0x14},//ae_level + + //vcm debug + {0x3600, 0x08}, + {0x3601, 0x33}, + + //50/60Hz + {0x3c01, 0xa4}, + {0x3c04, 0x28}, + {0x3c05, 0x98}, + {0x3c06, 0x00}, + {0x3c07, 0x08}, + {0x3c08, 0x00}, + {0x3c09, 0x1c}, + {0x3c0a, 0x9c}, + {0x3c0b, 0x40}, + + {0x460c, 0x22},//disable jpeg footer + + //BLC + {0x4001, 0x02}, + {0x4004, 0x02}, + + //AWB + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518f, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38}, + + //color matrix (Saturation) + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + + //CIP control (Sharpness) + {0x5300, 0x10},//sharpness + {0x5301, 0x10},//sharpness + {0x5302, 0x18},//sharpness + {0x5303, 0x19},//sharpness + {0x5304, 0x10}, + {0x5305, 0x10}, + {0x5306, 0x08},//denoise + {0x5307, 0x16}, + {0x5308, 0x40}, + {0x5309, 0x10},//sharpness + {0x530a, 0x10},//sharpness + {0x530b, 0x04},//sharpness + {0x530c, 0x06},//sharpness + + //GAMMA + {0x5480, 0x01}, + {0x5481, 0x00}, + {0x5482, 0x1e}, + {0x5483, 0x3b}, + {0x5484, 0x58}, + {0x5485, 0x66}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x83}, + {0x5489, 0x8f}, + {0x548a, 0x98}, + {0x548b, 0xa6}, + {0x548c, 0xb8}, + {0x548d, 0xca}, + {0x548e, 0xd7}, + {0x548f, 0xe3}, + {0x5490, 0x1d}, + + //Special Digital Effects (SDE) (UV adjust) + {0x5580, 0x06},//enable brightness and contrast + {0x5583, 0x40},//special_effect + {0x5584, 0x10},//special_effect + {0x5586, 0x20},//contrast + {0x5587, 0x00},//brightness + {0x5588, 0x00},//brightness + {0x5589, 0x10}, + {0x558a, 0x00}, + {0x558b, 0xf8}, + {0x501d, 0x40},// enable manual offset of contrast + + //power on + {0x3008, 0x02}, + + //50Hz + {0x3c00, 0x04}, + + {REG_DLY, 300}, + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x30}, // YUYV + {0x3002, 0x00},//0x1c to 0x00 !!! + {0x3006, 0xff},//0xc3 to 0xff !!! + {0x471c, 0x50},//0xd0 to 0x50 !!! + {REGLIST_TAIL, 0x00}, // tail +}; + +static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { + {FORMAT_CTRL, 0x03}, // RAW (DPC) + {FORMAT_CTRL00, 0x00}, // RAW + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x10}, // Y8 + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { + {FORMAT_CTRL, 0x00}, // YUV422 + {FORMAT_CTRL00, 0x30}, // YUYV + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { + {FORMAT_CTRL, 0x01}, // RGB + {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) + {REGLIST_TAIL, 0x00} +}; + +static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { + {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 + {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 + {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 + {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 + {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 + {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 + {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 + {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 + {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 +}; + +static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { + {0x06, 0x40, 0x2c, 0x08},//Normal + {0x46, 0x40, 0x28, 0x08},//Negative + {0x1e, 0x80, 0x80, 0x08},//Grayscale + {0x1e, 0x80, 0xc0, 0x08},//Red Tint + {0x1e, 0x60, 0x60, 0x08},//Green Tint + {0x1e, 0xa0, 0x40, 0x08},//Blue Tint + {0x1e, 0x40, 0xa0, 0x08},//Sepia +}; + +static const DRAM_ATTR uint16_t sensor_regs_gamma0[][2] = { + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d} +}; + +static const DRAM_ATTR uint16_t sensor_regs_gamma1[][2] = { + {0x5480, 0x1}, + {0x5481, 0x0}, + {0x5482, 0x1e}, + {0x5483, 0x3b}, + {0x5484, 0x58}, + {0x5485, 0x66}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x83}, + {0x5489, 0x8f}, + {0x548a, 0x98}, + {0x548b, 0xa6}, + {0x548c, 0xb8}, + {0x548d, 0xca}, + {0x548e, 0xd7}, + {0x548f, 0xe3}, + {0x5490, 0x1d} +}; + +static const DRAM_ATTR uint16_t sensor_regs_awb0[][2] = { + {0x5180, 0xff}, + {0x5181, 0xf2}, + {0x5182, 0x00}, + {0x5183, 0x14}, + {0x5184, 0x25}, + {0x5185, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x75}, + {0x518a, 0x54}, + {0x518b, 0xe0}, + {0x518c, 0xb2}, + {0x518d, 0x42}, + {0x518e, 0x3d}, + {0x518f, 0x56}, + {0x5190, 0x46}, + {0x5191, 0xf8}, + {0x5192, 0x04}, + {0x5193, 0x70}, + {0x5194, 0xf0}, + {0x5195, 0xf0}, + {0x5196, 0x03}, + {0x5197, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x12}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x06}, + {0x519d, 0x82}, + {0x519e, 0x38} +}; + +#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h new file mode 100644 index 0000000000..b3a645a70d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h @@ -0,0 +1,33 @@ +/* + * This file is part of the OpenMV project. + * author: Juan Schiavoni + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7670 driver. + * + */ +#ifndef __OV7670_H__ +#define __OV7670_H__ +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov7670_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov7670_init(sensor_t *sensor); + +#endif // __OV7670_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h new file mode 100644 index 0000000000..699354877f --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h @@ -0,0 +1,354 @@ +/* + * This file is for the OpenMV project so the OV7670 can be used + * author: Juan Schiavoni + * + * OV7670 register definitions. + */ +#ifndef __OV7670_REG_REGS_H__ +#define __OV7670_REG_REGS_H__ +#define GAIN 0x00 /* AGC – Gain control gain setting */ +#define BLUE 0x01 /* AWB – Blue channel gain setting */ +#define RED 0x02 /* AWB – Red channel gain setting */ +#define VREF 0x03 /* AWB – Green channel gain setting */ +#define COM1 0x04 /* Common Control 1 */ +#define BAVG 0x05 /* U/B Average Level */ +#define GAVG 0x06 /* Y/Gb Average Level */ +#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */ +#define RAVG 0x08 /* V/R Average Level */ + +#define COM2 0x09 /* Common Control 2 */ +#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ +#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ +#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ +#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ +#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ + +#define REG_PID 0x0A /* Product ID Number MSB */ +#define REG_VER 0x0B /* Product ID Number LSB */ + +#define COM3 0x0C /* Common Control 3 */ +#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */ +#define COM3_TRI_CLK 0x20 /* Tri-state output clock */ +#define COM3_TRI_DATA 0x10 /* Tri-state option output */ +#define COM3_SCALE_EN 0x08 /* Scale enable */ +#define COM3_DCW 0x04 /* DCW enable */ + +#define COM4 0x0D /* Common Control 4 */ +#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ +#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ +#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ +#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ +#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ +#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ +#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ +#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ + +#define COM5 0x0E /* Common Control 5 */ +#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ +#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ +#define COM5_AFR_0 0x00 /* No reduction of frame rate */ +#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ +#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ +#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ +#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ +#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ +#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ +#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ + +#define COM6 0x0F /* Common Control 6 */ +#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ + +#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ +#define CLKRC 0x11 /* Internal Clock */ + +#define COM7 0x12 /* Common Control 7 */ +#define COM7_RESET 0x80 /* SCCB Register Reset */ +#define COM7_RES_VGA 0x00 /* Resolution VGA */ +#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ +#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ +#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ +#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ +#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ +#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ +#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ +#define COM7_FMT_YUV 0x00 /* Output format YUV */ +#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ +#define COM7_FMT_RGB 0x04 /* Output format RGB */ +#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ +#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0)) + +#define COM8 0x13 /* Common Control 8 */ +#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ +#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ +#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ +#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ +#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ +#define COM8_AGC_EN 0x04 /* AGC Enable */ +#define COM8_AWB_EN 0x02 /* AWB Enable */ +#define COM8_AEC_EN 0x01 /* AEC Enable */ +#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) +#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) +#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) + +#define COM9 0x14 /* Common Control 9 */ +#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ +#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ +#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ +#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ +#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ +#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ +#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ +#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ +#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) + +#define COM10 0x15 /* Common Control 10 */ +#define COM10_NEGATIVE 0x80 /* Output negative data */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ +#define COM10_PCLK_REV 0x10 /* PCLK reverse */ +#define COM10_HREF_REV 0x08 /* HREF reverse */ +#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ +#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ +#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ + +#define RSVD_16 0x16 /* Reserved register */ + +#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */ +#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */ +#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */ +#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */ +#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ +#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */ +#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */ + +#define MVFP 0x1E /* Mirror/Vflip Enable */ +#define MVFP_MIRROR 0x20 /* Mirror image */ +#define MVFP_FLIP 0x10 /* Vertical flip */ +#define MVFP_SUN 0x02 /* Black sun enable */ +#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */ +#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */ + +#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */ +#define ADCCTR0 0x20 /* ADC control */ +#define ADCCTR1 0x21 /* reserved */ +#define ADCCTR2 0x22 /* reserved */ +#define ADCCTR3 0x23 /* reserved */ +#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ +#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ +#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ +#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */ +#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */ +#define RSVD_29 0x29 /* reserved */ +#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ +#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ +#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */ +#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ +#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ +#define YAVE 0x2F /* Y/G Channel Average Value */ +#define HSYST 0x30 /* HSync rising edge delay */ +#define HSYEN 0x31 /* HSync falling edge delay */ +#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */ +#define CHLF 0x33 /* Array Current control */ +#define ARBLM 0x34 /* Array reference control */ +#define RSVD_35 0x35 /* Reserved */ +#define RSVD_36 0x36 /* Reserved */ +#define ADC 0x37 /* ADC control */ +#define ACOM 0x38 /* ADC and analog common mode control */ +#define OFON 0x39 /* ADC offset control */ +#define TSLB 0x3A /* Line buffer test option */ + +#define COM11 0x3B /* Common control 11 */ +#define COM11_EXP 0x02 +#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ + +#define COM12 0x3C /* Common control 12 */ + +#define COM13 0x3D /* Common control 13 */ +#define COM13_GAMMA 0x80 /* Gamma enable */ +#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ + +#define COM14 0x3E /* Common Control 14 */ + +#define EDGE 0x3F /* edge enhancement adjustment */ +#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */ +#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */ +#define COM15_RGB565 0x10 /* RGB565 output */ +#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */ + +#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */ +#define COM16_AWBGAIN 0x08 /* AWB gain enable */ +#define COM17 0x42 /* Common Control 17 */ + +#define AWBC1 0x43 /* Reserved */ +#define AWBC2 0x44 /* Reserved */ +#define AWBC3 0x45 /* Reserved */ +#define AWBC4 0x46 /* Reserved */ +#define AWBC5 0x47 /* Reserved */ +#define AWBC6 0x48 /* Reserved */ + +#define RSVD_49 0x49 /* Reserved */ +#define RSVD_4A 0x4A /* Reserved */ + +#define REG4B 0x4B /* Register 4B */ +#define DNSTH 0x4C /* Denoise strength */ + +#define RSVD_4D 0x4D /* Reserved */ +#define RSVD_4E 0x4E /* Reserved */ + +#define MTX1 0x4F /* Matrix coefficient 1 */ +#define MTX2 0x50 /* Matrix coefficient 2 */ +#define MTX3 0x51 /* Matrix coefficient 3 */ +#define MTX4 0x52 /* Matrix coefficient 4 */ +#define MTX5 0x53 /* Matrix coefficient 5 */ +#define MTX6 0x54 /* Matrix coefficient 6 */ +#define BRIGHTNESS 0x55 /* Brightness control */ +#define CONTRAST 0x56 /* Contrast control */ +#define CONTRASCENTER 0x57 /* Contrast center */ +#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/ + +#define RSVD_59 0x59 /* Reserved */ +#define RSVD_5A 0x5A /* Reserved */ +#define RSVD_5B 0x5B /* Reserved */ +#define RSVD_5C 0x5C /* Reserved */ +#define RSVD_5D 0x5D /* Reserved */ +#define RSVD_5E 0x5E /* Reserved */ +#define RSVD_5F 0x5F /* Reserved */ +#define RSVD_60 0x60 /* Reserved */ +#define RSVD_61 0x61 /* Reserved */ + +#define LCC1 0x62 /* Lens correction option 1 */ + +#define LCC2 0x63 /* Lens correction option 2 */ +#define LCC3 0x64 /* Lens correction option 3 */ +#define LCC4 0x65 /* Lens correction option 4 */ +#define LCC5 0x66 /* Lens correction option 5 */ + +#define MANU 0x67 /* Manual U Value */ +#define MANV 0x68 /* Manual V Value */ +#define GFIX 0x69 /* Fix gain control */ +#define GGAIN 0x6A /* G channel AWB gain */ + +#define DBLV 0x6B /* PLL and clock ? */ + +#define AWBCTR3 0x6C /* AWB Control 3 */ +#define AWBCTR2 0x6D /* AWB Control 2 */ +#define AWBCTR1 0x6E /* AWB Control 1 */ +#define AWBCTR0 0x6F /* AWB Control 0 */ +#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */ +#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */ +#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */ +#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */ +#define SCALING_DCWCTR 0x72 /* DCW control */ +#define SCALING_PCLK_DIV 0x73 /* */ +#define REG74 0x74 /* */ +#define REG75 0x75 /* */ +#define REG76 0x76 /* */ +#define REG77 0x77 /* */ + +#define RSVD_78 0x78 /* Reserved */ +#define RSVD_79 0x79 /* Reserved */ + +#define SLOP 0x7A /* Gamma curve highest segment slope */ +#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ +#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ +#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ +#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ +#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ +#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */ +#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ +#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ +#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ +#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ +#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ +#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ +#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ +#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ +#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ + +#define RSVD_8A 0x8A /* Reserved */ +#define RSVD_8B 0x8B /* Reserved */ + +#define RGB444 0x8C /* */ + +#define RSVD_8D 0x8D /* Reserved */ +#define RSVD_8E 0x8E /* Reserved */ +#define RSVD_8F 0x8F /* Reserved */ +#define RSVD_90 0x90 /* Reserved */ +#define RSVD_91 0x91 /* Reserved */ + +#define DM_LNL 0x92 /* Dummy line low 8 bit */ +#define DM_LNH 0x93 /* Dummy line high 8 bit */ +#define LCC6 0x94 /* Lens correction option 6 */ +#define LCC7 0x95 /* Lens correction option 7 */ + +#define RSVD_96 0x96 /* Reserved */ +#define RSVD_97 0x97 /* Reserved */ +#define RSVD_98 0x98 /* Reserved */ +#define RSVD_99 0x99 /* Reserved */ +#define RSVD_9A 0x9A /* Reserved */ +#define RSVD_9B 0x9B /* Reserved */ +#define RSVD_9C 0x9C /* Reserved */ + +#define BD50ST 0x9D /* 50 Hz banding filter value */ +#define BD60ST 0x9E /* 60 Hz banding filter value */ +#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */ +#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */ + +#define RSVD_A1 0xA1 /* Reserved */ + +#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */ + +#define RSVD_A3 0xA3 /* Reserved */ + +#define NT_CNTRL 0xA4 /* */ +#define BD50MAX 0xA5 /* 50 Hz banding step limit */ +#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */ +#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */ +#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */ +#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */ + +#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */ +#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */ + +#define BD60MAX 0xAB /* 60 Hz banding step limit */ + +#define STR_OPT 0xAC /* Register AC */ +#define STR_R 0xAD /* R gain for led output frame */ +#define STR_G 0xAE /* G gain for led output frame */ +#define STR_B 0xAF /* B gain for led output frame */ +#define RSVD_B0 0xB0 /* Reserved */ +#define ABLC1 0xB1 /* */ +#define RSVD_B2 0xB2 /* Reserved */ +#define THL_ST 0xB3 /* ABLC target */ +#define THL_DLT 0xB5 /* ABLC stable range */ + +#define RSVD_B6 0xB6 /* Reserved */ +#define RSVD_B7 0xB7 /* Reserved */ +#define RSVD_B8 0xB8 /* Reserved */ +#define RSVD_B9 0xB9 /* Reserved */ +#define RSVD_BA 0xBA /* Reserved */ +#define RSVD_BB 0xBB /* Reserved */ +#define RSVD_BC 0xBC /* Reserved */ +#define RSVD_BD 0xBD /* Reserved */ + +#define AD_CHB 0xBE /* blue channel black level compensation */ +#define AD_CHR 0xBF /* Red channel black level compensation */ +#define AD_CHGb 0xC0 /* Gb channel black level compensation */ +#define AD_CHGr 0xC1 /* Gr channel black level compensation */ + +#define RSVD_C2 0xC2 /* Reserved */ +#define RSVD_C3 0xC3 /* Reserved */ +#define RSVD_C4 0xC4 /* Reserved */ +#define RSVD_C5 0xC5 /* Reserved */ +#define RSVD_C6 0xC6 /* Reserved */ +#define RSVD_C7 0xC7 /* Reserved */ +#define RSVD_C8 0xC8 /* Reserved */ + +#define SATCTR 0xC9 /* Saturation control */ +#define SET_REG(reg, x) (##reg_DEFAULT|x) + +#endif //__OV7670_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h new file mode 100644 index 0000000000..291b266800 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h @@ -0,0 +1,33 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV7725 driver. + * + */ +#ifndef __OV7725_H__ +#define __OV7725_H__ +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int ov7725_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int ov7725_init(sensor_t *sensor); + +#endif // __OV7725_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h new file mode 100644 index 0000000000..5cb233dc97 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h @@ -0,0 +1,335 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013/2014 Ibrahim Abdelkader + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * OV2640 register definitions. + */ +#ifndef __REG_REGS_H__ +#define __REG_REGS_H__ +#define GAIN 0x00 /* AGC – Gain control gain setting */ +#define BLUE 0x01 /* AWB – Blue channel gain setting */ +#define RED 0x02 /* AWB – Red channel gain setting */ +#define GREEN 0x03 /* AWB – Green channel gain setting */ +#define BAVG 0x05 /* U/B Average Level */ +#define GAVG 0x06 /* Y/Gb Average Level */ +#define RAVG 0x07 /* V/R Average Level */ +#define AECH 0x08 /* Exposure Value – AEC MSBs */ + +#define COM2 0x09 /* Common Control 2 */ +#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ +#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ +#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ +#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ +#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ + +#define REG_PID 0x0A /* Product ID Number MSB */ +#define REG_VER 0x0B /* Product ID Number LSB */ + +#define COM3 0x0C /* Common Control 3 */ +#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */ +#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */ +#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */ +#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */ +#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */ +#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */ +#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */ +#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */ +#define COM3_SET_CBAR(r, x) ((r&0xFE)|((x&1)<<0)) +#define COM3_SET_MIRROR(r, x) ((r&0xBF)|((x&1)<<6)) +#define COM3_SET_FLIP(r, x) ((r&0x7F)|((x&1)<<7)) + +#define COM4 0x0D /* Common Control 4 */ +#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ +#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ +#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ +#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ +#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ +#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ +#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ +#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ + +#define COM5 0x0E /* Common Control 5 */ +#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ +#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ +#define COM5_AFR_0 0x00 /* No reduction of frame rate */ +#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ +#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ +#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ +#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ +#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ +#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ +#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ + +#define COM6 0x0F /* Common Control 6 */ +#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ + +#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ +#define CLKRC 0x11 /* Internal Clock */ + +#define COM7 0x12 /* Common Control 7 */ +#define COM7_RESET 0x80 /* SCCB Register Reset */ +#define COM7_RES_VGA 0x00 /* Resolution VGA */ +#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ +#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ +#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ +#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ +#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ +#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ +#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ +#define COM7_FMT_YUV 0x00 /* Output format YUV */ +#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ +#define COM7_FMT_RGB 0x02 /* Output format RGB */ +#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ +#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x3)<<0)) +#define COM7_SET_RGB(r, x) ((r&0xF0)|(x&0x0C)|COM7_FMT_RGB) + +#define COM8 0x13 /* Common Control 8 */ +#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ +#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ +#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ +#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ +#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ +#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ +#define COM8_AGC_EN 0x04 /* AGC Enable */ +#define COM8_AWB_EN 0x02 /* AWB Enable */ +#define COM8_AEC_EN 0x01 /* AEC Enable */ +#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) +#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) +#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) + +#define COM9 0x14 /* Common Control 9 */ +#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ +#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ +#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ +#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ +#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ +#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ +#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ +#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ +#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) + +#define COM10 0x15 /* Common Control 10 */ +#define COM10_NEGATIVE 0x80 /* Output negative data */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ +#define COM10_PCLK_REV 0x10 /* PCLK reverse */ +#define COM10_HREF_REV 0x08 /* HREF reverse */ +#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ +#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ +#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ + +#define REG16 0x16 /* Register 16 */ +#define REG16_BIT_SHIFT 0x80 /* Bit shift test pattern options */ +#define HSTART 0x17 /* Horizontal Frame (HREF column) Start 8 MSBs (2 LSBs are at HREF[5:4]) */ +#define HSIZE 0x18 /* Horizontal Sensor Size (2 LSBs are at HREF[1:0]) */ +#define VSTART 0x19 /* Vertical Frame (row) Start 8 MSBs (1 LSB is at HREF[6]) */ +#define VSIZE 0x1A /* Vertical Sensor Size (1 LSB is at HREF[2]) */ +#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ +#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */ +#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */ +#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period */ + +#define COM11 0x20 /* Common Control 11 */ +#define COM11_SNGL_FRAME_EN 0x02 /* Single frame ON/OFF selection */ +#define COM11_SNGL_XFR_TRIG 0x01 /* Single frame transfer trigger */ + +#define BDBASE 0x22 /* Banding Filter Minimum AEC Value */ +#define DBSTEP 0x23 /* Banding Filter Maximum Step */ +#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ +#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ +#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ +#define REG28 0x28 /* Selection on the number of dummy rows, N */ +#define HOUTSIZE 0x29 /* Horizontal Data Output Size MSBs (2 LSBs at register EXHCH[1:0]) */ +#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ +#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ +#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */ +#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ +#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ +#define YAVE 0x2F /* Y/G Channel Average Value */ +#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance High Level Threshold */ +#define LUMLTH 0x31 /* Histogram AEC/AGC Luminance Low Level Threshold */ +#define HREF 0x32 /* Image Start and Size Control */ +#define DM_LNL 0x33 /* Dummy Row Low 8 Bits */ +#define DM_LNH 0x34 /* Dummy Row High 8 Bits */ +#define ADOFF_B 0x35 /* AD Offset Compensation Value for B Channel */ +#define ADOFF_R 0x36 /* AD Offset Compensation Value for R Channel */ +#define ADOFF_GB 0x37 /* AD Offset Compensation Value for GB Channel */ +#define ADOFF_GR 0x38 /* AD Offset Compensation Value for GR Channel */ +#define OFF_B 0x39 /* AD Offset Compensation Value for B Channel */ +#define OFF_R 0x3A /* AD Offset Compensation Value for R Channel */ +#define OFF_GB 0x3B /* AD Offset Compensation Value for GB Channel */ +#define OFF_GR 0x3C /* AD Offset Compensation Value for GR Channel */ +#define COM12 0x3D /* DC offset compensation for analog process */ + +#define COM13 0x3E /* Common Control 13 */ +#define COM13_BLC_EN 0x80 /* BLC enable */ +#define COM13_ADC_EN 0x40 /* ADC channel BLC ON/OFF control */ +#define COM13_ANALOG_BLC 0x20 /* Analog processing channel BLC ON/OFF control */ +#define COM13_ABLC_GAIN_EN 0x04 /* ABLC gain trigger enable */ + +#define COM14 0x3F /* Common Control 14 */ +#define COM15 0x40 /* Common Control 15 */ +#define COM16 0x41 /* Common Control 16 */ +#define TGT_B 0x42 /* BLC Blue Channel Target Value */ +#define TGT_R 0x43 /* BLC Red Channel Target Value */ +#define TGT_GB 0x44 /* BLC Gb Channel Target Value */ +#define TGT_GR 0x45 /* BLC Gr Channel Target Value */ + +#define LC_CTR 0x46 /* Lens Correction Control */ +#define LC_CTR_RGB_COMP_1 0x00 /* R, G, and B channel compensation coefficient is set by LC_COEF (0x49) */ +#define LC_CTR_RGB_COMP_3 0x04 /* R, G, and B channel compensation coefficient is set by registers + LC_COEFB (0x4B), LC_COEF (0x49), and LC_COEFR (0x4C), respectively */ +#define LC_CTR_EN 0x01 /* Lens correction enable */ +#define LC_XC 0x47 /* X Coordinate of Lens Correction Center Relative to Array Center */ +#define LC_YC 0x48 /* Y Coordinate of Lens Correction Center Relative to Array Center */ +#define LC_COEF 0x49 /* Lens Correction Coefficient */ +#define LC_RADI 0x4A /* Lens Correction Radius */ +#define LC_COEFB 0x4B /* Lens Correction B Channel Compensation Coefficient */ +#define LC_COEFR 0x4C /* Lens Correction R Channel Compensation Coefficient */ + +#define FIXGAIN 0x4D /* Analog Fix Gain Amplifier */ +#define AREF0 0x4E /* Sensor Reference Control */ +#define AREF1 0x4F /* Sensor Reference Current Control */ +#define AREF2 0x50 /* Analog Reference Control */ +#define AREF3 0x51 /* ADC Reference Control */ +#define AREF4 0x52 /* ADC Reference Control */ +#define AREF5 0x53 /* ADC Reference Control */ +#define AREF6 0x54 /* Analog Reference Control */ +#define AREF7 0x55 /* Analog Reference Control */ +#define UFIX 0x60 /* U Channel Fixed Value Output */ +#define VFIX 0x61 /* V Channel Fixed Value Output */ +#define AWBB_BLK 0x62 /* AWB Option for Advanced AWB */ + +#define AWB_CTRL0 0x63 /* AWB Control Byte 0 */ +#define AWB_CTRL0_GAIN_EN 0x80 /* AWB gain enable */ +#define AWB_CTRL0_CALC_EN 0x40 /* AWB calculate enable */ +#define AWB_CTRL0_WBC_MASK 0x0F /* WBC threshold 2 */ + +#define DSP_CTRL1 0x64 /* DSP Control Byte 1 */ +#define DSP_CTRL1_FIFO_EN 0x80 /* FIFO enable/disable selection */ +#define DSP_CTRL1_UV_EN 0x40 /* UV adjust function ON/OFF selection */ +#define DSP_CTRL1_SDE_EN 0x20 /* SDE enable */ +#define DSP_CTRL1_MTRX_EN 0x10 /* Color matrix ON/OFF selection */ +#define DSP_CTRL1_INTRP_EN 0x08 /* Interpolation ON/OFF selection */ +#define DSP_CTRL1_GAMMA_EN 0x04 /* Gamma function ON/OFF selection */ +#define DSP_CTRL1_BLACK_EN 0x02 /* Black defect auto correction ON/OFF */ +#define DSP_CTRL1_WHITE_EN 0x01 /* White defect auto correction ON/OFF */ + +#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */ +#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */ +#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */ +#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */ +#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */ + +#define DSP_CTRL3 0x66 /* DSP Control Byte 3 */ +#define DSP_CTRL3_UV_EN 0x80 /* UV output sequence option */ +#define DSP_CTRL3_CBAR_EN 0x20 /* DSP color bar ON/OFF selection */ +#define DSP_CTRL3_FIFO_EN 0x08 /* FIFO power down ON/OFF selection */ +#define DSP_CTRL3_SCAL1_PWDN 0x04 /* Scaling module power down control 1 */ +#define DSP_CTRL3_SCAL2_PWDN 0x02 /* Scaling module power down control 2 */ +#define DSP_CTRL3_INTRP_PWDN 0x01 /* Interpolation module power down control */ +#define DSP_CTRL3_SET_CBAR(r, x) ((r&0xDF)|((x&1)<<5)) + + +#define DSP_CTRL4 0x67 /* DSP Control Byte 4 */ +#define DSP_CTRL4_YUV_RGB 0x00 /* Output selection YUV or RGB */ +#define DSP_CTRL4_RAW8 0x02 /* Output selection RAW8 */ +#define DSP_CTRL4_RAW10 0x03 /* Output selection RAW10 */ + + +#define AWB_BIAS 0x68 /* AWB BLC Level Clip */ +#define AWB_CTRL1 0x69 /* AWB Control 1 */ +#define AWB_CTRL2 0x6A /* AWB Control 2 */ + +#define AWB_CTRL3 0x6B /* AWB Control 3 */ +#define AWB_CTRL3_ADVANCED 0x80 /* AWB mode select - Advanced AWB */ +#define AWB_CTRL3_SIMPLE 0x00 /* AWB mode select - Simple AWB */ + +#define AWB_CTRL4 0x6C /* AWB Control 4 */ +#define AWB_CTRL5 0x6D /* AWB Control 5 */ +#define AWB_CTRL6 0x6E /* AWB Control 6 */ +#define AWB_CTRL7 0x6F /* AWB Control 7 */ +#define AWB_CTRL8 0x70 /* AWB Control 8 */ +#define AWB_CTRL9 0x71 /* AWB Control 9 */ +#define AWB_CTRL10 0x72 /* AWB Control 10 */ +#define AWB_CTRL11 0x73 /* AWB Control 11 */ +#define AWB_CTRL12 0x74 /* AWB Control 12 */ +#define AWB_CTRL13 0x75 /* AWB Control 13 */ +#define AWB_CTRL14 0x76 /* AWB Control 14 */ +#define AWB_CTRL15 0x77 /* AWB Control 15 */ +#define AWB_CTRL16 0x78 /* AWB Control 16 */ +#define AWB_CTRL17 0x79 /* AWB Control 17 */ +#define AWB_CTRL18 0x7A /* AWB Control 18 */ +#define AWB_CTRL19 0x7B /* AWB Control 19 */ +#define AWB_CTRL20 0x7C /* AWB Control 20 */ +#define AWB_CTRL21 0x7D /* AWB Control 21 */ +#define GAM1 0x7E /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ +#define GAM2 0x7F /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ +#define GAM3 0x80 /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ +#define GAM4 0x81 /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ +#define GAM5 0x82 /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ +#define GAM6 0x83 /* Gamma Curve 6th Segment Input End Point 0x30 Output Value */ +#define GAM7 0x84 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ +#define GAM8 0x85 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ +#define GAM9 0x86 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ +#define GAM10 0x87 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ +#define GAM11 0x88 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ +#define GAM12 0x89 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ +#define GAM13 0x8A /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ +#define GAM14 0x8B /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ +#define GAM15 0x8C /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ +#define SLOP 0x8D /* Gamma Curve Highest Segment Slope */ +#define DNSTH 0x8E /* De-noise Threshold */ +#define EDGE0 0x8F /* Edge Enhancement Strength Control */ +#define EDGE1 0x90 /* Edge Enhancement Threshold Control */ +#define DNSOFF 0x91 /* Auto De-noise Threshold Control */ +#define EDGE2 0x92 /* Edge Enhancement Strength Upper Limit */ +#define EDGE3 0x93 /* Edge Enhancement Strength Upper Limit */ +#define MTX1 0x94 /* Matrix Coefficient 1 */ +#define MTX2 0x95 /* Matrix Coefficient 2 */ +#define MTX3 0x96 /* Matrix Coefficient 3 */ +#define MTX4 0x97 /* Matrix Coefficient 4 */ +#define MTX5 0x98 /* Matrix Coefficient 5 */ +#define MTX6 0x99 /* Matrix Coefficient 6 */ + +#define MTX_CTRL 0x9A /* Matrix Control */ +#define MTX_CTRL_DBL_EN 0x80 /* Matrix double ON/OFF selection */ + +#define BRIGHTNESS 0x9B /* Brightness Control */ +#define CONTRAST 0x9C /* Contrast Gain */ +#define UVADJ0 0x9E /* Auto UV Adjust Control 0 */ +#define UVADJ1 0x9F /* Auto UV Adjust Control 1 */ +#define SCAL0 0xA0 /* DCW Ratio Control */ +#define SCAL1 0xA1 /* Horizontal Zoom Out Control */ +#define SCAL2 0xA2 /* Vertical Zoom Out Control */ +#define FIFODLYM 0xA3 /* FIFO Manual Mode Delay Control */ +#define FIFODLYA 0xA4 /* FIFO Auto Mode Delay Control */ + +#define SDE 0xA6 /* Special Digital Effect Control */ +#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */ +#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */ +#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */ +#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */ +#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */ +#define SDE_SATURATION_EN 0x02 /* Saturation enable */ +#define SDE_HUE_EN 0x01 /* Hue enable */ + +#define USAT 0xA7 /* U Component Saturation Gain */ +#define VSAT 0xA8 /* V Component Saturation Gain */ +#define HUECOS 0xA9 /* Cosine value × 0x80 */ +#define HUESIN 0xAA /* Sine value × 0x80 */ +#define SIGN_BIT 0xAB /* Sign Bit for Hue and Brightness */ + +#define DSPAUTO 0xAC /* DSP Auto Function ON/OFF Control */ +#define DSPAUTO_AWB_EN 0x80 /* AWB auto threshold control */ +#define DSPAUTO_DENOISE_EN 0x40 /* De-noise auto threshold control */ +#define DSPAUTO_EDGE_EN 0x20 /* Sharpness (edge enhancement) auto strength control */ +#define DSPAUTO_UV_EN 0x10 /* UV adjust auto slope control */ +#define DSPAUTO_SCAL0_EN 0x08 /* Auto scaling factor control (register SCAL0 (0xA0)) */ +#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2))*/ +#define SET_REG(reg, x) (##reg_DEFAULT|x) +#endif //__REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h new file mode 100644 index 0000000000..19298b76c2 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h @@ -0,0 +1,31 @@ +/* + * + * SC030IOT DVP driver. + * + */ +#ifndef __SC030IOT_H__ +#define __SC030IOT_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int sc030iot_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int sc030iot_init(sensor_t *sensor); + +#endif // __SC030IOT_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h new file mode 100644 index 0000000000..56f5654c8a --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h @@ -0,0 +1,491 @@ +//version: V01P00_20220303 +//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 +//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI +//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P +//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data +//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data +//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR +//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M +//pin :BIT0 pwdn// BIT1:reset +//avdd 0:3.3V// 1:2.5V// 2:1.8V +//dovdd 0:2.8V// 1:2.5V// 2:1.8V +//dvdd 0:1.8V// 1:1.5V// 2:1.2V + +/* +[DataBase] +DBName=Dothinkey + +[Vendor] +VendorName=SmartSens + +[Sensor] +SensorName=SC031IOT +width=640 +height=480 +port=1 +type=2 +pin=3 +SlaveID=0xd0 +mode=0 +FlagReg=0xf7 +FlagMask=0xff +FlagData=0xfa +FlagReg1=0xf8 +FlagMask1=0xff +FlagData1=0x46 +outformat=0 +mclk=20 +avdd=2.80000 +dovdd=2.800000 +dvdd=1.5 + +Ext0=0 +Ext1=0 +Ext2=0 +AFVCC=0.0000 +VPP=0.000000 +*/ +#include + +static const uint8_t sc030iot_default_init_regs[][2] = { + {0xf0, 0x30}, + {0x01, 0xff}, + {0x02, 0xff}, + {0x22, 0x07}, + {0x19, 0xff}, + {0x3f, 0x82}, + {0x30, 0x02}, + {0xf0, 0x01}, + {0x70, 0x00}, + {0x71, 0x80}, + {0x72, 0x20}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x75, 0x10}, + {0x76, 0x81}, + {0x77, 0x88}, + {0x78, 0xe1}, + {0x79, 0x01}, + {0xf5, 0x01}, + {0xf4, 0x0a}, + {0xf0, 0x36}, + {0x37, 0x79}, + {0x31, 0x82}, + {0x3e, 0x60}, + {0x30, 0xf0}, + {0x33, 0x33}, + {0xf0, 0x32}, + {0x48, 0x02}, + {0xf0, 0x33}, + {0x02, 0x12}, + {0x7c, 0x02}, + {0x7d, 0x0e}, + {0xa2, 0x04}, + {0x5e, 0x06}, + {0x5f, 0x0a}, + {0x0b, 0x58}, + {0x06, 0x38}, + {0xf0, 0x32}, + {0x48, 0x02}, + {0xf0, 0x39}, + {0x02, 0x70}, + {0xf0, 0x45}, + {0x09, 0x1c}, + {0xf0, 0x37}, + {0x22, 0x0d}, + {0xf0, 0x33}, + {0x33, 0x10}, + {0xb1, 0x80}, + {0x34, 0x40}, + {0x0b, 0x54}, + {0xb2, 0x78}, + {0xf0, 0x36}, + {0x11, 0x80}, + {0xf0, 0x30}, + {0x38, 0x44}, + {0xf0, 0x33}, + {0xb3, 0x51}, + {0x01, 0x10}, + {0x0b, 0x6c}, + {0x06, 0x24}, + {0xf0, 0x36}, + {0x31, 0x82}, + {0x3e, 0x60}, + {0x30, 0xf0}, + {0x33, 0x33}, + {0xf0, 0x34}, + {0x9f, 0x02}, + {0xa6, 0x40}, + {0xa7, 0x47}, + {0xe8, 0x5f}, + {0xa8, 0x51}, + {0xa9, 0x44}, + {0xe9, 0x36}, + {0xf0, 0x33}, + {0xb3, 0x51}, + {0x64, 0x17}, + {0x90, 0x01}, + {0x91, 0x03}, + {0x92, 0x07}, + {0x01, 0x10}, + {0x93, 0x10}, + {0x94, 0x10}, + {0x95, 0x10}, + {0x96, 0x01}, + {0x97, 0x07}, + {0x98, 0x1f}, + {0x99, 0x10}, + {0x9a, 0x20}, + {0x9b, 0x28}, + {0x9c, 0x28}, + {0xf0, 0x36}, + {0x70, 0x54}, + {0xb6, 0x40}, + {0xb7, 0x41}, + {0xb8, 0x43}, + {0xb9, 0x47}, + {0xba, 0x4f}, + {0xb0, 0x8b}, + {0xb1, 0x8b}, + {0xb2, 0x8b}, + {0xb3, 0x9b}, + {0xb4, 0xb8}, + {0xb5, 0xf0}, + {0x7e, 0x41}, + {0x7f, 0x47}, + {0x77, 0x80}, + {0x78, 0x84}, + {0x79, 0x8a}, + {0xa0, 0x47}, + {0xa1, 0x5f}, + {0x96, 0x43}, + {0x97, 0x44}, + {0x98, 0x54}, + {0xf0, 0x00}, + {0xf0, 0x01}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x70, 0x00}, + {0x71, 0x80}, + {0xf0, 0x36}, + {0x37, 0x74}, + {0xf0, 0x3f}, + {0x03, 0xa1}, + {0xf0, 0x36},//cvbs_off + {0x11, 0x80}, + {0xf0, 0x01}, + {0x79, 0xc1}, + {0xf0, 0x37}, + {0x24, 0x21}, + {0xf0, 0x36}, + {0x41, 0x00}, + {0xea, 0x09}, + {0xeb, 0x03}, + {0xec, 0x19}, + {0xed, 0x38}, + {0xe9, 0x30}, + {0xf0, 0x33}, + {0x33, 0x00}, + {0x34, 0x00}, + {0xb1, 0x00}, + {0xf0, 0x00}, + {0xe0, 0x04}, + {0xf0, 0x01}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x70, 0x00}, + {0x71, 0x80}, + {0xf0, 0x36}, + {0x32, 0x44}, + {0xf0, 0x36}, + {0x3e, 0xe0}, + {0x70, 0x56}, + {0x7c, 0x43}, + {0x7d, 0x47}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0xa0, 0x47}, + {0xa1, 0x5f}, + {0x96, 0x22}, + {0x97, 0x22}, + {0x98, 0x22}, + {0xf0, 0x00}, + {0x72, 0x38}, + {0x7a, 0x80}, + {0x85, 0x18}, + {0x9b, 0x35}, + {0x9e, 0x20}, + {0xd0, 0x66}, + {0xd1, 0x34}, + {0Xd3, 0x44}, + {0xd6, 0x44}, + {0xb0, 0x41}, + {0xb2, 0x48}, + {0xb3, 0xf4}, + {0xb4, 0x0b}, + {0xb5, 0x78}, + {0xba, 0xff}, + {0xbb, 0xc0}, + {0xbc, 0x90}, + {0xbd, 0x3a}, + {0xc1, 0x67}, + {0xf0, 0x01}, + {0x20, 0x11}, + {0x23, 0x90}, + {0x24, 0x15}, + {0x25, 0x87}, + {0xbc, 0x9f}, + {0xbd, 0x3a}, + {0x48, 0xe6}, + {0x49, 0xc0}, + {0x4a, 0xd0}, + {0x4b, 0x48}, + + // [cvbs_on] + {0xf0, 0x36}, + {0x11, 0x00}, + {0xf0, 0x01}, + {0x79, 0xf1}, + + // [cvbs_off] + {0xf0, 0x36}, + {0x11, 0x80}, + {0xf0, 0x01}, + {0x79, 0xc1}, +}; + +/* +[Sensor] +SensorName=SC031IOT +width=640 +height=480 +port=1 +type=2 +pin=3 +SlaveID=0xd0 +mode=0 +FlagReg=0xf7 +FlagMask=0xff +FlagData=0xfa +FlagReg1=0xf8 +FlagMask1=0xff +FlagData1=0x46 +outformat=0 +mclk=27 +avdd=2.80000 +dovdd=2.800000 +dvdd=1.5 + +Ext0=0 +Ext1=0 +Ext2=0 +AFVCC=0.0000 +VPP=0.000000 +*/ +/* 27M MCLK, 30fps +static const uint8_t sc030iot_default_init_regs[][2] = { + {0xf0, 0x30}, + {0x01, 0xff}, + {0x02, 0xff}, + {0x22, 0x07}, + {0x19, 0xff}, + {0x3f, 0x82}, + {0x30, 0x02}, + {0xf0, 0x01}, + {0x70, 0x00}, + {0x71, 0x80}, + {0x72, 0x20}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x75, 0x10}, + {0x76, 0x81}, + {0x77, 0x88}, + {0x78, 0xe1}, + {0x79, 0x01}, + {0xf5, 0x01}, + {0xf4, 0x0a}, + {0xf0, 0x36}, + {0x37, 0x79}, + {0x31, 0x82}, + {0x3e, 0x60}, + {0x30, 0xf0}, + {0x33, 0x33}, + {0xf0, 0x32}, + {0x48, 0x02}, + {0xf0, 0x33}, + {0x02, 0x12}, + {0x7c, 0x02}, + {0x7d, 0x0e}, + {0xa2, 0x04}, + {0x5e, 0x06}, + {0x5f, 0x0a}, + {0x0b, 0x58}, + {0x06, 0x38}, + {0xf0, 0x32}, + {0x48, 0x02}, + {0xf0, 0x39}, + {0x02, 0x70}, + {0xf0, 0x45}, + {0x09, 0x1c}, + {0xf0, 0x37}, + {0x22, 0x0d}, + {0xf0, 0x33}, + {0x33, 0x10}, + {0xb1, 0x80}, + {0x34, 0x40}, + {0x0b, 0x54}, + {0xb2, 0x78}, + {0xf0, 0x36}, + {0x11, 0x80}, + {0xf0, 0x30}, + {0x38, 0x44}, + {0xf0, 0x33}, + {0xb3, 0x51}, + {0x01, 0x10}, + {0x0b, 0x6c}, + {0x06, 0x24}, + {0xf0, 0x36}, + {0x31, 0x82}, + {0x3e, 0x60}, + {0x30, 0xf0}, + {0x33, 0x33}, + {0xf0, 0x34}, + {0x9f, 0x02}, + {0xa6, 0x40}, + {0xa7, 0x47}, + {0xe8, 0x5f}, + {0xa8, 0x51}, + {0xa9, 0x44}, + {0xe9, 0x36}, + {0xf0, 0x33}, + {0xb3, 0x51}, + {0x64, 0x17}, + {0x90, 0x01}, + {0x91, 0x03}, + {0x92, 0x07}, + {0x01, 0x10}, + {0x93, 0x10}, + {0x94, 0x10}, + {0x95, 0x10}, + {0x96, 0x01}, + {0x97, 0x07}, + {0x98, 0x1f}, + {0x99, 0x10}, + {0x9a, 0x20}, + {0x9b, 0x28}, + {0x9c, 0x28}, + {0xf0, 0x36}, + {0x70, 0x54}, + {0xb6, 0x40}, + {0xb7, 0x41}, + {0xb8, 0x43}, + {0xb9, 0x47}, + {0xba, 0x4f}, + {0xb0, 0x8b}, + {0xb1, 0x8b}, + {0xb2, 0x8b}, + {0xb3, 0x9b}, + {0xb4, 0xb8}, + {0xb5, 0xf0}, + {0x7e, 0x41}, + {0x7f, 0x47}, + {0x77, 0x80}, + {0x78, 0x84}, + {0x79, 0x8a}, + {0xa0, 0x47}, + {0xa1, 0x5f}, + {0x96, 0x43}, + {0x97, 0x44}, + {0x98, 0x54}, + {0xf0, 0x00}, + {0xf0, 0x01}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x70, 0x00}, + {0x71, 0x80}, + {0xf0, 0x36}, + {0x37, 0x74}, + {0xf0, 0x3f}, + {0x03, 0x93}, + {0xf0, 0x36},//cvbs_off + {0x11, 0x80}, + {0xf0, 0x01}, + {0x79, 0xc1}, + {0xf0, 0x37}, + {0x24, 0x21}, + {0xf0, 0x36}, + {0x41, 0x00}, + {0xe9, 0x2c}, + {0xf0, 0x33}, + {0x33, 0x00}, + {0x34, 0x00}, + {0xb1, 0x00}, + {0xf0, 0x00}, + {0xe0, 0x04}, + {0xf0, 0x01}, + {0x73, 0x00}, + {0x74, 0xe0}, + {0x70, 0x00}, + {0x71, 0x80}, + {0xf0, 0x36}, + {0x32, 0x44}, + {0xf0, 0x36}, + {0x3e, 0xe0}, + {0x70, 0x56}, + {0x7c, 0x43}, + {0x7d, 0x47}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0xa0, 0x47}, + {0xa1, 0x5f}, + {0x96, 0x22}, + {0x97, 0x22}, + {0x98, 0x22}, + {0xf0, 0x00}, + {0x72, 0x38}, + {0x7a, 0x80}, + {0x85, 0x18}, + {0x9b, 0x35}, + {0x9e, 0x20}, + {0xd0, 0x66}, + {0xd1, 0x34}, + {0Xd3, 0x44}, + {0xd6, 0x44}, + {0xb0, 0x41}, + {0xb2, 0x48}, + {0xb3, 0xf4}, + {0xb4, 0x0b}, + {0xb5, 0x78}, + {0xba, 0xff}, + {0xbb, 0xc0}, + {0xbc, 0x90}, + {0xbd, 0x3a}, + {0xc1, 0x67}, + {0xf0, 0x01}, + {0x20, 0x11}, + {0x23, 0x90}, + {0x24, 0x15}, + {0x25, 0x87}, + {0xbc, 0x9f}, + {0xbd, 0x3a}, + {0x48, 0xe6}, + {0x49, 0xc0}, + {0x4a, 0xd0}, + {0x4b, 0x48}, + + // [cvbs_on] + {0xf0, 0x36}, + {0x11, 0x00}, + {0xf0, 0x01}, + {0x79, 0xf1}, + + // [cvbs_off] + {0xf0, 0x36}, + {0x11, 0x80}, + {0xf0, 0x01}, + {0x79, 0xc1}, +}; + +*/ \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h new file mode 100644 index 0000000000..bf3cdecef8 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h @@ -0,0 +1,31 @@ +/* + * + * SC031GS DVP driver. + * + */ +#ifndef __SC031GS_H__ +#define __SC030GS_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int sc031gs_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int sc031gs_init(sensor_t *sensor); + +#endif // __SC031GS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h new file mode 100644 index 0000000000..255c1b28a6 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h @@ -0,0 +1,202 @@ +// Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 +//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI +//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P +//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data +//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data +//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR +//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M +//pin :BIT0 pwdn// BIT1:reset +//avdd 0:2.8V// 1:2.5V// 2:1.8V +//dovdd 0:2.8V// 1:2.5V// 2:1.8V +//dvdd 0:1.8V// 1:1.5V// 2:1.2V + +/* +[database] +DBName=Dothinkey + +[vendor] +VendorName=SmartSens + +[sensor] +SensorName=SC031GS +width=200 +height=200 +port=1 +type=1 +pin=2 +SlaveID=0x60 +mode=3 +FlagReg=0x36FF +FlagMask=0xff +FlagData=0x00 +FlagReg1=0x36FF +FlagMask1=0xff +FlagData1=0x00 +outformat=3 +mclk=10 +avdd=2.800000 +dovdd=2.800000 +dvdd=1.500000 + +Ext0=0 +Ext1=0 +Ext2=0 +AFVCC=2.513000 +VPP=0.000000 +*/ +#include + +#define SC031GS_OUTPUT_WINDOW_START_X_H_REG 0x3212 +#define SC031GS_OUTPUT_WINDOW_START_X_L_REG 0x3213 +#define SC031GS_OUTPUT_WINDOW_START_Y_H_REG 0x3210 +#define SC031GS_OUTPUT_WINDOW_START_Y_L_REG 0x3211 +#define SC031GS_OUTPUT_WINDOW_WIDTH_H_REG 0x3208 +#define SC031GS_OUTPUT_WINDOW_WIDTH_L_REG 0x3209 +#define SC031GS_OUTPUT_WINDOW_HIGH_H_REG 0x320a +#define SC031GS_OUTPUT_WINDOW_HIGH_L_REG 0x320b +#define SC031GS_LED_STROBE_ENABLE_REG 0x3361 // When the camera is in exposure, this PAD LEDSTROBE will be high to drive the external LED. + +#define REG_NULL 0xFFFF +#define REG_DELAY 0X0000 + +struct sc031gs_regval { + uint16_t addr; + uint8_t val; +}; + +// 200*200, xclk=10M, fps=120fps +static const struct sc031gs_regval sc031gs_default_init_regs[] = { + {0x0103, 0x01}, // soft reset. + {REG_DELAY, 10}, // delay. + {0x0100, 0x00}, + {0x36e9, 0x80}, + {0x36f9, 0x80}, + {0x300f, 0x0f}, + {0x3018, 0x1f}, + {0x3019, 0xff}, + {0x301c, 0xb4}, + {0x301f, 0x7b}, + {0x3028, 0x82}, + {0x3200, 0x00}, + {0x3201, 0xdc}, + {0x3202, 0x00}, + {0x3203, 0x98}, + {0x3204, 0x01}, + {0x3205, 0xb3}, + {0x3206, 0x01}, + {0x3207, 0x67}, + {SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, 0x00}, + {SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, 0xc8}, + {SC031GS_OUTPUT_WINDOW_HIGH_H_REG, 0x00}, + {SC031GS_OUTPUT_WINDOW_HIGH_L_REG, 0xc8}, + {0x320c, 0x03}, + {0x320d, 0x6b}, + {0x320e, 0x01}, //default 120fps: {0x320e, 0x01},{0x320f, 0x40}, 58fps: {0x320e, 0x02},{0x320f, 0xab}; 30fps: {0x320e, 0x05}, {0x320f, 0x34} + {0x320f, 0x40}, + {SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x00}, + {SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08}, + {SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x00}, + {SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x04}, + {0x3220, 0x10}, + {0x3223, 0x50}, + {0x3250, 0xf0}, + {0x3251, 0x02}, + {0x3252, 0x01}, + {0x3253, 0x3b}, + {0x3254, 0x02}, + {0x3255, 0x07}, + {0x3304, 0x48}, + {0x3306, 0x38}, + {0x3309, 0x50}, + {0x330b, 0xe0}, + {0x330c, 0x18}, + {0x330f, 0x20}, + {0x3310, 0x10}, + {0x3314, 0x70}, + {0x3315, 0x38}, + {0x3316, 0x68}, + {0x3317, 0x0d}, + {0x3329, 0x5c}, + {0x332d, 0x5c}, + {0x332f, 0x60}, + {0x3335, 0x64}, + {0x3344, 0x64}, + {0x335b, 0x80}, + {0x335f, 0x80}, + {0x3366, 0x06}, + {0x3385, 0x41}, + {0x3387, 0x49}, + {0x3389, 0x01}, + {0x33b1, 0x03}, + {0x33b2, 0x06}, + {0x3621, 0xa4}, + {0x3622, 0x05}, + {0x3624, 0x47}, + {0x3631, 0x48}, + {0x3633, 0x52}, + {0x3635, 0x18}, + {0x3636, 0x25}, + {0x3637, 0x89}, + {0x3638, 0x0f}, + {0x3639, 0x08}, + {0x363a, 0x00}, + {0x363b, 0x48}, + {0x363c, 0x06}, + {0x363e, 0xf8}, + {0x3640, 0x00}, + {0x3641, 0x01}, + {0x36ea, 0x39}, + {0x36eb, 0x1e}, + {0x36ec, 0x0e}, + {0x36ed, 0x23}, + {0x36fa, 0x39}, + {0x36fb, 0x10}, + {0x36fc, 0x01}, + {0x36fd, 0x03}, + {0x3908, 0x91}, + {0x3d08, 0x01}, + {0x3d04, 0x04}, + {0x3e01, 0x13}, + {0x3e02, 0xa0}, + {0x3e06, 0x0c}, + {0x3f04, 0x03}, + {0x3f05, 0x4b}, + {0x4500, 0x59}, + {0x4501, 0xc4}, + {0x4809, 0x01}, + {0x4837, 0x39}, + {0x5011, 0x00}, + {0x36e9, 0x04}, + {0x36f9, 0x04}, + {0x0100, 0x01}, + + //delay 10ms + {REG_DELAY, 0X0a}, + {0x4418, 0x08}, + {0x4419, 0x80}, + {0x363d, 0x10}, + {0x3630, 0x48}, + + // [gain<4] + {0x3317, 0x0d}, + {0x3314, 0x70}, + + // [gain>=4] + {0x3314, 0x68}, + {0x3317, 0x0e}, + {REG_NULL, 0x00}, +}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h new file mode 100644 index 0000000000..85858498ec --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h @@ -0,0 +1,31 @@ +/* + * + * SC101IOT DVP driver. + * + */ +#ifndef __SC101IOT_H__ +#define __SC101IOT_H__ + +#include "sensor.h" + +/** + * @brief Detect sensor pid + * + * @param slv_addr SCCB address + * @param id Detection result + * @return + * 0: Can't detect this sensor + * Nonzero: This sensor has been detected + */ +int sc101iot_detect(int slv_addr, sensor_id_t *id); + +/** + * @brief initialize sensor function pointers + * + * @param sensor pointer of sensor + * @return + * Always 0 + */ +int sc101iot_init(sensor_t *sensor); + +#endif // __SC101IOT_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h new file mode 100644 index 0000000000..2eb143982a --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h @@ -0,0 +1,257 @@ +//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 +//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI +//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P +//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data +//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data +//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR +//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M +//pin :BIT0 pwdn// BIT1:reset +//avdd 0:2.8V// 1:2.5V// 2:1.8V +//dovdd 0:2.8V// 1:2.5V// 2:1.8V +//dvdd 0:1.8V// 1:1.5V// 2:1.2V +/* +[DataBase] +DBName=DemoSens + +[Vendor] +VendorName=SmartSens +I2C_CRC=0 + +[Sensor] +SensorName=SC101AP_raw +width=1280 +height=720 +port=1 +type=2 +pin=3 +SlaveID=0xd0 +mode=0 +FlagReg=0xf7 +FlagMask=0xff +FlagData=0xda +FlagReg1=0xf8 +FlagMask1=0xff +FlagData1=0x4a +outformat=0 +mclk=20 +avdd=2.800000 +dovdd=2.800000 +dvdd=1.200000 + +Ext0=0 +Ext1=0 +Ext2=0 +AFVCC=0.00 +VPP=0.000000 +*/ +#include + +static const uint8_t sc101iot_default_init_regs[][2] = { +#if CONFIG_SC101IOT_720P_15FPS_ENABLED // 720P+YUV422+15FPS sensor default regs +/* Here are some test results: +# size xclk fps pic pclk +# ------- ------- ------ --------- ------- --- --- --- --- --- +# 720p 4 3 err +# 720p 8 5 normal 15 +# 720p 10 7.8 normal 19 +# 720p 20 15 warning 37.5 +# VGA 8 6 normal +# VGA 20 16 normal + +*/ + {0xf0, 0x30}, + {0x01, 0xff}, + {0x02, 0xe0}, + {0x30, 0x10}, + {0x3f, 0x81}, + {0xf0, 0x00}, + {0x70, 0x6b}, + {0x72, 0x30}, + {0x84, 0xb4}, + {0x8b, 0x00}, + {0x8c, 0x20}, + {0x8d, 0x02}, + {0x8e, 0xec}, + {0x9e, 0x10}, + {0xb0, 0xc1}, + {0xc8, 0x10}, + {0xc9, 0x10}, + {0xc6, 0x00}, + {0xe0, 0x0f}, + {0xb5, 0xf0}, + {0xde, 0x80}, + {0xb5, 0xf0}, + {0xde, 0x80}, + {0xb2, 0x50}, + {0xb3, 0xfc}, + {0xb4, 0x40}, + {0xb5, 0xc0}, + {0xb6, 0x50}, + {0xb7, 0xfc}, + {0xb8, 0x40}, + {0xb9, 0xc0}, + {0xba, 0xff}, + {0xbb, 0xcc}, + {0xbc, 0xa9}, + {0xbd, 0x7d}, + {0xc1, 0x77}, + {0xf0, 0x01}, + {0x70, 0x02}, + {0x71, 0x02}, + {0x72, 0x50}, + {0x73, 0x02}, + {0x74, 0xd2}, + {0x75, 0x20}, + {0x76, 0x81}, + {0x77, 0x8c}, + {0x78, 0x81}, + {0xf4, 0x01}, + {0xf5, 0x00}, + {0xf6, 0x00}, + {0xf0, 0x36}, + {0x40, 0x03}, + {0x41, 0x01}, + {0xf0, 0x39}, + {0x02, 0x70}, + {0xf0, 0x32}, + {0x41, 0x00}, + {0x43, 0x01}, + {0x48, 0x02}, + {0xf0, 0x45}, + {0x09, 0x20}, + {0xf0, 0x33}, + {0x33, 0x10}, + {0xf0, 0x30}, + {0x38, 0x44}, + {0xf0, 0x39}, + {0x07, 0x00}, + {0x08, 0x19}, + {0x47, 0x00}, + {0x48, 0x00}, + {0xf0, 0x37}, + {0x24, 0x31}, + {0xf0, 0x34}, + {0x9f, 0x02}, + {0xa6, 0x51}, + {0xa7, 0x57}, + {0xe8, 0x5f}, + {0xa8, 0x50}, + {0xa9, 0x50}, + {0xe9, 0x50}, + {0xf0, 0x33}, + {0xb3, 0x58}, + {0xb2, 0x78}, + {0xf0, 0x34}, + {0x9f, 0x03}, + {0xa6, 0x51}, + {0xa7, 0x57}, + {0xaa, 0x01}, + {0xab, 0x28}, + {0xac, 0x01}, + {0xad, 0x38}, + {0xf0, 0x33}, + {0x0a, 0x01}, + {0x0b, 0x28}, + {0xf0, 0x33}, + {0x64, 0x0f}, + {0xec, 0x51}, + {0xed, 0x57}, + {0x06, 0x58}, + {0xe9, 0x58}, + {0xeb, 0x68}, + {0xf0, 0x33}, + {0x64, 0x0f}, + {0xf0, 0x36}, + {0x70, 0xdf}, + {0xb6, 0x40}, + {0xb7, 0x51}, + {0xb8, 0x53}, + {0xb9, 0x57}, + {0xba, 0x5f}, + {0xb0, 0x84}, + {0xb1, 0x82}, + {0xb2, 0x84}, + {0xb3, 0x88}, + {0xb4, 0x90}, + {0xb5, 0x90}, + {0xf0, 0x36}, + {0x7e, 0x50}, + {0x7f, 0x51}, + {0x77, 0x81}, + {0x78, 0x86}, + {0x79, 0x89}, + {0xf0, 0x36}, + {0x70, 0xdf}, + {0x9c, 0x51}, + {0x9d, 0x57}, + {0x90, 0x54}, + {0x91, 0x54}, + {0x92, 0x56}, + {0xf0, 0x36}, + {0xa0, 0x51}, + {0xa1, 0x57}, + {0x96, 0x33}, + {0x97, 0x43}, + {0x98, 0x43}, + {0xf0, 0x36}, + {0x70, 0xdf}, + {0x7c, 0x40}, + {0x7d, 0x53}, + {0x74, 0xd0}, + {0x75, 0xf0}, + {0x76, 0xf0}, + {0xf0, 0x37}, + {0x0f, 0xd5}, + {0x7a, 0x40}, + {0x7b, 0x57}, + {0x71, 0x09}, + {0x72, 0x09}, + {0x73, 0x05}, + {0xf0, 0x33}, + {0x01, 0x44}, + {0xf0, 0x36}, + {0x37, 0xfb}, + {0xf0, 0x36}, + {0x3c, 0x0d}, + {0xf0, 0x33}, + {0x14, 0x95}, + {0xf0, 0x33}, + {0x8f, 0x80}, + {0xf0, 0x37}, + {0x27, 0x14}, + {0x28, 0x03}, + {0xf0, 0x36}, + {0x37, 0xf4}, + {0xf0, 0x33}, + {0x01, 0x44}, + {0xf0, 0x36}, + {0x79, 0x89}, + {0xf0, 0x34}, + {0xac, 0x01}, + {0xad, 0x40}, + {0xf0, 0x33}, + {0xeb, 0x70}, + {0xf0, 0x34}, + {0xa8, 0x50}, + {0xa9, 0x50}, + {0xf0, 0x33}, + {0xb3, 0x58}, + {0xf0, 0x36}, + {0x11, 0x80}, + {0xf0, 0x36}, + {0x41, 0x51}, + {0xf0, 0x3f}, + {0x03, 0x09}, + {0xf0, 0x32}, + {0x0c, 0x06}, + {0x0d, 0x82}, + {0x0e, 0x02}, + {0x0f, 0xee}, + {0xf0, 0x36}, + {0xea, 0x09}, + {0xeb, 0xf5}, + {0xec, 0x11}, + {0xed, 0x27}, + {0xe9, 0x20}, +#endif +}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c new file mode 100644 index 0000000000..86f525f376 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c @@ -0,0 +1,335 @@ +/* + * SC030IOT driver. + * + * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "sc030iot.h" +#include "sc030iot_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "sc030"; +#endif + +#define SC030_SENSOR_ID_HIGH_REG 0XF7 +#define SC030_SENSOR_ID_LOW_REG 0XF8 +#define SC030_MAX_FRAME_WIDTH (640) +#define SC030_MAX_FRAME_HIGH (480) + +// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. +// For more information please refer to the Technical Reference Manual. +static int get_reg(sensor_t *sensor, int reg, int reg_value_mask) +{ + int ret = 0; + uint8_t reg_high = (reg>>8) & 0xFF; + uint8_t reg_low = reg & 0xFF; + + if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { + return -1; + } + + ret = SCCB_Read(sensor->slv_addr, reg_low); + if(ret > 0){ + ret &= reg_value_mask; + } + return ret; +} + +// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. +// For more information please refer to the Technical Reference Manual. +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + uint8_t reg_high = (reg>>8) & 0xFF; + uint8_t reg_low = reg & 0xFF; + + if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { + return -1; + } + + ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF); + return ret; +} + +static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len) +{ + int i=0, res = 0; + while (islv_addr, regs[i][0], regs[i][1]); + if (res) { + return res; + } + i++; + } + return res; +} + +static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + ret = get_reg(sensor, reg, 0xff); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value); + return ret; +} + +#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;} +#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} +#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on + } else { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off + } + + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on + } else { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable test pattern mode + + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement + WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value + WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit + + return ret; +} + +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control + WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1 + WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2 + WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3 + WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4 + + return ret; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control + WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target + + return ret; +} + +static int set_awb_gain(sensor_t *sensor, int value) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control + WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain + WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control + WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128) + WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128) + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control + WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64) + return ret; +} + +static int reset(sensor_t *sensor) +{ + int ret = set_regs(sensor, sc030iot_default_init_regs, sizeof(sc030iot_default_init_regs)/(sizeof(uint8_t) * 2)); + + // Delay + vTaskDelay(50 / portTICK_PERIOD_MS); + + // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor + // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff)); + if (ret) { + ESP_LOGE(TAG, "reset fail"); + } + return ret; +} + +static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) +{ + int ret = 0; + //sc:H_start={0x0172[1:0],0x0170},H_end={0x0172[5:4],0x0171}, + WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff); + WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff); + WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x03) | (((offset_x+w)>>4)&0x30)); + + //sc:V_start={0x0175[1:0],0x0173},H_end={0x0175[5:4],0x0174}, + WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff); + WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff); + WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x03) | (((offset_y+h)>>4)&0x30)); + + vTaskDelay(10 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + if(w>SC030_MAX_FRAME_WIDTH || h > SC030_MAX_FRAME_HIGH) { + goto err; + } + + uint16_t offset_x = (640-w) /2; + uint16_t offset_y = (480-h) /2; + + if(set_window(sensor, offset_x, offset_y, w, h)) { + goto err; + } + + sensor->status.framesize = framesize; + return 0; +err: + ESP_LOGE(TAG, "frame size err"); + return -1; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret=0; + sensor->pixformat = pixformat; + + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_RAW: + case PIXFORMAT_GRAYSCALE: + ESP_LOGE(TAG, "Not support"); + break; + case PIXFORMAT_YUV422: // For now, sc030/sc031 sensor only support YUV422. + break; + default: + return -1; + } + + return ret; +} + +static int init_status(sensor_t *sensor) +{ + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int sc030iot_detect(int slv_addr, sensor_id_t *id) +{ + if (SC030IOT_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read(slv_addr, SC030_SENSOR_ID_LOW_REG); + uint8_t MIDH = SCCB_Read(slv_addr, SC030_SENSOR_ID_HIGH_REG); + uint16_t PID = MIDH << 8 | MIDL; + if (SC030IOT_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int sc030iot_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + + sensor->set_saturation= set_saturation; + sensor->set_colorbar = set_colorbar; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->set_sharpness = set_sharpness; + sensor->set_agc_gain = set_agc_gain; + sensor->set_aec_value = set_aec_value; + sensor->set_awb_gain = set_awb_gain; + sensor->set_contrast = set_contrast; + //not supported + sensor->set_denoise = set_dummy; + sensor->set_quality = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_xclk = set_xclk; + + ESP_LOGD(TAG, "sc030iot Attached"); + + return 0; +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c new file mode 100644 index 0000000000..dbd75ea054 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c @@ -0,0 +1,346 @@ +/* + * SC031GS driver. + * + * Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "sc031gs.h" +#include "sc031gs_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "sc031gs"; +#endif + +#define SC031GS_PID_LOW_REG 0x3107 +#define SC031GS_PID_HIGH_REG 0x3108 +#define SC031GS_MAX_FRAME_WIDTH (640) +#define SC031GS_MAX_FRAME_HIGH (480) +#define SC031GS_GAIN_CTRL_COARSE_REG 0x3e08 +#define SC031GS_GAIN_CTRL_FINE_REG 0x3e09 + +#define SC031GS_PIDH_MAGIC 0x00 // High byte of sensor ID +#define SC031GS_PIDL_MAGIC 0x31 // Low byte of sensor ID + +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF); + if(ret > 0){ + ret &= mask; + } + return ret; +} + +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF); + if(ret < 0){ + return ret; + } + value = (ret & ~mask) | (value & mask); + ret = SCCB_Write16(sensor->slv_addr, reg & 0xFFFF, value); + return ret; +} + +static int set_reg_bits(sensor_t *sensor, uint16_t reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + ret = SCCB_Read16(sensor->slv_addr, reg); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = SCCB_Write16(sensor->slv_addr, reg, value); + return ret; +} + +static int write_regs(uint8_t slv_addr, const struct sc031gs_regval *regs) +{ + int i = 0, ret = 0; + while (!ret && regs[i].addr != REG_NULL) { + if (regs[i].addr == REG_DELAY) { + vTaskDelay(regs[i].val / portTICK_PERIOD_MS); + } else { + ret = SCCB_Write16(slv_addr, regs[i].addr, regs[i].val); + } + i++; + } + return ret; +} + +#define WRITE_REGS_OR_RETURN(regs) ret = write_regs(slv_addr, regs); if(ret){return ret;} +#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} +#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on + } else { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off + } + + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on + } else { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x4501, 3, 1, enable & 0x01); // enable test pattern mode + SET_REG_BITS_OR_RETURN(0x3902, 6, 1, 1); // enable auto BLC, disable auto BLC if set to 0 + SET_REG_BITS_OR_RETURN(0x3e06, 0, 2, 3); // digital gain: 00->1x, 01->2x, 03->4x. + return ret; +} + +static int set_special_effect(sensor_t *sensor, int sleep_mode_enable) // For sc03ags sensor, This API used for sensor sleep mode control. +{ + // Add some others special control in this API, use switch to control different funcs, such as ctrl_id. + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0100, 0, 1, !(sleep_mode_enable & 0x01)); // 0: enable sleep mode. In sleep mode, the registers can be accessed. + return ret; +} + +int set_bpc(sensor_t *sensor, int enable) // // For sc03ags sensor, This API used to control BLC +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x3900, 0, 1, enable & 0x01); + SET_REG_BITS_OR_RETURN(0x3902, 6, 1, enable & 0x01); + return ret; +} + +static int set_agc_gain(sensor_t *sensor, int gain) +{ + // sc031gs doesn't support AGC, use this func to control. + int ret = 0; + uint32_t coarse_gain, fine_gain, fine_again_reg_v, coarse_gain_reg_v; + + if (gain < 0x20) { + WRITE_REG_OR_RETURN(0x3314, 0x3a); + WRITE_REG_OR_RETURN(0x3317, 0x20); + } else { + WRITE_REG_OR_RETURN(0x3314, 0x44); + WRITE_REG_OR_RETURN(0x3317, 0x0f); + } + + if (gain < 0x20) { /*1x ~ 2x*/ + fine_gain = gain - 16; + coarse_gain = 0x03; + fine_again_reg_v = ((0x01 << 4) & 0x10) | + (fine_gain & 0x0f); + coarse_gain_reg_v = coarse_gain & 0x1F; + } else if (gain < 0x40) { /*2x ~ 4x*/ + fine_gain = (gain >> 1) - 16; + coarse_gain = 0x7; + fine_again_reg_v = ((0x01 << 4) & 0x10) | + (fine_gain & 0x0f); + coarse_gain_reg_v = coarse_gain & 0x1F; + } else if (gain < 0x80) { /*4x ~ 8x*/ + fine_gain = (gain >> 2) - 16; + coarse_gain = 0xf; + fine_again_reg_v = ((0x01 << 4) & 0x10) | + (fine_gain & 0x0f); + coarse_gain_reg_v = coarse_gain & 0x1F; + } else { /*8x ~ 16x*/ + fine_gain = (gain >> 3) - 16; + coarse_gain = 0x1f; + fine_again_reg_v = ((0x01 << 4) & 0x10) | + (fine_gain & 0x0f); + coarse_gain_reg_v = coarse_gain & 0x1F; + } + + WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_COARSE_REG, coarse_gain_reg_v); + WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_FINE_REG, fine_again_reg_v); + + return ret; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + // For now, HDR is disabled, the sensor work in normal mode. + int ret = 0; + WRITE_REG_OR_RETURN(0x3e01, value & 0xFF); // AE target high + WRITE_REG_OR_RETURN(0x3e02, (value >> 8) & 0xFF); // AE target low + + return ret; +} + +static int reset(sensor_t *sensor) +{ + int ret = write_regs(sensor->slv_addr, sc031gs_default_init_regs); + if (ret) { + ESP_LOGE(TAG, "reset fail"); + } + // printf("reg 0x3d04=%02x\r\n", get_reg(sensor, 0x3d04, 0xff)); + // set_colorbar(sensor, 1); + return ret; +} + +static int set_output_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) +{ + int ret = 0; + //sc:H_start={0x3212[1:0],0x3213},H_length={0x3208[1:0],0x3209}, + // printf("%d, %d, %d, %d\r\n", ((offset_x>>8) & 0x03), offset_x & 0xff, ((w>>8) & 0x03), w & 0xff); + + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x0); // For now, we use x_start is 0x04 + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x04); + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, ((w>>8) & 0x03)); + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, w & 0xff); + + //sc:V_start={0x3210[1:0],0x3211},V_length={0x320a[1:0],0x320b}, + // printf("%d, %d, %d, %d\r\n", ((offset_y>>8) & 0x03), offset_y & 0xff, ((h>>8) & 0x03), h & 0xff); + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x0); // For now, we use y_start is 0x08 + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08); + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_H_REG, ((h>>8) & 0x03)); + WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_L_REG, h & 0xff); + + vTaskDelay(10 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + if(w > SC031GS_MAX_FRAME_WIDTH || h > SC031GS_MAX_FRAME_HIGH) { + goto err; + } + + if(w != 200 || h != 200) { + ESP_LOGE(TAG, "Only support 200*200 for now, contact us if you want to use other resolutions"); + goto err; + } + + uint16_t offset_x = (640-w) /2 + 4; + uint16_t offset_y = (480-h) /2 + 4; + + if(set_output_window(sensor, offset_x, offset_y, w, h)) { + goto err; + } + + sensor->status.framesize = framesize; + return 0; +err: + ESP_LOGE(TAG, "frame size err"); + return -1; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret=0; + sensor->pixformat = pixformat; + + switch (pixformat) { + case PIXFORMAT_GRAYSCALE: + break; + default: + ESP_LOGE(TAG, "Only support GRAYSCALE(Y8)"); + return -1; + } + + return ret; +} + +static int init_status(sensor_t *sensor) +{ + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int sc031gs_detect(int slv_addr, sensor_id_t *id) +{ + if (SC031GS_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read16(slv_addr, SC031GS_PID_HIGH_REG); + uint8_t MIDH = SCCB_Read16(slv_addr, SC031GS_PID_LOW_REG); + uint16_t PID = MIDH << 8 | MIDL; + if (SC031GS_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int sc031gs_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + + sensor->set_colorbar = set_colorbar; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->set_agc_gain = set_agc_gain; + sensor->set_aec_value = set_aec_value; + sensor->set_special_effect = set_special_effect; + + //not supported + sensor->set_awb_gain = set_dummy; + sensor->set_contrast = set_dummy; + sensor->set_sharpness = set_dummy; + sensor->set_saturation= set_dummy; + sensor->set_denoise = set_dummy; + sensor->set_quality = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_xclk = set_xclk; + + ESP_LOGD(TAG, "sc031gs Attached"); + + return 0; +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c new file mode 100644 index 0000000000..310a04768b --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c @@ -0,0 +1,342 @@ +/* + * SC101IOT driver. + * + * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include +#include "sccb.h" +#include "xclk.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "sc101iot.h" +#include "sc101iot_settings.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "sc101"; +#endif + +#define SC101_SENSOR_ID_HIGH_REG 0XF7 +#define SC101_SENSOR_ID_LOW_REG 0XF8 +#define SC101_MAX_FRAME_WIDTH (1280) +#define SC101_MAX_FRAME_HIGH (720) + +// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. +// For more information please refer to the Technical Reference Manual. +static int get_reg(sensor_t *sensor, int reg, int mask) +{ + int ret = 0; + uint8_t reg_high = (reg>>8) & 0xFF; + uint8_t reg_low = reg & 0xFF; + + if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { + return -1; + } + + ret = SCCB_Read(sensor->slv_addr, reg_low); + if(ret > 0){ + ret &= mask; + } + return ret; +} + +// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. +// For more information please refer to the Technical Reference Manual. +static int set_reg(sensor_t *sensor, int reg, int mask, int value) +{ + int ret = 0; + uint8_t reg_high = (reg>>8) & 0xFF; + uint8_t reg_low = reg & 0xFF; + + if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { + return -1; + } + + ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF); + return ret; +} + +static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len) +{ + int i=0, res = 0; + while (islv_addr, regs[i][0], regs[i][1]); + if (res) { + return res; + } + i++; + } + return res; +} + +static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value) +{ + int ret = 0; + ret = get_reg(sensor, reg, 0xff); + if(ret < 0){ + return ret; + } + uint8_t mask = ((1 << length) - 1) << offset; + value = (ret & ~mask) | ((value << offset) & mask); + ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value); + return ret; +} + +#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;} +#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} +#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} + +static int set_hmirror(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // enable mirror + } else { + SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // disable mirror + } + + return ret; +} + +static int set_vflip(sensor_t *sensor, int enable) +{ + int ret = 0; + if(enable) { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on + } else { + SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off + } + + return ret; +} + +static int set_colorbar(sensor_t *sensor, int enable) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable colorbar mode + return ret; +} + +static int set_raw_gma(sensor_t *sensor, int enable) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00f5, 1, 1, enable & 0xff); // enable gamma compensation + + return ret; +} + +static int set_sharpness(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement + WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value + WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit + + return ret; +} + +static int set_agc_gain(sensor_t *sensor, int gain) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control + WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1 + WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2 + WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3 + WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4 + + return ret; +} + +static int set_aec_value(sensor_t *sensor, int value) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control + WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target + + return ret; +} + +static int set_awb_gain(sensor_t *sensor, int value) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control + WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain + WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain + return ret; +} + +static int set_saturation(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control + WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128) + WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128) + return ret; +} + +static int set_contrast(sensor_t *sensor, int level) +{ + int ret = 0; + SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control + WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64) + return ret; +} + +static int reset(sensor_t *sensor) +{ + int ret = set_regs(sensor, sc101iot_default_init_regs, sizeof(sc101iot_default_init_regs)/(sizeof(uint8_t) * 2)); + + // Delay + vTaskDelay(50 / portTICK_PERIOD_MS); + + // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor + // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff)); + if (ret) { + ESP_LOGE(TAG, "reset fail"); + } + return ret; +} + +static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) +{ + int ret = 0; + //sc:H_start={0x0172[3:0],0x0170},H_end={0x0172[7:4],0x0171}, + WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff); + WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff); + WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x0f) | (((offset_x+w)>>4)&0xf0)); + + //sc:V_start={0x0175[3:0],0x0173},H_end={0x0175[7:4],0x0174}, + WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff); + WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff); + WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x0f) | (((offset_y+h)>>4)&0xf0)); + + vTaskDelay(10 / portTICK_PERIOD_MS); + + return ret; +} + +static int set_framesize(sensor_t *sensor, framesize_t framesize) +{ + uint16_t w = resolution[framesize].width; + uint16_t h = resolution[framesize].height; + if(w>SC101_MAX_FRAME_WIDTH || h > SC101_MAX_FRAME_HIGH) { + goto err; + } + + uint16_t offset_x = (SC101_MAX_FRAME_WIDTH-w) /2; + uint16_t offset_y = (SC101_MAX_FRAME_HIGH-h) /2; + + if(set_window(sensor, offset_x, offset_y, w, h)) { + goto err; + } + + sensor->status.framesize = framesize; + return 0; +err: + ESP_LOGE(TAG, "frame size err"); + return -1; +} + +static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) +{ + int ret=0; + sensor->pixformat = pixformat; + + switch (pixformat) { + case PIXFORMAT_RGB565: + case PIXFORMAT_RAW: + case PIXFORMAT_GRAYSCALE: + ESP_LOGE(TAG, "Not support"); + break; + case PIXFORMAT_YUV422: // For now, sc101 sensor only support YUV422. + break; + default: + ret = -1; + } + + return ret; +} + +static int init_status(sensor_t *sensor) +{ + return 0; +} + +static int set_dummy(sensor_t *sensor, int val){ return -1; } + +static int set_xclk(sensor_t *sensor, int timer, int xclk) +{ + int ret = 0; + sensor->xclk_freq_hz = xclk * 1000000U; + ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); + return ret; +} + +int sc101iot_detect(int slv_addr, sensor_id_t *id) +{ + if (SC101IOT_SCCB_ADDR == slv_addr) { + uint8_t MIDL = SCCB_Read(slv_addr, SC101_SENSOR_ID_LOW_REG); + uint8_t MIDH = SCCB_Read(slv_addr, SC101_SENSOR_ID_HIGH_REG); + uint16_t PID = MIDH << 8 | MIDL; + if (SC101IOT_PID == PID) { + id->PID = PID; + return PID; + } else { + ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); + } + } + return 0; +} + +int sc101iot_init(sensor_t *sensor) +{ + // Set function pointers + sensor->reset = reset; + sensor->init_status = init_status; + sensor->set_pixformat = set_pixformat; + sensor->set_framesize = set_framesize; + sensor->set_hmirror = set_hmirror; + sensor->set_vflip = set_vflip; + sensor->set_colorbar = set_colorbar; + sensor->set_raw_gma = set_raw_gma; + sensor->set_sharpness = set_sharpness; + sensor->set_agc_gain = set_agc_gain; + sensor->set_aec_value = set_aec_value; + sensor->set_awb_gain = set_awb_gain; + sensor->set_saturation= set_saturation; + sensor->set_contrast = set_contrast; + + sensor->set_denoise = set_dummy; + sensor->set_quality = set_dummy; + sensor->set_special_effect = set_dummy; + sensor->set_wb_mode = set_dummy; + sensor->set_ae_level = set_dummy; + + + sensor->get_reg = get_reg; + sensor->set_reg = set_reg; + sensor->set_xclk = set_xclk; + + ESP_LOGD(TAG, "sc101iot Attached"); + + return 0; +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c new file mode 100644 index 0000000000..e1a2fee719 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c @@ -0,0 +1,539 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "soc/i2s_struct.h" +#include "esp_idf_version.h" +#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR > 1) +#include "hal/gpio_ll.h" +#else +#include "soc/gpio_periph.h" +#define esp_rom_delay_us ets_delay_us +static inline int gpio_ll_get_level(gpio_dev_t *hw, int gpio_num) +{ + if (gpio_num < 32) { + return (hw->in >> gpio_num) & 0x1; + } else { + return (hw->in1.data >> (gpio_num - 32)) & 0x1; + } +} +#endif +#include "ll_cam.h" +#include "xclk.h" +#include "cam_hal.h" + +#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3) +#include "esp_rom_gpio.h" +#endif + +#if (ESP_IDF_VERSION_MAJOR >= 5) +#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE +#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE +#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) +#endif + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 2) +#define ets_delay_us esp_rom_delay_us +#endif + +static const char *TAG = "esp32 ll_cam"; + +#define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;} +#define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;} + +typedef union { + struct { + uint32_t sample2:8; + uint32_t unused2:8; + uint32_t sample1:8; + uint32_t unused1:8; + }; + uint32_t val; +} dma_elem_t; + +typedef enum { + /* camera sends byte sequence: s1, s2, s3, s4, ... + * fifo receives: 00 s1 00 s2, 00 s2 00 s3, 00 s3 00 s4, ... + */ + SM_0A0B_0B0C = 0, + /* camera sends byte sequence: s1, s2, s3, s4, ... + * fifo receives: 00 s1 00 s2, 00 s3 00 s4, ... + */ + SM_0A0B_0C0D = 1, + /* camera sends byte sequence: s1, s2, s3, s4, ... + * fifo receives: 00 s1 00 00, 00 s2 00 00, 00 s3 00 00, ... + */ + SM_0A00_0B00 = 3, +} i2s_sampling_mode_t; + +typedef size_t (*dma_filter_t)(uint8_t* dst, const uint8_t* src, size_t len); + +static i2s_sampling_mode_t sampling_mode = SM_0A00_0B00; + +static size_t ll_cam_bytes_per_sample(i2s_sampling_mode_t mode) +{ + switch(mode) { + case SM_0A00_0B00: + return 4; + case SM_0A0B_0B0C: + return 4; + case SM_0A0B_0C0D: + return 2; + default: + assert(0 && "invalid sampling mode"); + return 0; + } +} + +static size_t IRAM_ATTR ll_cam_dma_filter_jpeg(uint8_t* dst, const uint8_t* src, size_t len) +{ + const dma_elem_t* dma_el = (const dma_elem_t*)src; + size_t elements = len / sizeof(dma_elem_t); + size_t end = elements / 4; + // manually unrolling 4 iterations of the loop here + for (size_t i = 0; i < end; ++i) { + dst[0] = dma_el[0].sample1; + dst[1] = dma_el[1].sample1; + dst[2] = dma_el[2].sample1; + dst[3] = dma_el[3].sample1; + dma_el += 4; + dst += 4; + } + return elements; +} + +static size_t IRAM_ATTR ll_cam_dma_filter_grayscale(uint8_t* dst, const uint8_t* src, size_t len) +{ + const dma_elem_t* dma_el = (const dma_elem_t*)src; + size_t elements = len / sizeof(dma_elem_t); + size_t end = elements / 4; + for (size_t i = 0; i < end; ++i) { + // manually unrolling 4 iterations of the loop here + dst[0] = dma_el[0].sample1; + dst[1] = dma_el[1].sample1; + dst[2] = dma_el[2].sample1; + dst[3] = dma_el[3].sample1; + dma_el += 4; + dst += 4; + } + return elements; +} + +static size_t IRAM_ATTR ll_cam_dma_filter_grayscale_highspeed(uint8_t* dst, const uint8_t* src, size_t len) +{ + const dma_elem_t* dma_el = (const dma_elem_t*)src; + size_t elements = len / sizeof(dma_elem_t); + size_t end = elements / 8; + for (size_t i = 0; i < end; ++i) { + // manually unrolling 4 iterations of the loop here + dst[0] = dma_el[0].sample1; + dst[1] = dma_el[2].sample1; + dst[2] = dma_el[4].sample1; + dst[3] = dma_el[6].sample1; + dma_el += 8; + dst += 4; + } + // the final sample of a line in SM_0A0B_0B0C sampling mode needs special handling + if ((elements & 0x7) != 0) { + dst[0] = dma_el[0].sample1; + dst[1] = dma_el[2].sample1; + elements += 1; + } + return elements / 2; +} + +static size_t IRAM_ATTR ll_cam_dma_filter_yuyv(uint8_t* dst, const uint8_t* src, size_t len) +{ + const dma_elem_t* dma_el = (const dma_elem_t*)src; + size_t elements = len / sizeof(dma_elem_t); + size_t end = elements / 4; + for (size_t i = 0; i < end; ++i) { + dst[0] = dma_el[0].sample1;//y0 + dst[1] = dma_el[0].sample2;//u + dst[2] = dma_el[1].sample1;//y1 + dst[3] = dma_el[1].sample2;//v + + dst[4] = dma_el[2].sample1;//y0 + dst[5] = dma_el[2].sample2;//u + dst[6] = dma_el[3].sample1;//y1 + dst[7] = dma_el[3].sample2;//v + dma_el += 4; + dst += 8; + } + return elements * 2; +} + +static size_t IRAM_ATTR ll_cam_dma_filter_yuyv_highspeed(uint8_t* dst, const uint8_t* src, size_t len) +{ + const dma_elem_t* dma_el = (const dma_elem_t*)src; + size_t elements = len / sizeof(dma_elem_t); + size_t end = elements / 8; + for (size_t i = 0; i < end; ++i) { + dst[0] = dma_el[0].sample1;//y0 + dst[1] = dma_el[1].sample1;//u + dst[2] = dma_el[2].sample1;//y1 + dst[3] = dma_el[3].sample1;//v + + dst[4] = dma_el[4].sample1;//y0 + dst[5] = dma_el[5].sample1;//u + dst[6] = dma_el[6].sample1;//y1 + dst[7] = dma_el[7].sample1;//v + dma_el += 8; + dst += 8; + } + if ((elements & 0x7) != 0) { + dst[0] = dma_el[0].sample1;//y0 + dst[1] = dma_el[1].sample1;//u + dst[2] = dma_el[2].sample1;//y1 + dst[3] = dma_el[2].sample2;//v + elements += 4; + } + return elements; +} + +static void IRAM_ATTR ll_cam_vsync_isr(void *arg) +{ + //DBG_PIN_SET(1); + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + // filter + ets_delay_us(1); + if (gpio_ll_get_level(&GPIO, cam->vsync_pin) == !cam->vsync_invert) { + ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + } + //DBG_PIN_SET(0); +} + +static void IRAM_ATTR ll_cam_dma_isr(void *arg) +{ + //DBG_PIN_SET(1); + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + + typeof(I2S0.int_st) status = I2S0.int_st; + if (status.val == 0) { + return; + } + + I2S0.int_clr.val = status.val; + + if (status.in_suc_eof) { + ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); + } + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + //DBG_PIN_SET(0); +} + +bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) +{ + I2S0.conf.rx_start = 0; + I2S_ISR_DISABLE(in_suc_eof); + I2S0.in_link.stop = 1; + return true; +} + +esp_err_t ll_cam_deinit(cam_obj_t *cam) +{ + gpio_isr_handler_remove(cam->vsync_pin); + + if (cam->cam_intr_handle) { + esp_intr_free(cam->cam_intr_handle); + cam->cam_intr_handle = NULL; + } + gpio_uninstall_isr_service(); + return ESP_OK; +} + +bool ll_cam_start(cam_obj_t *cam, int frame_pos) +{ + I2S0.conf.rx_start = 0; + + I2S_ISR_ENABLE(in_suc_eof); + + I2S0.conf.rx_reset = 1; + I2S0.conf.rx_reset = 0; + I2S0.conf.rx_fifo_reset = 1; + I2S0.conf.rx_fifo_reset = 0; + I2S0.lc_conf.in_rst = 1; + I2S0.lc_conf.in_rst = 0; + I2S0.lc_conf.ahbm_fifo_rst = 1; + I2S0.lc_conf.ahbm_fifo_rst = 0; + I2S0.lc_conf.ahbm_rst = 1; + I2S0.lc_conf.ahbm_rst = 0; + + I2S0.rx_eof_num = cam->dma_half_buffer_size / sizeof(dma_elem_t); + I2S0.in_link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; + + I2S0.in_link.start = 1; + I2S0.conf.rx_start = 1; + return true; +} + +esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) +{ + // Enable and configure I2S peripheral + periph_module_enable(PERIPH_I2S0_MODULE); + + I2S0.conf.rx_reset = 1; + I2S0.conf.rx_reset = 0; + I2S0.conf.rx_fifo_reset = 1; + I2S0.conf.rx_fifo_reset = 0; + I2S0.lc_conf.in_rst = 1; + I2S0.lc_conf.in_rst = 0; + I2S0.lc_conf.ahbm_fifo_rst = 1; + I2S0.lc_conf.ahbm_fifo_rst = 0; + I2S0.lc_conf.ahbm_rst = 1; + I2S0.lc_conf.ahbm_rst = 0; + + I2S0.conf.rx_slave_mod = 1; + I2S0.conf.rx_right_first = 0; + I2S0.conf.rx_msb_right = 0; + I2S0.conf.rx_msb_shift = 0; + I2S0.conf.rx_mono = 0; + I2S0.conf.rx_short_sync = 0; + + I2S0.conf2.lcd_en = 1; + I2S0.conf2.camera_en = 1; + + // Configure clock divider + I2S0.clkm_conf.clkm_div_a = 0; + I2S0.clkm_conf.clkm_div_b = 0; + I2S0.clkm_conf.clkm_div_num = 2; + + I2S0.fifo_conf.dscr_en = 1; + I2S0.fifo_conf.rx_fifo_mod = sampling_mode; + I2S0.fifo_conf.rx_fifo_mod_force_en = 1; + + I2S0.conf_chan.rx_chan_mod = 1; + I2S0.sample_rate_conf.rx_bits_mod = 0; + I2S0.timing.val = 0; + I2S0.timing.rx_dsync_sw = 1; + + return ESP_OK; +} + +void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) +{ + if (en) { + gpio_intr_enable(cam->vsync_pin); + } else { + gpio_intr_disable(cam->vsync_pin); + } +} + +esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) +{ + gpio_config_t io_conf = {0}; + io_conf.intr_type = cam->vsync_invert ? GPIO_PIN_INTR_NEGEDGE : GPIO_PIN_INTR_POSEDGE; + io_conf.pin_bit_mask = 1ULL << config->pin_vsync; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); + gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM); + gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam); + gpio_intr_disable(config->pin_vsync); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); + gpio_matrix_in(config->pin_pclk, I2S0I_WS_IN_IDX, false); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); + gpio_matrix_in(config->pin_vsync, I2S0I_V_SYNC_IDX, false); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); + gpio_matrix_in(config->pin_href, I2S0I_H_SYNC_IDX, false); + + int data_pins[8] = { + config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, + }; + for (int i = 0; i < 8; i++) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); + gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); + gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); + gpio_matrix_in(data_pins[i], I2S0I_DATA_IN0_IDX + i, false); + } + + gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX, false); + return ESP_OK; +} + +esp_err_t ll_cam_init_isr(cam_obj_t *cam) +{ + return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, ll_cam_dma_isr, cam, &cam->cam_intr_handle); +} + +void ll_cam_do_vsync(cam_obj_t *cam) +{ +} + +uint8_t ll_cam_get_dma_align(cam_obj_t *cam) +{ + return 0; +} + +static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ + size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; + size_t dma_buffer_max = 2 * dma_half_buffer_max; + size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; + + size_t line_width = cam->width * cam->in_bytes_per_pixel; + size_t image_size = cam->height * line_width; + if (image_size > (4 * 1024 * 1024) || (line_width > dma_half_buffer_max)) { + ESP_LOGE(TAG, "Resolution too high"); + return 0; + } + + size_t node_size = node_max; + size_t nodes_per_line = 1; + size_t lines_per_node = 1; + size_t lines_per_half_buffer = 1; + size_t dma_half_buffer_min = node_max; + size_t dma_half_buffer = dma_half_buffer_max; + size_t dma_buffer_size = dma_buffer_max; + + // Calculate DMA Node Size so that it's divisable by or divisor of the line width + if(line_width >= node_max){ + // One or more nodes will be requied for one line + for(size_t i = node_max; i > 0; i=i-1){ + if ((line_width % i) == 0) { + node_size = i; + nodes_per_line = line_width / node_size; + break; + } + } + } else { + // One or more lines can fit into one node + for(size_t i = node_max; i > 0; i=i-1){ + if ((i % line_width) == 0) { + node_size = i; + lines_per_node = node_size / line_width; + while((cam->height % lines_per_node) != 0){ + lines_per_node = lines_per_node - 1; + node_size = lines_per_node * line_width; + } + break; + } + } + } + // Calculate minimum EOF size = max(mode_size, line_size) + dma_half_buffer_min = node_size * nodes_per_line; + // Calculate max EOF size divisable by node size + dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; + // Adjust EOF size so that height will be divisable by the number of lines in each EOF + lines_per_half_buffer = dma_half_buffer / line_width; + while((cam->height % lines_per_half_buffer) != 0){ + dma_half_buffer = dma_half_buffer - dma_half_buffer_min; + lines_per_half_buffer = dma_half_buffer / line_width; + } + // Calculate DMA size + dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; + + ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u, dma_half_buffer_min: %5u, dma_half_buffer: %5u," + "lines_per_half_buffer: %2u, dma_buffer_size: %5u, image_size: %u", + (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node, + (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), + (unsigned) (lines_per_half_buffer), (unsigned) (dma_buffer_size * cam->dma_bytes_per_item), (unsigned) image_size); + + cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; + cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; + cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; + cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; + return 1; +} + +bool ll_cam_dma_sizes(cam_obj_t *cam) +{ + cam->dma_bytes_per_item = ll_cam_bytes_per_sample(sampling_mode); + if (cam->jpeg_mode) { + cam->dma_half_buffer_cnt = 8; + cam->dma_node_buffer_size = 2048; + cam->dma_half_buffer_size = cam->dma_node_buffer_size * 2; + cam->dma_buffer_size = cam->dma_half_buffer_cnt * cam->dma_half_buffer_size; + } else { + return ll_cam_calc_rgb_dma(cam); + } + return 1; +} + +static dma_filter_t dma_filter = ll_cam_dma_filter_jpeg; + +size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) +{ + //DBG_PIN_SET(1); + size_t r = dma_filter(out, in, len); + //DBG_PIN_SET(0); + return r; +} + +esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) +{ + if (pix_format == PIXFORMAT_GRAYSCALE) { + if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { + if (xclk_freq_hz > 10000000) { + sampling_mode = SM_0A00_0B00; + dma_filter = ll_cam_dma_filter_yuyv_highspeed; + } else { + sampling_mode = SM_0A0B_0C0D; + dma_filter = ll_cam_dma_filter_yuyv; + } + cam->in_bytes_per_pixel = 1; // camera sends Y8 + } else { + if (xclk_freq_hz > 10000000 && sensor_pid != OV7725_PID) { + sampling_mode = SM_0A00_0B00; + dma_filter = ll_cam_dma_filter_grayscale_highspeed; + } else { + sampling_mode = SM_0A0B_0C0D; + dma_filter = ll_cam_dma_filter_grayscale; + } + cam->in_bytes_per_pixel = 2; // camera sends YU/YV + } + cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 + } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { + if (xclk_freq_hz > 10000000 && sensor_pid != OV7725_PID) { + if (sensor_pid == OV7670_PID) { + sampling_mode = SM_0A0B_0B0C; + } else { + sampling_mode = SM_0A00_0B00; + } + dma_filter = ll_cam_dma_filter_yuyv_highspeed; + } else { + sampling_mode = SM_0A0B_0C0D; + dma_filter = ll_cam_dma_filter_yuyv; + } + cam->in_bytes_per_pixel = 2; // camera sends YU/YV + cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 + } else if (pix_format == PIXFORMAT_JPEG) { + cam->in_bytes_per_pixel = 1; + cam->fb_bytes_per_pixel = 1; + dma_filter = ll_cam_dma_filter_jpeg; + sampling_mode = SM_0A00_0B00; + } else { + ESP_LOGE(TAG, "Requested format is not supported"); + return ESP_ERR_NOT_SUPPORTED; + } + I2S0.fifo_conf.rx_fifo_mod = sampling_mode; + return ESP_OK; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c new file mode 100644 index 0000000000..93313e8f38 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c @@ -0,0 +1,414 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "soc/system_reg.h" +#include "soc/i2s_struct.h" +#include "hal/gpio_ll.h" +#include "ll_cam.h" +#include "xclk.h" +#include "cam_hal.h" + +#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3) +#include "esp_rom_gpio.h" +#endif + +#if (ESP_IDF_VERSION_MAJOR >= 5) +#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE +#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE +#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) +#define ets_delay_us(a) esp_rom_delay_us(a) +#endif + +static const char *TAG = "s2 ll_cam"; + +#define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;} +#define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;} + +static void IRAM_ATTR ll_cam_vsync_isr(void *arg) +{ + //DBG_PIN_SET(1); + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + // filter + ets_delay_us(1); + if (gpio_ll_get_level(&GPIO, cam->vsync_pin) == !cam->vsync_invert) { + ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); + } + + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + //DBG_PIN_SET(0); +} + +static void IRAM_ATTR ll_cam_dma_isr(void *arg) +{ + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + + typeof(I2S0.int_st) status = I2S0.int_st; + if (status.val == 0) { + return; + } + + I2S0.int_clr.val = status.val; + + if (status.in_suc_eof) { + ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); + } + + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) +{ + I2S0.conf.rx_start = 0; + + if (cam->jpeg_mode || !cam->psram_mode) { + I2S_ISR_DISABLE(in_suc_eof); + } + + I2S0.in_link.stop = 1; + return true; +} + +esp_err_t ll_cam_deinit(cam_obj_t *cam) +{ + gpio_isr_handler_remove(cam->vsync_pin); + + if (cam->cam_intr_handle) { + esp_intr_free(cam->cam_intr_handle); + cam->cam_intr_handle = NULL; + } + gpio_uninstall_isr_service(); + return ESP_OK; +} + +bool ll_cam_start(cam_obj_t *cam, int frame_pos) +{ + I2S0.conf.rx_start = 0; + + if (cam->jpeg_mode || !cam->psram_mode) { + I2S_ISR_ENABLE(in_suc_eof); + } + + I2S0.conf.rx_reset = 1; + I2S0.conf.rx_reset = 0; + I2S0.conf.rx_fifo_reset = 1; + I2S0.conf.rx_fifo_reset = 0; + I2S0.lc_conf.in_rst = 1; + I2S0.lc_conf.in_rst = 0; + I2S0.lc_conf.ahbm_fifo_rst = 1; + I2S0.lc_conf.ahbm_fifo_rst = 0; + I2S0.lc_conf.ahbm_rst = 1; + I2S0.lc_conf.ahbm_rst = 0; + + I2S0.rx_eof_num = cam->dma_half_buffer_size; // Ping pong operation + if (!cam->psram_mode) { + I2S0.in_link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; + } else { + I2S0.in_link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff; + } + + I2S0.in_link.start = 1; + I2S0.conf.rx_start = 1; + return true; +} + +esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) +{ + esp_err_t err = camera_enable_out_clock(config); + if(err != ESP_OK) { + return err; + } + periph_module_enable(PERIPH_I2S0_MODULE); + // Configure the clock + I2S0.clkm_conf.clkm_div_num = 2; // 160MHz / 2 = 80MHz + I2S0.clkm_conf.clkm_div_b = 0; + I2S0.clkm_conf.clkm_div_a = 0; + I2S0.clkm_conf.clk_sel = 2; + I2S0.clkm_conf.clk_en = 1; + + + I2S0.conf.val = 0; + I2S0.fifo_conf.val = 0; + I2S0.fifo_conf.dscr_en = 1; + + I2S0.lc_conf.ahbm_fifo_rst = 1; + I2S0.lc_conf.ahbm_fifo_rst = 0; + I2S0.lc_conf.ahbm_rst = 1; + I2S0.lc_conf.ahbm_rst = 0; + I2S0.lc_conf.check_owner = 0; + //I2S0.lc_conf.indscr_burst_en = 1; + //I2S0.lc_conf.ext_mem_bk_size = 0; // DMA access external memory block size. 0: 16 bytes, 1: 32 bytes, 2:64 bytes, 3:reserved + + I2S0.timing.val = 0; + + I2S0.int_ena.val = 0; + I2S0.int_clr.val = ~0; + + I2S0.conf2.lcd_en = 1; + I2S0.conf2.camera_en = 1; + + // Configuration data format + I2S0.conf.rx_slave_mod = 1; + I2S0.conf.rx_right_first = 0; + I2S0.conf.rx_msb_right = cam->swap_data; + I2S0.conf.rx_short_sync = 0; + I2S0.conf.rx_mono = 0; + I2S0.conf.rx_msb_shift = 0; + I2S0.conf.rx_dma_equal = 1; + + // Configure sampling rate + I2S0.sample_rate_conf.rx_bck_div_num = 1; + I2S0.sample_rate_conf.rx_bits_mod = 8; + + I2S0.conf1.rx_pcm_bypass = 1; + + I2S0.conf2.i_v_sync_filter_en = 1; + I2S0.conf2.i_v_sync_filter_thres = 4; + I2S0.conf2.cam_sync_fifo_reset = 1; + I2S0.conf2.cam_sync_fifo_reset = 0; + + I2S0.conf_chan.rx_chan_mod = 1; + + I2S0.fifo_conf.rx_fifo_mod_force_en = 1; + I2S0.fifo_conf.rx_data_num = 32; + I2S0.fifo_conf.rx_fifo_mod = 2; + + I2S0.lc_conf.in_rst = 1; + I2S0.lc_conf.in_rst = 0; + + I2S0.conf.rx_start = 1; + + return ESP_OK; +} + +void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) +{ + if (en) { + gpio_intr_enable(cam->vsync_pin); + } else { + gpio_intr_disable(cam->vsync_pin); + } +} + +esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) +{ + gpio_config_t io_conf = {0}; + io_conf.intr_type = cam->vsync_invert ? GPIO_PIN_INTR_NEGEDGE : GPIO_PIN_INTR_POSEDGE; + io_conf.pin_bit_mask = 1ULL << config->pin_vsync; + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); + gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM); + gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam); + gpio_intr_disable(config->pin_vsync); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); + gpio_matrix_in(config->pin_pclk, I2S0I_WS_IN_IDX, false); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); + gpio_matrix_in(config->pin_vsync, I2S0I_V_SYNC_IDX, cam->vsync_invert); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); + gpio_matrix_in(config->pin_href, I2S0I_H_SYNC_IDX, false); + + int data_pins[8] = { + config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, + }; + for (int i = 0; i < 8; i++) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); + gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); + gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); + // High bit alignment, IN16 is always the highest bit + // fifo accesses data by bit, when rx_bits_mod is 8, the data needs to be aligned by 8 bits + gpio_matrix_in(data_pins[i], I2S0I_DATA_IN0_IDX + 8 + i, false); + } + + gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX, false); + + return ESP_OK; +} + +esp_err_t ll_cam_init_isr(cam_obj_t *cam) +{ + return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, ll_cam_dma_isr, cam, &cam->cam_intr_handle); +} + +void ll_cam_do_vsync(cam_obj_t *cam) +{ + ll_cam_vsync_intr_enable(cam, false); + gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, !cam->vsync_invert); + ets_delay_us(10); + gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, cam->vsync_invert); + ll_cam_vsync_intr_enable(cam, true); +} + +uint8_t ll_cam_get_dma_align(cam_obj_t *cam) +{ + return 64;//16 << I2S0.lc_conf.ext_mem_bk_size; +} + +static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ + size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; + size_t line_width = cam->width * cam->in_bytes_per_pixel; + size_t node_size = node_max; + size_t nodes_per_line = 1; + size_t lines_per_node = 1; + + // Calculate DMA Node Size so that it's divisable by or divisor of the line width + if(line_width >= node_max){ + // One or more nodes will be requied for one line + for(size_t i = node_max; i > 0; i=i-1){ + if ((line_width % i) == 0) { + node_size = i; + nodes_per_line = line_width / node_size; + break; + } + } + } else { + // One or more lines can fit into one node + for(size_t i = node_max; i > 0; i=i-1){ + if ((i % line_width) == 0) { + node_size = i; + lines_per_node = node_size / line_width; + while((cam->height % lines_per_node) != 0){ + lines_per_node = lines_per_node - 1; + node_size = lines_per_node * line_width; + } + break; + } + } + } + + ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u", + (unsigned) (node_size * cam->dma_bytes_per_item), nodes_per_line, lines_per_node); + + cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; + + if (cam->psram_mode) { + cam->dma_buffer_size = cam->recv_size * cam->dma_bytes_per_item; + cam->dma_half_buffer_cnt = 2; + cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; + } else { + size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; + if (line_width > dma_half_buffer_max) { + ESP_LOGE(TAG, "Resolution too high"); + return 0; + } + + // Calculate minimum EOF size = max(mode_size, line_size) + size_t dma_half_buffer_min = node_size * nodes_per_line; + + // Calculate max EOF size divisable by node size + size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; + + // Adjust EOF size so that height will be divisable by the number of lines in each EOF + size_t lines_per_half_buffer = dma_half_buffer / line_width; + while((cam->height % lines_per_half_buffer) != 0){ + dma_half_buffer = dma_half_buffer - dma_half_buffer_min; + lines_per_half_buffer = dma_half_buffer / line_width; + } + + // Calculate DMA size + size_t dma_buffer_max = 2 * dma_half_buffer_max; + size_t dma_buffer_size = dma_buffer_max; + dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; + + ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u", + (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), + (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item)); + + cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; + cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; + cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; + } + return 1; +} + +bool ll_cam_dma_sizes(cam_obj_t *cam) +{ + cam->dma_bytes_per_item = 1; + if (cam->jpeg_mode) { + if (cam->psram_mode) { + cam->dma_buffer_size = cam->recv_size; + cam->dma_half_buffer_size = 1024; + cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; + cam->dma_node_buffer_size = cam->dma_half_buffer_size; + } else { + cam->dma_half_buffer_cnt = 16; + cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024; + cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; + cam->dma_node_buffer_size = cam->dma_half_buffer_size; + } + } else { + return ll_cam_calc_rgb_dma(cam); + } + return 1; +} + +size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) +{ + // YUV to Grayscale + if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) { + size_t end = len / 8; + for (size_t i = 0; i < end; ++i) { + out[0] = in[0]; + out[1] = in[2]; + out[2] = in[4]; + out[3] = in[6]; + out += 4; + in += 8; + } + return len / 2; + } + + // just memcpy + memcpy(out, in, len); + return len; +} + +esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) +{ + if (pix_format == PIXFORMAT_GRAYSCALE) { + if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { + cam->in_bytes_per_pixel = 1; // camera sends Y8 + } else { + cam->in_bytes_per_pixel = 2; // camera sends YU/YV + } + cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 + } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { + cam->in_bytes_per_pixel = 2; // camera sends YU/YV + cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 + } else if (pix_format == PIXFORMAT_JPEG) { + cam->in_bytes_per_pixel = 1; + cam->fb_bytes_per_pixel = 1; + } else { + ESP_LOGE(TAG, "Requested format is not supported"); + return ESP_ERR_NOT_SUPPORTED; + } + return ESP_OK; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h new file mode 100644 index 0000000000..31fbc97cce --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 +/----------------------------------------------------------------------------*/ +#ifndef _TJPGDEC +#define _TJPGDEC +/*---------------------------------------------------------------------------*/ +/* System Configurations */ + +#define JD_SZBUF 512 /* Size of stream input buffer */ +#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ +#define JD_USE_SCALE 1 /* Use descaling feature for output */ +#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ + +/*---------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be damaged data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + + + +/* Rectangular structure */ +typedef struct { + WORD left, right, top, bottom; +} JRECT; + + + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + UINT dctr; /* Number of bytes available in the input buffer */ + BYTE* dptr; /* Current data read ptr */ + BYTE* inbuf; /* Bit stream input buffer */ + BYTE dmsk; /* Current bit in the current read byte */ + BYTE scale; /* Output scaling ratio */ + BYTE msx, msy; /* MCU size in unit of block (width, height) */ + BYTE qtid[3]; /* Quantization table ID of each component */ + SHORT dcv[3]; /* Previous DC element of each component */ + WORD nrst; /* Restart inverval */ + UINT width, height; /* Size of the input image (pixel) */ + BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + LONG* qttbl[4]; /* Dequaitizer tables [id] */ + void* workbuf; /* Working buffer for IDCT and RGB output */ + BYTE* mcubuf; /* Working buffer for the MCU */ + void* pool; /* Pointer to available memory pool */ + UINT sz_pool; /* Size of momory pool (bytes available) */ + UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ + void* device; /* Pointer to I/O device identifiler for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); +JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c new file mode 100644 index 0000000000..28a260384d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c @@ -0,0 +1,538 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "soc/system_reg.h" +#include "soc/lcd_cam_struct.h" +#include "soc/lcd_cam_reg.h" +#include "soc/gdma_struct.h" +#include "soc/gdma_periph.h" +#include "soc/gdma_reg.h" +#include "ll_cam.h" +#include "cam_hal.h" +#include "esp_rom_gpio.h" + +#if (ESP_IDF_VERSION_MAJOR >= 5) +#include "soc/gpio_sig_map.h" +#include "soc/gpio_periph.h" +#include "soc/io_mux_reg.h" +#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) +#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d) +#define ets_delay_us(a) esp_rom_delay_us(a) +#endif + +#if !defined(SOC_GDMA_PAIRS_PER_GROUP) && defined(SOC_GDMA_PAIRS_PER_GROUP_MAX) +#define SOC_GDMA_PAIRS_PER_GROUP SOC_GDMA_PAIRS_PER_GROUP_MAX +#endif + +static const char *TAG = "s3 ll_cam"; + +static void IRAM_ATTR ll_cam_vsync_isr(void *arg) +{ + //DBG_PIN_SET(1); + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + + typeof(LCD_CAM.lc_dma_int_st) status = LCD_CAM.lc_dma_int_st; + if (status.val == 0) { + return; + } + + LCD_CAM.lc_dma_int_clr.val = status.val; + + if (status.cam_vsync_int_st) { + ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); + } + + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } + //DBG_PIN_SET(0); +} + +static void IRAM_ATTR ll_cam_dma_isr(void *arg) +{ + cam_obj_t *cam = (cam_obj_t *)arg; + BaseType_t HPTaskAwoken = pdFALSE; + + typeof(GDMA.channel[cam->dma_num].in.int_st) status = GDMA.channel[cam->dma_num].in.int_st; + if (status.val == 0) { + return; + } + + GDMA.channel[cam->dma_num].in.int_clr.val = status.val; + + if (status.in_suc_eof) { + ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); + } + + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) +{ + if (cam->jpeg_mode || !cam->psram_mode) { + GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 0; + GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1; + } + GDMA.channel[cam->dma_num].in.link.stop = 1; + return true; +} + +esp_err_t ll_cam_deinit(cam_obj_t *cam) +{ + if (cam->cam_intr_handle) { + esp_intr_free(cam->cam_intr_handle); + cam->cam_intr_handle = NULL; + } + + if (cam->dma_intr_handle) { + esp_intr_free(cam->dma_intr_handle); + cam->dma_intr_handle = NULL; + } + GDMA.channel[cam->dma_num].in.link.addr = 0x0; + + LCD_CAM.cam_ctrl1.cam_start = 0; + LCD_CAM.cam_ctrl1.cam_reset = 1; + LCD_CAM.cam_ctrl1.cam_reset = 0; + return ESP_OK; +} + +bool ll_cam_start(cam_obj_t *cam, int frame_pos) +{ + LCD_CAM.cam_ctrl1.cam_start = 0; + + if (cam->jpeg_mode || !cam->psram_mode) { + GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1; + GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 1; + } + + LCD_CAM.cam_ctrl1.cam_reset = 1; + LCD_CAM.cam_ctrl1.cam_reset = 0; + LCD_CAM.cam_ctrl1.cam_afifo_reset = 1; + LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; + GDMA.channel[cam->dma_num].in.conf0.in_rst = 1; + GDMA.channel[cam->dma_num].in.conf0.in_rst = 0; + + LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = cam->dma_half_buffer_size - 1; // Ping pong operation + + if (!cam->psram_mode) { + GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; + } else { + GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff; + } + + GDMA.channel[cam->dma_num].in.link.start = 1; + + LCD_CAM.cam_ctrl.cam_update = 1; + LCD_CAM.cam_ctrl1.cam_start = 1; + return true; +} + +static esp_err_t ll_cam_dma_init(cam_obj_t *cam) +{ + for (int x = (SOC_GDMA_PAIRS_PER_GROUP - 1); x >= 0; x--) { + if (GDMA.channel[x].in.link.addr == 0x0) { + cam->dma_num = x; + ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num); + break; + } + if (x == 0) { + cam_deinit(); + ESP_LOGE(TAG, "Can't found available GDMA channel"); + return ESP_FAIL; + } + } + + if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) { + REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + } + + GDMA.channel[cam->dma_num].in.int_clr.val = ~0; + GDMA.channel[cam->dma_num].in.int_ena.val = 0; + + GDMA.channel[cam->dma_num].in.conf0.val = 0; + GDMA.channel[cam->dma_num].in.conf0.in_rst = 1; + GDMA.channel[cam->dma_num].in.conf0.in_rst = 0; + + //internal SRAM only + if (!cam->psram_mode) { + GDMA.channel[cam->dma_num].in.conf0.indscr_burst_en = 1; + GDMA.channel[cam->dma_num].in.conf0.in_data_burst_en = 1; + } + + GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0; + // GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2; + + GDMA.channel[cam->dma_num].in.peri_sel.sel = 5; + //GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15 + //GDMA.channel[cam->dma_num].in.sram_size.in_size = 6;//This register is used to configure the size of L2 Tx FIFO for Rx channel. 0:16 bytes, 1:24 bytes, 2:32 bytes, 3: 40 bytes, 4: 48 bytes, 5:56 bytes, 6: 64 bytes, 7: 72 bytes, 8: 80 bytes. + //GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15 + return ESP_OK; +} + +#if CONFIG_CAMERA_CONVERTER_ENABLED +static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t *config) +{ + esp_err_t ret = ESP_OK; + + switch (config->conv_mode) { + case YUV422_TO_YUV420: + if (config->pixel_format != PIXFORMAT_YUV422) { + ret = ESP_FAIL; + } else { + ESP_LOGI(TAG, "YUV422 to YUV420 mode"); + LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1; + LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0; + LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 1; + } + break; + case YUV422_TO_RGB565: + if (config->pixel_format != PIXFORMAT_YUV422) { + ret = ESP_FAIL; + } else { + ESP_LOGI(TAG, "YUV422 to RGB565 mode"); + LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3; + LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0; + LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0; + } + break; + default: + break; + } +#if CONFIG_LCD_CAM_CONV_BT709_ENABLED + LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 1; +#else + LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0; +#endif +#if CONFIG_LCD_CAM_CONV_FULL_RANGE_ENABLED + LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1; + LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1; +#else + LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0; + LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0; +#endif + LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1; + LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 1; + cam->conv_mode = config->conv_mode; + return ret; +} +#endif + +esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) +{ + esp_err_t ret = ESP_OK; + if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) { + REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); + REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); + REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); + } + + LCD_CAM.cam_ctrl.val = 0; + + LCD_CAM.cam_ctrl.cam_clkm_div_b = 0; + LCD_CAM.cam_ctrl.cam_clkm_div_a = 0; + LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / config->xclk_freq_hz; + LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. + + LCD_CAM.cam_ctrl.cam_stop_en = 0; + LCD_CAM.cam_ctrl.cam_vsync_filter_thres = 4; // Filter by LCD_CAM clock + LCD_CAM.cam_ctrl.cam_update = 0; + LCD_CAM.cam_ctrl.cam_byte_order = cam->swap_data; + LCD_CAM.cam_ctrl.cam_bit_order = 0; + LCD_CAM.cam_ctrl.cam_line_int_en = 0; + LCD_CAM.cam_ctrl.cam_vs_eof_en = 0; //1: CAM_VSYNC to generate in_suc_eof. 0: in_suc_eof is controlled by reg_cam_rec_data_cyclelen + + LCD_CAM.cam_ctrl1.val = 0; + LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - 1; // Cannot be assigned to 0, and it is easy to overflow + LCD_CAM.cam_ctrl1.cam_line_int_num = 0; // The number of hsyncs that generate hs interrupts + LCD_CAM.cam_ctrl1.cam_clk_inv = 0; + LCD_CAM.cam_ctrl1.cam_vsync_filter_en = 1; + LCD_CAM.cam_ctrl1.cam_2byte_en = 0; + LCD_CAM.cam_ctrl1.cam_de_inv = 0; + LCD_CAM.cam_ctrl1.cam_hsync_inv = 0; + LCD_CAM.cam_ctrl1.cam_vsync_inv = 0; + LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 0; + + LCD_CAM.cam_rgb_yuv.val = 0; + +#if CONFIG_CAMERA_CONVERTER_ENABLED + if (config->conv_mode) { + ret = ll_cam_converter_config(cam, config); + if(ret != ESP_OK) { + return ret; + } + } +#endif + + LCD_CAM.cam_ctrl.cam_update = 1; + LCD_CAM.cam_ctrl1.cam_start = 1; + + ret = ll_cam_dma_init(cam); + + return ret; +} + +void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) +{ + LCD_CAM.lc_dma_int_clr.cam_vsync_int_clr = 1; + if (en) { + LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1; + } else { + LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 0; + } +} + +esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) +{ + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); + gpio_matrix_in(config->pin_pclk, CAM_PCLK_IDX, false); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); + gpio_matrix_in(config->pin_vsync, CAM_V_SYNC_IDX, cam->vsync_invert); + + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); + gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); + gpio_matrix_in(config->pin_href, CAM_H_ENABLE_IDX, false); + + int data_pins[8] = { + config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, + }; + for (int i = 0; i < 8; i++) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); + gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); + gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); + gpio_matrix_in(data_pins[i], CAM_DATA_IN0_IDX + i, false); + } + if (config->pin_xclk >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_xclk], PIN_FUNC_GPIO); + gpio_set_direction(config->pin_xclk, GPIO_MODE_OUTPUT); + gpio_set_pull_mode(config->pin_xclk, GPIO_FLOATING); + gpio_matrix_out(config->pin_xclk, CAM_CLK_IDX, false, false); + } + + return ESP_OK; +} + +esp_err_t ll_cam_init_isr(cam_obj_t *cam) +{ + esp_err_t ret = ESP_OK; + ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[0].pairs[cam->dma_num].rx_irq_id, + ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, + (uint32_t)&GDMA.channel[cam->dma_num].in.int_st, GDMA_IN_SUC_EOF_CH0_INT_ST_M, + ll_cam_dma_isr, cam, &cam->dma_intr_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "DMA interrupt allocation of camera failed"); + return ret; + } + + ret = esp_intr_alloc_intrstatus(ETS_LCD_CAM_INTR_SOURCE, + ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, + (uint32_t)&LCD_CAM.lc_dma_int_st.val, LCD_CAM_CAM_VSYNC_INT_ST_M, + ll_cam_vsync_isr, cam, &cam->cam_intr_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "LCD_CAM interrupt allocation of camera failed"); + return ret; + } + return ESP_OK; +} + +void ll_cam_do_vsync(cam_obj_t *cam) +{ + gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, !cam->vsync_invert); + ets_delay_us(10); + gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, cam->vsync_invert); +} + +uint8_t ll_cam_get_dma_align(cam_obj_t *cam) +{ + return 16 << GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size; +} + +static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ + size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; + size_t line_width = cam->width * cam->in_bytes_per_pixel; + size_t node_size = node_max; + size_t nodes_per_line = 1; + size_t lines_per_node = 1; + + // Calculate DMA Node Size so that it's divisable by or divisor of the line width + if(line_width >= node_max){ + // One or more nodes will be requied for one line + for(size_t i = node_max; i > 0; i=i-1){ + if ((line_width % i) == 0) { + node_size = i; + nodes_per_line = line_width / node_size; + break; + } + } + } else { + // One or more lines can fit into one node + for(size_t i = node_max; i > 0; i=i-1){ + if ((i % line_width) == 0) { + node_size = i; + lines_per_node = node_size / line_width; + while((cam->height % lines_per_node) != 0){ + lines_per_node = lines_per_node - 1; + node_size = lines_per_node * line_width; + } + break; + } + } + } + + ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u", + (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node); + + cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; + + size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; + if (line_width > dma_half_buffer_max) { + ESP_LOGE(TAG, "Resolution too high"); + return 0; + } + + // Calculate minimum EOF size = max(mode_size, line_size) + size_t dma_half_buffer_min = node_size * nodes_per_line; + + // Calculate max EOF size divisable by node size + size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; + + // Adjust EOF size so that height will be divisable by the number of lines in each EOF + size_t lines_per_half_buffer = dma_half_buffer / line_width; + while((cam->height % lines_per_half_buffer) != 0){ + dma_half_buffer = dma_half_buffer - dma_half_buffer_min; + lines_per_half_buffer = dma_half_buffer / line_width; + } + + // Calculate DMA size + size_t dma_buffer_max = 2 * dma_half_buffer_max; + if (cam->psram_mode) { + dma_buffer_max = cam->recv_size / cam->dma_bytes_per_item; + } + size_t dma_buffer_size = dma_buffer_max; + if (!cam->psram_mode) { + dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; + } + + ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u", + (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), + (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item)); + + cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; + cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; + cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; + return 1; +} + +bool ll_cam_dma_sizes(cam_obj_t *cam) +{ + cam->dma_bytes_per_item = 1; + if (cam->jpeg_mode) { + if (cam->psram_mode) { + cam->dma_buffer_size = cam->recv_size; + cam->dma_half_buffer_size = 1024; + cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; + cam->dma_node_buffer_size = cam->dma_half_buffer_size; + } else { + cam->dma_half_buffer_cnt = 16; + cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024; + cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; + cam->dma_node_buffer_size = cam->dma_half_buffer_size; + } + } else { + return ll_cam_calc_rgb_dma(cam); + } + return 1; +} + +size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) +{ + // YUV to Grayscale + if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) { + size_t end = len / 8; + for (size_t i = 0; i < end; ++i) { + out[0] = in[0]; + out[1] = in[2]; + out[2] = in[4]; + out[3] = in[6]; + out += 4; + in += 8; + } + return len / 2; + } + + // just memcpy + memcpy(out, in, len); + return len; +} + +esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) +{ + if (pix_format == PIXFORMAT_GRAYSCALE) { + if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { + cam->in_bytes_per_pixel = 1; // camera sends Y8 + } else { + cam->in_bytes_per_pixel = 2; // camera sends YU/YV + } + cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 + } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { +#if CONFIG_CAMERA_CONVERTER_ENABLED + switch (cam->conv_mode) { + case YUV422_TO_YUV420: + cam->in_bytes_per_pixel = 1.5; // for DMA receive + cam->fb_bytes_per_pixel = 1.5; // frame buffer stores YUV420 + break; + case YUV422_TO_RGB565: + default: + cam->in_bytes_per_pixel = 2; // for DMA receive + cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 + break; + } +#else + cam->in_bytes_per_pixel = 2; // for DMA receive + cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 +#endif + } else if (pix_format == PIXFORMAT_JPEG) { + cam->in_bytes_per_pixel = 1; + cam->fb_bytes_per_pixel = 1; + } else { + ESP_LOGE(TAG, "Requested format is not supported"); + return ESP_ERR_NOT_SUPPORTED; + } + return ESP_OK; +} + +// implements function from xclk.c to allow dynamic XCLK change +esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) +{ + LCD_CAM.cam_ctrl.cam_clkm_div_b = 0; + LCD_CAM.cam_ctrl.cam_clkm_div_a = 0; + LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / xclk_freq_hz; + LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. + LCD_CAM.cam_ctrl.cam_update = 1; + return ESP_OK; +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h new file mode 100644 index 0000000000..31fbc97cce --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 +/----------------------------------------------------------------------------*/ +#ifndef _TJPGDEC +#define _TJPGDEC +/*---------------------------------------------------------------------------*/ +/* System Configurations */ + +#define JD_SZBUF 512 /* Size of stream input buffer */ +#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ +#define JD_USE_SCALE 1 /* Use descaling feature for output */ +#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ + +/*---------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + + +/* Error code */ +typedef enum { + JDR_OK = 0, /* 0: Succeeded */ + JDR_INTR, /* 1: Interrupted by output function */ + JDR_INP, /* 2: Device error or wrong termination of input stream */ + JDR_MEM1, /* 3: Insufficient memory pool for the image */ + JDR_MEM2, /* 4: Insufficient stream input buffer */ + JDR_PAR, /* 5: Parameter error */ + JDR_FMT1, /* 6: Data format error (may be damaged data) */ + JDR_FMT2, /* 7: Right format but not supported */ + JDR_FMT3 /* 8: Not supported JPEG standard */ +} JRESULT; + + + +/* Rectangular structure */ +typedef struct { + WORD left, right, top, bottom; +} JRECT; + + + +/* Decompressor object structure */ +typedef struct JDEC JDEC; +struct JDEC { + UINT dctr; /* Number of bytes available in the input buffer */ + BYTE* dptr; /* Current data read ptr */ + BYTE* inbuf; /* Bit stream input buffer */ + BYTE dmsk; /* Current bit in the current read byte */ + BYTE scale; /* Output scaling ratio */ + BYTE msx, msy; /* MCU size in unit of block (width, height) */ + BYTE qtid[3]; /* Quantization table ID of each component */ + SHORT dcv[3]; /* Previous DC element of each component */ + WORD nrst; /* Restart inverval */ + UINT width, height; /* Size of the input image (pixel) */ + BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ + WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ + BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ + LONG* qttbl[4]; /* Dequaitizer tables [id] */ + void* workbuf; /* Working buffer for IDCT and RGB output */ + BYTE* mcubuf; /* Working buffer for the MCU */ + void* pool; /* Pointer to available memory pool */ + UINT sz_pool; /* Size of momory pool (bytes available) */ + UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ + void* device; /* Pointer to I/O device identifiler for the session */ +}; + + + +/* TJpgDec API functions */ +JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); +JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); + + +#ifdef __cplusplus +} +#endif + +#endif /* _TJPGDEC */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h new file mode 100644 index 0000000000..34c8da36dd --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h @@ -0,0 +1,147 @@ +// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include +#include "sdkconfig.h" +#include "esp_idf_version.h" +#if CONFIG_IDF_TARGET_ESP32 +#if ESP_IDF_VERSION_MAJOR >= 4 +#include "esp32/rom/lldesc.h" +#else +#include "rom/lldesc.h" +#endif +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/lldesc.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/lldesc.h" +#endif +#include "esp_log.h" +#include "esp_camera.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +#if __has_include("esp_private/periph_ctrl.h") +# include "esp_private/periph_ctrl.h" +#endif + +#define CAMERA_DBG_PIN_ENABLE 0 +#if CAMERA_DBG_PIN_ENABLE + #if CONFIG_IDF_TARGET_ESP32 + #define DBG_PIN_NUM 26 + #else + #define DBG_PIN_NUM 7 + #endif + #include "hal/gpio_ll.h" + #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) +#else + #define DBG_PIN_SET(v) +#endif + +#define CAM_CHECK(a, str, ret) if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret); \ + } + +#define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ + ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + goto lab; \ + } + +#define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) + +typedef enum { + CAM_IN_SUC_EOF_EVENT = 0, + CAM_VSYNC_EVENT +} cam_event_t; + +typedef enum { + CAM_STATE_IDLE = 0, + CAM_STATE_READ_BUF = 1, +} cam_state_t; + +typedef struct { + camera_fb_t fb; + uint8_t en; + //for RGB/YUV modes + lldesc_t *dma; + size_t fb_offset; +} cam_frame_t; + +typedef struct { + uint32_t dma_bytes_per_item; + uint32_t dma_buffer_size; + uint32_t dma_half_buffer_size; + uint32_t dma_half_buffer_cnt; + uint32_t dma_node_buffer_size; + uint32_t dma_node_cnt; + uint32_t frame_copy_cnt; + + //for JPEG mode + lldesc_t *dma; + uint8_t *dma_buffer; + + cam_frame_t *frames; + + QueueHandle_t event_queue; + QueueHandle_t frame_buffer_queue; + TaskHandle_t task_handle; + intr_handle_t cam_intr_handle; + + uint8_t dma_num;//ESP32-S3 + intr_handle_t dma_intr_handle;//ESP32-S3 + + uint8_t jpeg_mode; + uint8_t vsync_pin; + uint8_t vsync_invert; + uint32_t frame_cnt; + uint32_t recv_size; + bool swap_data; + bool psram_mode; + + //for RGB/YUV modes + uint16_t width; + uint16_t height; +#if CONFIG_CAMERA_CONVERTER_ENABLED + float in_bytes_per_pixel; + float fb_bytes_per_pixel; + camera_conv_mode_t conv_mode; +#else + uint8_t in_bytes_per_pixel; + uint8_t fb_bytes_per_pixel; +#endif + uint32_t fb_size; + + cam_state_t state; +} cam_obj_t; + + +bool ll_cam_stop(cam_obj_t *cam); +bool ll_cam_start(cam_obj_t *cam, int frame_pos); +esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); +esp_err_t ll_cam_deinit(cam_obj_t *cam); +void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); +esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); +esp_err_t ll_cam_init_isr(cam_obj_t *cam); +void ll_cam_do_vsync(cam_obj_t *cam); +uint8_t ll_cam_get_dma_align(cam_obj_t *cam); +bool ll_cam_dma_sizes(cam_obj_t *cam); +size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); +esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid); + +// implemented in cam_hal +void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c new file mode 100644 index 0000000000..5a983c4c7f --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c @@ -0,0 +1,970 @@ +/*----------------------------------------------------------------------------/ +/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 +/-----------------------------------------------------------------------------/ +/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2012, ChaN, all right reserved. +/ +/ * The TJpgDec module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Oct 04,'11 R0.01 First release. +/ Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. +/ Sep 03,'12 R0.01b Added JD_TBLCLIP option. +/----------------------------------------------------------------------------*/ + +#include "tjpgd.h" + +#define SUPPORT_JPEG 1 + +#ifdef SUPPORT_JPEG +/*-----------------------------------------------*/ +/* Zigzag-order to raster-order conversion table */ +/*-----------------------------------------------*/ + +#define ZIG(n) Zig[n] + +static +const BYTE Zig[64] = { /* Zigzag-order to raster-order conversion table */ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + + + +/*-------------------------------------------------*/ +/* Input scale factor of Arai algorithm */ +/* (scaled up 16 bits for fixed point operations) */ +/*-------------------------------------------------*/ + +#define IPSF(n) Ipsf[n] + +static +const WORD Ipsf[64] = { /* See also aa_idct.png */ + (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), + (WORD)(1.38704*8192), (WORD)(1.92388*8192), (WORD)(1.81226*8192), (WORD)(1.63099*8192), (WORD)(1.38704*8192), (WORD)(1.08979*8192), (WORD)(0.75066*8192), (WORD)(0.38268*8192), + (WORD)(1.30656*8192), (WORD)(1.81226*8192), (WORD)(1.70711*8192), (WORD)(1.53636*8192), (WORD)(1.30656*8192), (WORD)(1.02656*8192), (WORD)(0.70711*8192), (WORD)(0.36048*8192), + (WORD)(1.17588*8192), (WORD)(1.63099*8192), (WORD)(1.53636*8192), (WORD)(1.38268*8192), (WORD)(1.17588*8192), (WORD)(0.92388*8192), (WORD)(0.63638*8192), (WORD)(0.32442*8192), + (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), + (WORD)(0.78570*8192), (WORD)(1.08979*8192), (WORD)(1.02656*8192), (WORD)(0.92388*8192), (WORD)(0.78570*8192), (WORD)(0.61732*8192), (WORD)(0.42522*8192), (WORD)(0.21677*8192), + (WORD)(0.54120*8192), (WORD)(0.75066*8192), (WORD)(0.70711*8192), (WORD)(0.63638*8192), (WORD)(0.54120*8192), (WORD)(0.42522*8192), (WORD)(0.29290*8192), (WORD)(0.14932*8192), + (WORD)(0.27590*8192), (WORD)(0.38268*8192), (WORD)(0.36048*8192), (WORD)(0.32442*8192), (WORD)(0.27590*8192), (WORD)(0.21678*8192), (WORD)(0.14932*8192), (WORD)(0.07612*8192) +}; + + + +/*---------------------------------------------*/ +/* Conversion table for fast clipping process */ +/*---------------------------------------------*/ + +#if JD_TBLCLIP + +#define BYTECLIP(v) Clip8[(UINT)(v) & 0x3FF] + +static +const BYTE Clip8[1024] = { + /* 0..255 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + /* 256..511 */ + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + /* -512..-257 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* -256..-1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#else /* JD_TBLCLIP */ + +inline +BYTE BYTECLIP ( + INT val +) +{ + if (val < 0) val = 0; + if (val > 255) val = 255; + + return (BYTE)val; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Allocate a memory block from memory pool */ +/*-----------------------------------------------------------------------*/ + +static +void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ + JDEC* jd, /* Pointer to the decompressor object */ + UINT nd /* Number of bytes to allocate */ +) +{ + char *rp = 0; + + + nd = (nd + 3) & ~3; /* Align block size to the word boundary */ + + if (jd->sz_pool >= nd) { + jd->sz_pool -= nd; + rp = (char*)jd->pool; /* Get start of available memory pool */ + jd->pool = (void*)(rp + nd); /* Allocate requierd bytes */ + } + + return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create de-quantization and prescaling tables with a DQT segment */ +/*-----------------------------------------------------------------------*/ + +static +UINT create_qt_tbl ( /* 0:OK, !0:Failed */ + JDEC* jd, /* Pointer to the decompressor object */ + const BYTE* data, /* Pointer to the quantizer tables */ + UINT ndata /* Size of input data */ +) +{ + UINT i; + BYTE d, z; + LONG *pb; + + + while (ndata) { /* Process all tables in the segment */ + if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ + ndata -= 65; + d = *data++; /* Get table property */ + if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ + i = d & 3; /* Get table ID */ + pb = alloc_pool(jd, 64 * sizeof (LONG));/* Allocate a memory block for the table */ + if (!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->qttbl[i] = pb; /* Register the table */ + for (i = 0; i < 64; i++) { /* Load the table */ + z = ZIG(i); /* Zigzag-order to raster-order conversion */ + pb[z] = (LONG)((DWORD)*data++ * IPSF(z)); /* Apply scale factor of Arai algorithm to the de-quantizers */ + } + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create huffman code tables with a DHT segment */ +/*-----------------------------------------------------------------------*/ + +static +UINT create_huffman_tbl ( /* 0:OK, !0:Failed */ + JDEC* jd, /* Pointer to the decompressor object */ + const BYTE* data, /* Pointer to the packed huffman tables */ + UINT ndata /* Size of input data */ +) +{ + UINT i, j, b, np, cls, num; + BYTE d, *pb, *pd; + WORD hc, *ph; + + + while (ndata) { /* Process all tables in the segment */ + if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ + ndata -= 17; + d = *data++; /* Get table number and class */ + cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ + if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ + pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ + if (!pb) return JDR_MEM1; /* Err: not enough memory */ + jd->huffbits[num][cls] = pb; + for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ + pb[i] = b = *data++; + np += b; /* Get sum of code words for each code */ + } + + ph = alloc_pool(jd, np * sizeof (WORD));/* Allocate a memory block for the code word table */ + if (!ph) return JDR_MEM1; /* Err: not enough memory */ + jd->huffcode[num][cls] = ph; + hc = 0; + for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ + b = pb[i]; + while (b--) ph[j++] = hc++; + hc <<= 1; + } + + if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ + ndata -= np; + pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ + if (!pd) return JDR_MEM1; /* Err: not enough memory */ + jd->huffdata[num][cls] = pd; + for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code ward */ + d = *data++; + if (!cls && d > 11) return JDR_FMT1; + *pd++ = d; + } + } + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract N bits from input stream */ +/*-----------------------------------------------------------------------*/ + +static +INT bitext ( /* >=0: extracted data, <0: error code */ + JDEC* jd, /* Pointer to the decompressor object */ + UINT nbit /* Number of bits to extract (1 to 11) */ +) +{ + BYTE msk, s, *dp; + UINT dc, v, f; + + + msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ + s = *dp; v = f = 0; + do { + if (!msk) { /* Next byte? */ + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (INT)JDR_INP; /* Err: read error or wrong stream termination */ + } else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if (f) { /* In flag sequence? */ + f = 0; /* Exit flag sequence */ + if (*dp != 0) return 0 - (INT)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = s = 0xFF; /* The flag is a data 0xFF */ + } else { + s = *dp; /* Get next data byte */ + if (s == 0xFF) { /* Is start of flag sequence? */ + f = 1; continue; /* Enter flag sequence */ + } + } + msk = 0x80; /* Read from MSB */ + } + v <<= 1; /* Get a bit */ + if (s & msk) v++; + msk >>= 1; + nbit--; + } while (nbit); + jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; + + return (INT)v; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Extract a huffman decoded data from input stream */ +/*-----------------------------------------------------------------------*/ + +static +INT huffext ( /* >=0: decoded data, <0: error code */ + JDEC* jd, /* Pointer to the decompressor object */ + const BYTE* hbits, /* Pointer to the bit distribution table */ + const WORD* hcode, /* Pointer to the code word table */ + const BYTE* hdata /* Pointer to the data table */ +) +{ + BYTE msk, s, *dp; + UINT dc, v, f, bl, nd; + + + msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ + s = *dp; v = f = 0; + bl = 16; /* Max code length */ + do { + if (!msk) { /* Next byte? */ + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; /* Top of input buffer */ + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return 0 - (INT)JDR_INP; /* Err: read error or wrong stream termination */ + } else { + dp++; /* Next data ptr */ + } + dc--; /* Decrement number of available bytes */ + if (f) { /* In flag sequence? */ + f = 0; /* Exit flag sequence */ + if (*dp != 0) + return 0 - (INT)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ + *dp = s = 0xFF; /* The flag is a data 0xFF */ + } else { + s = *dp; /* Get next data byte */ + if (s == 0xFF) { /* Is start of flag sequence? */ + f = 1; continue; /* Enter flag sequence, get trailing byte */ + } + } + msk = 0x80; /* Read from MSB */ + } + v <<= 1; /* Get a bit */ + if (s & msk) v++; + msk >>= 1; + + for (nd = *hbits++; nd; nd--) { /* Search the code word in this bit length */ + if (v == *hcode++) { /* Matched? */ + jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; + return *hdata; /* Return the decoded data */ + } + hdata++; + } + bl--; + } while (bl); + + return 0 - (INT)JDR_FMT1; /* Err: code not found (may be collapted data) */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ +/*-----------------------------------------------------------------------*/ + +static +void block_idct ( + LONG* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ + BYTE* dst /* Pointer to the destination to store the block as byte array */ +) +{ + const LONG M13 = (LONG)(1.41421*4096), M2 = (LONG)(1.08239*4096), M4 = (LONG)(2.61313*4096), M5 = (LONG)(1.84776*4096); + LONG v0, v1, v2, v3, v4, v5, v6, v7; + LONG t10, t11, t12, t13; + UINT i; + + /* Process columns */ + for (i = 0; i < 8; i++) { + v0 = src[8 * 0]; /* Get even elements */ + v1 = src[8 * 2]; + v2 = src[8 * 4]; + v3 = src[8 * 6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[8 * 7]; /* Get odd elements */ + v5 = src[8 * 1]; + v6 = src[8 * 5]; + v7 = src[8 * 3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + src[8 * 0] = v0 + v7; /* Write-back transformed values */ + src[8 * 7] = v0 - v7; + src[8 * 1] = v1 + v6; + src[8 * 6] = v1 - v6; + src[8 * 2] = v2 + v5; + src[8 * 5] = v2 - v5; + src[8 * 3] = v3 + v4; + src[8 * 4] = v3 - v4; + + src++; /* Next column */ + } + + /* Process rows */ + src -= 8; + for (i = 0; i < 8; i++) { + v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ + v1 = src[2]; + v2 = src[4]; + v3 = src[6]; + + t10 = v0 + v2; /* Process the even elements */ + t12 = v0 - v2; + t11 = (v1 - v3) * M13 >> 12; + v3 += v1; + t11 -= v3; + v0 = t10 + v3; + v3 = t10 - v3; + v1 = t11 + t12; + v2 = t12 - t11; + + v4 = src[7]; /* Get odd elements */ + v5 = src[1]; + v6 = src[5]; + v7 = src[3]; + + t10 = v5 - v4; /* Process the odd elements */ + t11 = v5 + v4; + t12 = v6 - v7; + v7 += v6; + v5 = (t11 - v7) * M13 >> 12; + v7 += t11; + t13 = (t10 + t12) * M5 >> 12; + v4 = t13 - (t10 * M2 >> 12); + v6 = t13 - (t12 * M4 >> 12) - v7; + v5 -= v6; + v4 -= v5; + + dst[0] = BYTECLIP((v0 + v7) >> 8); /* Descale the transformed values 8 bits and output */ + dst[7] = BYTECLIP((v0 - v7) >> 8); + dst[1] = BYTECLIP((v1 + v6) >> 8); + dst[6] = BYTECLIP((v1 - v6) >> 8); + dst[2] = BYTECLIP((v2 + v5) >> 8); + dst[5] = BYTECLIP((v2 - v5) >> 8); + dst[3] = BYTECLIP((v3 + v4) >> 8); + dst[4] = BYTECLIP((v3 - v4) >> 8); + dst += 8; + + src += 8; /* Next row */ + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load all blocks in the MCU into working buffer */ +/*-----------------------------------------------------------------------*/ + +static +JRESULT mcu_load ( + JDEC* jd /* Pointer to the decompressor object */ +) +{ + LONG *tmp = (LONG*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ + UINT blk, nby, nbc, i, z, id, cmp; + INT b, d, e; + BYTE *bp; + const BYTE *hb, *hd; + const WORD *hc; + const LONG *dqf; + + + nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ + nbc = 2; /* Number of C blocks (2) */ + bp = jd->mcubuf; /* Pointer to the first block */ + + for (blk = 0; blk < nby + nbc; blk++) { + cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ + id = cmp ? 1 : 0; /* Huffman table ID of the component */ + + /* Extract a DC element from input stream */ + hb = jd->huffbits[id][0]; /* Huffman table for the DC element */ + hc = jd->huffcode[id][0]; + hd = jd->huffdata[id][0]; + b = huffext(jd, hb, hc, hd); /* Extract a huffman coded data (bit length) */ + if (b < 0) return 0 - b; /* Err: invalid code or input */ + d = jd->dcv[cmp]; /* DC value of previous block */ + if (b) { /* If there is any difference from previous block */ + e = bitext(jd, b); /* Extract data bits */ + if (e < 0) return 0 - e; /* Err: input */ + b = 1 << (b - 1); /* MSB position */ + if (!(e & b)) e -= (b << 1) - 1; /* Restore sign if needed */ + d += e; /* Get current value */ + jd->dcv[cmp] = (SHORT)d; /* Save current DC value for next block */ + } + dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ + tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + + /* Extract following 63 AC elements from input stream */ + for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ + hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ + hc = jd->huffcode[id][1]; + hd = jd->huffdata[id][1]; + i = 1; /* Top of the AC elements */ + do { + b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ + if (b == 0) break; /* EOB? */ + if (b < 0) return 0 - b; /* Err: invalid code or input error */ + z = (UINT)b >> 4; /* Number of leading zero elements */ + if (z) { + i += z; /* Skip zero elements */ + if (i >= 64) return JDR_FMT1; /* Too long zero run */ + } + if (b &= 0x0F) { /* Bit length */ + d = bitext(jd, b); /* Extract data bits */ + if (d < 0) return 0 - d; /* Err: input device */ + b = 1 << (b - 1); /* MSB position */ + if (!(d & b)) d -= (b << 1) - 1;/* Restore negative value if needed */ + z = ZIG(i); /* Zigzag-order to raster-order converted index */ + tmp[z] = d * dqf[z] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ + } + } while (++i < 64); /* Next AC element */ + + if (JD_USE_SCALE && jd->scale == 3) + *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ + else + block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ + + bp += 64; /* Next block */ + } + + return JDR_OK; /* All blocks have been loaded successfully */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ +/*-----------------------------------------------------------------------*/ + +static +JRESULT mcu_output ( + JDEC* jd, /* Pointer to the decompressor object */ + UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ + UINT x, /* MCU position in the image (left of the MCU) */ + UINT y /* MCU position in the image (top of the MCU) */ +) +{ + const INT CVACC = (sizeof (INT) > 2) ? 1024 : 128; + UINT ix, iy, mx, my, rx, ry; + INT yy, cb, cr; + BYTE *py, *pc, *rgb24; + JRECT rect; + + + mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ + rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end) */ + ry = (y + my <= jd->height) ? my : jd->height - y; + if (JD_USE_SCALE) { + rx >>= jd->scale; ry >>= jd->scale; + if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ + x >>= jd->scale; y >>= jd->scale; + } + rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ + rect.top = y; rect.bottom = y + ry - 1; + + + if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ + + /* Build an RGB MCU from discrete comopnents */ + rgb24 = (BYTE*)jd->workbuf; + for (iy = 0; iy < my; iy++) { + pc = jd->mcubuf; + py = pc + iy * 8; + if (my == 16) { /* Double block height? */ + pc += 64 * 4 + (iy >> 1) * 8; + if (iy >= 8) py += 64; + } else { /* Single block height */ + pc += mx * 8 + iy * 8; + } + for (ix = 0; ix < mx; ix++) { + cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ + cr = pc[64] - 128; + if (mx == 16) { /* Double block width? */ + if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ + pc += ix & 1; /* Increase chroma pointer every two pixels */ + } else { /* Single block width */ + pc++; /* Increase chroma pointer every pixel */ + } + yy = *py++; /* Get Y component */ + + /* Convert YCbCr to RGB */ + *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr) / CVACC); + *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((INT)(1.772 * CVACC) * cb) / CVACC); + } + } + + /* Descale the MCU rectangular if needed */ + if (JD_USE_SCALE && jd->scale) { + UINT x, y, r, g, b, s, w, a; + BYTE *op; + + /* Get averaged RGB value of each square correcponds to a pixel */ + s = jd->scale * 2; /* Bumber of shifts for averaging */ + w = 1 << jd->scale; /* Width of square */ + a = (mx - w) * 3; /* Bytes to skip for next line in the square */ + op = (BYTE*)jd->workbuf; + for (iy = 0; iy < my; iy += w) { + for (ix = 0; ix < mx; ix += w) { + rgb24 = (BYTE*)jd->workbuf + (iy * mx + ix) * 3; + r = g = b = 0; + for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ + for (x = 0; x < w; x++) { + r += *rgb24++; + g += *rgb24++; + b += *rgb24++; + } + rgb24 += a; + } /* Put the averaged RGB value as a pixel */ + *op++ = (BYTE)(r >> s); + *op++ = (BYTE)(g >> s); + *op++ = (BYTE)(b >> s); + } + } + } + + } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ + + /* Build a 1/8 descaled RGB MCU from discrete comopnents */ + rgb24 = (BYTE*)jd->workbuf; + pc = jd->mcubuf + mx * my; + cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ + cr = pc[64] - 128; + for (iy = 0; iy < my; iy += 8) { + py = jd->mcubuf; + if (iy == 8) py += 64 * 2; + for (ix = 0; ix < mx; ix += 8) { + yy = *py; /* Get Y component */ + py += 64; + + /* Convert YCbCr to RGB */ + *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr / CVACC)); + *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC); + *rgb24++ = /* B */ BYTECLIP(yy + ((INT)(1.772 * CVACC) * cb / CVACC)); + } + } + } + + /* Squeeze up pixel table if a part of MCU is to be truncated */ + mx >>= jd->scale; + if (rx < mx) { + BYTE *s, *d; + UINT x, y; + + s = d = (BYTE*)jd->workbuf; + for (y = 0; y < ry; y++) { + for (x = 0; x < rx; x++) { /* Copy effective pixels */ + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + s += (mx - rx) * 3; /* Skip truncated pixels */ + } + } + + /* Convert RGB888 to RGB565 if needed */ + if (JD_FORMAT == 1) { + BYTE *s = (BYTE*)jd->workbuf; + WORD w, *d = (WORD*)s; + UINT n = rx * ry; + + do { + w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ + w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ + w |= *s++ >> 3; /* -----------BBBBB */ + *d++ = w; + } while (--n); + } + + /* Output the RGB rectangular */ + return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Process restart interval */ +/*-----------------------------------------------------------------------*/ + +static +JRESULT restart ( + JDEC* jd, /* Pointer to the decompressor object */ + WORD rstn /* Expected restert sequense number */ +) +{ + UINT i, dc; + WORD d; + BYTE *dp; + + + /* Discard padding bits and get two bytes from the input stream */ + dp = jd->dptr; dc = jd->dctr; + d = 0; + for (i = 0; i < 2; i++) { + if (!dc) { /* No input data is available, re-fill input buffer */ + dp = jd->inbuf; + dc = jd->infunc(jd, dp, JD_SZBUF); + if (!dc) return JDR_INP; + } else { + dp++; + } + dc--; + d = (d << 8) | *dp; /* Get a byte */ + } + jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0; + + /* Check the marker */ + if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) + return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ + + /* Reset DC offset */ + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; + + return JDR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Analyze the JPEG image and Initialize decompressor object */ +/*-----------------------------------------------------------------------*/ + +#define LDB_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr))<<8)|(WORD)*(BYTE*)((ptr)+1)) + + +JRESULT jd_prepare ( + JDEC* jd, /* Blank decompressor object */ + UINT (*infunc)(JDEC*, BYTE*, UINT), /* JPEG strem input function */ + void* pool, /* Working buffer for the decompression session */ + UINT sz_pool, /* Size of working buffer */ + void* dev /* I/O device identifier for the session */ +) +{ + BYTE *seg, b; + WORD marker; + DWORD ofs; + UINT n, i, j, len; + JRESULT rc; + + + if (!pool) return JDR_PAR; + + jd->pool = pool; /* Work memroy */ + jd->sz_pool = sz_pool; /* Size of given work memory */ + jd->infunc = infunc; /* Stream input function */ + jd->device = dev; /* I/O device identifier */ + jd->nrst = 0; /* No restart interval (default) */ + + for (i = 0; i < 2; i++) { /* Nulls pointers */ + for (j = 0; j < 2; j++) { + jd->huffbits[i][j] = 0; + jd->huffcode[i][j] = 0; + jd->huffdata[i][j] = 0; + } + } + for (i = 0; i < 4; i++) jd->qttbl[i] = 0; + + jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ + if (!seg) return JDR_MEM1; + + if (jd->infunc(jd, seg, 2) != 2) return JDR_INP;/* Check SOI marker */ + if (LDB_WORD(seg) != 0xFFD8) return JDR_FMT1; /* Err: SOI is not detected */ + ofs = 2; + + for (;;) { + /* Get a JPEG marker */ + if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; + marker = LDB_WORD(seg); /* Marker */ + len = LDB_WORD(seg + 2); /* Length field */ + if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; + len -= 2; /* Content size excluding length field */ + ofs += 4 + len; /* Number of bytes loaded */ + + switch (marker & 0xFF) { + case 0xC0: /* SOF0 (baseline JPEG) */ + /* Load segment data */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; + + jd->width = LDB_WORD(seg+3); /* Image width in unit of pixel */ + jd->height = LDB_WORD(seg+1); /* Image height in unit of pixel */ + if (seg[5] != 3) return JDR_FMT3; /* Err: Supports only Y/Cb/Cr format */ + + /* Check three image components */ + for (i = 0; i < 3; i++) { + b = seg[7 + 3 * i]; /* Get sampling factor */ + if (!i) { /* Y component */ + if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */ + return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ + jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ + } else { /* Cb/Cr component */ + if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ + } + b = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ + if (b > 3) return JDR_FMT3; /* Err: Invalid ID */ + jd->qtid[i] = b; + } + break; + + case 0xDD: /* DRI */ + /* Load segment data */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; + + /* Get restart interval (MCUs) */ + jd->nrst = LDB_WORD(seg); + break; + + case 0xC4: /* DHT */ + /* Load segment data */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; + + /* Create huffman tables */ + rc = create_huffman_tbl(jd, seg, len); + if (rc) return rc; + break; + + case 0xDB: /* DQT */ + /* Load segment data */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; + + /* Create de-quantizer tables */ + rc = create_qt_tbl(jd, seg, len); + if (rc) return rc; + break; + + case 0xDA: /* SOS */ + /* Load segment data */ + if (len > JD_SZBUF) return JDR_MEM2; + if (jd->infunc(jd, seg, len) != len) return JDR_INP; + + if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ + + if (seg[0] != 3) return JDR_FMT3; /* Err: Supports only three color components format */ + + /* Check if all tables corresponding to each components have been loaded */ + for (i = 0; i < 3; i++) { + b = seg[2 + 2 * i]; /* Get huffman table ID */ + if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ + b = i ? 1 : 0; + if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */ + return JDR_FMT1; /* Err: Huffman table not loaded */ + if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */ + } + + /* Allocate working buffer for MCU and RGB */ + n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ + if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ + len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ + if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ + jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ + if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ + jd->mcubuf = alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ + if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ + + /* Pre-load the JPEG data to extract it from the bit stream */ + jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */ + if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ + jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (UINT)ofs); + jd->dptr = seg + ofs - 1; + } + + return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ + + case 0xC1: /* SOF1 */ + case 0xC2: /* SOF2 */ + case 0xC3: /* SOF3 */ + case 0xC5: /* SOF5 */ + case 0xC6: /* SOF6 */ + case 0xC7: /* SOF7 */ + case 0xC9: /* SOF9 */ + case 0xCA: /* SOF10 */ + case 0xCB: /* SOF11 */ + case 0xCD: /* SOF13 */ + case 0xCE: /* SOF14 */ + case 0xCF: /* SOF15 */ + case 0xD9: /* EOI */ + return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ + + default: /* Unknown segment (comment, exif or etc..) */ + /* Skip segment data */ + if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */ + return JDR_INP; + } + } +} + + + + +/*-----------------------------------------------------------------------*/ +/* Start to decompress the JPEG picture */ +/*-----------------------------------------------------------------------*/ + +JRESULT jd_decomp ( + JDEC* jd, /* Initialized decompression object */ + UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ + BYTE scale /* Output de-scaling factor (0 to 3) */ +) +{ + UINT x, y, mx, my; + WORD rst, rsc; + JRESULT rc; + + + if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; + jd->scale = scale; + + mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ + + jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ + rst = rsc = 0; + + rc = JDR_OK; + for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ + for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ + if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ + rc = restart(jd, rsc++); + if (rc != JDR_OK) return rc; + rst = 1; + } + rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream and apply IDCT) */ + if (rc != JDR_OK) return rc; + rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (color space conversion, scaling and output) */ + if (rc != JDR_OK) return rc; + } + } + + return rc; +} +#endif//SUPPORT_JPEG + + diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c new file mode 100644 index 0000000000..cb67b677a5 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c @@ -0,0 +1,72 @@ +#include "driver/gpio.h" +#include "driver/ledc.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_system.h" +#include "xclk.h" +#include "esp_camera.h" + +#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) +#include "esp32-hal-log.h" +#else +#include "esp_log.h" +static const char* TAG = "camera_xclk"; +#endif + +#define NO_CAMERA_LEDC_CHANNEL 0xFF +static ledc_channel_t g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; + +esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) +{ + ledc_timer_config_t timer_conf; + timer_conf.duty_resolution = LEDC_TIMER_1_BIT; + timer_conf.freq_hz = xclk_freq_hz; + timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) + timer_conf.deconfigure = false; +#endif + +#if ESP_IDF_VERSION_MAJOR >= 4 + timer_conf.clk_cfg = LEDC_AUTO_CLK; +#endif + timer_conf.timer_num = (ledc_timer_t)ledc_timer; + esp_err_t err = ledc_timer_config(&timer_conf); + if (err != ESP_OK) { + ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); + } + return err; +} + +esp_err_t camera_enable_out_clock(const camera_config_t* config) +{ + esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); + if (err != ESP_OK) { + ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); + return err; + } + + g_ledc_channel = config->ledc_channel; + ledc_channel_config_t ch_conf; + ch_conf.gpio_num = config->pin_xclk; + ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; + ch_conf.channel = config->ledc_channel; + ch_conf.intr_type = LEDC_INTR_DISABLE; + ch_conf.timer_sel = config->ledc_timer; + ch_conf.duty = 1; + ch_conf.hpoint = 0; + err = ledc_channel_config(&ch_conf); + if (err != ESP_OK) { + ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); + return err; + } + return ESP_OK; +} + +void camera_disable_out_clock() +{ + if (g_ledc_channel != NO_CAMERA_LEDC_CHANNEL) { + ledc_stop(LEDC_LOW_SPEED_MODE, g_ledc_channel, 0); + g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; + } +} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt new file mode 100644 index 0000000000..a8c3d16b75 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRC_DIRS . + PRIV_INCLUDE_DIRS . + PRIV_REQUIRES test_utils esp32-camera nvs_flash + EMBED_TXTFILES pictures/testimg.jpeg pictures/test_outside.jpeg pictures/test_inside.jpeg) diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk new file mode 100644 index 0000000000..5fb883650e --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk @@ -0,0 +1,8 @@ +# +#Component Makefile +# + +COMPONENT_SRCDIRS += ./ +COMPONENT_PRIV_INCLUDEDIRS += ./ + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..92e7bc3694e8568be514673432c3601a8c1c4126 GIT binary patch literal 18832 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 F|Jg`@ubTh> literal 0 HcmV?d00001 diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..dcb4bf1b3c82c9aa3858223414be90a54a1ff4c6 GIT binary patch literal 81744 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 +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include +#include "esp_log.h" +#include "driver/i2c.h" + +#include "esp_camera.h" + +#ifdef CONFIG_IDF_TARGET_ESP32 +#define BOARD_WROVER_KIT 1 +#elif defined CONFIG_IDF_TARGET_ESP32S2 +#define BOARD_CAMERA_MODEL_ESP32S2 1 +#elif defined CONFIG_IDF_TARGET_ESP32S3 +#define BOARD_CAMERA_MODEL_ESP32_S3_EYE 1 +#endif + +// WROVER-KIT PIN Map +#if BOARD_WROVER_KIT + +#define PWDN_GPIO_NUM -1 //power down is not used +#define RESET_GPIO_NUM -1 //software reset will be performed +#define XCLK_GPIO_NUM 21 +#define SIOD_GPIO_NUM 26 +#define SIOC_GPIO_NUM 27 + +#define Y9_GPIO_NUM 35 +#define Y8_GPIO_NUM 34 +#define Y7_GPIO_NUM 39 +#define Y6_GPIO_NUM 36 +#define Y5_GPIO_NUM 19 +#define Y4_GPIO_NUM 18 +#define Y3_GPIO_NUM 5 +#define Y2_GPIO_NUM 4 +#define VSYNC_GPIO_NUM 25 +#define HREF_GPIO_NUM 23 +#define PCLK_GPIO_NUM 22 + +// ESP32Cam (AiThinker) PIN Map +#elif BOARD_ESP32CAM_AITHINKER + +#define PWDN_GPIO_NUM 32 +#define RESET_GPIO_NUM -1 //software reset will be performed +#define XCLK_GPIO_NUM 0 +#define SIOD_GPIO_NUM 26 +#define SIOC_GPIO_NUM 27 + +#define Y9_GPIO_NUM 35 +#define Y8_GPIO_NUM 34 +#define Y7_GPIO_NUM 39 +#define Y6_GPIO_NUM 36 +#define Y5_GPIO_NUM 21 +#define Y4_GPIO_NUM 19 +#define Y3_GPIO_NUM 18 +#define Y2_GPIO_NUM 5 +#define VSYNC_GPIO_NUM 25 +#define HREF_GPIO_NUM 23 +#define PCLK_GPIO_NUM 22 + +#elif BOARD_CAMERA_MODEL_ESP32S2 + +#define PWDN_GPIO_NUM -1 +#define RESET_GPIO_NUM -1 + +#define VSYNC_GPIO_NUM 21 +#define HREF_GPIO_NUM 38 +#define PCLK_GPIO_NUM 11 +#define XCLK_GPIO_NUM 40 + +#define SIOD_GPIO_NUM 17 +#define SIOC_GPIO_NUM 18 + +#define Y9_GPIO_NUM 39 +#define Y8_GPIO_NUM 41 +#define Y7_GPIO_NUM 42 +#define Y6_GPIO_NUM 12 +#define Y5_GPIO_NUM 3 +#define Y4_GPIO_NUM 14 +#define Y3_GPIO_NUM 37 +#define Y2_GPIO_NUM 13 + +#elif BOARD_CAMERA_MODEL_ESP32_S3_EYE + +#define PWDN_GPIO_NUM 43 +#define RESET_GPIO_NUM 44 + +#define VSYNC_GPIO_NUM 6 +#define HREF_GPIO_NUM 7 +#define PCLK_GPIO_NUM 13 +#define XCLK_GPIO_NUM 15 + +#define SIOD_GPIO_NUM 4 +#define SIOC_GPIO_NUM 5 + +#define Y9_GPIO_NUM 16 +#define Y8_GPIO_NUM 17 +#define Y7_GPIO_NUM 18 +#define Y6_GPIO_NUM 12 +#define Y5_GPIO_NUM 11 +#define Y4_GPIO_NUM 10 +#define Y3_GPIO_NUM 9 +#define Y2_GPIO_NUM 8 + +#endif + +#define I2C_MASTER_SCL_IO 4 /*!< GPIO number used for I2C master clock */ +#define I2C_MASTER_SDA_IO 5 /*!< GPIO number used for I2C master data */ +#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ +#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ + +static const char *TAG = "test camera"; + +typedef void (*decode_func_t)(uint8_t *jpegbuffer, uint32_t size, uint8_t *outbuffer); + +static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count, int sccb_sda_gpio_num, int sccb_port) +{ + framesize_t size_bak = frame_size; + if (PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > frame_size) { + frame_size = FRAMESIZE_HD; + } + camera_config_t camera_config = { + .pin_pwdn = PWDN_GPIO_NUM, + .pin_reset = RESET_GPIO_NUM, + .pin_xclk = XCLK_GPIO_NUM, + .pin_sccb_sda = sccb_sda_gpio_num, // If pin_sccb_sda is -1, sccb will use the already initialized i2c port specified by `sccb_i2c_port`. + .pin_sccb_scl = SIOC_GPIO_NUM, + .sccb_i2c_port = sccb_port, + + .pin_d7 = Y9_GPIO_NUM, + .pin_d6 = Y8_GPIO_NUM, + .pin_d5 = Y7_GPIO_NUM, + .pin_d4 = Y6_GPIO_NUM, + .pin_d3 = Y5_GPIO_NUM, + .pin_d2 = Y4_GPIO_NUM, + .pin_d1 = Y3_GPIO_NUM, + .pin_d0 = Y2_GPIO_NUM, + .pin_vsync = VSYNC_GPIO_NUM, + .pin_href = HREF_GPIO_NUM, + .pin_pclk = PCLK_GPIO_NUM, + + //EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode + .xclk_freq_hz = xclk_freq_hz, + .ledc_timer = LEDC_TIMER_0, + .ledc_channel = LEDC_CHANNEL_0, + + .pixel_format = pixel_format, //YUV422,GRAYSCALE,RGB565,JPEG + .frame_size = frame_size, //QQVGA-UXGAQQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. + + .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality + .fb_count = fb_count, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. + .grab_mode = CAMERA_GRAB_WHEN_EMPTY + }; + + //initialize the camera + esp_err_t ret = esp_camera_init(&camera_config); + + if (ESP_OK == ret && PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > size_bak) { + sensor_t *s = esp_camera_sensor_get(); + s->set_framesize(s, size_bak); + } + + return ret; +} + +static bool camera_test_fps(uint16_t times, float *fps, uint32_t *size) +{ + *fps = 0.0f; + *size = 0; + uint32_t s = 0; + uint32_t num = 0; + uint64_t total_time = esp_timer_get_time(); + for (size_t i = 0; i < times; i++) { + camera_fb_t *pic = esp_camera_fb_get(); + if (NULL == pic) { + ESP_LOGW(TAG, "fb get failed"); + return 0; + } else { + s += pic->len; + num++; + } + esp_camera_fb_return(pic); + } + total_time = esp_timer_get_time() - total_time; + if (num) { + *fps = num * 1000000.0f / total_time ; + *size = s / num; + } + return 1; +} + +static const char *get_cam_format_name(pixformat_t pixel_format) +{ + switch (pixel_format) { + case PIXFORMAT_JPEG: return "JPEG"; + case PIXFORMAT_RGB565: return "RGB565"; + case PIXFORMAT_RGB888: return "RGB888"; + case PIXFORMAT_YUV422: return "YUV422"; + default: + break; + } + return "UNKNOW"; +} + +static void printf_img_base64(const camera_fb_t *pic) +{ + uint8_t *outbuffer = NULL; + size_t outsize = 0; + if (PIXFORMAT_JPEG != pic->format) { + fmt2jpg(pic->buf, pic->width * pic->height * 2, pic->width, pic->height, pic->format, 50, &outbuffer, &outsize); + } else { + outbuffer = pic->buf; + outsize = pic->len; + } + + uint8_t *base64_buf = calloc(1, outsize * 4); + if (NULL != base64_buf) { + size_t out_len = 0; + mbedtls_base64_encode(base64_buf, outsize * 4, &out_len, outbuffer, outsize); + printf("%s\n", base64_buf); + free(base64_buf); + if (PIXFORMAT_JPEG != pic->format) { + free(outbuffer); + } + } else { + ESP_LOGE(TAG, "malloc for base64 buffer failed"); + } +} + +static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num) +{ + esp_err_t ret = ESP_OK; + //detect sensor information + TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); + sensor_t *s = esp_camera_sensor_get(); + camera_sensor_info_t *info = esp_camera_sensor_get_info(&s->id); + TEST_ASSERT_NOT_NULL(info); + TEST_ESP_OK(esp_camera_deinit()); + vTaskDelay(500 / portTICK_RATE_MS); + framesize_t max_size = info->max_size; + pixformat_t all_format[] = {PIXFORMAT_JPEG, PIXFORMAT_RGB565, PIXFORMAT_YUV422, }; + pixformat_t *format_s = &all_format[0]; + pixformat_t *format_e = &all_format[2]; + if (false == info->support_jpeg) { + format_s++; // skip jpeg + } + + struct fps_result { + float fps[FRAMESIZE_INVALID]; + uint32_t size[FRAMESIZE_INVALID]; + }; + struct fps_result results[3] = {0}; + + for (; format_s <= format_e; format_s++) { + for (size_t i = 0; i <= max_size; i++) { + ESP_LOGI(TAG, "\n\n===> Testing format:%s resolution: %d x %d <===", get_cam_format_name(*format_s), resolution[i].width, resolution[i].height); + ret = init_camera(xclk_freq, *format_s, i, 2, SIOD_GPIO_NUM, -1); + vTaskDelay(100 / portTICK_RATE_MS); + if (ESP_OK != ret) { + ESP_LOGW(TAG, "Testing init failed :-(, skip this item"); + vTaskDelay(500 / portTICK_RATE_MS); + continue; + } + camera_test_fps(pic_num, &results[format_s - all_format].fps[i], &results[format_s - all_format].size[i]); + TEST_ESP_OK(esp_camera_deinit()); + } + } + + printf("FPS Result\n"); + printf("resolution , JPEG fps, JPEG size, RGB565 fps, RGB565 size, YUV422 fps, YUV422 size \n"); + for (size_t i = 0; i <= max_size; i++) { + printf("%4d x %4d , %5.2f, %6d, %5.2f, %7d, %5.2f, %7d \n", + resolution[i].width, resolution[i].height, + results[0].fps[i], results[0].size[i], + results[1].fps[i], results[1].size[i], + results[2].fps[i], results[2].size[i]); + } + printf("----------------------------------------------------------------------------------------\n"); +} + +TEST_CASE("Camera driver init, deinit test", "[camera]") +{ + uint64_t t1 = esp_timer_get_time(); + TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); + uint64_t t2 = esp_timer_get_time(); + ESP_LOGI(TAG, "Camera init time %llu ms", (t2 - t1) / 1000); + + TEST_ESP_OK(esp_camera_deinit()); +} + +TEST_CASE("Camera driver take RGB565 picture test", "[camera]") +{ + TEST_ESP_OK(init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); + vTaskDelay(500 / portTICK_RATE_MS); + ESP_LOGI(TAG, "Taking picture..."); + camera_fb_t *pic = esp_camera_fb_get(); + if (pic) { + ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); + printf_img_base64(pic); + esp_camera_fb_return(pic); + } + + TEST_ESP_OK(esp_camera_deinit()); + TEST_ASSERT_NOT_NULL(pic); +} + +TEST_CASE("Camera driver take YUV422 picture test", "[camera]") +{ + TEST_ESP_OK(init_camera(10000000, PIXFORMAT_YUV422, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); + vTaskDelay(500 / portTICK_RATE_MS); + ESP_LOGI(TAG, "Taking picture..."); + camera_fb_t *pic = esp_camera_fb_get(); + if (pic) { + ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); + printf_img_base64(pic); + esp_camera_fb_return(pic); + } + + TEST_ESP_OK(esp_camera_deinit()); + TEST_ASSERT_NOT_NULL(pic); +} + +TEST_CASE("Camera driver take JPEG picture test", "[camera]") +{ + TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); + vTaskDelay(500 / portTICK_RATE_MS); + ESP_LOGI(TAG, "Taking picture..."); + camera_fb_t *pic = esp_camera_fb_get(); + if (pic) { + ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); + printf_img_base64(pic); + esp_camera_fb_return(pic); + } + + TEST_ESP_OK(esp_camera_deinit()); + TEST_ASSERT_NOT_NULL(pic); +} + +TEST_CASE("Camera driver performance test", "[camera]") +{ + camera_performance_test(20 * 1000000, 16); +} + + +static void print_rgb565_img(uint8_t *img, int width, int height) +{ + uint16_t *p = (uint16_t *)img; + const char temp2char[17] = "@MNHQ&#UJ*x7^i;."; + for (size_t j = 0; j < height; j++) { + for (size_t i = 0; i < width; i++) { + uint32_t c = p[j * width + i]; + uint8_t r = c >> 11; + uint8_t g = (c >> 6) & 0x1f; + uint8_t b = c & 0x1f; + c = (r + g + b) / 3; + c >>= 1; + printf("%c", temp2char[15 - c]); + } + printf("\n"); + } +} + +static void print_rgb888_img(uint8_t *img, int width, int height) +{ + uint8_t *p = (uint8_t *)img; + const char temp2char[17] = "@MNHQ&#UJ*x7^i;."; + for (size_t j = 0; j < height; j++) { + for (size_t i = 0; i < width; i++) { + uint8_t *c = p + 3 * (j * width + i); + uint8_t r = *c++; + uint8_t g = *c++; + uint8_t b = *c; + uint32_t v = (r + g + b) / 3; + v >>= 4; + printf("%c", temp2char[15 - v]); + } + printf("\n"); + } +} + +static void tjpgd_decode_rgb565(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer) +{ + jpg2rgb565(mjpegbuffer, size, outbuffer, JPG_SCALE_NONE); +} + +static void tjpgd_decode_rgb888(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer) +{ + fmt2rgb888(mjpegbuffer, size, PIXFORMAT_JPEG, outbuffer); +} + +typedef enum { + DECODE_RGB565, + DECODE_RGB888, +} decode_type_t; + +static const decode_func_t g_decode_func[2][2] = { + {tjpgd_decode_rgb565,}, + {tjpgd_decode_rgb888,}, +}; + + +static float jpg_decode_test(uint8_t decoder_index, decode_type_t type, const uint8_t *jpg, uint32_t length, uint32_t img_w, uint32_t img_h, uint32_t times) +{ + uint8_t *jpg_buf = malloc(length); + if (NULL == jpg_buf) { + ESP_LOGE(TAG, "malloc for jpg buffer failed"); + return 0; + } + memcpy(jpg_buf, jpg, length); + + uint8_t *rgb_buf = heap_caps_malloc(img_w * img_h * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (NULL == rgb_buf) { + free(jpg_buf); + ESP_LOGE(TAG, "malloc for rgb buffer failed"); + return 0; + } + decode_func_t decode = g_decode_func[type][decoder_index]; + decode(jpg_buf, length, rgb_buf); + if (DECODE_RGB565 == type) { + ESP_LOGI(TAG, "jpeg decode to rgb565"); + print_rgb565_img(rgb_buf, img_w, img_h); + } else { + ESP_LOGI(TAG, "jpeg decode to rgb888"); + print_rgb888_img(rgb_buf, img_w, img_h); + } + + uint64_t t_decode[times]; + for (size_t i = 0; i < times; i++) { + uint64_t t1 = esp_timer_get_time(); + decode(jpg_buf, length, rgb_buf); + t_decode[i] = esp_timer_get_time() - t1; + } + + printf("resolution , t \n"); + uint64_t t_total = 0; + for (size_t i = 0; i < times; i++) { + t_total += t_decode[i]; + float t = t_decode[i] / 1000.0f; + printf("%4d x %4d , %5.2f ms \n", img_w, img_h, t); + } + + float fps = times / (t_total / 1000000.0f); + printf("Decode FPS Result\n"); + printf("resolution , fps \n"); + printf("%4d x %4d , %5.2f \n", img_w, img_h, fps); + + free(jpg_buf); + heap_caps_free(rgb_buf); + return fps; +} + +static void img_jpeg_decode_test(uint16_t pic_index, uint16_t lib_index) +{ + extern const uint8_t img1_start[] asm("_binary_testimg_jpeg_start"); + extern const uint8_t img1_end[] asm("_binary_testimg_jpeg_end"); + extern const uint8_t img2_start[] asm("_binary_test_inside_jpeg_start"); + extern const uint8_t img2_end[] asm("_binary_test_inside_jpeg_end"); + extern const uint8_t img3_start[] asm("_binary_test_outside_jpeg_start"); + extern const uint8_t img3_end[] asm("_binary_test_outside_jpeg_end"); + + struct img_t { + const uint8_t *buf; + uint32_t length; + uint16_t w, h; + }; + struct img_t imgs[3] = { + { + .buf = img1_start, + .length = img1_end - img1_start, + .w = 227, + .h = 149, + }, + { + .buf = img2_start, + .length = img2_end - img2_start, + .w = 320, + .h = 240, + }, + { + .buf = img3_start, + .length = img3_end - img3_start, + .w = 480, + .h = 320, + }, + }; + + ESP_LOGI(TAG, "pic_index:%d", pic_index); + ESP_LOGI(TAG, "lib_index:%d", lib_index); + jpg_decode_test(lib_index, DECODE_RGB565, imgs[pic_index].buf, imgs[pic_index].length, imgs[pic_index].w, imgs[pic_index].h, 16); +} + +/** + * @brief i2c master initialization + */ +static esp_err_t i2c_master_init(int i2c_port) +{ + i2c_config_t conf = { + .mode = I2C_MODE_MASTER, + .sda_io_num = I2C_MASTER_SDA_IO, + .scl_io_num = I2C_MASTER_SCL_IO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = I2C_MASTER_FREQ_HZ, + }; + + i2c_param_config(i2c_port, &conf); + + return i2c_driver_install(i2c_port, conf.mode, 0, 0, 0); +} + +TEST_CASE("Conversions image 227x149 jpeg decode test", "[camera]") +{ + img_jpeg_decode_test(0, 0); +} + +TEST_CASE("Conversions image 320x240 jpeg decode test", "[camera]") +{ + img_jpeg_decode_test(1, 0); +} + +TEST_CASE("Conversions image 480x320 jpeg decode test", "[camera]") +{ + img_jpeg_decode_test(2, 0); +} + +TEST_CASE("Camera driver uses an i2c port initialized by other devices test", "[camera]") +{ + TEST_ESP_OK(i2c_master_init(I2C_MASTER_NUM)); + TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, -1, I2C_MASTER_NUM)); + vTaskDelay(500 / portTICK_RATE_MS); + TEST_ESP_OK(esp_camera_deinit()); + TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM)); +} diff --git a/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt new file mode 100644 index 0000000000..b779e24d3c --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt @@ -0,0 +1,6 @@ +idf_component_register( SRCS + app_peripherals.c + app_main.c + INCLUDE_DIRS + include + ) \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c new file mode 100644 index 0000000000..ec8779fd77 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "app_peripherals.h" +#include "quirc.h" + +static const char *TAG = "APP_CODE_SCANNER"; + +static void decode_task() +{ + if(ESP_OK != app_camera_init()) { + vTaskDelete(NULL); + return; + } + + camera_fb_t *fb = NULL; + + // Initializing the quirc handle + struct quirc *q = quirc_new(); + if (!q) { + ESP_LOGE(TAG,"Failed to allocate memory\n"); + exit(1); + } + + + // Get image size through fb parameters + fb = esp_camera_fb_get(); + if(fb == NULL){ + ESP_LOGI(TAG, "camera get failed\n"); + } + + uint16_t p_width = fb->width; + uint16_t p_height = fb->height; + + + if (quirc_resize(q, p_width,p_height) < 0) { + ESP_LOGE(TAG,"Failed to allocate video memory\n"); + exit(1); + } + + struct quirc_code code; + struct quirc_data data; + quirc_decode_error_t err; + uint16_t num_codes; + + while (1) + { + fb = esp_camera_fb_get(); + if(fb == NULL){ + ESP_LOGI(TAG, "camera get failed\n"); + continue; + } + // Decode Progress + + memcpy(quirc_begin(q, NULL, NULL), fb->buf, fb->len); + quirc_end(q); + + num_codes = quirc_count(q); + for (uint16_t i = 0; i < num_codes; i++) { + + quirc_extract(q, i, &code); + /* Decoding stage */ + err = quirc_decode(&code, &data); + if (err) + printf("%d/%d] DECODE FAILED: %s\n", i,num_codes,quirc_strerror(err)); + else + printf("%d/%d]Data: %s\n",i,num_codes,data.payload); + } + + esp_camera_fb_return(fb); + vTaskDelay(10 / portTICK_PERIOD_MS); + } + + quirc_destroy(q); +} + + +void app_main() +{ + xTaskCreatePinnedToCore(decode_task, TAG, 40 * 1024, NULL, 6, NULL, 0); +} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/app_peripherals.c b/quirc/examples/esp-eye-qrcode/main/app_peripherals.c new file mode 100644 index 0000000000..734c73cfb1 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/main/app_peripherals.c @@ -0,0 +1,65 @@ +#include "app_peripherals.h" +#include "esp_log.h" +#include "esp_system.h" + +static const char *TAG = "app_peripherals"; + +esp_err_t app_camera_init() +{ + ESP_LOGI(TAG, "Camera module is %s", CAMERA_MODULE_NAME); + + camera_config_t config; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.pin_d0 = CAMERA_PIN_D0; + config.pin_d1 = CAMERA_PIN_D1; + config.pin_d2 = CAMERA_PIN_D2; + config.pin_d3 = CAMERA_PIN_D3; + config.pin_d4 = CAMERA_PIN_D4; + config.pin_d5 = CAMERA_PIN_D5; + config.pin_d6 = CAMERA_PIN_D6; + config.pin_d7 = CAMERA_PIN_D7; + config.pin_xclk = CAMERA_PIN_XCLK; + config.pin_pclk = CAMERA_PIN_PCLK; + config.pin_vsync = CAMERA_PIN_VSYNC; + config.pin_href = CAMERA_PIN_HREF; + config.pin_sccb_sda = CAMERA_PIN_SIOD; + config.pin_sccb_scl = CAMERA_PIN_SIOC; + config.pin_pwdn = CAMERA_PIN_PWDN; + config.pin_reset = CAMERA_PIN_RESET; + config.xclk_freq_hz = XCLK_FREQ_HZ; + config.pixel_format = CAMERA_PIXFORMAT; + config.frame_size = CAMERA_FRAME_SIZE; + config.jpeg_quality = 5; + config.fb_count = CAMERA_FB_COUNT; + config.fb_location = CAMERA_FB_IN_PSRAM; + config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; + + // camera init + esp_err_t err = esp_camera_init(&config); + if (err != ESP_OK) + { + ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); + return ESP_FAIL; + } + + sensor_t *s = esp_camera_sensor_get(); + if (s->id.PID == OV3660_PID || s->id.PID == OV2640_PID) + s->set_vflip(s, 1); //flip it back + else if (s->id.PID == GC0308_PID){ + s->set_hmirror(s, 0); + } + else if (s->id.PID == GC032A_PID){ + s->set_vflip(s, 1); + } + + if (s->id.PID == OV3660_PID) + { + s->set_brightness(s, 2); + s->set_contrast(s, 3); + } + + return ESP_OK; +} + + diff --git a/quirc/examples/esp-eye-qrcode/main/idf_component.yml b/quirc/examples/esp-eye-qrcode/main/idf_component.yml new file mode 100644 index 0000000000..03f3c26f84 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/main/idf_component.yml @@ -0,0 +1,10 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/quirc: + version: "^1.2.0" + # This line define the local path of the component because this + # example is part of the component. This line is optional. + override_path: "../../.." + ## Required IDF version + idf: + version: ">=4.3.0" \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h new file mode 100644 index 0000000000..e7fe3df17d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h @@ -0,0 +1,248 @@ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" + +#include "esp_camera.h" + +#define CONFIG_CAMERA_MODULE_ESP_EYE 1 +// camera pins +#if CONFIG_CAMERA_MODULE_WROVER_KIT +#define CAMERA_MODULE_NAME "Wrover Kit" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 +#define CAMERA_PIN_XCLK 21 +#define CAMERA_PIN_SIOD 26 +#define CAMERA_PIN_SIOC 27 + +#define CAMERA_PIN_D7 35 +#define CAMERA_PIN_D6 34 +#define CAMERA_PIN_D5 39 +#define CAMERA_PIN_D4 36 +#define CAMERA_PIN_D3 19 +#define CAMERA_PIN_D2 18 +#define CAMERA_PIN_D1 5 +#define CAMERA_PIN_D0 4 +#define CAMERA_PIN_VSYNC 25 +#define CAMERA_PIN_HREF 23 +#define CAMERA_PIN_PCLK 22 + +#elif CONFIG_CAMERA_MODULE_ESP_EYE +#define CAMERA_MODULE_NAME "ESP-EYE" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 +#define CAMERA_PIN_XCLK 4 +#define CAMERA_PIN_SIOD 18 +#define CAMERA_PIN_SIOC 23 + +#define CAMERA_PIN_D7 36 +#define CAMERA_PIN_D6 37 +#define CAMERA_PIN_D5 38 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 35 +#define CAMERA_PIN_D2 14 +#define CAMERA_PIN_D1 13 +#define CAMERA_PIN_D0 34 +#define CAMERA_PIN_VSYNC 5 +#define CAMERA_PIN_HREF 27 +#define CAMERA_PIN_PCLK 25 + +#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA +#define CAMERA_MODULE_NAME "ESP-S2-KALUGA" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 +#define CAMERA_PIN_XCLK 1 +#define CAMERA_PIN_SIOD 8 +#define CAMERA_PIN_SIOC 7 + +#define CAMERA_PIN_D7 38 +#define CAMERA_PIN_D6 21 +#define CAMERA_PIN_D5 40 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 42 +#define CAMERA_PIN_D2 41 +#define CAMERA_PIN_D1 37 +#define CAMERA_PIN_D0 36 +#define CAMERA_PIN_VSYNC 2 +#define CAMERA_PIN_HREF 3 +#define CAMERA_PIN_PCLK 33 + +#elif CONFIG_CAMERA_MODULE_ESP_S3_EYE +#define CAMERA_MODULE_NAME "ESP-S3-EYE" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET -1 + +#define CAMERA_PIN_VSYNC 6 +#define CAMERA_PIN_HREF 7 +#define CAMERA_PIN_PCLK 13 +#define CAMERA_PIN_XCLK 15 + +#define CAMERA_PIN_SIOD 4 +#define CAMERA_PIN_SIOC 5 + +#define CAMERA_PIN_D0 11 +#define CAMERA_PIN_D1 9 +#define CAMERA_PIN_D2 8 +#define CAMERA_PIN_D3 10 +#define CAMERA_PIN_D4 12 +#define CAMERA_PIN_D5 18 +#define CAMERA_PIN_D6 17 +#define CAMERA_PIN_D7 16 + +#elif CONFIG_CAMERA_MODULE_ESP32_CAM_BOARD +#define CAMERA_MODULE_NAME "ESP-DEVCAM" +#define CAMERA_PIN_PWDN 32 +#define CAMERA_PIN_RESET 33 + +#define CAMERA_PIN_XCLK 4 +#define CAMERA_PIN_SIOD 18 +#define CAMERA_PIN_SIOC 23 + +#define CAMERA_PIN_D7 36 +#define CAMERA_PIN_D6 19 +#define CAMERA_PIN_D5 21 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 35 +#define CAMERA_PIN_D2 14 +#define CAMERA_PIN_D1 13 +#define CAMERA_PIN_D0 34 +#define CAMERA_PIN_VSYNC 5 +#define CAMERA_PIN_HREF 27 +#define CAMERA_PIN_PCLK 25 + +#elif CONFIG_CAMERA_MODULE_M5STACK_PSRAM +#define CAMERA_MODULE_NAME "M5STACK-PSRAM" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET 15 + +#define CAMERA_PIN_XCLK 27 +#define CAMERA_PIN_SIOD 25 +#define CAMERA_PIN_SIOC 23 + +#define CAMERA_PIN_D7 19 +#define CAMERA_PIN_D6 36 +#define CAMERA_PIN_D5 18 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 5 +#define CAMERA_PIN_D2 34 +#define CAMERA_PIN_D1 35 +#define CAMERA_PIN_D0 32 +#define CAMERA_PIN_VSYNC 22 +#define CAMERA_PIN_HREF 26 +#define CAMERA_PIN_PCLK 21 + +#elif CONFIG_CAMERA_MODULE_M5STACK_WIDE +#define CAMERA_MODULE_NAME "M5STACK-WIDE" +#define CAMERA_PIN_PWDN -1 +#define CAMERA_PIN_RESET 15 +#define CAMERA_PIN_XCLK 27 +#define CAMERA_PIN_SIOD 22 +#define CAMERA_PIN_SIOC 23 + +#define CAMERA_PIN_D7 19 +#define CAMERA_PIN_D6 36 +#define CAMERA_PIN_D5 18 +#define CAMERA_PIN_D4 39 +#define CAMERA_PIN_D3 5 +#define CAMERA_PIN_D2 34 +#define CAMERA_PIN_D1 35 +#define CAMERA_PIN_D0 32 +#define CAMERA_PIN_VSYNC 25 +#define CAMERA_PIN_HREF 26 +#define CAMERA_PIN_PCLK 21 + +#elif CONFIG_CAMERA_MODULE_AI_THINKER +#define CAMERA_MODULE_NAME "AI-THINKER" +#define CAMERA_PIN_PWDN 32 +#define CAMERA_PIN_RESET -1 +#define CAMERA_PIN_XCLK 0 +#define CAMERA_PIN_SIOD 26 +#define CAMERA_PIN_SIOC 27 + +#define CAMERA_PIN_D7 35 +#define CAMERA_PIN_D6 34 +#define CAMERA_PIN_D5 39 +#define CAMERA_PIN_D4 36 +#define CAMERA_PIN_D3 21 +#define CAMERA_PIN_D2 19 +#define CAMERA_PIN_D1 18 +#define CAMERA_PIN_D0 5 +#define CAMERA_PIN_VSYNC 25 +#define CAMERA_PIN_HREF 23 +#define CAMERA_PIN_PCLK 22 + +#elif CONFIG_CAMERA_MODULE_CUSTOM +#define CAMERA_MODULE_NAME "CUSTOM" +#define CAMERA_PIN_PWDN CONFIG_CAMERA_PIN_PWDN +#define CAMERA_PIN_RESET CONFIG_CAMERA_PIN_RESET +#define CAMERA_PIN_XCLK CONFIG_CAMERA_PIN_XCLK +#define CAMERA_PIN_SIOD CONFIG_CAMERA_PIN_SIOD +#define CAMERA_PIN_SIOC CONFIG_CAMERA_PIN_SIOC + +#define CAMERA_PIN_D7 CONFIG_CAMERA_PIN_Y9 +#define CAMERA_PIN_D6 CONFIG_CAMERA_PIN_Y8 +#define CAMERA_PIN_D5 CONFIG_CAMERA_PIN_Y7 +#define CAMERA_PIN_D4 CONFIG_CAMERA_PIN_Y6 +#define CAMERA_PIN_D3 CONFIG_CAMERA_PIN_Y5 +#define CAMERA_PIN_D2 CONFIG_CAMERA_PIN_Y4 +#define CAMERA_PIN_D1 CONFIG_CAMERA_PIN_Y3 +#define CAMERA_PIN_D0 CONFIG_CAMERA_PIN_Y2 +#define CAMERA_PIN_VSYNC CONFIG_CAMERA_PIN_VSYNC +#define CAMERA_PIN_HREF CONFIG_CAMERA_PIN_HREF +#define CAMERA_PIN_PCLK CONFIG_CAMERA_PIN_PCLK +#endif + +#define XCLK_FREQ_HZ 20000000 +#define CAMERA_PIXFORMAT PIXFORMAT_GRAYSCALE +#define CAMERA_FRAME_SIZE FRAMESIZE_240X240 +#define CAMERA_FB_COUNT 2 + + + +// lcd pins and setting +#if CONFIG_CAMERA_MODULE_ESP_S3_EYE +#define LCD_CONTROLLER SCREEN_CONTROLLER_ST7789 + +#define LCD_MOSI 47 +#define LCD_MISO -1 +#define LCD_SCLK 21 +#define LCD_CS 44 +#define LCD_DC 43 +#define LCD_RST -1 +#define LCD_BCKL 48 + +#define LCD_WIDTH 240 +#define LCD_HEIGHT 240 +#define LCD_ROTATE 0 +#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA +#define LCD_CONTROLLER SCREEN_CONTROLLER_ST7789 + +#define LCD_MOSI 9 +#define LCD_MISO -1 +#define LCD_SCLK 15 +#define LCD_CS 11 +#define LCD_DC 13 +#define LCD_RST 16 +#define LCD_BCKL 6 + +// LCD display width and height +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +#define LCD_ROTATE SCR_SWAP_XY|SCR_MIRROR_X +#endif + + + + +#ifdef __cplusplus +extern "C" +{ +#endif + + esp_err_t app_camera_init(); + esp_err_t app_lcd_init(); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults new file mode 100644 index 0000000000..d53e9f466d --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y + +CONFIG_SPIRAM_SPEED_80M=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 new file mode 100644 index 0000000000..ecc2d87564 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 @@ -0,0 +1,4 @@ +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_SPIRAM_SUPPORT=y + +CONFIG_CAMERA_MODULE_ESP_EYE=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 new file mode 100644 index 0000000000..93fe3e9675 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 @@ -0,0 +1,8 @@ +CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S2_SPIRAM_SUPPORT=y + +CONFIG_ESP32S2_DATA_CACHE_16KB=y +ESP32S2_DATA_CACHE_LINE_32B=y + +CONFIG_CAMERA_MODULE_ESP_S2_KALUGA=y +CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 new file mode 100644 index 0000000000..b95f661535 --- /dev/null +++ b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 @@ -0,0 +1,13 @@ +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y + +CONFIG_ESP32S3_DATA_CACHE_64KB=y +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y + +CONFIG_CAMERA_MODULE_ESP_S3_EYE=y +CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y +CONFIG_ESPTOOLPY_NO_STUB=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y + +CONFIG_SPIRAM_MODE_OCT=y From a7e61d9b02a7e211df10cf210e31e5d0b44cdfb7 Mon Sep 17 00:00:00 2001 From: fbez Date: Tue, 19 Sep 2023 16:07:53 +0200 Subject: [PATCH 02/14] Changed output string, updated readme --- quirc/examples/esp-eye-qrcode/README.md | 33 +- .../esp32-camera/.github/workflows/build.yml | 57 - .../esp32-camera/.github/workflows/stale.yml | 27 - .../.github/workflows/upload_component.yml | 19 - .../components/esp32-camera/.gitignore | 6 - .../components/esp32-camera/CMakeLists.txt | 98 -- .../components/esp32-camera/Kconfig | 213 ---- .../components/esp32-camera/LICENSE | 202 --- .../components/esp32-camera/README.md | 373 ------ .../components/esp32-camera/component.mk | 4 - .../esp32-camera/conversions/esp_jpg_decode.c | 134 -- .../conversions/include/esp_jpg_decode.h | 43 - .../conversions/include/img_converters.h | 130 -- .../esp32-camera/conversions/jpge.cpp | 728 ----------- .../conversions/private_include/jpge.h | 142 --- .../conversions/private_include/yuv.h | 29 - .../esp32-camera/conversions/to_bmp.c | 397 ------ .../esp32-camera/conversions/to_jpg.cpp | 235 ---- .../components/esp32-camera/conversions/yuv.c | 298 ----- .../components/esp32-camera/driver/cam_hal.c | 514 -------- .../esp32-camera/driver/esp_camera.c | 486 ------- .../esp32-camera/driver/include/esp_camera.h | 251 ---- .../esp32-camera/driver/include/sensor.h | 261 ---- .../driver/private_include/cam_hal.h | 62 - .../driver/private_include/sccb.h | 22 - .../driver/private_include/xclk.h | 10 - .../components/esp32-camera/driver/sccb.c | 260 ---- .../components/esp32-camera/driver/sensor.c | 57 - .../esp32-camera/examples/CMakeLists.txt | 9 - .../components/esp32-camera/examples/Makefile | 11 - .../esp32-camera/examples/main/CMakeLists.txt | 3 - .../esp32-camera/examples/main/component.mk | 5 - .../esp32-camera/examples/main/take_picture.c | 167 --- .../esp32-camera/examples/sdkconfig.defaults | 17 - .../components/esp32-camera/idf_component.yml | 2 - .../components/esp32-camera/library.json | 26 - .../components/esp32-camera/sensors/bf20a6.c | 410 ------ .../components/esp32-camera/sensors/bf3005.c | 541 -------- .../components/esp32-camera/sensors/gc0308.c | 468 ------- .../components/esp32-camera/sensors/gc032a.c | 391 ------ .../components/esp32-camera/sensors/gc2145.c | 477 ------- .../components/esp32-camera/sensors/nt99141.c | 1022 --------------- .../components/esp32-camera/sensors/ov2640.c | 612 --------- .../components/esp32-camera/sensors/ov3660.c | 1053 --------------- .../components/esp32-camera/sensors/ov5640.c | 1130 ----------------- .../components/esp32-camera/sensors/ov7670.c | 457 ------- .../components/esp32-camera/sensors/ov7725.c | 575 --------- .../sensors/private_include/bf20a6.h | 27 - .../sensors/private_include/bf20a6_regs.h | 12 - .../sensors/private_include/bf20a6_settings.h | 158 --- .../sensors/private_include/bf3005.h | 33 - .../sensors/private_include/bf3005_regs.h | 337 ----- .../sensors/private_include/gc0308.h | 31 - .../sensors/private_include/gc0308_regs.h | 25 - .../sensors/private_include/gc0308_settings.h | 258 ---- .../sensors/private_include/gc032a.h | 31 - .../sensors/private_include/gc032a_regs.h | 82 -- .../sensors/private_include/gc032a_settings.h | 401 ------ .../sensors/private_include/gc2145.h | 27 - .../sensors/private_include/gc2145_regs.h | 85 -- .../sensors/private_include/gc2145_settings.h | 719 ----------- .../sensors/private_include/nt99141.h | 34 - .../sensors/private_include/nt99141_regs.h | 211 --- .../private_include/nt99141_settings.h | 825 ------------ .../sensors/private_include/ov2640.h | 32 - .../sensors/private_include/ov2640_regs.h | 216 ---- .../sensors/private_include/ov2640_settings.h | 485 ------- .../sensors/private_include/ov3660.h | 34 - .../sensors/private_include/ov3660_regs.h | 211 --- .../sensors/private_include/ov3660_settings.h | 318 ----- .../sensors/private_include/ov5640.h | 27 - .../sensors/private_include/ov5640_regs.h | 213 ---- .../sensors/private_include/ov5640_settings.h | 335 ----- .../sensors/private_include/ov7670.h | 33 - .../sensors/private_include/ov7670_regs.h | 354 ------ .../sensors/private_include/ov7725.h | 33 - .../sensors/private_include/ov7725_regs.h | 335 ----- .../sensors/private_include/sc030iot.h | 31 - .../private_include/sc030iot_settings.h | 491 ------- .../sensors/private_include/sc031gs.h | 31 - .../private_include/sc031gs_settings.h | 202 --- .../sensors/private_include/sc101iot.h | 31 - .../private_include/sc101iot_settings.h | 257 ---- .../esp32-camera/sensors/sc030iot.c | 335 ----- .../components/esp32-camera/sensors/sc031gs.c | 346 ----- .../esp32-camera/sensors/sc101iot.c | 342 ----- .../esp32-camera/target/esp32/ll_cam.c | 539 -------- .../esp32-camera/target/esp32s2/ll_cam.c | 414 ------ .../target/esp32s2/private_include/tjpgd.h | 99 -- .../esp32-camera/target/esp32s3/ll_cam.c | 538 -------- .../esp32-camera/target/jpeg_include/tjpgd.h | 99 -- .../target/private_include/ll_cam.h | 147 --- .../components/esp32-camera/target/tjpgd.c | 970 -------------- .../components/esp32-camera/target/xclk.c | 72 -- .../esp32-camera/test/CMakeLists.txt | 4 - .../components/esp32-camera/test/component.mk | 8 - .../test/pictures/test_inside.jpeg | Bin 18832 -> 0 bytes .../test/pictures/test_outside.jpeg | Bin 81744 -> 0 bytes .../esp32-camera/test/pictures/testimg.jpeg | Bin 5764 -> 0 bytes .../esp32-camera/test/test_camera.c | 535 -------- quirc/examples/esp-eye-qrcode/main/app_main.c | 4 +- .../esp-eye-qrcode/main/idf_component.yml | 1 + 102 files changed, 7 insertions(+), 23878 deletions(-) delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/testimg.jpeg delete mode 100644 quirc/examples/esp-eye-qrcode/components/esp32-camera/test/test_camera.c diff --git a/quirc/examples/esp-eye-qrcode/README.md b/quirc/examples/esp-eye-qrcode/README.md index c53eca8f79..9fa021bb89 100644 --- a/quirc/examples/esp-eye-qrcode/README.md +++ b/quirc/examples/esp-eye-qrcode/README.md @@ -1,35 +1,10 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | - -# _Sample project_ - -(See the README.md file in the upper level 'examples' directory for more information about examples.) - -This is the simplest buildable example. The example is used by command `idf.py create-project` -that copies the project to user specified path and set it's name. For more information follow the [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project) +| x | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +# ESP-EYE QR-CODE with QUIRC +In this example the esp-eye takes a picture every few ms and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). ## How to use example -We encourage the users to use the example as a template for the new projects. -A recommended way is to follow the instructions on a [docs page](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#start-a-new-project). - -## Example folder contents - -The project **sample_project** contains one source file in C language [main.c](main/main.c). The file is located in folder [main](main). - -ESP-IDF projects are built using CMake. The project build configuration is contained in `CMakeLists.txt` -files that provide set of directives and instructions describing the project's source files and targets -(executable, library, or both). - -Below is short explanation of remaining files in the project folder. -``` -├── CMakeLists.txt -├── main -│   ├── CMakeLists.txt -│   └── main.c -└── README.md This is the file you are currently reading -``` -Additionally, the sample project contains Makefile and component.mk files, used for the legacy Make based build system. -They are not used or needed when building with CMake and idf.py. +Build and flash on an esp-eye. It may work with small changes also on ESP32-CAM and ESP32-S3-EYE. diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml deleted file mode 100644 index bd35672a7d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/build.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Build examples -on: - push: - branches: - - master - pull_request: - -jobs: - build-examples: - name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} - runs-on: ubuntu-latest - strategy: - matrix: - idf_ver: ["release-v4.1", "release-v4.2", "release-v4.3"] - idf_target: ["esp32", "esp32s2"] - exclude: - - idf_ver: "release-v4.1" - idf_target: esp32s2 # ESP32S2 support started with version 4.2 - container: espressif/idf:${{ matrix.idf_ver }} - steps: - - uses: actions/checkout@v1 - with: - submodules: 'true' - - name: esp-idf build - env: - IDF_TARGET: ${{ matrix.idf_target }} - shell: bash - working-directory: examples - run: | - . ${IDF_PATH}/export.sh - idf.py build - build-examples-pedantic: - name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} - runs-on: ubuntu-latest - strategy: - matrix: - idf_ver: ["release-v4.4", "release-v5.0", "release-v5.1", "latest"] - idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3"] - exclude: - - idf_ver: "release-v4.4" - idf_target: esp32c2 # ESP32C2 support started with version 5.0 - container: espressif/idf:${{ matrix.idf_ver }} - steps: - - uses: actions/checkout@v1 - with: - submodules: 'true' - - name: esp-idf build - env: - IDF_TARGET: ${{ matrix.idf_target }} - shell: bash - working-directory: examples - run: | - . ${IDF_PATH}/export.sh - export PEDANTIC_FLAGS="-DIDF_CI_BUILD -Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" - export EXTRA_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" - export EXTRA_CXXFLAGS="${PEDANTIC_FLAGS}" - idf.py build diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml deleted file mode 100644 index a601f26337..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/stale.yml +++ /dev/null @@ -1,27 +0,0 @@ -# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. -# -# You can adjust the behavior by modifying this file. -# For more information, see: -# https://github.com/actions/stale -name: Mark stale issues and pull requests - -on: - schedule: - - cron: '20 9 * * *' - -jobs: - stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v3 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'This issue appears to be stale. Please close it if its no longer valid.' - stale-pr-message: 'This pull request appears to be stale. Please close it if its no longer valid.' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml deleted file mode 100644 index f550e696de..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.github/workflows/upload_component.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Push component to https://components.espressif.com -on: - push: - tags: - - v* -jobs: - upload_components: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - with: - submodules: "recursive" - - name: Upload component to the component registry - uses: espressif/github-actions/upload_components@master - with: - name: "esp32-camera" - namespace: "espressif" - version: ${{ github.ref_name }} - api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore b/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore deleted file mode 100644 index f39d5fda1b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -*.DS_Store -.vscode -**/build -**/sdkconfig -**/sdkconfig.old -**/dependencies.lock \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt deleted file mode 100644 index 65e46aef60..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/CMakeLists.txt +++ /dev/null @@ -1,98 +0,0 @@ -# get IDF version for comparison -set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") - -# set conversion sources -set(COMPONENT_SRCS - conversions/yuv.c - conversions/to_jpg.cpp - conversions/to_bmp.c - conversions/jpge.cpp - conversions/esp_jpg_decode.c - ) - -set(COMPONENT_PRIV_INCLUDEDIRS - conversions/private_include - ) - -set(COMPONENT_ADD_INCLUDEDIRS - driver/include - conversions/include - ) - -set(COMPONENT_REQUIRES driver) - -# set driver sources only for supported platforms -if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") - list(APPEND COMPONENT_SRCS - driver/esp_camera.c - driver/cam_hal.c - driver/sccb.c - driver/sensor.c - sensors/ov2640.c - sensors/ov3660.c - sensors/ov5640.c - sensors/ov7725.c - sensors/ov7670.c - sensors/nt99141.c - sensors/gc0308.c - sensors/gc2145.c - sensors/gc032a.c - sensors/bf3005.c - sensors/bf20a6.c - sensors/sc101iot.c - sensors/sc030iot.c - sensors/sc031gs.c - ) - - list(APPEND COMPONENT_PRIV_INCLUDEDIRS - driver/private_include - sensors/private_include - target/private_include - ) - - if(IDF_TARGET STREQUAL "esp32") - list(APPEND COMPONENT_SRCS - target/xclk.c - target/esp32/ll_cam.c - ) - endif() - - if(IDF_TARGET STREQUAL "esp32s2") - list(APPEND COMPONENT_SRCS - target/xclk.c - target/esp32s2/ll_cam.c - target/tjpgd.c - ) - - list(APPEND COMPONENT_PRIV_INCLUDEDIRS - target/esp32s2/private_include - ) - endif() - - if(IDF_TARGET STREQUAL "esp32s3") - list(APPEND COMPONENT_SRCS - target/esp32s3/ll_cam.c - ) - endif() - - set(COMPONENT_PRIV_REQUIRES freertos nvs_flash) - - set(min_version_for_esp_timer "4.2") - if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer) - list(APPEND COMPONENT_PRIV_REQUIRES esp_timer) - endif() - -endif() - -# CONFIG_ESP_ROM_HAS_JPEG_DECODE is available from IDF v4.4 but -# previous IDF supported chips already support JPEG decoder, hence okay to use this -if(idf_version VERSION_GREATER_EQUAL "4.4" AND NOT CONFIG_ESP_ROM_HAS_JPEG_DECODE) - list(APPEND COMPONENT_SRCS - target/tjpgd.c - ) - list(APPEND COMPONENT_PRIV_INCLUDEDIRS - target/jpeg_include/ - ) -endif() - -register_component() diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig b/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig deleted file mode 100644 index 2632c8235f..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/Kconfig +++ /dev/null @@ -1,213 +0,0 @@ -menu "Camera configuration" - - config OV7670_SUPPORT - bool "Support OV7670 VGA" - default y - help - Enable this option if you want to use the OV7670. - Disable this option to save memory. - - config OV7725_SUPPORT - bool "Support OV7725 VGA" - default y - help - Enable this option if you want to use the OV7725. - Disable this option to save memory. - - config NT99141_SUPPORT - bool "Support NT99141 HD" - default y - help - Enable this option if you want to use the NT99141. - Disable this option to save memory. - - config OV2640_SUPPORT - bool "Support OV2640 2MP" - default y - help - Enable this option if you want to use the OV2640. - Disable this option to save memory. - - config OV3660_SUPPORT - bool "Support OV3660 3MP" - default y - help - Enable this option if you want to use the OV3360. - Disable this option to save memory. - - config OV5640_SUPPORT - bool "Support OV5640 5MP" - default y - help - Enable this option if you want to use the OV5640. - Disable this option to save memory. - - config GC2145_SUPPORT - bool "Support GC2145 2MP" - default y - help - Enable this option if you want to use the GC2145. - Disable this option to save memory. - - config GC032A_SUPPORT - bool "Support GC032A VGA" - default y - help - Enable this option if you want to use the GC032A. - Disable this option to save memory. - - config GC0308_SUPPORT - bool "Support GC0308 VGA" - default y - help - Enable this option if you want to use the GC0308. - Disable this option to save memory. - - config BF3005_SUPPORT - bool "Support BF3005(BYD3005) VGA" - default y - help - Enable this option if you want to use the BF3005. - Disable this option to save memory. - - config BF20A6_SUPPORT - bool "Support BF20A6(BYD20A6) VGA" - default y - help - Enable this option if you want to use the BF20A6. - Disable this option to save memory. - - config SC101IOT_SUPPORT - bool "Support SC101IOT HD" - default n - help - Enable this option if you want to use the SC101IOT. - Disable this option to save memory. - - choice SC101_REGS_SELECT - prompt "SC101iot default regs" - default SC101IOT_720P_15FPS_ENABLED - depends on SC101IOT_SUPPORT - help - Currently SC010iot has several register sets available. - Select the one that matches your needs. - - config SC101IOT_720P_15FPS_ENABLED - bool "xclk20M_720p_15fps" - help - Select this option means that when xclk is 20M, the frame rate is 15fps at 720p resolution. - config SC101IOT_VGA_25FPS_ENABLED - bool "xclk20M_VGA_25fps" - help - Select this option means that when xclk is 20M, the frame rate is 25fps at VGA resolution. - endchoice - - config SC030IOT_SUPPORT - bool "Support SC030IOT VGA" - default y - help - Enable this option if you want to use the SC030IOT. - Disable this option to save memory. - - config SC031GS_SUPPORT - bool "Support SC031GS VGA" - default n - help - SC031GS is a global shutter CMOS sensor with high frame rate and single-frame HDR. - Enable this option if you want to use the SC031GS. - Disable this option to save memory. - - choice SCCB_HARDWARE_I2C_PORT - bool "I2C peripheral to use for SCCB" - default SCCB_HARDWARE_I2C_PORT1 - - config SCCB_HARDWARE_I2C_PORT0 - bool "I2C0" - config SCCB_HARDWARE_I2C_PORT1 - bool "I2C1" - - endchoice - - config SCCB_CLK_FREQ - int "SCCB clk frequency" - default 100000 - range 100000 400000 - help - Increasing this value can reduce the initialization time of the sensor. - Please refer to the relevant instructions of the sensor to adjust the value. - - choice GC_SENSOR_WINDOW_MODE - bool "GalaxyCore Sensor Window Mode" - depends on (GC2145_SUPPORT || GC032A_SUPPORT || GC0308_SUPPORT) - default GC_SENSOR_SUBSAMPLE_MODE - help - This option determines how to reduce the output size when the resolution you set is less than the maximum resolution. - SUBSAMPLE_MODE has a bigger perspective and WINDOWING_MODE has a higher frame rate. - - config GC_SENSOR_WINDOWING_MODE - bool "Windowing Mode" - config GC_SENSOR_SUBSAMPLE_MODE - bool "Subsample Mode" - endchoice - - config CAMERA_TASK_STACK_SIZE - int "CAM task stack size" - default 2048 - help - Camera task stack size - - choice CAMERA_TASK_PINNED_TO_CORE - bool "Camera task pinned to core" - default CAMERA_CORE0 - help - Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. - - config CAMERA_CORE0 - bool "CORE0" - config CAMERA_CORE1 - bool "CORE1" - config CAMERA_NO_AFFINITY - bool "NO_AFFINITY" - - endchoice - - config CAMERA_DMA_BUFFER_SIZE_MAX - int "DMA buffer size" - range 8192 32768 - default 32768 - help - Maximum value of DMA buffer - Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent. - - config CAMERA_CONVERTER_ENABLED - bool "Enable camera RGB/YUV converter" - depends on IDF_TARGET_ESP32S3 - default n - help - Enable this option if you want to use RGB565/YUV422/YUV420/YUV411 format conversion. - - choice CAMERA_CONV_PROTOCOL - bool "Camera converter protocol" - depends on CAMERA_CONVERTER_ENABLED - default LCD_CAM_CONV_BT601_ENABLED - help - Supports format conversion under both BT601 and BT709 standards. - - config LCD_CAM_CONV_BT601_ENABLED - bool "BT601" - config LCD_CAM_CONV_BT709_ENABLED - bool "BT709" - endchoice - - config LCD_CAM_CONV_FULL_RANGE_ENABLED - bool "Camera converter full range mode" - depends on CAMERA_CONVERTER_ENABLED - default y - help - Supports format conversion under both full color range mode and limited color range mode. - If full color range mode is selected, the color range of RGB or YUV is 0~255. - If limited color range mode is selected, the color range of RGB is 16~240, and the color range of YUV is Y[16~240], UV[16~235]. - Full color range mode has a wider color range, so details in the image show more clearly. - Please confirm the color range mode of the current camera sensor, incorrect color range mode may cause color difference in the final converted image. - Full range mode is used by default. If this option is not selected, the format conversion function will be done using the limited range mode. -endmenu diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE b/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md b/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md deleted file mode 100644 index 792f657565..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/README.md +++ /dev/null @@ -1,373 +0,0 @@ -# ESP32 Camera Driver - -[![Build examples](https://github.com/espressif/esp32-camera/actions/workflows/build.yml/badge.svg)](https://github.com/espressif/esp32-camera/actions/workflows/build.yml) [![Component Registry](https://components.espressif.com/components/espressif/esp32-camera/badge.svg)](https://components.espressif.com/components/espressif/esp32-camera) -## General Information - -This repository hosts ESP32 series Soc compatible driver for image sensors. Additionally it provides a few tools, which allow converting the captured frame data to the more common BMP and JPEG formats. - -### Supported Soc - -- ESP32 -- ESP32-S2 -- ESP32-S3 - -### Supported Sensor - -| model | max resolution | color type | output format | Len Size | -| ------- | -------------- | ---------- | ------------------------------------------------------------ | -------- | -| OV2640 | 1600 x 1200 | color | YUV(422/420)/YCbCr422
RGB565/555
8-bit compressed data
8/10-bit Raw RGB data | 1/4" | -| OV3660 | 2048 x 1536 | color | raw RGB data
RGB565/555/444
CCIR656
YCbCr422
compression | 1/5" | -| OV5640 | 2592 x 1944 | color | RAW RGB
RGB565/555/444
CCIR656
YUV422/420
YCbCr422
compression | 1/4" | -| OV7670 | 640 x 480 | color | Raw Bayer RGB
Processed Bayer RGB
YUV/YCbCr422
GRB422
RGB565/555 | 1/6" | -| OV7725 | 640 x 480 | color | Raw RGB
GRB 422
RGB565/555/444
YCbCr 422 | 1/4" | -| NT99141 | 1280 x 720 | color | YCbCr 422
RGB565/555/444
Raw
CCIR656
JPEG compression | 1/4" | -| GC032A | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/10" | -| GC0308 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/6.5" | -| GC2145 | 1600 x 1200 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/5" | -| BF3005 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/4" | -| BF20A6 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
Only Y | 1/10" | -| SC101IOT| 1280 x 720 | color | YUV/YCbCr422
Raw RGB | 1/4.2" | -| SC030IOT| 640 x 480 | color | YUV/YCbCr422
RAW Bayer | 1/6.5" | -| SC031GS | 640 x 480 | monochrome | RAW MONO
Grayscale | 1/6" | - -## Important to Remember - -- Except when using CIF or lower resolution with JPEG, the driver requires PSRAM to be installed and activated. -- Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using `fmt2rgb888` or `fmt2bmp`/`frame2bmp`. -- When 1 frame buffer is used, the driver will wait for the current frame to finish (VSYNC) and start I2S DMA. After the frame is acquired, I2S will be stopped and the frame buffer returned to the application. This approach gives more control over the system, but results in longer time to get the frame. -- When 2 or more frame bufers are used, I2S is running in continuous mode and each frame is pushed to a queue that the application can access. This approach puts more strain on the CPU/Memory, but allows for double the frame rate. Please use only with JPEG. - -## Installation Instructions - - -### Using esp-idf - -- Clone or download and extract the repository to the components folder of your ESP-IDF project -- Enable PSRAM in `menuconfig` (also set Flash and PSRAM frequiencies to 80MHz) -- Include `esp_camera.h` in your code - -### Using PlatformIO - -The easy way -- on the `env` section of `platformio.ini`, add the following: - -```ini -[env] -lib_deps = - esp32-camera -``` - -Now the `esp_camera.h` is available to be included: - -```c -#include "esp_camera.h" -``` - -Enable PSRAM on `menuconfig` or type it direclty on `sdkconfig`. Check the [official doc](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support) for more info. - -``` -CONFIG_ESP32_SPIRAM_SUPPORT=y -``` - -***Arduino*** The easy-way (content above) only seems to work if you're using `framework=arduino` which seems to take a bunch of the guesswork out (thanks Arduino!) but also suck up a lot more memory and flash, almost crippling the performance. If you plan to use the `framework=espidf` then read the sections below carefully!! - -## Platform.io lib/submodule (for framework=espidf) - -It's probably easier to just skip the platform.io library registry version and link the git repo as a submodule. (i.e. using code outside the platform.io library management). In this example we will install this as a submodule inside the platform.io $project/lib folder: -``` -cd $project\lib -git submodule add -b master https://github.com/espressif/esp32-camera.git -``` - -Then in `platformio.ini` file -``` -build_flags = - -I../lib/esp32-camera -``` -After that `#include "esp_camera.h"` statement will be available. Now the module is included, and you're hopefully back to the same place as the easy-Arduino way. - -**Warning about platform.io/espidf and fresh (not initialized) git repos** -There is a sharp-edge on you'll discover in the platform.io build process (in espidf v3.3 & 4.0.1) where a project which has only had `git init` but nothing committed will crash platform.io build process with highly non-useful output. The cause is due to lack of a version (making you think you did something wrong, when you didn't at all) - the output is horribly non-descript. Solution: the devs want you to create a file called version.txt with a number in it, or simply commit any file to the projects git repo and use git. This happens because platform.io build process tries to be too clever and determine the build version number from the git repo - it's a sharp edge you'll only encounter if you're experimenting on a new project with no commits .. like wtf is my camera not working let's try a 'clean project'?! - -## Platform.io Kconfig -Kconfig is used by the platform.io menuconfig (accessed by running: `pio run -t menuconfig`) to interactively manage the various #ifdef statements throughout the espidf and supporting libraries (i.e. this repo: esp32-camera and arduino-esp32.git). The menuconfig process generates the `sdkconfig` file which is ultimately used behind the scenes by espidf compile+build process. - -**Make sure to append or symlink** [this `Kconfig`](./Kconfig) content into the `Kconfig` of your project. - -You symlink (or copy) the included Kconfig into your platform.io projects src directory. The file should be named `Kconfig.projbuild` in your projects src\ directory or you could also add the library path to a CMakefile.txt and hope the `Kconfig` (or `Kconfig.projbuild`) gets discovered by the menuconfig process, though this unpredictable for me. - -The unpredictable wonky behavior in platform.io build process around Kconfig naming (Kconfig vs. Kconfig.projbuild) occurs between espidf versions 3.3 and 4.0 - but if you don't see "Camera configuration" in your `pio run -t menuconfig` then there is no point trying to test camera code (it may compile, but it probably won't work!) and it seems the platform.io devs (when they built their wrapper around the espidf menuconfig) didn't implement it properly. You've probably already figured out you can't use the espidf build tools since the files are in totally different locations and also different versions with sometimes different syntax. This is one of those times you might consider changing the `platformio.ini` from `platform=espressif32` to `platform=https://github.com/platformio/platform-espressif32.git#develop` to get a more recent version of the espidf 4.0 tools. - -However with a bit of patience and experimenting you'll figure the Kconfig out. Once Kconfig (or Kconfig.projbuild) is working then you will be able to choose the configurations according to your setup or the camera libraries will be compiled. Although you might also need to delete your .pio/build directory before the options appear .. again, the `pio run -t menuconfig` doens't always notice the new Kconfig files! - -If you miss-skip-ignore this critical step the camera module will compile but camera logic inside the library will be 'empty' because the Kconfig sets the proper #ifdef statements during the build process to initialize the selected cameras. It's very not optional! - - -## Examples - -### Initialization - -```c -#include "esp_camera.h" - -//WROVER-KIT PIN Map -#define CAM_PIN_PWDN -1 //power down is not used -#define CAM_PIN_RESET -1 //software reset will be performed -#define CAM_PIN_XCLK 21 -#define CAM_PIN_SIOD 26 -#define CAM_PIN_SIOC 27 - -#define CAM_PIN_D7 35 -#define CAM_PIN_D6 34 -#define CAM_PIN_D5 39 -#define CAM_PIN_D4 36 -#define CAM_PIN_D3 19 -#define CAM_PIN_D2 18 -#define CAM_PIN_D1 5 -#define CAM_PIN_D0 4 -#define CAM_PIN_VSYNC 25 -#define CAM_PIN_HREF 23 -#define CAM_PIN_PCLK 22 - -static camera_config_t camera_config = { - .pin_pwdn = CAM_PIN_PWDN, - .pin_reset = CAM_PIN_RESET, - .pin_xclk = CAM_PIN_XCLK, - .pin_sccb_sda = CAM_PIN_SIOD, - .pin_sccb_scl = CAM_PIN_SIOC, - - .pin_d7 = CAM_PIN_D7, - .pin_d6 = CAM_PIN_D6, - .pin_d5 = CAM_PIN_D5, - .pin_d4 = CAM_PIN_D4, - .pin_d3 = CAM_PIN_D3, - .pin_d2 = CAM_PIN_D2, - .pin_d1 = CAM_PIN_D1, - .pin_d0 = CAM_PIN_D0, - .pin_vsync = CAM_PIN_VSYNC, - .pin_href = CAM_PIN_HREF, - .pin_pclk = CAM_PIN_PCLK, - - .xclk_freq_hz = 20000000,//EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode - .ledc_timer = LEDC_TIMER_0, - .ledc_channel = LEDC_CHANNEL_0, - - .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG - .frame_size = FRAMESIZE_UXGA,//QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. - - .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality - .fb_count = 1, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. - .grab_mode = CAMERA_GRAB_WHEN_EMPTY//CAMERA_GRAB_LATEST. Sets when buffers should be filled -}; - -esp_err_t camera_init(){ - //power up the camera if PWDN pin is defined - if(CAM_PIN_PWDN != -1){ - pinMode(CAM_PIN_PWDN, OUTPUT); - digitalWrite(CAM_PIN_PWDN, LOW); - } - - //initialize the camera - esp_err_t err = esp_camera_init(&camera_config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Camera Init Failed"); - return err; - } - - return ESP_OK; -} - -esp_err_t camera_capture(){ - //acquire a frame - camera_fb_t * fb = esp_camera_fb_get(); - if (!fb) { - ESP_LOGE(TAG, "Camera Capture Failed"); - return ESP_FAIL; - } - //replace this with your own function - process_image(fb->width, fb->height, fb->format, fb->buf, fb->len); - - //return the frame buffer back to the driver for reuse - esp_camera_fb_return(fb); - return ESP_OK; -} -``` - -### JPEG HTTP Capture - -```c -#include "esp_camera.h" -#include "esp_http_server.h" -#include "esp_timer.h" - -typedef struct { - httpd_req_t *req; - size_t len; -} jpg_chunking_t; - -static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ - jpg_chunking_t *j = (jpg_chunking_t *)arg; - if(!index){ - j->len = 0; - } - if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){ - return 0; - } - j->len += len; - return len; -} - -esp_err_t jpg_httpd_handler(httpd_req_t *req){ - camera_fb_t * fb = NULL; - esp_err_t res = ESP_OK; - size_t fb_len = 0; - int64_t fr_start = esp_timer_get_time(); - - fb = esp_camera_fb_get(); - if (!fb) { - ESP_LOGE(TAG, "Camera capture failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - res = httpd_resp_set_type(req, "image/jpeg"); - if(res == ESP_OK){ - res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); - } - - if(res == ESP_OK){ - if(fb->format == PIXFORMAT_JPEG){ - fb_len = fb->len; - res = httpd_resp_send(req, (const char *)fb->buf, fb->len); - } else { - jpg_chunking_t jchunk = {req, 0}; - res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL; - httpd_resp_send_chunk(req, NULL, 0); - fb_len = jchunk.len; - } - } - esp_camera_fb_return(fb); - int64_t fr_end = esp_timer_get_time(); - ESP_LOGI(TAG, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000)); - return res; -} -``` - -### JPEG HTTP Stream - -```c -#include "esp_camera.h" -#include "esp_http_server.h" -#include "esp_timer.h" - -#define PART_BOUNDARY "123456789000000000000987654321" -static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; -static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; -static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; - -esp_err_t jpg_stream_httpd_handler(httpd_req_t *req){ - camera_fb_t * fb = NULL; - esp_err_t res = ESP_OK; - size_t _jpg_buf_len; - uint8_t * _jpg_buf; - char * part_buf[64]; - static int64_t last_frame = 0; - if(!last_frame) { - last_frame = esp_timer_get_time(); - } - - res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); - if(res != ESP_OK){ - return res; - } - - while(true){ - fb = esp_camera_fb_get(); - if (!fb) { - ESP_LOGE(TAG, "Camera capture failed"); - res = ESP_FAIL; - break; - } - if(fb->format != PIXFORMAT_JPEG){ - bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); - if(!jpeg_converted){ - ESP_LOGE(TAG, "JPEG compression failed"); - esp_camera_fb_return(fb); - res = ESP_FAIL; - } - } else { - _jpg_buf_len = fb->len; - _jpg_buf = fb->buf; - } - - if(res == ESP_OK){ - res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); - } - if(res == ESP_OK){ - size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); - - res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); - } - if(res == ESP_OK){ - res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); - } - if(fb->format != PIXFORMAT_JPEG){ - free(_jpg_buf); - } - esp_camera_fb_return(fb); - if(res != ESP_OK){ - break; - } - int64_t fr_end = esp_timer_get_time(); - int64_t frame_time = fr_end - last_frame; - last_frame = fr_end; - frame_time /= 1000; - ESP_LOGI(TAG, "MJPG: %uKB %ums (%.1ffps)", - (uint32_t)(_jpg_buf_len/1024), - (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time); - } - - last_frame = 0; - return res; -} -``` - -### BMP HTTP Capture - -```c -#include "esp_camera.h" -#include "esp_http_server.h" -#include "esp_timer.h" - -esp_err_t bmp_httpd_handler(httpd_req_t *req){ - camera_fb_t * fb = NULL; - esp_err_t res = ESP_OK; - int64_t fr_start = esp_timer_get_time(); - - fb = esp_camera_fb_get(); - if (!fb) { - ESP_LOGE(TAG, "Camera capture failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - - uint8_t * buf = NULL; - size_t buf_len = 0; - bool converted = frame2bmp(fb, &buf, &buf_len); - esp_camera_fb_return(fb); - if(!converted){ - ESP_LOGE(TAG, "BMP conversion failed"); - httpd_resp_send_500(req); - return ESP_FAIL; - } - - res = httpd_resp_set_type(req, "image/x-windows-bmp") - || httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.bmp") - || httpd_resp_send(req, (const char *)buf, buf_len); - free(buf); - int64_t fr_end = esp_timer_get_time(); - ESP_LOGI(TAG, "BMP: %uKB %ums", (uint32_t)(buf_len/1024), (uint32_t)((fr_end - fr_start)/1000)); - return res; -} -``` - - - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk deleted file mode 100644 index 8db15eb883..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/component.mk +++ /dev/null @@ -1,4 +0,0 @@ -COMPONENT_ADD_INCLUDEDIRS := driver/include conversions/include -COMPONENT_PRIV_INCLUDEDIRS := driver/private_include conversions/private_include sensors/private_include target/private_include -COMPONENT_SRCDIRS := driver conversions sensors target target/esp32 -CXXFLAGS += -fno-rtti diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c deleted file mode 100644 index 168325baf5..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/esp_jpg_decode.c +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "esp_jpg_decode.h" - -#include "esp_system.h" -#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ -#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 -#include "esp32/rom/tjpgd.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/tjpgd.h" -#elif CONFIG_IDF_TARGET_ESP32C3 -#include "esp32c3/rom/tjpgd.h" -#elif CONFIG_ESP_ROM_HAS_JPEG_DECODE // available since IDF 4.4 -#include "rom/tjpgd.h" // latest IDFs have `rom/` includes available -#else -#include "tjpgd.h" // using software decoder -#endif -#else // ESP32 Before IDF 4.0 -#include "rom/tjpgd.h" -#endif - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#define TAG "" -#else -#include "esp_log.h" -static const char* TAG = "esp_jpg_decode"; -#endif - -typedef struct { - jpg_scale_t scale; - jpg_reader_cb reader; - jpg_writer_cb writer; - void * arg; - size_t len; - size_t index; -} esp_jpg_decoder_t; - -static const char * jd_errors[] = { - "Succeeded", - "Interrupted by output function", - "Device error or wrong termination of input stream", - "Insufficient memory pool for the image", - "Insufficient stream input buffer", - "Parameter error", - "Data format error", - "Right format but not supported", - "Not supported JPEG standard" -}; - -static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) -{ - uint16_t x = rect->left; - uint16_t y = rect->top; - uint16_t w = rect->right + 1 - x; - uint16_t h = rect->bottom + 1 - y; - uint8_t *data = (uint8_t *)bitmap; - - esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; - - if (jpeg->writer) { - return jpeg->writer(jpeg->arg, x, y, w, h, data); - } - return 0; -} - -static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len) -{ - esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; - if (jpeg->len && len > (jpeg->len - jpeg->index)) { - len = jpeg->len - jpeg->index; - } - if (len) { - len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); - if (!len) { - ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); - } - jpeg->index += len; - } - return len; -} - -esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) -{ - static uint8_t work[3100]; - JDEC decoder; - esp_jpg_decoder_t jpeg; - - jpeg.len = len; - jpeg.reader = reader; - jpeg.writer = writer; - jpeg.arg = arg; - jpeg.scale = scale; - jpeg.index = 0; - - JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); - if(jres != JDR_OK){ - ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); - return ESP_FAIL; - } - - uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); - uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); - - //output start - writer(arg, 0, 0, output_width, output_height, NULL); - //output write - jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); - //output end - writer(arg, output_width, output_height, output_width, output_height, NULL); - - if (jres != JDR_OK) { - ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); - return ESP_FAIL; - } - //check if all data has been consumed. - if (len && jpeg.index < len) { - _jpg_read(&decoder, NULL, len - jpeg.index); - } - - return ESP_OK; -} - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h deleted file mode 100644 index f13536edf4..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/esp_jpg_decode.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _ESP_JPG_DECODE_H_ -#define _ESP_JPG_DECODE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "esp_err.h" - -typedef enum { - JPG_SCALE_NONE, - JPG_SCALE_2X, - JPG_SCALE_4X, - JPG_SCALE_8X, - JPG_SCALE_MAX = JPG_SCALE_8X -} jpg_scale_t; - -typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); -typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); - -esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); - -#ifdef __cplusplus -} -#endif - -#endif /* _ESP_JPG_DECODE_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h deleted file mode 100644 index f736200a9b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/include/img_converters.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _IMG_CONVERTERS_H_ -#define _IMG_CONVERTERS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include "esp_camera.h" -#include "esp_jpg_decode.h" - -typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); - -/** - * @brief Convert image buffer to JPEG - * - * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format - * @param src_len Length in bytes of the source buffer - * @param width Width in pixels of the source image - * @param height Height in pixels of the source image - * @param format Format of the source image - * @param quality JPEG quality of the resulting image - * @param cp Callback to be called to write the bytes of the output JPEG - * @param arg Pointer to be passed to the callback - * - * @return true on success - */ -bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); - -/** - * @brief Convert camera frame buffer to JPEG - * - * @param fb Source camera frame buffer - * @param quality JPEG quality of the resulting image - * @param cp Callback to be called to write the bytes of the output JPEG - * @param arg Pointer to be passed to the callback - * - * @return true on success - */ -bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); - -/** - * @brief Convert image buffer to JPEG buffer - * - * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format - * @param src_len Length in bytes of the source buffer - * @param width Width in pixels of the source image - * @param height Height in pixels of the source image - * @param format Format of the source image - * @param quality JPEG quality of the resulting image - * @param out Pointer to be populated with the address of the resulting buffer. - * You MUST free the pointer once you are done with it. - * @param out_len Pointer to be populated with the length of the output buffer - * - * @return true on success - */ -bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); - -/** - * @brief Convert camera frame buffer to JPEG buffer - * - * @param fb Source camera frame buffer - * @param quality JPEG quality of the resulting image - * @param out Pointer to be populated with the address of the resulting buffer - * @param out_len Pointer to be populated with the length of the output buffer - * - * @return true on success - */ -bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); - -/** - * @brief Convert image buffer to BMP buffer - * - * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format - * @param src_len Length in bytes of the source buffer - * @param width Width in pixels of the source image - * @param height Height in pixels of the source image - * @param format Format of the source image - * @param out Pointer to be populated with the address of the resulting buffer - * @param out_len Pointer to be populated with the length of the output buffer - * - * @return true on success - */ -bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); - -/** - * @brief Convert camera frame buffer to BMP buffer - * - * @param fb Source camera frame buffer - * @param out Pointer to be populated with the address of the resulting buffer - * @param out_len Pointer to be populated with the length of the output buffer - * - * @return true on success - */ -bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); - -/** - * @brief Convert image buffer to RGB888 buffer (used for face detection) - * - * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format - * @param src_len Length in bytes of the source buffer - * @param format Format of the source image - * @param rgb_buf Pointer to the output buffer (width * height * 3) - * - * @return true on success - */ -bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); - -bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); - -#ifdef __cplusplus -} -#endif - -#endif /* _IMG_CONVERTERS_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp deleted file mode 100644 index dd6790e63b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/jpge.cpp +++ /dev/null @@ -1,728 +0,0 @@ -// jpge.cpp - C++ class for JPEG compression. -// Public domain, Rich Geldreich -// v1.01, Dec. 18, 2010 - Initial release -// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.) -// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc. -// Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03). -// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug. -// Code tweaks to fix VS2008 static code analysis warnings (all looked harmless). -// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02. - -#include "jpge.h" - -#include -#include -#include -#include -#include -#include -#include -#include "esp_heap_caps.h" - -#define JPGE_MAX(a,b) (((a)>(b))?(a):(b)) -#define JPGE_MIN(a,b) (((a)<(b))?(a):(b)) - -namespace jpge { - - static inline void *jpge_malloc(size_t nSize) { - void * b = malloc(nSize); - if(b){ - return b; - } - // check if SPIRAM is enabled and allocate on SPIRAM if allocatable -#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) - return heap_caps_malloc(nSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -#else - return NULL; -#endif - } - static inline void jpge_free(void *p) { free(p); } - - // Various JPEG enums and tables. - enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 }; - enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 }; - - static const uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 }; - static const int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 }; - static const int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 }; - static const uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 }; - static const uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; - static const uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d }; - static const uint8 s_ac_lum_val[AC_LUM_CODES] = { - 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0, - 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49, - 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, - 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5, - 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, - 0xf9,0xfa - }; - static const uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; - static const uint8 s_dc_chroma_val[DC_CHROMA_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 }; - static const uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 }; - static const uint8 s_ac_chroma_val[AC_CHROMA_CODES] = { - 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0, - 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48, - 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, - 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3, - 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8, - 0xf9,0xfa - }; - - const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329; - - static int32 m_last_quality = 0; - static int32 m_quantization_tables[2][64]; - - static bool m_huff_initialized = false; - static uint m_huff_codes[4][256]; - static uint8 m_huff_code_sizes[4][256]; - static uint8 m_huff_bits[4][17]; - static uint8 m_huff_val[4][256]; - - static inline uint8 clamp(int i) { - if (i < 0) { - i = 0; - } else if (i > 255){ - i = 255; - } - return static_cast(i); - } - - static void RGB_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels) { - for ( ; num_pixels; pDst += 3, pSrc += 3, num_pixels--) { - const int r = pSrc[0], g = pSrc[1], b = pSrc[2]; - pDst[0] = static_cast((r * YR + g * YG + b * YB + 32768) >> 16); - pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16)); - pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16)); - } - } - - static void RGB_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels) { - for ( ; num_pixels; pDst++, pSrc += 3, num_pixels--) { - pDst[0] = static_cast((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16); - } - } - - static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels) { - for( ; num_pixels; pDst += 3, pSrc++, num_pixels--) { - pDst[0] = pSrc[0]; - pDst[1] = 128; - pDst[2] = 128; - } - } - - // Forward DCT - DCT derived from jfdctint. - enum { CONST_BITS = 13, ROW_BITS = 2 }; -#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n)) -#define DCT_MUL(var, c) (static_cast(var) * static_cast(c)) -#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \ - int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \ - int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \ - int32 u1 = DCT_MUL(t12 + t13, 4433); \ - s2 = u1 + DCT_MUL(t13, 6270); \ - s6 = u1 + DCT_MUL(t12, -15137); \ - u1 = t4 + t7; \ - int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \ - int32 z5 = DCT_MUL(u3 + u4, 9633); \ - t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \ - t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \ - u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \ - u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \ - u3 += z5; u4 += z5; \ - s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3; - - static void DCT2D(int32 *p) { - int32 c, *q = p; - for (c = 7; c >= 0; c--, q += 8) { - int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7]; - DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); - q[0] = s0 << ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS); - q[4] = s4 << ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS); - } - for (q = p, c = 7; c >= 0; c--, q++) { - int32 s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8]; - DCT1D(s0, s1, s2, s3, s4, s5, s6, s7); - q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3); - q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3); - } - } - - // Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays. - static void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val) - { - int i, l, last_p, si; - static uint8 huff_size[257]; - static uint huff_code[257]; - uint code; - - int p = 0; - for (l = 1; l <= 16; l++) { - for (i = 1; i <= bits[l]; i++) { - huff_size[p++] = (char)l; - } - } - - huff_size[p] = 0; - last_p = p; // write sentinel - - code = 0; si = huff_size[0]; p = 0; - - while (huff_size[p]) { - while (huff_size[p] == si) { - huff_code[p++] = code++; - } - code <<= 1; - si++; - } - - memset(codes, 0, sizeof(codes[0])*256); - memset(code_sizes, 0, sizeof(code_sizes[0])*256); - for (p = 0; p < last_p; p++) { - codes[val[p]] = huff_code[p]; - code_sizes[val[p]] = huff_size[p]; - } - } - - void jpeg_encoder::flush_output_buffer() - { - if (m_out_buf_left != JPGE_OUT_BUF_SIZE) { - m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left); - } - m_pOut_buf = m_out_buf; - m_out_buf_left = JPGE_OUT_BUF_SIZE; - } - - void jpeg_encoder::emit_byte(uint8 i) - { - *m_pOut_buf++ = i; - if (--m_out_buf_left == 0) { - flush_output_buffer(); - } - } - - void jpeg_encoder::put_bits(uint bits, uint len) - { - uint8 c = 0; - m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len))); - while (m_bits_in >= 8) { - c = (uint8)((m_bit_buffer >> 16) & 0xFF); - emit_byte(c); - if (c == 0xFF) { - emit_byte(0); - } - m_bit_buffer <<= 8; - m_bits_in -= 8; - } - } - - void jpeg_encoder::emit_word(uint i) - { - emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF)); - } - - // JPEG marker generation. - void jpeg_encoder::emit_marker(int marker) - { - emit_byte(uint8(0xFF)); emit_byte(uint8(marker)); - } - - // Emit JFIF marker - void jpeg_encoder::emit_jfif_app0() - { - emit_marker(M_APP0); - emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); - emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */ - emit_byte(0); - emit_byte(1); /* Major version */ - emit_byte(1); /* Minor version */ - emit_byte(0); /* Density unit */ - emit_word(1); - emit_word(1); - emit_byte(0); /* No thumbnail image */ - emit_byte(0); - } - - // Emit quantization tables - void jpeg_encoder::emit_dqt() - { - for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++) - { - emit_marker(M_DQT); - emit_word(64 + 1 + 2); - emit_byte(static_cast(i)); - for (int j = 0; j < 64; j++) - emit_byte(static_cast(m_quantization_tables[i][j])); - } - } - - // Emit start of frame marker - void jpeg_encoder::emit_sof() - { - emit_marker(M_SOF0); /* baseline */ - emit_word(3 * m_num_components + 2 + 5 + 1); - emit_byte(8); /* precision */ - emit_word(m_image_y); - emit_word(m_image_x); - emit_byte(m_num_components); - for (int i = 0; i < m_num_components; i++) - { - emit_byte(static_cast(i + 1)); /* component ID */ - emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]); /* h and v sampling */ - emit_byte(i > 0); /* quant. table num */ - } - } - - // Emit Huffman table. - void jpeg_encoder::emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag) - { - emit_marker(M_DHT); - - int length = 0; - for (int i = 1; i <= 16; i++) - length += bits[i]; - - emit_word(length + 2 + 1 + 16); - emit_byte(static_cast(index + (ac_flag << 4))); - - for (int i = 1; i <= 16; i++) - emit_byte(bits[i]); - - for (int i = 0; i < length; i++) - emit_byte(val[i]); - } - - // Emit all Huffman tables. - void jpeg_encoder::emit_dhts() - { - emit_dht(m_huff_bits[0+0], m_huff_val[0+0], 0, false); - emit_dht(m_huff_bits[2+0], m_huff_val[2+0], 0, true); - if (m_num_components == 3) { - emit_dht(m_huff_bits[0+1], m_huff_val[0+1], 1, false); - emit_dht(m_huff_bits[2+1], m_huff_val[2+1], 1, true); - } - } - - // emit start of scan - void jpeg_encoder::emit_sos() - { - emit_marker(M_SOS); - emit_word(2 * m_num_components + 2 + 1 + 3); - emit_byte(m_num_components); - for (int i = 0; i < m_num_components; i++) - { - emit_byte(static_cast(i + 1)); - if (i == 0) - emit_byte((0 << 4) + 0); - else - emit_byte((1 << 4) + 1); - } - emit_byte(0); /* spectral selection */ - emit_byte(63); - emit_byte(0); - } - - void jpeg_encoder::load_block_8_8_grey(int x) - { - uint8 *pSrc; - sample_array_t *pDst = m_sample_array; - x <<= 3; - for (int i = 0; i < 8; i++, pDst += 8) - { - pSrc = m_mcu_lines[i] + x; - pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128; - pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128; - } - } - - void jpeg_encoder::load_block_8_8(int x, int y, int c) - { - uint8 *pSrc; - sample_array_t *pDst = m_sample_array; - x = (x * (8 * 3)) + c; - y <<= 3; - for (int i = 0; i < 8; i++, pDst += 8) - { - pSrc = m_mcu_lines[y + i] + x; - pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128; - pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128; - } - } - - void jpeg_encoder::load_block_16_8(int x, int c) - { - uint8 *pSrc1, *pSrc2; - sample_array_t *pDst = m_sample_array; - x = (x * (16 * 3)) + c; - int a = 0, b = 2; - for (int i = 0; i < 16; i += 2, pDst += 8) - { - pSrc1 = m_mcu_lines[i + 0] + x; - pSrc2 = m_mcu_lines[i + 1] + x; - pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3] + pSrc2[ 0 * 3] + pSrc2[ 1 * 3] + a) >> 2) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3] + pSrc2[ 2 * 3] + pSrc2[ 3 * 3] + b) >> 2) - 128; - pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3] + pSrc2[ 4 * 3] + pSrc2[ 5 * 3] + a) >> 2) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3] + pSrc2[ 6 * 3] + pSrc2[ 7 * 3] + b) >> 2) - 128; - pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3] + pSrc2[ 8 * 3] + pSrc2[ 9 * 3] + a) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + b) >> 2) - 128; - pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + a) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + b) >> 2) - 128; - int temp = a; a = b; b = temp; - } - } - - void jpeg_encoder::load_block_16_8_8(int x, int c) - { - uint8 *pSrc1; - sample_array_t *pDst = m_sample_array; - x = (x * (16 * 3)) + c; - for (int i = 0; i < 8; i++, pDst += 8) - { - pSrc1 = m_mcu_lines[i + 0] + x; - pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3]) >> 1) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3]) >> 1) - 128; - pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3]) >> 1) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3]) >> 1) - 128; - pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3]) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3]) >> 1) - 128; - pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3]) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3]) >> 1) - 128; - } - } - - void jpeg_encoder::load_quantized_coefficients(int component_num) - { - int32 *q = m_quantization_tables[component_num > 0]; - int16 *pDst = m_coefficient_array; - for (int i = 0; i < 64; i++) - { - sample_array_t j = m_sample_array[s_zag[i]]; - if (j < 0) - { - if ((j = -j + (*q >> 1)) < *q) - *pDst++ = 0; - else - *pDst++ = static_cast(-(j / *q)); - } - else - { - if ((j = j + (*q >> 1)) < *q) - *pDst++ = 0; - else - *pDst++ = static_cast((j / *q)); - } - q++; - } - } - - void jpeg_encoder::code_coefficients_pass_two(int component_num) - { - int i, j, run_len, nbits, temp1, temp2; - int16 *pSrc = m_coefficient_array; - uint *codes[2]; - uint8 *code_sizes[2]; - - if (component_num == 0) - { - codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0]; - code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0]; - } - else - { - codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1]; - code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1]; - } - - temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num]; - m_last_dc_val[component_num] = pSrc[0]; - - if (temp1 < 0) - { - temp1 = -temp1; temp2--; - } - - nbits = 0; - while (temp1) - { - nbits++; temp1 >>= 1; - } - - put_bits(codes[0][nbits], code_sizes[0][nbits]); - if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits); - - for (run_len = 0, i = 1; i < 64; i++) - { - if ((temp1 = m_coefficient_array[i]) == 0) - run_len++; - else - { - while (run_len >= 16) - { - put_bits(codes[1][0xF0], code_sizes[1][0xF0]); - run_len -= 16; - } - if ((temp2 = temp1) < 0) - { - temp1 = -temp1; - temp2--; - } - nbits = 1; - while (temp1 >>= 1) - nbits++; - j = (run_len << 4) + nbits; - put_bits(codes[1][j], code_sizes[1][j]); - put_bits(temp2 & ((1 << nbits) - 1), nbits); - run_len = 0; - } - } - if (run_len) - put_bits(codes[1][0], code_sizes[1][0]); - } - - void jpeg_encoder::code_block(int component_num) - { - DCT2D(m_sample_array); - load_quantized_coefficients(component_num); - code_coefficients_pass_two(component_num); - } - - void jpeg_encoder::process_mcu_row() - { - if (m_num_components == 1) - { - for (int i = 0; i < m_mcus_per_row; i++) - { - load_block_8_8_grey(i); code_block(0); - } - } - else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1)) - { - for (int i = 0; i < m_mcus_per_row; i++) - { - load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2); - } - } - else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1)) - { - for (int i = 0; i < m_mcus_per_row; i++) - { - load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); - load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2); - } - } - else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2)) - { - for (int i = 0; i < m_mcus_per_row; i++) - { - load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0); - load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0); - load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2); - } - } - } - - void jpeg_encoder::load_mcu(const void *pSrc) - { - const uint8* Psrc = reinterpret_cast(pSrc); - - uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst - - if (m_num_components == 1) { - if (m_image_bpp == 3) - RGB_to_Y(pDst, Psrc, m_image_x); - else - memcpy(pDst, Psrc, m_image_x); - } else { - if (m_image_bpp == 3) - RGB_to_YCC(pDst, Psrc, m_image_x); - else - Y_to_YCC(pDst, Psrc, m_image_x); - } - - // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16 - if (m_num_components == 1) - memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x); - else - { - const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2]; - uint8 *q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt; - for (int i = m_image_x; i < m_image_x_mcu; i++) - { - *q++ = y; *q++ = cb; *q++ = cr; - } - } - - if (++m_mcu_y_ofs == m_mcu_y) - { - process_mcu_row(); - m_mcu_y_ofs = 0; - } - } - - // Quantization table generation. - void jpeg_encoder::compute_quant_table(int32 *pDst, const int16 *pSrc) - { - int32 q; - if (m_params.m_quality < 50) - q = 5000 / m_params.m_quality; - else - q = 200 - m_params.m_quality * 2; - for (int i = 0; i < 64; i++) - { - int32 j = *pSrc++; j = (j * q + 50L) / 100L; - *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255); - } - } - - // Higher-level methods. - bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels) - { - m_num_components = 3; - switch (m_params.m_subsampling) - { - case Y_ONLY: - { - m_num_components = 1; - m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; - m_mcu_x = 8; m_mcu_y = 8; - break; - } - case H1V1: - { - m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1; - m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; - m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; - m_mcu_x = 8; m_mcu_y = 8; - break; - } - case H2V1: - { - m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1; - m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; - m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; - m_mcu_x = 16; m_mcu_y = 8; - break; - } - case H2V2: - { - m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2; - m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1; - m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1; - m_mcu_x = 16; m_mcu_y = 16; - } - } - - m_image_x = p_x_res; m_image_y = p_y_res; - m_image_bpp = src_channels; - m_image_bpl = m_image_x * src_channels; - m_image_x_mcu = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1)); - m_image_y_mcu = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1)); - m_image_bpl_xlt = m_image_x * m_num_components; - m_image_bpl_mcu = m_image_x_mcu * m_num_components; - m_mcus_per_row = m_image_x_mcu / m_mcu_x; - - if ((m_mcu_lines[0] = static_cast(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) { - return false; - } - for (int i = 1; i < m_mcu_y; i++) - m_mcu_lines[i] = m_mcu_lines[i-1] + m_image_bpl_mcu; - - if(m_last_quality != m_params.m_quality){ - m_last_quality = m_params.m_quality; - compute_quant_table(m_quantization_tables[0], s_std_lum_quant); - compute_quant_table(m_quantization_tables[1], s_std_croma_quant); - } - - if(!m_huff_initialized){ - m_huff_initialized = true; - - memcpy(m_huff_bits[0+0], s_dc_lum_bits, 17); memcpy(m_huff_val[0+0], s_dc_lum_val, DC_LUM_CODES); - memcpy(m_huff_bits[2+0], s_ac_lum_bits, 17); memcpy(m_huff_val[2+0], s_ac_lum_val, AC_LUM_CODES); - memcpy(m_huff_bits[0+1], s_dc_chroma_bits, 17); memcpy(m_huff_val[0+1], s_dc_chroma_val, DC_CHROMA_CODES); - memcpy(m_huff_bits[2+1], s_ac_chroma_bits, 17); memcpy(m_huff_val[2+1], s_ac_chroma_val, AC_CHROMA_CODES); - - compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0], m_huff_val[0+0]); - compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0], m_huff_val[2+0]); - compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1], m_huff_val[0+1]); - compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1], m_huff_val[2+1]); - } - - m_out_buf_left = JPGE_OUT_BUF_SIZE; - m_pOut_buf = m_out_buf; - m_bit_buffer = 0; - m_bits_in = 0; - m_mcu_y_ofs = 0; - m_pass_num = 2; - memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0])); - - // Emit all markers at beginning of image file. - emit_marker(M_SOI); - emit_jfif_app0(); - emit_dqt(); - emit_sof(); - emit_dhts(); - emit_sos(); - - return m_all_stream_writes_succeeded; - } - - bool jpeg_encoder::process_end_of_image() - { - if (m_mcu_y_ofs) { - if (m_mcu_y_ofs < 16) { // check here just to shut up static analysis - for (int i = m_mcu_y_ofs; i < m_mcu_y; i++) { - memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu); - } - } - process_mcu_row(); - } - - put_bits(0x7F, 7); - emit_marker(M_EOI); - flush_output_buffer(); - m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(NULL, 0); - m_pass_num++; // purposely bump up m_pass_num, for debugging - return true; - } - - void jpeg_encoder::clear() - { - m_mcu_lines[0] = NULL; - m_pass_num = 0; - m_all_stream_writes_succeeded = true; - } - - jpeg_encoder::jpeg_encoder() - { - clear(); - } - - jpeg_encoder::~jpeg_encoder() - { - deinit(); - } - - bool jpeg_encoder::init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params) - { - deinit(); - if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check())) return false; - m_pStream = pStream; - m_params = comp_params; - return jpg_open(width, height, src_channels); - } - - void jpeg_encoder::deinit() - { - jpge_free(m_mcu_lines[0]); - clear(); - } - - bool jpeg_encoder::process_scanline(const void* pScanline) - { - if ((m_pass_num < 1) || (m_pass_num > 2)) { - return false; - } - if (m_all_stream_writes_succeeded) { - if (!pScanline) { - if (!process_end_of_image()) { - return false; - } - } else { - load_mcu(pScanline); - } - } - return m_all_stream_writes_succeeded; - } - -} // namespace jpge diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h deleted file mode 100644 index aa295c8af0..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/jpge.h +++ /dev/null @@ -1,142 +0,0 @@ -// jpge.h - C++ class for JPEG compression. -// Public domain, Rich Geldreich -// Alex Evans: Added RGBA support, linear memory allocator. -#ifndef JPEG_ENCODER_H -#define JPEG_ENCODER_H - -namespace jpge -{ - typedef unsigned char uint8; - typedef signed short int16; - typedef signed int int32; - typedef unsigned short uint16; - typedef unsigned int uint32; - typedef unsigned int uint; - - // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. - enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; - - // JPEG compression parameters structure. - struct params { - inline params() : m_quality(85), m_subsampling(H2V2) { } - - inline bool check() const { - if ((m_quality < 1) || (m_quality > 100)) { - return false; - } - if ((uint)m_subsampling > (uint)H2V2) { - return false; - } - return true; - } - - // Quality: 1-100, higher is better. Typical values are around 50-95. - int m_quality; - - // m_subsampling: - // 0 = Y (grayscale) only - // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) - // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) - // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) - subsampling_t m_subsampling; - }; - - // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. - // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. - class output_stream { - public: - virtual ~output_stream() { }; - virtual bool put_buf(const void* Pbuf, int len) = 0; - virtual uint get_size() const = 0; - }; - - // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. - class jpeg_encoder { - public: - jpeg_encoder(); - ~jpeg_encoder(); - - // Initializes the compressor. - // pStream: The stream object to use for writing compressed data. - // params - Compression parameters structure, defined above. - // width, height - Image dimensions. - // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. - // Returns false on out of memory or if a stream write fails. - bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); - - // Call this method with each source scanline. - // width * src_channels bytes per scanline is expected (RGB or Y format). - // You must call with NULL after all scanlines are processed to finish compression. - // Returns false on out of memory or if a stream write fails. - bool process_scanline(const void* pScanline); - - // Deinitializes the compressor, freeing any allocated memory. May be called at any time. - void deinit(); - - private: - jpeg_encoder(const jpeg_encoder &); - jpeg_encoder &operator =(const jpeg_encoder &); - - typedef int32 sample_array_t; - enum { JPGE_OUT_BUF_SIZE = 512 }; - - output_stream *m_pStream; - params m_params; - uint8 m_num_components; - uint8 m_comp_h_samp[3], m_comp_v_samp[3]; - int m_image_x, m_image_y, m_image_bpp, m_image_bpl; - int m_image_x_mcu, m_image_y_mcu; - int m_image_bpl_xlt, m_image_bpl_mcu; - int m_mcus_per_row; - int m_mcu_x, m_mcu_y; - uint8 *m_mcu_lines[16]; - uint8 m_mcu_y_ofs; - sample_array_t m_sample_array[64]; - int16 m_coefficient_array[64]; - - int m_last_dc_val[3]; - uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; - uint8 *m_pOut_buf; - uint m_out_buf_left; - uint32 m_bit_buffer; - uint m_bits_in; - uint8 m_pass_num; - bool m_all_stream_writes_succeeded; - - bool jpg_open(int p_x_res, int p_y_res, int src_channels); - - void flush_output_buffer(); - void put_bits(uint bits, uint len); - - void emit_byte(uint8 i); - void emit_word(uint i); - void emit_marker(int marker); - - void emit_jfif_app0(); - void emit_dqt(); - void emit_sof(); - void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); - void emit_dhts(); - void emit_sos(); - - void compute_quant_table(int32 *dst, const int16 *src); - void load_quantized_coefficients(int component_num); - - void load_block_8_8_grey(int x); - void load_block_8_8(int x, int y, int c); - void load_block_16_8(int x, int c); - void load_block_16_8_8(int x, int c); - - void code_coefficients_pass_two(int component_num); - void code_block(int component_num); - - void process_mcu_row(); - bool process_end_of_image(); - void load_mcu(const void* src); - void clear(); - void init(); - }; - -} // namespace jpge - -#endif // JPEG_ENCODER diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h deleted file mode 100644 index c5a0577ef8..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/private_include/yuv.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _CONVERSIONS_YUV_H_ -#define _CONVERSIONS_YUV_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); - -#ifdef __cplusplus -} -#endif - -#endif /* _CONVERSIONS_YUV_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c deleted file mode 100644 index 27072f7113..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_bmp.c +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include "img_converters.h" -#include "soc/efuse_reg.h" -#include "esp_heap_caps.h" -#include "yuv.h" -#include "sdkconfig.h" -#include "esp_jpg_decode.h" - -#include "esp_system.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#define TAG "" -#else -#include "esp_log.h" -static const char* TAG = "to_bmp"; -#endif - -static const int BMP_HEADER_LEN = 54; - -typedef struct { - uint32_t filesize; - uint32_t reserved; - uint32_t fileoffset_to_pixelarray; - uint32_t dibheadersize; - int32_t width; - int32_t height; - uint16_t planes; - uint16_t bitsperpixel; - uint32_t compression; - uint32_t imagesize; - uint32_t ypixelpermeter; - uint32_t xpixelpermeter; - uint32_t numcolorspallette; - uint32_t mostimpcolor; -} bmp_header_t; - -typedef struct { - uint16_t width; - uint16_t height; - uint16_t data_offset; - const uint8_t *input; - uint8_t *output; -} rgb_jpg_decoder; - -static void *_malloc(size_t size) -{ - // check if SPIRAM is enabled and allocate on SPIRAM if allocatable -#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) - return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -#endif - // try allocating in internal memory - return malloc(size); -} - -//output buffer and image width -static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data) -{ - rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; - if(!data){ - if(x == 0 && y == 0){ - //write start - jpeg->width = w; - jpeg->height = h; - //if output is null, this is BMP - if(!jpeg->output){ - jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset); - if(!jpeg->output){ - return false; - } - } - } else { - //write end - } - return true; - } - - size_t jw = jpeg->width*3; - size_t t = y * jw; - size_t b = t + (h * jw); - size_t l = x * 3; - uint8_t *out = jpeg->output+jpeg->data_offset; - uint8_t *o = out; - size_t iy, ix; - - w = w * 3; - - for(iy=t; iywidth = w; - jpeg->height = h; - //if output is null, this is BMP - if(!jpeg->output){ - jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset); - if(!jpeg->output){ - return false; - } - } - } else { - //write end - } - return true; - } - - size_t jw = jpeg->width*3; - size_t jw2 = jpeg->width*2; - size_t t = y * jw; - size_t t2 = y * jw2; - size_t b = t + (h * jw); - size_t l = x * 2; - uint8_t *out = jpeg->output+jpeg->data_offset; - uint8_t *o = out; - size_t iy, iy2, ix, ix2; - - w = w * 3; - - for(iy=t, iy2=t2; iy> 3); - o[ix2+1] = c>>8; - o[ix2] = c&0xff; - } - data+=w; - } - return true; -} - -//input buffer -static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len) -{ - rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg; - if(buf) { - memcpy(buf, jpeg->input + index, len); - } - return len; -} - -static bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale) -{ - rgb_jpg_decoder jpeg; - jpeg.width = 0; - jpeg.height = 0; - jpeg.input = src; - jpeg.output = out; - jpeg.data_offset = 0; - - if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){ - return false; - } - return true; -} - -bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale) -{ - rgb_jpg_decoder jpeg; - jpeg.width = 0; - jpeg.height = 0; - jpeg.input = src; - jpeg.output = out; - jpeg.data_offset = 0; - - if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb565_write, (void*)&jpeg) != ESP_OK){ - return false; - } - return true; -} - -bool jpg2bmp(const uint8_t *src, size_t src_len, uint8_t ** out, size_t * out_len) -{ - - rgb_jpg_decoder jpeg; - jpeg.width = 0; - jpeg.height = 0; - jpeg.input = src; - jpeg.output = NULL; - jpeg.data_offset = BMP_HEADER_LEN; - - if(esp_jpg_decode(src_len, JPG_SCALE_NONE, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){ - return false; - } - - size_t output_size = jpeg.width*jpeg.height*3; - - jpeg.output[0] = 'B'; - jpeg.output[1] = 'M'; - bmp_header_t * bitmap = (bmp_header_t*)&jpeg.output[2]; - bitmap->reserved = 0; - bitmap->filesize = output_size+BMP_HEADER_LEN; - bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN; - bitmap->dibheadersize = 40; - bitmap->width = jpeg.width; - bitmap->height = -jpeg.height;//set negative for top to bottom - bitmap->planes = 1; - bitmap->bitsperpixel = 24; - bitmap->compression = 0; - bitmap->imagesize = output_size; - bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI - bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI - bitmap->numcolorspallette = 0; - bitmap->mostimpcolor = 0; - - *out = jpeg.output; - *out_len = output_size+BMP_HEADER_LEN; - - return true; -} - -bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf) -{ - int pix_count = 0; - if(format == PIXFORMAT_JPEG) { - return jpg2rgb888(src_buf, src_len, rgb_buf, JPG_SCALE_NONE); - } else if(format == PIXFORMAT_RGB888) { - memcpy(rgb_buf, src_buf, src_len); - } else if(format == PIXFORMAT_RGB565) { - int i; - uint8_t hb, lb; - pix_count = src_len / 2; - for(i=0; i> 3; - *rgb_buf++ = hb & 0xF8; - } - } else if(format == PIXFORMAT_GRAYSCALE) { - int i; - uint8_t b; - pix_count = src_len; - for(i=0; ireserved = 0; - bitmap->filesize = out_size; - bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN + palette_size; - bitmap->dibheadersize = 40; - bitmap->width = width; - bitmap->height = -height;//set negative for top to bottom - bitmap->planes = 1; - bitmap->bitsperpixel = bpp * 8; - bitmap->compression = 0; - bitmap->imagesize = pix_count * bpp; - bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI - bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI - bitmap->numcolorspallette = 0; - bitmap->mostimpcolor = 0; - - uint8_t * palette_buf = out_buf + BMP_HEADER_LEN; - uint8_t * pix_buf = palette_buf + palette_size; - uint8_t * src_buf = src; - - if (palette_size > 0) { - // Grayscale palette - for (int i = 0; i < 256; ++i) { - for (int j = 0; j < 3; ++j) { - *palette_buf = i; - palette_buf++; - } - // Reserved / alpha channel. - *palette_buf = 0; - palette_buf++; - } - } - - //convert data to RGB888 - if(format == PIXFORMAT_RGB888) { - memcpy(pix_buf, src_buf, pix_count*3); - } else if(format == PIXFORMAT_RGB565) { - int i; - uint8_t hb, lb; - for(i=0; i> 3; - *pix_buf++ = hb & 0xF8; - } - } else if(format == PIXFORMAT_GRAYSCALE) { - memcpy(pix_buf, src_buf, pix_count); - } else if(format == PIXFORMAT_YUV422) { - int i, maxi = pix_count / 2; - uint8_t y0, y1, u, v; - uint8_t r, g, b; - for(i=0; ibuf, fb->len, fb->width, fb->height, fb->format, out, out_len); -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp deleted file mode 100644 index 24cc2989cd..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/to_jpg.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include "esp_attr.h" -#include "soc/efuse_reg.h" -#include "esp_heap_caps.h" -#include "esp_camera.h" -#include "img_converters.h" -#include "jpge.h" -#include "yuv.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#define TAG "" -#else -#include "esp_log.h" -static const char* TAG = "to_jpg"; -#endif - -static void *_malloc(size_t size) -{ - void * res = malloc(size); - if(res) { - return res; - } - - // check if SPIRAM is enabled and is allocatable -#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) - return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -#endif - return NULL; -} - -static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line) -{ - int i=0, o=0, l=0; - if(format == PIXFORMAT_GRAYSCALE) { - memcpy(dst, src + line * width, width); - } else if(format == PIXFORMAT_RGB888) { - l = width * 3; - src += l * line; - for(i=0; i> 3; - dst[o++] = (src[i+1] & 0x1F) << 3; - } - } else if(format == PIXFORMAT_YUV422) { - uint8_t y0, y1, u, v; - uint8_t r, g, b; - l = width * 2; - src += l * line; - for(i=0; i 100) { - quality = 100; - } - - jpge::params comp_params = jpge::params(); - comp_params.m_subsampling = subsampling; - comp_params.m_quality = quality; - - jpge::jpeg_encoder dst_image; - - if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) { - ESP_LOGE(TAG, "JPG encoder init failed"); - return false; - } - - uint8_t* line = (uint8_t*)_malloc(width * num_channels); - if(!line) { - ESP_LOGE(TAG, "Scan line malloc failed"); - return false; - } - - for (int i = 0; i < height; i++) { - convert_line_format(src, format, line, width, num_channels, i); - if (!dst_image.process_scanline(line)) { - ESP_LOGE(TAG, "JPG process line %u failed", i); - free(line); - return false; - } - } - free(line); - - if (!dst_image.process_scanline(NULL)) { - ESP_LOGE(TAG, "JPG image finish failed"); - return false; - } - dst_image.deinit(); - return true; -} - -class callback_stream : public jpge::output_stream { -protected: - jpg_out_cb ocb; - void * oarg; - size_t index; - -public: - callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { } - virtual ~callback_stream() { } - virtual bool put_buf(const void* data, int len) - { - index += ocb(oarg, index, data, len); - return true; - } - virtual size_t get_size() const - { - return index; - } -}; - -bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg) -{ - callback_stream dst_stream(cb, arg); - return convert_image(src, width, height, format, quality, &dst_stream); -} - -bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg) -{ - return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg); -} - - - -class memory_stream : public jpge::output_stream { -protected: - uint8_t *out_buf; - size_t max_len, index; - -public: - memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast(pBuf)), max_len(buf_size), index(0) { } - - virtual ~memory_stream() { } - - virtual bool put_buf(const void* pBuf, int len) - { - if (!pBuf) { - //end of image - return true; - } - if ((size_t)len > (max_len - index)) { - //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len); - len = max_len - index; - } - if (len) { - memcpy(out_buf + index, pBuf, len); - index += len; - } - return true; - } - - virtual size_t get_size() const - { - return index; - } -}; - -bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len) -{ - //todo: allocate proper buffer for holding JPEG data - //this should be enough for CIF frame size - int jpg_buf_len = 128*1024; - - - uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len); - if(jpg_buf == NULL) { - ESP_LOGE(TAG, "JPG buffer malloc failed"); - return false; - } - memory_stream dst_stream(jpg_buf, jpg_buf_len); - - if(!convert_image(src, width, height, format, quality, &dst_stream)) { - free(jpg_buf); - return false; - } - - *out = jpg_buf; - *out_len = dst_stream.get_size(); - return true; -} - -bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len) -{ - return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len); -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c deleted file mode 100644 index 46034cc868..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/conversions/yuv.c +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "yuv.h" -#include "esp_attr.h" - -typedef struct { - int16_t vY; - int16_t vVr; - int16_t vVg; - int16_t vUg; - int16_t vUb; -} yuv_table_row; - -static const yuv_table_row yuv_table[256] = { - // Y Vr Vg Ug Ub // # - { -18, -204, 50, 104, -258 }, // 0 - { -17, -202, 49, 103, -256 }, // 1 - { -16, -201, 49, 102, -254 }, // 2 - { -15, -199, 48, 101, -252 }, // 3 - { -13, -197, 48, 100, -250 }, // 4 - { -12, -196, 48, 99, -248 }, // 5 - { -11, -194, 47, 99, -246 }, // 6 - { -10, -193, 47, 98, -244 }, // 7 - { -9, -191, 46, 97, -242 }, // 8 - { -8, -189, 46, 96, -240 }, // 9 - { -6, -188, 46, 95, -238 }, // 10 - { -5, -186, 45, 95, -236 }, // 11 - { -4, -185, 45, 94, -234 }, // 12 - { -3, -183, 44, 93, -232 }, // 13 - { -2, -181, 44, 92, -230 }, // 14 - { -1, -180, 44, 91, -228 }, // 15 - { 0, -178, 43, 91, -226 }, // 16 - { 1, -177, 43, 90, -223 }, // 17 - { 2, -175, 43, 89, -221 }, // 18 - { 3, -173, 42, 88, -219 }, // 19 - { 4, -172, 42, 87, -217 }, // 20 - { 5, -170, 41, 86, -215 }, // 21 - { 6, -169, 41, 86, -213 }, // 22 - { 8, -167, 41, 85, -211 }, // 23 - { 9, -165, 40, 84, -209 }, // 24 - { 10, -164, 40, 83, -207 }, // 25 - { 11, -162, 39, 82, -205 }, // 26 - { 12, -161, 39, 82, -203 }, // 27 - { 13, -159, 39, 81, -201 }, // 28 - { 15, -158, 38, 80, -199 }, // 29 - { 16, -156, 38, 79, -197 }, // 30 - { 17, -154, 37, 78, -195 }, // 31 - { 18, -153, 37, 78, -193 }, // 32 - { 19, -151, 37, 77, -191 }, // 33 - { 20, -150, 36, 76, -189 }, // 34 - { 22, -148, 36, 75, -187 }, // 35 - { 23, -146, 35, 74, -185 }, // 36 - { 24, -145, 35, 73, -183 }, // 37 - { 25, -143, 35, 73, -181 }, // 38 - { 26, -142, 34, 72, -179 }, // 39 - { 27, -140, 34, 71, -177 }, // 40 - { 29, -138, 34, 70, -175 }, // 41 - { 30, -137, 33, 69, -173 }, // 42 - { 31, -135, 33, 69, -171 }, // 43 - { 32, -134, 32, 68, -169 }, // 44 - { 33, -132, 32, 67, -167 }, // 45 - { 34, -130, 32, 66, -165 }, // 46 - { 36, -129, 31, 65, -163 }, // 47 - { 37, -127, 31, 65, -161 }, // 48 - { 38, -126, 30, 64, -159 }, // 49 - { 39, -124, 30, 63, -157 }, // 50 - { 40, -122, 30, 62, -155 }, // 51 - { 41, -121, 29, 61, -153 }, // 52 - { 43, -119, 29, 60, -151 }, // 53 - { 44, -118, 28, 60, -149 }, // 54 - { 45, -116, 28, 59, -147 }, // 55 - { 46, -114, 28, 58, -145 }, // 56 - { 47, -113, 27, 57, -143 }, // 57 - { 48, -111, 27, 56, -141 }, // 58 - { 50, -110, 26, 56, -139 }, // 59 - { 51, -108, 26, 55, -137 }, // 60 - { 52, -106, 26, 54, -135 }, // 61 - { 53, -105, 25, 53, -133 }, // 62 - { 54, -103, 25, 52, -131 }, // 63 - { 55, -102, 25, 52, -129 }, // 64 - { 57, -100, 24, 51, -127 }, // 65 - { 58, -98, 24, 50, -125 }, // 66 - { 59, -97, 23, 49, -123 }, // 67 - { 60, -95, 23, 48, -121 }, // 68 - { 61, -94, 23, 47, -119 }, // 69 - { 62, -92, 22, 47, -117 }, // 70 - { 64, -90, 22, 46, -115 }, // 71 - { 65, -89, 21, 45, -113 }, // 72 - { 66, -87, 21, 44, -110 }, // 73 - { 67, -86, 21, 43, -108 }, // 74 - { 68, -84, 20, 43, -106 }, // 75 - { 69, -82, 20, 42, -104 }, // 76 - { 71, -81, 19, 41, -102 }, // 77 - { 72, -79, 19, 40, -100 }, // 78 - { 73, -78, 19, 39, -98 }, // 79 - { 74, -76, 18, 39, -96 }, // 80 - { 75, -75, 18, 38, -94 }, // 81 - { 76, -73, 17, 37, -92 }, // 82 - { 77, -71, 17, 36, -90 }, // 83 - { 79, -70, 17, 35, -88 }, // 84 - { 80, -68, 16, 34, -86 }, // 85 - { 81, -67, 16, 34, -84 }, // 86 - { 82, -65, 16, 33, -82 }, // 87 - { 83, -63, 15, 32, -80 }, // 88 - { 84, -62, 15, 31, -78 }, // 89 - { 86, -60, 14, 30, -76 }, // 90 - { 87, -59, 14, 30, -74 }, // 91 - { 88, -57, 14, 29, -72 }, // 92 - { 89, -55, 13, 28, -70 }, // 93 - { 90, -54, 13, 27, -68 }, // 94 - { 91, -52, 12, 26, -66 }, // 95 - { 93, -51, 12, 26, -64 }, // 96 - { 94, -49, 12, 25, -62 }, // 97 - { 95, -47, 11, 24, -60 }, // 98 - { 96, -46, 11, 23, -58 }, // 99 - { 97, -44, 10, 22, -56 }, // 100 - { 98, -43, 10, 21, -54 }, // 101 - { 100, -41, 10, 21, -52 }, // 102 - { 101, -39, 9, 20, -50 }, // 103 - { 102, -38, 9, 19, -48 }, // 104 - { 103, -36, 8, 18, -46 }, // 105 - { 104, -35, 8, 17, -44 }, // 106 - { 105, -33, 8, 17, -42 }, // 107 - { 107, -31, 7, 16, -40 }, // 108 - { 108, -30, 7, 15, -38 }, // 109 - { 109, -28, 7, 14, -36 }, // 110 - { 110, -27, 6, 13, -34 }, // 111 - { 111, -25, 6, 13, -32 }, // 112 - { 112, -23, 5, 12, -30 }, // 113 - { 114, -22, 5, 11, -28 }, // 114 - { 115, -20, 5, 10, -26 }, // 115 - { 116, -19, 4, 9, -24 }, // 116 - { 117, -17, 4, 8, -22 }, // 117 - { 118, -15, 3, 8, -20 }, // 118 - { 119, -14, 3, 7, -18 }, // 119 - { 121, -12, 3, 6, -16 }, // 120 - { 122, -11, 2, 5, -14 }, // 121 - { 123, -9, 2, 4, -12 }, // 122 - { 124, -7, 1, 4, -10 }, // 123 - { 125, -6, 1, 3, -8 }, // 124 - { 126, -4, 1, 2, -6 }, // 125 - { 128, -3, 0, 1, -4 }, // 126 - { 129, -1, 0, 0, -2 }, // 127 - { 130, 0, 0, 0, 0 }, // 128 - { 131, 1, 0, 0, 2 }, // 129 - { 132, 3, 0, -1, 4 }, // 130 - { 133, 4, -1, -2, 6 }, // 131 - { 135, 6, -1, -3, 8 }, // 132 - { 136, 7, -1, -4, 10 }, // 133 - { 137, 9, -2, -4, 12 }, // 134 - { 138, 11, -2, -5, 14 }, // 135 - { 139, 12, -3, -6, 16 }, // 136 - { 140, 14, -3, -7, 18 }, // 137 - { 142, 15, -3, -8, 20 }, // 138 - { 143, 17, -4, -8, 22 }, // 139 - { 144, 19, -4, -9, 24 }, // 140 - { 145, 20, -5, -10, 26 }, // 141 - { 146, 22, -5, -11, 28 }, // 142 - { 147, 23, -5, -12, 30 }, // 143 - { 148, 25, -6, -13, 32 }, // 144 - { 150, 27, -6, -13, 34 }, // 145 - { 151, 28, -7, -14, 36 }, // 146 - { 152, 30, -7, -15, 38 }, // 147 - { 153, 31, -7, -16, 40 }, // 148 - { 154, 33, -8, -17, 42 }, // 149 - { 155, 35, -8, -17, 44 }, // 150 - { 157, 36, -8, -18, 46 }, // 151 - { 158, 38, -9, -19, 48 }, // 152 - { 159, 39, -9, -20, 50 }, // 153 - { 160, 41, -10, -21, 52 }, // 154 - { 161, 43, -10, -21, 54 }, // 155 - { 162, 44, -10, -22, 56 }, // 156 - { 164, 46, -11, -23, 58 }, // 157 - { 165, 47, -11, -24, 60 }, // 158 - { 166, 49, -12, -25, 62 }, // 159 - { 167, 51, -12, -26, 64 }, // 160 - { 168, 52, -12, -26, 66 }, // 161 - { 169, 54, -13, -27, 68 }, // 162 - { 171, 55, -13, -28, 70 }, // 163 - { 172, 57, -14, -29, 72 }, // 164 - { 173, 59, -14, -30, 74 }, // 165 - { 174, 60, -14, -30, 76 }, // 166 - { 175, 62, -15, -31, 78 }, // 167 - { 176, 63, -15, -32, 80 }, // 168 - { 178, 65, -16, -33, 82 }, // 169 - { 179, 67, -16, -34, 84 }, // 170 - { 180, 68, -16, -34, 86 }, // 171 - { 181, 70, -17, -35, 88 }, // 172 - { 182, 71, -17, -36, 90 }, // 173 - { 183, 73, -17, -37, 92 }, // 174 - { 185, 75, -18, -38, 94 }, // 175 - { 186, 76, -18, -39, 96 }, // 176 - { 187, 78, -19, -39, 98 }, // 177 - { 188, 79, -19, -40, 100 }, // 178 - { 189, 81, -19, -41, 102 }, // 179 - { 190, 82, -20, -42, 104 }, // 180 - { 192, 84, -20, -43, 106 }, // 181 - { 193, 86, -21, -43, 108 }, // 182 - { 194, 87, -21, -44, 110 }, // 183 - { 195, 89, -21, -45, 113 }, // 184 - { 196, 90, -22, -46, 115 }, // 185 - { 197, 92, -22, -47, 117 }, // 186 - { 199, 94, -23, -47, 119 }, // 187 - { 200, 95, -23, -48, 121 }, // 188 - { 201, 97, -23, -49, 123 }, // 189 - { 202, 98, -24, -50, 125 }, // 190 - { 203, 100, -24, -51, 127 }, // 191 - { 204, 102, -25, -52, 129 }, // 192 - { 206, 103, -25, -52, 131 }, // 193 - { 207, 105, -25, -53, 133 }, // 194 - { 208, 106, -26, -54, 135 }, // 195 - { 209, 108, -26, -55, 137 }, // 196 - { 210, 110, -26, -56, 139 }, // 197 - { 211, 111, -27, -56, 141 }, // 198 - { 213, 113, -27, -57, 143 }, // 199 - { 214, 114, -28, -58, 145 }, // 200 - { 215, 116, -28, -59, 147 }, // 201 - { 216, 118, -28, -60, 149 }, // 202 - { 217, 119, -29, -60, 151 }, // 203 - { 218, 121, -29, -61, 153 }, // 204 - { 219, 122, -30, -62, 155 }, // 205 - { 221, 124, -30, -63, 157 }, // 206 - { 222, 126, -30, -64, 159 }, // 207 - { 223, 127, -31, -65, 161 }, // 208 - { 224, 129, -31, -65, 163 }, // 209 - { 225, 130, -32, -66, 165 }, // 210 - { 226, 132, -32, -67, 167 }, // 211 - { 228, 134, -32, -68, 169 }, // 212 - { 229, 135, -33, -69, 171 }, // 213 - { 230, 137, -33, -69, 173 }, // 214 - { 231, 138, -34, -70, 175 }, // 215 - { 232, 140, -34, -71, 177 }, // 216 - { 233, 142, -34, -72, 179 }, // 217 - { 235, 143, -35, -73, 181 }, // 218 - { 236, 145, -35, -73, 183 }, // 219 - { 237, 146, -35, -74, 185 }, // 220 - { 238, 148, -36, -75, 187 }, // 221 - { 239, 150, -36, -76, 189 }, // 222 - { 240, 151, -37, -77, 191 }, // 223 - { 242, 153, -37, -78, 193 }, // 224 - { 243, 154, -37, -78, 195 }, // 225 - { 244, 156, -38, -79, 197 }, // 226 - { 245, 158, -38, -80, 199 }, // 227 - { 246, 159, -39, -81, 201 }, // 228 - { 247, 161, -39, -82, 203 }, // 229 - { 249, 162, -39, -82, 205 }, // 230 - { 250, 164, -40, -83, 207 }, // 231 - { 251, 165, -40, -84, 209 }, // 232 - { 252, 167, -41, -85, 211 }, // 233 - { 253, 169, -41, -86, 213 }, // 234 - { 254, 170, -41, -86, 215 }, // 235 - { 256, 172, -42, -87, 217 }, // 236 - { 257, 173, -42, -88, 219 }, // 237 - { 258, 175, -43, -89, 221 }, // 238 - { 259, 177, -43, -90, 223 }, // 239 - { 260, 178, -43, -91, 226 }, // 240 - { 261, 180, -44, -91, 228 }, // 241 - { 263, 181, -44, -92, 230 }, // 242 - { 264, 183, -44, -93, 232 }, // 243 - { 265, 185, -45, -94, 234 }, // 244 - { 266, 186, -45, -95, 236 }, // 245 - { 267, 188, -46, -95, 238 }, // 246 - { 268, 189, -46, -96, 240 }, // 247 - { 270, 191, -46, -97, 242 }, // 248 - { 271, 193, -47, -98, 244 }, // 249 - { 272, 194, -47, -99, 246 }, // 250 - { 273, 196, -48, -99, 248 }, // 251 - { 274, 197, -48, -100, 250 }, // 252 - { 275, 199, -48, -101, 252 }, // 253 - { 277, 201, -49, -102, 254 }, // 254 - { 278, 202, -49, -103, 256 } // 255 -}; - -#define YUYV_CONSTRAIN(v) ((v)<0)?0:(((v)>255)?255:(v)) - -void IRAM_ATTR yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b) -{ - int16_t ri, gi, bi; - - ri = yuv_table[y].vY + yuv_table[v].vVr; - gi = yuv_table[y].vY + yuv_table[u].vUg + yuv_table[v].vVg; - bi = yuv_table[y].vY + yuv_table[u].vUb; - - *r = YUYV_CONSTRAIN(ri); - *g = YUYV_CONSTRAIN(gi); - *b = YUYV_CONSTRAIN(bi); -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c deleted file mode 100644 index d9bb7cf680..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/cam_hal.c +++ /dev/null @@ -1,514 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include "esp_heap_caps.h" -#include "ll_cam.h" -#include "cam_hal.h" - -#if (ESP_IDF_VERSION_MAJOR == 3) && (ESP_IDF_VERSION_MINOR == 3) -#include "rom/ets_sys.h" -#else -#include "esp_timer.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0 -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/ets_sys.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/ets_sys.h" -#endif -#endif // ESP_IDF_VERSION_MAJOR -#define ESP_CAMERA_ETS_PRINTF ets_printf - -#if CONFIG_CAMERA_TASK_STACK_SIZE -#define CAM_TASK_STACK CONFIG_CAMERA_TASK_STACK_SIZE -#else -#define CAM_TASK_STACK (2*1024) -#endif - -static const char *TAG = "cam_hal"; -static cam_obj_t *cam_obj = NULL; - -static const uint32_t JPEG_SOI_MARKER = 0xFFD8FF; // written in little-endian for esp32 -static const uint16_t JPEG_EOI_MARKER = 0xD9FF; // written in little-endian for esp32 - -static int cam_verify_jpeg_soi(const uint8_t *inbuf, uint32_t length) -{ - for (uint32_t i = 0; i < length; i++) { - if (memcmp(&inbuf[i], &JPEG_SOI_MARKER, 3) == 0) { - //ESP_LOGW(TAG, "SOI: %d", (int) i); - return i; - } - } - ESP_LOGW(TAG, "NO-SOI"); - return -1; -} - -static int cam_verify_jpeg_eoi(const uint8_t *inbuf, uint32_t length) -{ - int offset = -1; - uint8_t *dptr = (uint8_t *)inbuf + length - 2; - while (dptr > inbuf) { - if (memcmp(dptr, &JPEG_EOI_MARKER, 2) == 0) { - offset = dptr - inbuf; - //ESP_LOGW(TAG, "EOI: %d", length - (offset + 2)); - return offset; - } - dptr--; - } - return -1; -} - -static bool cam_get_next_frame(int * frame_pos) -{ - if(!cam_obj->frames[*frame_pos].en){ - for (int x = 0; x < cam_obj->frame_cnt; x++) { - if (cam_obj->frames[x].en) { - *frame_pos = x; - return true; - } - } - } else { - return true; - } - return false; -} - -static bool cam_start_frame(int * frame_pos) -{ - if (cam_get_next_frame(frame_pos)) { - if(ll_cam_start(cam_obj, *frame_pos)){ - // Vsync the frame manually - ll_cam_do_vsync(cam_obj); - uint64_t us = (uint64_t)esp_timer_get_time(); - cam_obj->frames[*frame_pos].fb.timestamp.tv_sec = us / 1000000UL; - cam_obj->frames[*frame_pos].fb.timestamp.tv_usec = us % 1000000UL; - return true; - } - } - return false; -} - -void IRAM_ATTR ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken) -{ - if (xQueueSendFromISR(cam->event_queue, (void *)&cam_event, HPTaskAwoken) != pdTRUE) { - ll_cam_stop(cam); - cam->state = CAM_STATE_IDLE; - ESP_CAMERA_ETS_PRINTF(DRAM_STR("cam_hal: EV-%s-OVF\r\n"), cam_event==CAM_IN_SUC_EOF_EVENT ? DRAM_STR("EOF") : DRAM_STR("VSYNC")); - } -} - -//Copy fram from DMA dma_buffer to fram dma_buffer -static void cam_task(void *arg) -{ - int cnt = 0; - int frame_pos = 0; - cam_obj->state = CAM_STATE_IDLE; - cam_event_t cam_event = 0; - - xQueueReset(cam_obj->event_queue); - - while (1) { - xQueueReceive(cam_obj->event_queue, (void *)&cam_event, portMAX_DELAY); - DBG_PIN_SET(1); - switch (cam_obj->state) { - - case CAM_STATE_IDLE: { - if (cam_event == CAM_VSYNC_EVENT) { - //DBG_PIN_SET(1); - if(cam_start_frame(&frame_pos)){ - cam_obj->frames[frame_pos].fb.len = 0; - cam_obj->state = CAM_STATE_READ_BUF; - } - cnt = 0; - } - } - break; - - case CAM_STATE_READ_BUF: { - camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb; - size_t pixels_per_dma = (cam_obj->dma_half_buffer_size * cam_obj->fb_bytes_per_pixel) / (cam_obj->dma_bytes_per_item * cam_obj->in_bytes_per_pixel); - - if (cam_event == CAM_IN_SUC_EOF_EVENT) { - if(!cam_obj->psram_mode){ - if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) { - ESP_LOGW(TAG, "FB-OVF"); - ll_cam_stop(cam_obj); - DBG_PIN_SET(0); - continue; - } - frame_buffer_event->len += ll_cam_memcpy(cam_obj, - &frame_buffer_event->buf[frame_buffer_event->len], - &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size], - cam_obj->dma_half_buffer_size); - } - //Check for JPEG SOI in the first buffer. stop if not found - if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) { - ll_cam_stop(cam_obj); - cam_obj->state = CAM_STATE_IDLE; - } - cnt++; - - } else if (cam_event == CAM_VSYNC_EVENT) { - //DBG_PIN_SET(1); - ll_cam_stop(cam_obj); - - if (cnt || !cam_obj->jpeg_mode || cam_obj->psram_mode) { - if (cam_obj->jpeg_mode) { - if (!cam_obj->psram_mode) { - if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) { - ESP_LOGW(TAG, "FB-OVF"); - cnt--; - } else { - frame_buffer_event->len += ll_cam_memcpy(cam_obj, - &frame_buffer_event->buf[frame_buffer_event->len], - &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size], - cam_obj->dma_half_buffer_size); - } - } - cnt++; - } - - cam_obj->frames[frame_pos].en = 0; - - if (cam_obj->psram_mode) { - if (cam_obj->jpeg_mode) { - frame_buffer_event->len = cnt * cam_obj->dma_half_buffer_size; - } else { - frame_buffer_event->len = cam_obj->recv_size; - } - } else if (!cam_obj->jpeg_mode) { - if (frame_buffer_event->len != cam_obj->fb_size) { - cam_obj->frames[frame_pos].en = 1; - ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, (unsigned) cam_obj->fb_size); - } - } - //send frame - if(!cam_obj->frames[frame_pos].en && xQueueSend(cam_obj->frame_buffer_queue, (void *)&frame_buffer_event, 0) != pdTRUE) { - //pop frame buffer from the queue - camera_fb_t * fb2 = NULL; - if(xQueueReceive(cam_obj->frame_buffer_queue, &fb2, 0) == pdTRUE) { - //push the new frame to the end of the queue - if (xQueueSend(cam_obj->frame_buffer_queue, (void *)&frame_buffer_event, 0) != pdTRUE) { - cam_obj->frames[frame_pos].en = 1; - ESP_LOGE(TAG, "FBQ-SND"); - } - //free the popped buffer - cam_give(fb2); - } else { - //queue is full and we could not pop a frame from it - cam_obj->frames[frame_pos].en = 1; - ESP_LOGE(TAG, "FBQ-RCV"); - } - } - } - - if(!cam_start_frame(&frame_pos)){ - cam_obj->state = CAM_STATE_IDLE; - } else { - cam_obj->frames[frame_pos].fb.len = 0; - } - cnt = 0; - } - } - break; - } - DBG_PIN_SET(0); - } -} - -static lldesc_t * allocate_dma_descriptors(uint32_t count, uint16_t size, uint8_t * buffer) -{ - lldesc_t *dma = (lldesc_t *)heap_caps_malloc(count * sizeof(lldesc_t), MALLOC_CAP_DMA); - if (dma == NULL) { - return dma; - } - - for (int x = 0; x < count; x++) { - dma[x].size = size; - dma[x].length = 0; - dma[x].sosf = 0; - dma[x].eof = 0; - dma[x].owner = 1; - dma[x].buf = (buffer + size * x); - dma[x].empty = (uint32_t)&dma[(x + 1) % count]; - } - return dma; -} - -static esp_err_t cam_dma_config(const camera_config_t *config) -{ - bool ret = ll_cam_dma_sizes(cam_obj); - if (0 == ret) { - return ESP_FAIL; - } - - cam_obj->dma_node_cnt = (cam_obj->dma_buffer_size) / cam_obj->dma_node_buffer_size; // Number of DMA nodes - cam_obj->frame_copy_cnt = cam_obj->recv_size / cam_obj->dma_half_buffer_size; // Number of interrupted copies, ping-pong copy - - ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d", - (int) cam_obj->dma_buffer_size, (int) cam_obj->dma_half_buffer_size, (int) cam_obj->dma_node_buffer_size, - (int) cam_obj->dma_node_cnt, (int) cam_obj->frame_copy_cnt); - - cam_obj->dma_buffer = NULL; - cam_obj->dma = NULL; - - cam_obj->frames = (cam_frame_t *)heap_caps_calloc(1, cam_obj->frame_cnt * sizeof(cam_frame_t), MALLOC_CAP_DEFAULT); - CAM_CHECK(cam_obj->frames != NULL, "frames malloc failed", ESP_FAIL); - - uint8_t dma_align = 0; - size_t fb_size = cam_obj->fb_size; - if (cam_obj->psram_mode) { - dma_align = ll_cam_get_dma_align(cam_obj); - if (cam_obj->fb_size < cam_obj->recv_size) { - fb_size = cam_obj->recv_size; - } - } - - /* Allocate memory for frame buffer */ - size_t alloc_size = fb_size * sizeof(uint8_t) + dma_align; - uint32_t _caps = MALLOC_CAP_8BIT; - if (CAMERA_FB_IN_DRAM == config->fb_location) { - _caps |= MALLOC_CAP_INTERNAL; - } else { - _caps |= MALLOC_CAP_SPIRAM; - } - for (int x = 0; x < cam_obj->frame_cnt; x++) { - cam_obj->frames[x].dma = NULL; - cam_obj->frames[x].fb_offset = 0; - cam_obj->frames[x].en = 0; - ESP_LOGI(TAG, "Allocating %d Byte frame buffer in %s", alloc_size, _caps & MALLOC_CAP_SPIRAM ? "PSRAM" : "OnBoard RAM"); -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) - // In IDF v4.2 and earlier, memory returned by heap_caps_aligned_alloc must be freed using heap_caps_aligned_free. - // And heap_caps_aligned_free is deprecated on v4.3. - cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_aligned_alloc(16, alloc_size, _caps); -#else - cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(alloc_size, _caps); -#endif - CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL); - if (cam_obj->psram_mode) { - //align PSRAM buffer. TODO: save the offset so proper address can be freed later - cam_obj->frames[x].fb_offset = dma_align - ((uint32_t)cam_obj->frames[x].fb.buf & (dma_align - 1)); - cam_obj->frames[x].fb.buf += cam_obj->frames[x].fb_offset; - ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (unsigned) cam_obj->frames[x].fb.buf); - cam_obj->frames[x].dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->frames[x].fb.buf); - CAM_CHECK(cam_obj->frames[x].dma != NULL, "frame dma malloc failed", ESP_FAIL); - } - cam_obj->frames[x].en = 1; - } - - if (!cam_obj->psram_mode) { - cam_obj->dma_buffer = (uint8_t *)heap_caps_malloc(cam_obj->dma_buffer_size * sizeof(uint8_t), MALLOC_CAP_DMA); - if(NULL == cam_obj->dma_buffer) { - ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__, - (int) cam_obj->dma_buffer_size, (int) heap_caps_get_largest_free_block(MALLOC_CAP_DMA)); - return ESP_FAIL; - } - - cam_obj->dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->dma_buffer); - CAM_CHECK(cam_obj->dma != NULL, "dma malloc failed", ESP_FAIL); - } - - return ESP_OK; -} - -esp_err_t cam_init(const camera_config_t *config) -{ - CAM_CHECK(NULL != config, "config pointer is invalid", ESP_ERR_INVALID_ARG); - - esp_err_t ret = ESP_OK; - cam_obj = (cam_obj_t *)heap_caps_calloc(1, sizeof(cam_obj_t), MALLOC_CAP_DMA); - CAM_CHECK(NULL != cam_obj, "lcd_cam object malloc error", ESP_ERR_NO_MEM); - - cam_obj->swap_data = 0; - cam_obj->vsync_pin = config->pin_vsync; - cam_obj->vsync_invert = true; - - ll_cam_set_pin(cam_obj, config); - ret = ll_cam_config(cam_obj, config); - CAM_CHECK_GOTO(ret == ESP_OK, "ll_cam initialize failed", err); - -#if CAMERA_DBG_PIN_ENABLE - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[DBG_PIN_NUM], PIN_FUNC_GPIO); - gpio_set_direction(DBG_PIN_NUM, GPIO_MODE_OUTPUT); - gpio_set_pull_mode(DBG_PIN_NUM, GPIO_FLOATING); -#endif - - ESP_LOGI(TAG, "cam init ok"); - return ESP_OK; - -err: - free(cam_obj); - cam_obj = NULL; - return ESP_FAIL; -} - -esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid) -{ - CAM_CHECK(NULL != config, "config pointer is invalid", ESP_ERR_INVALID_ARG); - esp_err_t ret = ESP_OK; - - ret = ll_cam_set_sample_mode(cam_obj, (pixformat_t)config->pixel_format, config->xclk_freq_hz, sensor_pid); - - cam_obj->jpeg_mode = config->pixel_format == PIXFORMAT_JPEG; -#if CONFIG_IDF_TARGET_ESP32 - cam_obj->psram_mode = false; -#else - cam_obj->psram_mode = (config->xclk_freq_hz == 16000000); -#endif - cam_obj->frame_cnt = config->fb_count; - cam_obj->width = resolution[frame_size].width; - cam_obj->height = resolution[frame_size].height; - - if(cam_obj->jpeg_mode){ - cam_obj->recv_size = cam_obj->width * cam_obj->height / 5; - cam_obj->fb_size = cam_obj->recv_size; - } else { - cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel; - cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel; - } - - ret = cam_dma_config(config); - CAM_CHECK_GOTO(ret == ESP_OK, "cam_dma_config failed", err); - - size_t queue_size = cam_obj->dma_half_buffer_cnt - 1; - if (queue_size == 0) { - queue_size = 1; - } - cam_obj->event_queue = xQueueCreate(queue_size, sizeof(cam_event_t)); - CAM_CHECK_GOTO(cam_obj->event_queue != NULL, "event_queue create failed", err); - - size_t frame_buffer_queue_len = cam_obj->frame_cnt; - if (config->grab_mode == CAMERA_GRAB_LATEST && cam_obj->frame_cnt > 1) { - frame_buffer_queue_len = cam_obj->frame_cnt - 1; - } - cam_obj->frame_buffer_queue = xQueueCreate(frame_buffer_queue_len, sizeof(camera_fb_t*)); - CAM_CHECK_GOTO(cam_obj->frame_buffer_queue != NULL, "frame_buffer_queue create failed", err); - - ret = ll_cam_init_isr(cam_obj); - CAM_CHECK_GOTO(ret == ESP_OK, "cam intr alloc failed", err); - - -#if CONFIG_CAMERA_CORE0 - xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0); -#elif CONFIG_CAMERA_CORE1 - xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1); -#else - xTaskCreate(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle); -#endif - - ESP_LOGI(TAG, "cam config ok"); - return ESP_OK; - -err: - cam_deinit(); - return ESP_FAIL; -} - -esp_err_t cam_deinit(void) -{ - if (!cam_obj) { - return ESP_FAIL; - } - - cam_stop(); - if (cam_obj->task_handle) { - vTaskDelete(cam_obj->task_handle); - } - if (cam_obj->event_queue) { - vQueueDelete(cam_obj->event_queue); - } - if (cam_obj->frame_buffer_queue) { - vQueueDelete(cam_obj->frame_buffer_queue); - } - - ll_cam_deinit(cam_obj); - - if (cam_obj->dma) { - free(cam_obj->dma); - } - if (cam_obj->dma_buffer) { - free(cam_obj->dma_buffer); - } - if (cam_obj->frames) { - for (int x = 0; x < cam_obj->frame_cnt; x++) { - free(cam_obj->frames[x].fb.buf - cam_obj->frames[x].fb_offset); - if (cam_obj->frames[x].dma) { - free(cam_obj->frames[x].dma); - } - } - free(cam_obj->frames); - } - - free(cam_obj); - cam_obj = NULL; - return ESP_OK; -} - -void cam_stop(void) -{ - ll_cam_vsync_intr_enable(cam_obj, false); - ll_cam_stop(cam_obj); -} - -void cam_start(void) -{ - ll_cam_vsync_intr_enable(cam_obj, true); -} - -camera_fb_t *cam_take(TickType_t timeout) -{ - camera_fb_t *dma_buffer = NULL; - TickType_t start = xTaskGetTickCount(); - xQueueReceive(cam_obj->frame_buffer_queue, (void *)&dma_buffer, timeout); - if (dma_buffer) { - if(cam_obj->jpeg_mode){ - // find the end marker for JPEG. Data after that can be discarded - int offset_e = cam_verify_jpeg_eoi(dma_buffer->buf, dma_buffer->len); - if (offset_e >= 0) { - // adjust buffer length - dma_buffer->len = offset_e + sizeof(JPEG_EOI_MARKER); - return dma_buffer; - } else { - ESP_LOGW(TAG, "NO-EOI"); - cam_give(dma_buffer); - return cam_take(timeout - (xTaskGetTickCount() - start));//recurse!!!! - } - } else if(cam_obj->psram_mode && cam_obj->in_bytes_per_pixel != cam_obj->fb_bytes_per_pixel){ - //currently this is used only for YUV to GRAYSCALE - dma_buffer->len = ll_cam_memcpy(cam_obj, dma_buffer->buf, dma_buffer->buf, dma_buffer->len); - } - return dma_buffer; - } else { - ESP_LOGW(TAG, "Failed to get the frame on time!"); - } - return NULL; -} - -void cam_give(camera_fb_t *dma_buffer) -{ - for (int x = 0; x < cam_obj->frame_cnt; x++) { - if (&cam_obj->frames[x].fb == dma_buffer) { - cam_obj->frames[x].en = 1; - break; - } - } -} - -void cam_give_all(void) { - for (int x = 0; x < cam_obj->frame_cnt; x++) { - cam_obj->frames[x].en = 1; - } -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c deleted file mode 100644 index 4b7e906a57..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/esp_camera.c +++ /dev/null @@ -1,486 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include -#include -#include -#include "time.h" -#include "sys/time.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "esp_system.h" -#include "nvs_flash.h" -#include "nvs.h" -#include "sensor.h" -#include "sccb.h" -#include "cam_hal.h" -#include "esp_camera.h" -#include "xclk.h" -#if CONFIG_OV2640_SUPPORT -#include "ov2640.h" -#endif -#if CONFIG_OV7725_SUPPORT -#include "ov7725.h" -#endif -#if CONFIG_OV3660_SUPPORT -#include "ov3660.h" -#endif -#if CONFIG_OV5640_SUPPORT -#include "ov5640.h" -#endif -#if CONFIG_NT99141_SUPPORT -#include "nt99141.h" -#endif -#if CONFIG_OV7670_SUPPORT -#include "ov7670.h" -#endif -#if CONFIG_GC2145_SUPPORT -#include "gc2145.h" -#endif -#if CONFIG_GC032A_SUPPORT -#include "gc032a.h" -#endif -#if CONFIG_GC0308_SUPPORT -#include "gc0308.h" -#endif -#if CONFIG_BF3005_SUPPORT -#include "bf3005.h" -#endif -#if CONFIG_BF20A6_SUPPORT -#include "bf20a6.h" -#endif -#if CONFIG_SC101IOT_SUPPORT -#include "sc101iot.h" -#endif -#if CONFIG_SC030IOT_SUPPORT -#include "sc030iot.h" -#endif -#if CONFIG_SC031GS_SUPPORT -#include "sc031gs.h" -#endif - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#define TAG "" -#else -#include "esp_log.h" -static const char *TAG = "camera"; -#endif - -typedef struct { - sensor_t sensor; - camera_fb_t fb; -} camera_state_t; - -static const char *CAMERA_SENSOR_NVS_KEY = "sensor"; -static const char *CAMERA_PIXFORMAT_NVS_KEY = "pixformat"; -static camera_state_t *s_state = NULL; - -#if CONFIG_IDF_TARGET_ESP32S3 // LCD_CAM module of ESP32-S3 will generate xclk -#define CAMERA_ENABLE_OUT_CLOCK(v) -#define CAMERA_DISABLE_OUT_CLOCK() -#else -#define CAMERA_ENABLE_OUT_CLOCK(v) camera_enable_out_clock((v)) -#define CAMERA_DISABLE_OUT_CLOCK() camera_disable_out_clock() -#endif - -typedef struct { - int (*detect)(int slv_addr, sensor_id_t *id); - int (*init)(sensor_t *sensor); -} sensor_func_t; - -static const sensor_func_t g_sensors[] = { -#if CONFIG_OV7725_SUPPORT - {ov7725_detect, ov7725_init}, -#endif -#if CONFIG_OV7670_SUPPORT - {ov7670_detect, ov7670_init}, -#endif -#if CONFIG_OV2640_SUPPORT - {ov2640_detect, ov2640_init}, -#endif -#if CONFIG_OV3660_SUPPORT - {ov3660_detect, ov3660_init}, -#endif -#if CONFIG_OV5640_SUPPORT - {ov5640_detect, ov5640_init}, -#endif -#if CONFIG_NT99141_SUPPORT - {nt99141_detect, nt99141_init}, -#endif -#if CONFIG_GC2145_SUPPORT - {gc2145_detect, gc2145_init}, -#endif -#if CONFIG_GC032A_SUPPORT - {gc032a_detect, gc032a_init}, -#endif -#if CONFIG_GC0308_SUPPORT - {gc0308_detect, gc0308_init}, -#endif -#if CONFIG_BF3005_SUPPORT - {bf3005_detect, bf3005_init}, -#endif -#if CONFIG_BF20A6_SUPPORT - {bf20a6_detect, bf20a6_init}, -#endif -#if CONFIG_SC101IOT_SUPPORT - {sc101iot_detect, sc101iot_init}, -#endif -#if CONFIG_SC030IOT_SUPPORT - {sc030iot_detect, sc030iot_init}, -#endif -#if CONFIG_SC031GS_SUPPORT - {sc031gs_detect, sc031gs_init}, -#endif -}; - -static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model) -{ - esp_err_t ret = ESP_OK; - *out_camera_model = CAMERA_NONE; - if (s_state != NULL) { - return ESP_ERR_INVALID_STATE; - } - - s_state = (camera_state_t *) calloc(sizeof(camera_state_t), 1); - if (!s_state) { - return ESP_ERR_NO_MEM; - } - - if (config->pin_xclk >= 0) { - ESP_LOGD(TAG, "Enabling XCLK output"); - CAMERA_ENABLE_OUT_CLOCK(config); - } - - if (config->pin_sccb_sda != -1) { - ESP_LOGD(TAG, "Initializing SCCB"); - ret = SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl); - } else { - ESP_LOGD(TAG, "Using existing I2C port"); - ret = SCCB_Use_Port(config->sccb_i2c_port); - } - - if(ret != ESP_OK) { - ESP_LOGE(TAG, "sccb init err"); - goto err; - } - - if (config->pin_pwdn >= 0) { - ESP_LOGD(TAG, "Resetting camera by power down line"); - gpio_config_t conf = { 0 }; - conf.pin_bit_mask = 1LL << config->pin_pwdn; - conf.mode = GPIO_MODE_OUTPUT; - gpio_config(&conf); - - // carefull, logic is inverted compared to reset pin - gpio_set_level(config->pin_pwdn, 1); - vTaskDelay(10 / portTICK_PERIOD_MS); - gpio_set_level(config->pin_pwdn, 0); - vTaskDelay(10 / portTICK_PERIOD_MS); - } - - if (config->pin_reset >= 0) { - ESP_LOGD(TAG, "Resetting camera"); - gpio_config_t conf = { 0 }; - conf.pin_bit_mask = 1LL << config->pin_reset; - conf.mode = GPIO_MODE_OUTPUT; - gpio_config(&conf); - - gpio_set_level(config->pin_reset, 0); - vTaskDelay(10 / portTICK_PERIOD_MS); - gpio_set_level(config->pin_reset, 1); - vTaskDelay(10 / portTICK_PERIOD_MS); - } - - ESP_LOGD(TAG, "Searching for camera address"); - vTaskDelay(10 / portTICK_PERIOD_MS); - - uint8_t slv_addr = SCCB_Probe(); - - if (slv_addr == 0) { - ret = ESP_ERR_NOT_FOUND; - goto err; - } - - ESP_LOGI(TAG, "Detected camera at address=0x%02x", slv_addr); - s_state->sensor.slv_addr = slv_addr; - s_state->sensor.xclk_freq_hz = config->xclk_freq_hz; - - /** - * Read sensor ID and then initialize sensor - * Attention: Some sensors have the same SCCB address. Therefore, several attempts may be made in the detection process - */ - sensor_id_t *id = &s_state->sensor.id; - for (size_t i = 0; i < sizeof(g_sensors) / sizeof(sensor_func_t); i++) { - if (g_sensors[i].detect(slv_addr, id)) { - camera_sensor_info_t *info = esp_camera_sensor_get_info(id); - if (NULL != info) { - *out_camera_model = info->model; - ESP_LOGI(TAG, "Detected %s camera", info->name); - g_sensors[i].init(&s_state->sensor); - break; - } - } - } - - if (CAMERA_NONE == *out_camera_model) { //If no supported sensors are detected - ESP_LOGE(TAG, "Detected camera not supported."); - ret = ESP_ERR_NOT_SUPPORTED; - goto err; - } - - ESP_LOGI(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x", - id->PID, id->VER, id->MIDH, id->MIDL); - - ESP_LOGD(TAG, "Doing SW reset of sensor"); - vTaskDelay(10 / portTICK_PERIOD_MS); - - return s_state->sensor.reset(&s_state->sensor); -err : - CAMERA_DISABLE_OUT_CLOCK(); - return ret; -} - -#if CONFIG_CAMERA_CONVERTER_ENABLED -static pixformat_t get_output_data_format(camera_conv_mode_t conv_mode) -{ - pixformat_t format = PIXFORMAT_RGB565; - switch (conv_mode) { - case YUV422_TO_YUV420: - format = PIXFORMAT_YUV420; - break; - case YUV422_TO_RGB565: // default format is RGB565 - default: - break; - } - ESP_LOGD(TAG, "Convert to %d format enabled", format); - return format; -} -#endif - -esp_err_t esp_camera_init(const camera_config_t *config) -{ - esp_err_t err; - err = cam_init(config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); - return err; - } - - camera_model_t camera_model = CAMERA_NONE; - err = camera_probe(config, &camera_model); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Camera probe failed with error 0x%x(%s)", err, esp_err_to_name(err)); - goto fail; - } - - framesize_t frame_size = (framesize_t) config->frame_size; - pixformat_t pix_format = (pixformat_t) config->pixel_format; - - if (PIXFORMAT_JPEG == pix_format && (!camera_sensor[camera_model].support_jpeg)) { - ESP_LOGE(TAG, "JPEG format is not supported on this sensor"); - err = ESP_ERR_NOT_SUPPORTED; - goto fail; - } - - if (frame_size > camera_sensor[camera_model].max_size) { - ESP_LOGW(TAG, "The frame size exceeds the maximum for this sensor, it will be forced to the maximum possible value"); - frame_size = camera_sensor[camera_model].max_size; - } - - err = cam_config(config, frame_size, s_state->sensor.id.PID); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Camera config failed with error 0x%x", err); - goto fail; - } - - s_state->sensor.status.framesize = frame_size; - s_state->sensor.pixformat = pix_format; - - ESP_LOGD(TAG, "Setting frame size to %dx%d", resolution[frame_size].width, resolution[frame_size].height); - if (s_state->sensor.set_framesize(&s_state->sensor, frame_size) != 0) { - ESP_LOGE(TAG, "Failed to set frame size"); - err = ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE; - goto fail; - } - s_state->sensor.set_pixformat(&s_state->sensor, pix_format); -#if CONFIG_CAMERA_CONVERTER_ENABLED - if(config->conv_mode) { - s_state->sensor.pixformat = get_output_data_format(config->conv_mode); // If conversion enabled, change the out data format by conversion mode - } -#endif - - if (s_state->sensor.id.PID == OV2640_PID) { - s_state->sensor.set_gainceiling(&s_state->sensor, GAINCEILING_2X); - s_state->sensor.set_bpc(&s_state->sensor, false); - s_state->sensor.set_wpc(&s_state->sensor, true); - s_state->sensor.set_lenc(&s_state->sensor, true); - } - - if (pix_format == PIXFORMAT_JPEG) { - s_state->sensor.set_quality(&s_state->sensor, config->jpeg_quality); - } - s_state->sensor.init_status(&s_state->sensor); - - cam_start(); - - return ESP_OK; - -fail: - esp_camera_deinit(); - return err; -} - -esp_err_t esp_camera_deinit() -{ - esp_err_t ret = cam_deinit(); - CAMERA_DISABLE_OUT_CLOCK(); - if (s_state) { - SCCB_Deinit(); - - free(s_state); - s_state = NULL; - } - - return ret; -} - -#define FB_GET_TIMEOUT (4000 / portTICK_PERIOD_MS) - -camera_fb_t *esp_camera_fb_get() -{ - if (s_state == NULL) { - return NULL; - } - camera_fb_t *fb = cam_take(FB_GET_TIMEOUT); - //set the frame properties - if (fb) { - fb->width = resolution[s_state->sensor.status.framesize].width; - fb->height = resolution[s_state->sensor.status.framesize].height; - fb->format = s_state->sensor.pixformat; - } - return fb; -} - -void esp_camera_fb_return(camera_fb_t *fb) -{ - if (s_state == NULL) { - return; - } - cam_give(fb); -} - -sensor_t *esp_camera_sensor_get() -{ - if (s_state == NULL) { - return NULL; - } - return &s_state->sensor; -} - -esp_err_t esp_camera_save_to_nvs(const char *key) -{ -#if ESP_IDF_VERSION_MAJOR > 3 - nvs_handle_t handle; -#else - nvs_handle handle; -#endif - esp_err_t ret = nvs_open(key, NVS_READWRITE, &handle); - - if (ret == ESP_OK) { - sensor_t *s = esp_camera_sensor_get(); - if (s != NULL) { - ret = nvs_set_blob(handle, CAMERA_SENSOR_NVS_KEY, &s->status, sizeof(camera_status_t)); - if (ret == ESP_OK) { - uint8_t pf = s->pixformat; - ret = nvs_set_u8(handle, CAMERA_PIXFORMAT_NVS_KEY, pf); - } - return ret; - } else { - return ESP_ERR_CAMERA_NOT_DETECTED; - } - nvs_close(handle); - return ret; - } else { - return ret; - } -} - -esp_err_t esp_camera_load_from_nvs(const char *key) -{ -#if ESP_IDF_VERSION_MAJOR > 3 - nvs_handle_t handle; -#else - nvs_handle handle; -#endif - uint8_t pf; - - esp_err_t ret = nvs_open(key, NVS_READWRITE, &handle); - - if (ret == ESP_OK) { - sensor_t *s = esp_camera_sensor_get(); - camera_status_t st; - if (s != NULL) { - size_t size = sizeof(camera_status_t); - ret = nvs_get_blob(handle, CAMERA_SENSOR_NVS_KEY, &st, &size); - if (ret == ESP_OK) { - s->set_ae_level(s, st.ae_level); - s->set_aec2(s, st.aec2); - s->set_aec_value(s, st.aec_value); - s->set_agc_gain(s, st.agc_gain); - s->set_awb_gain(s, st.awb_gain); - s->set_bpc(s, st.bpc); - s->set_brightness(s, st.brightness); - s->set_colorbar(s, st.colorbar); - s->set_contrast(s, st.contrast); - s->set_dcw(s, st.dcw); - s->set_denoise(s, st.denoise); - s->set_exposure_ctrl(s, st.aec); - s->set_framesize(s, st.framesize); - s->set_gain_ctrl(s, st.agc); - s->set_gainceiling(s, st.gainceiling); - s->set_hmirror(s, st.hmirror); - s->set_lenc(s, st.lenc); - s->set_quality(s, st.quality); - s->set_raw_gma(s, st.raw_gma); - s->set_saturation(s, st.saturation); - s->set_sharpness(s, st.sharpness); - s->set_special_effect(s, st.special_effect); - s->set_vflip(s, st.vflip); - s->set_wb_mode(s, st.wb_mode); - s->set_whitebal(s, st.awb); - s->set_wpc(s, st.wpc); - } - ret = nvs_get_u8(handle, CAMERA_PIXFORMAT_NVS_KEY, &pf); - if (ret == ESP_OK) { - s->set_pixformat(s, pf); - } - } else { - return ESP_ERR_CAMERA_NOT_DETECTED; - } - nvs_close(handle); - return ret; - } else { - ESP_LOGW(TAG, "Error (%d) opening nvs key \"%s\"", ret, key); - return ret; - } -} - -void esp_camera_return_all(void) { - if (s_state == NULL) { - return; - } - cam_give_all(); -} - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h deleted file mode 100644 index ce031c88d4..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/esp_camera.h +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -/* - * Example Use - * - static camera_config_t camera_example_config = { - .pin_pwdn = PIN_PWDN, - .pin_reset = PIN_RESET, - .pin_xclk = PIN_XCLK, - .pin_sccb_sda = PIN_SIOD, - .pin_sccb_scl = PIN_SIOC, - .pin_d7 = PIN_D7, - .pin_d6 = PIN_D6, - .pin_d5 = PIN_D5, - .pin_d4 = PIN_D4, - .pin_d3 = PIN_D3, - .pin_d2 = PIN_D2, - .pin_d1 = PIN_D1, - .pin_d0 = PIN_D0, - .pin_vsync = PIN_VSYNC, - .pin_href = PIN_HREF, - .pin_pclk = PIN_PCLK, - - .xclk_freq_hz = 20000000, - .ledc_timer = LEDC_TIMER_0, - .ledc_channel = LEDC_CHANNEL_0, - .pixel_format = PIXFORMAT_JPEG, - .frame_size = FRAMESIZE_SVGA, - .jpeg_quality = 10, - .fb_count = 2, - .grab_mode = CAMERA_GRAB_WHEN_EMPTY - }; - - esp_err_t camera_example_init(){ - return esp_camera_init(&camera_example_config); - } - - esp_err_t camera_example_capture(){ - //capture a frame - camera_fb_t * fb = esp_camera_fb_get(); - if (!fb) { - ESP_LOGE(TAG, "Frame buffer could not be acquired"); - return ESP_FAIL; - } - - //replace this with your own function - display_image(fb->width, fb->height, fb->pixformat, fb->buf, fb->len); - - //return the frame buffer back to be reused - esp_camera_fb_return(fb); - - return ESP_OK; - } -*/ - -#pragma once - -#include "esp_err.h" -#include "driver/ledc.h" -#include "sensor.h" -#include "sys/time.h" -#include "sdkconfig.h" - -/** - * @brief define for if chip supports camera - */ -#define ESP_CAMERA_SUPPORTED (CONFIG_IDF_TARGET_ESP32 | CONFIG_IDF_TARGET_ESP32S3 | \ - CONFIG_IDF_TARGET_ESP32S2) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Configuration structure for camera initialization - */ -typedef enum { - CAMERA_GRAB_WHEN_EMPTY, /*!< Fills buffers when they are empty. Less resources but first 'fb_count' frames might be old */ - CAMERA_GRAB_LATEST /*!< Except when 1 frame buffer is used, queue will always contain the last 'fb_count' frames */ -} camera_grab_mode_t; - -/** - * @brief Camera frame buffer location - */ -typedef enum { - CAMERA_FB_IN_PSRAM, /*!< Frame buffer is placed in external PSRAM */ - CAMERA_FB_IN_DRAM /*!< Frame buffer is placed in internal DRAM */ -} camera_fb_location_t; - -#if CONFIG_CAMERA_CONVERTER_ENABLED -/** - * @brief Camera RGB\YUV conversion mode - */ -typedef enum { - CONV_DISABLE, - RGB565_TO_YUV422, - - YUV422_TO_RGB565, - YUV422_TO_YUV420 -} camera_conv_mode_t; -#endif - -/** - * @brief Configuration structure for camera initialization - */ -typedef struct { - int pin_pwdn; /*!< GPIO pin for camera power down line */ - int pin_reset; /*!< GPIO pin for camera reset line */ - int pin_xclk; /*!< GPIO pin for camera XCLK line */ - union { - int pin_sccb_sda; /*!< GPIO pin for camera SDA line */ - int pin_sscb_sda __attribute__((deprecated("please use pin_sccb_sda instead"))); /*!< GPIO pin for camera SDA line (legacy name) */ - }; - union { - int pin_sccb_scl; /*!< GPIO pin for camera SCL line */ - int pin_sscb_scl __attribute__((deprecated("please use pin_sccb_scl instead"))); /*!< GPIO pin for camera SCL line (legacy name) */ - }; - int pin_d7; /*!< GPIO pin for camera D7 line */ - int pin_d6; /*!< GPIO pin for camera D6 line */ - int pin_d5; /*!< GPIO pin for camera D5 line */ - int pin_d4; /*!< GPIO pin for camera D4 line */ - int pin_d3; /*!< GPIO pin for camera D3 line */ - int pin_d2; /*!< GPIO pin for camera D2 line */ - int pin_d1; /*!< GPIO pin for camera D1 line */ - int pin_d0; /*!< GPIO pin for camera D0 line */ - int pin_vsync; /*!< GPIO pin for camera VSYNC line */ - int pin_href; /*!< GPIO pin for camera HREF line */ - int pin_pclk; /*!< GPIO pin for camera PCLK line */ - - int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode */ - - ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */ - ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */ - - pixformat_t pixel_format; /*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */ - framesize_t frame_size; /*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */ - - int jpeg_quality; /*!< Quality of JPEG output. 0-63 lower means higher quality */ - size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */ - camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */ - camera_grab_mode_t grab_mode; /*!< When buffers should be filled */ -#if CONFIG_CAMERA_CONVERTER_ENABLED - camera_conv_mode_t conv_mode; /*!< RGB<->YUV Conversion mode */ -#endif - - int sccb_i2c_port; /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */ -} camera_config_t; - -/** - * @brief Data structure of camera frame buffer - */ -typedef struct { - uint8_t * buf; /*!< Pointer to the pixel data */ - size_t len; /*!< Length of the buffer in bytes */ - size_t width; /*!< Width of the buffer in pixels */ - size_t height; /*!< Height of the buffer in pixels */ - pixformat_t format; /*!< Format of the pixel data */ - struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */ -} camera_fb_t; - -#define ESP_ERR_CAMERA_BASE 0x20000 -#define ESP_ERR_CAMERA_NOT_DETECTED (ESP_ERR_CAMERA_BASE + 1) -#define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2) -#define ESP_ERR_CAMERA_FAILED_TO_SET_OUT_FORMAT (ESP_ERR_CAMERA_BASE + 3) -#define ESP_ERR_CAMERA_NOT_SUPPORTED (ESP_ERR_CAMERA_BASE + 4) - -/** - * @brief Initialize the camera driver - * - * @note call camera_probe before calling this function - * - * This function detects and configures camera over I2C interface, - * allocates framebuffer and DMA buffers, - * initializes parallel I2S input, and sets up DMA descriptors. - * - * Currently this function can only be called once and there is - * no way to de-initialize this module. - * - * @param config Camera configuration parameters - * - * @return ESP_OK on success - */ -esp_err_t esp_camera_init(const camera_config_t* config); - -/** - * @brief Deinitialize the camera driver - * - * @return - * - ESP_OK on success - * - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet - */ -esp_err_t esp_camera_deinit(void); - -/** - * @brief Obtain pointer to a frame buffer. - * - * @return pointer to the frame buffer - */ -camera_fb_t* esp_camera_fb_get(void); - -/** - * @brief Return the frame buffer to be reused again. - * - * @param fb Pointer to the frame buffer - */ -void esp_camera_fb_return(camera_fb_t * fb); - -/** - * @brief Get a pointer to the image sensor control structure - * - * @return pointer to the sensor - */ -sensor_t * esp_camera_sensor_get(void); - -/** - * @brief Save camera settings to non-volatile-storage (NVS) - * - * @param key A unique nvs key name for the camera settings - */ -esp_err_t esp_camera_save_to_nvs(const char *key); - -/** - * @brief Load camera settings from non-volatile-storage (NVS) - * - * @param key A unique nvs key name for the camera settings - */ -esp_err_t esp_camera_load_from_nvs(const char *key); - -/** - * @brief Return all frame buffers to be reused again. - */ -void esp_camera_return_all(void); - - -#ifdef __cplusplus -} -#endif - -#include "img_converters.h" - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h deleted file mode 100644 index 6ab12a21aa..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/include/sensor.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * Sensor abstraction layer. - * - */ -#ifndef __SENSOR_H__ -#define __SENSOR_H__ -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - OV9650_PID = 0x96, - OV7725_PID = 0x77, - OV2640_PID = 0x26, - OV3660_PID = 0x3660, - OV5640_PID = 0x5640, - OV7670_PID = 0x76, - NT99141_PID = 0x1410, - GC2145_PID = 0x2145, - GC032A_PID = 0x232a, - GC0308_PID = 0x9b, - BF3005_PID = 0x30, - BF20A6_PID = 0x20a6, - SC101IOT_PID = 0xda4a, - SC030IOT_PID = 0x9a46, - SC031GS_PID = 0x0031, -} camera_pid_t; - -typedef enum { - CAMERA_OV7725, - CAMERA_OV2640, - CAMERA_OV3660, - CAMERA_OV5640, - CAMERA_OV7670, - CAMERA_NT99141, - CAMERA_GC2145, - CAMERA_GC032A, - CAMERA_GC0308, - CAMERA_BF3005, - CAMERA_BF20A6, - CAMERA_SC101IOT, - CAMERA_SC030IOT, - CAMERA_SC031GS, - CAMERA_MODEL_MAX, - CAMERA_NONE, -} camera_model_t; - -typedef enum { - OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1 - OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1 - OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1 - OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1 - OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1 - NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1 - GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1 - GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1 - GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1 - BF3005_SCCB_ADDR = 0x6E, - BF20A6_SCCB_ADDR = 0x6E, - SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 - SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 - SC031GS_SCCB_ADDR = 0x30, -} camera_sccb_addr_t; - -typedef enum { - PIXFORMAT_RGB565, // 2BPP/RGB565 - PIXFORMAT_YUV422, // 2BPP/YUV422 - PIXFORMAT_YUV420, // 1.5BPP/YUV420 - PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE - PIXFORMAT_JPEG, // JPEG/COMPRESSED - PIXFORMAT_RGB888, // 3BPP/RGB888 - PIXFORMAT_RAW, // RAW - PIXFORMAT_RGB444, // 3BP2P/RGB444 - PIXFORMAT_RGB555, // 3BP2P/RGB555 -} pixformat_t; - -typedef enum { - FRAMESIZE_96X96, // 96x96 - FRAMESIZE_QQVGA, // 160x120 - FRAMESIZE_QCIF, // 176x144 - FRAMESIZE_HQVGA, // 240x176 - FRAMESIZE_240X240, // 240x240 - FRAMESIZE_QVGA, // 320x240 - FRAMESIZE_CIF, // 400x296 - FRAMESIZE_HVGA, // 480x320 - FRAMESIZE_VGA, // 640x480 - FRAMESIZE_SVGA, // 800x600 - FRAMESIZE_XGA, // 1024x768 - FRAMESIZE_HD, // 1280x720 - FRAMESIZE_SXGA, // 1280x1024 - FRAMESIZE_UXGA, // 1600x1200 - // 3MP Sensors - FRAMESIZE_FHD, // 1920x1080 - FRAMESIZE_P_HD, // 720x1280 - FRAMESIZE_P_3MP, // 864x1536 - FRAMESIZE_QXGA, // 2048x1536 - // 5MP Sensors - FRAMESIZE_QHD, // 2560x1440 - FRAMESIZE_WQXGA, // 2560x1600 - FRAMESIZE_P_FHD, // 1080x1920 - FRAMESIZE_QSXGA, // 2560x1920 - FRAMESIZE_INVALID -} framesize_t; - -typedef struct { - const camera_model_t model; - const char *name; - const camera_sccb_addr_t sccb_addr; - const camera_pid_t pid; - const framesize_t max_size; - const bool support_jpeg; -} camera_sensor_info_t; - -typedef enum { - ASPECT_RATIO_4X3, - ASPECT_RATIO_3X2, - ASPECT_RATIO_16X10, - ASPECT_RATIO_5X3, - ASPECT_RATIO_16X9, - ASPECT_RATIO_21X9, - ASPECT_RATIO_5X4, - ASPECT_RATIO_1X1, - ASPECT_RATIO_9X16 -} aspect_ratio_t; - -typedef enum { - GAINCEILING_2X, - GAINCEILING_4X, - GAINCEILING_8X, - GAINCEILING_16X, - GAINCEILING_32X, - GAINCEILING_64X, - GAINCEILING_128X, -} gainceiling_t; - -typedef struct { - uint16_t max_width; - uint16_t max_height; - uint16_t start_x; - uint16_t start_y; - uint16_t end_x; - uint16_t end_y; - uint16_t offset_x; - uint16_t offset_y; - uint16_t total_x; - uint16_t total_y; -} ratio_settings_t; - -typedef struct { - const uint16_t width; - const uint16_t height; - const aspect_ratio_t aspect_ratio; -} resolution_info_t; - -// Resolution table (in sensor.c) -extern const resolution_info_t resolution[]; -// camera sensor table (in sensor.c) -extern const camera_sensor_info_t camera_sensor[]; - -typedef struct { - uint8_t MIDH; - uint8_t MIDL; - uint16_t PID; - uint8_t VER; -} sensor_id_t; - -typedef struct { - framesize_t framesize;//0 - 10 - bool scale; - bool binning; - uint8_t quality;//0 - 63 - int8_t brightness;//-2 - 2 - int8_t contrast;//-2 - 2 - int8_t saturation;//-2 - 2 - int8_t sharpness;//-2 - 2 - uint8_t denoise; - uint8_t special_effect;//0 - 6 - uint8_t wb_mode;//0 - 4 - uint8_t awb; - uint8_t awb_gain; - uint8_t aec; - uint8_t aec2; - int8_t ae_level;//-2 - 2 - uint16_t aec_value;//0 - 1200 - uint8_t agc; - uint8_t agc_gain;//0 - 30 - uint8_t gainceiling;//0 - 6 - uint8_t bpc; - uint8_t wpc; - uint8_t raw_gma; - uint8_t lenc; - uint8_t hmirror; - uint8_t vflip; - uint8_t dcw; - uint8_t colorbar; -} camera_status_t; - -typedef struct _sensor sensor_t; -typedef struct _sensor { - sensor_id_t id; // Sensor ID. - uint8_t slv_addr; // Sensor I2C slave address. - pixformat_t pixformat; - camera_status_t status; - int xclk_freq_hz; - - // Sensor function pointers - int (*init_status) (sensor_t *sensor); - int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful - int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat); - int (*set_framesize) (sensor_t *sensor, framesize_t framesize); - int (*set_contrast) (sensor_t *sensor, int level); - int (*set_brightness) (sensor_t *sensor, int level); - int (*set_saturation) (sensor_t *sensor, int level); - int (*set_sharpness) (sensor_t *sensor, int level); - int (*set_denoise) (sensor_t *sensor, int level); - int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling); - int (*set_quality) (sensor_t *sensor, int quality); - int (*set_colorbar) (sensor_t *sensor, int enable); - int (*set_whitebal) (sensor_t *sensor, int enable); - int (*set_gain_ctrl) (sensor_t *sensor, int enable); - int (*set_exposure_ctrl) (sensor_t *sensor, int enable); - int (*set_hmirror) (sensor_t *sensor, int enable); - int (*set_vflip) (sensor_t *sensor, int enable); - - int (*set_aec2) (sensor_t *sensor, int enable); - int (*set_awb_gain) (sensor_t *sensor, int enable); - int (*set_agc_gain) (sensor_t *sensor, int gain); - int (*set_aec_value) (sensor_t *sensor, int gain); - - int (*set_special_effect) (sensor_t *sensor, int effect); - int (*set_wb_mode) (sensor_t *sensor, int mode); - int (*set_ae_level) (sensor_t *sensor, int level); - - int (*set_dcw) (sensor_t *sensor, int enable); - int (*set_bpc) (sensor_t *sensor, int enable); - int (*set_wpc) (sensor_t *sensor, int enable); - - int (*set_raw_gma) (sensor_t *sensor, int enable); - int (*set_lenc) (sensor_t *sensor, int enable); - - int (*get_reg) (sensor_t *sensor, int reg, int mask); - int (*set_reg) (sensor_t *sensor, int reg, int mask, int value); - int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning); - int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk); - int (*set_xclk) (sensor_t *sensor, int timer, int xclk); -} sensor_t; - -camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id); - -#ifdef __cplusplus -} -#endif - -#endif /* __SENSOR_H__ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h deleted file mode 100644 index cd0d3aaeec..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/cam_hal.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include "esp_camera.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Uninitialize the lcd_cam module - * - * @param handle Provide handle pointer to release resources - * - * @return - * - ESP_OK Success - * - ESP_FAIL Uninitialize fail - */ -esp_err_t cam_deinit(void); - -/** - * @brief Initialize the lcd_cam module - * - * @param config Configurations - see lcd_cam_config_t struct - * - * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_NO_MEM No memory to initialize lcd_cam - * - ESP_FAIL Initialize fail - */ -esp_err_t cam_init(const camera_config_t *config); - -esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid); - -void cam_stop(void); - -void cam_start(void); - -camera_fb_t *cam_take(TickType_t timeout); - -void cam_give(camera_fb_t *dma_buffer); - -void cam_give_all(void); - -#ifdef __cplusplus -} -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h deleted file mode 100644 index f000fba112..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/sccb.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * SCCB (I2C like) driver. - * - */ -#ifndef __SCCB_H__ -#define __SCCB_H__ -#include -int SCCB_Init(int pin_sda, int pin_scl); -int SCCB_Use_Port(int sccb_i2c_port); -int SCCB_Deinit(void); -uint8_t SCCB_Probe(void); -uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); -int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); -uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); -int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); -uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg); -int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data); -#endif // __SCCB_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h deleted file mode 100644 index 922cd7029d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/private_include/xclk.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "esp_system.h" -#include "esp_camera.h" - -esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz); - -esp_err_t camera_enable_out_clock(const camera_config_t *config); - -void camera_disable_out_clock(void); diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c deleted file mode 100644 index 307166d0fb..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sccb.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * SCCB (I2C like) driver. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "sensor.h" -#include -#include "sdkconfig.h" -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "sccb"; -#endif - -#define LITTLETOBIG(x) ((x<<8)|(x>>8)) - -#include "driver/i2c.h" - -// support IDF 5.x -#ifndef portTICK_RATE_MS -#define portTICK_RATE_MS portTICK_PERIOD_MS -#endif - -#define SCCB_FREQ CONFIG_SCCB_CLK_FREQ /*!< I2C master frequency*/ -#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ -#define READ_BIT I2C_MASTER_READ /*!< I2C master read */ -#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ -#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ -#define ACK_VAL 0x0 /*!< I2C ack value */ -#define NACK_VAL 0x1 /*!< I2C nack value */ -#if CONFIG_SCCB_HARDWARE_I2C_PORT1 -const int SCCB_I2C_PORT_DEFAULT = 1; -#else -const int SCCB_I2C_PORT_DEFAULT = 0; -#endif - -static int sccb_i2c_port; -static bool sccb_owns_i2c_port; - -int SCCB_Init(int pin_sda, int pin_scl) -{ - ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); - i2c_config_t conf; - esp_err_t ret; - - memset(&conf, 0, sizeof(i2c_config_t)); - - sccb_i2c_port = SCCB_I2C_PORT_DEFAULT; - sccb_owns_i2c_port = true; - ESP_LOGI(TAG, "sccb_i2c_port=%d", sccb_i2c_port); - - conf.mode = I2C_MODE_MASTER; - conf.sda_io_num = pin_sda; - conf.sda_pullup_en = GPIO_PULLUP_ENABLE; - conf.scl_io_num = pin_scl; - conf.scl_pullup_en = GPIO_PULLUP_ENABLE; - conf.master.clk_speed = SCCB_FREQ; - - if ((ret = i2c_param_config(sccb_i2c_port, &conf)) != ESP_OK) { - return ret; - } - - return i2c_driver_install(sccb_i2c_port, conf.mode, 0, 0, 0); -} - -int SCCB_Use_Port(int i2c_num) { // sccb use an already initialized I2C port - if (sccb_owns_i2c_port) { - SCCB_Deinit(); - } - if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) { - return ESP_ERR_INVALID_ARG; - } - sccb_i2c_port = i2c_num; - return ESP_OK; -} - -int SCCB_Deinit(void) -{ - if (!sccb_owns_i2c_port) { - return ESP_OK; - } - sccb_owns_i2c_port = false; - return i2c_driver_delete(sccb_i2c_port); -} - -uint8_t SCCB_Probe(void) -{ - uint8_t slave_addr = 0x0; - - for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { - if (slave_addr == camera_sensor[i].sccb_addr) { - continue; - } - slave_addr = camera_sensor[i].sccb_addr; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_stop(cmd); - esp_err_t ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if( ret == ESP_OK) { - return slave_addr; - } - } - return 0; -} - -uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) -{ - uint8_t data=0; - esp_err_t ret = ESP_FAIL; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) return -1; - cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); - i2c_master_read_byte(cmd, &data, NACK_VAL); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); - } - return data; -} - -int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) -{ - esp_err_t ret = ESP_FAIL; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); - i2c_master_write_byte(cmd, data, ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); - } - return ret == ESP_OK ? 0 : -1; -} - -uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) -{ - uint8_t data=0; - esp_err_t ret = ESP_FAIL; - uint16_t reg_htons = LITTLETOBIG(reg); - uint8_t *reg_u8 = (uint8_t *)®_htons; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) return -1; - cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); - i2c_master_read_byte(cmd, &data, NACK_VAL); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); - } - return data; -} - -int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) -{ - static uint16_t i = 0; - esp_err_t ret = ESP_FAIL; - uint16_t reg_htons = LITTLETOBIG(reg); - uint8_t *reg_u8 = (uint8_t *)®_htons; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); - i2c_master_write_byte(cmd, data, ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); - } - return ret == ESP_OK ? 0 : -1; -} - -uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg) -{ - uint16_t data = 0; - uint8_t *data_u8 = (uint8_t *)&data; - esp_err_t ret = ESP_FAIL; - uint16_t reg_htons = LITTLETOBIG(reg); - uint8_t *reg_u8 = (uint8_t *)®_htons; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) return -1; - - cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); - i2c_master_read_byte(cmd, &data_u8[1], ACK_VAL); - i2c_master_read_byte(cmd, &data_u8[0], NACK_VAL); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); - } - return data; -} - -int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data) -{ - esp_err_t ret = ESP_FAIL; - uint16_t reg_htons = LITTLETOBIG(reg); - uint8_t *reg_u8 = (uint8_t *)®_htons; - uint16_t data_htons = LITTLETOBIG(data); - uint8_t *data_u8 = (uint8_t *)&data_htons; - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); - i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); - i2c_master_write_byte(cmd, data_u8[0], ACK_CHECK_EN); - i2c_master_write_byte(cmd, data_u8[1], ACK_CHECK_EN); - i2c_master_stop(cmd); - ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); - i2c_cmd_link_delete(cmd); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); - } - return ret == ESP_OK ? 0 : -1; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c deleted file mode 100644 index 23071f6c2c..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/driver/sensor.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include "sensor.h" - -const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { - // The sequence must be consistent with camera_model_t - {CAMERA_OV7725, "OV7725", OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA, false}, - {CAMERA_OV2640, "OV2640", OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA, true}, - {CAMERA_OV3660, "OV3660", OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA, true}, - {CAMERA_OV5640, "OV5640", OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA, true}, - {CAMERA_OV7670, "OV7670", OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA, false}, - {CAMERA_NT99141, "NT99141", NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD, true}, - {CAMERA_GC2145, "GC2145", GC2145_SCCB_ADDR, GC2145_PID, FRAMESIZE_UXGA, false}, - {CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false}, - {CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false}, - {CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false}, - {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false}, - {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false}, - {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false}, - {CAMERA_SC031GS, "SC031GS", SC031GS_SCCB_ADDR, SC031GS_PID, FRAMESIZE_VGA, false}, -}; - -const resolution_info_t resolution[FRAMESIZE_INVALID] = { - { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ - { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ - { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ - { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ - { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ - { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ - { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ - { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ - { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ - { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ - { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ - { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ - { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ - { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ - // 3MP Sensors - { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ - { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ - { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ - { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ - // 5MP Sensors - { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ - { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ - { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ - { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ -}; - -camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id) -{ - for (int i = 0; i < CAMERA_MODEL_MAX; i++) { - if (id->PID == camera_sensor[i].pid) { - return (camera_sensor_info_t *)&camera_sensor[i]; - } - } - return NULL; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt deleted file mode 100644 index 0a03968845..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# The following lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -set(EXTRA_COMPONENT_DIRS "../") - -add_compile_options(-fdiagnostics-color=always) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(camera_example) \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile deleted file mode 100644 index f06df0ecc9..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := camera_example - -EXTRA_COMPONENT_DIRS := ../ - -include $(IDF_PATH)/make/project.mk - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt deleted file mode 100644 index 1735fb184b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -set(COMPONENT_SRCS take_picture.c) -set(COMPONENT_ADD_INCLUDEDIRS .) -register_component() \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk deleted file mode 100644 index 0b9d7585e7..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/component.mk +++ /dev/null @@ -1,5 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c deleted file mode 100644 index 3a243d2554..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/main/take_picture.c +++ /dev/null @@ -1,167 +0,0 @@ -/** - * This example takes a picture every 5s and print its size on serial monitor. - */ - -// =============================== SETUP ====================================== - -// 1. Board setup (Uncomment): -// #define BOARD_WROVER_KIT -// #define BOARD_ESP32CAM_AITHINKER - -/** - * 2. Kconfig setup - * - * If you have a Kconfig file, copy the content from - * https://github.com/espressif/esp32-camera/blob/master/Kconfig into it. - * In case you haven't, copy and paste this Kconfig file inside the src directory. - * This Kconfig file has definitions that allows more control over the camera and - * how it will be initialized. - */ - -/** - * 3. Enable PSRAM on sdkconfig: - * - * CONFIG_ESP32_SPIRAM_SUPPORT=y - * - * More info on - * https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support - */ - -// ================================ CODE ====================================== - -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -// support IDF 5.x -#ifndef portTICK_RATE_MS -#define portTICK_RATE_MS portTICK_PERIOD_MS -#endif - -#include "esp_camera.h" - -#define BOARD_WROVER_KIT 1 - -// WROVER-KIT PIN Map -#ifdef BOARD_WROVER_KIT - -#define CAM_PIN_PWDN -1 //power down is not used -#define CAM_PIN_RESET -1 //software reset will be performed -#define CAM_PIN_XCLK 21 -#define CAM_PIN_SIOD 26 -#define CAM_PIN_SIOC 27 - -#define CAM_PIN_D7 35 -#define CAM_PIN_D6 34 -#define CAM_PIN_D5 39 -#define CAM_PIN_D4 36 -#define CAM_PIN_D3 19 -#define CAM_PIN_D2 18 -#define CAM_PIN_D1 5 -#define CAM_PIN_D0 4 -#define CAM_PIN_VSYNC 25 -#define CAM_PIN_HREF 23 -#define CAM_PIN_PCLK 22 - -#endif - -// ESP32Cam (AiThinker) PIN Map -#ifdef BOARD_ESP32CAM_AITHINKER - -#define CAM_PIN_PWDN 32 -#define CAM_PIN_RESET -1 //software reset will be performed -#define CAM_PIN_XCLK 0 -#define CAM_PIN_SIOD 26 -#define CAM_PIN_SIOC 27 - -#define CAM_PIN_D7 35 -#define CAM_PIN_D6 34 -#define CAM_PIN_D5 39 -#define CAM_PIN_D4 36 -#define CAM_PIN_D3 21 -#define CAM_PIN_D2 19 -#define CAM_PIN_D1 18 -#define CAM_PIN_D0 5 -#define CAM_PIN_VSYNC 25 -#define CAM_PIN_HREF 23 -#define CAM_PIN_PCLK 22 - -#endif - -static const char *TAG = "example:take_picture"; - -#if ESP_CAMERA_SUPPORTED -static camera_config_t camera_config = { - .pin_pwdn = CAM_PIN_PWDN, - .pin_reset = CAM_PIN_RESET, - .pin_xclk = CAM_PIN_XCLK, - .pin_sccb_sda = CAM_PIN_SIOD, - .pin_sccb_scl = CAM_PIN_SIOC, - - .pin_d7 = CAM_PIN_D7, - .pin_d6 = CAM_PIN_D6, - .pin_d5 = CAM_PIN_D5, - .pin_d4 = CAM_PIN_D4, - .pin_d3 = CAM_PIN_D3, - .pin_d2 = CAM_PIN_D2, - .pin_d1 = CAM_PIN_D1, - .pin_d0 = CAM_PIN_D0, - .pin_vsync = CAM_PIN_VSYNC, - .pin_href = CAM_PIN_HREF, - .pin_pclk = CAM_PIN_PCLK, - - //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) - .xclk_freq_hz = 20000000, - .ledc_timer = LEDC_TIMER_0, - .ledc_channel = LEDC_CHANNEL_0, - - .pixel_format = PIXFORMAT_RGB565, //YUV422,GRAYSCALE,RGB565,JPEG - .frame_size = FRAMESIZE_QVGA, //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. - - .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality - .fb_count = 1, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. - .grab_mode = CAMERA_GRAB_WHEN_EMPTY, -}; - -static esp_err_t init_camera(void) -{ - //initialize the camera - esp_err_t err = esp_camera_init(&camera_config); - if (err != ESP_OK) - { - ESP_LOGE(TAG, "Camera Init Failed"); - return err; - } - - return ESP_OK; -} -#endif - -void app_main(void) -{ -#if ESP_CAMERA_SUPPORTED - if(ESP_OK != init_camera()) { - return; - } - - while (1) - { - ESP_LOGI(TAG, "Taking picture..."); - camera_fb_t *pic = esp_camera_fb_get(); - - // use pic->buf to access the image - ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len); - esp_camera_fb_return(pic); - - vTaskDelay(5000 / portTICK_RATE_MS); - } -#else - ESP_LOGE(TAG, "Camera support is not available for this chip"); - return; -#endif -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults b/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults deleted file mode 100644 index e5ac4557ac..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/examples/sdkconfig.defaults +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y - -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_PARTITION_TABLE_OFFSET=0x10000 - -CONFIG_FREERTOS_HZ=1000 -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y - -CONFIG_SPIRAM_SUPPORT=y -CONFIG_ESP32_SPIRAM_SUPPORT=y -CONFIG_ESP32S2_SPIRAM_SUPPORT=y -CONFIG_ESP32S3_SPIRAM_SUPPORT=y -CONFIG_SPIRAM_SPEED_80M=y - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml b/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml deleted file mode 100644 index 2b98f8d06c..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/idf_component.yml +++ /dev/null @@ -1,2 +0,0 @@ -description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors. -url: https://github.com/espressif/esp32-camera diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json b/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json deleted file mode 100644 index 1b367ee04b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/library.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "esp32-camera", - "version": "2.0.0", - "keywords": "esp32, camera, espressif, esp32-cam", - "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", - "repository": { - "type": "git", - "url": "https://github.com/espressif/esp32-camera" - }, - "frameworks": "espidf", - "platforms": "*", - "build": { - "flags": [ - "-Idriver/include", - "-Iconversions/include", - "-Idriver/private_include", - "-Iconversions/private_include", - "-Isensors/private_include", - "-Itarget/private_include", - "-fno-rtti" - ], - "includeDir": ".", - "srcDir": ".", - "srcFilter": ["-<*>", "+", "+", "+"] - } -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c deleted file mode 100644 index f8eb127d54..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf20a6.c +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sccb.h" -#include "bf20a6.h" -#include "bf20a6_regs.h" -#include "bf20a6_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "bf20a6"; -#endif - -#define H8(v) ((v)>>8) -#define L8(v) ((v)&0xff) - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg) -{ - int ret = SCCB_Read(slv_addr, reg); - // ESP_LOGI(TAG, "READ Register 0x%02x VALUE: 0x%02x", reg, ret); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) -{ - int ret = SCCB_Write(slv_addr, reg, value); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -#ifdef DEBUG_PRINT_REG -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) -{ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static void print_regs(uint8_t slv_addr) -{ - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_LOGI(TAG, "REG list look ======================"); - for (size_t i = 0xf0; i <= 0xfe; i++) { - ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 0 ==="); - write_reg(slv_addr, 0xfe, 0x00); // page 0 - for (size_t i = 0x03; i <= 0x24; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - for (size_t i = 0x40; i <= 0x95; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 3 ==="); - write_reg(slv_addr, 0xfe, 0x03); // page 3 - for (size_t i = 0x01; i <= 0x43; i++) { - ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } -} - -static int read_regs(uint8_t slv_addr, const uint16_t(*regs)[2]) -{ - int i = 0, ret = 0; - while (regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = read_reg(slv_addr, regs[i][0]); - } - i++; - } - return ret; -} -#endif - -static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - - ret = SCCB_Read(sensor->slv_addr, reg); - if (ret < 0) { - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t(*regs)[2]) -{ - int i = 0, ret = 0; - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static int reset(sensor_t *sensor) -{ - int ret; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, RESET_RELATED, 0x01); - if (ret) { - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - - ret = write_regs(sensor->slv_addr, bf20a6_default_init_regs); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - // int test_value = read_regs(sensor->slv_addr, bf20a6_default_init_regs); - - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - switch (pixformat) { - case PIXFORMAT_YUV422: - set_reg_bits(sensor, 0x12, 0, 1, 0); - break; - case PIXFORMAT_RAW: - set_reg_bits(sensor, 0x12, 0, 1, 0x1); - break; - case PIXFORMAT_GRAYSCALE: - write_reg(sensor->slv_addr, 0x12, 0x23); - write_reg(sensor->slv_addr, 0x3a, 0x00); - write_reg(sensor->slv_addr, 0xe1, 0x92); - write_reg(sensor->slv_addr, 0xe3, 0x02); - break; - default: - ESP_LOGW(TAG, "set_pix unsupport format"); - ret = -1; - break; - } - if (ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - if (framesize > FRAMESIZE_VGA) { - return -1; - } - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - - sensor->status.framesize = framesize; - - // Write MSBs - ret |= SCCB_Write(sensor->slv_addr, 0x17, 0); - ret |= SCCB_Write(sensor->slv_addr, 0x18, w >> 2); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, 0); - ret |= SCCB_Write(sensor->slv_addr, 0x1a, h >> 2); - - // Write LSBs - ret |= SCCB_Write(sensor->slv_addr, 0x1b, 0); - - if ((w <= 320) && (h <= 240)) { - ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 4)); - ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 4)); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 4)); - - ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 4)); - - } else if ((w <= 640) && (h <= 480)) { - ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 8)); - ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 8)); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 8)); - - ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 8)); - } - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - //ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor, 0x4a, 3, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - //ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor, 0x4a, 2, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int value) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, 0xb6, value); - if (ret == 0) { - sensor->status.colorbar = value; - ESP_LOGD(TAG, "Set colorbar to: %d", value); - } - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x70, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set sharpness to: %d", level); - sensor->status.sharpness = level; - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret > 0) { - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret < 0) { - return ret; - } - value = (ret & ~mask) | (value & mask); - - if (mask > 0xFF) { - - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - // write_reg(sensor->slv_addr, 0xfe, 0x00); - sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x6f); - sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0xd6); - sensor->status.saturation = 0; - sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70); - sensor->status.denoise = 0; - sensor->status.ae_level = 0; - sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x13); - sensor->status.awb = 0; - sensor->status.dcw = 0; - sensor->status.agc = 0; - sensor->status.aec = 0; - sensor->status.hmirror = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01); - sensor->status.vflip = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02); - sensor->status.colorbar = 0; - sensor->status.bpc = 0; - sensor->status.wpc = 0; - sensor->status.raw_gma = 0; - sensor->status.lenc = 0; - sensor->status.quality = 0; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = 0; - sensor->status.agc_gain = 0; - sensor->status.aec_value = 0; - sensor->status.aec2 = 0; - return 0; -} - -static int set_dummy(sensor_t *sensor, int val) -{ - ESP_LOGW(TAG, "dummy Unsupported"); - return -1; -} -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) -{ - ESP_LOGW(TAG, "gainceiling Unsupported"); - return -1; -} - -int bf20a6_detect(int slv_addr, sensor_id_t *id) -{ - if (BF20A6_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW); - uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH); - uint16_t PID = MIDH << 8 | MIDL; - if (BF20A6_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int bf20a6_init(sensor_t *sensor) -{ - sensor->init_status = init_status; - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_dummy; - sensor->set_brightness = set_dummy; - sensor->set_saturation = set_dummy; - sensor->set_sharpness = set_sharpness; - sensor->set_denoise = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - sensor->set_quality = set_dummy; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_dummy; - sensor->set_gain_ctrl = set_dummy; - sensor->set_exposure_ctrl = set_dummy; - sensor->set_hmirror = set_hmirror; // set_hmirror; - sensor->set_vflip = set_vflip; // set_vflip; - - sensor->set_aec2 = set_dummy; - sensor->set_awb_gain = set_dummy; - sensor->set_agc_gain = set_dummy; - sensor->set_aec_value = set_dummy; - - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - sensor->set_dcw = set_dummy; - sensor->set_bpc = set_dummy; - sensor->set_wpc = set_dummy; - - sensor->set_raw_gma = set_dummy; - sensor->set_lenc = set_dummy; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = NULL; - sensor->set_pll = NULL; - sensor->set_xclk = NULL; - - ESP_LOGD(TAG, "BF20A6 Attached"); - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c deleted file mode 100644 index 2da7594a70..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/bf3005.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * BF3005 driver. - * - * Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "bf3005.h" -#include "bf3005_regs.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "bf3005"; -#endif - -static const uint8_t default_regs[][2] = { - {0x12, 0x40}, //soft reset - {0xff, 0xff}, //delay - {0xff, 0xff}, //delay - {0xff, 0xff}, //delay - {0xff, 0xff}, //delay - {0x13, 0x10}, - {0x8c, 0x00}, - {0x8d, 0x64}, - {0x87, 0x10}, - {0x13, 0x17}, - {0x00, 0x20}, - {0x01, 0x1a}, - {0x02, 0x22}, - {0x09, 0x03}, - {0x0c, 0x80}, - {0x0d, 0x24}, - {0x0e, 0x21}, - {0x0f, 0x28}, - {0x11, 0x08}, - {0x15, 0x10}, // 0X10 - {0x16, 0x03}, - {0x1e, 0x30}, - {0x20, 0x8a}, - {0x21, 0x03}, - {0x23, 0x55}, - {0x24, 0x68}, - {0x25, 0x78}, - {0x2a, 0x00}, - {0x2b, 0x00}, - {0x2d, 0x4f}, - {0x2e, 0x98}, - {0x2f, 0x04}, - {0x30, 0xad}, - {0x31, 0x17}, - {0x32, 0x6e}, - {0x33, 0x20}, - {0x35, 0xa6}, - {0x3b, 0x00}, - {0x3e, 0x00}, - {0x3f, 0xA8}, - {0x40, 0x38}, - {0x41, 0x32}, - {0x42, 0x2b}, - {0x43, 0x26}, - {0x44, 0x1a}, - {0x45, 0x16}, - {0x46, 0x10}, - {0x47, 0x0f}, - {0x48, 0x0c}, - {0x49, 0x0a}, - {0x4b, 0x09}, - {0x4c, 0x08}, - {0x4d, 0x3c}, - {0x4e, 0x06}, - {0x4f, 0x05}, - {0x50, 0x03}, - {0x51, 0x25}, - {0x52, 0x88}, - {0x53, 0x03}, - {0x63, 0x20}, - {0x64, 0x02}, - {0x65, 0xa6}, - {0x66, 0xb6}, - {0x69, 0x00}, - {0x70, 0xFF}, - {0x71, 0xa6}, - {0x72, 0x2f}, - {0x73, 0x2f}, - {0x74, 0x2F}, - {0x75, 0x0e}, - {0x76, 0x1e}, - {0x77, 0x00}, - {0x78, 0x1e}, - {0x79, 0x8a}, - {0x7d, 0xe2}, - {0x80, 0x44}, - {0x81, 0x00}, - {0x82, 0x18}, - {0x83, 0x1b}, - {0x84, 0x24}, - {0x85, 0x2a}, - {0x86, 0x4f}, - {0x89, 0x82}, //0x82 - {0x8b, 0x02}, - {0x8e, 0x03}, - {0x8f, 0xFC}, - {0x9d, 0x4d}, - {0x9e, 0x41}, - {0xa1, 0x21}, - {0xa2, 0x12}, - {0xa3, 0x32}, - {0xa4, 0x05}, - {0xa5, 0x32}, - {0xa6, 0x04}, - {0xa7, 0x7f}, - {0xa8, 0x7f}, - {0xa9, 0x21}, - {0xaa, 0x21}, - {0xab, 0x21}, - {0xac, 0x0a}, - {0xad, 0xf0}, - {0xae, 0xff}, - {0xaf, 0x1d}, - {0xb0, 0x94}, - {0xb1, 0xc0}, - {0xb2, 0xc0}, - {0xd2, 0x30}, - {0xe0, 0x0d}, - {0xe1, 0x44}, - {0xe7, 0x7c}, - {0xe8, 0x89}, - {0xe9, 0x01}, - {0xea, 0x01}, - {0xf0, 0x01}, - {0xf3, 0x49}, - {0xf4, 0xff}, - {0xf5, 0x01}, - {0xf6, 0xf2}, - {0xf7, 0x6f}, - {0x1b, 0x80}, - {0x00, 0x00}, -}; - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); - return ret; -} - -static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); - return ret; -} - -static int get_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - return (ret & mask) >> offset; -} - - -static int reset(sensor_t *sensor) -{ - int i=0; - const uint8_t (*regs)[2]; - - // Write default regsiters - for (i=0, regs = default_regs; regs[i][0]; i++) { - SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); - } - - // Delay - vTaskDelay(50 / portTICK_PERIOD_MS); - - return 0; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret=0; - sensor->pixformat = pixformat; - - switch (pixformat) { - case PIXFORMAT_RGB565: - set_reg_bits(sensor, 0x12, 2, 1, 1); - break; - case PIXFORMAT_RAW: - set_reg_bits(sensor, 0x12, 0, 3, 0x4); - break; - case PIXFORMAT_YUV422: - case PIXFORMAT_GRAYSCALE: - set_reg_bits(sensor, 0x12, 2, 1, 0); - break; - default: - return -1; - } - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret=0; - if (framesize > FRAMESIZE_VGA) { - return -1; - } - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - // uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); - - sensor->status.framesize = framesize; - - // Write MSBs - ret |= SCCB_Write(sensor->slv_addr, 0x17, 0); - ret |= SCCB_Write(sensor->slv_addr, 0x18, w>>2); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, 0); - ret |= SCCB_Write(sensor->slv_addr, 0x1a, h>>2); - - // Write LSBs - ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); - printf("%s %d\r\n", __func__, __LINE__); - if((w<=320)&&(h<=240)) - { - printf("%s %d\r\n", __func__, __LINE__); - // Enable auto-scaling/zooming factors - //ret |= SCCB_Write(sensor->slv_addr, 0x12, 0x50); - set_reg_bits(sensor, 0x12, 4, 1, 1); - - ret |= SCCB_Write(sensor->slv_addr, 0x17, (80-w/4)); - ret |= SCCB_Write(sensor->slv_addr, 0x18, (80+w/4)); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, (60-h/4)); - - ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60+h/4)); - ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); - - } else if((w<=640)&&(h<=480)) - { - // Enable auto-scaling/zooming factors - //ret |= SCCB_Write(sensor->slv_addr, 0x12, 0x40); - set_reg_bits(sensor, 0x12, 4, 1, 0); - - ret |= SCCB_Write(sensor->slv_addr, 0x17, (80-w/8)); - ret |= SCCB_Write(sensor->slv_addr, 0x18, (80+w/8)); - - ret |= SCCB_Write(sensor->slv_addr, 0x19, (60-h/8)); - - ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60+h/8)); - ret |= SCCB_Write(sensor->slv_addr, 0x03, 0); - } - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int value) -{ - int ret=0; - sensor->status.colorbar = value; - - ret |= SCCB_Write(sensor->slv_addr, 0xb9, value); - - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, 0x13, 1, 1, enable) >= 0){ - sensor->status.awb = !!enable; - } - return sensor->status.awb; -} - - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, 0x13, 2, 1, enable) >= 0){ - sensor->status.agc = !!enable; - } - return sensor->status.agc; -} - - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, 0x13, 0, 1, enable) >= 0){ - sensor->status.aec = !!enable; - } - return sensor->status.aec; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, 0x1e, 5, 1, enable) >= 0){ - sensor->status.hmirror = !!enable; - } - return sensor->status.hmirror; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, 0x1e, 4, 1, enable) >= 0){ - sensor->status.vflip = !!enable; - } - return sensor->status.vflip; -} - -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0xf1, 1, 1, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set raw_gma to: %d", !enable); - sensor->status.raw_gma = !enable; - } - return ret; -} - - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0xf1, 0, 1, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set lenc to: %d", !enable); - sensor->status.lenc = !enable; - } - return ret; -} - -static int set_agc_gain(sensor_t *sensor, int option) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x13, 4, 1, !!option); - if (ret == 0) { - ESP_LOGD(TAG, "Set gain to: %d", !!option); - sensor->status.agc_gain = !!option; - } - return ret; -} - -static int set_awb_gain_dsp(sensor_t *sensor, int value) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0xa6, value); - if (ret == 0) { - ESP_LOGD(TAG, "Set awb gain threthold to: %d", value); - sensor->status.awb_gain = value; - } - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x55, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set brightness to: %d", level); - sensor->status.brightness = level; - } - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x56, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set contrast to: %d", level); - sensor->status.contrast = level; - } - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x70, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set sharpness to: %d", level); - sensor->status.sharpness = level; - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x55); - sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0x56); - sensor->status.saturation = 0; - sensor->status.ae_level = 0; - - sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x87); - sensor->status.awb = get_reg_bits(sensor, 0x13, 1, 1); - sensor->status.awb_gain = SCCB_Read(sensor->slv_addr, 0xa6); - sensor->status.aec = get_reg_bits(sensor, 0x13, 0, 1); - - sensor->status.agc = get_reg_bits(sensor, 0x13, 2, 1); - - sensor->status.raw_gma = get_reg_bits(sensor, 0xf1, 1, 1); - sensor->status.lenc = get_reg_bits(sensor, 0xf1, 0, 1); - sensor->status.hmirror = get_reg_bits(sensor, 0x1e, 5, 1); - sensor->status.vflip = get_reg_bits(sensor, 0x1e, 4, 1); - - sensor->status.colorbar = SCCB_Read(sensor->slv_addr, 0xb9); - sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70); - - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning){return -1;} -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div){return -1;} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int bf3005_detect(int slv_addr, sensor_id_t *id) -{ - if (BF3005_SCCB_ADDR == slv_addr) { - uint16_t PID = SCCB_Read(slv_addr, 0xFC); - if (BF3005_PID == PID) { - id->PID = PID; - id->VER = SCCB_Read(slv_addr, 0xFD); - id->MIDL = SCCB_Read(slv_addr, 0xFC); - id->MIDH = SCCB_Read(slv_addr, 0xFD); - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int bf3005_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_brightness = set_brightness; - sensor->set_contrast = set_contrast; - - sensor->set_colorbar = set_colorbar; - - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - sensor->set_whitebal = set_whitebal; - - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - - sensor->set_sharpness = set_sharpness; - //not supported - sensor->set_saturation= set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_quality = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - - ESP_LOGD(TAG, "BF3005 Attached"); - - return 0; -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c deleted file mode 100644 index f19025ebb3..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc0308.c +++ /dev/null @@ -1,468 +0,0 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sccb.h" -#include "gc0308.h" -#include "gc0308_regs.h" -#include "gc0308_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "gc0308"; -#endif - -#define H8(v) ((v)>>8) -#define L8(v) ((v)&0xff) - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg) -{ - int ret = SCCB_Read(slv_addr, reg); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) -{ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - if (old_value < 0) { - return old_value; - } - if ((uint8_t)old_value != value) { - ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write(slv_addr, reg, value);//maybe not? - } - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) -{ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - if (ret < 0) { - return ret; - } - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint8_t (*regs)[2], size_t regs_size) -{ - int i = 0, ret = 0; - while (!ret && (i < regs_size)) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static void print_regs(uint8_t slv_addr) -{ -#ifdef DEBUG_PRINT_REG - ESP_LOGI(TAG, "REG list look ======================"); - for (size_t i = 0xf0; i <= 0xfe; i++) { - ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 0 ==="); - write_reg(slv_addr, 0xfe, 0x00); // page 0 - for (size_t i = 0x03; i <= 0xa2; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - - ESP_LOGI(TAG, "\npage 3 ==="); - write_reg(slv_addr, 0xfe, 0x03); // page 3 - for (size_t i = 0x01; i <= 0x43; i++) { - ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } -#endif -} - -static int reset(sensor_t *sensor) -{ - int ret = 0; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); - if (ret) { - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - - vTaskDelay(80 / portTICK_PERIOD_MS); - ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs, sizeof(gc0308_sensor_default_regs)/(sizeof(uint8_t) * 2)); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - vTaskDelay(80 / portTICK_PERIOD_MS); - write_reg(sensor->slv_addr, 0xfe, 0x00); -#ifdef CONFIG_IDF_TARGET_ESP32 - set_reg_bits(sensor->slv_addr, 0x28, 4, 0x07, 1); //frequency division for esp32, ensure pclk <= 15MHz -#endif - } - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - - switch (pixformat) { - case PIXFORMAT_RGB565: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 6); //RGB565 - break; - - case PIXFORMAT_YUV422: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, 0x24, 0, 0x0f, 2); //yuv422 Y Cb Y Cr - break; - default: - ESP_LOGW(TAG, "unsupport format"); - ret = -1; - break; - } - - if (ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - if (framesize > FRAMESIZE_VGA) { - ESP_LOGW(TAG, "Invalid framesize: %u", framesize); - framesize = FRAMESIZE_VGA; - } - sensor->status.framesize = framesize; - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; - uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; - (void)row_s; - (void)col_s; - -#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE - struct subsample_cfg { - uint16_t ratio_numerator; - uint16_t ratio_denominator; - uint8_t reg0x54; - uint8_t reg0x56; - uint8_t reg0x57; - uint8_t reg0x58; - uint8_t reg0x59; - }; - const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio - {84, 420, 0x55, 0x00, 0x00, 0x00, 0x00}, //1/5 - {105, 420, 0x44, 0x00, 0x00, 0x00, 0x00},//1/4 - {140, 420, 0x33, 0x00, 0x00, 0x00, 0x00},//1/3 - {210, 420, 0x22, 0x00, 0x00, 0x00, 0x00},//1/2 - {240, 420, 0x77, 0x02, 0x46, 0x02, 0x46},//4/7 - {252, 420, 0x55, 0x02, 0x04, 0x02, 0x04},//3/5 - {280, 420, 0x33, 0x02, 0x00, 0x02, 0x00},//2/3 - {420, 420, 0x11, 0x00, 0x00, 0x00, 0x00},//1/1 - }; - uint16_t win_w = 640; - uint16_t win_h = 480; - const struct subsample_cfg *cfg = NULL; - /** - * Strategy: try to keep the maximum perspective - */ - for (size_t i = 0; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { - cfg = &subsample_cfgs[i]; - if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { - win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; - win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; - row_s = (resolution[FRAMESIZE_VGA].height - win_h) / 2; - col_s = (resolution[FRAMESIZE_VGA].width - win_w) / 2; - ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); - break; - } - } - - write_reg(sensor->slv_addr, 0xfe, 0x00); - - write_reg(sensor->slv_addr, 0x05, H8(row_s)); - write_reg(sensor->slv_addr, 0x06, L8(row_s)); - write_reg(sensor->slv_addr, 0x07, H8(col_s)); - write_reg(sensor->slv_addr, 0x08, L8(col_s)); - write_reg(sensor->slv_addr, 0x09, H8(win_h + 8)); - write_reg(sensor->slv_addr, 0x0a, L8(win_h + 8)); - write_reg(sensor->slv_addr, 0x0b, H8(win_w + 8)); - write_reg(sensor->slv_addr, 0x0c, L8(win_w + 8)); - - write_reg(sensor->slv_addr, 0xfe, 0x01); - set_reg_bits(sensor->slv_addr, 0x53, 7, 0x01, 1); - set_reg_bits(sensor->slv_addr, 0x55, 0, 0x01, 1); - write_reg(sensor->slv_addr, 0x54, cfg->reg0x54); - write_reg(sensor->slv_addr, 0x56, cfg->reg0x56); - write_reg(sensor->slv_addr, 0x57, cfg->reg0x57); - write_reg(sensor->slv_addr, 0x58, cfg->reg0x58); - write_reg(sensor->slv_addr, 0x59, cfg->reg0x59); - - write_reg(sensor->slv_addr, 0xfe, 0x00); - -#elif CONFIG_GC_SENSOR_WINDOWING_MODE - write_reg(sensor->slv_addr, 0xfe, 0x00); - - write_reg(sensor->slv_addr, 0xf7, col_s / 4); - write_reg(sensor->slv_addr, 0xf8, row_s / 4); - write_reg(sensor->slv_addr, 0xf9, (col_s + h) / 4); - write_reg(sensor->slv_addr, 0xfa, (row_s + w) / 4); - - write_reg(sensor->slv_addr, 0x05, H8(row_s)); - write_reg(sensor->slv_addr, 0x06, L8(row_s)); - write_reg(sensor->slv_addr, 0x07, H8(col_s)); - write_reg(sensor->slv_addr, 0x08, L8(col_s)); - - write_reg(sensor->slv_addr, 0x09, H8(h + 8)); - write_reg(sensor->slv_addr, 0x0a, L8(h + 8)); - write_reg(sensor->slv_addr, 0x0b, H8(w + 8)); - write_reg(sensor->slv_addr, 0x0c, L8(w + 8)); - -#endif - if (ret == 0) { - ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); - } - return 0; -} - -static int set_contrast(sensor_t *sensor, int contrast) -{ - if (contrast != 0) { - write_reg(sensor->slv_addr, 0xfe, 0x00); - write_reg(sensor->slv_addr, 0xb3, contrast); - } - return 0; -} - -static int set_global_gain(sensor_t *sensor, int gain_level) -{ - if (gain_level != 0) { - write_reg(sensor->slv_addr, 0xfe, 0x00); - write_reg(sensor->slv_addr, 0x50, gain_level); - } - return 0; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, 0x14, 0, 0x01, enable != 0); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, 0x14, 1, 0x01, enable != 0); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, 0x2e, 0, 0x01, enable); - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret > 0) { - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret < 0) { - return ret; - } - value = (ret & ~mask) | (value & mask); - - if (mask > 0xFF) { - - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - write_reg(sensor->slv_addr, 0xfe, 0x00); - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = 0; - sensor->status.denoise = 0; - sensor->status.ae_level = 0; - sensor->status.gainceiling = 0; - sensor->status.awb = 0; - sensor->status.dcw = 0; - sensor->status.agc = 0; - sensor->status.aec = 0; - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, 0x14, 0x01); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, 0x14, 0x02); - sensor->status.colorbar = 0; - sensor->status.bpc = 0; - sensor->status.wpc = 0; - sensor->status.raw_gma = 0; - sensor->status.lenc = 0; - sensor->status.quality = 0; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = 0; - sensor->status.agc_gain = 0; - sensor->status.aec_value = 0; - sensor->status.aec2 = 0; - - print_regs(sensor->slv_addr); - return 0; -} - -static int set_dummy(sensor_t *sensor, int val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} - -int gc0308_detect(int slv_addr, sensor_id_t *id) -{ - if (GC0308_SCCB_ADDR == slv_addr) { - write_reg(slv_addr, 0xfe, 0x00); - uint8_t PID = SCCB_Read(slv_addr, 0x00); - if (GC0308_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int gc0308_init(sensor_t *sensor) -{ - sensor->init_status = init_status; - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_contrast; - sensor->set_brightness = set_dummy; - sensor->set_saturation = set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - sensor->set_quality = set_dummy; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_dummy; - sensor->set_gain_ctrl = set_global_gain; - sensor->set_exposure_ctrl = set_dummy; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - sensor->set_aec2 = set_dummy; - sensor->set_awb_gain = set_dummy; - sensor->set_agc_gain = set_dummy; - sensor->set_aec_value = set_dummy; - - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - sensor->set_dcw = set_dummy; - sensor->set_bpc = set_dummy; - sensor->set_wpc = set_dummy; - - sensor->set_raw_gma = set_dummy; - sensor->set_lenc = set_dummy; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = NULL; - sensor->set_pll = NULL; - sensor->set_xclk = NULL; - - ESP_LOGD(TAG, "GC0308 Attached"); - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c deleted file mode 100644 index 612e17b1ed..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc032a.c +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sccb.h" -#include "gc032a.h" -#include "gc032a_regs.h" -#include "gc032a_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "gc032a"; -#endif - -#define H8(v) ((v)>>8) -#define L8(v) ((v)&0xff) - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg) -{ - int ret = SCCB_Read(slv_addr, reg); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) -{ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - if (old_value < 0) { - return old_value; - } - if ((uint8_t)old_value != value) { - ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write(slv_addr, reg, value);//maybe not? - } - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) -{ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static void print_regs(uint8_t slv_addr) -{ -#ifdef DEBUG_PRINT_REG - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_LOGI(TAG, "REG list look ======================"); - for (size_t i = 0xf0; i <= 0xfe; i++) { - ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 0 ==="); - write_reg(slv_addr, 0xfe, 0x00); // page 0 - for (size_t i = 0x03; i <= 0x24; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - for (size_t i = 0x40; i <= 0x95; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 3 ==="); - write_reg(slv_addr, 0xfe, 0x03); // page 3 - for (size_t i = 0x01; i <= 0x43; i++) { - ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } -#endif -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - if (ret < 0) { - return ret; - } - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) -{ - int i = 0, ret = 0; - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static int reset(sensor_t *sensor) -{ - int ret; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xf0); - if (ret) { - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - - ret = write_regs(sensor->slv_addr, gc032a_default_regs); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - vTaskDelay(100 / portTICK_PERIOD_MS); - write_reg(sensor->slv_addr, 0xfe, 0x00); - set_reg_bits(sensor->slv_addr, 0xf7, 1, 0x01, 1); // PLL_mode1:div2en - set_reg_bits(sensor->slv_addr, 0xf7, 7, 0x01, 1); // PLL_mode1:dvp mode - set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 8); //PLL_mode2 :divx4 - set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); //vlk div mode :divide_by - } - - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - switch (pixformat) { - case PIXFORMAT_RGB565: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 6); //RGB565 - break; - - case PIXFORMAT_YUV422: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, 0x44, 0, 0x1f, 3); - break; - default: - ESP_LOGW(TAG, "unsupport format"); - ret = -1; - break; - } - if (ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - ESP_LOGI(TAG, "set_framesize"); - int ret = 0; - if (framesize > FRAMESIZE_VGA) { - ESP_LOGW(TAG, "Invalid framesize: %u", framesize); - framesize = FRAMESIZE_VGA; - } - sensor->status.framesize = framesize; - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - uint16_t row_s = (resolution[FRAMESIZE_VGA].height - h) / 2; - uint16_t col_s = (resolution[FRAMESIZE_VGA].width - w) / 2; - - write_reg(sensor->slv_addr, 0xfe, 0x00); - write_reg(sensor->slv_addr, P0_ROW_START_HIGH, H8(row_s)); // Row_start[8] - write_reg(sensor->slv_addr, P0_ROW_START_LOW, L8(row_s)); // Row_start[7:0] - write_reg(sensor->slv_addr, P0_COLUMN_START_HIGH, H8(col_s)); // Column_start[9:8] - write_reg(sensor->slv_addr, P0_COLUMN_START_LOW, L8(col_s)); // Column_start[7:0] - write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_HIGH, H8(h + 8)); //window_height [8] - write_reg(sensor->slv_addr, P0_WINDOW_HEIGHT_LOW, L8(h + 8)); //window_height [7:0] - write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_HIGH, H8(w + 8)); //window_width [9:8] - write_reg(sensor->slv_addr, P0_WINDOW_WIDTH_LOW, L8(w + 8)); //window_width [7:0] - - write_reg(sensor->slv_addr, P0_WIN_MODE, 0x01); - write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_HIGH, H8(h)); - write_reg(sensor->slv_addr, P0_OUT_WIN_HEIGHT_LOW, L8(h)); - write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_HIGH, H8(w)); - write_reg(sensor->slv_addr, P0_OUT_WIN_WIDTH_LOW, L8(w)); - - if (ret == 0) { - ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); - } - print_regs(sensor->slv_addr); - return ret; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 0, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, P0_CISCTL_MODE1, 1, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE2, 3, 0x01, enable); - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret > 0) { - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret < 0) { - return ret; - } - value = (ret & ~mask) | (value & mask); - - if (mask > 0xFF) { - - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - write_reg(sensor->slv_addr, 0xfe, 0x00); - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = 0; - sensor->status.denoise = 0; - sensor->status.ae_level = 0; - sensor->status.gainceiling = 0; - sensor->status.awb = 0; - sensor->status.dcw = 0; - sensor->status.agc = 0; - sensor->status.aec = 0; - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02); - sensor->status.colorbar = 0; - sensor->status.bpc = 0; - sensor->status.wpc = 0; - sensor->status.raw_gma = 0; - sensor->status.lenc = 0; - sensor->status.quality = 0; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = 0; - sensor->status.agc_gain = 0; - sensor->status.aec_value = 0; - sensor->status.aec2 = 0; - return 0; -} - -static int set_dummy(sensor_t *sensor, int val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} - -int gc032a_detect(int slv_addr, sensor_id_t *id) -{ - if (GC032A_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW); - uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH); - uint16_t PID = MIDH << 8 | MIDL; - if (GC032A_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int gc032a_init(sensor_t *sensor) -{ - sensor->init_status = init_status; - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_dummy; - sensor->set_brightness = set_dummy; - sensor->set_saturation = set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - sensor->set_quality = set_dummy; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_dummy; - sensor->set_gain_ctrl = set_dummy; - sensor->set_exposure_ctrl = set_dummy; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - sensor->set_aec2 = set_dummy; - sensor->set_awb_gain = set_dummy; - sensor->set_agc_gain = set_dummy; - sensor->set_aec_value = set_dummy; - - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - sensor->set_dcw = set_dummy; - sensor->set_bpc = set_dummy; - sensor->set_wpc = set_dummy; - - sensor->set_raw_gma = set_dummy; - sensor->set_lenc = set_dummy; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = NULL; - sensor->set_pll = NULL; - sensor->set_xclk = NULL; - - ESP_LOGD(TAG, "GC032A Attached"); - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c deleted file mode 100644 index 3a066cd941..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/gc2145.c +++ /dev/null @@ -1,477 +0,0 @@ -// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sccb.h" -#include "gc2145.h" -#include "gc2145_regs.h" -#include "gc2145_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "gc2145"; -#endif - -#define H8(v) ((v)>>8) -#define L8(v) ((v)&0xff) - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg) -{ - int ret = SCCB_Read(slv_addr, reg); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) -{ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - if (old_value < 0) { - return old_value; - } - if ((uint8_t)old_value != value) { - ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write(slv_addr, reg, value);//maybe not? - } - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) -{ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - if (ret < 0) { - return ret; - } - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) -{ - int i = 0, ret = 0; - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static void print_regs(uint8_t slv_addr) -{ -#ifdef DEBUG_PRINT_REG - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_LOGI(TAG, "REG list look ======================"); - for (size_t i = 0xf0; i <= 0xfe; i++) { - ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 0 ==="); - write_reg(slv_addr, 0xfe, 0x00); // page 0 - for (size_t i = 0x03; i <= 0x24; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - for (size_t i = 0x80; i <= 0xa2; i++) { - ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } - ESP_LOGI(TAG, "\npage 3 ==="); - write_reg(slv_addr, 0xfe, 0x03); // page 3 - for (size_t i = 0x01; i <= 0x43; i++) { - ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i)); - } -#endif -} - -static int reset(sensor_t *sensor) -{ - int ret = 0; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, RESET_RELATED, 0xe0); - if (ret) { - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - ret = write_regs(sensor->slv_addr, gc2145_default_init_regs); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - vTaskDelay(100 / portTICK_PERIOD_MS); -#ifdef CONFIG_IDF_TARGET_ESP32 - write_reg(sensor->slv_addr, 0xfe, 0x00); - //ensure pclk <= 15MHz for esp32 - set_reg_bits(sensor->slv_addr, 0xf8, 0, 0x3f, 2); // divx4 - set_reg_bits(sensor->slv_addr, 0xfa, 4, 0x0f, 2); // divide_by -#endif - - } - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - - switch (pixformat) { - case PIXFORMAT_RGB565: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 6); //RGB565 - break; - - case PIXFORMAT_YUV422: - write_reg(sensor->slv_addr, 0xfe, 0x00); - ret = set_reg_bits(sensor->slv_addr, P0_OUTPUT_FORMAT, 0, 0x1f, 2); //yuv422 - break; - default: - ESP_LOGW(TAG, "unsupport format"); - ret = -1; - break; - } - - if (ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - if (framesize > FRAMESIZE_UXGA) { - ESP_LOGW(TAG, "Invalid framesize: %u", framesize); - framesize = FRAMESIZE_UXGA; - } - sensor->status.framesize = framesize; - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - uint16_t row_s = (resolution[FRAMESIZE_UXGA].height - h) / 2; - uint16_t col_s = (resolution[FRAMESIZE_UXGA].width - w) / 2; - (void)row_s; - (void)col_s; - -#if CONFIG_GC_SENSOR_SUBSAMPLE_MODE - struct subsample_cfg { - uint16_t ratio_numerator; - uint16_t ratio_denominator; - uint8_t reg0x99; - uint8_t reg0x9b; - uint8_t reg0x9c; - uint8_t reg0x9d; - uint8_t reg0x9e; - uint8_t reg0x9f; - uint8_t reg0xa0; - uint8_t reg0xa1; - uint8_t reg0xa2; - }; - const struct subsample_cfg subsample_cfgs[] = { // define some subsample ratio - // {60, 420, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/7 // A smaller ratio brings a larger view, but it reduces the frame rate - // {84, 420, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //1/5 - // {105, 420, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/4 - {140, 420, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/3 - {210, 420, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/2 - {240, 420, 0x77, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46, 0x02, 0x46},//4/7 - {252, 420, 0x55, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04},//3/5 - {280, 420, 0x33, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},//2/3 - {420, 420, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//1/1 - }; - uint16_t win_w = resolution[FRAMESIZE_UXGA].width; - uint16_t win_h = resolution[FRAMESIZE_UXGA].height; - const struct subsample_cfg *cfg = NULL; - /** - * Strategy: try to keep the maximum perspective - */ - uint8_t i = 0; - if (framesize >= FRAMESIZE_QVGA) { - i = 1; - } - for (; i < sizeof(subsample_cfgs) / sizeof(struct subsample_cfg); i++) { - cfg = &subsample_cfgs[i]; - if ((win_w * cfg->ratio_numerator / cfg->ratio_denominator >= w) && (win_h * cfg->ratio_numerator / cfg->ratio_denominator >= h)) { - win_w = w * cfg->ratio_denominator / cfg->ratio_numerator; - win_h = h * cfg->ratio_denominator / cfg->ratio_numerator; - row_s = (resolution[FRAMESIZE_UXGA].height - win_h) / 2; - col_s = (resolution[FRAMESIZE_UXGA].width - win_w) / 2; - ESP_LOGI(TAG, "subsample win:%dx%d, ratio:%f", win_w, win_h, (float)cfg->ratio_numerator / (float)cfg->ratio_denominator); - break; - } - } - - write_reg(sensor->slv_addr, 0xfe, 0x00); - write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); - write_reg(sensor->slv_addr, 0x09, H8(row_s)); - write_reg(sensor->slv_addr, 0x0a, L8(row_s)); - write_reg(sensor->slv_addr, 0x0b, H8(col_s)); - write_reg(sensor->slv_addr, 0x0c, L8(col_s)); - write_reg(sensor->slv_addr, 0x0d, H8(win_h + 8)); - write_reg(sensor->slv_addr, 0x0e, L8(win_h + 8)); - write_reg(sensor->slv_addr, 0x0f, H8(win_w + 16)); - write_reg(sensor->slv_addr, 0x10, L8(win_w + 16)); - - write_reg(sensor->slv_addr, 0x99, cfg->reg0x99); - write_reg(sensor->slv_addr, 0x9b, cfg->reg0x9b); - write_reg(sensor->slv_addr, 0x9c, cfg->reg0x9c); - write_reg(sensor->slv_addr, 0x9d, cfg->reg0x9d); - write_reg(sensor->slv_addr, 0x9e, cfg->reg0x9e); - write_reg(sensor->slv_addr, 0x9f, cfg->reg0x9f); - write_reg(sensor->slv_addr, 0xa0, cfg->reg0xa0); - write_reg(sensor->slv_addr, 0xa1, cfg->reg0xa1); - write_reg(sensor->slv_addr, 0xa2, cfg->reg0xa2); - - write_reg(sensor->slv_addr, 0x95, H8(h)); - write_reg(sensor->slv_addr, 0x96, L8(h)); - write_reg(sensor->slv_addr, 0x97, H8(w)); - write_reg(sensor->slv_addr, 0x98, L8(w)); - - -#elif CONFIG_GC_SENSOR_WINDOWING_MODE - write_reg(sensor->slv_addr, 0xfe, 0x00); - - write_reg(sensor->slv_addr, P0_CROP_ENABLE, 0x01); - // write_reg(sensor->slv_addr, 0xec, col_s / 8); //measure window - // write_reg(sensor->slv_addr, 0xed, row_s / 8); - // write_reg(sensor->slv_addr, 0xee, (col_s + h) / 8); - // write_reg(sensor->slv_addr, 0xef, (row_s + w) / 8); - - write_reg(sensor->slv_addr, 0x09, H8(row_s)); - write_reg(sensor->slv_addr, 0x0a, L8(row_s)); - write_reg(sensor->slv_addr, 0x0b, H8(col_s)); - write_reg(sensor->slv_addr, 0x0c, L8(col_s)); - write_reg(sensor->slv_addr, 0x0d, H8(h + 8)); - write_reg(sensor->slv_addr, 0x0e, L8(h + 8)); - write_reg(sensor->slv_addr, 0x0f, H8(w + 8)); - write_reg(sensor->slv_addr, 0x10, L8(w + 8)); - - write_reg(sensor->slv_addr, 0x95, H8(h)); - write_reg(sensor->slv_addr, 0x96, L8(h)); - write_reg(sensor->slv_addr, 0x97, H8(w)); - write_reg(sensor->slv_addr, 0x98, L8(w)); - -#endif - - if (ret == 0) { - ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); - } - return ret; - -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 0, 0x01, enable != 0); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - ret |= set_reg_bits(sensor->slv_addr, P0_ANALOG_MODE1, 1, 0x01, enable != 0); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - // ret = write_reg(sensor->slv_addr, 0xfe, 0x00); - // ret |= set_reg_bits(sensor->slv_addr, P0_DEBUG_MODE3, 3, 0x01, enable); - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret > 0) { - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - if (mask > 0xFF) { - ESP_LOGE(TAG, "mask should not more than 0xff"); - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if (ret < 0) { - return ret; - } - value = (ret & ~mask) | (value & mask); - - if (mask > 0xFF) { - - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - write_reg(sensor->slv_addr, 0xfe, 0x00); - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = 0; - sensor->status.denoise = 0; - sensor->status.ae_level = 0; - sensor->status.gainceiling = 0; - sensor->status.awb = 0; - sensor->status.dcw = 0; - sensor->status.agc = 0; - sensor->status.aec = 0; - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x01); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, P0_ANALOG_MODE1, 0x02); - sensor->status.colorbar = 0; - sensor->status.bpc = 0; - sensor->status.wpc = 0; - sensor->status.raw_gma = 0; - sensor->status.lenc = 0; - sensor->status.quality = 0; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = 0; - sensor->status.agc_gain = 0; - sensor->status.aec_value = 0; - sensor->status.aec2 = 0; - - print_regs(sensor->slv_addr); - return 0; -} - -static int set_dummy(sensor_t *sensor, int val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val) -{ - ESP_LOGW(TAG, "Unsupported"); - return -1; -} - -int gc2145_detect(int slv_addr, sensor_id_t *id) -{ - if (GC2145_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read(slv_addr, CHIP_ID_LOW); - uint8_t MIDH = SCCB_Read(slv_addr, CHIP_ID_HIGH); - uint16_t PID = MIDH << 8 | MIDL; - if (GC2145_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int gc2145_init(sensor_t *sensor) -{ - sensor->init_status = init_status; - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_dummy; - sensor->set_brightness = set_dummy; - sensor->set_saturation = set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - sensor->set_quality = set_dummy; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_dummy; - sensor->set_gain_ctrl = set_dummy; - sensor->set_exposure_ctrl = set_dummy; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - sensor->set_aec2 = set_dummy; - sensor->set_awb_gain = set_dummy; - sensor->set_agc_gain = set_dummy; - sensor->set_aec_value = set_dummy; - - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - sensor->set_dcw = set_dummy; - sensor->set_bpc = set_dummy; - sensor->set_wpc = set_dummy; - - sensor->set_raw_gma = set_dummy; - sensor->set_lenc = set_dummy; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = NULL; - sensor->set_pll = NULL; - sensor->set_xclk = NULL; - - ESP_LOGD(TAG, "GC2145 Attached"); - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c deleted file mode 100644 index 86a8b8a0b5..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/nt99141.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * NT99141 driver. - * - */ -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "nt99141.h" -#include "nt99141_regs.h" -#include "nt99141_settings.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "NT99141"; -#endif - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg) -{ - int ret = SCCB_Read16(slv_addr, reg); -#ifdef REG_DEBUG_ON - - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } - -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask) -{ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static int read_reg16(uint8_t slv_addr, const uint16_t reg) -{ - int ret = 0, ret2 = 0; - ret = read_reg(slv_addr, reg); - - if (ret >= 0) { - ret = (ret & 0xFF) << 8; - ret2 = read_reg(slv_addr, reg + 1); - - if (ret2 < 0) { - ret = ret2; - } else { - ret |= ret2 & 0xFF; - } - } - - return ret; -} - - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value) -{ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write16(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - - if (old_value < 0) { - return old_value; - } - - if ((uint8_t)old_value != value) { - ESP_LOGD(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write16(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write16(slv_addr, reg, value);//maybe not? - } - - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } - -#endif - return ret; -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - - if (ret < 0) { - return ret; - } - - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) -{ - int i = 0, ret = 0; - - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - - i++; - } - - return ret; -} - -static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) -{ - if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { - return -1; - } - - return 0; -} - -static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) -{ - if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { - return -1; - } - - return 0; -} - -#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, enable?mask:0) - -static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t seld5, bool pclk_manual, uint8_t pclk_div) -{ - return -1; -} - -static int set_ae_level(sensor_t *sensor, int level); - -static int reset(sensor_t *sensor) -{ - - int ret = 0; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x01); - - if (ret) { - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - - vTaskDelay(100 / portTICK_PERIOD_MS); - ret = write_regs(sensor->slv_addr, sensor_default_regs); //re-initial - - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - ret = set_ae_level(sensor, 0); - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - const uint16_t (*regs)[2]; - - switch (pixformat) { - case PIXFORMAT_YUV422: - regs = sensor_fmt_yuv422; - break; - - case PIXFORMAT_GRAYSCALE: - regs = sensor_fmt_grayscale; - break; - - case PIXFORMAT_RGB565: - case PIXFORMAT_RGB888: - regs = sensor_fmt_rgb565; - break; - - case PIXFORMAT_JPEG: - regs = sensor_fmt_jpeg; - break; - - case PIXFORMAT_RAW: - regs = sensor_fmt_raw; - break; - - default: - ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); - return -1; - } - - ret = write_regs(sensor->slv_addr, regs); - - if (ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - - return ret; -} - -static int set_image_options(sensor_t *sensor) -{ - int ret = 0; - uint8_t reg20 = 0; - uint8_t reg21 = 0; - uint8_t reg4514 = 0; - uint8_t reg4514_test = 0; - - // V-Flip - if (sensor->status.vflip) { - reg20 |= 0x01; - reg4514_test |= 1; - } - - // H-Mirror - if (sensor->status.hmirror) { - reg21 |= 0x02; - reg4514_test |= 2; - } - - switch (reg4514_test) { - - } - - if (write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20 | reg21)) { - ESP_LOGE(TAG, "Setting Image Options Failed"); - ret = -1; - } - - ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", - sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - - sensor->status.framesize = framesize; - ret = write_regs(sensor->slv_addr, sensor_default_regs); - - if (framesize == FRAMESIZE_QVGA) { - ESP_LOGD(TAG, "Set FRAMESIZE_QVGA"); - ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA); -#if CONFIG_NT99141_SUPPORT_XSKIP - ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: xskip mode"); - ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA_xskip); -#elif CONFIG_NT99141_SUPPORT_CROP - ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: crop mode"); - ret = write_regs(sensor->slv_addr, sensor_framesize_QVGA_crop); -#endif - } else if (framesize == FRAMESIZE_VGA) { - ESP_LOGD(TAG, "Set FRAMESIZE_VGA"); - // ret = write_regs(sensor->slv_addr, sensor_framesize_VGA); - ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_xyskip);// Resolution:640*360 This configuration is equally-scaled without deforming -#ifdef CONFIG_NT99141_SUPPORT_XSKIP - ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: xskip mode"); - ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_xskip); -#elif CONFIG_NT99141_SUPPORT_CROP - ESP_LOGD(TAG, "Set FRAMESIZE_QVGA: crop mode"); - ret = write_regs(sensor->slv_addr, sensor_framesize_VGA_crop); -#endif - } else if (framesize >= FRAMESIZE_HD) { - ESP_LOGD(TAG, "Set FRAMESIZE_HD"); - ret = write_regs(sensor->slv_addr, sensor_framesize_HD); - } else { - ESP_LOGD(TAG, "Dont suppost this size, Set FRAMESIZE_VGA"); - ret = write_regs(sensor->slv_addr, sensor_framesize_VGA); - } - - return ret; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = set_image_options(sensor); - - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = set_image_options(sensor); - - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - - return ret; -} - -static int set_quality(sensor_t *sensor, int qs) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); - - if (ret == 0) { - sensor->status.quality = qs; - ESP_LOGD(TAG, "Set quality to: %d", qs); - } - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); - - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - - return ret; -} - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x32bb, 0x87, enable); - - if (ret == 0) { - ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); - sensor->status.agc = enable; - } - - return ret; -} - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - int data = 0; - // ret = write_reg_bits(sensor->slv_addr, 0x32bb, 0x87, enable); - data = read_reg(sensor->slv_addr, 0x3201); - ESP_LOGD(TAG, "set_exposure_ctrl:enable"); - if (enable) { - ESP_LOGD(TAG, "set_exposure_ctrl:enable"); - ret = write_reg(sensor->slv_addr, 0x3201, (1 << 5) | data); - } else { - ESP_LOGD(TAG, "set_exposure_ctrl:disable"); - ret = write_reg(sensor->slv_addr, 0x3201, (~(1 << 5)) & data); - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); - sensor->status.aec = enable; - } - - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set awb to: %d", enable); - sensor->status.awb = enable; - } - - return ret; -} - -//Advanced AWB -static int set_dcw_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set dcw to: %d", enable); - sensor->status.dcw = enable; - } - - return ret; -} - -//night mode enable -static int set_aec2(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set aec2 to: %d", enable); - sensor->status.aec2 = enable; - } - - return ret; -} - -static int set_bpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set bpc to: %d", enable); - sensor->status.bpc = enable; - } - - return ret; -} - -static int set_wpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set wpc to: %d", enable); - sensor->status.wpc = enable; - } - - return ret; -} - -//Gamma enable -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set raw_gma to: %d", enable); - sensor->status.raw_gma = enable; - } - - return ret; -} - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - - if (ret == 0) { - ESP_LOGD(TAG, "Set lenc to: %d", enable); - sensor->status.lenc = enable; - } - - return ret; -} - -static int get_agc_gain(sensor_t *sensor) -{ - ESP_LOGD(TAG, "get_agc_gain can not be configured at present"); - return 0; -} - -//real gain -static int set_agc_gain(sensor_t *sensor, int gain) -{ - ESP_LOGD(TAG, "set_agc_gain can not be configured at present"); - // ESP_LOGD(TAG, "GAIN = %d\n", gain); - int cnt = gain / 2; - - switch (cnt) { - case 0: - ESP_LOGD(TAG, "set_agc_gain: 1x"); - write_reg(sensor->slv_addr, 0X301D, 0X00); - break; - - case 1: - ESP_LOGD(TAG,"set_agc_gain: 2x"); - write_reg(sensor->slv_addr, 0X301D, 0X0F); - break; - - case 2: - ESP_LOGD(TAG,"set_agc_gain: 4x"); - write_reg(sensor->slv_addr, 0X301D, 0X2F); - break; - - case 3: - ESP_LOGD(TAG,"set_agc_gain: 6x"); - write_reg(sensor->slv_addr, 0X301D, 0X37); - break; - - case 4: - ESP_LOGD(TAG,"set_agc_gain: 8x"); - write_reg(sensor->slv_addr, 0X301D, 0X3F); - break; - - default: - ESP_LOGD(TAG,"fail set_agc_gain"); - break; - } - - return 0; -} - -static int get_aec_value(sensor_t *sensor) -{ - ESP_LOGD(TAG, "get_aec_value can not be configured at present"); - return 0; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - ESP_LOGD(TAG, "set_aec_value can not be configured at present"); - int ret = 0; - // ESP_LOGD(TAG, " set_aec_value to: %d", value); - ret = write_reg_bits(sensor->slv_addr, 0x3012, 0x00, (value >> 8) & 0xff); - ret = write_reg_bits(sensor->slv_addr, 0x3013, 0x01, value & 0xff); - - if (ret == 0) { - ESP_LOGD(TAG, " set_aec_value to: %d", value); - // sensor->status.aec = enable; - } - - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level) -{ - ESP_LOGD(TAG, "set_ae_level can not be configured at present"); - int ret = 0; - - if (level < 0) { - level = 0; - } else if (level > 9) { - level = 9; - } - - for (int i = 0; i < 5; i++) { - ret += write_reg(sensor->slv_addr, sensor_ae_level[ 5 * level + i ][0], sensor_ae_level[5 * level + i ][1]); - } - - if (ret) { - ESP_LOGE(TAG, " fail to set ae level: %d", ret); - } - - return 0; -} - -static int set_wb_mode(sensor_t *sensor, int mode) -{ - int ret = 0; - - if (mode < 0 || mode > 4) { - return -1; - } - - ret = write_reg(sensor->slv_addr, 0x3201, (mode != 0)); - - if (ret) { - return ret; - } - - switch (mode) { - case 1://Sunny - ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) - || write_reg16(sensor->slv_addr, 0x3291, 0x38) - || write_reg16(sensor->slv_addr, 0x3296, 0x01) - || write_reg16(sensor->slv_addr, 0x3297, 0x68) - || write_reg16(sensor->slv_addr, 0x3060, 0x01); - - break; - - case 2://Cloudy - - ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) - || write_reg16(sensor->slv_addr, 0x3291, 0x51) - || write_reg16(sensor->slv_addr, 0x3296, 0x01) - || write_reg16(sensor->slv_addr, 0x3297, 0x00) - || write_reg16(sensor->slv_addr, 0x3060, 0x01); - break; - - case 3://INCANDESCENCE] - ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) - || write_reg16(sensor->slv_addr, 0x3291, 0x30) - || write_reg16(sensor->slv_addr, 0x3296, 0x01) - || write_reg16(sensor->slv_addr, 0x3297, 0xCB) - || write_reg16(sensor->slv_addr, 0x3060, 0x01); - break; - - case 4://FLUORESCENT - ret = write_reg16(sensor->slv_addr, 0x3290, 0x01) - || write_reg16(sensor->slv_addr, 0x3291, 0x70) - || write_reg16(sensor->slv_addr, 0x3296, 0x01) - || write_reg16(sensor->slv_addr, 0x3297, 0xFF) - || write_reg16(sensor->slv_addr, 0x3060, 0x01); - break; - - default://AUTO - break; - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set wb_mode to: %d", mode); - sensor->status.wb_mode = mode; - } - - return ret; -} - -static int set_awb_gain_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - int old_mode = sensor->status.wb_mode; - int mode = enable ? old_mode : 0; - - ret = set_wb_mode(sensor, mode); - - if (ret == 0) { - sensor->status.wb_mode = old_mode; - ESP_LOGD(TAG, "Set awb_gain to: %d", enable); - sensor->status.awb_gain = enable; - } - - return ret; -} - -static int set_special_effect(sensor_t *sensor, int effect) -{ - int ret = 0; - - if (effect < 0 || effect > 6) { - return -1; - } - - uint8_t *regs = (uint8_t *)sensor_special_effects[effect]; - ret = write_reg(sensor->slv_addr, 0x32F1, regs[0]) - || write_reg(sensor->slv_addr, 0x32F4, regs[1]) - || write_reg(sensor->slv_addr, 0x32F5, regs[2]) - || write_reg(sensor->slv_addr, 0x3060, regs[3]); - - if (ret == 0) { - ESP_LOGD(TAG, "Set special_effect to: %d", effect); - sensor->status.special_effect = effect; - } - - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret = 0; - uint8_t value = 0; - - switch (level) { - case 3: - value = 0xA0; - break; - - case 2: - value = 0x90; - break; - - case 1: - value = 0x88; - break; - - case -1: - value = 0x78; - break; - - case -2: - value = 0x70; - break; - - case -3: - value = 0x60; - break; - - default: // 0 - break; - } - - ret = write_reg(sensor->slv_addr, 0x32F2, value); - - if (ret == 0) { - ESP_LOGD(TAG, "Set brightness to: %d", level); - sensor->status.brightness = level; - } - - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - uint8_t value1 = 0, value2 = 0 ; - - switch (level) { - case 3: - value1 = 0xD0; - value2 = 0xB0; - break; - - case 2: - value1 = 0xE0; - value2 = 0xA0; - break; - - case 1: - value1 = 0xF0; - value2 = 0x90; - break; - - case 0: - value1 = 0x00; - value2 = 0x80; - break; - - case -1: - value1 = 0x10; - value2 = 0x70; - break; - - case -2: - value1 = 0x20; - value2 = 0x60; - break; - - case -3: - value1 = 0x30; - value2 = 0x50; - break; - - default: // 0 - break; - } - - ret = write_reg(sensor->slv_addr, 0x32FC, value1); - ret = write_reg(sensor->slv_addr, 0x32F2, value2); - ret = write_reg(sensor->slv_addr, 0x3060, 0x01); - - if (ret == 0) { - ESP_LOGD(TAG, "Set contrast to: %d", level); - sensor->status.contrast = level; - } - - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret = 0; - - if (level > 4 || level < -4) { - return -1; - } - - uint8_t *regs = (uint8_t *)sensor_saturation_levels[level + 4]; - { - ret = write_reg(sensor->slv_addr, 0x32F3, regs[0]); - - if (ret) { - return ret; - } - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set saturation to: %d", level); - sensor->status.saturation = level; - } - - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - - if (level > 3 || level < -3) { - return -1; - } - - uint8_t mt_offset_2 = (level + 3) * 8; - uint8_t mt_offset_1 = mt_offset_2 + 1; - - ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto - || write_reg(sensor->slv_addr, 0x5300, 0x10) - || write_reg(sensor->slv_addr, 0x5301, 0x10) - || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) - || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) - || write_reg(sensor->slv_addr, 0x5309, 0x10) - || write_reg(sensor->slv_addr, 0x530a, 0x10) - || write_reg(sensor->slv_addr, 0x530b, 0x04) - || write_reg(sensor->slv_addr, 0x530c, 0x06); - - if (ret == 0) { - ESP_LOGD(TAG, "Set sharpness to: %d", level); - sensor->status.sharpness = level; - } - - return ret; -} - -static int set_gainceiling(sensor_t *sensor, gainceiling_t level) -{ - ESP_LOGD(TAG, "set_gainceiling can not be configured at present"); - return 0; -} - -static int get_denoise(sensor_t *sensor) -{ - - return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; -} - -static int set_denoise(sensor_t *sensor, int level) -{ - ESP_LOGD(TAG, "set_denoise can not be configured at present"); - return 0; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0, ret2 = 0; - - if (mask > 0xFF) { - ret = read_reg16(sensor->slv_addr, reg); - - if (ret >= 0 && mask > 0xFFFF) { - ret2 = read_reg(sensor->slv_addr, reg + 2); - - if (ret2 >= 0) { - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - - if (ret > 0) { - ret &= mask; - } - - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0, ret2 = 0; - - if (mask > 0xFF) { - ret = read_reg16(sensor->slv_addr, reg); - - if (ret >= 0 && mask > 0xFFFF) { - ret2 = read_reg(sensor->slv_addr, reg + 2); - - if (ret2 >= 0) { - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - - if (ret < 0) { - return ret; - } - - value = (ret & ~mask) | (value & mask); - - if (mask > 0xFFFF) { - ret = write_reg16(sensor->slv_addr, reg, value >> 8); - - if (ret >= 0) { - ret = write_reg(sensor->slv_addr, reg + 2, value & 0xFF); - } - } else if (mask > 0xFF) { - ret = write_reg16(sensor->slv_addr, reg, value); - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - - return ret; -} - -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) -{ - int ret = 0; - ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) - || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) - || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) - || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY); - - if (!ret) { - sensor->status.scale = scale; - sensor->status.binning = binning; - ret = set_image_options(sensor); - } - - return ret; -} - -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) -{ - return set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); -} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - if (xclk > 10) - { - ESP_LOGE(TAG, "only XCLK under 10MHz is supported, and XCLK is now set to 10M"); - xclk = 10; - } - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int nt99141_detect(int slv_addr, sensor_id_t *id) -{ - if (NT99141_SCCB_ADDR == slv_addr) { - SCCB_Write16(slv_addr, 0x3008, 0x01);//bank sensor - uint16_t h = SCCB_Read16(slv_addr, 0x3000); - uint16_t l = SCCB_Read16(slv_addr, 0x3001); - uint16_t PID = (h<<8) | l; - if (NT99141_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x3301)); - sensor->status.denoise = get_denoise(sensor); - sensor->status.ae_level = 0; - sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x32F0) & 0xFF; - sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x10); - sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); - sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); - sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); - sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); - sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); - sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); - sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); - sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); - sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3000, 0x01); - sensor->status.agc_gain = get_agc_gain(sensor); - sensor->status.aec_value = get_aec_value(sensor); - sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3000, 0x04); - return 0; -} - -int nt99141_init(sensor_t *sensor) -{ - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_contrast; - sensor->set_brightness = set_brightness; - sensor->set_saturation = set_saturation; - sensor->set_sharpness = set_sharpness; - sensor->set_gainceiling = set_gainceiling; - sensor->set_quality = set_quality; - sensor->set_colorbar = set_colorbar; - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_whitebal = set_whitebal; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->init_status = init_status; - sensor->set_aec2 = set_aec2; - sensor->set_aec_value = set_aec_value; - sensor->set_special_effect = set_special_effect; - sensor->set_wb_mode = set_wb_mode; - sensor->set_ae_level = set_ae_level; - sensor->set_dcw = set_dcw_dsp; - sensor->set_bpc = set_bpc_dsp; - sensor->set_wpc = set_wpc_dsp; - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - sensor->set_denoise = set_denoise; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c deleted file mode 100644 index 7e3d77174d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov2640.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV2640 driver. - * - */ -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "ov2640.h" -#include "ov2640_regs.h" -#include "ov2640_settings.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "ov2640"; -#endif - -static volatile ov2640_bank_t reg_bank = BANK_MAX; -static int set_bank(sensor_t *sensor, ov2640_bank_t bank) -{ - int res = 0; - if (bank != reg_bank) { - reg_bank = bank; - res = SCCB_Write(sensor->slv_addr, BANK_SEL, bank); - } - return res; -} - -static int write_regs(sensor_t *sensor, const uint8_t (*regs)[2]) -{ - int i=0, res = 0; - while (regs[i][0]) { - if (regs[i][0] == BANK_SEL) { - res = set_bank(sensor, regs[i][1]); - } else { - res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); - } - if (res) { - return res; - } - i++; - } - return res; -} - -static int write_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg, uint8_t value) -{ - int ret = set_bank(sensor, bank); - if(!ret) { - ret = SCCB_Write(sensor->slv_addr, reg, value); - } - return ret; -} - -static int set_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - - ret = set_bank(sensor, bank); - if(ret) { - return ret; - } - c_value = SCCB_Read(sensor->slv_addr, reg); - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = SCCB_Write(sensor->slv_addr, reg, new_value); - return ret; -} - -static int read_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg) -{ - if(set_bank(sensor, bank)){ - return 0; - } - return SCCB_Read(sensor->slv_addr, reg); -} - -static uint8_t get_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask) -{ - return (read_reg(sensor, bank, reg) >> offset) & mask; -} - -static int write_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t mask, int enable) -{ - return set_reg_bits(sensor, bank, reg, 0, mask, enable?mask:0); -} - -#define WRITE_REGS_OR_RETURN(regs) ret = write_regs(sensor, regs); if(ret){return ret;} -#define WRITE_REG_OR_RETURN(bank, reg, val) ret = write_reg(sensor, bank, reg, val); if(ret){return ret;} -#define SET_REG_BITS_OR_RETURN(bank, reg, offset, mask, val) ret = set_reg_bits(sensor, bank, reg, offset, mask, val); if(ret){return ret;} - -static int reset(sensor_t *sensor) -{ - int ret = 0; - WRITE_REG_OR_RETURN(BANK_SENSOR, COM7, COM7_SRST); - vTaskDelay(10 / portTICK_PERIOD_MS); - WRITE_REGS_OR_RETURN(ov2640_settings_cif); - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - sensor->pixformat = pixformat; - switch (pixformat) { - case PIXFORMAT_RGB565: - case PIXFORMAT_RGB888: - WRITE_REGS_OR_RETURN(ov2640_settings_rgb565); - break; - case PIXFORMAT_YUV422: - case PIXFORMAT_GRAYSCALE: - WRITE_REGS_OR_RETURN(ov2640_settings_yuv422); - break; - case PIXFORMAT_JPEG: - WRITE_REGS_OR_RETURN(ov2640_settings_jpeg3); - break; - default: - ret = -1; - break; - } - if(!ret) { - vTaskDelay(10 / portTICK_PERIOD_MS); - } - - return ret; -} - -static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x, int offset_y, int max_x, int max_y, int w, int h){ - int ret = 0; - const uint8_t (*regs)[2]; - ov2640_clk_t c; - c.reserved = 0; - - max_x /= 4; - max_y /= 4; - w /= 4; - h /= 4; - uint8_t win_regs[][2] = { - {BANK_SEL, BANK_DSP}, - {HSIZE, max_x & 0xFF}, - {VSIZE, max_y & 0xFF}, - {XOFFL, offset_x & 0xFF}, - {YOFFL, offset_y & 0xFF}, - {VHYX, ((max_y >> 1) & 0X80) | ((offset_y >> 4) & 0X70) | ((max_x >> 5) & 0X08) | ((offset_x >> 8) & 0X07)}, - {TEST, (max_x >> 2) & 0X80}, - {ZMOW, (w)&0xFF}, - {ZMOH, (h)&0xFF}, - {ZMHH, ((h>>6)&0x04)|((w>>8)&0x03)}, - {0, 0} - }; - - if (sensor->pixformat == PIXFORMAT_JPEG) { - c.clk_2x = 0; - c.clk_div = 0; - c.pclk_auto = 0; - c.pclk_div = 8; - if(mode == OV2640_MODE_UXGA) { - c.pclk_div = 12; - } - // if (sensor->xclk_freq_hz == 16000000) { - // c.pclk_div = c.pclk_div / 2; - // } - } else { -#if CONFIG_IDF_TARGET_ESP32 - c.clk_2x = 0; -#else - c.clk_2x = 1; -#endif - c.clk_div = 7; - c.pclk_auto = 1; - c.pclk_div = 8; - if (mode == OV2640_MODE_CIF) { - c.clk_div = 3; - } else if(mode == OV2640_MODE_UXGA) { - c.pclk_div = 12; - } - } - ESP_LOGI(TAG, "Set PLL: clk_2x: %u, clk_div: %u, pclk_auto: %u, pclk_div: %u", c.clk_2x, c.clk_div, c.pclk_auto, c.pclk_div); - - if (mode == OV2640_MODE_CIF) { - regs = ov2640_settings_to_cif; - } else if (mode == OV2640_MODE_SVGA) { - regs = ov2640_settings_to_svga; - } else { - regs = ov2640_settings_to_uxga; - } - - WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS); - WRITE_REGS_OR_RETURN(regs); - WRITE_REGS_OR_RETURN(win_regs); - WRITE_REG_OR_RETURN(BANK_SENSOR, CLKRC, c.clk); - WRITE_REG_OR_RETURN(BANK_DSP, R_DVP_SP, c.pclk); - WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_EN); - - vTaskDelay(10 / portTICK_PERIOD_MS); - //required when changing resolution - set_pixformat(sensor, sensor->pixformat); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - aspect_ratio_t ratio = resolution[framesize].aspect_ratio; - uint16_t max_x = ratio_table[ratio].max_x; - uint16_t max_y = ratio_table[ratio].max_y; - uint16_t offset_x = ratio_table[ratio].offset_x; - uint16_t offset_y = ratio_table[ratio].offset_y; - ov2640_sensor_mode_t mode = OV2640_MODE_UXGA; - - sensor->status.framesize = framesize; - - - - if (framesize <= FRAMESIZE_CIF) { - mode = OV2640_MODE_CIF; - max_x /= 4; - max_y /= 4; - offset_x /= 4; - offset_y /= 4; - if(max_y > 296){ - max_y = 296; - } - } else if (framesize <= FRAMESIZE_SVGA) { - mode = OV2640_MODE_SVGA; - max_x /= 2; - max_y /= 2; - offset_x /= 2; - offset_y /= 2; - } - - ret = set_window(sensor, mode, offset_x, offset_y, max_x, max_y, w, h); - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret=0; - level += 3; - if (level <= 0 || level > NUM_CONTRAST_LEVELS) { - return -1; - } - sensor->status.contrast = level-3; - for (int i=0; i<7; i++) { - WRITE_REG_OR_RETURN(BANK_DSP, contrast_regs[0][i], contrast_regs[level][i]); - } - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret=0; - level += 3; - if (level <= 0 || level > NUM_BRIGHTNESS_LEVELS) { - return -1; - } - sensor->status.brightness = level-3; - for (int i=0; i<5; i++) { - WRITE_REG_OR_RETURN(BANK_DSP, brightness_regs[0][i], brightness_regs[level][i]); - } - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret=0; - level += 3; - if (level <= 0 || level > NUM_SATURATION_LEVELS) { - return -1; - } - sensor->status.saturation = level-3; - for (int i=0; i<5; i++) { - WRITE_REG_OR_RETURN(BANK_DSP, saturation_regs[0][i], saturation_regs[level][i]); - } - return ret; -} - -static int set_special_effect(sensor_t *sensor, int effect) -{ - int ret=0; - effect++; - if (effect <= 0 || effect > NUM_SPECIAL_EFFECTS) { - return -1; - } - sensor->status.special_effect = effect-1; - for (int i=0; i<5; i++) { - WRITE_REG_OR_RETURN(BANK_DSP, special_effects_regs[0][i], special_effects_regs[effect][i]); - } - return ret; -} - -static int set_wb_mode(sensor_t *sensor, int mode) -{ - int ret=0; - if (mode < 0 || mode > NUM_WB_MODES) { - return -1; - } - sensor->status.wb_mode = mode; - SET_REG_BITS_OR_RETURN(BANK_DSP, 0XC7, 6, 1, mode?1:0); - if(mode) { - for (int i=0; i<3; i++) { - WRITE_REG_OR_RETURN(BANK_DSP, wb_modes_regs[0][i], wb_modes_regs[mode][i]); - } - } - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level) -{ - int ret=0; - level += 3; - if (level <= 0 || level > NUM_AE_LEVELS) { - return -1; - } - sensor->status.ae_level = level-3; - for (int i=0; i<3; i++) { - WRITE_REG_OR_RETURN(BANK_SENSOR, ae_levels_regs[0][i], ae_levels_regs[level][i]); - } - return ret; -} - -static int set_quality(sensor_t *sensor, int quality) -{ - if(quality < 0) { - quality = 0; - } else if(quality > 63) { - quality = 63; - } - sensor->status.quality = quality; - return write_reg(sensor, BANK_DSP, QS, quality); -} - -static int set_agc_gain(sensor_t *sensor, int gain) -{ - if(gain < 0) { - gain = 0; - } else if(gain > 30) { - gain = 30; - } - sensor->status.agc_gain = gain; - return write_reg(sensor, BANK_SENSOR, GAIN, agc_gain_tbl[gain]); -} - -static int set_gainceiling_sensor(sensor_t *sensor, gainceiling_t gainceiling) -{ - sensor->status.gainceiling = gainceiling; - //return write_reg(sensor, BANK_SENSOR, COM9, COM9_AGC_SET(gainceiling)); - return set_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7, gainceiling); -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - if(value < 0) { - value = 0; - } else if(value > 1200) { - value = 1200; - } - sensor->status.aec_value = value; - return set_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3, value & 0x3) - || write_reg(sensor, BANK_SENSOR, AEC, (value >> 2) & 0xFF) - || set_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F, value >> 10); -} - -static int set_aec2(sensor_t *sensor, int enable) -{ - sensor->status.aec2 = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1, enable?0:1); -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - sensor->status.colorbar = enable; - return write_reg_bits(sensor, BANK_SENSOR, COM7, COM7_COLOR_BAR, enable?1:0); -} - -static int set_agc_sensor(sensor_t *sensor, int enable) -{ - sensor->status.agc = enable; - return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AGC_EN, enable?1:0); -} - -static int set_aec_sensor(sensor_t *sensor, int enable) -{ - sensor->status.aec = enable; - return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AEC_EN, enable?1:0); -} - -static int set_hmirror_sensor(sensor_t *sensor, int enable) -{ - sensor->status.hmirror = enable; - return write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_HFLIP_IMG, enable?1:0); -} - -static int set_vflip_sensor(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VREF_EN, enable?1:0); - return ret & write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VFLIP_IMG, enable?1:0); -} - -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - sensor->status.raw_gma = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1, enable?1:0); -} - -static int set_awb_dsp(sensor_t *sensor, int enable) -{ - sensor->status.awb = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1, enable?1:0); -} - -static int set_awb_gain_dsp(sensor_t *sensor, int enable) -{ - sensor->status.awb_gain = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1, enable?1:0); -} - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - sensor->status.lenc = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1, enable?1:0); -} - -static int set_dcw_dsp(sensor_t *sensor, int enable) -{ - sensor->status.dcw = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1, enable?1:0); -} - -static int set_bpc_dsp(sensor_t *sensor, int enable) -{ - sensor->status.bpc = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1, enable?1:0); -} - -static int set_wpc_dsp(sensor_t *sensor, int enable) -{ - sensor->status.wpc = enable; - return set_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1, enable?1:0); -} - -//unsupported -static int set_sharpness(sensor_t *sensor, int level) -{ - return -1; -} - -static int set_denoise(sensor_t *sensor, int level) -{ - return -1; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF); - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF); - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - ret = write_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF, value); - return ret; -} - -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) -{ - return set_window(sensor, (ov2640_sensor_mode_t)startX, offsetX, offsetY, totalX, totalY, outputX, outputY); -} - -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) -{ - return -1; -} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -static int init_status(sensor_t *sensor){ - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.ae_level = 0; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - - sensor->status.agc_gain = 30; - int agc_gain = read_reg(sensor, BANK_SENSOR, GAIN); - for (int i=0; i<30; i++){ - if(agc_gain >= agc_gain_tbl[i] && agc_gain < agc_gain_tbl[i+1]){ - sensor->status.agc_gain = i; - break; - } - } - - sensor->status.aec_value = ((uint16_t)get_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F) << 10) - | ((uint16_t)read_reg(sensor, BANK_SENSOR, AEC) << 2) - | get_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3);//0 - 1200 - sensor->status.quality = read_reg(sensor, BANK_DSP, QS); - sensor->status.gainceiling = get_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7); - - sensor->status.awb = get_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1); - sensor->status.awb_gain = get_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1); - sensor->status.aec = get_reg_bits(sensor, BANK_SENSOR, COM8, 0, 1); - sensor->status.aec2 = get_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1); - sensor->status.agc = get_reg_bits(sensor, BANK_SENSOR, COM8, 2, 1); - sensor->status.bpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1); - sensor->status.wpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1); - sensor->status.raw_gma = get_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1); - sensor->status.lenc = get_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1); - sensor->status.hmirror = get_reg_bits(sensor, BANK_SENSOR, REG04, 7, 1); - sensor->status.vflip = get_reg_bits(sensor, BANK_SENSOR, REG04, 6, 1); - sensor->status.dcw = get_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1); - sensor->status.colorbar = get_reg_bits(sensor, BANK_SENSOR, COM7, 1, 1); - - sensor->status.sharpness = 0;//not supported - sensor->status.denoise = 0; - return 0; -} - -int ov2640_detect(int slv_addr, sensor_id_t *id) -{ - if (OV2640_SCCB_ADDR == slv_addr) { - SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor - uint16_t PID = SCCB_Read(slv_addr, 0x0A); - if (OV2640_PID == PID) { - id->PID = PID; - id->VER = SCCB_Read(slv_addr, REG_VER); - id->MIDL = SCCB_Read(slv_addr, REG_MIDL); - id->MIDH = SCCB_Read(slv_addr, REG_MIDH); - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int ov2640_init(sensor_t *sensor) -{ - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_contrast; - sensor->set_brightness= set_brightness; - sensor->set_saturation= set_saturation; - - sensor->set_quality = set_quality; - sensor->set_colorbar = set_colorbar; - - sensor->set_gainceiling = set_gainceiling_sensor; - sensor->set_gain_ctrl = set_agc_sensor; - sensor->set_exposure_ctrl = set_aec_sensor; - sensor->set_hmirror = set_hmirror_sensor; - sensor->set_vflip = set_vflip_sensor; - - sensor->set_whitebal = set_awb_dsp; - sensor->set_aec2 = set_aec2; - sensor->set_aec_value = set_aec_value; - sensor->set_special_effect = set_special_effect; - sensor->set_wb_mode = set_wb_mode; - sensor->set_ae_level = set_ae_level; - - sensor->set_dcw = set_dcw_dsp; - sensor->set_bpc = set_bpc_dsp; - sensor->set_wpc = set_wpc_dsp; - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - - //not supported - sensor->set_sharpness = set_sharpness; - sensor->set_denoise = set_denoise; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - ESP_LOGD(TAG, "OV2640 Attached"); - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c deleted file mode 100644 index b9ebdba3ba..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov3660.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV3660 driver. - * - */ -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "ov3660.h" -#include "ov3660_regs.h" -#include "ov3660_settings.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "ov3660"; -#endif - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg){ - int ret = SCCB_Read16(slv_addr, reg); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask){ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static int read_reg16(uint8_t slv_addr, const uint16_t reg){ - int ret = 0, ret2 = 0; - ret = read_reg(slv_addr, reg); - if (ret >= 0) { - ret = (ret & 0xFF) << 8; - ret2 = read_reg(slv_addr, reg+1); - if (ret2 < 0) { - ret = ret2; - } else { - ret |= ret2 & 0xFF; - } - } - return ret; -} - - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value){ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write16(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - if (old_value < 0) { - return old_value; - } - if ((uint8_t)old_value != value) { - ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write16(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write16(slv_addr, reg, value);//maybe not? - } - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - if(ret < 0) { - return ret; - } - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) -{ - int i = 0, ret = 0; - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) -{ - if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { - return -1; - } - return 0; -} - -static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) -{ - if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { - return -1; - } - return 0; -} - -#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, enable?mask:0) - -static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pll_pre_div, bool pll_root_2x, int pll_seld5, bool pclk_manual, int pclk_div) -{ - const int pll_pre_div2x_map[] = { 2, 3, 4, 6 };//values are multiplied by two to avoid floats - const int pll_seld52x_map[] = { 2, 2, 4, 5 }; - - if(!pll_sys_div) { - pll_sys_div = 1; - } - - int pll_pre_div2x = pll_pre_div2x_map[pll_pre_div]; - int pll_root_div = pll_root_2x?2:1; - int pll_seld52x = pll_seld52x_map[pll_seld5]; - - int VCO = (xclk / 1000) * pll_multiplier * pll_root_div * 2 / pll_pre_div2x; - int PLLCLK = pll_bypass?(xclk):(VCO * 1000 * 2 / pll_sys_div / pll_seld52x); - int PCLK = PLLCLK / 2 / ((pclk_manual && pclk_div)?pclk_div:1); - int SYSCLK = PLLCLK / 4; - - ESP_LOGI(TAG, "Calculated VCO: %d Hz, PLLCLK: %d Hz, SYSCLK: %d Hz, PCLK: %d Hz", VCO*1000, PLLCLK, SYSCLK, PCLK); - return SYSCLK; -} - -static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t seld5, bool pclk_manual, uint8_t pclk_div){ - int ret = 0; - if(multiplier > 31 || sys_div > 15 || pre_div > 3 || pclk_div > 31 || seld5 > 3){ - ESP_LOGE(TAG, "Invalid arguments"); - return -1; - } - - calc_sysclk(sensor->xclk_freq_hz, bypass, multiplier, sys_div, pre_div, root_2x, seld5, pclk_manual, pclk_div); - - ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL0, bypass?0x80:0x00); - if (ret == 0) { - ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL1, multiplier & 0x1f); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL2, 0x10 | (sys_div & 0x0f)); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, SC_PLLS_CTRL3, (pre_div & 0x3) << 4 | seld5 | (root_2x?0x40:0x00)); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, PCLK_RATIO, pclk_div & 0x1f); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, VFIFO_CTRL0C, pclk_manual?0x22:0x20); - } - if(ret){ - ESP_LOGE(TAG, "set_sensor_pll FAILED!"); - } - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level); - -static int reset(sensor_t *sensor) -{ - int ret = 0; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x82); - if(ret){ - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - ret = write_regs(sensor->slv_addr, sensor_default_regs); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - ret = set_ae_level(sensor, 0); - vTaskDelay(100 / portTICK_PERIOD_MS); - } - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - const uint16_t (*regs)[2]; - - switch (pixformat) { - case PIXFORMAT_YUV422: - regs = sensor_fmt_yuv422; - break; - - case PIXFORMAT_GRAYSCALE: - regs = sensor_fmt_grayscale; - break; - - case PIXFORMAT_RGB565: - case PIXFORMAT_RGB888: - regs = sensor_fmt_rgb565; - break; - - case PIXFORMAT_JPEG: - regs = sensor_fmt_jpeg; - break; - - case PIXFORMAT_RAW: - regs = sensor_fmt_raw; - break; - - default: - ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); - return -1; - } - - ret = write_regs(sensor->slv_addr, regs); - if(ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - return ret; -} - -static int set_image_options(sensor_t *sensor) -{ - int ret = 0; - uint8_t reg20 = 0; - uint8_t reg21 = 0; - uint8_t reg4514 = 0; - uint8_t reg4514_test = 0; - - // compression - if (sensor->pixformat == PIXFORMAT_JPEG) { - reg21 |= 0x20; - } - - // binning - if (sensor->status.binning) { - reg20 |= 0x01; - reg21 |= 0x01; - reg4514_test |= 4; - } else { - reg20 |= 0x40; - } - - // V-Flip - if (sensor->status.vflip) { - reg20 |= 0x06; - reg4514_test |= 1; - } - - // H-Mirror - if (sensor->status.hmirror) { - reg21 |= 0x06; - reg4514_test |= 2; - } - - switch (reg4514_test) { - //no binning - case 0: reg4514 = 0x88; break;//normal - case 1: reg4514 = 0x88; break;//v-flip - case 2: reg4514 = 0xbb; break;//h-mirror - case 3: reg4514 = 0xbb; break;//v-flip+h-mirror - //binning - case 4: reg4514 = 0xaa; break;//normal - case 5: reg4514 = 0xbb; break;//v-flip - case 6: reg4514 = 0xbb; break;//h-mirror - case 7: reg4514 = 0xaa; break;//v-flip+h-mirror - } - - if(write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20) - || write_reg(sensor->slv_addr, TIMING_TC_REG21, reg21) - || write_reg(sensor->slv_addr, 0x4514, reg4514)){ - ESP_LOGE(TAG, "Setting Image Options Failed"); - ret = -1; - } - - if (sensor->status.binning) { - ret = write_reg(sensor->slv_addr, 0x4520, 0x0b) - || write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1 - || write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1 - } else { - ret = write_reg(sensor->slv_addr, 0x4520, 0xb0) - || write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1 - || write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1 - } - - ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", - sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - - if(framesize > FRAMESIZE_QXGA){ - ESP_LOGW(TAG, "Invalid framesize: %u", framesize); - framesize = FRAMESIZE_QXGA; - } - framesize_t old_framesize = sensor->status.framesize; - sensor->status.framesize = framesize; - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - aspect_ratio_t ratio = resolution[sensor->status.framesize].aspect_ratio; - ratio_settings_t settings = ratio_table[ratio]; - - sensor->status.binning = (w <= (settings.max_width / 2) && h <= (settings.max_height / 2)); - sensor->status.scale = !((w == settings.max_width && h == settings.max_height) - || (w == (settings.max_width / 2) && h == (settings.max_height / 2))); - - ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, settings.start_x, settings.start_y) - || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, settings.end_x, settings.end_y) - || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, w, h); - - if (ret) { - goto fail; - } - - if (sensor->status.binning) { - ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, (settings.total_y / 2) + 1) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, 8, 2); - } else { - ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, settings.total_y) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, 16, 6); - } - - if (ret == 0) { - ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, sensor->status.scale); - } - - if (ret == 0) { - ret = set_image_options(sensor); - } - - if (ret) { - goto fail; - } - - if (sensor->pixformat == PIXFORMAT_JPEG) { - if (framesize == FRAMESIZE_QXGA || sensor->xclk_freq_hz == 16000000) { - //40MHz SYSCLK and 10MHz PCLK - ret = set_pll(sensor, false, 24, 1, 3, false, 0, true, 8); - } else { - //50MHz SYSCLK and 10MHz PCLK - ret = set_pll(sensor, false, 30, 1, 3, false, 0, true, 10); - } - } else { - //tuned for 16MHz XCLK and 8MHz PCLK - if (framesize > FRAMESIZE_HVGA) { - //8MHz SYSCLK and 8MHz PCLK (4.44 FPS) - ret = set_pll(sensor, false, 4, 1, 0, false, 2, true, 2); - } else if (framesize >= FRAMESIZE_QVGA) { - //16MHz SYSCLK and 8MHz PCLK (10.25 FPS) - ret = set_pll(sensor, false, 8, 1, 0, false, 2, true, 4); - } else { - //32MHz SYSCLK and 8MHz PCLK (17.77 FPS) - ret = set_pll(sensor, false, 8, 1, 0, false, 0, true, 8); - } - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); - } - return ret; - -fail: - sensor->status.framesize = old_framesize; - ESP_LOGE(TAG, "Setting framesize to: %ux%u failed", w, h); - return ret; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = set_image_options(sensor); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = set_image_options(sensor); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_quality(sensor_t *sensor, int qs) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); - if (ret == 0) { - sensor->status.quality = qs; - ESP_LOGD(TAG, "Set quality to: %d", qs); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - return ret; -} - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); - sensor->status.agc = enable; - } - return ret; -} - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); - sensor->status.aec = enable; - } - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set awb to: %d", enable); - sensor->status.awb = enable; - } - return ret; -} - -//Advanced AWB -static int set_dcw_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5183, 0x80, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set dcw to: %d", enable); - sensor->status.dcw = enable; - } - return ret; -} - -//night mode enable -static int set_aec2(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x3a00, 0x04, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set aec2 to: %d", enable); - sensor->status.aec2 = enable; - } - return ret; -} - -static int set_bpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x04, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set bpc to: %d", enable); - sensor->status.bpc = enable; - } - return ret; -} - -static int set_wpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x02, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set wpc to: %d", enable); - sensor->status.wpc = enable; - } - return ret; -} - -//Gamma enable -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x20, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set raw_gma to: %d", enable); - sensor->status.raw_gma = enable; - } - return ret; -} - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x80, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set lenc to: %d", enable); - sensor->status.lenc = enable; - } - return ret; -} - -static int get_agc_gain(sensor_t *sensor) -{ - int ra = read_reg(sensor->slv_addr, 0x350a); - if (ra < 0) { - return 0; - } - int rb = read_reg(sensor->slv_addr, 0x350b); - if (rb < 0) { - return 0; - } - int res = (rb & 0xF0) >> 4 | (ra & 0x03) << 4; - if (rb & 0x0F) { - res += 1; - } - return res; -} - -//real gain -static int set_agc_gain(sensor_t *sensor, int gain) -{ - int ret = 0; - if(gain < 0) { - gain = 0; - } else if(gain > 64) { - gain = 64; - } - - //gain value is 6.4 bits float - //in order to use the max range, we deduct 1/16 - int gainv = gain << 4; - if(gainv){ - gainv -= 1; - } - - ret = write_reg(sensor->slv_addr, 0x350a, gainv >> 8) || write_reg(sensor->slv_addr, 0x350b, gainv & 0xff); - if (ret == 0) { - ESP_LOGD(TAG, "Set agc_gain to: %d", gain); - sensor->status.agc_gain = gain; - } - return ret; -} - -static int get_aec_value(sensor_t *sensor) -{ - int ra = read_reg(sensor->slv_addr, 0x3500); - if (ra < 0) { - return 0; - } - int rb = read_reg(sensor->slv_addr, 0x3501); - if (rb < 0) { - return 0; - } - int rc = read_reg(sensor->slv_addr, 0x3502); - if (rc < 0) { - return 0; - } - int res = (ra & 0x0F) << 12 | (rb & 0xFF) << 4 | (rc & 0xF0) >> 4; - return res; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - int ret = 0, max_val = 0; - max_val = read_reg16(sensor->slv_addr, 0x380e); - if (max_val < 0) { - ESP_LOGE(TAG, "Could not read max aec_value"); - return -1; - } - if (value > max_val) { - value =max_val; - } - - ret = write_reg(sensor->slv_addr, 0x3500, (value >> 12) & 0x0F) - || write_reg(sensor->slv_addr, 0x3501, (value >> 4) & 0xFF) - || write_reg(sensor->slv_addr, 0x3502, (value << 4) & 0xF0); - - if (ret == 0) { - ESP_LOGD(TAG, "Set aec_value to: %d / %d", value, max_val); - sensor->status.aec_value = value; - } - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level) -{ - int ret = 0; - if (level < -5 || level > 5) { - return -1; - } - //good targets are between 5 and 115 - int target_level = ((level + 5) * 10) + 5; - - int level_high, level_low; - int fast_high, fast_low; - - level_low = target_level * 23 / 25; //0.92 (0.46) - level_high = target_level * 27 / 25; //1.08 (2.08) - - fast_low = level_low >> 1; - fast_high = level_high << 1; - - if(fast_high>255) { - fast_high = 255; - } - - ret = write_reg(sensor->slv_addr, 0x3a0f, level_high) - || write_reg(sensor->slv_addr, 0x3a10, level_low) - || write_reg(sensor->slv_addr, 0x3a1b, level_high) - || write_reg(sensor->slv_addr, 0x3a1e, level_low) - || write_reg(sensor->slv_addr, 0x3a11, fast_high) - || write_reg(sensor->slv_addr, 0x3a1f, fast_low); - - if (ret == 0) { - ESP_LOGD(TAG, "Set ae_level to: %d", level); - sensor->status.ae_level = level; - } - return ret; -} - -static int set_wb_mode(sensor_t *sensor, int mode) -{ - int ret = 0; - if (mode < 0 || mode > 4) { - return -1; - } - - ret = write_reg(sensor->slv_addr, 0x3406, (mode != 0)); - if (ret) { - return ret; - } - switch (mode) { - case 1://Sunny - ret = write_reg16(sensor->slv_addr, 0x3400, 0x5e0) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x540);//AWB B GAIN - break; - case 2://Cloudy - ret = write_reg16(sensor->slv_addr, 0x3400, 0x650) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x4f0);//AWB B GAIN - break; - case 3://Office - ret = write_reg16(sensor->slv_addr, 0x3400, 0x520) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x660);//AWB B GAIN - break; - case 4://HOME - ret = write_reg16(sensor->slv_addr, 0x3400, 0x420) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x3f0) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x710);//AWB B GAIN - break; - default://AUTO - break; - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set wb_mode to: %d", mode); - sensor->status.wb_mode = mode; - } - return ret; -} - -static int set_awb_gain_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - int old_mode = sensor->status.wb_mode; - int mode = enable?old_mode:0; - - ret = set_wb_mode(sensor, mode); - - if (ret == 0) { - sensor->status.wb_mode = old_mode; - ESP_LOGD(TAG, "Set awb_gain to: %d", enable); - sensor->status.awb_gain = enable; - } - return ret; -} - -static int set_special_effect(sensor_t *sensor, int effect) -{ - int ret=0; - if (effect < 0 || effect > 6) { - return -1; - } - - uint8_t * regs = (uint8_t *)sensor_special_effects[effect]; - ret = write_reg(sensor->slv_addr, 0x5580, regs[0]) - || write_reg(sensor->slv_addr, 0x5583, regs[1]) - || write_reg(sensor->slv_addr, 0x5584, regs[2]) - || write_reg(sensor->slv_addr, 0x5003, regs[3]); - - if (ret == 0) { - ESP_LOGD(TAG, "Set special_effect to: %d", effect); - sensor->status.special_effect = effect; - } - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret = 0; - uint8_t value = 0; - bool negative = false; - - switch (level) { - case 3: - value = 0x30; - break; - case 2: - value = 0x20; - break; - case 1: - value = 0x10; - break; - case -1: - value = 0x10; - negative = true; - break; - case -2: - value = 0x20; - negative = true; - break; - case -3: - value = 0x30; - negative = true; - break; - default: // 0 - break; - } - - ret = write_reg(sensor->slv_addr, 0x5587, value); - if (ret == 0) { - ret = write_reg_bits(sensor->slv_addr, 0x5588, 0x08, negative); - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set brightness to: %d", level); - sensor->status.brightness = level; - } - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 3 || level < -3) { - return -1; - } - ret = write_reg(sensor->slv_addr, 0x5586, (level + 4) << 3); - - if (ret == 0) { - ESP_LOGD(TAG, "Set contrast to: %d", level); - sensor->status.contrast = level; - } - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 4 || level < -4) { - return -1; - } - - uint8_t * regs = (uint8_t *)sensor_saturation_levels[level+4]; - for(int i=0; i<11; i++) { - ret = write_reg(sensor->slv_addr, 0x5381 + i, regs[i]); - if (ret) { - break; - } - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set saturation to: %d", level); - sensor->status.saturation = level; - } - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 3 || level < -3) { - return -1; - } - - uint8_t mt_offset_2 = (level + 3) * 8; - uint8_t mt_offset_1 = mt_offset_2 + 1; - - ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto - || write_reg(sensor->slv_addr, 0x5300, 0x10) - || write_reg(sensor->slv_addr, 0x5301, 0x10) - || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) - || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) - || write_reg(sensor->slv_addr, 0x5309, 0x10) - || write_reg(sensor->slv_addr, 0x530a, 0x10) - || write_reg(sensor->slv_addr, 0x530b, 0x04) - || write_reg(sensor->slv_addr, 0x530c, 0x06); - - if (ret == 0) { - ESP_LOGD(TAG, "Set sharpness to: %d", level); - sensor->status.sharpness = level; - } - return ret; -} - -static int set_gainceiling(sensor_t *sensor, gainceiling_t level) -{ - int ret = 0, l = (int)level; - - ret = write_reg(sensor->slv_addr, 0x3A18, (l >> 8) & 3) - || write_reg(sensor->slv_addr, 0x3A19, l & 0xFF); - - if (ret == 0) { - ESP_LOGD(TAG, "Set gainceiling to: %d", l); - sensor->status.gainceiling = l; - } - return ret; -} - -static int get_denoise(sensor_t *sensor) -{ - if (!check_reg_mask(sensor->slv_addr, 0x5308, 0x10)) { - return 0; - } - return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; -} - -static int set_denoise(sensor_t *sensor, int level) -{ - int ret = 0; - if (level < 0 || level > 8) { - return -1; - } - - ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x10, level > 0); - if (ret == 0 && level > 0) { - ret = write_reg(sensor->slv_addr, 0x5306, (level - 1) * 4); - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set denoise to: %d", level); - sensor->status.denoise = level; - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0, ret2 = 0; - if(mask > 0xFF){ - ret = read_reg16(sensor->slv_addr, reg); - if(ret >= 0 && mask > 0xFFFF){ - ret2 = read_reg(sensor->slv_addr, reg+2); - if(ret2 >= 0){ - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0, ret2 = 0; - if(mask > 0xFF){ - ret = read_reg16(sensor->slv_addr, reg); - if(ret >= 0 && mask > 0xFFFF){ - ret2 = read_reg(sensor->slv_addr, reg+2); - if(ret2 >= 0){ - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - if(mask > 0xFFFF){ - ret = write_reg16(sensor->slv_addr, reg, value >> 8); - if(ret >= 0){ - ret = write_reg(sensor->slv_addr, reg+2, value & 0xFF); - } - } else if(mask > 0xFF){ - ret = write_reg16(sensor->slv_addr, reg, value); - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) -{ - int ret = 0; - ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) - || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) - || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) - || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY) - || write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, scale); - if(!ret){ - sensor->status.scale = scale; - sensor->status.binning = binning; - ret = set_image_options(sensor); - } - return ret; -} - -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) -{ - return set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); -} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x5303) / 8) - 3; - sensor->status.denoise = get_denoise(sensor); - sensor->status.ae_level = 0; - sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x3A18) & 0x3FF; - sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x01); - sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); - sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); - sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); - sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); - sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); - sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); - sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); - sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); - sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3406, 0x01); - sensor->status.agc_gain = get_agc_gain(sensor); - sensor->status.aec_value = get_aec_value(sensor); - sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3a00, 0x04); - return 0; -} - -int ov3660_detect(int slv_addr, sensor_id_t *id) -{ - if (OV3660_SCCB_ADDR == slv_addr) { - uint8_t h = SCCB_Read16(slv_addr, 0x300A); - uint8_t l = SCCB_Read16(slv_addr, 0x300B); - uint16_t PID = (h<<8) | l; - if (OV3660_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int ov3660_init(sensor_t *sensor) -{ - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_contrast; - sensor->set_brightness = set_brightness; - sensor->set_saturation = set_saturation; - sensor->set_sharpness = set_sharpness; - sensor->set_gainceiling = set_gainceiling; - sensor->set_quality = set_quality; - sensor->set_colorbar = set_colorbar; - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_whitebal = set_whitebal; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->init_status = init_status; - sensor->set_aec2 = set_aec2; - sensor->set_aec_value = set_aec_value; - sensor->set_special_effect = set_special_effect; - sensor->set_wb_mode = set_wb_mode; - sensor->set_ae_level = set_ae_level; - sensor->set_dcw = set_dcw_dsp; - sensor->set_bpc = set_bpc_dsp; - sensor->set_wpc = set_wpc_dsp; - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - sensor->set_denoise = set_denoise; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c deleted file mode 100644 index a32b374f54..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov5640.c +++ /dev/null @@ -1,1130 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV3660 driver. - * - */ -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "ov5640.h" -#include "ov5640_regs.h" -#include "ov5640_settings.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char *TAG = "ov5640"; -#endif - -//#define REG_DEBUG_ON - -static int read_reg(uint8_t slv_addr, const uint16_t reg){ - int ret = SCCB_Read16(slv_addr, reg); -#ifdef REG_DEBUG_ON - if (ret < 0) { - ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask){ - return (read_reg(slv_addr, reg) & mask) == mask; -} - -static int read_reg16(uint8_t slv_addr, const uint16_t reg){ - int ret = 0, ret2 = 0; - ret = read_reg(slv_addr, reg); - if (ret >= 0) { - ret = (ret & 0xFF) << 8; - ret2 = read_reg(slv_addr, reg+1); - if (ret2 < 0) { - ret = ret2; - } else { - ret |= ret2 & 0xFF; - } - } - return ret; -} - -//static void dump_reg(sensor_t *sensor, const uint16_t reg){ -// int v = SCCB_Read16(sensor->slv_addr, reg); -// if(v < 0){ -// ets_printf(" 0x%04x: FAIL[%d]\n", reg, v); -// } else { -// ets_printf(" 0x%04x: 0x%02X\n", reg, v); -// } -//} -// -//static void dump_range(sensor_t *sensor, const char * name, const uint16_t start_reg, const uint16_t end_reg){ -// ets_printf("%s: 0x%04x - 0x%04X\n", name, start_reg, end_reg); -// for(uint16_t reg = start_reg; reg <= end_reg; reg++){ -// dump_reg(sensor, reg); -// } -//} -// -//static void dump_regs(sensor_t *sensor){ -//// dump_range(sensor, "All Regs", 0x3000, 0x6100); -//// dump_range(sensor, "system and IO pad control", 0x3000, 0x3052); -//// dump_range(sensor, "SCCB control", 0x3100, 0x3108); -//// dump_range(sensor, "SRB control", 0x3200, 0x3211); -//// dump_range(sensor, "AWB gain control", 0x3400, 0x3406); -//// dump_range(sensor, "AEC/AGC control", 0x3500, 0x350D); -//// dump_range(sensor, "VCM control", 0x3600, 0x3606); -//// dump_range(sensor, "timing control", 0x3800, 0x3821); -//// dump_range(sensor, "AEC/AGC power down domain control", 0x3A00, 0x3A25); -//// dump_range(sensor, "strobe control", 0x3B00, 0x3B0C); -//// dump_range(sensor, "50/60Hz detector control", 0x3C00, 0x3C1E); -//// dump_range(sensor, "OTP control", 0x3D00, 0x3D21); -//// dump_range(sensor, "MC control", 0x3F00, 0x3F0D); -//// dump_range(sensor, "BLC control", 0x4000, 0x4033); -//// dump_range(sensor, "frame control", 0x4201, 0x4202); -//// dump_range(sensor, "format control", 0x4300, 0x430D); -//// dump_range(sensor, "JPEG control", 0x4400, 0x4431); -//// dump_range(sensor, "VFIFO control", 0x4600, 0x460D); -//// dump_range(sensor, "DVP control", 0x4709, 0x4745); -//// dump_range(sensor, "MIPI control", 0x4800, 0x4837); -//// dump_range(sensor, "ISP frame control", 0x4901, 0x4902); -//// dump_range(sensor, "ISP top control", 0x5000, 0x5063); -//// dump_range(sensor, "AWB control", 0x5180, 0x51D0); -//// dump_range(sensor, "CIP control", 0x5300, 0x530F); -//// dump_range(sensor, "CMX control", 0x5380, 0x538B); -//// dump_range(sensor, "gamma control", 0x5480, 0x5490); -//// dump_range(sensor, "SDE control", 0x5580, 0x558C); -//// dump_range(sensor, "scale control", 0x5600, 0x5606); -//// dump_range(sensor, "AVG control", 0x5680, 0x56A2); -//// dump_range(sensor, "LENC control", 0x5800, 0x5849); -//// dump_range(sensor, "AFC control", 0x6000, 0x603F); -//} - -static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value){ - int ret = 0; -#ifndef REG_DEBUG_ON - ret = SCCB_Write16(slv_addr, reg, value); -#else - int old_value = read_reg(slv_addr, reg); - if (old_value < 0) { - return old_value; - } - if ((uint8_t)old_value != value) { - ESP_LOGI(TAG, "NEW REG 0x%04x: 0x%02x to 0x%02x", reg, (uint8_t)old_value, value); - ret = SCCB_Write16(slv_addr, reg, value); - } else { - ESP_LOGD(TAG, "OLD REG 0x%04x: 0x%02x", reg, (uint8_t)old_value); - ret = SCCB_Write16(slv_addr, reg, value);//maybe not? - } - if (ret < 0) { - ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret); - } -#endif - return ret; -} - -static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t mask, uint8_t value) -{ - int ret = 0; - uint8_t c_value, new_value; - ret = read_reg(slv_addr, reg); - if(ret < 0) { - return ret; - } - c_value = ret; - new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset); - ret = write_reg(slv_addr, reg, new_value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2]) -{ - int i = 0, ret = 0; - while (!ret && regs[i][0] != REGLIST_TAIL) { - if (regs[i][0] == REG_DLY) { - vTaskDelay(regs[i][1] / portTICK_PERIOD_MS); - } else { - ret = write_reg(slv_addr, regs[i][0], regs[i][1]); - } - i++; - } - return ret; -} - -static int write_reg16(uint8_t slv_addr, const uint16_t reg, uint16_t value) -{ - if (write_reg(slv_addr, reg, value >> 8) || write_reg(slv_addr, reg + 1, value)) { - return -1; - } - return 0; -} - -static int write_addr_reg(uint8_t slv_addr, const uint16_t reg, uint16_t x_value, uint16_t y_value) -{ - if (write_reg16(slv_addr, reg, x_value) || write_reg16(slv_addr, reg + 2, y_value)) { - return -1; - } - return 0; -} - -#define write_reg_bits(slv_addr, reg, mask, enable) set_reg_bits(slv_addr, reg, 0, mask, (enable)?(mask):0) - -static int calc_sysclk(int xclk, bool pll_bypass, int pll_multiplier, int pll_sys_div, int pre_div, bool root_2x, int pclk_root_div, bool pclk_manual, int pclk_div) -{ - const float pll_pre_div2x_map[] = { 1, 1, 2, 3, 4, 1.5, 6, 2.5, 8}; - const int pll_pclk_root_div_map[] = { 1, 2, 4, 8 }; - - if(!pll_sys_div) { - pll_sys_div = 1; - } - - float pll_pre_div = pll_pre_div2x_map[pre_div]; - unsigned int root_2x_div = root_2x?2:1; - unsigned int pll_pclk_root_div = pll_pclk_root_div_map[pclk_root_div]; - - unsigned int REFIN = xclk / pll_pre_div; - - unsigned int VCO = REFIN * pll_multiplier / root_2x_div; - - unsigned int PLL_CLK = pll_bypass?(xclk):(VCO / pll_sys_div * 2 / 5);//5 here is 10bit mode / 2, for 8bit it should be 4 (reg 0x3034) - - unsigned int PCLK = PLL_CLK / pll_pclk_root_div / ((pclk_manual && pclk_div)?pclk_div:2); - - unsigned int SYSCLK = PLL_CLK / 4; - - ESP_LOGI(TAG, "Calculated XVCLK: %d Hz, REFIN: %u Hz, VCO: %u Hz, PLL_CLK: %u Hz, SYSCLK: %u Hz, PCLK: %u Hz", xclk, REFIN, VCO, PLL_CLK, SYSCLK, PCLK); - return SYSCLK; -} - -static int set_pll(sensor_t *sensor, bool bypass, uint8_t multiplier, uint8_t sys_div, uint8_t pre_div, bool root_2x, uint8_t pclk_root_div, bool pclk_manual, uint8_t pclk_div){ - int ret = 0; - if(multiplier > 252 || multiplier < 4 || sys_div > 15 || pre_div > 8 || pclk_div > 31 || pclk_root_div > 3){ - ESP_LOGE(TAG, "Invalid arguments"); - return -1; - } - if(multiplier > 127){ - multiplier &= 0xFE;//only even integers above 127 - } - ESP_LOGI(TAG, "Set PLL: bypass: %u, multiplier: %u, sys_div: %u, pre_div: %u, root_2x: %u, pclk_root_div: %u, pclk_manual: %u, pclk_div: %u", bypass, multiplier, sys_div, pre_div, root_2x, pclk_root_div, pclk_manual, pclk_div); - - calc_sysclk(sensor->xclk_freq_hz, bypass, multiplier, sys_div, pre_div, root_2x, pclk_root_div, pclk_manual, pclk_div); - - ret = write_reg(sensor->slv_addr, 0x3039, bypass?0x80:0x00); - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3034, 0x1A);//10bit mode - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3035, 0x01 | ((sys_div & 0x0f) << 4)); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3036, multiplier & 0xff); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3037, (pre_div & 0xf) | (root_2x?0x10:0x00)); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3108, (pclk_root_div & 0x3) << 4 | 0x06); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3824, pclk_div & 0x1f); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x460C, pclk_manual?0x22:0x20); - } - if (ret == 0) { - ret = write_reg(sensor->slv_addr, 0x3103, 0x13);// system clock from pll, bit[1] - } - if(ret){ - ESP_LOGE(TAG, "set_sensor_pll FAILED!"); - } - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level); - -static int reset(sensor_t *sensor) -{ - //dump_regs(sensor); - vTaskDelay(100 / portTICK_PERIOD_MS); - int ret = 0; - // Software Reset: clear all registers and reset them to their default values - ret = write_reg(sensor->slv_addr, SYSTEM_CTROL0, 0x82); - if(ret){ - ESP_LOGE(TAG, "Software Reset FAILED!"); - return ret; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - ret = write_regs(sensor->slv_addr, sensor_default_regs); - if (ret == 0) { - ESP_LOGD(TAG, "Camera defaults loaded"); - vTaskDelay(100 / portTICK_PERIOD_MS); - //write_regs(sensor->slv_addr, sensor_regs_awb0); - //write_regs(sensor->slv_addr, sensor_regs_gamma1); - } - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret = 0; - const uint16_t (*regs)[2]; - - switch (pixformat) { - case PIXFORMAT_YUV422: - regs = sensor_fmt_yuv422; - break; - - case PIXFORMAT_GRAYSCALE: - regs = sensor_fmt_grayscale; - break; - - case PIXFORMAT_RGB565: - case PIXFORMAT_RGB888: - regs = sensor_fmt_rgb565; - break; - - case PIXFORMAT_JPEG: - regs = sensor_fmt_jpeg; - break; - - case PIXFORMAT_RAW: - regs = sensor_fmt_raw; - break; - - default: - ESP_LOGE(TAG, "Unsupported pixformat: %u", pixformat); - return -1; - } - - ret = write_regs(sensor->slv_addr, regs); - if(ret == 0) { - sensor->pixformat = pixformat; - ESP_LOGD(TAG, "Set pixformat to: %u", pixformat); - } - return ret; -} - -static int set_image_options(sensor_t *sensor) -{ - int ret = 0; - uint8_t reg20 = 0; - uint8_t reg21 = 0; - uint8_t reg4514 = 0; - uint8_t reg4514_test = 0; - - // compression - if (sensor->pixformat == PIXFORMAT_JPEG) { - reg21 |= 0x20; - } - - // binning - if (!sensor->status.binning) { - reg20 |= 0x40; - } else { - reg20 |= 0x01; - reg21 |= 0x01; - reg4514_test |= 4; - } - - // V-Flip - if (sensor->status.vflip) { - reg20 |= 0x06; - reg4514_test |= 1; - } - - // H-Mirror - if (sensor->status.hmirror) { - reg21 |= 0x06; - reg4514_test |= 2; - } - - switch (reg4514_test) { - //no binning - case 0: reg4514 = 0x88; break;//normal - case 1: reg4514 = 0x00; break;//v-flip - case 2: reg4514 = 0xbb; break;//h-mirror - case 3: reg4514 = 0x00; break;//v-flip+h-mirror - //binning - case 4: reg4514 = 0xaa; break;//normal - case 5: reg4514 = 0xbb; break;//v-flip - case 6: reg4514 = 0xbb; break;//h-mirror - case 7: reg4514 = 0xaa; break;//v-flip+h-mirror - } - - if(write_reg(sensor->slv_addr, TIMING_TC_REG20, reg20) - || write_reg(sensor->slv_addr, TIMING_TC_REG21, reg21) - || write_reg(sensor->slv_addr, 0x4514, reg4514)){ - ESP_LOGE(TAG, "Setting Image Options Failed"); - return -1; - } - - if (!sensor->status.binning) { - ret = write_reg(sensor->slv_addr, 0x4520, 0x10) - || write_reg(sensor->slv_addr, X_INCREMENT, 0x11)//odd:1, even: 1 - || write_reg(sensor->slv_addr, Y_INCREMENT, 0x11);//odd:1, even: 1 - } else { - ret = write_reg(sensor->slv_addr, 0x4520, 0x0b) - || write_reg(sensor->slv_addr, X_INCREMENT, 0x31)//odd:3, even: 1 - || write_reg(sensor->slv_addr, Y_INCREMENT, 0x31);//odd:3, even: 1 - } - - ESP_LOGD(TAG, "Set Image Options: Compression: %u, Binning: %u, V-Flip: %u, H-Mirror: %u, Reg-4514: 0x%02x", - sensor->pixformat == PIXFORMAT_JPEG, sensor->status.binning, sensor->status.vflip, sensor->status.hmirror, reg4514); - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret = 0; - framesize_t old_framesize = sensor->status.framesize; - sensor->status.framesize = framesize; - - if(framesize > FRAMESIZE_QSXGA){ - ESP_LOGE(TAG, "Invalid framesize: %u", framesize); - return -1; - } - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - aspect_ratio_t ratio = resolution[framesize].aspect_ratio; - ratio_settings_t settings = ratio_table[ratio]; - - sensor->status.binning = (w <= (settings.max_width / 2) && h <= (settings.max_height / 2)); - sensor->status.scale = !((w == settings.max_width && h == settings.max_height) - || (w == (settings.max_width / 2) && h == (settings.max_height / 2))); - - ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, settings.start_x, settings.start_y) - || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, settings.end_x, settings.end_y) - || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, w, h); - - if (ret) { - goto fail; - } - - if (!sensor->status.binning) { - ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x, settings.total_y) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, settings.offset_x, settings.offset_y); - } else { - if (w > 920) { - ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, settings.total_x - 200, settings.total_y / 2); - } else { - ret = write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, 2060, settings.total_y / 2); - } - if (ret == 0) { - ret = write_addr_reg(sensor->slv_addr, X_OFFSET_H, settings.offset_x / 2, settings.offset_y / 2); - } - } - - if (ret == 0) { - ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, sensor->status.scale); - } - - if (ret == 0) { - ret = set_image_options(sensor); - } - - if (ret) { - goto fail; - } - - if (sensor->pixformat == PIXFORMAT_JPEG) { - //10MHz PCLK - uint8_t sys_mul = 200; - if(framesize < FRAMESIZE_QVGA || sensor->xclk_freq_hz == 16000000){ - sys_mul = 160; - } else if(framesize < FRAMESIZE_XGA){ - sys_mul = 180; - } - ret = set_pll(sensor, false, sys_mul, 4, 2, false, 2, true, 4); - //Set PLL: bypass: 0, multiplier: sys_mul, sys_div: 4, pre_div: 2, root_2x: 0, pclk_root_div: 2, pclk_manual: 1, pclk_div: 4 - } else { - //ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4); - if (framesize > FRAMESIZE_HVGA) { - ret = set_pll(sensor, false, 10, 1, 2, false, 1, true, 2); - } else if (framesize >= FRAMESIZE_QVGA) { - ret = set_pll(sensor, false, 8, 1, 1, false, 1, true, 4); - } else { - ret = set_pll(sensor, false, 20, 1, 1, false, 1, true, 8); - } - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set framesize to: %ux%u", w, h); - } - return ret; - -fail: - sensor->status.framesize = old_framesize; - ESP_LOGE(TAG, "Setting framesize to: %ux%u failed", w, h); - return ret; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.hmirror = enable; - ret = set_image_options(sensor); - if (ret == 0) { - ESP_LOGD(TAG, "Set h-mirror to: %d", enable); - } - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - sensor->status.vflip = enable; - ret = set_image_options(sensor); - if (ret == 0) { - ESP_LOGD(TAG, "Set v-flip to: %d", enable); - } - return ret; -} - -static int set_quality(sensor_t *sensor, int qs) -{ - int ret = 0; - ret = write_reg(sensor->slv_addr, COMPRESSION_CTRL07, qs & 0x3f); - if (ret == 0) { - sensor->status.quality = qs; - ESP_LOGD(TAG, "Set quality to: %d", qs); - } - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR, enable); - if (ret == 0) { - sensor->status.colorbar = enable; - ESP_LOGD(TAG, "Set colorbar to: %d", enable); - } - return ret; -} - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set gain_ctrl to: %d", enable); - sensor->status.agc = enable; - } - return ret; -} - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set exposure_ctrl to: %d", enable); - sensor->status.aec = enable; - } - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x01, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set awb to: %d", enable); - sensor->status.awb = enable; - } - return ret; -} - -//Advanced AWB -static int set_dcw_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5183, 0x80, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set dcw to: %d", enable); - sensor->status.dcw = enable; - } - return ret; -} - -//night mode enable -static int set_aec2(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x3a00, 0x04, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set aec2 to: %d", enable); - sensor->status.aec2 = enable; - } - return ret; -} - -static int set_bpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x04, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set bpc to: %d", enable); - sensor->status.bpc = enable; - } - return ret; -} - -static int set_wpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x02, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set wpc to: %d", enable); - sensor->status.wpc = enable; - } - return ret; -} - -//Gamma enable -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x20, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set raw_gma to: %d", enable); - sensor->status.raw_gma = enable; - } - return ret; -} - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = write_reg_bits(sensor->slv_addr, 0x5000, 0x80, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set lenc to: %d", enable); - sensor->status.lenc = enable; - } - return ret; -} - -static int get_agc_gain(sensor_t *sensor) -{ - int ra = read_reg(sensor->slv_addr, 0x350a); - if (ra < 0) { - return 0; - } - int rb = read_reg(sensor->slv_addr, 0x350b); - if (rb < 0) { - return 0; - } - int res = (rb & 0xF0) >> 4 | (ra & 0x03) << 4; - if (rb & 0x0F) { - res += 1; - } - return res; -} - -//real gain -static int set_agc_gain(sensor_t *sensor, int gain) -{ - int ret = 0; - if(gain < 0) { - gain = 0; - } else if(gain > 64) { - gain = 64; - } - - //gain value is 6.4 bits float - //in order to use the max range, we deduct 1/16 - int gainv = gain << 4; - if(gainv){ - gainv -= 1; - } - - ret = write_reg(sensor->slv_addr, 0x350a, gainv >> 8) || write_reg(sensor->slv_addr, 0x350b, gainv & 0xff); - if (ret == 0) { - ESP_LOGD(TAG, "Set agc_gain to: %d", gain); - sensor->status.agc_gain = gain; - } - return ret; -} - -static int get_aec_value(sensor_t *sensor) -{ - int ra = read_reg(sensor->slv_addr, 0x3500); - if (ra < 0) { - return 0; - } - int rb = read_reg(sensor->slv_addr, 0x3501); - if (rb < 0) { - return 0; - } - int rc = read_reg(sensor->slv_addr, 0x3502); - if (rc < 0) { - return 0; - } - int res = (ra & 0x0F) << 12 | (rb & 0xFF) << 4 | (rc & 0xF0) >> 4; - return res; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - int ret = 0, max_val = 0; - max_val = read_reg16(sensor->slv_addr, 0x380e); - if (max_val < 0) { - ESP_LOGE(TAG, "Could not read max aec_value"); - return -1; - } - if (value > max_val) { - value =max_val; - } - - ret = write_reg(sensor->slv_addr, 0x3500, (value >> 12) & 0x0F) - || write_reg(sensor->slv_addr, 0x3501, (value >> 4) & 0xFF) - || write_reg(sensor->slv_addr, 0x3502, (value << 4) & 0xF0); - - if (ret == 0) { - ESP_LOGD(TAG, "Set aec_value to: %d / %d", value, max_val); - sensor->status.aec_value = value; - } - return ret; -} - -static int set_ae_level(sensor_t *sensor, int level) -{ - int ret = 0; - if (level < -5 || level > 5) { - return -1; - } - //good targets are between 5 and 115 - int target_level = ((level + 5) * 10) + 5; - - int level_high, level_low; - int fast_high, fast_low; - - level_low = target_level * 23 / 25; //0.92 (0.46) - level_high = target_level * 27 / 25; //1.08 (2.08) - - fast_low = level_low >> 1; - fast_high = level_high << 1; - - if(fast_high>255) { - fast_high = 255; - } - - ret = write_reg(sensor->slv_addr, 0x3a0f, level_high) - || write_reg(sensor->slv_addr, 0x3a10, level_low) - || write_reg(sensor->slv_addr, 0x3a1b, level_high) - || write_reg(sensor->slv_addr, 0x3a1e, level_low) - || write_reg(sensor->slv_addr, 0x3a11, fast_high) - || write_reg(sensor->slv_addr, 0x3a1f, fast_low); - - if (ret == 0) { - ESP_LOGD(TAG, "Set ae_level to: %d", level); - sensor->status.ae_level = level; - } - return ret; -} - -static int set_wb_mode(sensor_t *sensor, int mode) -{ - int ret = 0; - if (mode < 0 || mode > 4) { - return -1; - } - - ret = write_reg(sensor->slv_addr, 0x3406, (mode != 0)); - if (ret) { - return ret; - } - switch (mode) { - case 1://Sunny - ret = write_reg16(sensor->slv_addr, 0x3400, 0x5e0) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x540);//AWB B GAIN - break; - case 2://Cloudy - ret = write_reg16(sensor->slv_addr, 0x3400, 0x650) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x4f0);//AWB B GAIN - break; - case 3://Office - ret = write_reg16(sensor->slv_addr, 0x3400, 0x520) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x410) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x660);//AWB B GAIN - break; - case 4://HOME - ret = write_reg16(sensor->slv_addr, 0x3400, 0x420) //AWB R GAIN - || write_reg16(sensor->slv_addr, 0x3402, 0x3f0) //AWB G GAIN - || write_reg16(sensor->slv_addr, 0x3404, 0x710);//AWB B GAIN - break; - default://AUTO - break; - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set wb_mode to: %d", mode); - sensor->status.wb_mode = mode; - } - return ret; -} - -static int set_awb_gain_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - int old_mode = sensor->status.wb_mode; - int mode = enable?old_mode:0; - - ret = set_wb_mode(sensor, mode); - - if (ret == 0) { - sensor->status.wb_mode = old_mode; - ESP_LOGD(TAG, "Set awb_gain to: %d", enable); - sensor->status.awb_gain = enable; - } - return ret; -} - -static int set_special_effect(sensor_t *sensor, int effect) -{ - int ret=0; - if (effect < 0 || effect > 6) { - return -1; - } - - uint8_t * regs = (uint8_t *)sensor_special_effects[effect]; - ret = write_reg(sensor->slv_addr, 0x5580, regs[0]) - || write_reg(sensor->slv_addr, 0x5583, regs[1]) - || write_reg(sensor->slv_addr, 0x5584, regs[2]) - || write_reg(sensor->slv_addr, 0x5003, regs[3]); - - if (ret == 0) { - ESP_LOGD(TAG, "Set special_effect to: %d", effect); - sensor->status.special_effect = effect; - } - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret = 0; - uint8_t value = 0; - bool negative = false; - - switch (level) { - case 3: - value = 0x30; - break; - case 2: - value = 0x20; - break; - case 1: - value = 0x10; - break; - case -1: - value = 0x10; - negative = true; - break; - case -2: - value = 0x20; - negative = true; - break; - case -3: - value = 0x30; - negative = true; - break; - default: // 0 - break; - } - - ret = write_reg(sensor->slv_addr, 0x5587, value); - if (ret == 0) { - ret = write_reg_bits(sensor->slv_addr, 0x5588, 0x08, negative); - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set brightness to: %d", level); - sensor->status.brightness = level; - } - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 3 || level < -3) { - return -1; - } - ret = write_reg(sensor->slv_addr, 0x5586, (level + 4) << 3); - - if (ret == 0) { - ESP_LOGD(TAG, "Set contrast to: %d", level); - sensor->status.contrast = level; - } - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 4 || level < -4) { - return -1; - } - - uint8_t * regs = (uint8_t *)sensor_saturation_levels[level+4]; - for(int i=0; i<11; i++) { - ret = write_reg(sensor->slv_addr, 0x5381 + i, regs[i]); - if (ret) { - break; - } - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set saturation to: %d", level); - sensor->status.saturation = level; - } - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - if(level > 3 || level < -3) { - return -1; - } - - uint8_t mt_offset_2 = (level + 3) * 8; - uint8_t mt_offset_1 = mt_offset_2 + 1; - - ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x40, false)//0x40 means auto - || write_reg(sensor->slv_addr, 0x5300, 0x10) - || write_reg(sensor->slv_addr, 0x5301, 0x10) - || write_reg(sensor->slv_addr, 0x5302, mt_offset_1) - || write_reg(sensor->slv_addr, 0x5303, mt_offset_2) - || write_reg(sensor->slv_addr, 0x5309, 0x10) - || write_reg(sensor->slv_addr, 0x530a, 0x10) - || write_reg(sensor->slv_addr, 0x530b, 0x04) - || write_reg(sensor->slv_addr, 0x530c, 0x06); - - if (ret == 0) { - ESP_LOGD(TAG, "Set sharpness to: %d", level); - sensor->status.sharpness = level; - } - return ret; -} - -static int set_gainceiling(sensor_t *sensor, gainceiling_t level) -{ - int ret = 0, l = (int)level; - - ret = write_reg(sensor->slv_addr, 0x3A18, (l >> 8) & 3) - || write_reg(sensor->slv_addr, 0x3A19, l & 0xFF); - - if (ret == 0) { - ESP_LOGD(TAG, "Set gainceiling to: %d", l); - sensor->status.gainceiling = l; - } - return ret; -} - -static int get_denoise(sensor_t *sensor) -{ - if (!check_reg_mask(sensor->slv_addr, 0x5308, 0x10)) { - return 0; - } - return (read_reg(sensor->slv_addr, 0x5306) / 4) + 1; -} - -static int set_denoise(sensor_t *sensor, int level) -{ - int ret = 0; - if (level < 0 || level > 8) { - return -1; - } - - ret = write_reg_bits(sensor->slv_addr, 0x5308, 0x10, level > 0); - if (ret == 0 && level > 0) { - ret = write_reg(sensor->slv_addr, 0x5306, (level - 1) * 4); - } - - if (ret == 0) { - ESP_LOGD(TAG, "Set denoise to: %d", level); - sensor->status.denoise = level; - } - return ret; -} - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0, ret2 = 0; - if(mask > 0xFF){ - ret = read_reg16(sensor->slv_addr, reg); - if(ret >= 0 && mask > 0xFFFF){ - ret2 = read_reg(sensor->slv_addr, reg+2); - if(ret2 >= 0){ - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0, ret2 = 0; - if(mask > 0xFF){ - ret = read_reg16(sensor->slv_addr, reg); - if(ret >= 0 && mask > 0xFFFF){ - ret2 = read_reg(sensor->slv_addr, reg+2); - if(ret2 >= 0){ - ret = (ret << 8) | ret2 ; - } else { - ret = ret2; - } - } - } else { - ret = read_reg(sensor->slv_addr, reg); - } - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - if(mask > 0xFFFF){ - ret = write_reg16(sensor->slv_addr, reg, value >> 8); - if(ret >= 0){ - ret = write_reg(sensor->slv_addr, reg+2, value & 0xFF); - } - } else if(mask > 0xFF){ - ret = write_reg16(sensor->slv_addr, reg, value); - } else { - ret = write_reg(sensor->slv_addr, reg, value); - } - return ret; -} - -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning) -{ - int ret = 0; - ret = write_addr_reg(sensor->slv_addr, X_ADDR_ST_H, startX, startY) - || write_addr_reg(sensor->slv_addr, X_ADDR_END_H, endX, endY) - || write_addr_reg(sensor->slv_addr, X_OFFSET_H, offsetX, offsetY) - || write_addr_reg(sensor->slv_addr, X_TOTAL_SIZE_H, totalX, totalY) - || write_addr_reg(sensor->slv_addr, X_OUTPUT_SIZE_H, outputX, outputY) - || write_reg_bits(sensor->slv_addr, ISP_CONTROL_01, 0x20, scale); - if(!ret){ - sensor->status.scale = scale; - sensor->status.binning = binning; - ret = set_image_options(sensor); - } - return ret; -} - -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div) -{ - int ret = 0; - ret = set_pll(sensor, bypass > 0, multiplier, sys_div, pre_div, root_2x > 0, seld5, pclk_manual > 0, pclk_div); - return ret; -} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.brightness = 0; - sensor->status.contrast = 0; - sensor->status.saturation = 0; - sensor->status.sharpness = (read_reg(sensor->slv_addr, 0x5303) / 8) - 3; - sensor->status.denoise = get_denoise(sensor); - sensor->status.ae_level = 0; - sensor->status.gainceiling = read_reg16(sensor->slv_addr, 0x3A18) & 0x3FF; - sensor->status.awb = check_reg_mask(sensor->slv_addr, ISP_CONTROL_01, 0x01); - sensor->status.dcw = !check_reg_mask(sensor->slv_addr, 0x5183, 0x80); - sensor->status.agc = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AGC_MANUALEN); - sensor->status.aec = !check_reg_mask(sensor->slv_addr, AEC_PK_MANUAL, AEC_PK_MANUAL_AEC_MANUALEN); - sensor->status.hmirror = check_reg_mask(sensor->slv_addr, TIMING_TC_REG21, TIMING_TC_REG21_HMIRROR); - sensor->status.vflip = check_reg_mask(sensor->slv_addr, TIMING_TC_REG20, TIMING_TC_REG20_VFLIP); - sensor->status.colorbar = check_reg_mask(sensor->slv_addr, PRE_ISP_TEST_SETTING_1, TEST_COLOR_BAR); - sensor->status.bpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x04); - sensor->status.wpc = check_reg_mask(sensor->slv_addr, 0x5000, 0x02); - sensor->status.raw_gma = check_reg_mask(sensor->slv_addr, 0x5000, 0x20); - sensor->status.lenc = check_reg_mask(sensor->slv_addr, 0x5000, 0x80); - sensor->status.quality = read_reg(sensor->slv_addr, COMPRESSION_CTRL07) & 0x3f; - sensor->status.special_effect = 0; - sensor->status.wb_mode = 0; - sensor->status.awb_gain = check_reg_mask(sensor->slv_addr, 0x3406, 0x01); - sensor->status.agc_gain = get_agc_gain(sensor); - sensor->status.aec_value = get_aec_value(sensor); - sensor->status.aec2 = check_reg_mask(sensor->slv_addr, 0x3a00, 0x04); - return 0; -} - -int ov5640_detect(int slv_addr, sensor_id_t *id) -{ - if (OV5640_SCCB_ADDR == slv_addr) { - uint8_t h = SCCB_Read16(slv_addr, 0x300A); - uint8_t l = SCCB_Read16(slv_addr, 0x300B); - uint16_t PID = (h<<8) | l; - if (OV5640_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int ov5640_init(sensor_t *sensor) -{ - sensor->reset = reset; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_contrast = set_contrast; - sensor->set_brightness = set_brightness; - sensor->set_saturation = set_saturation; - sensor->set_sharpness = set_sharpness; - sensor->set_gainceiling = set_gainceiling; - sensor->set_quality = set_quality; - sensor->set_colorbar = set_colorbar; - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_whitebal = set_whitebal; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->init_status = init_status; - sensor->set_aec2 = set_aec2; - sensor->set_aec_value = set_aec_value; - sensor->set_special_effect = set_special_effect; - sensor->set_wb_mode = set_wb_mode; - sensor->set_ae_level = set_ae_level; - sensor->set_dcw = set_dcw_dsp; - sensor->set_bpc = set_bpc_dsp; - sensor->set_wpc = set_wpc_dsp; - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - sensor->set_denoise = set_denoise; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c deleted file mode 100644 index c683eda041..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7670.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * This file is part of the OpenMV project. - * author: Juan Schiavoni - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV7725 driver. - * - */ -#include -#include -#include -#include "sccb.h" -#include "ov7670.h" -#include "ov7670_regs.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "ov7760"; -#endif - -static int ov7670_clkrc = 0x01; - -/* - * The default register settings, as obtained from OmniVision. There - * is really no making sense of most of these - lots of "reserved" values - * and such. - * - * These settings give VGA YUYV. - */ -struct regval_list { - uint8_t reg_num; - uint8_t value; -}; - -static struct regval_list ov7670_default_regs[] = { - /* Sensor automatically sets output window when resolution changes. */ - {TSLB, 0x04}, - - /* Frame rate 30 fps at 12 Mhz clock */ - {CLKRC, 0x00}, - {DBLV, 0x4A}, - - {COM10, COM10_VSYNC_NEG | COM10_PCLK_FREE}, - - /* Improve white balance */ - {COM4, 0x40}, - - /* Improve color */ - {RSVD_B0, 0x84}, - - /* Enable 50/60 Hz auto detection */ - {COM11, COM11_EXP|COM11_HZAUTO}, - - /* Disable some delays */ - {HSYST, 0}, - {HSYEN, 0}, - - {MVFP, MVFP_SUN}, - - /* More reserved magic, some of which tweaks white balance */ - {AWBC1, 0x0a}, - {AWBC2, 0xf0}, - {AWBC3, 0x34}, - {AWBC4, 0x58}, - {AWBC5, 0x28}, - {AWBC6, 0x3a}, - - {AWBCTR3, 0x0a}, - {AWBCTR2, 0x55}, - {AWBCTR1, 0x11}, - {AWBCTR0, 0x9e}, - - {COM8, COM8_FAST_AUTO|COM8_STEP_UNLIMIT|COM8_AGC_EN|COM8_AEC_EN|COM8_AWB_EN}, - - /* End marker is FF because in ov7670 the address of GAIN 0 and default value too. */ - {0xFF, 0xFF}, -}; - -static struct regval_list ov7670_fmt_yuv422[] = { - { COM7, 0x0 }, /* Selects YUV mode */ - { RGB444, 0 }, /* No RGB444 please */ - { COM1, 0 }, /* CCIR601 */ - { COM15, COM15_R00FF }, - { MVFP, MVFP_SUN }, - { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ - { MTX1, 0x80 }, /* "matrix coefficient 1" */ - { MTX2, 0x80 }, /* "matrix coefficient 2" */ - { MTX3, 0 }, /* vb */ - { MTX4, 0x22 }, /* "matrix coefficient 4" */ - { MTX5, 0x5e }, /* "matrix coefficient 5" */ - { MTX6, 0x80 }, /* "matrix coefficient 6" */ - { COM13, COM13_UVSAT }, - { 0xff, 0xff }, /* END MARKER */ -}; - -static struct regval_list ov7670_fmt_rgb565[] = { - { COM7, COM7_FMT_RGB565 }, /* Selects RGB mode */ - { RGB444, 0 }, /* No RGB444 please */ - { COM1, 0x0 }, /* CCIR601 */ - { COM15, COM15_RGB565 |COM15_R00FF }, - { MVFP, MVFP_SUN }, - { COM9, 0x6A }, /* 128x gain ceiling; 0x8 is reserved bit */ - { MTX1, 0xb3 }, /* "matrix coefficient 1" */ - { MTX2, 0xb3 }, /* "matrix coefficient 2" */ - { MTX3, 0 }, /* vb */ - { MTX4, 0x3d }, /* "matrix coefficient 4" */ - { MTX5, 0xa7 }, /* "matrix coefficient 5" */ - { MTX6, 0xe4 }, /* "matrix coefficient 6" */ - { COM13, COM13_UVSAT }, - { 0xff, 0xff }, /* END MARKER */ -}; - - -static struct regval_list ov7670_vga[] = { - { COM3, 0x00 }, - { COM14, 0x00 }, - { SCALING_XSC, 0x3A }, - { SCALING_YSC, 0x35 }, - { SCALING_DCWCTR, 0x11 }, - { SCALING_PCLK_DIV, 0xF0 }, - { SCALING_PCLK_DELAY, 0x02 }, - { 0xff, 0xff }, -}; - -static struct regval_list ov7670_qvga[] = { - { COM3, 0x04 }, - { COM14, 0x19 }, - { SCALING_XSC, 0x3A }, - { SCALING_YSC, 0x35 }, - { SCALING_DCWCTR, 0x11 }, - { SCALING_PCLK_DIV, 0xF1 }, - { SCALING_PCLK_DELAY, 0x02 }, - { 0xff, 0xff }, -}; - -static struct regval_list ov7670_qqvga[] = { - { COM3, 0x04 }, //DCW enable - { COM14, 0x1a }, //pixel clock divided by 4, manual scaling enable, DCW and PCLK controlled by register - { SCALING_XSC, 0x3a }, - { SCALING_YSC, 0x35 }, - { SCALING_DCWCTR, 0x22 }, //downsample by 4 - { SCALING_PCLK_DIV, 0xf2 }, //pixel clock divided by 4 - { SCALING_PCLK_DELAY, 0x02 }, - { 0xff, 0xff }, -}; - -/* - * Write a list of register settings; ff/ff stops the process. - */ -static int ov7670_write_array(sensor_t *sensor, struct regval_list *vals) -{ -int ret = 0; - - while ( (vals->reg_num != 0xff || vals->value != 0xff) && (ret == 0) ) { - ret = SCCB_Write(sensor->slv_addr, vals->reg_num, vals->value); - - ESP_LOGD(TAG, "reset reg %02X, W(%02X) R(%02X)", vals->reg_num, - vals->value, SCCB_Read(sensor->slv_addr, vals->reg_num) ); - - vals++; - } - - return ret; -} - -/* - * Calculate the frame control registers. - */ -static int ov7670_frame_control(sensor_t *sensor, int hstart, int hstop, int vstart, int vstop) -{ - struct regval_list frame[7]; - - frame[0].reg_num = HSTART; - frame[0].value = (hstart >> 3); - - frame[1].reg_num = HSTOP; - frame[1].value = (hstop >> 3); - - frame[2].reg_num = HREF; - frame[2].value = (((hstop & 0x07) << 3) | (hstart & 0x07)); - - frame[3].reg_num = VSTART; - frame[3].value = (vstart >> 2); - - frame[4].reg_num = VSTOP; - frame[4].value = (vstop >> 2); - - frame[5].reg_num = VREF; - frame[5].value = (((vstop & 0x02) << 2) | (vstart & 0x02)); - - /* End mark */ - frame[6].reg_num = 0xFF; - frame[6].value = 0xFF; - - return ov7670_write_array(sensor, frame); -} - -static int reset(sensor_t *sensor) -{ - int ret; - - // Reset all registers - SCCB_Write(sensor->slv_addr, COM7, COM7_RESET); - - // Delay 10 ms - vTaskDelay(10 / portTICK_PERIOD_MS); - - ret = ov7670_write_array(sensor, ov7670_default_regs); - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ -int ret; - - switch (pixformat) { - case PIXFORMAT_RGB565: - case PIXFORMAT_RGB888: - ret = ov7670_write_array(sensor, ov7670_fmt_rgb565); - break; - - case PIXFORMAT_YUV422: - case PIXFORMAT_GRAYSCALE: - default: - ret = ov7670_write_array(sensor, ov7670_fmt_yuv422); - break; - } - - vTaskDelay(30 / portTICK_PERIOD_MS); - - /* - * If we're running RGB565, we must rewrite clkrc after setting - * the other parameters or the image looks poor. If we're *not* - * doing RGB565, we must not rewrite clkrc or the image looks - * *really* poor. - * - * (Update) Now that we retain clkrc state, we should be able - * to write it unconditionally, and that will make the frame - * rate persistent too. - */ - if (pixformat == PIXFORMAT_RGB565) { - ret = SCCB_Write(sensor->slv_addr, CLKRC, ov7670_clkrc); - } - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret; - - // store clkrc before changing window settings... - ov7670_clkrc = SCCB_Read(sensor->slv_addr, CLKRC); - - switch (framesize){ - case FRAMESIZE_VGA: - if( (ret = ov7670_write_array(sensor, ov7670_vga)) == 0 ) { - /* These values from Omnivision */ - ret = ov7670_frame_control(sensor, 158, 14, 10, 490); - } - break; - case FRAMESIZE_QVGA: - if( (ret = ov7670_write_array(sensor, ov7670_qvga)) == 0 ) { - /* These values from Omnivision */ - ret = ov7670_frame_control(sensor, 158, 14, 10, 490); - } - break; - case FRAMESIZE_QQVGA: - if( (ret = ov7670_write_array(sensor, ov7670_qqvga)) == 0 ) { - /* These values from Omnivision */ - ret = ov7670_frame_control(sensor, 158, 14, 12, 490); - } - break; - - default: - ret = -1; - } - - vTaskDelay(30 / portTICK_PERIOD_MS); - - if (ret == 0) { - sensor->status.framesize = framesize; - } - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - uint8_t ret = 0; - // Read register scaling_xsc - uint8_t reg = SCCB_Read(sensor->slv_addr, SCALING_XSC); - - // Pattern to set color bar bit[0]=0 in every case - reg = SCALING_XSC_CBAR(reg); - - // Write pattern to SCALING_XSC - ret = SCCB_Write(sensor->slv_addr, SCALING_XSC, reg); - - // Read register scaling_ysc - reg = SCCB_Read(sensor->slv_addr, SCALING_YSC); - - // Pattern to set color bar bit[0]=0 in every case - reg = SCALING_YSC_CBAR(reg, enable); - - // Write pattern to SCALING_YSC - ret = ret | SCCB_Write(sensor->slv_addr, SCALING_YSC, reg); - - // return 0 or 0xFF - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - // Read register COM8 - uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); - - // Set white bal on/off - reg = COM8_SET_AWB(reg, enable); - - // Write back register COM8 - return SCCB_Write(sensor->slv_addr, COM8, reg); -} - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - // Read register COM8 - uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); - - // Set white bal on/off - reg = COM8_SET_AGC(reg, enable); - - // Write back register COM8 - return SCCB_Write(sensor->slv_addr, COM8, reg); -} - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - // Read register COM8 - uint8_t reg = SCCB_Read(sensor->slv_addr, COM8); - - // Set white bal on/off - reg = COM8_SET_AEC(reg, enable); - - // Write back register COM8 - return SCCB_Write(sensor->slv_addr, COM8, reg); -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - // Read register MVFP - uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); - - // Set mirror on/off - reg = MVFP_SET_MIRROR(reg, enable); - - // Write back register MVFP - return SCCB_Write(sensor->slv_addr, MVFP, reg); -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - // Read register MVFP - uint8_t reg = SCCB_Read(sensor->slv_addr, MVFP); - - // Set mirror on/off - reg = MVFP_SET_FLIP(reg, enable); - - // Write back register MVFP - return SCCB_Write(sensor->slv_addr, MVFP, reg); -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.awb = 0; - sensor->status.aec = 0; - sensor->status.agc = 0; - sensor->status.hmirror = 0; - sensor->status.vflip = 0; - sensor->status.colorbar = 0; - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } - -int ov7670_detect(int slv_addr, sensor_id_t *id) -{ - if (OV7670_SCCB_ADDR == slv_addr) { - SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor - uint16_t PID = SCCB_Read(slv_addr, 0x0A); - if (OV7670_PID == PID) { - id->PID = PID; - id->VER = SCCB_Read(slv_addr, REG_VER); - id->MIDL = SCCB_Read(slv_addr, REG_MIDL); - id->MIDH = SCCB_Read(slv_addr, REG_MIDH); - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int ov7670_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_whitebal; - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - //not supported - sensor->set_brightness= set_dummy; - sensor->set_saturation= set_dummy; - sensor->set_quality = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - sensor->set_aec2 = set_dummy; - sensor->set_aec_value = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - sensor->set_dcw = set_dummy; - sensor->set_bpc = set_dummy; - sensor->set_wpc = set_dummy; - sensor->set_awb_gain = set_dummy; - sensor->set_agc_gain = set_dummy; - sensor->set_raw_gma = set_dummy; - sensor->set_lenc = set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_denoise = set_dummy; - - // Retrieve sensor's signature - sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH); - sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL); - sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID); - sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER); - - ESP_LOGD(TAG, "OV7670 Attached"); - - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c deleted file mode 100644 index 9418a82f3f..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/ov7725.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV7725 driver. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "ov7725.h" -#include "ov7725_regs.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "ov7725"; -#endif - - -static const uint8_t default_regs[][2] = { - {COM3, COM3_SWAP_YUV}, - {COM7, COM7_RES_QVGA | COM7_FMT_YUV}, - - {COM4, 0x01 | 0x00}, /* bypass PLL (0x00:off, 0x40:4x, 0x80:6x, 0xC0:8x) */ - {CLKRC, 0x80 | 0x03}, /* Res/Bypass pre-scalar (0x40:bypass, 0x00-0x3F:prescaler PCLK=XCLK/(prescaler + 1)/2 ) */ - - // QVGA Window Size - {HSTART, 0x3F}, - {HSIZE, 0x50}, - {VSTART, 0x03}, - {VSIZE, 0x78}, - {HREF, 0x00}, - - // Scale down to QVGA Resolution - {HOUTSIZE, 0x50}, - {VOUTSIZE, 0x78}, - {EXHCH, 0x00}, - - {COM12, 0x03}, - {TGT_B, 0x7F}, - {FIXGAIN, 0x09}, - {AWB_CTRL0, 0xE0}, - {DSP_CTRL1, 0xFF}, - - {DSP_CTRL2, DSP_CTRL2_VDCW_EN | DSP_CTRL2_HDCW_EN | DSP_CTRL2_HZOOM_EN | DSP_CTRL2_VZOOM_EN}, - - {DSP_CTRL3, 0x00}, - {DSP_CTRL4, 0x00}, - {DSPAUTO, 0xFF}, - - {COM8, 0xF0}, - {COM6, 0xC5}, - {COM9, 0x11}, - {COM10, COM10_VSYNC_NEG | COM10_PCLK_FREE}, //Invert VSYNC and MASK PCLK - {BDBASE, 0x7F}, - {DBSTEP, 0x03}, - {AEW, 0x75}, - {AEB, 0x64}, - {VPT, 0xA1}, - {EXHCL, 0x00}, - {AWB_CTRL3, 0xAA}, - {COM8, 0xFF}, - - //Gamma - {GAM1, 0x0C}, - {GAM2, 0x16}, - {GAM3, 0x2A}, - {GAM4, 0x4E}, - {GAM5, 0x61}, - {GAM6, 0x6F}, - {GAM7, 0x7B}, - {GAM8, 0x86}, - {GAM9, 0x8E}, - {GAM10, 0x97}, - {GAM11, 0xA4}, - {GAM12, 0xAF}, - {GAM13, 0xC5}, - {GAM14, 0xD7}, - {GAM15, 0xE8}, - - {SLOP, 0x20}, - {EDGE1, 0x05}, - {EDGE2, 0x03}, - {EDGE3, 0x00}, - {DNSOFF, 0x01}, - - {MTX1, 0xB0}, - {MTX2, 0x9D}, - {MTX3, 0x13}, - {MTX4, 0x16}, - {MTX5, 0x7B}, - {MTX6, 0x91}, - {MTX_CTRL, 0x1E}, - - {BRIGHTNESS, 0x08}, - {CONTRAST, 0x30}, - {UVADJ0, 0x81}, - {SDE, (SDE_CONT_BRIGHT_EN | SDE_SATURATION_EN)}, - - // For 30 fps/60Hz - {DM_LNL, 0x00}, - {DM_LNH, 0x00}, - {BDBASE, 0x7F}, - {DBSTEP, 0x03}, - - // Lens Correction, should be tuned with real camera module - {LC_RADI, 0x10}, - {LC_COEF, 0x10}, - {LC_COEFB, 0x14}, - {LC_COEFR, 0x17}, - {LC_CTR, 0x05}, - {COM5, 0xF5}, //0x65 - - {0x00, 0x00}, -}; - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg & 0xFF); - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); - return ret; -} - -static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value); - return ret; -} - -static int get_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length) -{ - int ret = 0; - ret = SCCB_Read(sensor->slv_addr, reg); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - return (ret & mask) >> offset; -} - - -static int reset(sensor_t *sensor) -{ - int i=0; - const uint8_t (*regs)[2]; - - // Reset all registers - SCCB_Write(sensor->slv_addr, COM7, COM7_RESET); - - // Delay 10 ms - vTaskDelay(10 / portTICK_PERIOD_MS); - - // Write default regsiters - for (i=0, regs = default_regs; regs[i][0]; i++) { - SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]); - } - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return 0; -} - - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret=0; - sensor->pixformat = pixformat; - // Read register COM7 - uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); - - switch (pixformat) { - case PIXFORMAT_RGB565: - reg = COM7_SET_RGB(reg, COM7_FMT_RGB565); - break; - case PIXFORMAT_YUV422: - case PIXFORMAT_GRAYSCALE: - reg = COM7_SET_FMT(reg, COM7_FMT_YUV); - break; - default: - return -1; - } - - // Write back register COM7 - ret = SCCB_Write(sensor->slv_addr, COM7, reg); - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - int ret=0; - if (framesize > FRAMESIZE_VGA) { - return -1; - } - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - uint8_t reg = SCCB_Read(sensor->slv_addr, COM7); - - sensor->status.framesize = framesize; - - // Write MSBs - ret |= SCCB_Write(sensor->slv_addr, HOUTSIZE, w>>2); - ret |= SCCB_Write(sensor->slv_addr, VOUTSIZE, h>>1); - - ret |= SCCB_Write(sensor->slv_addr, HSIZE, w>>2); - ret |= SCCB_Write(sensor->slv_addr, VSIZE, h>>1); - - // Write LSBs - ret |= SCCB_Write(sensor->slv_addr, HREF, ((w&0x3) | ((h&0x1) << 2))); - - if (framesize < FRAMESIZE_VGA) { - // Enable auto-scaling/zooming factors - ret |= SCCB_Write(sensor->slv_addr, DSPAUTO, 0xFF); - - ret |= SCCB_Write(sensor->slv_addr, HSTART, 0x3F); - ret |= SCCB_Write(sensor->slv_addr, VSTART, 0x03); - - ret |= SCCB_Write(sensor->slv_addr, COM7, reg | COM7_RES_QVGA); - - ret |= SCCB_Write(sensor->slv_addr, CLKRC, 0x80 | 0x01); - - } else { - // Disable auto-scaling/zooming factors - ret |= SCCB_Write(sensor->slv_addr, DSPAUTO, 0xF3); - - // Clear auto-scaling/zooming factors - ret |= SCCB_Write(sensor->slv_addr, SCAL0, 0x00); - ret |= SCCB_Write(sensor->slv_addr, SCAL1, 0x00); - ret |= SCCB_Write(sensor->slv_addr, SCAL2, 0x00); - - ret |= SCCB_Write(sensor->slv_addr, HSTART, 0x23); - ret |= SCCB_Write(sensor->slv_addr, VSTART, 0x07); - - ret |= SCCB_Write(sensor->slv_addr, COM7, reg & ~COM7_RES_QVGA); - - ret |= SCCB_Write(sensor->slv_addr, CLKRC, 0x80 | 0x03); - } - - // Delay - vTaskDelay(30 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret=0; - uint8_t reg; - sensor->status.colorbar = enable; - - // Read reg COM3 - reg = SCCB_Read(sensor->slv_addr, COM3); - // Enable colorbar test pattern output - reg = COM3_SET_CBAR(reg, enable); - // Write back COM3 - ret |= SCCB_Write(sensor->slv_addr, COM3, reg); - - // Read reg DSP_CTRL3 - reg = SCCB_Read(sensor->slv_addr, DSP_CTRL3); - // Enable DSP colorbar output - reg = DSP_CTRL3_SET_CBAR(reg, enable); - // Write back DSP_CTRL3 - ret |= SCCB_Write(sensor->slv_addr, DSP_CTRL3, reg); - - return ret; -} - -static int set_whitebal(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, COM8, 1, 1, enable) >= 0){ - sensor->status.awb = !!enable; - } - return sensor->status.awb; -} - -static int set_gain_ctrl(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, COM8, 2, 1, enable) >= 0){ - sensor->status.agc = !!enable; - } - return sensor->status.agc; -} - -static int set_exposure_ctrl(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, COM8, 0, 1, enable) >= 0){ - sensor->status.aec = !!enable; - } - return sensor->status.aec; -} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, COM3, 6, 1, enable) >= 0){ - sensor->status.hmirror = !!enable; - } - return sensor->status.hmirror; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - if(set_reg_bits(sensor, COM3, 7, 1, enable) >= 0){ - sensor->status.vflip = !!enable; - } - return sensor->status.vflip; -} - -static int set_dcw_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x65, 2, 1, !enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set dcw to: %d", enable); - sensor->status.dcw = enable; - } - return ret; -} - -static int set_aec2(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, COM8, 7, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set aec2 to: %d", enable); - sensor->status.aec2 = enable; - } - return ret; -} - -static int set_bpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x64, 1, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set bpc to: %d", enable); - sensor->status.bpc = enable; - } - return ret; -} - -static int set_wpc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x64, 0, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set wpc to: %d", enable); - sensor->status.wpc = enable; - } - return ret; -} - -static int set_raw_gma_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x64, 2, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set raw_gma to: %d", enable); - sensor->status.raw_gma = enable; - } - return ret; -} - -static int set_lenc_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, LC_CTR, 0, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set lenc to: %d", enable); - sensor->status.lenc = enable; - } - return ret; -} - -//real gain -static int set_agc_gain(sensor_t *sensor, int gain) -{ - int ret = 0; - ret = set_reg_bits(sensor, COM9, 4, 3, gain % 5); - if (ret == 0) { - ESP_LOGD(TAG, "Set gain to: %d", gain); - sensor->status.agc_gain = gain; - } - return ret; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, AEC, value & 0xff) | SCCB_Write(sensor->slv_addr, AECH, value >> 8); - if (ret == 0) { - ESP_LOGD(TAG, "Set aec_value to: %d", value); - sensor->status.aec_value = value; - } - return ret; -} - -static int set_awb_gain_dsp(sensor_t *sensor, int enable) -{ - int ret = 0; - ret = set_reg_bits(sensor, 0x63, 7, 1, enable); - if (ret == 0) { - ESP_LOGD(TAG, "Set awb_gain to: %d", enable); - sensor->status.awb_gain = enable; - } - return ret; -} - -static int set_brightness(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x9B, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set brightness to: %d", level); - sensor->status.brightness = level; - } - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - ret = SCCB_Write(sensor->slv_addr, 0x9C, level); - if (ret == 0) { - ESP_LOGD(TAG, "Set contrast to: %d", level); - sensor->status.contrast = level; - } - return ret; -} - -static int init_status(sensor_t *sensor) -{ - sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x9B); - sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0x9C); - sensor->status.saturation = 0; - sensor->status.ae_level = 0; - sensor->status.special_effect = get_reg_bits(sensor, 0x64, 5, 1); - sensor->status.wb_mode = get_reg_bits(sensor, 0x6B, 7, 1); - sensor->status.agc_gain = get_reg_bits(sensor, COM9, 4, 3); - sensor->status.aec_value = SCCB_Read(sensor->slv_addr, AEC) | (SCCB_Read(sensor->slv_addr, AECH) << 8); - sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x00); - sensor->status.awb = get_reg_bits(sensor, COM8, 1, 1); - sensor->status.awb_gain = get_reg_bits(sensor, 0x63, 7, 1); - sensor->status.aec = get_reg_bits(sensor, COM8, 0, 1); - sensor->status.aec2 = get_reg_bits(sensor, COM8, 7, 1); - sensor->status.agc = get_reg_bits(sensor, COM8, 2, 1); - sensor->status.bpc = get_reg_bits(sensor, 0x64, 1, 1); - sensor->status.wpc = get_reg_bits(sensor, 0x64, 0, 1); - sensor->status.raw_gma = get_reg_bits(sensor, 0x64, 2, 1); - sensor->status.lenc = get_reg_bits(sensor, LC_CTR, 0, 1); - sensor->status.hmirror = get_reg_bits(sensor, COM3, 6, 1); - sensor->status.vflip = get_reg_bits(sensor, COM3, 7, 1); - sensor->status.dcw = get_reg_bits(sensor, 0x65, 2, 1); - sensor->status.colorbar = get_reg_bits(sensor, COM3, 0, 1); - sensor->status.sharpness = get_reg_bits(sensor, EDGE0, 0, 5); - sensor->status.denoise = SCCB_Read(sensor->slv_addr, 0x8E); - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } -static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val){ return -1; } -static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning){return -1;} -static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div){return -1;} - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int ov7725_detect(int slv_addr, sensor_id_t *id) -{ - if (OV7725_SCCB_ADDR == slv_addr) { - SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor - uint16_t PID = SCCB_Read(slv_addr, 0x0A); - if (OV7725_PID == PID) { - id->PID = PID; - id->VER = SCCB_Read(slv_addr, REG_VER); - id->MIDL = SCCB_Read(slv_addr, REG_MIDL); - id->MIDH = SCCB_Read(slv_addr, REG_MIDH); - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int ov7725_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_colorbar = set_colorbar; - sensor->set_whitebal = set_whitebal; - sensor->set_gain_ctrl = set_gain_ctrl; - sensor->set_exposure_ctrl = set_exposure_ctrl; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - - sensor->set_brightness = set_brightness; - sensor->set_contrast = set_contrast; - sensor->set_aec2 = set_aec2; - sensor->set_aec_value = set_aec_value; - sensor->set_awb_gain = set_awb_gain_dsp; - sensor->set_agc_gain = set_agc_gain; - sensor->set_dcw = set_dcw_dsp; - sensor->set_bpc = set_bpc_dsp; - sensor->set_wpc = set_wpc_dsp; - sensor->set_raw_gma = set_raw_gma_dsp; - sensor->set_lenc = set_lenc_dsp; - - //not supported - sensor->set_saturation= set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_quality = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - sensor->set_gainceiling = set_gainceiling_dummy; - - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_res_raw = set_res_raw; - sensor->set_pll = _set_pll; - sensor->set_xclk = set_xclk; - - // Retrieve sensor's signature - sensor->id.MIDH = SCCB_Read(sensor->slv_addr, REG_MIDH); - sensor->id.MIDL = SCCB_Read(sensor->slv_addr, REG_MIDL); - sensor->id.PID = SCCB_Read(sensor->slv_addr, REG_PID); - sensor->id.VER = SCCB_Read(sensor->slv_addr, REG_VER); - - ESP_LOGD(TAG, "OV7725 Attached"); - - return 0; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h deleted file mode 100644 index 8c925eb5e5..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef __BF20A6_H__ -#define __BF20A6_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int bf20a6_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int bf20a6_init(sensor_t *sensor); - -#endif // __BF20A6_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h deleted file mode 100644 index ab1ff69e94..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_regs.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * BF20A6 register definitions. - */ -#ifndef __BF20A6_REG_REGS_H__ -#define __BF20A6_REG_REGS_H__ - -#define SENSOR_ID_HIGH 0XFC -#define SENSOR_ID_LOW 0XFD -#define RESET_RELATED 0XF2 - - -#endif //__BF20A6_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h deleted file mode 100644 index 0414bbacd6..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf20a6_settings.h +++ /dev/null @@ -1,158 +0,0 @@ - -#include - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0xffff /* Array end token */ - -static const uint16_t bf20a6_default_init_regs[][2] = { - {0xf2,0x01}, - {0x12,0x20}, - {0x3a,0x00}, - {0xe1,0x92}, - {0xe3,0x12},// PLL Control, important for framerate(choice: 0x02\0x12\0x22\0x32\0x82) - {0xe0,0x00}, - {0x2a,0x98}, - {0xcd,0x17}, - {0xc0,0x10}, - {0xc6,0x1d}, - {0x10,0x35}, - {0xe2,0x09}, - {0xe4,0x72}, - {0xe5,0x22}, - {0xe6,0x24}, - {0xe7,0x64}, - {0xe8,0xa2}, // DVP:a2}, SPI:f2 VDDIO=1.8V,E8[2]=1},VDDIO=2.8V,E8[2]=0}, - {0x4a,0x00}, - {0x00,0x03}, - {0x1f,0x02}, - {0x22,0x02}, - {0x0c,0x31}, - - {0x00,0x00}, - {0x60,0x81}, - {0x61,0x81}, - - {0xa0,0x08}, - {0x01,0x1a}, - // {0x01,0x1a}, - // {0x01,0x1a}, - // {0x02,0x15}, - // {0x02,0x15}, - {0x02,0x15}, - {0x13,0x08}, - {0x8a,0x96}, - {0x8b,0x06}, - {0x87,0x18}, - - - {0x34,0x48}, // lens - {0x35,0x40}, - {0x36,0x40}, - - {0x71,0x44}, - {0x72,0x48}, - {0x74,0xa2}, - {0x75,0xa9}, - {0x78,0x12}, - {0x79,0xa0}, - {0x7a,0x94}, - {0x7c,0x97}, - {0x40,0x30}, - {0x41,0x30}, - {0x42,0x28}, - {0x43,0x1f}, - {0x44,0x1c}, - {0x45,0x16}, - {0x46,0x13}, - {0x47,0x10}, - {0x48,0x0D}, - {0x49,0x0C}, - {0x4B,0x0A}, - {0x4C,0x0B}, - {0x4E,0x09}, - {0x4F,0x08}, - {0x50,0x08}, - - - {0x5f,0x29}, - {0x23,0x33}, - {0xa1,0x10}, // AWB - {0xa2,0x0d}, - {0xa3,0x30}, - {0xa4,0x06}, - {0xa5,0x22}, - {0xa6,0x56}, - {0xa7,0x18}, - {0xa8,0x1a}, - {0xa9,0x12}, - {0xaa,0x12}, - {0xab,0x16}, - {0xac,0xb1}, - {0xba,0x12}, - {0xbb,0x12}, - {0xad,0x12}, - {0xae,0x56}, - {0xaf,0x0a}, - {0x3b,0x30}, - {0x3c,0x12}, - {0x3d,0x22}, - {0x3e,0x3f}, - {0x3f,0x28}, - {0xb8,0xc3}, - {0xb9,0xa3}, - {0x39,0x47}, // pure color threshold - {0x26,0x13}, - {0x27,0x16}, - {0x28,0x14}, - {0x29,0x18}, - {0xee,0x0d}, - - - {0x13,0x05}, - {0x24,0x3C}, - {0x81,0x20}, - {0x82,0x40}, - {0x83,0x30}, - {0x84,0x58}, - {0x85,0x30}, - {0x92,0x08}, - {0x86,0x80}, - {0x8a,0x96}, - {0x91,0xff}, - {0x94,0x62}, - {0x9a,0x18}, // outdoor threshold - {0xf0,0x45}, // integral time control, important for framerate(choice: 0x46\0x45\0x44..) - {0x51,0x17}, // color normal - {0x52,0x03}, - {0x53,0x5F}, - {0x54,0x47}, - {0x55,0x66}, - {0x56,0x0F}, - {0x7e,0x14}, - {0x57,0x36}, // color - {0x58,0x2A}, - {0x59,0xAA}, - {0x5a,0xA8}, - {0x5b,0x43}, - {0x5c,0x10}, - {0x5d,0x00}, - {0x7d,0x36}, - {0x5e,0x10}, - - {0xd6,0x88}, // contrast - {0xd5,0x20}, // bright - {0xb0,0x84}, // low light ctrl in gray section - {0xb5,0x08}, // the threshold of GLB_GAIN - {0xb1,0xc8}, // saturation - {0xb2,0xc0}, - {0xb3,0xd0}, - {0xb4,0xB0}, - - {0x32,0x10}, - // {0x8a,0x00}, - // {0x8b,0x10}, - {0xa0,0x09}, - {0x00,0x03}, - {0x0b,0x02}, - {REGLIST_TAIL, 0x00}, -}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h deleted file mode 100644 index 6524a1d495..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * BF3005 driver. - * - */ -#ifndef __BF3005_H__ -#define __BF3005_H__ -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int bf3005_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int bf3005_init(sensor_t *sensor); - -#endif // __BF3005_H__ \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h deleted file mode 100644 index 0bf0d37a7c..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/bf3005_regs.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * BF3005 register definitions. - */ -#ifndef __REG_REGS_H__ -#define __REG_REGS_H__ -#if 0 -#define GAIN 0x00 /* AGC C Gain control gain setting */ -#define BLUE 0x01 /* AWB C Blue channel gain setting */ -#define RED 0x02 /* AWB C Red channel gain setting */ -#define GREEN 0x03 /* AWB C Green channel gain setting */ -#define BAVG 0x05 /* U/B Average Level */ -#define GAVG 0x06 /* Y/Gb Average Level */ -#define RAVG 0x07 /* V/R Average Level */ -#define AECH 0x08 /* Exposure Value C AEC MSBs */ - -#define COM2 0x09 /* Common Control 2 */ -#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ -#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ -#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ -#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ -#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ - -#define REG_PID 0x0A /* Product ID Number MSB */ -#define REG_VER 0x0B /* Product ID Number LSB */ - -#define COM3 0x0C /* Common Control 3 */ -#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */ -#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */ -#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */ -#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */ -#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */ -#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */ -#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */ -#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */ -#define COM3_SET_CBAR(r, x) ((r&0xFE)|((x&1)<<0)) -#define COM3_SET_MIRROR(r, x) ((r&0xBF)|((x&1)<<6)) -#define COM3_SET_FLIP(r, x) ((r&0x7F)|((x&1)<<7)) - -#define COM4 0x0D /* Common Control 4 */ -#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ -#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ -#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ -#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ -#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ -#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ -#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ -#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ - -#define COM5 0x0E /* Common Control 5 */ -#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ -#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ -#define COM5_AFR_0 0x00 /* No reduction of frame rate */ -#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ -#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ -#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ -#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ -#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ -#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ -#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ - -#define COM6 0x0F /* Common Control 6 */ -#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ - -#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ -#define CLKRC 0x11 /* Internal Clock */ - -#define COM7 0x12 /* Common Control 7 */ -#define COM7_RESET 0x80 /* SCCB Register Reset */ -#define COM7_RES_VGA 0x00 /* Resolution VGA */ -#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ -#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ -#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ -#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ -#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ -#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ -#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ -#define COM7_FMT_YUV 0x00 /* Output format YUV */ -#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ -#define COM7_FMT_RGB 0x02 /* Output format RGB */ -#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ -#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x3)<<0)) -#define COM7_SET_RGB(r, x) ((r&0xF0)|(x&0x0C)|COM7_FMT_RGB) - -#define COM8 0x13 /* Common Control 8 */ -#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ -#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ -#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ -#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ -#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ -#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ -#define COM8_AGC_EN 0x04 /* AGC Enable */ -#define COM8_AWB_EN 0x02 /* AWB Enable */ -#define COM8_AEC_EN 0x01 /* AEC Enable */ -#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) -#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) -#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) - -#define COM9 0x14 /* Common Control 9 */ -#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ -#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ -#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ -#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ -#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ -#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ -#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ -#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ -#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) - -#define COM10 0x15 /* Common Control 10 */ -#define COM10_NEGATIVE 0x80 /* Output negative data */ -#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ -#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ -#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ -#define COM10_PCLK_REV 0x10 /* PCLK reverse */ -#define COM10_HREF_REV 0x08 /* HREF reverse */ -#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ -#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ -#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ -#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ -#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ - -#define REG16 0x16 /* Register 16 */ -#define REG16_BIT_SHIFT 0x80 /* Bit shift test pattern options */ -#define HSTART 0x17 /* Horizontal Frame (HREF column) Start 8 MSBs (2 LSBs are at HREF[5:4]) */ -#define HSIZE 0x18 /* Horizontal Sensor Size (2 LSBs are at HREF[1:0]) */ -#define VSTART 0x19 /* Vertical Frame (row) Start 8 MSBs (1 LSB is at HREF[6]) */ -#define VSIZE 0x1A /* Vertical Sensor Size (1 LSB is at HREF[2]) */ -#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ -#define REG_MIDH 0x1C /* Manufacturer ID Byte C High */ -#define REG_MIDL 0x1D /* Manufacturer ID Byte C Low */ -#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period */ - -#define COM11 0x20 /* Common Control 11 */ -#define COM11_SNGL_FRAME_EN 0x02 /* Single frame ON/OFF selection */ -#define COM11_SNGL_XFR_TRIG 0x01 /* Single frame transfer trigger */ - -#define BDBASE 0x22 /* Banding Filter Minimum AEC Value */ -#define DBSTEP 0x23 /* Banding Filter Maximum Step */ -#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ -#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ -#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ -#define REG28 0x28 /* Selection on the number of dummy rows, N */ -#define HOUTSIZE 0x29 /* Horizontal Data Output Size MSBs (2 LSBs at register EXHCH[1:0]) */ -#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ -#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ -#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */ -#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ -#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ -#define YAVE 0x2F /* Y/G Channel Average Value */ -#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance High Level Threshold */ -#define LUMLTH 0x31 /* Histogram AEC/AGC Luminance Low Level Threshold */ -#define HREF 0x32 /* Image Start and Size Control */ -#define DM_LNL 0x33 /* Dummy Row Low 8 Bits */ -#define DM_LNH 0x34 /* Dummy Row High 8 Bits */ -#define ADOFF_B 0x35 /* AD Offset Compensation Value for B Channel */ -#define ADOFF_R 0x36 /* AD Offset Compensation Value for R Channel */ -#define ADOFF_GB 0x37 /* AD Offset Compensation Value for GB Channel */ -#define ADOFF_GR 0x38 /* AD Offset Compensation Value for GR Channel */ -#define OFF_B 0x39 /* AD Offset Compensation Value for B Channel */ -#define OFF_R 0x3A /* AD Offset Compensation Value for R Channel */ -#define OFF_GB 0x3B /* AD Offset Compensation Value for GB Channel */ -#define OFF_GR 0x3C /* AD Offset Compensation Value for GR Channel */ -#define COM12 0x3D /* DC offset compensation for analog process */ - -#define COM13 0x3E /* Common Control 13 */ -#define COM13_BLC_EN 0x80 /* BLC enable */ -#define COM13_ADC_EN 0x40 /* ADC channel BLC ON/OFF control */ -#define COM13_ANALOG_BLC 0x20 /* Analog processing channel BLC ON/OFF control */ -#define COM13_ABLC_GAIN_EN 0x04 /* ABLC gain trigger enable */ - -#define COM14 0x3F /* Common Control 14 */ -#define COM15 0x40 /* Common Control 15 */ -#define COM16 0x41 /* Common Control 16 */ -#define TGT_B 0x42 /* BLC Blue Channel Target Value */ -#define TGT_R 0x43 /* BLC Red Channel Target Value */ -#define TGT_GB 0x44 /* BLC Gb Channel Target Value */ -#define TGT_GR 0x45 /* BLC Gr Channel Target Value */ - -#define LC_CTR 0x46 /* Lens Correction Control */ -#define LC_CTR_RGB_COMP_1 0x00 /* R, G, and B channel compensation coefficient is set by LC_COEF (0x49) */ -#define LC_CTR_RGB_COMP_3 0x04 /* R, G, and B channel compensation coefficient is set by registers - LC_COEFB (0x4B), LC_COEF (0x49), and LC_COEFR (0x4C), respectively */ -#define LC_CTR_EN 0x01 /* Lens correction enable */ -#define LC_XC 0x47 /* X Coordinate of Lens Correction Center Relative to Array Center */ -#define LC_YC 0x48 /* Y Coordinate of Lens Correction Center Relative to Array Center */ -#define LC_COEF 0x49 /* Lens Correction Coefficient */ -#define LC_RADI 0x4A /* Lens Correction Radius */ -#define LC_COEFB 0x4B /* Lens Correction B Channel Compensation Coefficient */ -#define LC_COEFR 0x4C /* Lens Correction R Channel Compensation Coefficient */ - -#define FIXGAIN 0x4D /* Analog Fix Gain Amplifier */ -#define AREF0 0x4E /* Sensor Reference Control */ -#define AREF1 0x4F /* Sensor Reference Current Control */ -#define AREF2 0x50 /* Analog Reference Control */ -#define AREF3 0x51 /* ADC Reference Control */ -#define AREF4 0x52 /* ADC Reference Control */ -#define AREF5 0x53 /* ADC Reference Control */ -#define AREF6 0x54 /* Analog Reference Control */ -#define AREF7 0x55 /* Analog Reference Control */ -#define UFIX 0x60 /* U Channel Fixed Value Output */ -#define VFIX 0x61 /* V Channel Fixed Value Output */ -#define AWBB_BLK 0x62 /* AWB Option for Advanced AWB */ - -#define AWB_CTRL0 0x63 /* AWB Control Byte 0 */ -#define AWB_CTRL0_GAIN_EN 0x80 /* AWB gain enable */ -#define AWB_CTRL0_CALC_EN 0x40 /* AWB calculate enable */ -#define AWB_CTRL0_WBC_MASK 0x0F /* WBC threshold 2 */ - -#define DSP_CTRL1 0x64 /* DSP Control Byte 1 */ -#define DSP_CTRL1_FIFO_EN 0x80 /* FIFO enable/disable selection */ -#define DSP_CTRL1_UV_EN 0x40 /* UV adjust function ON/OFF selection */ -#define DSP_CTRL1_SDE_EN 0x20 /* SDE enable */ -#define DSP_CTRL1_MTRX_EN 0x10 /* Color matrix ON/OFF selection */ -#define DSP_CTRL1_INTRP_EN 0x08 /* Interpolation ON/OFF selection */ -#define DSP_CTRL1_GAMMA_EN 0x04 /* Gamma function ON/OFF selection */ -#define DSP_CTRL1_BLACK_EN 0x02 /* Black defect auto correction ON/OFF */ -#define DSP_CTRL1_WHITE_EN 0x01 /* White defect auto correction ON/OFF */ - -#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */ -#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */ -#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */ -#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */ -#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */ - -#define DSP_CTRL3 0x66 /* DSP Control Byte 3 */ -#define DSP_CTRL3_UV_EN 0x80 /* UV output sequence option */ -#define DSP_CTRL3_CBAR_EN 0x20 /* DSP color bar ON/OFF selection */ -#define DSP_CTRL3_FIFO_EN 0x08 /* FIFO power down ON/OFF selection */ -#define DSP_CTRL3_SCAL1_PWDN 0x04 /* Scaling module power down control 1 */ -#define DSP_CTRL3_SCAL2_PWDN 0x02 /* Scaling module power down control 2 */ -#define DSP_CTRL3_INTRP_PWDN 0x01 /* Interpolation module power down control */ -#define DSP_CTRL3_SET_CBAR(r, x) ((r&0xDF)|((x&1)<<5)) - - -#define DSP_CTRL4 0x67 /* DSP Control Byte 4 */ -#define DSP_CTRL4_YUV_RGB 0x00 /* Output selection YUV or RGB */ -#define DSP_CTRL4_RAW8 0x02 /* Output selection RAW8 */ -#define DSP_CTRL4_RAW10 0x03 /* Output selection RAW10 */ - - -#define AWB_BIAS 0x68 /* AWB BLC Level Clip */ -#define AWB_CTRL1 0x69 /* AWB Control 1 */ -#define AWB_CTRL2 0x6A /* AWB Control 2 */ - -#define AWB_CTRL3 0x6B /* AWB Control 3 */ -#define AWB_CTRL3_ADVANCED 0x80 /* AWB mode select - Advanced AWB */ -#define AWB_CTRL3_SIMPLE 0x00 /* AWB mode select - Simple AWB */ - -#define AWB_CTRL4 0x6C /* AWB Control 4 */ -#define AWB_CTRL5 0x6D /* AWB Control 5 */ -#define AWB_CTRL6 0x6E /* AWB Control 6 */ -#define AWB_CTRL7 0x6F /* AWB Control 7 */ -#define AWB_CTRL8 0x70 /* AWB Control 8 */ -#define AWB_CTRL9 0x71 /* AWB Control 9 */ -#define AWB_CTRL10 0x72 /* AWB Control 10 */ -#define AWB_CTRL11 0x73 /* AWB Control 11 */ -#define AWB_CTRL12 0x74 /* AWB Control 12 */ -#define AWB_CTRL13 0x75 /* AWB Control 13 */ -#define AWB_CTRL14 0x76 /* AWB Control 14 */ -#define AWB_CTRL15 0x77 /* AWB Control 15 */ -#define AWB_CTRL16 0x78 /* AWB Control 16 */ -#define AWB_CTRL17 0x79 /* AWB Control 17 */ -#define AWB_CTRL18 0x7A /* AWB Control 18 */ -#define AWB_CTRL19 0x7B /* AWB Control 19 */ -#define AWB_CTRL20 0x7C /* AWB Control 20 */ -#define AWB_CTRL21 0x7D /* AWB Control 21 */ -#define GAM1 0x7E /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ -#define GAM2 0x7F /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ -#define GAM3 0x80 /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ -#define GAM4 0x81 /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ -#define GAM5 0x82 /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ -#define GAM6 0x83 /* Gamma Curve 6th Segment Input End Point 0x30 Output Value */ -#define GAM7 0x84 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ -#define GAM8 0x85 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ -#define GAM9 0x86 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ -#define GAM10 0x87 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ -#define GAM11 0x88 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ -#define GAM12 0x89 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ -#define GAM13 0x8A /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ -#define GAM14 0x8B /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ -#define GAM15 0x8C /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ -#define SLOP 0x8D /* Gamma Curve Highest Segment Slope */ -#define DNSTH 0x8E /* De-noise Threshold */ -#define EDGE0 0x8F /* Edge Enhancement Strength Control */ -#define EDGE1 0x90 /* Edge Enhancement Threshold Control */ -#define DNSOFF 0x91 /* Auto De-noise Threshold Control */ -#define EDGE2 0x92 /* Edge Enhancement Strength Upper Limit */ -#define EDGE3 0x93 /* Edge Enhancement Strength Upper Limit */ -#define MTX1 0x94 /* Matrix Coefficient 1 */ -#define MTX2 0x95 /* Matrix Coefficient 2 */ -#define MTX3 0x96 /* Matrix Coefficient 3 */ -#define MTX4 0x97 /* Matrix Coefficient 4 */ -#define MTX5 0x98 /* Matrix Coefficient 5 */ -#define MTX6 0x99 /* Matrix Coefficient 6 */ - -#define MTX_CTRL 0x9A /* Matrix Control */ -#define MTX_CTRL_DBL_EN 0x80 /* Matrix double ON/OFF selection */ - -#define BRIGHTNESS 0x9B /* Brightness Control */ -#define CONTRAST 0x9C /* Contrast Gain */ -#define UVADJ0 0x9E /* Auto UV Adjust Control 0 */ -#define UVADJ1 0x9F /* Auto UV Adjust Control 1 */ -#define SCAL0 0xA0 /* DCW Ratio Control */ -#define SCAL1 0xA1 /* Horizontal Zoom Out Control */ -#define SCAL2 0xA2 /* Vertical Zoom Out Control */ -#define FIFODLYM 0xA3 /* FIFO Manual Mode Delay Control */ -#define FIFODLYA 0xA4 /* FIFO Auto Mode Delay Control */ - -#define SDE 0xA6 /* Special Digital Effect Control */ -#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */ -#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */ -#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */ -#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */ -#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */ -#define SDE_SATURATION_EN 0x02 /* Saturation enable */ -#define SDE_HUE_EN 0x01 /* Hue enable */ - -#define USAT 0xA7 /* U Component Saturation Gain */ -#define VSAT 0xA8 /* V Component Saturation Gain */ -#define HUECOS 0xA9 /* Cosine value 0x80 */ -#define HUESIN 0xAA /* Sine value 0x80 */ -#define SIGN_BIT 0xAB /* Sign Bit for Hue and Brightness */ - -#define DSPAUTO 0xAC /* DSP Auto Function ON/OFF Control */ -#define DSPAUTO_AWB_EN 0x80 /* AWB auto threshold control */ -#define DSPAUTO_DENOISE_EN 0x40 /* De-noise auto threshold control */ -#define DSPAUTO_EDGE_EN 0x20 /* Sharpness (edge enhancement) auto strength control */ -#define DSPAUTO_UV_EN 0x10 /* UV adjust auto slope control */ -#define DSPAUTO_SCAL0_EN 0x08 /* Auto scaling factor control (register SCAL0 (0xA0)) */ -#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2))*/ -#define SET_REG(reg, x) (##reg_DEFAULT|x) -#endif //__REG_REGS_H__ -#endif \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h deleted file mode 100644 index edffca1e00..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "sensor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int gc0308_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int gc0308_init(sensor_t *sensor); - -#ifdef __cplusplus -} -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h deleted file mode 100644 index f1cb4532b7..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_regs.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * GC0308 register definitions. - */ -#ifndef __GC0308_REG_REGS_H__ -#define __GC0308_REG_REGS_H__ - -#define RESET_RELATED 0xfe // Bit[7]: Software reset - // Bit[6:5]: NA - // Bit[4]: CISCTL_restart_n - // Bit[3:1]: NA - // Bit[0]: page select - // 0:page0 - // 1:page1 - - -// page0: - - - -/** - * @brief register value - */ - - -#endif // __GC0308_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h deleted file mode 100644 index adf5f28d76..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc0308_settings.h +++ /dev/null @@ -1,258 +0,0 @@ -#ifndef _GC0308_SETTINGS_H_ -#define _GC0308_SETTINGS_H_ - -#include - -#define REG_DLY 0xff - -static const uint8_t gc0308_sensor_default_regs[][2] = { - {0xfe, 0x00}, - {0xec, 0x20}, - {0x05, 0x00}, - {0x06, 0x00}, - {0x07, 0x00}, - {0x08, 0x00}, - {0x09, 0x01}, - {0x0a, 0xe8}, - {0x0b, 0x02}, - {0x0c, 0x88}, - {0x0d, 0x02}, - {0x0e, 0x02}, - {0x10, 0x26}, - {0x11, 0x0d}, - {0x12, 0x2a}, - {0x13, 0x00}, - {0x14, 0x11}, - {0x15, 0x0a}, - {0x16, 0x05}, - {0x17, 0x01}, - {0x18, 0x44}, - {0x19, 0x44}, - {0x1a, 0x2a}, - {0x1b, 0x00}, - {0x1c, 0x49}, - {0x1d, 0x9a}, - {0x1e, 0x61}, - {0x1f, 0x00}, //pad drv <=24MHz, use 0x00 is ok - {0x20, 0x7f}, - {0x21, 0xfa}, - {0x22, 0x57}, - {0x24, 0xa2}, //YCbYCr - {0x25, 0x0f}, - {0x26, 0x03}, // 0x01 - {0x28, 0x00}, - {0x2d, 0x0a}, - {0x2f, 0x01}, - {0x30, 0xf7}, - {0x31, 0x50}, - {0x32, 0x00}, - {0x33, 0x28}, - {0x34, 0x2a}, - {0x35, 0x28}, - {0x39, 0x04}, - {0x3a, 0x20}, - {0x3b, 0x20}, - {0x3c, 0x00}, - {0x3d, 0x00}, - {0x3e, 0x00}, - {0x3f, 0x00}, - {0x50, 0x14}, // 0x14 - {0x52, 0x41}, - {0x53, 0x80}, - {0x54, 0x80}, - {0x55, 0x80}, - {0x56, 0x80}, - {0x8b, 0x20}, - {0x8c, 0x20}, - {0x8d, 0x20}, - {0x8e, 0x14}, - {0x8f, 0x10}, - {0x90, 0x14}, - {0x91, 0x3c}, - {0x92, 0x50}, -//{0x8b,0x10}, -//{0x8c,0x10}, -//{0x8d,0x10}, -//{0x8e,0x10}, -//{0x8f,0x10}, -//{0x90,0x10}, -//{0x91,0x3c}, -//{0x92,0x50}, - {0x5d, 0x12}, - {0x5e, 0x1a}, - {0x5f, 0x24}, - {0x60, 0x07}, - {0x61, 0x15}, - {0x62, 0x08}, // 0x08 - {0x64, 0x03}, // 0x03 - {0x66, 0xe8}, - {0x67, 0x86}, - {0x68, 0x82}, - {0x69, 0x18}, - {0x6a, 0x0f}, - {0x6b, 0x00}, - {0x6c, 0x5f}, - {0x6d, 0x8f}, - {0x6e, 0x55}, - {0x6f, 0x38}, - {0x70, 0x15}, - {0x71, 0x33}, - {0x72, 0xdc}, - {0x73, 0x00}, - {0x74, 0x02}, - {0x75, 0x3f}, - {0x76, 0x02}, - {0x77, 0x38}, // 0x47 - {0x78, 0x88}, - {0x79, 0x81}, - {0x7a, 0x81}, - {0x7b, 0x22}, - {0x7c, 0xff}, - {0x93, 0x48}, //color matrix default - {0x94, 0x02}, - {0x95, 0x07}, - {0x96, 0xe0}, - {0x97, 0x40}, - {0x98, 0xf0}, - {0xb1, 0x40}, - {0xb2, 0x40}, - {0xb3, 0x40}, //0x40 - {0xb6, 0xe0}, - {0xbd, 0x38}, - {0xbe, 0x36}, - {0xd0, 0xCB}, - {0xd1, 0x10}, - {0xd2, 0x90}, - {0xd3, 0x48}, - {0xd5, 0xF2}, - {0xd6, 0x16}, - {0xdb, 0x92}, - {0xdc, 0xA5}, - {0xdf, 0x23}, - {0xd9, 0x00}, - {0xda, 0x00}, - {0xe0, 0x09}, - {0xed, 0x04}, - {0xee, 0xa0}, - {0xef, 0x40}, - {0x80, 0x03}, - - {0x9F, 0x10}, - {0xA0, 0x20}, - {0xA1, 0x38}, - {0xA2, 0x4e}, - {0xA3, 0x63}, - {0xA4, 0x76}, - {0xA5, 0x87}, - {0xA6, 0xa2}, - {0xA7, 0xb8}, - {0xA8, 0xca}, - {0xA9, 0xd8}, - {0xAA, 0xe3}, - {0xAB, 0xeb}, - {0xAC, 0xf0}, - {0xAD, 0xF8}, - {0xAE, 0xFd}, - {0xAF, 0xFF}, - - {0xc0, 0x00}, - {0xc1, 0x10}, - {0xc2, 0x1c}, - {0xc3, 0x30}, - {0xc4, 0x43}, - {0xc5, 0x54}, - {0xc6, 0x65}, - {0xc7, 0x75}, - {0xc8, 0x93}, - {0xc9, 0xB0}, - {0xca, 0xCB}, - {0xcb, 0xE6}, - {0xcc, 0xFF}, - {0xf0, 0x02}, - {0xf1, 0x01}, - {0xf2, 0x02}, - {0xf3, 0x30}, - {0xf7, 0x04}, - {0xf8, 0x02}, - {0xf9, 0x9f}, - {0xfa, 0x78}, - {0xfe, 0x01}, - {0x00, 0xf5}, - {0x02, 0x20}, - {0x04, 0x10}, - {0x05, 0x08}, - {0x06, 0x20}, - {0x08, 0x0a}, - {0x0a, 0xa0}, - {0x0b, 0x60}, - {0x0c, 0x08}, - {0x0e, 0x44}, - {0x0f, 0x32}, - {0x10, 0x41}, - {0x11, 0x37}, - {0x12, 0x22}, - {0x13, 0x19}, - {0x14, 0x44}, - {0x15, 0x44}, - {0x16, 0xc2}, - {0x17, 0xA8}, - {0x18, 0x18}, - {0x19, 0x50}, - {0x1a, 0xd8}, - {0x1b, 0xf5}, - {0x70, 0x40}, - {0x71, 0x58}, - {0x72, 0x30}, - {0x73, 0x48}, - {0x74, 0x20}, - {0x75, 0x60}, - {0x77, 0x20}, - {0x78, 0x32}, - {0x30, 0x03}, - {0x31, 0x40}, - {0x32, 0x10}, - {0x33, 0xe0}, - {0x34, 0xe0}, - {0x35, 0x00}, - {0x36, 0x80}, - {0x37, 0x00}, - {0x38, 0x04}, - {0x39, 0x09}, - {0x3a, 0x12}, - {0x3b, 0x1C}, - {0x3c, 0x28}, - {0x3d, 0x31}, - {0x3e, 0x44}, - {0x3f, 0x57}, - {0x40, 0x6C}, - {0x41, 0x81}, - {0x42, 0x94}, - {0x43, 0xA7}, - {0x44, 0xB8}, - {0x45, 0xD6}, - {0x46, 0xEE}, - {0x47, 0x0d}, - {0x62, 0xf7}, - {0x63, 0x68}, - {0x64, 0xd3}, - {0x65, 0xd3}, - {0x66, 0x60}, - {0xfe, 0x00}, - - {0x01, 0x32}, //frame setting - {0x02, 0x0c}, - {0x0f, 0x01}, - {0xe2, 0x00}, - {0xe3, 0x78}, - {0xe4, 0x00}, - {0xe5, 0xfe}, - {0xe6, 0x01}, - {0xe7, 0xe0}, - {0xe8, 0x01}, - {0xe9, 0xe0}, - {0xea, 0x01}, - {0xeb, 0xe0}, - {0xfe, 0x00}, -}; - -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h deleted file mode 100644 index 7679f07089..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * GC032A driver. - * - */ -#ifndef __GC032A_H__ -#define __GC032A_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int gc032a_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int gc032a_init(sensor_t *sensor); - -#endif // __GC032A_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h deleted file mode 100644 index 5de59d1d26..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_regs.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * GC032A register definitions. - */ -#ifndef __GC032A_REG_REGS_H__ -#define __GC032A_REG_REGS_H__ - -#define SENSOR_ID_HIGH 0XF0 -#define SENSOR_ID_LOW 0XF1 -#define PAD_VB_HIZ_MODE 0XF2 -#define SYNC_OUTPUT 0XF3 -#define I2C_CONFIG 0XF4 -#define PLL_MODE1 0XF7 -#define PLL_MODE2 0XF8 -#define CM_MODE 0XF9 -#define ISP_DIV_MODE 0XFA -#define I2C_DEVICE_ID 0XFB -#define ANALOG_PWC 0XFC -#define ISP_DIV_MODE2 0XFD -#define RESET_RELATED 0XFE // Bit[7]: Software reset - // Bit[6]: cm reset - // Bit[5]: spi reset - // Bit[4]: CISCTL_restart_n - // Bit[3]: PLL_rst - // Bit[2:0]: page select - // 000:page0 - // 001:page1 - // 010:page2 - // 011:page3 - -//----page0----------------------------- -#define P0_EXPOSURE_HIGH 0X03 -#define P0_EXPOSURE_LOW 0X04 -#define P0_HB_HIGH 0X05 -#define P0_HB_LOW 0X06 -#define P0_VB_HIGH 0X07 -#define P0_VB_LOW 0X08 -#define P0_ROW_START_HIGH 0X09 -#define P0_ROW_START_LOW 0X0A -#define P0_COLUMN_START_HIGH 0X0B -#define P0_COLUMN_START_LOW 0X0C -#define P0_WINDOW_HEIGHT_HIGH 0X0D -#define P0_WINDOW_HEIGHT_LOW 0X0E -#define P0_WINDOW_WIDTH_HIGH 0X0F -#define P0_WINDOW_WIDTH_LOW 0X10 -#define P0_SH_DELAY 0X11 -#define P0_VS_ST 0X12 -#define P0_VS_ET 0X13 -#define P0_CISCTL_MODE1 0X17 - -#define P0_BLOCK_ENABLE_1 0X40 -#define P0_AAAA_ENABLE 0X42 -#define P0_SPECIAL_EFFECT 0X43 -#define P0_SYNC_MODE 0X46 -#define P0_GAIN_CODE 0X48 -#define P0_DEBUG_MODE2 0X4C -#define P0_WIN_MODE 0X50 -#define P0_OUT_WIN_Y1_HIGH 0X51 -#define P0_OUT_WIN_Y1_LOW 0X52 -#define P0_OUT_WIN_X1_HIGH 0X53 -#define P0_OUT_WIN_X1_LOW 0X54 -#define P0_OUT_WIN_HEIGHT_HIGH 0X55 -#define P0_OUT_WIN_HEIGHT_LOW 0X56 -#define P0_OUT_WIN_WIDTH_HIGH 0X57 -#define P0_OUT_WIN_WIDTH_LOW 0X58 - -#define P0_GLOBAL_SATURATION 0XD0 -#define P0_SATURATION_CB 0XD1 -#define P0_SATURATION_CR 0XD2 -#define P0_LUMA_CONTRAST 0XD3 -#define P0_CONTRAST_CENTER 0XD4 -#define P0_LUMA_OFFSET 0XD5 -#define P0_FIXED_CB 0XDA -#define P0_FIXED_CR 0XDB - -//----page3----------------------------- -#define P3_IMAGE_WIDTH_LOW 0X5B -#define P3_IMAGE_WIDTH_HIGH 0X5C -#define P3_IMAGE_HEIGHT_LOW 0X5D -#define P3_IMAGE_HEIGHT_HIGH 0X5E - - -#endif //__GC032A_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h deleted file mode 100644 index a19ffc7c6d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc032a_settings.h +++ /dev/null @@ -1,401 +0,0 @@ -#ifndef _GC032A_SETTINGS_H_ -#define _GC032A_SETTINGS_H_ - -#include -#include -#include "esp_attr.h" -#include "gc032a_regs.h" - - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0x0000 - - -/* - * The default register settings, as obtained from OmniVision. There - * is really no making sense of most of these - lots of "reserved" values - * and such. - * - */ -static const uint16_t gc032a_default_regs[][2] = { - /*System*/ - {0xf3, 0xff}, - {0xf5, 0x06}, - {0xf7, 0x01}, - {0xf8, 0x03}, - {0xf9, 0xce}, - {0xfa, 0x00}, - {0xfc, 0x02}, - {0xfe, 0x02}, - {0x81, 0x03}, - - {0xfe, 0x00}, - {0x77, 0x64}, - {0x78, 0x40}, - {0x79, 0x60}, - /*ANALOG & CISCTL*/ - {0xfe, 0x00}, - {0x03, 0x01}, - {0x04, 0xce}, - {0x05, 0x01}, - {0x06, 0xad}, - {0x07, 0x00}, - {0x08, 0x10}, - {0x0a, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x01}, - {0x0e, 0xe8}, // height 488 - {0x0f, 0x02}, - {0x10, 0x88}, // width 648 - {0x17, 0x54}, - {0x19, 0x08}, - {0x1a, 0x0a}, - {0x1f, 0x40}, - {0x20, 0x30}, - {0x2e, 0x80}, - {0x2f, 0x2b}, - {0x30, 0x1a}, - {0xfe, 0x02}, - {0x03, 0x02}, - {0x05, 0xd7}, - {0x06, 0x60}, - {0x08, 0x80}, - {0x12, 0x89}, - - /*blk*/ - {0xfe, 0x00}, - {0x18, 0x02}, - {0xfe, 0x02}, - {0x40, 0x22}, - {0x45, 0x00}, - {0x46, 0x00}, - {0x49, 0x20}, - {0x4b, 0x3c}, - {0x50, 0x20}, - {0x42, 0x10}, - - /*isp*/ - {0xfe, 0x01}, - {0x0a, 0xc5}, - {0x45, 0x00}, - {0xfe, 0x00}, - {0x40, 0xff}, - {0x41, 0x25}, - {0x42, 0xcf}, - {0x43, 0x10}, - {0x44, 0x83}, - {0x46, 0x23}, - {0x49, 0x03}, - {0x52, 0x02}, - {0x54, 0x00}, - {0xfe, 0x02}, - {0x22, 0xf6}, - - /*Shading*/ - {0xfe, 0x01}, - {0xc1, 0x38}, - {0xc2, 0x4c}, - {0xc3, 0x00}, - {0xc4, 0x32}, - {0xc5, 0x24}, - {0xc6, 0x16}, - {0xc7, 0x08}, - {0xc8, 0x08}, - {0xc9, 0x00}, - {0xca, 0x20}, - {0xdc, 0x8a}, - {0xdd, 0xa0}, - {0xde, 0xa6}, - {0xdf, 0x75}, - - /*AWB*/ - {0xfe, 0x01}, - {0x7c, 0x09}, - {0x65, 0x06}, - {0x7c, 0x08}, - {0x56, 0xf4}, - {0x66, 0x0f}, - {0x67, 0x84}, - {0x6b, 0x80}, - {0x6d, 0x12}, - {0x6e, 0xb0}, - {0x86, 0x00}, - {0x87, 0x00}, - {0x88, 0x00}, - {0x89, 0x00}, - {0x8a, 0x00}, - {0x8b, 0x00}, - {0x8c, 0x00}, - {0x8d, 0x00}, - {0x8e, 0x00}, - {0x8f, 0x00}, - {0x90, 0x00}, - {0x91, 0x00}, - {0x92, 0xf4}, - {0x93, 0xd5}, - {0x94, 0x50}, - {0x95, 0x0f}, - {0x96, 0xf4}, - {0x97, 0x2d}, - {0x98, 0x0f}, - {0x99, 0xa6}, - {0x9a, 0x2d}, - {0x9b, 0x0f}, - {0x9c, 0x59}, - {0x9d, 0x2d}, - {0x9e, 0xaa}, - {0x9f, 0x67}, - {0xa0, 0x59}, - {0xa1, 0x00}, - {0xa2, 0x00}, - {0xa3, 0x0a}, - {0xa4, 0x00}, - {0xa5, 0x00}, - {0xa6, 0xd4}, - {0xa7, 0x9f}, - {0xa8, 0x55}, - {0xa9, 0xd4}, - {0xaa, 0x9f}, - {0xab, 0xac}, - {0xac, 0x9f}, - {0xad, 0x55}, - {0xae, 0xd4}, - {0xaf, 0xac}, - {0xb0, 0xd4}, - {0xb1, 0xa3}, - {0xb2, 0x55}, - {0xb3, 0xd4}, - {0xb4, 0xac}, - {0xb5, 0x00}, - {0xb6, 0x00}, - {0xb7, 0x05}, - {0xb8, 0xd6}, - {0xb9, 0x8c}, - - /*CC*/ - {0xfe, 0x01}, - {0xd0, 0x40}, - {0xd1, 0xf8}, - {0xd2, 0x00}, - {0xd3, 0xfa}, - {0xd4, 0x45}, - {0xd5, 0x02}, - - {0xd6, 0x30}, - {0xd7, 0xfa}, - {0xd8, 0x08}, - {0xd9, 0x08}, - {0xda, 0x58}, - {0xdb, 0x02}, - {0xfe, 0x00}, - - /*Gamma*/ - {0xfe, 0x00}, - {0xba, 0x00}, - {0xbb, 0x04}, - {0xbc, 0x0a}, - {0xbd, 0x0e}, - {0xbe, 0x22}, - {0xbf, 0x30}, - {0xc0, 0x3d}, - {0xc1, 0x4a}, - {0xc2, 0x5d}, - {0xc3, 0x6b}, - {0xc4, 0x7a}, - {0xc5, 0x85}, - {0xc6, 0x90}, - {0xc7, 0xa5}, - {0xc8, 0xb5}, - {0xc9, 0xc2}, - {0xca, 0xcc}, - {0xcb, 0xd5}, - {0xcc, 0xde}, - {0xcd, 0xea}, - {0xce, 0xf5}, - {0xcf, 0xff}, - - /*Auto Gamma*/ - {0xfe, 0x00}, - {0x5a, 0x08}, - {0x5b, 0x0f}, - {0x5c, 0x15}, - {0x5d, 0x1c}, - {0x5e, 0x28}, - {0x5f, 0x36}, - {0x60, 0x45}, - {0x61, 0x51}, - {0x62, 0x6a}, - {0x63, 0x7d}, - {0x64, 0x8d}, - {0x65, 0x98}, - {0x66, 0xa2}, - {0x67, 0xb5}, - {0x68, 0xc3}, - {0x69, 0xcd}, - {0x6a, 0xd4}, - {0x6b, 0xdc}, - {0x6c, 0xe3}, - {0x6d, 0xf0}, - {0x6e, 0xf9}, - {0x6f, 0xff}, - - /*Gain*/ - {0xfe, 0x00}, - {0x70, 0x50}, - - /*AEC*/ - {0xfe, 0x00}, - {0x4f, 0x01}, - {0xfe, 0x01}, - {0x0d, 0x00}, - {0x12, 0xa0}, - {0x13, 0x3a}, - {0x44, 0x04}, - {0x1f, 0x30}, - {0x20, 0x40}, - {0x26, 0x9a}, - {0x3e, 0x20}, - {0x3f, 0x2d}, - {0x40, 0x40}, - {0x41, 0x5b}, - {0x42, 0x82}, - {0x43, 0xb7}, - {0x04, 0x0a}, - {0x02, 0x79}, - {0x03, 0xc0}, - - /*measure window*/ - {0xfe, 0x01}, - {0xcc, 0x08}, - {0xcd, 0x08}, - {0xce, 0xa4}, - {0xcf, 0xec}, - - /*DNDD*/ - {0xfe, 0x00}, - {0x81, 0xb8}, - {0x82, 0x12}, - {0x83, 0x0a}, - {0x84, 0x01}, - {0x86, 0x50}, - {0x87, 0x18}, - {0x88, 0x10}, - {0x89, 0x70}, - {0x8a, 0x20}, - {0x8b, 0x10}, - {0x8c, 0x08}, - {0x8d, 0x0a}, - - /*Intpee*/ - {0xfe, 0x00}, - {0x8f, 0xaa}, - {0x90, 0x9c}, - {0x91, 0x52}, - {0x92, 0x03}, - {0x93, 0x03}, - {0x94, 0x08}, - {0x95, 0x44}, - {0x97, 0x00}, - {0x98, 0x00}, - - /*ASDE*/ - {0xfe, 0x00}, - {0xa1, 0x30}, - {0xa2, 0x41}, - {0xa4, 0x30}, - {0xa5, 0x20}, - {0xaa, 0x30}, - {0xac, 0x32}, - - /*YCP*/ - {0xfe, 0x00}, - {0xd1, 0x3c}, - {0xd2, 0x3c}, - {0xd3, 0x38}, - {0xd6, 0xf4}, - {0xd7, 0x1d}, - {0xdd, 0x73}, - {0xde, 0x84}, - - /*Banding*/ - {0xfe, 0x00}, - {0x05, 0x01}, - {0x06, 0xad}, - {0x07, 0x00}, - {0x08, 0x10}, - - {0xfe, 0x01}, - {0x25, 0x00}, - {0x26, 0x9a}, - - {0x27, 0x01}, - {0x28, 0xce}, - {0x29, 0x02}, - {0x2a, 0x68}, - {0x2b, 0x02}, - {0x2c, 0x68}, - {0x2d, 0x07}, - {0x2e, 0xd2}, - {0x2f, 0x0b}, - {0x30, 0x6e}, - {0x31, 0x0e}, - {0x32, 0x70}, - {0x33, 0x12}, - {0x34, 0x0c}, - {0x3c, 0x30}, - - /*Analog&Cisctl*/ - {0xfe, 0x00}, - {0x05, 0x01}, - {0x06, 0xa0}, - {0x07, 0x00}, - {0x08, 0x20}, - {0x0a, 0x78}, - {0x0c, 0xa0}, - {0x0d, 0x00}, //window_height [8] - {0x0e, 0xf8}, //window_height [7:0] 248 - {0x0f, 0x01}, //window_width [9:8] - {0x10, 0x48}, //window_width [7:0] 328 - - {0x55, 0x00}, - {0x56, 0xf0}, // 240 - {0x57, 0x01}, - {0x58, 0x40}, // 320 - - /*SPI*/ - {0xfe, 0x03}, - {0x5b, 0x40}, - {0x5c, 0x01}, - {0x5d, 0xf0}, - {0x5e, 0x00}, - - /*AEC*/ - {0xfe, 0x01}, - {0x25, 0x00}, //step - {0x26, 0x63}, - {0x27, 0x01}, - {0x28, 0x29}, - {0x29, 0x01}, - {0x2a, 0x29}, - {0x2b, 0x01}, - {0x2c, 0x29}, - {0x2d, 0x01}, - {0x2e, 0x29}, - {0x2f, 0x01}, - {0x30, 0x29}, - {0x31, 0x01}, - {0x32, 0x29}, - {0x33, 0x01}, - {0x34, 0x29}, - {0x3c, 0x00}, - - /*measure window*/ - {0xfe, 0x01}, - {0xcc, 0x04}, - {0xcd, 0x04}, - {0xce, 0x72}, - {0xcf, 0x52}, - {REGLIST_TAIL, 0x00}, -}; - -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h deleted file mode 100644 index 6c5b60f703..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef __GC2145_H__ -#define __GC2145_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int gc2145_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int gc2145_init(sensor_t *sensor); - -#endif // __GC2145_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h deleted file mode 100644 index b034a16898..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_regs.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * GC2145 register definitions. - */ -#ifndef __GC2145_REG_REGS_H__ -#define __GC2145_REG_REGS_H__ - -#define CHIP_ID_HIGH 0XF0 -#define CHIP_ID_LOW 0XF1 -#define PLL_MODE1 0XF7 -#define PLL_MODE2 0XF8 -#define CM_MODE 0XF9 -#define CLK_DIV_MODE 0XFA -#define RESET_RELATED 0xfe // Bit[7]: Software reset - // Bit[6]: cm reset - // Bit[5]: mipi reset - // Bit[4]: CISCTL_restart_n - // Bit[3]: NA - // Bit[2:0]: page select - // 000:page0 - // 001:page1 - // 010:page2 - // 011:page3 - -//-page0---------------- - -#define P0_EXPOSURE_HIGH 0X03 -#define P0_EXPOSURE_LOW 0X04 -#define P0_HB_HIGH 0X05 -#define P0_HB_LOW 0X06 -#define P0_VB_HIGH 0X07 -#define P0_VB_LOW 0X08 -#define P0_ROW_START_HIGH 0X09 -#define P0_ROW_START_LOW 0X0A -#define P0_COL_START_HIGH 0X0B -#define P0_COL_START_LOW 0X0C - -#define P0_WIN_HEIGHT_HIGH 0X0D -#define P0_WIN_HEIGHT_LOW 0X0E -#define P0_WIN_WIDTH_HIGH 0X0F -#define P0_WIN_WIDTH_LOW 0X10 -#define P0_ANALOG_MODE1 0X17 -#define P0_ANALOG_MODE2 0X18 - -#define P0_SPECIAL_EFFECT 0X83 -#define P0_OUTPUT_FORMAT 0x84 // Format select - // Bit[7]:YUV420 row switch - // Bit[6]:YUV420 col switch - // Bit[7]:YUV420_legacy - // Bit[4:0]:output data mode - // 5’h00 Cb Y Cr Y - // 5’h01 Cr Y Cb Y - // 5’h02 Y Cb Y Cr - // 5’h03 Y Cr Y Cb - // 5’h04 LSC bypass, C/Y - // 5’h05 LSC bypass, Y/C - // 5’h06 RGB 565 - // 5’h0f bypass 10bits - // 5’h17 switch odd/even column /row to controls output Bayer pattern - // 00 RGBG - // 01 RGGB - // 10 BGGR - // 11 GBRG - // 5'h18 DNDD out mode - // 5'h19 LSC out mode - // 5;h1b EEINTP out mode -#define P0_FRAME_START 0X85 -#define P0_SYNC_MODE 0X86 -#define P0_MODULE_GATING 0X88 -#define P0_BYPASS_MODE 0X89 -#define P0_DEBUG_MODE2 0X8C -#define P0_DEBUG_MODE3 0X8D -#define P0_CROP_ENABLE 0X90 -#define P0_OUT_WIN_Y1_HIGH 0X91 -#define P0_OUT_WIN_Y1_LOW 0X92 -#define P0_OUT_WIN_X1_HIGH 0X93 -#define P0_OUT_WIN_X1_LOW 0X94 -#define P0_OUT_WIN_HEIGHT_HIGH 0X95 -#define P0_OUT_WIN_HEIGHT_LOW 0X96 -#define P0_OUT_WIN_WIDTH_HIGH 0X97 -#define P0_OUT_WIN_WIDTH_LOW 0X98 -#define P0_SUBSAMPLE 0X99 -#define P0_SUBSAMPLE_MODE 0X9A - - -#endif // __GC2145_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h deleted file mode 100644 index 879fd53b33..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/gc2145_settings.h +++ /dev/null @@ -1,719 +0,0 @@ - -#include - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0x0000 /* Array end token */ - -static const uint16_t gc2145_default_init_regs[][2] = { - {0xfe, 0xf0}, - {0xfe, 0xf0}, - {0xfe, 0xf0}, - - {0xfc, 0x06}, - {0xf6, 0x00}, - - {0xf7, 0x1d}, //37 //17 //37 //1d//05 - {0xf8, 0x83}, //87 //83 //82 - {0xfa, 0x00}, - {0xf9, 0xfe}, //ff - {0xfd, 0x00}, - {0xc2, 0x00}, - {0xf2, 0x0f}, -////////////////////////////////////////////////////// -//////////////////// Analog & Cisctl //////////////// -////////////////////////////////////////////////////// - {0xfe, 0x00}, - - {0x03, 0x04}, //exp time - {0x04, 0x62}, //exp time - - {0x05, 0x01}, //00 //hb[11:8] - {0x06, 0x3b}, //0b //hb - - {0x09, 0x00}, //row start - {0x0a, 0x00}, // - {0x0b, 0x00}, //col start - {0x0c, 0x00}, - {0x0d, 0x04}, //height - {0x0e, 0xc0}, - {0x0f, 0x06}, //width - {0x10, 0x52}, - - {0x12, 0x2e}, //sh_delay 太短 YUV出图异常 - {0x17, 0x14}, //CISCTL Mode1 [1:0]mirror flip - {0x18, 0x22}, //sdark mode - {0x19, 0x0f}, // AD pipe number - {0x1a, 0x01}, //AD manual switch mode - - {0x1b, 0x4b}, //48 restg Width,SH width - {0x1c, 0x07}, //06 帧率快后,横条纹 //12 //TX Width,Space Width - {0x1d, 0x10}, //double reset - {0x1e, 0x88}, //90//98 //fix 竖线//Analog Mode1,TX high,Coln_r - {0x1f, 0x78}, //78 //38 //18 //Analog Mode2,txlow - {0x20, 0x03}, //07 //Analog Mode3,comv,ad_clk mode - {0x21, 0x40}, //10//20//40 //fix 灯管横条纹 - {0x22, 0xa0}, //d0//f0 //a2 //Vref vpix FPN严重 - {0x24, 0x1e}, - {0x25, 0x01}, //col sel - {0x26, 0x10}, //Analog PGA gain1 - {0x2d, 0x60}, //40//40 //txl drv mode - {0x30, 0x01}, //Analog Mode4 - {0x31, 0x90}, //b0//70 // Analog Mode7 [7:5]rsgh_r灯管横条纹[4:3]isp_g - {0x33, 0x06}, //03//02//01 //EQ_hstart_width - {0x34, 0x01}, -// -/////////////////////////////////////////////////// -//////////////////// ISP reg ////////////////////// -////////////////////////////////////////////////////// - {0x80, 0xff}, //outdoor gamma_en, GAMMA_en, CC_en, EE_en, INTP_en, DN_en, DD_en,LSC_en - {0x81, 0x24}, //26//24 //BLK dither mode, ll_y_en ,skin_en, edge SA, new_skin_mode, autogray_en,ll_gamma_en,BFF test image - {0x82, 0xfa}, //FA //auto_SA, auto_EE, auto_DN, auto_DD, auto_LSC, ABS_en, AWB_en, NA - {0x83, 0x00}, //special_effect - {0x84, 0x02}, //output format - {0x86, 0x03}, //c2 //46 //c2 //sync mode - {0x88, 0x03}, //[1]ctl_auto_gating [0]out_auto_gating - {0x89, 0x03}, //bypass disable - {0x85, 0x30}, //60//frame start cut - {0x8a, 0x00}, //ISP_quiet_mode,close aaa pclk,BLK gate mode,exception,close first pipe clock,close dndd clock,close intp clock,DIV_gatedclk_en - {0x8b, 0x00}, //[7:6]BFF_gate_mode,[5]BLK switch gain,[4]protect exp,[3:2]pipe gate mode,[1]not split sram,[0]dark current update - - {0xb0, 0x55}, //60 //global gain - {0xc3, 0x00}, //[7:4]auto_exp_gamma_th1[11:8],[3:0]auto_exp_gamma_th2[11:8] - {0xc4, 0x80}, //auto_exp_gamma_th1[7:0] into - {0xc5, 0x90}, //auto_exp_gamma_th2[7:0] out //outdoor gamma - {0xc6, 0x38}, //auto_gamma_th1 - {0xc7, 0x40}, //auto_gamma_th2 - - {0xec, 0x06}, //measure window - {0xed, 0x04}, - {0xee, 0x60}, //16 col - {0xef, 0x90}, //8 row - - {0xb6, 0x01}, //[0]aec en - - {0x90, 0x01}, //crop - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, //08 - {0x95, 0x04}, - {0x96, 0xb0}, - {0x97, 0x06}, - {0x98, 0x40}, - -/////////////////////////////////////////////// -/////////// BLK //////////////////////// -/////////////////////////////////////////////// - {0x18, 0x02}, - {0x40, 0x42}, //2b //27 - {0x41, 0x00}, //80 //dark row sel - {0x43, 0x54}, //[7:4]BLK start not smooth [3:0]output start frame - - {0x5e, 0x00}, //00//10 //18 - {0x5f, 0x00}, //00//10 //18 - {0x60, 0x00}, //00//10 //18 - {0x61, 0x00}, //00///10 //18 - {0x62, 0x00}, //00//10 //18 - {0x63, 0x00}, //00//10 //18 - {0x64, 0x00}, //00/10 //18 - {0x65, 0x00}, //00//10 //18 - {0x66, 0x20}, //1e - {0x67, 0x20}, //1e - {0x68, 0x20}, //1e - {0x69, 0x20}, //1e - - - {0x76, 0x00}, //0f - - {0x6a, 0x00}, //06 - {0x6b, 0x00}, //06 - {0x6c, 0x3e}, //06 - {0x6d, 0x3e}, //06 - {0x6e, 0x3f}, //06 - {0x6f, 0x3f}, //06 - {0x70, 0x00}, //06 - {0x71, 0x00}, //06 //manual offset - - {0x76, 0x00}, //1f//add offset - {0x72, 0xf0}, //[7:4]BLK DD th [3:0]BLK various th - {0x7e, 0x3c}, //ndark - {0x7f, 0x00}, - - {0xfe, 0x02}, - {0x48, 0x15}, - {0x49, 0x00}, //04//04 //ASDE OFFSET SLOPE - {0x4b, 0x0b}, //ASDE y OFFSET SLOPE - {0xfe, 0x00}, - -/////////////////////////////////////////////// -/////////// AEC //////////////////////// -/////////////////////////////////////////////// - {0xfe, 0x01}, - - {0x01, 0x04}, //AEC X1 - {0x02, 0xc0}, //AEC X2 - {0x03, 0x04}, //AEC Y1 - {0x04, 0x90}, //AEC Y2 - {0x05, 0x30}, //20 //AEC center X1 - {0x06, 0x90}, //40 //AEC center X2 - {0x07, 0x20}, //30 //AEC center Y1 - {0x08, 0x70}, //60 //AEC center Y2 - - {0x09, 0x00}, //AEC show mode - {0x0a, 0xc2}, //[7]col gain enable - {0x0b, 0x11}, //AEC every N - {0x0c, 0x10}, //AEC_mode3 center weight - {0x13, 0x40}, //2a //AEC Y target - {0x17, 0x00}, //AEC ignore mode - {0x1c, 0x11}, // - {0x1e, 0x61}, // - {0x1f, 0x30}, //40//50 //max pre gain - {0x20, 0x40}, //60//40 //max post gain - {0x22, 0x80}, //AEC outdoor THD - {0x23, 0x20}, //target_Y_low_limit - {0xfe, 0x02}, - {0x0f, 0x04}, //05 - {0xfe, 0x01}, - - {0x12, 0x35}, //35 //[5:4]group_size [3]slope_disable [2]outdoor_enable [0]histogram_enable - {0x15, 0x50}, //target_Y_high_limit - {0x10, 0x31}, //num_thd_high - {0x3e, 0x28}, //num_thd_low - {0x3f, 0xe0}, //luma_thd - {0x40, 0x20}, //luma_slope - {0x41, 0x0f}, //color_diff - - {0xfe, 0x02}, - {0x0f, 0x05}, //max_col_level -/////////////////////////// -////// INTPEE ///////////// -/////////////////////////// - {0xfe, 0x02}, //page2 - {0x90, 0x6c}, //ac //eeintp mode1 - {0x91, 0x03}, //02 ////eeintp mode2 - {0x92, 0xc8}, //44 //low criteria for direction - {0x94, 0x66}, - {0x95, 0xb5}, - {0x97, 0x64}, //78 ////edge effect - {0xa2, 0x11}, //fix direction - {0xfe, 0x00}, - -///////////////////////////// -//////// DNDD/////////////// -///////////////////////////// - {0xfe, 0x02}, - {0x80, 0xc1}, //c1 //[7]share mode [6]skin mode [5]is 5x5 mode [1:0]noise value select 0:2 1:2.5 2:3 3:4 - {0x81, 0x08}, // - {0x82, 0x08}, //signal a 0.6 - {0x83, 0x08}, //04 //signal b 2.5 - - {0x84, 0x0a}, //10 //05 dark_DD_TH - {0x86, 0xf0}, //a0 Y_value_dd_th2 - {0x87, 0x50}, //90 Y_value_dd_th3 - {0x88, 0x15}, //60 Y_value_dd_th4 - - {0x89, 0x50}, //80 // asde th2 - {0x8a, 0x30}, //60 // asde th3 - {0x8b, 0x10}, //30 // asde th4 - -///////////////////////////////////////////////// -///////////// ASDE //////////////////////// -///////////////////////////////////////////////// - {0xfe, 0x01}, //page 1 - {0x21, 0x14}, //luma_value_div_sel(分频,与0xef呈2倍关系,增大1,0xef的值减小1倍) -//ff ef luma_value read_only - - {0xfe, 0x02}, //page2 - {0xa3, 0x40}, //ASDE_low_luma_value_LSC_th_H - {0xa4, 0x20}, //ASDE_low_luma_value_LSC_th_L - - {0xa5, 0x40}, //80 //ASDE_LSC_gain_dec_slope_H - {0xa6, 0x80}, // 80 //ASDE_LSC_gain_dec_slope_L -//ff a7 ASDE_LSC_gain_dec //read only - - {0xab, 0x40}, //50 //ASDE_low_luma_value_OT_th - - {0xae, 0x0c}, //[3]EE1_effect_inc_or_dec_high,[2]EE2_effect_inc_or_dec_high, - //[1]EE1_effect_inc_or_dec_low,[0]EE2_effect_inc_or_dec_low, 1:inc 0:dec - - {0xb3, 0x34}, //44 //ASDE_EE1_effect_slope_low,ASDE_EE2_effect_slope_low - {0xb4, 0x44}, //12 //ASDE_EE1_effect_slope_high,ASDE_EE2_effect_slope_high - - {0xb6, 0x38}, //40//40 //ASDE_auto_saturation_dec_slope - {0xb7, 0x02}, //04 //ASDE_sub_saturation_slope - {0xb9, 0x30}, //[7:0]ASDE_auto_saturation_low_limit - {0x3c, 0x08}, //[3:0]auto gray_dec_slope - {0x3d, 0x30}, //[7:0]auto gray_dec_th - - - {0x4b, 0x0d}, //y offset slope - {0x4c, 0x20}, //y offset limit - - {0xfe, 0x00}, -// -///////////////////gamma1//////////////////// -////Gamma - {0xfe, 0x02}, - {0x10, 0x10}, - {0x11, 0x15}, - {0x12, 0x1a}, - {0x13, 0x1f}, - {0x14, 0x2c}, - {0x15, 0x39}, - {0x16, 0x45}, - {0x17, 0x54}, - {0x18, 0x69}, - {0x19, 0x7d}, - {0x1a, 0x8f}, - {0x1b, 0x9d}, - {0x1c, 0xa9}, - {0x1d, 0xbd}, - {0x1e, 0xcd}, - {0x1f, 0xd9}, - {0x20, 0xe3}, - {0x21, 0xea}, - {0x22, 0xef}, - {0x23, 0xf5}, - {0x24, 0xf9}, - {0x25, 0xff}, - -/////auto gamma///// - {0xfe, 0x02}, - {0x26, 0x0f}, - {0x27, 0x14}, - {0x28, 0x19}, - {0x29, 0x1e}, - {0x2a, 0x27}, - {0x2b, 0x33}, - {0x2c, 0x3b}, - {0x2d, 0x45}, - {0x2e, 0x59}, - {0x2f, 0x69}, - {0x30, 0x7c}, - {0x31, 0x89}, - {0x32, 0x98}, - {0x33, 0xae}, - {0x34, 0xc0}, - {0x35, 0xcf}, - {0x36, 0xda}, - {0x37, 0xe2}, - {0x38, 0xe9}, - {0x39, 0xf3}, - {0x3a, 0xf9}, - {0x3b, 0xff}, - -/////////////////////////////////////////////// -/////////// YCP /////////////////////// -/////////////////////////////////////////////// - {0xfe, 0x02}, - {0xd1, 0x30}, //32 // - {0xd2, 0x30}, //32 // - {0xd3, 0x45}, - {0xdd, 0x14}, //edge sa - {0xde, 0x86}, //asde auto gray - {0xed, 0x01}, // - {0xee, 0x28}, - {0xef, 0x30}, - {0xd8, 0xd8}, //autogray protecy - -//////////////////////////// -//////// LSC 0.8/////////////// -//////////////////////////// - {0xfe, 0x01}, - {0xa1, 0x80}, // center_row - {0xa2, 0x80}, // center_col - {0xa4, 0x00}, // sign of b1 - {0xa5, 0x00}, // sign of b1 - {0xa6, 0x70}, // sign of b4 - {0xa7, 0x00}, // sign of b4 - {0xa8, 0x77}, // sign of b22 - {0xa9, 0x77}, // sign of b22 - {0xaa, 0x1f}, // Q1_b1 of R - {0xab, 0x0d}, // Q1_b1 of G - {0xac, 0x19}, // Q1_b1 of B - {0xad, 0x24}, // Q2_b1 of R - {0xae, 0x0e}, // Q2_b1 of G - {0xaf, 0x1d}, // Q2_b1 of B - {0xb0, 0x12}, // Q3_b1 of R - {0xb1, 0x0c}, // Q3_b1 of G - {0xb2, 0x06}, // Q3_b1 of B - {0xb3, 0x13}, // Q4_b1 of R - {0xb4, 0x10}, // Q4_b1 of G - {0xb5, 0x0c}, // Q4_b1 of B - {0xb6, 0x6a}, // right_b2 of R - {0xb7, 0x46}, // right_b2 of G - {0xb8, 0x40}, // right_b2 of B - {0xb9, 0x0b}, // right_b4 of R - {0xba, 0x04}, // right_b4 of G - {0xbb, 0x00}, // right_b4 of B - {0xbc, 0x53}, // left_b2 of R - {0xbd, 0x37}, // left_b2 of G - {0xbe, 0x2d}, // left_b2 of B - {0xbf, 0x0a}, // left_b4 of R - {0xc0, 0x0a}, // left_b4 of G - {0xc1, 0x14}, // left_b4 of B - {0xc2, 0x34}, // up_b2 of R - {0xc3, 0x22}, // up_b2 of G - {0xc4, 0x18}, // up_b2 of B - {0xc5, 0x23}, // up_b4 of R - {0xc6, 0x0f}, // up_b4 of G - {0xc7, 0x3c}, // up_b4 of B - {0xc8, 0x20}, // down_b2 of R - {0xc9, 0x1f}, // down_b2 of G - {0xca, 0x17}, // down_b2 of B - {0xcb, 0x2d}, // down_b4 of R - {0xcc, 0x12}, // down_b4 of G - {0xcd, 0x20}, // down_b4 of B - {0xd0, 0x61}, // right_up_b22 of R - {0xd1, 0x2f}, // right_up_b22 of G - {0xd2, 0x39}, // right_up_b22 of B - {0xd3, 0x45}, // right_down_b22 of R - {0xd4, 0x2c}, // right_down_b22 of G - {0xd5, 0x21}, // right_down_b22 of B - {0xd6, 0x64}, // left_up_b22 of R - {0xd7, 0x2d}, // left_up_b22 of G - {0xd8, 0x30}, // left_up_b22 of B - {0xd9, 0x42}, // left_down_b22 of R - {0xda, 0x27}, // left_down_b22 of G - {0xdb, 0x13}, // left_down_b22 of B - {0xfe, 0x00}, - -///////////////////////////////////////////////// -///////////// AWB //////////////////////// -///////////////////////////////////////////////// - {0xfe, 0x01}, - - {0x4f, 0x00}, - {0x4f, 0x00}, - {0x4b, 0x01}, - {0x4f, 0x00}, - - - {0x4c, 0x01}, - {0x4d, 0x6f}, - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0x70}, - - {0x4e, 0x02}, - {0x4c, 0x01}, - {0x4d, 0x8f}, - {0x4e, 0x02}, - - {0x4c, 0x01}, - {0x4d, 0x90}, - {0x4e, 0x02}, //light - - - {0x4c, 0x01}, - {0x4d, 0xed}, - {0x4e, 0x33}, //light - {0x4c, 0x01}, - {0x4d, 0xcd}, - {0x4e, 0x33}, //light - {0x4c, 0x01}, - {0x4d, 0xec}, - {0x4e, 0x03}, //light - - {0x4c, 0x01}, - {0x4d, 0x6c}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x6d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x6e}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8c}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0x8e}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xab}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xac}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xad}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xae}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xcb}, - {0x4e, 0x03}, - - {0x4c, 0x01}, - {0x4d, 0xcc}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xce}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xeb}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xec}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xee}, - {0x4e, 0x03}, - {0x4c, 0x02}, - {0x4d, 0x0c}, - {0x4e, 0x03}, - {0x4c, 0x02}, - {0x4d, 0x0d}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xea}, - {0x4e, 0x03}, - {0x4c, 0x01}, - {0x4d, 0xaf}, - {0x4e, 0x03}, //dark - {0x4c, 0x01}, - {0x4d, 0xcf}, - {0x4e, 0x03}, //dark - - {0x4c, 0x01}, - {0x4d, 0xca}, - {0x4e, 0x04}, //light - {0x4c, 0x02}, - {0x4d, 0x0b}, - {0x4e, 0x05}, //light - {0x4c, 0x02}, - {0x4d, 0xc8}, - {0x4e, 0x06}, //light 100lux - {0x4c, 0x02}, - {0x4d, 0xa8}, - - {0x4e, 0x06}, //light - {0x4c, 0x02}, - {0x4d, 0xa9}, - {0x4e, 0x06}, //light - - - {0x4c, 0x02}, - {0x4d, 0x89}, - {0x4e, 0x06}, //400lux - {0x4c, 0x02}, - {0x4d, 0x69}, - {0x4e, 0x06}, //f12 - {0x4c, 0x02}, - {0x4d, 0x6a}, - {0x4e, 0x06}, //f12 - {0x4c, 0x02}, - {0x4d, 0xc7}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xe7}, - {0x4e, 0x07}, //100lux - {0x4c, 0x03}, - {0x4d, 0x07}, - {0x4e, 0x07}, //light - - {0x4c, 0x02}, - {0x4d, 0xe8}, - {0x4e, 0x07}, - {0x4c, 0x02}, - {0x4d, 0xe9}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x08}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x09}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x27}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x28}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x29}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x47}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x48}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x49}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x67}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x68}, - {0x4e, 0x07}, - {0x4c, 0x03}, - {0x4d, 0x69}, - {0x4e, 0x07}, - - {0x4f, 0x01}, - {0xfe, 0x01}, - {0x50, 0x80}, //AWB_PRE_mode - {0x51, 0xa8}, //AWB_pre_THD_min[7:0] - {0x52, 0x57}, //AWB_pre_THD_min[15:8] Dominiate luma 0.25=639c 0.22=57a8 - {0x53, 0x38}, //AWB_pre_THD_min_MIX[7:0] - {0x54, 0xc7}, //AWB_pre_THD_min_MIX[15:8] Mix luma 0.5 - - {0x56, 0x0e}, //AWB_tone mode - {0x58, 0x08}, //AWB_C_num_sel,AWB_D_num_sel - {0x5b, 0x00}, //AWB_mix_mode - - {0x5c, 0x74}, //green_num0[7:0] - {0x5d, 0x8b}, //green_num0[15:8] 0.35 - - {0x61, 0xd3}, //R2G_stand0 - {0x62, 0xb5}, //B2G_stand0 - {0x63, 0x00}, //88//a4 //AWB gray mode [7]enable - {0x65, 0x04}, //AWB margin - - {0x67, 0xb2}, //R2G_stand3[7:0] FF/CWF - {0x68, 0xac}, //B2G_stand3[7:0] - {0x69, 0x00}, //R2G_stand4[9:8] B2G_stand4[9:8] R2G_stand3[9:8] B2G_stand3[9:8] - {0x6a, 0xb2}, //R2G_stand4[7:0] TL84/TL84&CWF - {0x6b, 0xac}, //B2G_stand4[7:0] - {0x6c, 0xb2}, //R2G_stand5[7:0] A - {0x6d, 0xac}, //B2G_stand5[7:0] - {0x6e, 0x40}, //AWB_skin_weight R2G_stand5[9:8] B2G_stand5[9:8] - {0x6f, 0x18}, //AWB_indoor_THD (0x21=17 caculate) - {0x73, 0x00}, //AWB_indoor_mode - - {0x70, 0x10}, //AWB low luma TH - {0x71, 0xe8}, //AWB outdoor TH - {0x72, 0xc0}, //outdoor mode - {0x74, 0x01}, //[2:0]AWB skip mode 2x2,4x4,4x8,8x8 - {0x75, 0x01}, //[1:0]AWB_every_N - {0x7f, 0x08}, //[3]gray world frame start - - {0x76, 0x70}, //R limit - {0x77, 0x58}, //G limit - {0x78, 0xa0}, //d8 //B limit - - {0xfe, 0x00}, -// -////////////////////////////////////////// -/////////// CC //////////////////////// -////////////////////////////////////////// - {0xfe, 0x02}, - - {0xc0, 0x01}, //[5:4] CC mode [0]CCT enable - - {0xC1, 0x50}, //D50/D65 - {0xc2, 0xF9}, - {0xc3, 0x00}, //0 - {0xc4, 0xe8}, //e0 - {0xc5, 0x48}, - {0xc6, 0xf0}, - - - {0xC7, 0x50}, - {0xc8, 0xf2}, - {0xc9, 0x00}, - {0xcA, 0xE0}, - {0xcB, 0x45}, - {0xcC, 0xec}, - - {0xCd, 0x45}, - {0xce, 0xf0}, - {0xcf, 0x00}, - {0xe3, 0xf0}, - {0xe4, 0x45}, - {0xe5, 0xe8}, - - - {0xfe, 0x00}, - - {0xf2, 0x0f}, - - -//////////////frame rate 50Hz - {0xfe, 0x00}, - - {0xf7, 0x1d}, - {0xf8, 0x84}, - {0xfa, 0x00}, - - {0x05, 0x01}, //hb - {0x06, 0x3b}, - {0x07, 0x01}, //Vb - {0x08, 0x0b}, - - {0xfe, 0x01}, - {0x25, 0x01}, - {0x26, 0x32}, //step - {0x27, 0x03}, //8.15fps - {0x28, 0x96}, - {0x29, 0x03}, //8.15fps - {0x2a, 0x96}, - {0x2b, 0x03}, //8.15fps - {0x2c, 0x96}, - {0x2d, 0x04}, //8.15fps - {0x2e, 0x62}, - {0x3c, 0x00}, - {0xfe, 0x00}, - -/////////dark sun////// - {0xfe, 0x00}, - {0x18, 0x22}, - {0xfe, 0x02}, - {0x40, 0xbf}, - {0x46, 0xcf}, - {0xfe, 0x00}, - - {0xfe, 0x00}, - - {0xf7, 0x1d}, - {0xf8, 0x84}, - {0xfa, 0x10}, - - {0x05, 0x01}, //hb - {0x06, 0x18}, - {0x07, 0x00}, //Vb - {0x08, 0x2e}, - - {0xfe, 0x01}, - {0x25, 0x00}, - {0x26, 0xa2}, //step - {0x27, 0x01}, - {0x28, 0xe6}, - {0x29, 0x01}, - {0x2a, 0xe6}, - {0x2b, 0x01}, - {0x2c, 0xe6}, - {0x2d, 0x04}, // AEC_exp_level4[12:8] - {0x2e, 0x62}, // AEC_exp_level4[7:0] - {0x3c, 0x00}, - {0xfe, 0x00}, - - {0x09, 0x01}, //row start - {0x0a, 0xd0}, // - {0x0b, 0x02}, //col start - {0x0c, 0x70}, - {0x0d, 0x01}, //height - {0x0e, 0x00}, - {0x0f, 0x01}, //width - {0x10, 0x50}, - - {0x90, 0x01}, //crop - {0x91, 0x00}, - {0x92, 0x00}, - {0x93, 0x00}, - {0x94, 0x00}, - {0x95, 0x00}, - {0x96, 0xf0}, - {0x97, 0x01}, - {0x98, 0x40}, - - - {REGLIST_TAIL, 0x00}, -}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h deleted file mode 100644 index 8b0c562b94..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * NT99141 driver. - * - */ -#ifndef __NT99141_H__ -#define __NT99141_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int nt99141_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int nt99141_init(sensor_t *sensor); - -#endif // __NT99141_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h deleted file mode 100644 index 8301db901a..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_regs.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * NT99141 register definitions. - */ -#ifndef __NT99141_REG_REGS_H__ -#define __NT99141_REG_REGS_H__ - -/* system control registers */ -#define SYSTEM_CTROL0 0x3021 // Bit[7]: Software reset - // Bit[6]: Software power down - // Bit[5]: Reserved - // Bit[4]: SRB clock SYNC enable - // Bit[3]: Isolation suspend select - // Bit[2:0]: Not used - -/* output format control registers */ -#define FORMAT_CTRL 0x501F // Format select - // Bit[2:0]: - // 000: YUV422 - // 001: RGB - // 010: Dither - // 011: RAW after DPC - // 101: RAW after CIP - -/* format control registers */ -#define FORMAT_CTRL00 0x4300 - -/* frame control registers */ -#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // Bit[3:0]: Frame ON number -#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // BIT[3:0]: Frame OFF number - -/* ISP top control registers */ -#define PRE_ISP_TEST_SETTING_1 0x3025 // Bit[7]: Test enable - // 0: Test disable - // 1: Color bar enable - // Bit[6]: Rolling - // Bit[5]: Transparent - // Bit[4]: Square black and white - // Bit[3:2]: Color bar style - // 00: Standard 8 color bar - // 01: Gradual change at vertical mode 1 - // 10: Gradual change at horizontal - // 11: Gradual change at vertical mode 2 - // Bit[1:0]: Test select - // 00: Color bar - // 01: Random data - // 10: Square data - // 11: Black image - -//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW - -/* AEC/AGC control functions */ -#define AEC_PK_MANUAL 0x3201 // AEC Manual Mode Control - // Bit[7:6]: Reserved - // Bit[5]: Gain delay option - // Valid when 0x3503[4]=1’b0 - // 0: Delay one frame latch - // 1: One frame latch - // Bit[4:2]: Reserved - // Bit[1]: AGC manual - // 0: Auto enable - // 1: Manual enable - // Bit[0]: AEC manual - // 0: Auto enable - // 1: Manual enable - -//gain = {0x350A[1:0], 0x350B[7:0]} / 16 - -/* mirror and flip registers */ -#define TIMING_TC_REG20 0x3022 // Timing Control Register - // Bit[2:1]: Vertical flip enable - // 00: Normal - // 11: Vertical flip - // Bit[0]: Vertical binning enable -#define TIMING_TC_REG21 0x3022 // Timing Control Register - // Bit[5]: Compression Enable - // Bit[2:1]: Horizontal mirror enable - // 00: Normal - // 11: Horizontal mirror - // Bit[0]: Horizontal binning enable - -#define CLOCK_POL_CONTROL 0x3024// Bit[5]: PCLK polarity 0: active low - // 1: active high - // Bit[3]: Gate PCLK under VSYNC - // Bit[2]: Gate PCLK under HREF - // Bit[1]: HREF polarity - // 0: active low - // 1: active high - // Bit[0] VSYNC polarity - // 0: active low - // 1: active high -#define DRIVE_CAPABILITY 0x306a // Bit[7:6]: - // 00: 1x - // 01: 2x - // 10: 3x - // 11: 4x - - -#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] -#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] -#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] -#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] -#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] -#define X_ADDR_END_L 0x3805 //Bit[7:0]: -#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] -#define Y_ADDR_END_L 0x3807 //Bit[7:0]: -// Size after scaling -#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] -#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: -#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] -#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: -#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] -#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: -#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] -#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: -#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] -#define X_OFFSET_L 0x3811 //Bit[7:0]: -#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] -#define Y_OFFSET_L 0x3813 //Bit[7:0]: -#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment - //Bit[3:0]: Horizontal even subsample increment -#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment - //Bit[3:0]: Vertical even subsample increment -// Size before scaling -//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) -//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) - -#define ISP_CONTROL_01 0x3021 // Bit[5]: Scale enable - // 0: Disable - // 1: Enable - -#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - // Bit[2:0]: VDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - -#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits -#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits -#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits -#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits -#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset - -#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual -#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable - // 0: Auto - // 1: Manual by PCLK_RATIO - -#define VFIFO_X_SIZE_H 0x4602 -#define VFIFO_X_SIZE_L 0x4603 -#define VFIFO_Y_SIZE_H 0x4604 -#define VFIFO_Y_SIZE_L 0x4605 - -#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass -#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier -#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control - // Bit[3:0]: PLLS system divider -#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider - // 00: 1 - // 01: 1.5 - // 10: 2 - // 11: 3 - // Bit[2]: PLLS root-divider - 1 - // Bit[1:0]: PLLS seld5 - // 00: 1 - // 01: 1 - // 10: 2 - // 11: 2.5 - -#define COMPRESSION_CTRL00 0x4400 // -#define COMPRESSION_CTRL01 0x4401 // -#define COMPRESSION_CTRL02 0x4402 // -#define COMPRESSION_CTRL03 0x4403 // -#define COMPRESSION_CTRL04 0x4404 // -#define COMPRESSION_CTRL05 0x4405 // -#define COMPRESSION_CTRL06 0x4406 // -#define COMPRESSION_CTRL07 0x3401 // Bit[5:0]: QS -#define COMPRESSION_ISI_CTRL 0x4408 // -#define COMPRESSION_CTRL09 0x4409 // -#define COMPRESSION_CTRL0a 0x440a // -#define COMPRESSION_CTRL0b 0x440b // -#define COMPRESSION_CTRL0c 0x440c // -#define COMPRESSION_CTRL0d 0x440d // -#define COMPRESSION_CTRL0E 0x440e // - -/** - * @brief register value - */ -#define TEST_COLOR_BAR 0x02 /* Enable Color Bar roling Test */ - -#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ -#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ - -#define TIMING_TC_REG20_VFLIP 0x01 /* Vertical flip enable */ -#define TIMING_TC_REG21_HMIRROR 0x02 /* Horizontal mirror enable */ - -#endif // __NT99141_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h deleted file mode 100644 index 1ffec20539..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/nt99141_settings.h +++ /dev/null @@ -1,825 +0,0 @@ -#ifndef _NT99141_SETTINGS_H_ -#define _NT99141_SETTINGS_H_ - -#include -#include -#include "esp_attr.h" -#include "nt99141_regs.h" - -static const ratio_settings_t ratio_table[] = { - // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty - { 1280, 720, 0, 4, 1283, 723, 0, 4, 1660, 963 }, - -}; - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0x0000 - -static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { - //initial -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x3109, 0x04}, -{0x3040, 0x04}, -{0x3041, 0x02}, -{0x3042, 0xFF}, -{0x3043, 0x08}, -{0x3052, 0xE0}, -{0x305F, 0x33}, -{0x3100, 0x07}, -{0x3106, 0x03}, -{0x3105, 0x01}, -{0x3108, 0x05}, -{0x3110, 0x22}, -{0x3111, 0x57}, -{0x3112, 0x22}, -{0x3113, 0x55}, -{0x3114, 0x05}, -{0x3135, 0x00}, -{0x32F0, 0x01}, -{0x3290, 0x01}, -{0x3291, 0x80}, -{0x3296, 0x01}, -{0x3297, 0x73}, -{0x3250, 0x80}, -{0x3251, 0x03}, -{0x3252, 0xFF}, -{0x3253, 0x00}, -{0x3254, 0x03}, -{0x3255, 0xFF}, -{0x3256, 0x00}, -{0x3257, 0x50}, -{0x3270, 0x00}, -{0x3271, 0x0C}, -{0x3272, 0x18}, -{0x3273, 0x32}, -{0x3274, 0x44}, -{0x3275, 0x54}, -{0x3276, 0x70}, -{0x3277, 0x88}, -{0x3278, 0x9D}, -{0x3279, 0xB0}, -{0x327A, 0xCF}, -{0x327B, 0xE2}, -{0x327C, 0xEF}, -{0x327D, 0xF7}, -{0x327E, 0xFF}, -{0x3302, 0x00}, -{0x3303, 0x40}, -{0x3304, 0x00}, -{0x3305, 0x96}, -{0x3306, 0x00}, -{0x3307, 0x29}, -{0x3308, 0x07}, -{0x3309, 0xBA}, -{0x330A, 0x06}, -{0x330B, 0xF5}, -{0x330C, 0x01}, -{0x330D, 0x51}, -{0x330E, 0x01}, -{0x330F, 0x30}, -{0x3310, 0x07}, -{0x3311, 0x16}, -{0x3312, 0x07}, -{0x3313, 0xBA}, -{0x3326, 0x02}, -{0x32F6, 0x0F}, -{0x32F9, 0x42}, -{0x32FA, 0x24}, -{0x3325, 0x4A}, -{0x3330, 0x00}, -{0x3331, 0x0A}, -{0x3332, 0xFF}, -{0x3338, 0x30}, -{0x3339, 0x84}, -{0x333A, 0x48}, -{0x333F, 0x07}, -{0x3360, 0x10}, -{0x3361, 0x18}, -{0x3362, 0x1f}, -{0x3363, 0x37}, -{0x3364, 0x80}, -{0x3365, 0x80}, -{0x3366, 0x68}, -{0x3367, 0x60}, -{0x3368, 0x30}, -{0x3369, 0x28}, -{0x336A, 0x20}, -{0x336B, 0x10}, -{0x336C, 0x00}, -{0x336D, 0x20}, -{0x336E, 0x1C}, -{0x336F, 0x18}, -{0x3370, 0x10}, -{0x3371, 0x38}, -{0x3372, 0x3C}, -{0x3373, 0x3F}, -{0x3374, 0x3F}, -{0x338A, 0x34}, -{0x338B, 0x7F}, -{0x338C, 0x10}, -{0x338D, 0x23}, -{0x338E, 0x7F}, -{0x338F, 0x14}, -{0x3375, 0x08}, -{0x3376, 0x0C}, -{0x3377, 0x18}, -{0x3378, 0x20}, -{0x3012, 0x02}, -{0x3013, 0xD0}, -{0x3025, 0x02}, //colorbar -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { - {0x32F0, 0x70}, // YUV422 - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { - {0x32F0, 0x50}, // RAW - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { - {0x32F1, 0x01}, - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { - {0x32F0, 0x00}, // YUV422 - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { - {0x32F0, 0x01}, // RGB - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint8_t sensor_saturation_levels[9][1] = { - {0x60},//-4 - {0x68},//-3 - {0x70},//-2 - {0x78},//-1 - {0x80},//0 - {0x88},//+1 - {0x90},//+2 - {0x98},//+3 - {0xA0},//+4 -}; - -static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { - {0x00, 0x80, 0x80, 0x01},//Normal - {0x03, 0x80, 0x80, 0x01},//Negative - {0x01, 0x80, 0x80, 0x01},//Grayscale - {0x05, 0x2A, 0xF0, 0x01},//Red Tint - {0x05, 0x60, 0x20, 0x01},//Green Tint - {0x05, 0xF0, 0x80, 0x01},//Blue Tint - {0x02, 0x80, 0x80, 0x01},//Sepia - -}; - -// AE LEVEL -static const DRAM_ATTR uint16_t sensor_ae_level[][2] = { - -// 1. [AE_Target : 0x24] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x29 }, - {0x32B9, 0x1F }, - {0x32BC, 0x24 }, - {0x32BD, 0x27 }, - {0x32BE, 0x21 }, -//------------------------------------------------------------------------ -// 2. [AE_Target : 0x28] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x2D }, - {0x32B9, 0x23 }, - {0x32BC, 0x28 }, - {0x32BD, 0x2B }, - {0x32BE, 0x25 }, -//------------------------------------------------------------------------ -// 3. [AE_Target : 0x2C] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x32 }, - {0x32B9, 0x26 }, - {0x32BC, 0x2C }, - {0x32BD, 0x2F }, - {0x32BE, 0x29 }, -//------------------------------------------------------------------------ -// 4, [AE_Target : 0x30] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x36 }, - {0x32B9, 0x2A }, - {0x32BC, 0x30 }, - {0x32BD, 0x33 }, - {0x32BE, 0x2D }, -//------------------------------------------------------------------------ -// 5. [AE_Target : 0x34] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x3B }, - {0x32B9, 0x2D }, - {0x32BC, 0x34 }, - {0x32BD, 0x38 }, - {0x32BE, 0x30 }, -//------------------------------------------------------------------------ -// 6. [AE_Target : 0x38] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x3F }, - {0x32B9, 0x31 }, - {0x32BC, 0x38 }, - {0x32BD, 0x3C }, - {0x32BE, 0x34 }, -//------------------------------------------------------------------------ -// 7. [AE_Target : 0x3D] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x44 }, - {0x32B9, 0x34 }, - {0x32BC, 0x3C }, - {0x32BD, 0x40 }, - {0x32BE, 0x38 }, -//------------------------------------------------------------------------ -// 8. [AE_Target : 0x40] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x48 }, - {0x32B9, 0x38 }, - {0x32BC, 0x40 }, - {0x32BD, 0x44 }, - {0x32BE, 0x3C }, -//------------------------------------------------------------------------ -// 9. [AE_Target : 0x44] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 - {0x32B8, 0x4D }, - {0x32B9, 0x3B }, - {0x32BC, 0x44 }, - {0x32BD, 0x49 }, - {0x32BE, 0x3F }, -}; - -static const DRAM_ATTR uint16_t sensor_framesize_HD[][2] = { -//[JPEG_1280x720_8.18_8.18_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x3C}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x5E}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x24}, -{0x3002, 0x00}, -{0x3003, 0x04}, -{0x3004, 0x00}, -{0x3005, 0x04}, -{0x3006, 0x05}, -{0x3007, 0x03}, -{0x3008, 0x02}, -{0x3009, 0xD3}, -{0x300A, 0x06}, -{0x300B, 0x7C}, -{0x300C, 0x02}, -{0x300D, 0xE0}, -{0x300E, 0x05}, -{0x300F, 0x00}, -{0x3010, 0x02}, -{0x3011, 0xD0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x3F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_VGA[][2] = { -//[JPEG_640x480_10.14_10.14_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x4B}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x62}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x32E0, 0x02}, -{0x32E1, 0x80}, -{0x32E2, 0x01}, -{0x32E3, 0xE0}, -{0x32E4, 0x00}, -{0x32E5, 0x80}, -{0x32E6, 0x00}, -{0x32E7, 0x80}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x24}, -{0x3002, 0x00}, -{0x3003, 0xA4}, -{0x3004, 0x00}, -{0x3005, 0x04}, -{0x3006, 0x04}, -{0x3007, 0x63}, -{0x3008, 0x02}, -{0x3009, 0xD3}, -{0x300A, 0x05}, -{0x300B, 0x3C}, -{0x300C, 0x02}, -{0x300D, 0xE0}, -{0x300E, 0x03}, -{0x300F, 0xC0}, -{0x3010, 0x02}, -{0x3011, 0xD0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x7F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_QVGA[][2] = { -//[JPEG_320x240_10.14_10.14_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x4B}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x62}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x32E0, 0x01}, -{0x32E1, 0x40}, -{0x32E2, 0x00}, -{0x32E3, 0xF0}, -{0x32E4, 0x02}, -{0x32E5, 0x02}, -{0x32E6, 0x02}, -{0x32E7, 0x03}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x24}, -{0x3002, 0x00}, -{0x3003, 0xA4}, -{0x3004, 0x00}, -{0x3005, 0x04}, -{0x3006, 0x04}, -{0x3007, 0x63}, -{0x3008, 0x02}, -{0x3009, 0xD3}, -{0x300A, 0x05}, -{0x300B, 0x3C}, -{0x300C, 0x02}, -{0x300D, 0xE0}, -{0x300E, 0x03}, -{0x300F, 0xC0}, -{0x3010, 0x02}, -{0x3011, 0xD0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x7F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_VGA_xyskip[][2] = { -// [JPEG_640x360_20.00_25.01_Fps_XY_Skip] -// Set_Device_Format = FORMAT_16_8 -// SET_Device_Addr = 0x54 -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60 }, -{0x320A, 0xB2 }, -{0x32C0, 0x64 }, -{0x32C1, 0x64 }, -{0x32C2, 0x64 }, -{0x32C3, 0x00 }, -{0x32C4, 0x20 }, -{0x32C5, 0x20 }, -{0x32C6, 0x20 }, -{0x32C7, 0x00 }, -{0x32C8, 0x62 }, -{0x32C9, 0x64 }, -{0x32CA, 0x84 }, -{0x32CB, 0x84 }, -{0x32CC, 0x84 }, -{0x32CD, 0x84 }, -{0x32DB, 0x68 }, -{0x32F0, 0x70 }, -{0x3400, 0x08 }, -{0x3400, 0x00 }, -{0x3401, 0x4E }, -{0x3404, 0x00 }, -{0x3405, 0x00 }, -{0x3410, 0x00 }, -{0x3200, 0x3E }, -{0x3201, 0x0F }, -{0x3028, 0x0F }, -{0x3029, 0x00 }, -{0x302A, 0x08 }, -{0x3022, 0x24 }, -{0x3023, 0x6C }, -{0x3002, 0x00 }, -{0x3003, 0x04 }, -{0x3004, 0x00 }, -{0x3005, 0x04 }, -{0x3006, 0x05 }, -{0x3007, 0x03 }, -{0x3008, 0x02 }, -{0x3009, 0xD3 }, -{0x300A, 0x03 }, -{0x300B, 0xFC }, -{0x300C, 0x01 }, -{0x300D, 0x88 }, -{0x300E, 0x02 }, -{0x300F, 0x80 }, -{0x3010, 0x01 }, -{0x3011, 0x68 }, -{0x32B8, 0x3F }, -{0x32B9, 0x31 }, -{0x32BB, 0x87 }, -{0x32BC, 0x38 }, -{0x32BD, 0x3C }, -{0x32BE, 0x34 }, -{0x3201, 0x3F }, -{0x3025, 0x00 }, //normal -{0x3021, 0x06 }, -{0x3400, 0x01 }, -{0x3060, 0x01 }, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_VGA_xskip[][2] = { -//[JPEG_640x480_Xskip_13.32_13.32_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x62}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x68}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x32E0, 0x02}, -{0x32E1, 0x80}, -{0x32E2, 0x01}, -{0x32E3, 0xE0}, -{0x32E4, 0x00}, -{0x32E5, 0x00}, -{0x32E6, 0x00}, -{0x32E7, 0x80}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x2C}, -{0x3002, 0x00}, -{0x3003, 0x04}, -{0x3004, 0x00}, -{0x3005, 0x04}, -{0x3006, 0x05}, -{0x3007, 0x03}, -{0x3008, 0x02}, -{0x3009, 0xD3}, -{0x300A, 0x03}, -{0x300B, 0xFC}, -{0x300C, 0x02}, -{0x300D, 0xE0}, -{0x300E, 0x02}, -{0x300F, 0x80}, -{0x3010, 0x02}, -{0x3011, 0xD0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x7F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_QVGA_xskip[][2] = { -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -//[JPEG_320x240_Xskip_13.32_13.32_Fps] -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x62}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x68}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x32E0, 0x01}, -{0x32E1, 0x40}, -{0x32E2, 0x00}, -{0x32E3, 0xF0}, -{0x32E4, 0x01}, -{0x32E5, 0x01}, -{0x32E6, 0x02}, -{0x32E7, 0x03}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x2C}, -{0x3002, 0x00}, -{0x3003, 0x04}, -{0x3004, 0x00}, -{0x3005, 0x04}, -{0x3006, 0x05}, -{0x3007, 0x03}, -{0x3008, 0x02}, -{0x3009, 0xD3}, -{0x300A, 0x03}, -{0x300B, 0xFC}, -{0x300C, 0x02}, -{0x300D, 0xE0}, -{0x300E, 0x02}, -{0x300F, 0x80}, -{0x3010, 0x02}, -{0x3011, 0xD0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x7F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - - -static const DRAM_ATTR uint16_t sensor_framesize_VGA_crop[][2] = { -//[JPEG_640x480_Crop_19.77_19.77_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x62}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x68}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x24}, -{0x3002, 0x01}, -{0x3003, 0x44}, -{0x3004, 0x00}, -{0x3005, 0x7C}, -{0x3006, 0x03}, -{0x3007, 0xC3}, -{0x3008, 0x02}, -{0x3009, 0x5B}, -{0x300A, 0x03}, -{0x300B, 0xFC}, -{0x300C, 0x01}, -{0x300D, 0xF0}, -{0x300E, 0x02}, -{0x300F, 0x80}, -{0x3010, 0x01}, -{0x3011, 0xE0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x3F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_framesize_QVGA_crop[][2] = { -//[JPEG_320x240_Crop_19.77_19.77_Fps] -{0x3021, 0x00}, -{REG_DLY, 100}, // delay 100ms -{0x32BF, 0x60}, -{0x32C0, 0x5A}, -{0x32C1, 0x5A}, -{0x32C2, 0x5A}, -{0x32C3, 0x00}, -{0x32C4, 0x20}, -{0x32C5, 0x20}, -{0x32C6, 0x20}, -{0x32C7, 0x00}, -{0x32C8, 0x62}, -{0x32C9, 0x5A}, -{0x32CA, 0x7A}, -{0x32CB, 0x7A}, -{0x32CC, 0x7A}, -{0x32CD, 0x7A}, -{0x32DB, 0x68}, -{0x32F0, 0x70}, -{0x3400, 0x08}, -{0x3400, 0x00}, -{0x3401, 0x4E}, -{0x3404, 0x00}, -{0x3405, 0x00}, -{0x3410, 0x00}, -{0x32E0, 0x01}, -{0x32E1, 0x40}, -{0x32E2, 0x00}, -{0x32E3, 0xF0}, -{0x32E4, 0x01}, -{0x32E5, 0x01}, -{0x32E6, 0x01}, -{0x32E7, 0x02}, -{0x3200, 0x3E}, -{0x3201, 0x0F}, -{0x3028, 0x0F}, -{0x3029, 0x00}, -{0x302A, 0x08}, -{0x3022, 0x24}, -{0x3023, 0x24}, -{0x3002, 0x01}, -{0x3003, 0x44}, -{0x3004, 0x00}, -{0x3005, 0x7C}, -{0x3006, 0x03}, -{0x3007, 0xC3}, -{0x3008, 0x02}, -{0x3009, 0x5B}, -{0x300A, 0x03}, -{0x300B, 0xFC}, -{0x300C, 0x01}, -{0x300D, 0xF0}, -{0x300E, 0x02}, -{0x300F, 0x80}, -{0x3010, 0x01}, -{0x3011, 0xE0}, -{0x32B8, 0x3F}, -{0x32B9, 0x31}, -{0x32BB, 0x87}, -{0x32BC, 0x38}, -{0x32BD, 0x3C}, -{0x32BE, 0x34}, -{0x3201, 0x7F}, -{0x3021, 0x06}, -{0x3025, 0x00}, //normal -{0x3400, 0x01}, -{0x3060, 0x01}, -{REGLIST_TAIL, 0x00}, // tail -}; - -#endif - - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h deleted file mode 100644 index 342ab21328..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV2640 driver. - * - */ -#ifndef __OV2640_H__ -#define __OV2640_H__ -#include "sensor.h" -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int ov2640_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int ov2640_init(sensor_t *sensor); - -#endif // __OV2640_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h deleted file mode 100644 index 8f47333fa9..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_regs.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV2640 register definitions. - */ -#ifndef __REG_REGS_H__ -#define __REG_REGS_H__ -/* DSP register bank FF=0x00*/ -#define R_BYPASS 0x05 -#define QS 0x44 -#define CTRLI 0x50 -#define HSIZE 0x51 -#define VSIZE 0x52 -#define XOFFL 0x53 -#define YOFFL 0x54 -#define VHYX 0x55 -#define DPRP 0x56 -#define TEST 0x57 -#define ZMOW 0x5A -#define ZMOH 0x5B -#define ZMHH 0x5C -#define BPADDR 0x7C -#define BPDATA 0x7D -#define CTRL2 0x86 -#define CTRL3 0x87 -#define SIZEL 0x8C -#define HSIZE8 0xC0 -#define VSIZE8 0xC1 -#define CTRL0 0xC2 -#define CTRL1 0xC3 -#define R_DVP_SP 0xD3 -#define IMAGE_MODE 0xDA -#define RESET 0xE0 -#define MS_SP 0xF0 -#define SS_ID 0xF7 -#define SS_CTRL 0xF7 -#define MC_BIST 0xF9 -#define MC_AL 0xFA -#define MC_AH 0xFB -#define MC_D 0xFC -#define P_CMD 0xFD -#define P_STATUS 0xFE -#define BANK_SEL 0xFF - -#define CTRLI_LP_DP 0x80 -#define CTRLI_ROUND 0x40 - -#define CTRL0_AEC_EN 0x80 -#define CTRL0_AEC_SEL 0x40 -#define CTRL0_STAT_SEL 0x20 -#define CTRL0_VFIRST 0x10 -#define CTRL0_YUV422 0x08 -#define CTRL0_YUV_EN 0x04 -#define CTRL0_RGB_EN 0x02 -#define CTRL0_RAW_EN 0x01 - -#define CTRL2_DCW_EN 0x20 -#define CTRL2_SDE_EN 0x10 -#define CTRL2_UV_ADJ_EN 0x08 -#define CTRL2_UV_AVG_EN 0x04 -#define CTRL2_CMX_EN 0x01 - -#define CTRL3_BPC_EN 0x80 -#define CTRL3_WPC_EN 0x40 - -#define R_DVP_SP_AUTO_MODE 0x80 - -#define R_BYPASS_DSP_EN 0x00 -#define R_BYPASS_DSP_BYPAS 0x01 - -#define IMAGE_MODE_Y8_DVP_EN 0x40 -#define IMAGE_MODE_JPEG_EN 0x10 -#define IMAGE_MODE_YUV422 0x00 -#define IMAGE_MODE_RAW10 0x04 -#define IMAGE_MODE_RGB565 0x08 -#define IMAGE_MODE_HREF_VSYNC 0x02 -#define IMAGE_MODE_LBYTE_FIRST 0x01 - -#define RESET_MICROC 0x40 -#define RESET_SCCB 0x20 -#define RESET_JPEG 0x10 -#define RESET_DVP 0x04 -#define RESET_IPU 0x02 -#define RESET_CIF 0x01 - -#define MC_BIST_RESET 0x80 -#define MC_BIST_BOOT_ROM_SEL 0x40 -#define MC_BIST_12KB_SEL 0x20 -#define MC_BIST_12KB_MASK 0x30 -#define MC_BIST_512KB_SEL 0x08 -#define MC_BIST_512KB_MASK 0x0C -#define MC_BIST_BUSY_BIT_R 0x02 -#define MC_BIST_MC_RES_ONE_SH_W 0x02 -#define MC_BIST_LAUNCH 0x01 - - -typedef enum { - BANK_DSP, BANK_SENSOR, BANK_MAX -} ov2640_bank_t; - -/* Sensor register bank FF=0x01*/ -#define GAIN 0x00 -#define COM1 0x03 -#define REG04 0x04 -#define REG08 0x08 -#define COM2 0x09 -#define REG_PID 0x0A -#define REG_VER 0x0B -#define COM3 0x0C -#define COM4 0x0D -#define AEC 0x10 -#define CLKRC 0x11 -#define COM7 0x12 -#define COM8 0x13 -#define COM9 0x14 /* AGC gain ceiling */ -#define COM10 0x15 -#define HSTART 0x17 -#define HSTOP 0x18 -#define VSTART 0x19 -#define VSTOP 0x1A -#define REG_MIDH 0x1C -#define REG_MIDL 0x1D -#define AEW 0x24 -#define AEB 0x25 -#define VV 0x26 -#define REG2A 0x2A -#define FRARL 0x2B -#define ADDVSL 0x2D -#define ADDVSH 0x2E -#define YAVG 0x2F -#define HSDY 0x30 -#define HEDY 0x31 -#define REG32 0x32 -#define ARCOM2 0x34 -#define REG45 0x45 -#define FLL 0x46 -#define FLH 0x47 -#define COM19 0x48 -#define ZOOMS 0x49 -#define COM22 0x4B -#define COM25 0x4E -#define BD50 0x4F -#define BD60 0x50 -#define REG5D 0x5D -#define REG5E 0x5E -#define REG5F 0x5F -#define REG60 0x60 -#define HISTO_LOW 0x61 -#define HISTO_HIGH 0x62 - -#define REG04_DEFAULT 0x28 -#define REG04_HFLIP_IMG 0x80 -#define REG04_VFLIP_IMG 0x40 -#define REG04_VREF_EN 0x10 -#define REG04_HREF_EN 0x08 -#define REG04_SET(x) (REG04_DEFAULT|x) - -#define COM2_STDBY 0x10 -#define COM2_OUT_DRIVE_1x 0x00 -#define COM2_OUT_DRIVE_2x 0x01 -#define COM2_OUT_DRIVE_3x 0x02 -#define COM2_OUT_DRIVE_4x 0x03 - -#define COM3_DEFAULT 0x38 -#define COM3_BAND_50Hz 0x04 -#define COM3_BAND_60Hz 0x00 -#define COM3_BAND_AUTO 0x02 -#define COM3_BAND_SET(x) (COM3_DEFAULT|x) - -#define COM7_SRST 0x80 -#define COM7_RES_UXGA 0x00 /* UXGA */ -#define COM7_RES_SVGA 0x40 /* SVGA */ -#define COM7_RES_CIF 0x20 /* CIF */ -#define COM7_ZOOM_EN 0x04 /* Enable Zoom */ -#define COM7_COLOR_BAR 0x02 /* Enable Color Bar Test */ - -#define COM8_DEFAULT 0xC0 -#define COM8_BNDF_EN 0x20 /* Enable Banding filter */ -#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ -#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ -#define COM8_SET(x) (COM8_DEFAULT|x) - -#define COM9_DEFAULT 0x08 -#define COM9_AGC_GAIN_2x 0x00 /* AGC: 2x */ -#define COM9_AGC_GAIN_4x 0x01 /* AGC: 4x */ -#define COM9_AGC_GAIN_8x 0x02 /* AGC: 8x */ -#define COM9_AGC_GAIN_16x 0x03 /* AGC: 16x */ -#define COM9_AGC_GAIN_32x 0x04 /* AGC: 32x */ -#define COM9_AGC_GAIN_64x 0x05 /* AGC: 64x */ -#define COM9_AGC_GAIN_128x 0x06 /* AGC: 128x */ -#define COM9_AGC_SET(x) (COM9_DEFAULT|(x<<5)) - -#define COM10_HREF_EN 0x80 /* HSYNC changes to HREF */ -#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ -#define COM10_PCLK_FREE 0x20 /* PCLK output option: free running PCLK */ -#define COM10_PCLK_EDGE 0x10 /* Data is updated at the rising edge of PCLK */ -#define COM10_HREF_NEG 0x08 /* HREF negative */ -#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ -#define COM10_HSYNC_NEG 0x01 /* HSYNC negative */ - -#define CTRL1_AWB 0x08 /* Enable AWB */ - -#define VV_AGC_TH_SET(h,l) ((h<<4)|(l&0x0F)) - -#define REG32_UXGA 0x36 -#define REG32_SVGA 0x09 -#define REG32_CIF 0x89 - -#define CLKRC_2X 0x80 -#define CLKRC_2X_UXGA (0x01 | CLKRC_2X) -#define CLKRC_2X_SVGA CLKRC_2X -#define CLKRC_2X_CIF CLKRC_2X - -#endif //__REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h deleted file mode 100644 index f151f0a428..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov2640_settings.h +++ /dev/null @@ -1,485 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef _OV2640_SETTINGS_H_ -#define _OV2640_SETTINGS_H_ - -#include -#include -#include "esp_attr.h" -#include "ov2640_regs.h" - -typedef enum { - OV2640_MODE_UXGA, OV2640_MODE_SVGA, OV2640_MODE_CIF, OV2640_MODE_MAX -} ov2640_sensor_mode_t; - -typedef struct { - union { - struct { - uint8_t pclk_div:7; - uint8_t pclk_auto:1; - }; - uint8_t pclk; - }; - union { - struct { - uint8_t clk_div:6; - uint8_t reserved:1; - uint8_t clk_2x:1; - }; - uint8_t clk; - }; -} ov2640_clk_t; - -typedef struct { - uint16_t offset_x; - uint16_t offset_y; - uint16_t max_x; - uint16_t max_y; -} ov2640_ratio_settings_t; - -static const DRAM_ATTR ov2640_ratio_settings_t ratio_table[] = { - // ox, oy, mx, my - { 0, 0, 1600, 1200 }, //4x3 - { 8, 72, 1584, 1056 }, //3x2 - { 0, 100, 1600, 1000 }, //16x10 - { 0, 120, 1600, 960 }, //5x3 - { 0, 150, 1600, 900 }, //16x9 - { 2, 258, 1596, 684 }, //21x9 - { 50, 0, 1500, 1200 }, //5x4 - { 200, 0, 1200, 1200 }, //1x1 - { 462, 0, 676, 1200 } //9x16 -}; - -// 30fps@24MHz -const DRAM_ATTR uint8_t ov2640_settings_cif[][2] = { - {BANK_SEL, BANK_DSP}, - {0x2c, 0xff}, - {0x2e, 0xdf}, - {BANK_SEL, BANK_SENSOR}, - {0x3c, 0x32}, - {CLKRC, 0x01}, - {COM2, COM2_OUT_DRIVE_3x}, - {REG04, REG04_DEFAULT}, - {COM8, COM8_DEFAULT | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN}, - {COM9, COM9_AGC_SET(COM9_AGC_GAIN_8x)}, - {0x2c, 0x0c}, - {0x33, 0x78}, - {0x3a, 0x33}, - {0x3b, 0xfB}, - {0x3e, 0x00}, - {0x43, 0x11}, - {0x16, 0x10}, - {0x39, 0x92}, - {0x35, 0xda}, - {0x22, 0x1a}, - {0x37, 0xc3}, - {0x23, 0x00}, - {ARCOM2, 0xc0}, - {0x06, 0x88}, - {0x07, 0xc0}, - {COM4, 0x87}, - {0x0e, 0x41}, - {0x4c, 0x00}, - {0x4a, 0x81}, - {0x21, 0x99}, - {AEW, 0x40}, - {AEB, 0x38}, - {VV, VV_AGC_TH_SET(8,2)}, - {0x5c, 0x00}, - {0x63, 0x00}, - {HISTO_LOW, 0x70}, - {HISTO_HIGH, 0x80}, - {0x7c, 0x05}, - {0x20, 0x80}, - {0x28, 0x30}, - {0x6c, 0x00}, - {0x6d, 0x80}, - {0x6e, 0x00}, - {0x70, 0x02}, - {0x71, 0x94}, - {0x73, 0xc1}, - {0x3d, 0x34}, - {0x5a, 0x57}, - {BD50, 0xbb}, - {BD60, 0x9c}, - {COM7, COM7_RES_CIF}, - {HSTART, 0x11}, - {HSTOP, 0x43}, - {VSTART, 0x00}, - {VSTOP, 0x25}, - {REG32, 0x89}, - {0x37, 0xc0}, - {BD50, 0xca}, - {BD60, 0xa8}, - {0x6d, 0x00}, - {0x3d, 0x38}, - {BANK_SEL, BANK_DSP}, - {0xe5, 0x7f}, - {MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL}, - {0x41, 0x24}, - {RESET, RESET_JPEG | RESET_DVP}, - {0x76, 0xff}, - {0x33, 0xa0}, - {0x42, 0x20}, - {0x43, 0x18}, - {0x4c, 0x00}, - {CTRL3, CTRL3_WPC_EN | 0x10 }, - {0x88, 0x3f}, - {0xd7, 0x03}, - {0xd9, 0x10}, - {R_DVP_SP, R_DVP_SP_AUTO_MODE | 0x02}, - {0xc8, 0x08}, - {0xc9, 0x80}, - {BPADDR, 0x00}, - {BPDATA, 0x00}, - {BPADDR, 0x03}, - {BPDATA, 0x48}, - {BPDATA, 0x48}, - {BPADDR, 0x08}, - {BPDATA, 0x20}, - {BPDATA, 0x10}, - {BPDATA, 0x0e}, - {0x90, 0x00}, - {0x91, 0x0e}, - {0x91, 0x1a}, - {0x91, 0x31}, - {0x91, 0x5a}, - {0x91, 0x69}, - {0x91, 0x75}, - {0x91, 0x7e}, - {0x91, 0x88}, - {0x91, 0x8f}, - {0x91, 0x96}, - {0x91, 0xa3}, - {0x91, 0xaf}, - {0x91, 0xc4}, - {0x91, 0xd7}, - {0x91, 0xe8}, - {0x91, 0x20}, - {0x92, 0x00}, - {0x93, 0x06}, - {0x93, 0xe3}, - {0x93, 0x05}, - {0x93, 0x05}, - {0x93, 0x00}, - {0x93, 0x04}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x93, 0x00}, - {0x96, 0x00}, - {0x97, 0x08}, - {0x97, 0x19}, - {0x97, 0x02}, - {0x97, 0x0c}, - {0x97, 0x24}, - {0x97, 0x30}, - {0x97, 0x28}, - {0x97, 0x26}, - {0x97, 0x02}, - {0x97, 0x98}, - {0x97, 0x80}, - {0x97, 0x00}, - {0x97, 0x00}, - {0xa4, 0x00}, - {0xa8, 0x00}, - {0xc5, 0x11}, - {0xc6, 0x51}, - {0xbf, 0x80}, - {0xc7, 0x10}, - {0xb6, 0x66}, - {0xb8, 0xA5}, - {0xb7, 0x64}, - {0xb9, 0x7C}, - {0xb3, 0xaf}, - {0xb4, 0x97}, - {0xb5, 0xFF}, - {0xb0, 0xC5}, - {0xb1, 0x94}, - {0xb2, 0x0f}, - {0xc4, 0x5c}, - {CTRL1, 0xfd}, - {0x7f, 0x00}, - {0xe5, 0x1f}, - {0xe1, 0x67}, - {0xdd, 0x7f}, - {IMAGE_MODE, 0x00}, - {RESET, 0x00}, - {R_BYPASS, R_BYPASS_DSP_EN}, - {0, 0} -}; - -const DRAM_ATTR uint8_t ov2640_settings_to_cif[][2] = { - {BANK_SEL, BANK_SENSOR}, - {COM7, COM7_RES_CIF}, - - //Set the sensor output window - {COM1, 0x0A}, - {REG32, REG32_CIF}, - {HSTART, 0x11}, - {HSTOP, 0x43}, - {VSTART, 0x00}, - {VSTOP, 0x25}, - - //{CLKRC, 0x00}, - {BD50, 0xca}, - {BD60, 0xa8}, - {0x5a, 0x23}, - {0x6d, 0x00}, - {0x3d, 0x38}, - {0x39, 0x92}, - {0x35, 0xda}, - {0x22, 0x1a}, - {0x37, 0xc3}, - {0x23, 0x00}, - {ARCOM2, 0xc0}, - {0x06, 0x88}, - {0x07, 0xc0}, - {COM4, 0x87}, - {0x0e, 0x41}, - {0x4c, 0x00}, - {BANK_SEL, BANK_DSP}, - {RESET, RESET_DVP}, - - //Set the sensor resolution (UXGA, SVGA, CIF) - {HSIZE8, 0x32}, - {VSIZE8, 0x25}, - {SIZEL, 0x00}, - - //Set the image window size >= output size - {HSIZE, 0x64}, - {VSIZE, 0x4a}, - {XOFFL, 0x00}, - {YOFFL, 0x00}, - {VHYX, 0x00}, - {TEST, 0x00}, - - {CTRL2, CTRL2_DCW_EN | 0x1D}, - {CTRLI, CTRLI_LP_DP | 0x00}, - //{R_DVP_SP, 0x08}, - {0, 0} -}; - -const DRAM_ATTR uint8_t ov2640_settings_to_svga[][2] = { - {BANK_SEL, BANK_SENSOR}, - {COM7, COM7_RES_SVGA}, - - //Set the sensor output window - {COM1, 0x0A}, - {REG32, REG32_SVGA}, - {HSTART, 0x11}, - {HSTOP, 0x43}, - {VSTART, 0x00}, - {VSTOP, 0x4b}, - - //{CLKRC, 0x00}, - {0x37, 0xc0}, - {BD50, 0xca}, - {BD60, 0xa8}, - {0x5a, 0x23}, - {0x6d, 0x00}, - {0x3d, 0x38}, - {0x39, 0x92}, - {0x35, 0xda}, - {0x22, 0x1a}, - {0x37, 0xc3}, - {0x23, 0x00}, - {ARCOM2, 0xc0}, - {0x06, 0x88}, - {0x07, 0xc0}, - {COM4, 0x87}, - {0x0e, 0x41}, - {0x42, 0x03}, - {0x4c, 0x00}, - {BANK_SEL, BANK_DSP}, - {RESET, RESET_DVP}, - - //Set the sensor resolution (UXGA, SVGA, CIF) - {HSIZE8, 0x64}, - {VSIZE8, 0x4B}, - {SIZEL, 0x00}, - - //Set the image window size >= output size - {HSIZE, 0xC8}, - {VSIZE, 0x96}, - {XOFFL, 0x00}, - {YOFFL, 0x00}, - {VHYX, 0x00}, - {TEST, 0x00}, - - {CTRL2, CTRL2_DCW_EN | 0x1D}, - {CTRLI, CTRLI_LP_DP | 0x00}, - //{R_DVP_SP, 0x08}, - {0, 0} -}; - -const DRAM_ATTR uint8_t ov2640_settings_to_uxga[][2] = { - {BANK_SEL, BANK_SENSOR}, - {COM7, COM7_RES_UXGA}, - - //Set the sensor output window - {COM1, 0x0F}, - {REG32, REG32_UXGA}, - {HSTART, 0x11}, - {HSTOP, 0x75}, - {VSTART, 0x01}, - {VSTOP, 0x97}, - - //{CLKRC, 0x00}, - {0x3d, 0x34}, - {BD50, 0xbb}, - {BD60, 0x9c}, - {0x5a, 0x57}, - {0x6d, 0x80}, - {0x39, 0x82}, - {0x23, 0x00}, - {0x07, 0xc0}, - {0x4c, 0x00}, - {0x35, 0x88}, - {0x22, 0x0a}, - {0x37, 0x40}, - {ARCOM2, 0xa0}, - {0x06, 0x02}, - {COM4, 0xb7}, - {0x0e, 0x01}, - {0x42, 0x83}, - {BANK_SEL, BANK_DSP}, - {RESET, RESET_DVP}, - - //Set the sensor resolution (UXGA, SVGA, CIF) - {HSIZE8, 0xc8}, - {VSIZE8, 0x96}, - {SIZEL, 0x00}, - - //Set the image window size >= output size - {HSIZE, 0x90}, - {VSIZE, 0x2c}, - {XOFFL, 0x00}, - {YOFFL, 0x00}, - {VHYX, 0x88}, - {TEST, 0x00}, - - {CTRL2, CTRL2_DCW_EN | 0x1d}, - {CTRLI, 0x00}, - //{R_DVP_SP, 0x06}, - {0, 0} -}; - -const DRAM_ATTR uint8_t ov2640_settings_jpeg3[][2] = { - {BANK_SEL, BANK_DSP}, - {RESET, RESET_JPEG | RESET_DVP}, - {IMAGE_MODE, IMAGE_MODE_JPEG_EN | IMAGE_MODE_HREF_VSYNC}, - {0xD7, 0x03}, - {0xE1, 0x77}, - {0xE5, 0x1F}, - {0xD9, 0x10}, - {0xDF, 0x80}, - {0x33, 0x80}, - {0x3C, 0x10}, - {0xEB, 0x30}, - {0xDD, 0x7F}, - {RESET, 0x00}, - {0, 0} -}; - -static const uint8_t ov2640_settings_yuv422[][2] = { - {BANK_SEL, BANK_DSP}, - {RESET, RESET_DVP}, - {IMAGE_MODE, IMAGE_MODE_YUV422}, - {0xD7, 0x01}, - {0xE1, 0x67}, - {RESET, 0x00}, - {0, 0}, -}; - -static const uint8_t ov2640_settings_rgb565[][2] = { - {BANK_SEL, BANK_DSP}, - {RESET, RESET_DVP}, - {IMAGE_MODE, IMAGE_MODE_RGB565}, - {0xD7, 0x03}, - {0xE1, 0x77}, - {RESET, 0x00}, - {0, 0}, -}; - -#define NUM_BRIGHTNESS_LEVELS (5) -static const uint8_t brightness_regs[NUM_BRIGHTNESS_LEVELS + 1][5] = { - {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, - {0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */ - {0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */ - {0x00, 0x04, 0x09, 0x20, 0x00 }, /* 0 */ - {0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */ - {0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */ -}; - -#define NUM_CONTRAST_LEVELS (5) -static const uint8_t contrast_regs[NUM_CONTRAST_LEVELS + 1][7] = { - {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA, BPDATA, BPDATA }, - {0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */ - {0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */ - {0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /* 0 */ - {0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */ - {0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */ -}; - -#define NUM_SATURATION_LEVELS (5) -static const uint8_t saturation_regs[NUM_SATURATION_LEVELS + 1][5] = { - {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, - {0x00, 0x02, 0x03, 0x28, 0x28 }, /* -2 */ - {0x00, 0x02, 0x03, 0x38, 0x38 }, /* -1 */ - {0x00, 0x02, 0x03, 0x48, 0x48 }, /* 0 */ - {0x00, 0x02, 0x03, 0x58, 0x58 }, /* +1 */ - {0x00, 0x02, 0x03, 0x68, 0x68 }, /* +2 */ -}; - -#define NUM_SPECIAL_EFFECTS (7) -static const uint8_t special_effects_regs[NUM_SPECIAL_EFFECTS + 1][5] = { - {BPADDR, BPDATA, BPADDR, BPDATA, BPDATA }, - {0x00, 0X00, 0x05, 0X80, 0X80 }, /* no effect */ - {0x00, 0X40, 0x05, 0X80, 0X80 }, /* negative */ - {0x00, 0X18, 0x05, 0X80, 0X80 }, /* black and white */ - {0x00, 0X18, 0x05, 0X40, 0XC0 }, /* reddish */ - {0x00, 0X18, 0x05, 0X40, 0X40 }, /* greenish */ - {0x00, 0X18, 0x05, 0XA0, 0X40 }, /* blue */ - {0x00, 0X18, 0x05, 0X40, 0XA6 }, /* retro */ -}; - -#define NUM_WB_MODES (4) -static const uint8_t wb_modes_regs[NUM_WB_MODES + 1][3] = { - {0XCC, 0XCD, 0XCE }, - {0x5E, 0X41, 0x54 }, /* sunny */ - {0x65, 0X41, 0x4F }, /* cloudy */ - {0x52, 0X41, 0x66 }, /* office */ - {0x42, 0X3F, 0x71 }, /* home */ -}; - -#define NUM_AE_LEVELS (5) -static const uint8_t ae_levels_regs[NUM_AE_LEVELS + 1][3] = { - { AEW, AEB, VV }, - {0x20, 0X18, 0x60 }, - {0x34, 0X1C, 0x00 }, - {0x3E, 0X38, 0x81 }, - {0x48, 0X40, 0x81 }, - {0x58, 0X50, 0x92 }, -}; - -const uint8_t agc_gain_tbl[31] = { - 0x00, 0x10, 0x18, 0x30, 0x34, 0x38, 0x3C, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E, 0xF0, - 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF -}; - -#endif /* _OV2640_SETTINGS_H_ */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h deleted file mode 100644 index 341d688616..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV3660 driver. - * - */ -#ifndef __OV3660_H__ -#define __OV3660_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int ov3660_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int ov3660_init(sensor_t *sensor); - -#endif // __OV3660_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h deleted file mode 100644 index b5cf30a5b1..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_regs.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * OV3660 register definitions. - */ -#ifndef __OV3660_REG_REGS_H__ -#define __OV3660_REG_REGS_H__ - -/* system control registers */ -#define SYSTEM_CTROL0 0x3008 // Bit[7]: Software reset - // Bit[6]: Software power down - // Bit[5]: Reserved - // Bit[4]: SRB clock SYNC enable - // Bit[3]: Isolation suspend select - // Bit[2:0]: Not used - -/* output format control registers */ -#define FORMAT_CTRL 0x501F // Format select - // Bit[2:0]: - // 000: YUV422 - // 001: RGB - // 010: Dither - // 011: RAW after DPC - // 101: RAW after CIP - -/* format control registers */ -#define FORMAT_CTRL00 0x4300 - -/* frame control registers */ -#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // Bit[3:0]: Frame ON number -#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // BIT[3:0]: Frame OFF number - -/* ISP top control registers */ -#define PRE_ISP_TEST_SETTING_1 0x503D // Bit[7]: Test enable - // 0: Test disable - // 1: Color bar enable - // Bit[6]: Rolling - // Bit[5]: Transparent - // Bit[4]: Square black and white - // Bit[3:2]: Color bar style - // 00: Standard 8 color bar - // 01: Gradual change at vertical mode 1 - // 10: Gradual change at horizontal - // 11: Gradual change at vertical mode 2 - // Bit[1:0]: Test select - // 00: Color bar - // 01: Random data - // 10: Square data - // 11: Black image - -//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW - -/* AEC/AGC control functions */ -#define AEC_PK_MANUAL 0x3503 // AEC Manual Mode Control - // Bit[7:6]: Reserved - // Bit[5]: Gain delay option - // Valid when 0x3503[4]=1’b0 - // 0: Delay one frame latch - // 1: One frame latch - // Bit[4:2]: Reserved - // Bit[1]: AGC manual - // 0: Auto enable - // 1: Manual enable - // Bit[0]: AEC manual - // 0: Auto enable - // 1: Manual enable - -//gain = {0x350A[1:0], 0x350B[7:0]} / 16 - -/* mirror and flip registers */ -#define TIMING_TC_REG20 0x3820 // Timing Control Register - // Bit[2:1]: Vertical flip enable - // 00: Normal - // 11: Vertical flip - // Bit[0]: Vertical binning enable -#define TIMING_TC_REG21 0x3821 // Timing Control Register - // Bit[5]: Compression Enable - // Bit[2:1]: Horizontal mirror enable - // 00: Normal - // 11: Horizontal mirror - // Bit[0]: Horizontal binning enable - -#define CLOCK_POL_CONTROL 0x4740// Bit[5]: PCLK polarity 0: active low - // 1: active high - // Bit[3]: Gate PCLK under VSYNC - // Bit[2]: Gate PCLK under HREF - // Bit[1]: HREF polarity - // 0: active low - // 1: active high - // Bit[0] VSYNC polarity - // 0: active low - // 1: active high -#define DRIVE_CAPABILITY 0x302c // Bit[7:6]: - // 00: 1x - // 01: 2x - // 10: 3x - // 11: 4x - - -#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] -#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] -#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] -#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] -#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] -#define X_ADDR_END_L 0x3805 //Bit[7:0]: -#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] -#define Y_ADDR_END_L 0x3807 //Bit[7:0]: -// Size after scaling -#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] -#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: -#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] -#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: -#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] -#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: -#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] -#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: -#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] -#define X_OFFSET_L 0x3811 //Bit[7:0]: -#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] -#define Y_OFFSET_L 0x3813 //Bit[7:0]: -#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment - //Bit[3:0]: Horizontal even subsample increment -#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment - //Bit[3:0]: Vertical even subsample increment -// Size before scaling -//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) -//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) - -#define ISP_CONTROL_01 0x5001 // Bit[5]: Scale enable - // 0: Disable - // 1: Enable - -#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - // Bit[2:0]: VDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - -#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits -#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits -#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits -#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits -#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset - -#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual -#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable - // 0: Auto - // 1: Manual by PCLK_RATIO - -#define VFIFO_X_SIZE_H 0x4602 -#define VFIFO_X_SIZE_L 0x4603 -#define VFIFO_Y_SIZE_H 0x4604 -#define VFIFO_Y_SIZE_L 0x4605 - -#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass -#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier -#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control - // Bit[3:0]: PLLS system divider -#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider - // 00: 1 - // 01: 1.5 - // 10: 2 - // 11: 3 - // Bit[2]: PLLS root-divider - 1 - // Bit[1:0]: PLLS seld5 - // 00: 1 - // 01: 1 - // 10: 2 - // 11: 2.5 - -#define COMPRESSION_CTRL00 0x4400 // -#define COMPRESSION_CTRL01 0x4401 // -#define COMPRESSION_CTRL02 0x4402 // -#define COMPRESSION_CTRL03 0x4403 // -#define COMPRESSION_CTRL04 0x4404 // -#define COMPRESSION_CTRL05 0x4405 // -#define COMPRESSION_CTRL06 0x4406 // -#define COMPRESSION_CTRL07 0x4407 // Bit[5:0]: QS -#define COMPRESSION_ISI_CTRL 0x4408 // -#define COMPRESSION_CTRL09 0x4409 // -#define COMPRESSION_CTRL0a 0x440a // -#define COMPRESSION_CTRL0b 0x440b // -#define COMPRESSION_CTRL0c 0x440c // -#define COMPRESSION_CTRL0d 0x440d // -#define COMPRESSION_CTRL0E 0x440e // - -/** - * @brief register value - */ -#define TEST_COLOR_BAR 0xC0 /* Enable Color Bar roling Test */ - -#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ -#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ - -#define TIMING_TC_REG20_VFLIP 0x06 /* Vertical flip enable */ -#define TIMING_TC_REG21_HMIRROR 0x06 /* Horizontal mirror enable */ - -#endif // __OV3660_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h deleted file mode 100644 index 97c4e03b66..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov3660_settings.h +++ /dev/null @@ -1,318 +0,0 @@ -#ifndef _OV3660_SETTINGS_H_ -#define _OV3660_SETTINGS_H_ - -#include -#include -#include "esp_attr.h" -#include "ov3660_regs.h" - -static const ratio_settings_t ratio_table[] = { - // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty - { 2048, 1536, 0, 0, 2079, 1547, 16, 6, 2300, 1564 }, //4x3 - { 1920, 1280, 64, 128, 2015, 1419, 16, 6, 2172, 1436 }, //3x2 - { 2048, 1280, 0, 128, 2079, 1419, 16, 6, 2300, 1436 }, //16x10 - { 1920, 1152, 64, 192, 2015, 1355, 16, 6, 2172, 1372 }, //5x3 - { 1920, 1080, 64, 242, 2015, 1333, 16, 6, 2172, 1322 }, //16x9 - { 2048, 880, 0, 328, 2079, 1219, 16, 6, 2300, 1236 }, //21x9 - { 1920, 1536, 64, 0, 2015, 1547, 16, 6, 2172, 1564 }, //5x4 - { 1536, 1536, 256, 0, 1823, 1547, 16, 6, 2044, 1564 }, //1x1 - { 864, 1536, 592, 0, 1487, 1547, 16, 6, 2044, 1564 } //9x16 -}; - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0x0000 - -static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { - {SYSTEM_CTROL0, 0x82}, // software reset - {REG_DLY, 10}, // delay 10ms - - {0x3103, 0x13}, - {SYSTEM_CTROL0, 0x42}, - {0x3017, 0xff}, - {0x3018, 0xff}, - {DRIVE_CAPABILITY, 0xc3}, - {CLOCK_POL_CONTROL, 0x21}, - - {0x3611, 0x01}, - {0x3612, 0x2d}, - - {0x3032, 0x00}, - {0x3614, 0x80}, - {0x3618, 0x00}, - {0x3619, 0x75}, - {0x3622, 0x80}, - {0x3623, 0x00}, - {0x3624, 0x03}, - {0x3630, 0x52}, - {0x3632, 0x07}, - {0x3633, 0xd2}, - {0x3704, 0x80}, - {0x3708, 0x66}, - {0x3709, 0x12}, - {0x370b, 0x12}, - {0x3717, 0x00}, - {0x371b, 0x60}, - {0x371c, 0x00}, - {0x3901, 0x13}, - - {0x3600, 0x08}, - {0x3620, 0x43}, - {0x3702, 0x20}, - {0x3739, 0x48}, - {0x3730, 0x20}, - {0x370c, 0x0c}, - - {0x3a18, 0x00}, - {0x3a19, 0xf8}, - - {0x3000, 0x10}, - {0x3004, 0xef}, - - {0x6700, 0x05}, - {0x6701, 0x19}, - {0x6702, 0xfd}, - {0x6703, 0xd1}, - {0x6704, 0xff}, - {0x6705, 0xff}, - - {0x3c01, 0x80}, - {0x3c00, 0x04}, - {0x3a08, 0x00}, {0x3a09, 0x62}, //50Hz Band Width Step (10bit) - {0x3a0e, 0x08}, //50Hz Max Bands in One Frame (6 bit) - {0x3a0a, 0x00}, {0x3a0b, 0x52}, //60Hz Band Width Step (10bit) - {0x3a0d, 0x09}, //60Hz Max Bands in One Frame (6 bit) - - {0x3a00, 0x3a},//night mode off - {0x3a14, 0x09}, - {0x3a15, 0x30}, - {0x3a02, 0x09}, - {0x3a03, 0x30}, - - {COMPRESSION_CTRL0E, 0x08}, - {0x4520, 0x0b}, - {0x460b, 0x37}, - {0x4713, 0x02}, - {0x471c, 0xd0}, - {0x5086, 0x00}, - - {0x5002, 0x00}, - {0x501f, 0x00}, - - {SYSTEM_CTROL0, 0x02}, - - {0x5180, 0xff}, - {0x5181, 0xf2}, - {0x5182, 0x00}, - {0x5183, 0x14}, - {0x5184, 0x25}, - {0x5185, 0x24}, - {0x5186, 0x16}, - {0x5187, 0x16}, - {0x5188, 0x16}, - {0x5189, 0x68}, - {0x518a, 0x60}, - {0x518b, 0xe0}, - {0x518c, 0xb2}, - {0x518d, 0x42}, - {0x518e, 0x35}, - {0x518f, 0x56}, - {0x5190, 0x56}, - {0x5191, 0xf8}, - {0x5192, 0x04}, - {0x5193, 0x70}, - {0x5194, 0xf0}, - {0x5195, 0xf0}, - {0x5196, 0x03}, - {0x5197, 0x01}, - {0x5198, 0x04}, - {0x5199, 0x12}, - {0x519a, 0x04}, - {0x519b, 0x00}, - {0x519c, 0x06}, - {0x519d, 0x82}, - {0x519e, 0x38}, - - {0x5381, 0x1d}, - {0x5382, 0x60}, - {0x5383, 0x03}, - {0x5384, 0x0c}, - {0x5385, 0x78}, - {0x5386, 0x84}, - {0x5387, 0x7d}, - {0x5388, 0x6b}, - {0x5389, 0x12}, - {0x538a, 0x01}, - {0x538b, 0x98}, - - {0x5480, 0x01}, -// {0x5481, 0x05}, -// {0x5482, 0x09}, -// {0x5483, 0x10}, -// {0x5484, 0x3a}, -// {0x5485, 0x4c}, -// {0x5486, 0x5a}, -// {0x5487, 0x68}, -// {0x5488, 0x74}, -// {0x5489, 0x80}, -// {0x548a, 0x8e}, -// {0x548b, 0xa4}, -// {0x548c, 0xb4}, -// {0x548d, 0xc8}, -// {0x548e, 0xde}, -// {0x548f, 0xf0}, -// {0x5490, 0x15}, - - {0x5000, 0xa7}, - {0x5800, 0x0C}, - {0x5801, 0x09}, - {0x5802, 0x0C}, - {0x5803, 0x0C}, - {0x5804, 0x0D}, - {0x5805, 0x17}, - {0x5806, 0x06}, - {0x5807, 0x05}, - {0x5808, 0x04}, - {0x5809, 0x06}, - {0x580a, 0x09}, - {0x580b, 0x0E}, - {0x580c, 0x05}, - {0x580d, 0x01}, - {0x580e, 0x01}, - {0x580f, 0x01}, - {0x5810, 0x05}, - {0x5811, 0x0D}, - {0x5812, 0x05}, - {0x5813, 0x01}, - {0x5814, 0x01}, - {0x5815, 0x01}, - {0x5816, 0x05}, - {0x5817, 0x0D}, - {0x5818, 0x08}, - {0x5819, 0x06}, - {0x581a, 0x05}, - {0x581b, 0x07}, - {0x581c, 0x0B}, - {0x581d, 0x0D}, - {0x581e, 0x12}, - {0x581f, 0x0D}, - {0x5820, 0x0E}, - {0x5821, 0x10}, - {0x5822, 0x10}, - {0x5823, 0x1E}, - {0x5824, 0x53}, - {0x5825, 0x15}, - {0x5826, 0x05}, - {0x5827, 0x14}, - {0x5828, 0x54}, - {0x5829, 0x25}, - {0x582a, 0x33}, - {0x582b, 0x33}, - {0x582c, 0x34}, - {0x582d, 0x16}, - {0x582e, 0x24}, - {0x582f, 0x41}, - {0x5830, 0x50}, - {0x5831, 0x42}, - {0x5832, 0x15}, - {0x5833, 0x25}, - {0x5834, 0x34}, - {0x5835, 0x33}, - {0x5836, 0x24}, - {0x5837, 0x26}, - {0x5838, 0x54}, - {0x5839, 0x25}, - {0x583a, 0x15}, - {0x583b, 0x25}, - {0x583c, 0x53}, - {0x583d, 0xCF}, - - {0x3a0f, 0x30}, - {0x3a10, 0x28}, - {0x3a1b, 0x30}, - {0x3a1e, 0x28}, - {0x3a11, 0x60}, - {0x3a1f, 0x14}, - - {0x5302, 0x28}, - {0x5303, 0x20}, - - {0x5306, 0x1c}, //de-noise offset 1 - {0x5307, 0x28}, //de-noise offset 2 - - {0x4002, 0xc5}, - {0x4003, 0x81}, - {0x4005, 0x12}, - - {0x5688, 0x11}, - {0x5689, 0x11}, - {0x568a, 0x11}, - {0x568b, 0x11}, - {0x568c, 0x11}, - {0x568d, 0x11}, - {0x568e, 0x11}, - {0x568f, 0x11}, - - {0x5580, 0x06}, - {0x5588, 0x00}, - {0x5583, 0x40}, - {0x5584, 0x2c}, - - {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x30}, // YUYV - {0x3002, 0x00},//0x1c to 0x00 !!! - {0x3006, 0xff},//0xc3 to 0xff !!! - {0x471c, 0x50},//0xd0 to 0x50 !!! - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { - {FORMAT_CTRL00, 0x00}, // RAW - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x10}, // Y8 - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x30}, // YUYV - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { - {FORMAT_CTRL, 0x01}, // RGB - {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { - {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 - {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 - {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 - {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 - {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 - {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 - {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 - {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 - {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 -}; - -static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { - {0x06, 0x40, 0x2c, 0x08},//Normal - {0x46, 0x40, 0x28, 0x08},//Negative - {0x1e, 0x80, 0x80, 0x08},//Grayscale - {0x1e, 0x80, 0xc0, 0x08},//Red Tint - {0x1e, 0x60, 0x60, 0x08},//Green Tint - {0x1e, 0xa0, 0x40, 0x08},//Blue Tint - {0x1e, 0x40, 0xa0, 0x08},//Sepia -}; - -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h deleted file mode 100644 index 120ae72054..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef __OV5640_H__ -#define __OV5640_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int ov5640_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int ov5640_init(sensor_t *sensor); - -#endif // __OV5640_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h deleted file mode 100644 index c28d80f5bb..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_regs.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * OV5640 register definitions. - */ -#ifndef __OV5640_REG_REGS_H__ -#define __OV5640_REG_REGS_H__ - -/* system control registers */ -#define SYSTEM_CTROL0 0x3008 // Bit[7]: Software reset - // Bit[6]: Software power down - // Bit[5]: Reserved - // Bit[4]: SRB clock SYNC enable - // Bit[3]: Isolation suspend select - // Bit[2:0]: Not used - -#define DRIVE_CAPABILITY 0x302c // Bit[7:6]: - // 00: 1x - // 01: 2x - // 10: 3x - // 11: 4x - -#define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass -#define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier -#define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control - // Bit[3:0]: PLLS system divider -#define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider - // 00: 1 - // 01: 1.5 - // 10: 2 - // 11: 3 - // Bit[2]: PLLS root-divider - 1 - // Bit[1:0]: PLLS seld5 - // 00: 1 - // 01: 1 - // 10: 2 - // 11: 2.5 - -/* AEC/AGC control functions */ -#define AEC_PK_MANUAL 0x3503 // AEC Manual Mode Control - // Bit[7:6]: Reserved - // Bit[5]: Gain delay option - // Valid when 0x3503[4]=1’b0 - // 0: Delay one frame latch - // 1: One frame latch - // Bit[4:2]: Reserved - // Bit[1]: AGC manual - // 0: Auto enable - // 1: Manual enable - // Bit[0]: AEC manual - // 0: Auto enable - // 1: Manual enable - -//gain = {0x350A[1:0], 0x350B[7:0]} / 16 - - -#define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] -#define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] -#define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] -#define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] -#define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] -#define X_ADDR_END_L 0x3805 //Bit[7:0]: -#define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] -#define Y_ADDR_END_L 0x3807 //Bit[7:0]: -// Size after scaling -#define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] -#define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: -#define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] -#define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: -#define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] -#define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: -#define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] -#define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: -#define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] -#define X_OFFSET_L 0x3811 //Bit[7:0]: -#define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] -#define Y_OFFSET_L 0x3813 //Bit[7:0]: -#define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment - //Bit[3:0]: Horizontal even subsample increment -#define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment - //Bit[3:0]: Vertical even subsample increment -// Size before scaling -//#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) -//#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) - -/* mirror and flip registers */ -#define TIMING_TC_REG20 0x3820 // Timing Control Register - // Bit[2:1]: Vertical flip enable - // 00: Normal - // 11: Vertical flip - // Bit[0]: Vertical binning enable -#define TIMING_TC_REG21 0x3821 // Timing Control Register - // Bit[5]: Compression Enable - // Bit[2:1]: Horizontal mirror enable - // 00: Normal - // 11: Horizontal mirror - // Bit[0]: Horizontal binning enable - -#define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual - -/* frame control registers */ -#define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // Bit[3:0]: Frame ON number -#define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode - // Bit[7:4]: Not used - // BIT[3:0]: Frame OFF number - -/* format control registers */ -#define FORMAT_CTRL00 0x4300 - -#define CLOCK_POL_CONTROL 0x4740// Bit[5]: PCLK polarity 0: active low - // 1: active high - // Bit[3]: Gate PCLK under VSYNC - // Bit[2]: Gate PCLK under HREF - // Bit[1]: HREF polarity - // 0: active low - // 1: active high - // Bit[0] VSYNC polarity - // 0: active low - // 1: active high - -#define ISP_CONTROL_01 0x5001 // Bit[5]: Scale enable - // 0: Disable - // 1: Enable - -/* output format control registers */ -#define FORMAT_CTRL 0x501F // Format select - // Bit[2:0]: - // 000: YUV422 - // 001: RGB - // 010: Dither - // 011: RAW after DPC - // 101: RAW after CIP - -/* ISP top control registers */ -#define PRE_ISP_TEST_SETTING_1 0x503D // Bit[7]: Test enable - // 0: Test disable - // 1: Color bar enable - // Bit[6]: Rolling - // Bit[5]: Transparent - // Bit[4]: Square black and white - // Bit[3:2]: Color bar style - // 00: Standard 8 color bar - // 01: Gradual change at vertical mode 1 - // 10: Gradual change at horizontal - // 11: Gradual change at vertical mode 2 - // Bit[1:0]: Test select - // 00: Color bar - // 01: Random data - // 10: Square data - // 11: Black image - -//exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW - -#define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - // Bit[2:0]: VDIV RW - // DCW scale times - // 000: DCW 1 time - // 001: DCW 2 times - // 010: DCW 4 times - // 100: DCW 8 times - // 101: DCW 16 times - // Others: DCW 16 times - -#define SCALE_CTRL_2 0x5602 // X_SCALE High Bits -#define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits -#define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits -#define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits -#define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset - -#define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable - // 0: Auto - // 1: Manual by PCLK_RATIO - -#define VFIFO_X_SIZE_H 0x4602 -#define VFIFO_X_SIZE_L 0x4603 -#define VFIFO_Y_SIZE_H 0x4604 -#define VFIFO_Y_SIZE_L 0x4605 - -#define COMPRESSION_CTRL00 0x4400 // -#define COMPRESSION_CTRL01 0x4401 // -#define COMPRESSION_CTRL02 0x4402 // -#define COMPRESSION_CTRL03 0x4403 // -#define COMPRESSION_CTRL04 0x4404 // -#define COMPRESSION_CTRL05 0x4405 // -#define COMPRESSION_CTRL06 0x4406 // -#define COMPRESSION_CTRL07 0x4407 // Bit[5:0]: QS -#define COMPRESSION_ISI_CTRL 0x4408 // -#define COMPRESSION_CTRL09 0x4409 // -#define COMPRESSION_CTRL0a 0x440a // -#define COMPRESSION_CTRL0b 0x440b // -#define COMPRESSION_CTRL0c 0x440c // -#define COMPRESSION_CTRL0d 0x440d // -#define COMPRESSION_CTRL0E 0x440e // - -/** - * @brief register value - */ -#define TEST_COLOR_BAR 0xC0 /* Enable Color Bar roling Test */ - -#define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ -#define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ - -#define TIMING_TC_REG20_VFLIP 0x06 /* Vertical flip enable */ -#define TIMING_TC_REG21_HMIRROR 0x06 /* Horizontal mirror enable */ - -#endif // __OV3660_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h deleted file mode 100644 index f52572fa2b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov5640_settings.h +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef _OV5640_SETTINGS_H_ -#define _OV5640_SETTINGS_H_ - -#include -#include -#include "esp_attr.h" -#include "ov5640_regs.h" - -static const ratio_settings_t ratio_table[] = { - // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty - { 2560, 1920, 0, 0, 2623, 1951, 32, 16, 2844, 1968 }, //4x3 - { 2560, 1704, 0, 110, 2623, 1843, 32, 16, 2844, 1752 }, //3x2 - { 2560, 1600, 0, 160, 2623, 1791, 32, 16, 2844, 1648 }, //16x10 - { 2560, 1536, 0, 192, 2623, 1759, 32, 16, 2844, 1584 }, //5x3 - { 2560, 1440, 0, 240, 2623, 1711, 32, 16, 2844, 1488 }, //16x9 - { 2560, 1080, 0, 420, 2623, 1531, 32, 16, 2844, 1128 }, //21x9 - { 2400, 1920, 80, 0, 2543, 1951, 32, 16, 2684, 1968 }, //5x4 - { 1920, 1920, 320, 0, 2543, 1951, 32, 16, 2684, 1968 }, //1x1 - { 1088, 1920, 736, 0, 1887, 1951, 32, 16, 1884, 1968 } //9x16 -}; - -#define REG_DLY 0xffff -#define REGLIST_TAIL 0x0000 - -static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { - {SYSTEM_CTROL0, 0x82}, // software reset - {REG_DLY, 10}, // delay 10ms - {SYSTEM_CTROL0, 0x42}, // power down - - //enable pll - {0x3103, 0x13}, - - //io direction - {0x3017, 0xff}, - {0x3018, 0xff}, - - {DRIVE_CAPABILITY, 0xc3}, - {CLOCK_POL_CONTROL, 0x21}, - - {0x4713, 0x02},//jpg mode select - - {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE - - //sys reset - {0x3000, 0x20}, // reset MCU - {REG_DLY, 10}, // delay 10ms - {0x3002, 0x1c}, - - //clock enable - {0x3004, 0xff}, - {0x3006, 0xc3}, - - //isp control - {0x5000, 0xa7}, - {ISP_CONTROL_01, 0xa3},//+scaling? - {0x5003, 0x08},//special_effect - - //unknown - {0x370c, 0x02},//!!IMPORTANT - {0x3634, 0x40},//!!IMPORTANT - - //AEC/AGC - {0x3a02, 0x03}, - {0x3a03, 0xd8}, - {0x3a08, 0x01}, - {0x3a09, 0x27}, - {0x3a0a, 0x00}, - {0x3a0b, 0xf6}, - {0x3a0d, 0x04}, - {0x3a0e, 0x03}, - {0x3a0f, 0x30},//ae_level - {0x3a10, 0x28},//ae_level - {0x3a11, 0x60},//ae_level - {0x3a13, 0x43}, - {0x3a14, 0x03}, - {0x3a15, 0xd8}, - {0x3a18, 0x00},//gainceiling - {0x3a19, 0xf8},//gainceiling - {0x3a1b, 0x30},//ae_level - {0x3a1e, 0x26},//ae_level - {0x3a1f, 0x14},//ae_level - - //vcm debug - {0x3600, 0x08}, - {0x3601, 0x33}, - - //50/60Hz - {0x3c01, 0xa4}, - {0x3c04, 0x28}, - {0x3c05, 0x98}, - {0x3c06, 0x00}, - {0x3c07, 0x08}, - {0x3c08, 0x00}, - {0x3c09, 0x1c}, - {0x3c0a, 0x9c}, - {0x3c0b, 0x40}, - - {0x460c, 0x22},//disable jpeg footer - - //BLC - {0x4001, 0x02}, - {0x4004, 0x02}, - - //AWB - {0x5180, 0xff}, - {0x5181, 0xf2}, - {0x5182, 0x00}, - {0x5183, 0x14}, - {0x5184, 0x25}, - {0x5185, 0x24}, - {0x5186, 0x09}, - {0x5187, 0x09}, - {0x5188, 0x09}, - {0x5189, 0x75}, - {0x518a, 0x54}, - {0x518b, 0xe0}, - {0x518c, 0xb2}, - {0x518d, 0x42}, - {0x518e, 0x3d}, - {0x518f, 0x56}, - {0x5190, 0x46}, - {0x5191, 0xf8}, - {0x5192, 0x04}, - {0x5193, 0x70}, - {0x5194, 0xf0}, - {0x5195, 0xf0}, - {0x5196, 0x03}, - {0x5197, 0x01}, - {0x5198, 0x04}, - {0x5199, 0x12}, - {0x519a, 0x04}, - {0x519b, 0x00}, - {0x519c, 0x06}, - {0x519d, 0x82}, - {0x519e, 0x38}, - - //color matrix (Saturation) - {0x5381, 0x1e}, - {0x5382, 0x5b}, - {0x5383, 0x08}, - {0x5384, 0x0a}, - {0x5385, 0x7e}, - {0x5386, 0x88}, - {0x5387, 0x7c}, - {0x5388, 0x6c}, - {0x5389, 0x10}, - {0x538a, 0x01}, - {0x538b, 0x98}, - - //CIP control (Sharpness) - {0x5300, 0x10},//sharpness - {0x5301, 0x10},//sharpness - {0x5302, 0x18},//sharpness - {0x5303, 0x19},//sharpness - {0x5304, 0x10}, - {0x5305, 0x10}, - {0x5306, 0x08},//denoise - {0x5307, 0x16}, - {0x5308, 0x40}, - {0x5309, 0x10},//sharpness - {0x530a, 0x10},//sharpness - {0x530b, 0x04},//sharpness - {0x530c, 0x06},//sharpness - - //GAMMA - {0x5480, 0x01}, - {0x5481, 0x00}, - {0x5482, 0x1e}, - {0x5483, 0x3b}, - {0x5484, 0x58}, - {0x5485, 0x66}, - {0x5486, 0x71}, - {0x5487, 0x7d}, - {0x5488, 0x83}, - {0x5489, 0x8f}, - {0x548a, 0x98}, - {0x548b, 0xa6}, - {0x548c, 0xb8}, - {0x548d, 0xca}, - {0x548e, 0xd7}, - {0x548f, 0xe3}, - {0x5490, 0x1d}, - - //Special Digital Effects (SDE) (UV adjust) - {0x5580, 0x06},//enable brightness and contrast - {0x5583, 0x40},//special_effect - {0x5584, 0x10},//special_effect - {0x5586, 0x20},//contrast - {0x5587, 0x00},//brightness - {0x5588, 0x00},//brightness - {0x5589, 0x10}, - {0x558a, 0x00}, - {0x558b, 0xf8}, - {0x501d, 0x40},// enable manual offset of contrast - - //power on - {0x3008, 0x02}, - - //50Hz - {0x3c00, 0x04}, - - {REG_DLY, 300}, - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x30}, // YUYV - {0x3002, 0x00},//0x1c to 0x00 !!! - {0x3006, 0xff},//0xc3 to 0xff !!! - {0x471c, 0x50},//0xd0 to 0x50 !!! - {REGLIST_TAIL, 0x00}, // tail -}; - -static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { - {FORMAT_CTRL, 0x03}, // RAW (DPC) - {FORMAT_CTRL00, 0x00}, // RAW - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x10}, // Y8 - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { - {FORMAT_CTRL, 0x00}, // YUV422 - {FORMAT_CTRL00, 0x30}, // YUYV - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { - {FORMAT_CTRL, 0x01}, // RGB - {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) - {REGLIST_TAIL, 0x00} -}; - -static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { - {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 - {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 - {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 - {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 - {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 - {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 - {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 - {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 - {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 -}; - -static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { - {0x06, 0x40, 0x2c, 0x08},//Normal - {0x46, 0x40, 0x28, 0x08},//Negative - {0x1e, 0x80, 0x80, 0x08},//Grayscale - {0x1e, 0x80, 0xc0, 0x08},//Red Tint - {0x1e, 0x60, 0x60, 0x08},//Green Tint - {0x1e, 0xa0, 0x40, 0x08},//Blue Tint - {0x1e, 0x40, 0xa0, 0x08},//Sepia -}; - -static const DRAM_ATTR uint16_t sensor_regs_gamma0[][2] = { - {0x5480, 0x01}, - {0x5481, 0x08}, - {0x5482, 0x14}, - {0x5483, 0x28}, - {0x5484, 0x51}, - {0x5485, 0x65}, - {0x5486, 0x71}, - {0x5487, 0x7d}, - {0x5488, 0x87}, - {0x5489, 0x91}, - {0x548a, 0x9a}, - {0x548b, 0xaa}, - {0x548c, 0xb8}, - {0x548d, 0xcd}, - {0x548e, 0xdd}, - {0x548f, 0xea}, - {0x5490, 0x1d} -}; - -static const DRAM_ATTR uint16_t sensor_regs_gamma1[][2] = { - {0x5480, 0x1}, - {0x5481, 0x0}, - {0x5482, 0x1e}, - {0x5483, 0x3b}, - {0x5484, 0x58}, - {0x5485, 0x66}, - {0x5486, 0x71}, - {0x5487, 0x7d}, - {0x5488, 0x83}, - {0x5489, 0x8f}, - {0x548a, 0x98}, - {0x548b, 0xa6}, - {0x548c, 0xb8}, - {0x548d, 0xca}, - {0x548e, 0xd7}, - {0x548f, 0xe3}, - {0x5490, 0x1d} -}; - -static const DRAM_ATTR uint16_t sensor_regs_awb0[][2] = { - {0x5180, 0xff}, - {0x5181, 0xf2}, - {0x5182, 0x00}, - {0x5183, 0x14}, - {0x5184, 0x25}, - {0x5185, 0x24}, - {0x5186, 0x09}, - {0x5187, 0x09}, - {0x5188, 0x09}, - {0x5189, 0x75}, - {0x518a, 0x54}, - {0x518b, 0xe0}, - {0x518c, 0xb2}, - {0x518d, 0x42}, - {0x518e, 0x3d}, - {0x518f, 0x56}, - {0x5190, 0x46}, - {0x5191, 0xf8}, - {0x5192, 0x04}, - {0x5193, 0x70}, - {0x5194, 0xf0}, - {0x5195, 0xf0}, - {0x5196, 0x03}, - {0x5197, 0x01}, - {0x5198, 0x04}, - {0x5199, 0x12}, - {0x519a, 0x04}, - {0x519b, 0x00}, - {0x519c, 0x06}, - {0x519d, 0x82}, - {0x519e, 0x38} -}; - -#endif diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h deleted file mode 100644 index b3a645a70d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the OpenMV project. - * author: Juan Schiavoni - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV7670 driver. - * - */ -#ifndef __OV7670_H__ -#define __OV7670_H__ -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int ov7670_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int ov7670_init(sensor_t *sensor); - -#endif // __OV7670_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h deleted file mode 100644 index 699354877f..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7670_regs.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * This file is for the OpenMV project so the OV7670 can be used - * author: Juan Schiavoni - * - * OV7670 register definitions. - */ -#ifndef __OV7670_REG_REGS_H__ -#define __OV7670_REG_REGS_H__ -#define GAIN 0x00 /* AGC – Gain control gain setting */ -#define BLUE 0x01 /* AWB – Blue channel gain setting */ -#define RED 0x02 /* AWB – Red channel gain setting */ -#define VREF 0x03 /* AWB – Green channel gain setting */ -#define COM1 0x04 /* Common Control 1 */ -#define BAVG 0x05 /* U/B Average Level */ -#define GAVG 0x06 /* Y/Gb Average Level */ -#define AECH 0x07 /* Exposure VAlue - AEC MSB 5 bits */ -#define RAVG 0x08 /* V/R Average Level */ - -#define COM2 0x09 /* Common Control 2 */ -#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ -#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ -#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ -#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ -#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ - -#define REG_PID 0x0A /* Product ID Number MSB */ -#define REG_VER 0x0B /* Product ID Number LSB */ - -#define COM3 0x0C /* Common Control 3 */ -#define COM3_SWAP_OUT 0x40 /* Output data MSB/LSB swap */ -#define COM3_TRI_CLK 0x20 /* Tri-state output clock */ -#define COM3_TRI_DATA 0x10 /* Tri-state option output */ -#define COM3_SCALE_EN 0x08 /* Scale enable */ -#define COM3_DCW 0x04 /* DCW enable */ - -#define COM4 0x0D /* Common Control 4 */ -#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ -#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ -#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ -#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ -#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ -#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ -#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ -#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ - -#define COM5 0x0E /* Common Control 5 */ -#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ -#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ -#define COM5_AFR_0 0x00 /* No reduction of frame rate */ -#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ -#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ -#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ -#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ -#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ -#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ -#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ - -#define COM6 0x0F /* Common Control 6 */ -#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ - -#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ -#define CLKRC 0x11 /* Internal Clock */ - -#define COM7 0x12 /* Common Control 7 */ -#define COM7_RESET 0x80 /* SCCB Register Reset */ -#define COM7_RES_VGA 0x00 /* Resolution VGA */ -#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ -#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ -#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ -#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ -#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ -#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ -#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ -#define COM7_FMT_YUV 0x00 /* Output format YUV */ -#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ -#define COM7_FMT_RGB 0x04 /* Output format RGB */ -#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ -#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x5)<<0)) - -#define COM8 0x13 /* Common Control 8 */ -#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ -#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ -#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ -#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ -#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ -#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ -#define COM8_AGC_EN 0x04 /* AGC Enable */ -#define COM8_AWB_EN 0x02 /* AWB Enable */ -#define COM8_AEC_EN 0x01 /* AEC Enable */ -#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) -#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) -#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) - -#define COM9 0x14 /* Common Control 9 */ -#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ -#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ -#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ -#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ -#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ -#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ -#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ -#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ -#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) - -#define COM10 0x15 /* Common Control 10 */ -#define COM10_NEGATIVE 0x80 /* Output negative data */ -#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ -#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ -#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ -#define COM10_PCLK_REV 0x10 /* PCLK reverse */ -#define COM10_HREF_REV 0x08 /* HREF reverse */ -#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ -#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ -#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ -#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ -#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ - -#define RSVD_16 0x16 /* Reserved register */ - -#define HSTART 0x17 /* Horizontal Frame (HREF column) Start high 8-bit(low 3 bits are at HREF[2:0]) */ -#define HSTOP 0x18 /* Horizontal Frame (HREF column) end high 8-bit (low 3 bits are at HREF[5:3]) */ -#define VSTART 0x19 /* Vertical Frame (row) Start high 8-bit (low 2 bits are at VREF[1:0]) */ -#define VSTOP 0x1A /* Vertical Frame (row) End high 8-bit (low 2 bits are at VREF[3:2]) */ -#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ -#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */ -#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */ - -#define MVFP 0x1E /* Mirror/Vflip Enable */ -#define MVFP_MIRROR 0x20 /* Mirror image */ -#define MVFP_FLIP 0x10 /* Vertical flip */ -#define MVFP_SUN 0x02 /* Black sun enable */ -#define MVFP_SET_MIRROR(r,x) ((r&0xDF)|((x&1)<<5)) /* change only bit5 according to x */ -#define MVFP_SET_FLIP(r,x) ((r&0xEF)|((x&1)<<4)) /* change only bit4 according to x */ - -#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period (Reserved?) */ -#define ADCCTR0 0x20 /* ADC control */ -#define ADCCTR1 0x21 /* reserved */ -#define ADCCTR2 0x22 /* reserved */ -#define ADCCTR3 0x23 /* reserved */ -#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ -#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ -#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ -#define BBIAS 0x27 /* B channel signal output bias (effective only when COM6[3]=1) */ -#define GbBIAS 0x28 /* Gb channel signal output bias (effective only when COM6[3]=1) */ -#define RSVD_29 0x29 /* reserved */ -#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ -#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ -#define RBIAS 0x2C /* R channel signal output bias (effective only when COM6[3]=1) */ -#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ -#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ -#define YAVE 0x2F /* Y/G Channel Average Value */ -#define HSYST 0x30 /* HSync rising edge delay */ -#define HSYEN 0x31 /* HSync falling edge delay */ -#define HREF 0x32 /* Image Start and Size Control DIFFERENT CONTROL SEQUENCE */ -#define CHLF 0x33 /* Array Current control */ -#define ARBLM 0x34 /* Array reference control */ -#define RSVD_35 0x35 /* Reserved */ -#define RSVD_36 0x36 /* Reserved */ -#define ADC 0x37 /* ADC control */ -#define ACOM 0x38 /* ADC and analog common mode control */ -#define OFON 0x39 /* ADC offset control */ -#define TSLB 0x3A /* Line buffer test option */ - -#define COM11 0x3B /* Common control 11 */ -#define COM11_EXP 0x02 -#define COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */ - -#define COM12 0x3C /* Common control 12 */ - -#define COM13 0x3D /* Common control 13 */ -#define COM13_GAMMA 0x80 /* Gamma enable */ -#define COM13_UVSAT 0x40 /* UV saturation auto adjustment */ - -#define COM14 0x3E /* Common Control 14 */ - -#define EDGE 0x3F /* edge enhancement adjustment */ -#define COM15 0x40 /* Common Control 15 DIFFERENT CONTROLS */ -#define COM15_SET_RGB565(r,x) ((r&0xEF)|((x&1)<<4)) /* set rgb565 mode */ -#define COM15_RGB565 0x10 /* RGB565 output */ -#define COM15_R00FF 0xC0 /* Output range: [00] to [FF] */ - -#define COM16 0x41 /* Common Control 16 DIFFERENT CONTROLS */ -#define COM16_AWBGAIN 0x08 /* AWB gain enable */ -#define COM17 0x42 /* Common Control 17 */ - -#define AWBC1 0x43 /* Reserved */ -#define AWBC2 0x44 /* Reserved */ -#define AWBC3 0x45 /* Reserved */ -#define AWBC4 0x46 /* Reserved */ -#define AWBC5 0x47 /* Reserved */ -#define AWBC6 0x48 /* Reserved */ - -#define RSVD_49 0x49 /* Reserved */ -#define RSVD_4A 0x4A /* Reserved */ - -#define REG4B 0x4B /* Register 4B */ -#define DNSTH 0x4C /* Denoise strength */ - -#define RSVD_4D 0x4D /* Reserved */ -#define RSVD_4E 0x4E /* Reserved */ - -#define MTX1 0x4F /* Matrix coefficient 1 */ -#define MTX2 0x50 /* Matrix coefficient 2 */ -#define MTX3 0x51 /* Matrix coefficient 3 */ -#define MTX4 0x52 /* Matrix coefficient 4 */ -#define MTX5 0x53 /* Matrix coefficient 5 */ -#define MTX6 0x54 /* Matrix coefficient 6 */ -#define BRIGHTNESS 0x55 /* Brightness control */ -#define CONTRAST 0x56 /* Contrast control */ -#define CONTRASCENTER 0x57 /* Contrast center */ -#define MTXS 0x58 /* Matrix coefficient sign for coefficient 5 to 0*/ - -#define RSVD_59 0x59 /* Reserved */ -#define RSVD_5A 0x5A /* Reserved */ -#define RSVD_5B 0x5B /* Reserved */ -#define RSVD_5C 0x5C /* Reserved */ -#define RSVD_5D 0x5D /* Reserved */ -#define RSVD_5E 0x5E /* Reserved */ -#define RSVD_5F 0x5F /* Reserved */ -#define RSVD_60 0x60 /* Reserved */ -#define RSVD_61 0x61 /* Reserved */ - -#define LCC1 0x62 /* Lens correction option 1 */ - -#define LCC2 0x63 /* Lens correction option 2 */ -#define LCC3 0x64 /* Lens correction option 3 */ -#define LCC4 0x65 /* Lens correction option 4 */ -#define LCC5 0x66 /* Lens correction option 5 */ - -#define MANU 0x67 /* Manual U Value */ -#define MANV 0x68 /* Manual V Value */ -#define GFIX 0x69 /* Fix gain control */ -#define GGAIN 0x6A /* G channel AWB gain */ - -#define DBLV 0x6B /* PLL and clock ? */ - -#define AWBCTR3 0x6C /* AWB Control 3 */ -#define AWBCTR2 0x6D /* AWB Control 2 */ -#define AWBCTR1 0x6E /* AWB Control 1 */ -#define AWBCTR0 0x6F /* AWB Control 0 */ -#define SCALING_XSC 0x70 /* test pattern and horizontal scaling factor */ -#define SCALING_XSC_CBAR(r) (r&0x7F) /* make sure bit7 is 0 for color bar */ -#define SCALING_YSC 0x71 /* test pattern and vertical scaling factor */ -#define SCALING_YSC_CBAR(r,x) ((r&0x7F)|((x&1)<<7)) /* change bit7 for color bar on/off */ -#define SCALING_DCWCTR 0x72 /* DCW control */ -#define SCALING_PCLK_DIV 0x73 /* */ -#define REG74 0x74 /* */ -#define REG75 0x75 /* */ -#define REG76 0x76 /* */ -#define REG77 0x77 /* */ - -#define RSVD_78 0x78 /* Reserved */ -#define RSVD_79 0x79 /* Reserved */ - -#define SLOP 0x7A /* Gamma curve highest segment slope */ -#define GAM1 0x7B /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ -#define GAM2 0x7C /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ -#define GAM3 0x7D /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ -#define GAM4 0x7E /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ -#define GAM5 0x7F /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ -#define GAM6 0x80 /* Gamma Curve 6rd Segment Input End Point 0x30 Output Value */ -#define GAM7 0x81 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ -#define GAM8 0x82 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ -#define GAM9 0x83 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ -#define GAM10 0x84 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ -#define GAM11 0x85 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ -#define GAM12 0x86 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ -#define GAM13 0x87 /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ -#define GAM14 0x88 /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ -#define GAM15 0x89 /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ - -#define RSVD_8A 0x8A /* Reserved */ -#define RSVD_8B 0x8B /* Reserved */ - -#define RGB444 0x8C /* */ - -#define RSVD_8D 0x8D /* Reserved */ -#define RSVD_8E 0x8E /* Reserved */ -#define RSVD_8F 0x8F /* Reserved */ -#define RSVD_90 0x90 /* Reserved */ -#define RSVD_91 0x91 /* Reserved */ - -#define DM_LNL 0x92 /* Dummy line low 8 bit */ -#define DM_LNH 0x93 /* Dummy line high 8 bit */ -#define LCC6 0x94 /* Lens correction option 6 */ -#define LCC7 0x95 /* Lens correction option 7 */ - -#define RSVD_96 0x96 /* Reserved */ -#define RSVD_97 0x97 /* Reserved */ -#define RSVD_98 0x98 /* Reserved */ -#define RSVD_99 0x99 /* Reserved */ -#define RSVD_9A 0x9A /* Reserved */ -#define RSVD_9B 0x9B /* Reserved */ -#define RSVD_9C 0x9C /* Reserved */ - -#define BD50ST 0x9D /* 50 Hz banding filter value */ -#define BD60ST 0x9E /* 60 Hz banding filter value */ -#define HAECC1 0x9F /* Histogram-based AEC/AGC control 1 */ -#define HAECC2 0xA0 /* Histogram-based AEC/AGC control 2 */ - -#define RSVD_A1 0xA1 /* Reserved */ - -#define SCALING_PCLK_DELAY 0xA2 /* Pixel clock delay */ - -#define RSVD_A3 0xA3 /* Reserved */ - -#define NT_CNTRL 0xA4 /* */ -#define BD50MAX 0xA5 /* 50 Hz banding step limit */ -#define HAECC3 0xA6 /* Histogram-based AEC/AGC control 3 */ -#define HAECC4 0xA7 /* Histogram-based AEC/AGC control 4 */ -#define HAECC5 0xA8 /* Histogram-based AEC/AGC control 5 */ -#define HAECC6 0xA9 /* Histogram-based AEC/AGC control 6 */ - -#define HAECC7 0xAA /* Histogram-based AEC/AGC control 7 */ -#define HAECC_EN 0x80 /* Histogram-based AEC algorithm enable */ - -#define BD60MAX 0xAB /* 60 Hz banding step limit */ - -#define STR_OPT 0xAC /* Register AC */ -#define STR_R 0xAD /* R gain for led output frame */ -#define STR_G 0xAE /* G gain for led output frame */ -#define STR_B 0xAF /* B gain for led output frame */ -#define RSVD_B0 0xB0 /* Reserved */ -#define ABLC1 0xB1 /* */ -#define RSVD_B2 0xB2 /* Reserved */ -#define THL_ST 0xB3 /* ABLC target */ -#define THL_DLT 0xB5 /* ABLC stable range */ - -#define RSVD_B6 0xB6 /* Reserved */ -#define RSVD_B7 0xB7 /* Reserved */ -#define RSVD_B8 0xB8 /* Reserved */ -#define RSVD_B9 0xB9 /* Reserved */ -#define RSVD_BA 0xBA /* Reserved */ -#define RSVD_BB 0xBB /* Reserved */ -#define RSVD_BC 0xBC /* Reserved */ -#define RSVD_BD 0xBD /* Reserved */ - -#define AD_CHB 0xBE /* blue channel black level compensation */ -#define AD_CHR 0xBF /* Red channel black level compensation */ -#define AD_CHGb 0xC0 /* Gb channel black level compensation */ -#define AD_CHGr 0xC1 /* Gr channel black level compensation */ - -#define RSVD_C2 0xC2 /* Reserved */ -#define RSVD_C3 0xC3 /* Reserved */ -#define RSVD_C4 0xC4 /* Reserved */ -#define RSVD_C5 0xC5 /* Reserved */ -#define RSVD_C6 0xC6 /* Reserved */ -#define RSVD_C7 0xC7 /* Reserved */ -#define RSVD_C8 0xC8 /* Reserved */ - -#define SATCTR 0xC9 /* Saturation control */ -#define SET_REG(reg, x) (##reg_DEFAULT|x) - -#endif //__OV7670_REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h deleted file mode 100644 index 291b266800..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV7725 driver. - * - */ -#ifndef __OV7725_H__ -#define __OV7725_H__ -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int ov7725_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int ov7725_init(sensor_t *sensor); - -#endif // __OV7725_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h deleted file mode 100644 index 5cb233dc97..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/ov7725_regs.h +++ /dev/null @@ -1,335 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013/2014 Ibrahim Abdelkader - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * OV2640 register definitions. - */ -#ifndef __REG_REGS_H__ -#define __REG_REGS_H__ -#define GAIN 0x00 /* AGC – Gain control gain setting */ -#define BLUE 0x01 /* AWB – Blue channel gain setting */ -#define RED 0x02 /* AWB – Red channel gain setting */ -#define GREEN 0x03 /* AWB – Green channel gain setting */ -#define BAVG 0x05 /* U/B Average Level */ -#define GAVG 0x06 /* Y/Gb Average Level */ -#define RAVG 0x07 /* V/R Average Level */ -#define AECH 0x08 /* Exposure Value – AEC MSBs */ - -#define COM2 0x09 /* Common Control 2 */ -#define COM2_SOFT_SLEEP 0x10 /* Soft sleep mode */ -#define COM2_OUT_DRIVE_1x 0x00 /* Output drive capability 1x */ -#define COM2_OUT_DRIVE_2x 0x01 /* Output drive capability 2x */ -#define COM2_OUT_DRIVE_3x 0x02 /* Output drive capability 3x */ -#define COM2_OUT_DRIVE_4x 0x03 /* Output drive capability 4x */ - -#define REG_PID 0x0A /* Product ID Number MSB */ -#define REG_VER 0x0B /* Product ID Number LSB */ - -#define COM3 0x0C /* Common Control 3 */ -#define COM3_VFLIP 0x80 /* Vertical flip image ON/OFF selection */ -#define COM3_MIRROR 0x40 /* Horizontal mirror image ON/OFF selection */ -#define COM3_SWAP_BR 0x20 /* Swap B/R output sequence in RGB output mode */ -#define COM3_SWAP_YUV 0x10 /* Swap Y/UV output sequence in YUV output mode */ -#define COM3_SWAP_MSB 0x08 /* Swap output MSB/LSB */ -#define COM3_TRI_CLOCK 0x04 /* Tri-state option for output clock at power-down period */ -#define COM3_TRI_DATA 0x02 /* Tri-state option for output data at power-down period */ -#define COM3_COLOR_BAR 0x01 /* Sensor color bar test pattern output enable */ -#define COM3_SET_CBAR(r, x) ((r&0xFE)|((x&1)<<0)) -#define COM3_SET_MIRROR(r, x) ((r&0xBF)|((x&1)<<6)) -#define COM3_SET_FLIP(r, x) ((r&0x7F)|((x&1)<<7)) - -#define COM4 0x0D /* Common Control 4 */ -#define COM4_PLL_BYPASS 0x00 /* Bypass PLL */ -#define COM4_PLL_4x 0x40 /* PLL frequency 4x */ -#define COM4_PLL_6x 0x80 /* PLL frequency 6x */ -#define COM4_PLL_8x 0xc0 /* PLL frequency 8x */ -#define COM4_AEC_FULL 0x00 /* AEC evaluate full window */ -#define COM4_AEC_1_2 0x10 /* AEC evaluate 1/2 window */ -#define COM4_AEC_1_4 0x20 /* AEC evaluate 1/4 window */ -#define COM4_AEC_2_3 0x30 /* AEC evaluate 2/3 window */ - -#define COM5 0x0E /* Common Control 5 */ -#define COM5_AFR 0x80 /* Auto frame rate control ON/OFF selection (night mode) */ -#define COM5_AFR_SPEED 0x40 /* Auto frame rate control speed selection */ -#define COM5_AFR_0 0x00 /* No reduction of frame rate */ -#define COM5_AFR_1_2 0x10 /* Max reduction to 1/2 frame rate */ -#define COM5_AFR_1_4 0x20 /* Max reduction to 1/4 frame rate */ -#define COM5_AFR_1_8 0x30 /* Max reduction to 1/8 frame rate */ -#define COM5_AFR_4x 0x04 /* Add frame when AGC reaches 4x gain */ -#define COM5_AFR_8x 0x08 /* Add frame when AGC reaches 8x gain */ -#define COM5_AFR_16x 0x0c /* Add frame when AGC reaches 16x gain */ -#define COM5_AEC_NO_LIMIT 0x01 /* No limit to AEC increase step */ - -#define COM6 0x0F /* Common Control 6 */ -#define COM6_AUTO_WINDOW 0x01 /* Auto window setting ON/OFF selection when format changes */ - -#define AEC 0x10 /* AEC[7:0] (see register AECH for AEC[15:8]) */ -#define CLKRC 0x11 /* Internal Clock */ - -#define COM7 0x12 /* Common Control 7 */ -#define COM7_RESET 0x80 /* SCCB Register Reset */ -#define COM7_RES_VGA 0x00 /* Resolution VGA */ -#define COM7_RES_QVGA 0x40 /* Resolution QVGA */ -#define COM7_BT656 0x20 /* BT.656 protocol ON/OFF */ -#define COM7_SENSOR_RAW 0x10 /* Sensor RAW */ -#define COM7_FMT_GBR422 0x00 /* RGB output format GBR422 */ -#define COM7_FMT_RGB565 0x04 /* RGB output format RGB565 */ -#define COM7_FMT_RGB555 0x08 /* RGB output format RGB555 */ -#define COM7_FMT_RGB444 0x0C /* RGB output format RGB444 */ -#define COM7_FMT_YUV 0x00 /* Output format YUV */ -#define COM7_FMT_P_BAYER 0x01 /* Output format Processed Bayer RAW */ -#define COM7_FMT_RGB 0x02 /* Output format RGB */ -#define COM7_FMT_R_BAYER 0x03 /* Output format Bayer RAW */ -#define COM7_SET_FMT(r, x) ((r&0xFC)|((x&0x3)<<0)) -#define COM7_SET_RGB(r, x) ((r&0xF0)|(x&0x0C)|COM7_FMT_RGB) - -#define COM8 0x13 /* Common Control 8 */ -#define COM8_FAST_AUTO 0x80 /* Enable fast AGC/AEC algorithm */ -#define COM8_STEP_VSYNC 0x00 /* AEC - Step size limited to vertical blank */ -#define COM8_STEP_UNLIMIT 0x40 /* AEC - Step size unlimited step size */ -#define COM8_BANDF_EN 0x20 /* Banding filter ON/OFF */ -#define COM8_AEC_BANDF 0x10 /* Enable AEC below banding value */ -#define COM8_AEC_FINE_EN 0x08 /* Fine AEC ON/OFF control */ -#define COM8_AGC_EN 0x04 /* AGC Enable */ -#define COM8_AWB_EN 0x02 /* AWB Enable */ -#define COM8_AEC_EN 0x01 /* AEC Enable */ -#define COM8_SET_AGC(r, x) ((r&0xFB)|((x&0x1)<<2)) -#define COM8_SET_AWB(r, x) ((r&0xFD)|((x&0x1)<<1)) -#define COM8_SET_AEC(r, x) ((r&0xFE)|((x&0x1)<<0)) - -#define COM9 0x14 /* Common Control 9 */ -#define COM9_HISTO_AVG 0x80 /* Histogram or average based AEC/AGC selection */ -#define COM9_AGC_GAIN_2x 0x00 /* Automatic Gain Ceiling 2x */ -#define COM9_AGC_GAIN_4x 0x10 /* Automatic Gain Ceiling 4x */ -#define COM9_AGC_GAIN_8x 0x20 /* Automatic Gain Ceiling 8x */ -#define COM9_AGC_GAIN_16x 0x30 /* Automatic Gain Ceiling 16x */ -#define COM9_AGC_GAIN_32x 0x40 /* Automatic Gain Ceiling 32x */ -#define COM9_DROP_VSYNC 0x04 /* Drop VSYNC output of corrupt frame */ -#define COM9_DROP_HREF 0x02 /* Drop HREF output of corrupt frame */ -#define COM9_SET_AGC(r, x) ((r&0x8F)|((x&0x07)<<4)) - -#define COM10 0x15 /* Common Control 10 */ -#define COM10_NEGATIVE 0x80 /* Output negative data */ -#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ -#define COM10_PCLK_FREE 0x00 /* PCLK output option: free running PCLK */ -#define COM10_PCLK_MASK 0x20 /* PCLK output option: masked during horizontal blank */ -#define COM10_PCLK_REV 0x10 /* PCLK reverse */ -#define COM10_HREF_REV 0x08 /* HREF reverse */ -#define COM10_VSYNC_FALLING 0x00 /* VSYNC changes on falling edge of PCLK */ -#define COM10_VSYNC_RISING 0x04 /* VSYNC changes on rising edge of PCLK */ -#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ -#define COM10_OUT_RANGE_8 0x01 /* Output data range: Full range */ -#define COM10_OUT_RANGE_10 0x00 /* Output data range: Data from [10] to [F0] (8 MSBs) */ - -#define REG16 0x16 /* Register 16 */ -#define REG16_BIT_SHIFT 0x80 /* Bit shift test pattern options */ -#define HSTART 0x17 /* Horizontal Frame (HREF column) Start 8 MSBs (2 LSBs are at HREF[5:4]) */ -#define HSIZE 0x18 /* Horizontal Sensor Size (2 LSBs are at HREF[1:0]) */ -#define VSTART 0x19 /* Vertical Frame (row) Start 8 MSBs (1 LSB is at HREF[6]) */ -#define VSIZE 0x1A /* Vertical Sensor Size (1 LSB is at HREF[2]) */ -#define PSHFT 0x1B /* Data Format - Pixel Delay Select */ -#define REG_MIDH 0x1C /* Manufacturer ID Byte – High */ -#define REG_MIDL 0x1D /* Manufacturer ID Byte – Low */ -#define LAEC 0x1F /* Fine AEC Value - defines exposure value less than one row period */ - -#define COM11 0x20 /* Common Control 11 */ -#define COM11_SNGL_FRAME_EN 0x02 /* Single frame ON/OFF selection */ -#define COM11_SNGL_XFR_TRIG 0x01 /* Single frame transfer trigger */ - -#define BDBASE 0x22 /* Banding Filter Minimum AEC Value */ -#define DBSTEP 0x23 /* Banding Filter Maximum Step */ -#define AEW 0x24 /* AGC/AEC - Stable Operating Region (Upper Limit) */ -#define AEB 0x25 /* AGC/AEC - Stable Operating Region (Lower Limit) */ -#define VPT 0x26 /* AGC/AEC Fast Mode Operating Region */ -#define REG28 0x28 /* Selection on the number of dummy rows, N */ -#define HOUTSIZE 0x29 /* Horizontal Data Output Size MSBs (2 LSBs at register EXHCH[1:0]) */ -#define EXHCH 0x2A /* Dummy Pixel Insert MSB */ -#define EXHCL 0x2B /* Dummy Pixel Insert LSB */ -#define VOUTSIZE 0x2C /* Vertical Data Output Size MSBs (LSB at register EXHCH[2]) */ -#define ADVFL 0x2D /* LSB of Insert Dummy Rows in Vertical Sync (1 bit equals 1 row) */ -#define ADVFH 0x2E /* MSB of Insert Dummy Rows in Vertical Sync */ -#define YAVE 0x2F /* Y/G Channel Average Value */ -#define LUMHTH 0x30 /* Histogram AEC/AGC Luminance High Level Threshold */ -#define LUMLTH 0x31 /* Histogram AEC/AGC Luminance Low Level Threshold */ -#define HREF 0x32 /* Image Start and Size Control */ -#define DM_LNL 0x33 /* Dummy Row Low 8 Bits */ -#define DM_LNH 0x34 /* Dummy Row High 8 Bits */ -#define ADOFF_B 0x35 /* AD Offset Compensation Value for B Channel */ -#define ADOFF_R 0x36 /* AD Offset Compensation Value for R Channel */ -#define ADOFF_GB 0x37 /* AD Offset Compensation Value for GB Channel */ -#define ADOFF_GR 0x38 /* AD Offset Compensation Value for GR Channel */ -#define OFF_B 0x39 /* AD Offset Compensation Value for B Channel */ -#define OFF_R 0x3A /* AD Offset Compensation Value for R Channel */ -#define OFF_GB 0x3B /* AD Offset Compensation Value for GB Channel */ -#define OFF_GR 0x3C /* AD Offset Compensation Value for GR Channel */ -#define COM12 0x3D /* DC offset compensation for analog process */ - -#define COM13 0x3E /* Common Control 13 */ -#define COM13_BLC_EN 0x80 /* BLC enable */ -#define COM13_ADC_EN 0x40 /* ADC channel BLC ON/OFF control */ -#define COM13_ANALOG_BLC 0x20 /* Analog processing channel BLC ON/OFF control */ -#define COM13_ABLC_GAIN_EN 0x04 /* ABLC gain trigger enable */ - -#define COM14 0x3F /* Common Control 14 */ -#define COM15 0x40 /* Common Control 15 */ -#define COM16 0x41 /* Common Control 16 */ -#define TGT_B 0x42 /* BLC Blue Channel Target Value */ -#define TGT_R 0x43 /* BLC Red Channel Target Value */ -#define TGT_GB 0x44 /* BLC Gb Channel Target Value */ -#define TGT_GR 0x45 /* BLC Gr Channel Target Value */ - -#define LC_CTR 0x46 /* Lens Correction Control */ -#define LC_CTR_RGB_COMP_1 0x00 /* R, G, and B channel compensation coefficient is set by LC_COEF (0x49) */ -#define LC_CTR_RGB_COMP_3 0x04 /* R, G, and B channel compensation coefficient is set by registers - LC_COEFB (0x4B), LC_COEF (0x49), and LC_COEFR (0x4C), respectively */ -#define LC_CTR_EN 0x01 /* Lens correction enable */ -#define LC_XC 0x47 /* X Coordinate of Lens Correction Center Relative to Array Center */ -#define LC_YC 0x48 /* Y Coordinate of Lens Correction Center Relative to Array Center */ -#define LC_COEF 0x49 /* Lens Correction Coefficient */ -#define LC_RADI 0x4A /* Lens Correction Radius */ -#define LC_COEFB 0x4B /* Lens Correction B Channel Compensation Coefficient */ -#define LC_COEFR 0x4C /* Lens Correction R Channel Compensation Coefficient */ - -#define FIXGAIN 0x4D /* Analog Fix Gain Amplifier */ -#define AREF0 0x4E /* Sensor Reference Control */ -#define AREF1 0x4F /* Sensor Reference Current Control */ -#define AREF2 0x50 /* Analog Reference Control */ -#define AREF3 0x51 /* ADC Reference Control */ -#define AREF4 0x52 /* ADC Reference Control */ -#define AREF5 0x53 /* ADC Reference Control */ -#define AREF6 0x54 /* Analog Reference Control */ -#define AREF7 0x55 /* Analog Reference Control */ -#define UFIX 0x60 /* U Channel Fixed Value Output */ -#define VFIX 0x61 /* V Channel Fixed Value Output */ -#define AWBB_BLK 0x62 /* AWB Option for Advanced AWB */ - -#define AWB_CTRL0 0x63 /* AWB Control Byte 0 */ -#define AWB_CTRL0_GAIN_EN 0x80 /* AWB gain enable */ -#define AWB_CTRL0_CALC_EN 0x40 /* AWB calculate enable */ -#define AWB_CTRL0_WBC_MASK 0x0F /* WBC threshold 2 */ - -#define DSP_CTRL1 0x64 /* DSP Control Byte 1 */ -#define DSP_CTRL1_FIFO_EN 0x80 /* FIFO enable/disable selection */ -#define DSP_CTRL1_UV_EN 0x40 /* UV adjust function ON/OFF selection */ -#define DSP_CTRL1_SDE_EN 0x20 /* SDE enable */ -#define DSP_CTRL1_MTRX_EN 0x10 /* Color matrix ON/OFF selection */ -#define DSP_CTRL1_INTRP_EN 0x08 /* Interpolation ON/OFF selection */ -#define DSP_CTRL1_GAMMA_EN 0x04 /* Gamma function ON/OFF selection */ -#define DSP_CTRL1_BLACK_EN 0x02 /* Black defect auto correction ON/OFF */ -#define DSP_CTRL1_WHITE_EN 0x01 /* White defect auto correction ON/OFF */ - -#define DSP_CTRL2 0x65 /* DSP Control Byte 2 */ -#define DSP_CTRL2_VDCW_EN 0x08 /* Vertical DCW enable */ -#define DSP_CTRL2_HDCW_EN 0x04 /* Horizontal DCW enable */ -#define DSP_CTRL2_VZOOM_EN 0x02 /* Vertical zoom out enable */ -#define DSP_CTRL2_HZOOM_EN 0x01 /* Horizontal zoom out enable */ - -#define DSP_CTRL3 0x66 /* DSP Control Byte 3 */ -#define DSP_CTRL3_UV_EN 0x80 /* UV output sequence option */ -#define DSP_CTRL3_CBAR_EN 0x20 /* DSP color bar ON/OFF selection */ -#define DSP_CTRL3_FIFO_EN 0x08 /* FIFO power down ON/OFF selection */ -#define DSP_CTRL3_SCAL1_PWDN 0x04 /* Scaling module power down control 1 */ -#define DSP_CTRL3_SCAL2_PWDN 0x02 /* Scaling module power down control 2 */ -#define DSP_CTRL3_INTRP_PWDN 0x01 /* Interpolation module power down control */ -#define DSP_CTRL3_SET_CBAR(r, x) ((r&0xDF)|((x&1)<<5)) - - -#define DSP_CTRL4 0x67 /* DSP Control Byte 4 */ -#define DSP_CTRL4_YUV_RGB 0x00 /* Output selection YUV or RGB */ -#define DSP_CTRL4_RAW8 0x02 /* Output selection RAW8 */ -#define DSP_CTRL4_RAW10 0x03 /* Output selection RAW10 */ - - -#define AWB_BIAS 0x68 /* AWB BLC Level Clip */ -#define AWB_CTRL1 0x69 /* AWB Control 1 */ -#define AWB_CTRL2 0x6A /* AWB Control 2 */ - -#define AWB_CTRL3 0x6B /* AWB Control 3 */ -#define AWB_CTRL3_ADVANCED 0x80 /* AWB mode select - Advanced AWB */ -#define AWB_CTRL3_SIMPLE 0x00 /* AWB mode select - Simple AWB */ - -#define AWB_CTRL4 0x6C /* AWB Control 4 */ -#define AWB_CTRL5 0x6D /* AWB Control 5 */ -#define AWB_CTRL6 0x6E /* AWB Control 6 */ -#define AWB_CTRL7 0x6F /* AWB Control 7 */ -#define AWB_CTRL8 0x70 /* AWB Control 8 */ -#define AWB_CTRL9 0x71 /* AWB Control 9 */ -#define AWB_CTRL10 0x72 /* AWB Control 10 */ -#define AWB_CTRL11 0x73 /* AWB Control 11 */ -#define AWB_CTRL12 0x74 /* AWB Control 12 */ -#define AWB_CTRL13 0x75 /* AWB Control 13 */ -#define AWB_CTRL14 0x76 /* AWB Control 14 */ -#define AWB_CTRL15 0x77 /* AWB Control 15 */ -#define AWB_CTRL16 0x78 /* AWB Control 16 */ -#define AWB_CTRL17 0x79 /* AWB Control 17 */ -#define AWB_CTRL18 0x7A /* AWB Control 18 */ -#define AWB_CTRL19 0x7B /* AWB Control 19 */ -#define AWB_CTRL20 0x7C /* AWB Control 20 */ -#define AWB_CTRL21 0x7D /* AWB Control 21 */ -#define GAM1 0x7E /* Gamma Curve 1st Segment Input End Point 0x04 Output Value */ -#define GAM2 0x7F /* Gamma Curve 2nd Segment Input End Point 0x08 Output Value */ -#define GAM3 0x80 /* Gamma Curve 3rd Segment Input End Point 0x10 Output Value */ -#define GAM4 0x81 /* Gamma Curve 4th Segment Input End Point 0x20 Output Value */ -#define GAM5 0x82 /* Gamma Curve 5th Segment Input End Point 0x28 Output Value */ -#define GAM6 0x83 /* Gamma Curve 6th Segment Input End Point 0x30 Output Value */ -#define GAM7 0x84 /* Gamma Curve 7th Segment Input End Point 0x38 Output Value */ -#define GAM8 0x85 /* Gamma Curve 8th Segment Input End Point 0x40 Output Value */ -#define GAM9 0x86 /* Gamma Curve 9th Segment Input End Point 0x48 Output Value */ -#define GAM10 0x87 /* Gamma Curve 10th Segment Input End Point 0x50 Output Value */ -#define GAM11 0x88 /* Gamma Curve 11th Segment Input End Point 0x60 Output Value */ -#define GAM12 0x89 /* Gamma Curve 12th Segment Input End Point 0x70 Output Value */ -#define GAM13 0x8A /* Gamma Curve 13th Segment Input End Point 0x90 Output Value */ -#define GAM14 0x8B /* Gamma Curve 14th Segment Input End Point 0xB0 Output Value */ -#define GAM15 0x8C /* Gamma Curve 15th Segment Input End Point 0xD0 Output Value */ -#define SLOP 0x8D /* Gamma Curve Highest Segment Slope */ -#define DNSTH 0x8E /* De-noise Threshold */ -#define EDGE0 0x8F /* Edge Enhancement Strength Control */ -#define EDGE1 0x90 /* Edge Enhancement Threshold Control */ -#define DNSOFF 0x91 /* Auto De-noise Threshold Control */ -#define EDGE2 0x92 /* Edge Enhancement Strength Upper Limit */ -#define EDGE3 0x93 /* Edge Enhancement Strength Upper Limit */ -#define MTX1 0x94 /* Matrix Coefficient 1 */ -#define MTX2 0x95 /* Matrix Coefficient 2 */ -#define MTX3 0x96 /* Matrix Coefficient 3 */ -#define MTX4 0x97 /* Matrix Coefficient 4 */ -#define MTX5 0x98 /* Matrix Coefficient 5 */ -#define MTX6 0x99 /* Matrix Coefficient 6 */ - -#define MTX_CTRL 0x9A /* Matrix Control */ -#define MTX_CTRL_DBL_EN 0x80 /* Matrix double ON/OFF selection */ - -#define BRIGHTNESS 0x9B /* Brightness Control */ -#define CONTRAST 0x9C /* Contrast Gain */ -#define UVADJ0 0x9E /* Auto UV Adjust Control 0 */ -#define UVADJ1 0x9F /* Auto UV Adjust Control 1 */ -#define SCAL0 0xA0 /* DCW Ratio Control */ -#define SCAL1 0xA1 /* Horizontal Zoom Out Control */ -#define SCAL2 0xA2 /* Vertical Zoom Out Control */ -#define FIFODLYM 0xA3 /* FIFO Manual Mode Delay Control */ -#define FIFODLYA 0xA4 /* FIFO Auto Mode Delay Control */ - -#define SDE 0xA6 /* Special Digital Effect Control */ -#define SDE_NEGATIVE_EN 0x40 /* Negative image enable */ -#define SDE_GRAYSCALE_EN 0x20 /* Gray scale image enable */ -#define SDE_V_FIXED_EN 0x10 /* V fixed value enable */ -#define SDE_U_FIXED_EN 0x08 /* U fixed value enable */ -#define SDE_CONT_BRIGHT_EN 0x04 /* Contrast/Brightness enable */ -#define SDE_SATURATION_EN 0x02 /* Saturation enable */ -#define SDE_HUE_EN 0x01 /* Hue enable */ - -#define USAT 0xA7 /* U Component Saturation Gain */ -#define VSAT 0xA8 /* V Component Saturation Gain */ -#define HUECOS 0xA9 /* Cosine value × 0x80 */ -#define HUESIN 0xAA /* Sine value × 0x80 */ -#define SIGN_BIT 0xAB /* Sign Bit for Hue and Brightness */ - -#define DSPAUTO 0xAC /* DSP Auto Function ON/OFF Control */ -#define DSPAUTO_AWB_EN 0x80 /* AWB auto threshold control */ -#define DSPAUTO_DENOISE_EN 0x40 /* De-noise auto threshold control */ -#define DSPAUTO_EDGE_EN 0x20 /* Sharpness (edge enhancement) auto strength control */ -#define DSPAUTO_UV_EN 0x10 /* UV adjust auto slope control */ -#define DSPAUTO_SCAL0_EN 0x08 /* Auto scaling factor control (register SCAL0 (0xA0)) */ -#define DSPAUTO_SCAL1_EN 0x04 /* Auto scaling factor control (registers SCAL1 (0xA1 and SCAL2 (0xA2))*/ -#define SET_REG(reg, x) (##reg_DEFAULT|x) -#endif //__REG_REGS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h deleted file mode 100644 index 19298b76c2..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * SC030IOT DVP driver. - * - */ -#ifndef __SC030IOT_H__ -#define __SC030IOT_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int sc030iot_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int sc030iot_init(sensor_t *sensor); - -#endif // __SC030IOT_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h deleted file mode 100644 index 56f5654c8a..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc030iot_settings.h +++ /dev/null @@ -1,491 +0,0 @@ -//version: V01P00_20220303 -//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 -//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI -//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P -//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data -//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data -//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR -//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M -//pin :BIT0 pwdn// BIT1:reset -//avdd 0:3.3V// 1:2.5V// 2:1.8V -//dovdd 0:2.8V// 1:2.5V// 2:1.8V -//dvdd 0:1.8V// 1:1.5V// 2:1.2V - -/* -[DataBase] -DBName=Dothinkey - -[Vendor] -VendorName=SmartSens - -[Sensor] -SensorName=SC031IOT -width=640 -height=480 -port=1 -type=2 -pin=3 -SlaveID=0xd0 -mode=0 -FlagReg=0xf7 -FlagMask=0xff -FlagData=0xfa -FlagReg1=0xf8 -FlagMask1=0xff -FlagData1=0x46 -outformat=0 -mclk=20 -avdd=2.80000 -dovdd=2.800000 -dvdd=1.5 - -Ext0=0 -Ext1=0 -Ext2=0 -AFVCC=0.0000 -VPP=0.000000 -*/ -#include - -static const uint8_t sc030iot_default_init_regs[][2] = { - {0xf0, 0x30}, - {0x01, 0xff}, - {0x02, 0xff}, - {0x22, 0x07}, - {0x19, 0xff}, - {0x3f, 0x82}, - {0x30, 0x02}, - {0xf0, 0x01}, - {0x70, 0x00}, - {0x71, 0x80}, - {0x72, 0x20}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x75, 0x10}, - {0x76, 0x81}, - {0x77, 0x88}, - {0x78, 0xe1}, - {0x79, 0x01}, - {0xf5, 0x01}, - {0xf4, 0x0a}, - {0xf0, 0x36}, - {0x37, 0x79}, - {0x31, 0x82}, - {0x3e, 0x60}, - {0x30, 0xf0}, - {0x33, 0x33}, - {0xf0, 0x32}, - {0x48, 0x02}, - {0xf0, 0x33}, - {0x02, 0x12}, - {0x7c, 0x02}, - {0x7d, 0x0e}, - {0xa2, 0x04}, - {0x5e, 0x06}, - {0x5f, 0x0a}, - {0x0b, 0x58}, - {0x06, 0x38}, - {0xf0, 0x32}, - {0x48, 0x02}, - {0xf0, 0x39}, - {0x02, 0x70}, - {0xf0, 0x45}, - {0x09, 0x1c}, - {0xf0, 0x37}, - {0x22, 0x0d}, - {0xf0, 0x33}, - {0x33, 0x10}, - {0xb1, 0x80}, - {0x34, 0x40}, - {0x0b, 0x54}, - {0xb2, 0x78}, - {0xf0, 0x36}, - {0x11, 0x80}, - {0xf0, 0x30}, - {0x38, 0x44}, - {0xf0, 0x33}, - {0xb3, 0x51}, - {0x01, 0x10}, - {0x0b, 0x6c}, - {0x06, 0x24}, - {0xf0, 0x36}, - {0x31, 0x82}, - {0x3e, 0x60}, - {0x30, 0xf0}, - {0x33, 0x33}, - {0xf0, 0x34}, - {0x9f, 0x02}, - {0xa6, 0x40}, - {0xa7, 0x47}, - {0xe8, 0x5f}, - {0xa8, 0x51}, - {0xa9, 0x44}, - {0xe9, 0x36}, - {0xf0, 0x33}, - {0xb3, 0x51}, - {0x64, 0x17}, - {0x90, 0x01}, - {0x91, 0x03}, - {0x92, 0x07}, - {0x01, 0x10}, - {0x93, 0x10}, - {0x94, 0x10}, - {0x95, 0x10}, - {0x96, 0x01}, - {0x97, 0x07}, - {0x98, 0x1f}, - {0x99, 0x10}, - {0x9a, 0x20}, - {0x9b, 0x28}, - {0x9c, 0x28}, - {0xf0, 0x36}, - {0x70, 0x54}, - {0xb6, 0x40}, - {0xb7, 0x41}, - {0xb8, 0x43}, - {0xb9, 0x47}, - {0xba, 0x4f}, - {0xb0, 0x8b}, - {0xb1, 0x8b}, - {0xb2, 0x8b}, - {0xb3, 0x9b}, - {0xb4, 0xb8}, - {0xb5, 0xf0}, - {0x7e, 0x41}, - {0x7f, 0x47}, - {0x77, 0x80}, - {0x78, 0x84}, - {0x79, 0x8a}, - {0xa0, 0x47}, - {0xa1, 0x5f}, - {0x96, 0x43}, - {0x97, 0x44}, - {0x98, 0x54}, - {0xf0, 0x00}, - {0xf0, 0x01}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x70, 0x00}, - {0x71, 0x80}, - {0xf0, 0x36}, - {0x37, 0x74}, - {0xf0, 0x3f}, - {0x03, 0xa1}, - {0xf0, 0x36},//cvbs_off - {0x11, 0x80}, - {0xf0, 0x01}, - {0x79, 0xc1}, - {0xf0, 0x37}, - {0x24, 0x21}, - {0xf0, 0x36}, - {0x41, 0x00}, - {0xea, 0x09}, - {0xeb, 0x03}, - {0xec, 0x19}, - {0xed, 0x38}, - {0xe9, 0x30}, - {0xf0, 0x33}, - {0x33, 0x00}, - {0x34, 0x00}, - {0xb1, 0x00}, - {0xf0, 0x00}, - {0xe0, 0x04}, - {0xf0, 0x01}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x70, 0x00}, - {0x71, 0x80}, - {0xf0, 0x36}, - {0x32, 0x44}, - {0xf0, 0x36}, - {0x3e, 0xe0}, - {0x70, 0x56}, - {0x7c, 0x43}, - {0x7d, 0x47}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0xa0, 0x47}, - {0xa1, 0x5f}, - {0x96, 0x22}, - {0x97, 0x22}, - {0x98, 0x22}, - {0xf0, 0x00}, - {0x72, 0x38}, - {0x7a, 0x80}, - {0x85, 0x18}, - {0x9b, 0x35}, - {0x9e, 0x20}, - {0xd0, 0x66}, - {0xd1, 0x34}, - {0Xd3, 0x44}, - {0xd6, 0x44}, - {0xb0, 0x41}, - {0xb2, 0x48}, - {0xb3, 0xf4}, - {0xb4, 0x0b}, - {0xb5, 0x78}, - {0xba, 0xff}, - {0xbb, 0xc0}, - {0xbc, 0x90}, - {0xbd, 0x3a}, - {0xc1, 0x67}, - {0xf0, 0x01}, - {0x20, 0x11}, - {0x23, 0x90}, - {0x24, 0x15}, - {0x25, 0x87}, - {0xbc, 0x9f}, - {0xbd, 0x3a}, - {0x48, 0xe6}, - {0x49, 0xc0}, - {0x4a, 0xd0}, - {0x4b, 0x48}, - - // [cvbs_on] - {0xf0, 0x36}, - {0x11, 0x00}, - {0xf0, 0x01}, - {0x79, 0xf1}, - - // [cvbs_off] - {0xf0, 0x36}, - {0x11, 0x80}, - {0xf0, 0x01}, - {0x79, 0xc1}, -}; - -/* -[Sensor] -SensorName=SC031IOT -width=640 -height=480 -port=1 -type=2 -pin=3 -SlaveID=0xd0 -mode=0 -FlagReg=0xf7 -FlagMask=0xff -FlagData=0xfa -FlagReg1=0xf8 -FlagMask1=0xff -FlagData1=0x46 -outformat=0 -mclk=27 -avdd=2.80000 -dovdd=2.800000 -dvdd=1.5 - -Ext0=0 -Ext1=0 -Ext2=0 -AFVCC=0.0000 -VPP=0.000000 -*/ -/* 27M MCLK, 30fps -static const uint8_t sc030iot_default_init_regs[][2] = { - {0xf0, 0x30}, - {0x01, 0xff}, - {0x02, 0xff}, - {0x22, 0x07}, - {0x19, 0xff}, - {0x3f, 0x82}, - {0x30, 0x02}, - {0xf0, 0x01}, - {0x70, 0x00}, - {0x71, 0x80}, - {0x72, 0x20}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x75, 0x10}, - {0x76, 0x81}, - {0x77, 0x88}, - {0x78, 0xe1}, - {0x79, 0x01}, - {0xf5, 0x01}, - {0xf4, 0x0a}, - {0xf0, 0x36}, - {0x37, 0x79}, - {0x31, 0x82}, - {0x3e, 0x60}, - {0x30, 0xf0}, - {0x33, 0x33}, - {0xf0, 0x32}, - {0x48, 0x02}, - {0xf0, 0x33}, - {0x02, 0x12}, - {0x7c, 0x02}, - {0x7d, 0x0e}, - {0xa2, 0x04}, - {0x5e, 0x06}, - {0x5f, 0x0a}, - {0x0b, 0x58}, - {0x06, 0x38}, - {0xf0, 0x32}, - {0x48, 0x02}, - {0xf0, 0x39}, - {0x02, 0x70}, - {0xf0, 0x45}, - {0x09, 0x1c}, - {0xf0, 0x37}, - {0x22, 0x0d}, - {0xf0, 0x33}, - {0x33, 0x10}, - {0xb1, 0x80}, - {0x34, 0x40}, - {0x0b, 0x54}, - {0xb2, 0x78}, - {0xf0, 0x36}, - {0x11, 0x80}, - {0xf0, 0x30}, - {0x38, 0x44}, - {0xf0, 0x33}, - {0xb3, 0x51}, - {0x01, 0x10}, - {0x0b, 0x6c}, - {0x06, 0x24}, - {0xf0, 0x36}, - {0x31, 0x82}, - {0x3e, 0x60}, - {0x30, 0xf0}, - {0x33, 0x33}, - {0xf0, 0x34}, - {0x9f, 0x02}, - {0xa6, 0x40}, - {0xa7, 0x47}, - {0xe8, 0x5f}, - {0xa8, 0x51}, - {0xa9, 0x44}, - {0xe9, 0x36}, - {0xf0, 0x33}, - {0xb3, 0x51}, - {0x64, 0x17}, - {0x90, 0x01}, - {0x91, 0x03}, - {0x92, 0x07}, - {0x01, 0x10}, - {0x93, 0x10}, - {0x94, 0x10}, - {0x95, 0x10}, - {0x96, 0x01}, - {0x97, 0x07}, - {0x98, 0x1f}, - {0x99, 0x10}, - {0x9a, 0x20}, - {0x9b, 0x28}, - {0x9c, 0x28}, - {0xf0, 0x36}, - {0x70, 0x54}, - {0xb6, 0x40}, - {0xb7, 0x41}, - {0xb8, 0x43}, - {0xb9, 0x47}, - {0xba, 0x4f}, - {0xb0, 0x8b}, - {0xb1, 0x8b}, - {0xb2, 0x8b}, - {0xb3, 0x9b}, - {0xb4, 0xb8}, - {0xb5, 0xf0}, - {0x7e, 0x41}, - {0x7f, 0x47}, - {0x77, 0x80}, - {0x78, 0x84}, - {0x79, 0x8a}, - {0xa0, 0x47}, - {0xa1, 0x5f}, - {0x96, 0x43}, - {0x97, 0x44}, - {0x98, 0x54}, - {0xf0, 0x00}, - {0xf0, 0x01}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x70, 0x00}, - {0x71, 0x80}, - {0xf0, 0x36}, - {0x37, 0x74}, - {0xf0, 0x3f}, - {0x03, 0x93}, - {0xf0, 0x36},//cvbs_off - {0x11, 0x80}, - {0xf0, 0x01}, - {0x79, 0xc1}, - {0xf0, 0x37}, - {0x24, 0x21}, - {0xf0, 0x36}, - {0x41, 0x00}, - {0xe9, 0x2c}, - {0xf0, 0x33}, - {0x33, 0x00}, - {0x34, 0x00}, - {0xb1, 0x00}, - {0xf0, 0x00}, - {0xe0, 0x04}, - {0xf0, 0x01}, - {0x73, 0x00}, - {0x74, 0xe0}, - {0x70, 0x00}, - {0x71, 0x80}, - {0xf0, 0x36}, - {0x32, 0x44}, - {0xf0, 0x36}, - {0x3e, 0xe0}, - {0x70, 0x56}, - {0x7c, 0x43}, - {0x7d, 0x47}, - {0x74, 0x00}, - {0x75, 0x00}, - {0x76, 0x00}, - {0xa0, 0x47}, - {0xa1, 0x5f}, - {0x96, 0x22}, - {0x97, 0x22}, - {0x98, 0x22}, - {0xf0, 0x00}, - {0x72, 0x38}, - {0x7a, 0x80}, - {0x85, 0x18}, - {0x9b, 0x35}, - {0x9e, 0x20}, - {0xd0, 0x66}, - {0xd1, 0x34}, - {0Xd3, 0x44}, - {0xd6, 0x44}, - {0xb0, 0x41}, - {0xb2, 0x48}, - {0xb3, 0xf4}, - {0xb4, 0x0b}, - {0xb5, 0x78}, - {0xba, 0xff}, - {0xbb, 0xc0}, - {0xbc, 0x90}, - {0xbd, 0x3a}, - {0xc1, 0x67}, - {0xf0, 0x01}, - {0x20, 0x11}, - {0x23, 0x90}, - {0x24, 0x15}, - {0x25, 0x87}, - {0xbc, 0x9f}, - {0xbd, 0x3a}, - {0x48, 0xe6}, - {0x49, 0xc0}, - {0x4a, 0xd0}, - {0x4b, 0x48}, - - // [cvbs_on] - {0xf0, 0x36}, - {0x11, 0x00}, - {0xf0, 0x01}, - {0x79, 0xf1}, - - // [cvbs_off] - {0xf0, 0x36}, - {0x11, 0x80}, - {0xf0, 0x01}, - {0x79, 0xc1}, -}; - -*/ \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h deleted file mode 100644 index bf3cdecef8..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * SC031GS DVP driver. - * - */ -#ifndef __SC031GS_H__ -#define __SC030GS_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int sc031gs_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int sc031gs_init(sensor_t *sensor); - -#endif // __SC031GS_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h deleted file mode 100644 index 255c1b28a6..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc031gs_settings.h +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 -//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI -//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P -//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data -//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data -//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR -//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M -//pin :BIT0 pwdn// BIT1:reset -//avdd 0:2.8V// 1:2.5V// 2:1.8V -//dovdd 0:2.8V// 1:2.5V// 2:1.8V -//dvdd 0:1.8V// 1:1.5V// 2:1.2V - -/* -[database] -DBName=Dothinkey - -[vendor] -VendorName=SmartSens - -[sensor] -SensorName=SC031GS -width=200 -height=200 -port=1 -type=1 -pin=2 -SlaveID=0x60 -mode=3 -FlagReg=0x36FF -FlagMask=0xff -FlagData=0x00 -FlagReg1=0x36FF -FlagMask1=0xff -FlagData1=0x00 -outformat=3 -mclk=10 -avdd=2.800000 -dovdd=2.800000 -dvdd=1.500000 - -Ext0=0 -Ext1=0 -Ext2=0 -AFVCC=2.513000 -VPP=0.000000 -*/ -#include - -#define SC031GS_OUTPUT_WINDOW_START_X_H_REG 0x3212 -#define SC031GS_OUTPUT_WINDOW_START_X_L_REG 0x3213 -#define SC031GS_OUTPUT_WINDOW_START_Y_H_REG 0x3210 -#define SC031GS_OUTPUT_WINDOW_START_Y_L_REG 0x3211 -#define SC031GS_OUTPUT_WINDOW_WIDTH_H_REG 0x3208 -#define SC031GS_OUTPUT_WINDOW_WIDTH_L_REG 0x3209 -#define SC031GS_OUTPUT_WINDOW_HIGH_H_REG 0x320a -#define SC031GS_OUTPUT_WINDOW_HIGH_L_REG 0x320b -#define SC031GS_LED_STROBE_ENABLE_REG 0x3361 // When the camera is in exposure, this PAD LEDSTROBE will be high to drive the external LED. - -#define REG_NULL 0xFFFF -#define REG_DELAY 0X0000 - -struct sc031gs_regval { - uint16_t addr; - uint8_t val; -}; - -// 200*200, xclk=10M, fps=120fps -static const struct sc031gs_regval sc031gs_default_init_regs[] = { - {0x0103, 0x01}, // soft reset. - {REG_DELAY, 10}, // delay. - {0x0100, 0x00}, - {0x36e9, 0x80}, - {0x36f9, 0x80}, - {0x300f, 0x0f}, - {0x3018, 0x1f}, - {0x3019, 0xff}, - {0x301c, 0xb4}, - {0x301f, 0x7b}, - {0x3028, 0x82}, - {0x3200, 0x00}, - {0x3201, 0xdc}, - {0x3202, 0x00}, - {0x3203, 0x98}, - {0x3204, 0x01}, - {0x3205, 0xb3}, - {0x3206, 0x01}, - {0x3207, 0x67}, - {SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, 0x00}, - {SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, 0xc8}, - {SC031GS_OUTPUT_WINDOW_HIGH_H_REG, 0x00}, - {SC031GS_OUTPUT_WINDOW_HIGH_L_REG, 0xc8}, - {0x320c, 0x03}, - {0x320d, 0x6b}, - {0x320e, 0x01}, //default 120fps: {0x320e, 0x01},{0x320f, 0x40}, 58fps: {0x320e, 0x02},{0x320f, 0xab}; 30fps: {0x320e, 0x05}, {0x320f, 0x34} - {0x320f, 0x40}, - {SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x00}, - {SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08}, - {SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x00}, - {SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x04}, - {0x3220, 0x10}, - {0x3223, 0x50}, - {0x3250, 0xf0}, - {0x3251, 0x02}, - {0x3252, 0x01}, - {0x3253, 0x3b}, - {0x3254, 0x02}, - {0x3255, 0x07}, - {0x3304, 0x48}, - {0x3306, 0x38}, - {0x3309, 0x50}, - {0x330b, 0xe0}, - {0x330c, 0x18}, - {0x330f, 0x20}, - {0x3310, 0x10}, - {0x3314, 0x70}, - {0x3315, 0x38}, - {0x3316, 0x68}, - {0x3317, 0x0d}, - {0x3329, 0x5c}, - {0x332d, 0x5c}, - {0x332f, 0x60}, - {0x3335, 0x64}, - {0x3344, 0x64}, - {0x335b, 0x80}, - {0x335f, 0x80}, - {0x3366, 0x06}, - {0x3385, 0x41}, - {0x3387, 0x49}, - {0x3389, 0x01}, - {0x33b1, 0x03}, - {0x33b2, 0x06}, - {0x3621, 0xa4}, - {0x3622, 0x05}, - {0x3624, 0x47}, - {0x3631, 0x48}, - {0x3633, 0x52}, - {0x3635, 0x18}, - {0x3636, 0x25}, - {0x3637, 0x89}, - {0x3638, 0x0f}, - {0x3639, 0x08}, - {0x363a, 0x00}, - {0x363b, 0x48}, - {0x363c, 0x06}, - {0x363e, 0xf8}, - {0x3640, 0x00}, - {0x3641, 0x01}, - {0x36ea, 0x39}, - {0x36eb, 0x1e}, - {0x36ec, 0x0e}, - {0x36ed, 0x23}, - {0x36fa, 0x39}, - {0x36fb, 0x10}, - {0x36fc, 0x01}, - {0x36fd, 0x03}, - {0x3908, 0x91}, - {0x3d08, 0x01}, - {0x3d04, 0x04}, - {0x3e01, 0x13}, - {0x3e02, 0xa0}, - {0x3e06, 0x0c}, - {0x3f04, 0x03}, - {0x3f05, 0x4b}, - {0x4500, 0x59}, - {0x4501, 0xc4}, - {0x4809, 0x01}, - {0x4837, 0x39}, - {0x5011, 0x00}, - {0x36e9, 0x04}, - {0x36f9, 0x04}, - {0x0100, 0x01}, - - //delay 10ms - {REG_DELAY, 0X0a}, - {0x4418, 0x08}, - {0x4419, 0x80}, - {0x363d, 0x10}, - {0x3630, 0x48}, - - // [gain<4] - {0x3317, 0x0d}, - {0x3314, 0x70}, - - // [gain>=4] - {0x3314, 0x68}, - {0x3317, 0x0e}, - {REG_NULL, 0x00}, -}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h deleted file mode 100644 index 85858498ec..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * - * SC101IOT DVP driver. - * - */ -#ifndef __SC101IOT_H__ -#define __SC101IOT_H__ - -#include "sensor.h" - -/** - * @brief Detect sensor pid - * - * @param slv_addr SCCB address - * @param id Detection result - * @return - * 0: Can't detect this sensor - * Nonzero: This sensor has been detected - */ -int sc101iot_detect(int slv_addr, sensor_id_t *id); - -/** - * @brief initialize sensor function pointers - * - * @param sensor pointer of sensor - * @return - * Always 0 - */ -int sc101iot_init(sensor_t *sensor); - -#endif // __SC101IOT_H__ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h deleted file mode 100644 index 2eb143982a..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/private_include/sc101iot_settings.h +++ /dev/null @@ -1,257 +0,0 @@ -//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 -//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI -//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P -//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data -//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data -//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR -//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M -//pin :BIT0 pwdn// BIT1:reset -//avdd 0:2.8V// 1:2.5V// 2:1.8V -//dovdd 0:2.8V// 1:2.5V// 2:1.8V -//dvdd 0:1.8V// 1:1.5V// 2:1.2V -/* -[DataBase] -DBName=DemoSens - -[Vendor] -VendorName=SmartSens -I2C_CRC=0 - -[Sensor] -SensorName=SC101AP_raw -width=1280 -height=720 -port=1 -type=2 -pin=3 -SlaveID=0xd0 -mode=0 -FlagReg=0xf7 -FlagMask=0xff -FlagData=0xda -FlagReg1=0xf8 -FlagMask1=0xff -FlagData1=0x4a -outformat=0 -mclk=20 -avdd=2.800000 -dovdd=2.800000 -dvdd=1.200000 - -Ext0=0 -Ext1=0 -Ext2=0 -AFVCC=0.00 -VPP=0.000000 -*/ -#include - -static const uint8_t sc101iot_default_init_regs[][2] = { -#if CONFIG_SC101IOT_720P_15FPS_ENABLED // 720P+YUV422+15FPS sensor default regs -/* Here are some test results: -# size xclk fps pic pclk -# ------- ------- ------ --------- ------- --- --- --- --- --- -# 720p 4 3 err -# 720p 8 5 normal 15 -# 720p 10 7.8 normal 19 -# 720p 20 15 warning 37.5 -# VGA 8 6 normal -# VGA 20 16 normal - -*/ - {0xf0, 0x30}, - {0x01, 0xff}, - {0x02, 0xe0}, - {0x30, 0x10}, - {0x3f, 0x81}, - {0xf0, 0x00}, - {0x70, 0x6b}, - {0x72, 0x30}, - {0x84, 0xb4}, - {0x8b, 0x00}, - {0x8c, 0x20}, - {0x8d, 0x02}, - {0x8e, 0xec}, - {0x9e, 0x10}, - {0xb0, 0xc1}, - {0xc8, 0x10}, - {0xc9, 0x10}, - {0xc6, 0x00}, - {0xe0, 0x0f}, - {0xb5, 0xf0}, - {0xde, 0x80}, - {0xb5, 0xf0}, - {0xde, 0x80}, - {0xb2, 0x50}, - {0xb3, 0xfc}, - {0xb4, 0x40}, - {0xb5, 0xc0}, - {0xb6, 0x50}, - {0xb7, 0xfc}, - {0xb8, 0x40}, - {0xb9, 0xc0}, - {0xba, 0xff}, - {0xbb, 0xcc}, - {0xbc, 0xa9}, - {0xbd, 0x7d}, - {0xc1, 0x77}, - {0xf0, 0x01}, - {0x70, 0x02}, - {0x71, 0x02}, - {0x72, 0x50}, - {0x73, 0x02}, - {0x74, 0xd2}, - {0x75, 0x20}, - {0x76, 0x81}, - {0x77, 0x8c}, - {0x78, 0x81}, - {0xf4, 0x01}, - {0xf5, 0x00}, - {0xf6, 0x00}, - {0xf0, 0x36}, - {0x40, 0x03}, - {0x41, 0x01}, - {0xf0, 0x39}, - {0x02, 0x70}, - {0xf0, 0x32}, - {0x41, 0x00}, - {0x43, 0x01}, - {0x48, 0x02}, - {0xf0, 0x45}, - {0x09, 0x20}, - {0xf0, 0x33}, - {0x33, 0x10}, - {0xf0, 0x30}, - {0x38, 0x44}, - {0xf0, 0x39}, - {0x07, 0x00}, - {0x08, 0x19}, - {0x47, 0x00}, - {0x48, 0x00}, - {0xf0, 0x37}, - {0x24, 0x31}, - {0xf0, 0x34}, - {0x9f, 0x02}, - {0xa6, 0x51}, - {0xa7, 0x57}, - {0xe8, 0x5f}, - {0xa8, 0x50}, - {0xa9, 0x50}, - {0xe9, 0x50}, - {0xf0, 0x33}, - {0xb3, 0x58}, - {0xb2, 0x78}, - {0xf0, 0x34}, - {0x9f, 0x03}, - {0xa6, 0x51}, - {0xa7, 0x57}, - {0xaa, 0x01}, - {0xab, 0x28}, - {0xac, 0x01}, - {0xad, 0x38}, - {0xf0, 0x33}, - {0x0a, 0x01}, - {0x0b, 0x28}, - {0xf0, 0x33}, - {0x64, 0x0f}, - {0xec, 0x51}, - {0xed, 0x57}, - {0x06, 0x58}, - {0xe9, 0x58}, - {0xeb, 0x68}, - {0xf0, 0x33}, - {0x64, 0x0f}, - {0xf0, 0x36}, - {0x70, 0xdf}, - {0xb6, 0x40}, - {0xb7, 0x51}, - {0xb8, 0x53}, - {0xb9, 0x57}, - {0xba, 0x5f}, - {0xb0, 0x84}, - {0xb1, 0x82}, - {0xb2, 0x84}, - {0xb3, 0x88}, - {0xb4, 0x90}, - {0xb5, 0x90}, - {0xf0, 0x36}, - {0x7e, 0x50}, - {0x7f, 0x51}, - {0x77, 0x81}, - {0x78, 0x86}, - {0x79, 0x89}, - {0xf0, 0x36}, - {0x70, 0xdf}, - {0x9c, 0x51}, - {0x9d, 0x57}, - {0x90, 0x54}, - {0x91, 0x54}, - {0x92, 0x56}, - {0xf0, 0x36}, - {0xa0, 0x51}, - {0xa1, 0x57}, - {0x96, 0x33}, - {0x97, 0x43}, - {0x98, 0x43}, - {0xf0, 0x36}, - {0x70, 0xdf}, - {0x7c, 0x40}, - {0x7d, 0x53}, - {0x74, 0xd0}, - {0x75, 0xf0}, - {0x76, 0xf0}, - {0xf0, 0x37}, - {0x0f, 0xd5}, - {0x7a, 0x40}, - {0x7b, 0x57}, - {0x71, 0x09}, - {0x72, 0x09}, - {0x73, 0x05}, - {0xf0, 0x33}, - {0x01, 0x44}, - {0xf0, 0x36}, - {0x37, 0xfb}, - {0xf0, 0x36}, - {0x3c, 0x0d}, - {0xf0, 0x33}, - {0x14, 0x95}, - {0xf0, 0x33}, - {0x8f, 0x80}, - {0xf0, 0x37}, - {0x27, 0x14}, - {0x28, 0x03}, - {0xf0, 0x36}, - {0x37, 0xf4}, - {0xf0, 0x33}, - {0x01, 0x44}, - {0xf0, 0x36}, - {0x79, 0x89}, - {0xf0, 0x34}, - {0xac, 0x01}, - {0xad, 0x40}, - {0xf0, 0x33}, - {0xeb, 0x70}, - {0xf0, 0x34}, - {0xa8, 0x50}, - {0xa9, 0x50}, - {0xf0, 0x33}, - {0xb3, 0x58}, - {0xf0, 0x36}, - {0x11, 0x80}, - {0xf0, 0x36}, - {0x41, 0x51}, - {0xf0, 0x3f}, - {0x03, 0x09}, - {0xf0, 0x32}, - {0x0c, 0x06}, - {0x0d, 0x82}, - {0x0e, 0x02}, - {0x0f, 0xee}, - {0xf0, 0x36}, - {0xea, 0x09}, - {0xeb, 0xf5}, - {0xec, 0x11}, - {0xed, 0x27}, - {0xe9, 0x20}, -#endif -}; diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c deleted file mode 100644 index 86f525f376..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc030iot.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * SC030IOT driver. - * - * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "sc030iot.h" -#include "sc030iot_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "sc030"; -#endif - -#define SC030_SENSOR_ID_HIGH_REG 0XF7 -#define SC030_SENSOR_ID_LOW_REG 0XF8 -#define SC030_MAX_FRAME_WIDTH (640) -#define SC030_MAX_FRAME_HIGH (480) - -// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. -// For more information please refer to the Technical Reference Manual. -static int get_reg(sensor_t *sensor, int reg, int reg_value_mask) -{ - int ret = 0; - uint8_t reg_high = (reg>>8) & 0xFF; - uint8_t reg_low = reg & 0xFF; - - if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { - return -1; - } - - ret = SCCB_Read(sensor->slv_addr, reg_low); - if(ret > 0){ - ret &= reg_value_mask; - } - return ret; -} - -// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. -// For more information please refer to the Technical Reference Manual. -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - uint8_t reg_high = (reg>>8) & 0xFF; - uint8_t reg_low = reg & 0xFF; - - if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { - return -1; - } - - ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF); - return ret; -} - -static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len) -{ - int i=0, res = 0; - while (islv_addr, regs[i][0], regs[i][1]); - if (res) { - return res; - } - i++; - } - return res; -} - -static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - ret = get_reg(sensor, reg, 0xff); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value); - return ret; -} - -#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;} -#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} -#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on - } else { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off - } - - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on - } else { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off - } - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable test pattern mode - - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement - WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value - WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit - - return ret; -} - -static int set_agc_gain(sensor_t *sensor, int gain) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control - WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1 - WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2 - WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3 - WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4 - - return ret; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control - WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target - - return ret; -} - -static int set_awb_gain(sensor_t *sensor, int value) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control - WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain - WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control - WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128) - WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128) - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control - WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64) - return ret; -} - -static int reset(sensor_t *sensor) -{ - int ret = set_regs(sensor, sc030iot_default_init_regs, sizeof(sc030iot_default_init_regs)/(sizeof(uint8_t) * 2)); - - // Delay - vTaskDelay(50 / portTICK_PERIOD_MS); - - // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor - // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff)); - if (ret) { - ESP_LOGE(TAG, "reset fail"); - } - return ret; -} - -static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) -{ - int ret = 0; - //sc:H_start={0x0172[1:0],0x0170},H_end={0x0172[5:4],0x0171}, - WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff); - WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff); - WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x03) | (((offset_x+w)>>4)&0x30)); - - //sc:V_start={0x0175[1:0],0x0173},H_end={0x0175[5:4],0x0174}, - WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff); - WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff); - WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x03) | (((offset_y+h)>>4)&0x30)); - - vTaskDelay(10 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - if(w>SC030_MAX_FRAME_WIDTH || h > SC030_MAX_FRAME_HIGH) { - goto err; - } - - uint16_t offset_x = (640-w) /2; - uint16_t offset_y = (480-h) /2; - - if(set_window(sensor, offset_x, offset_y, w, h)) { - goto err; - } - - sensor->status.framesize = framesize; - return 0; -err: - ESP_LOGE(TAG, "frame size err"); - return -1; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret=0; - sensor->pixformat = pixformat; - - switch (pixformat) { - case PIXFORMAT_RGB565: - case PIXFORMAT_RAW: - case PIXFORMAT_GRAYSCALE: - ESP_LOGE(TAG, "Not support"); - break; - case PIXFORMAT_YUV422: // For now, sc030/sc031 sensor only support YUV422. - break; - default: - return -1; - } - - return ret; -} - -static int init_status(sensor_t *sensor) -{ - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int sc030iot_detect(int slv_addr, sensor_id_t *id) -{ - if (SC030IOT_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read(slv_addr, SC030_SENSOR_ID_LOW_REG); - uint8_t MIDH = SCCB_Read(slv_addr, SC030_SENSOR_ID_HIGH_REG); - uint16_t PID = MIDH << 8 | MIDL; - if (SC030IOT_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int sc030iot_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - - sensor->set_saturation= set_saturation; - sensor->set_colorbar = set_colorbar; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->set_sharpness = set_sharpness; - sensor->set_agc_gain = set_agc_gain; - sensor->set_aec_value = set_aec_value; - sensor->set_awb_gain = set_awb_gain; - sensor->set_contrast = set_contrast; - //not supported - sensor->set_denoise = set_dummy; - sensor->set_quality = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_xclk = set_xclk; - - ESP_LOGD(TAG, "sc030iot Attached"); - - return 0; -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c deleted file mode 100644 index dbd75ea054..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc031gs.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * SC031GS driver. - * - * Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "sc031gs.h" -#include "sc031gs_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "sc031gs"; -#endif - -#define SC031GS_PID_LOW_REG 0x3107 -#define SC031GS_PID_HIGH_REG 0x3108 -#define SC031GS_MAX_FRAME_WIDTH (640) -#define SC031GS_MAX_FRAME_HIGH (480) -#define SC031GS_GAIN_CTRL_COARSE_REG 0x3e08 -#define SC031GS_GAIN_CTRL_FINE_REG 0x3e09 - -#define SC031GS_PIDH_MAGIC 0x00 // High byte of sensor ID -#define SC031GS_PIDL_MAGIC 0x31 // Low byte of sensor ID - -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF); - if(ret > 0){ - ret &= mask; - } - return ret; -} - -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - ret = SCCB_Read16(sensor->slv_addr, reg & 0xFFFF); - if(ret < 0){ - return ret; - } - value = (ret & ~mask) | (value & mask); - ret = SCCB_Write16(sensor->slv_addr, reg & 0xFFFF, value); - return ret; -} - -static int set_reg_bits(sensor_t *sensor, uint16_t reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - ret = SCCB_Read16(sensor->slv_addr, reg); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = SCCB_Write16(sensor->slv_addr, reg, value); - return ret; -} - -static int write_regs(uint8_t slv_addr, const struct sc031gs_regval *regs) -{ - int i = 0, ret = 0; - while (!ret && regs[i].addr != REG_NULL) { - if (regs[i].addr == REG_DELAY) { - vTaskDelay(regs[i].val / portTICK_PERIOD_MS); - } else { - ret = SCCB_Write16(slv_addr, regs[i].addr, regs[i].val); - } - i++; - } - return ret; -} - -#define WRITE_REGS_OR_RETURN(regs) ret = write_regs(slv_addr, regs); if(ret){return ret;} -#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} -#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on - } else { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off - } - - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on - } else { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off - } - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x4501, 3, 1, enable & 0x01); // enable test pattern mode - SET_REG_BITS_OR_RETURN(0x3902, 6, 1, 1); // enable auto BLC, disable auto BLC if set to 0 - SET_REG_BITS_OR_RETURN(0x3e06, 0, 2, 3); // digital gain: 00->1x, 01->2x, 03->4x. - return ret; -} - -static int set_special_effect(sensor_t *sensor, int sleep_mode_enable) // For sc03ags sensor, This API used for sensor sleep mode control. -{ - // Add some others special control in this API, use switch to control different funcs, such as ctrl_id. - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0100, 0, 1, !(sleep_mode_enable & 0x01)); // 0: enable sleep mode. In sleep mode, the registers can be accessed. - return ret; -} - -int set_bpc(sensor_t *sensor, int enable) // // For sc03ags sensor, This API used to control BLC -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x3900, 0, 1, enable & 0x01); - SET_REG_BITS_OR_RETURN(0x3902, 6, 1, enable & 0x01); - return ret; -} - -static int set_agc_gain(sensor_t *sensor, int gain) -{ - // sc031gs doesn't support AGC, use this func to control. - int ret = 0; - uint32_t coarse_gain, fine_gain, fine_again_reg_v, coarse_gain_reg_v; - - if (gain < 0x20) { - WRITE_REG_OR_RETURN(0x3314, 0x3a); - WRITE_REG_OR_RETURN(0x3317, 0x20); - } else { - WRITE_REG_OR_RETURN(0x3314, 0x44); - WRITE_REG_OR_RETURN(0x3317, 0x0f); - } - - if (gain < 0x20) { /*1x ~ 2x*/ - fine_gain = gain - 16; - coarse_gain = 0x03; - fine_again_reg_v = ((0x01 << 4) & 0x10) | - (fine_gain & 0x0f); - coarse_gain_reg_v = coarse_gain & 0x1F; - } else if (gain < 0x40) { /*2x ~ 4x*/ - fine_gain = (gain >> 1) - 16; - coarse_gain = 0x7; - fine_again_reg_v = ((0x01 << 4) & 0x10) | - (fine_gain & 0x0f); - coarse_gain_reg_v = coarse_gain & 0x1F; - } else if (gain < 0x80) { /*4x ~ 8x*/ - fine_gain = (gain >> 2) - 16; - coarse_gain = 0xf; - fine_again_reg_v = ((0x01 << 4) & 0x10) | - (fine_gain & 0x0f); - coarse_gain_reg_v = coarse_gain & 0x1F; - } else { /*8x ~ 16x*/ - fine_gain = (gain >> 3) - 16; - coarse_gain = 0x1f; - fine_again_reg_v = ((0x01 << 4) & 0x10) | - (fine_gain & 0x0f); - coarse_gain_reg_v = coarse_gain & 0x1F; - } - - WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_COARSE_REG, coarse_gain_reg_v); - WRITE_REG_OR_RETURN(SC031GS_GAIN_CTRL_FINE_REG, fine_again_reg_v); - - return ret; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - // For now, HDR is disabled, the sensor work in normal mode. - int ret = 0; - WRITE_REG_OR_RETURN(0x3e01, value & 0xFF); // AE target high - WRITE_REG_OR_RETURN(0x3e02, (value >> 8) & 0xFF); // AE target low - - return ret; -} - -static int reset(sensor_t *sensor) -{ - int ret = write_regs(sensor->slv_addr, sc031gs_default_init_regs); - if (ret) { - ESP_LOGE(TAG, "reset fail"); - } - // printf("reg 0x3d04=%02x\r\n", get_reg(sensor, 0x3d04, 0xff)); - // set_colorbar(sensor, 1); - return ret; -} - -static int set_output_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) -{ - int ret = 0; - //sc:H_start={0x3212[1:0],0x3213},H_length={0x3208[1:0],0x3209}, - // printf("%d, %d, %d, %d\r\n", ((offset_x>>8) & 0x03), offset_x & 0xff, ((w>>8) & 0x03), w & 0xff); - - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x0); // For now, we use x_start is 0x04 - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x04); - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, ((w>>8) & 0x03)); - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, w & 0xff); - - //sc:V_start={0x3210[1:0],0x3211},V_length={0x320a[1:0],0x320b}, - // printf("%d, %d, %d, %d\r\n", ((offset_y>>8) & 0x03), offset_y & 0xff, ((h>>8) & 0x03), h & 0xff); - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x0); // For now, we use y_start is 0x08 - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08); - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_H_REG, ((h>>8) & 0x03)); - WRITE_REG_OR_RETURN(SC031GS_OUTPUT_WINDOW_HIGH_L_REG, h & 0xff); - - vTaskDelay(10 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - if(w > SC031GS_MAX_FRAME_WIDTH || h > SC031GS_MAX_FRAME_HIGH) { - goto err; - } - - if(w != 200 || h != 200) { - ESP_LOGE(TAG, "Only support 200*200 for now, contact us if you want to use other resolutions"); - goto err; - } - - uint16_t offset_x = (640-w) /2 + 4; - uint16_t offset_y = (480-h) /2 + 4; - - if(set_output_window(sensor, offset_x, offset_y, w, h)) { - goto err; - } - - sensor->status.framesize = framesize; - return 0; -err: - ESP_LOGE(TAG, "frame size err"); - return -1; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret=0; - sensor->pixformat = pixformat; - - switch (pixformat) { - case PIXFORMAT_GRAYSCALE: - break; - default: - ESP_LOGE(TAG, "Only support GRAYSCALE(Y8)"); - return -1; - } - - return ret; -} - -static int init_status(sensor_t *sensor) -{ - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int sc031gs_detect(int slv_addr, sensor_id_t *id) -{ - if (SC031GS_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read16(slv_addr, SC031GS_PID_HIGH_REG); - uint8_t MIDH = SCCB_Read16(slv_addr, SC031GS_PID_LOW_REG); - uint16_t PID = MIDH << 8 | MIDL; - if (SC031GS_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int sc031gs_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - - sensor->set_colorbar = set_colorbar; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->set_agc_gain = set_agc_gain; - sensor->set_aec_value = set_aec_value; - sensor->set_special_effect = set_special_effect; - - //not supported - sensor->set_awb_gain = set_dummy; - sensor->set_contrast = set_dummy; - sensor->set_sharpness = set_dummy; - sensor->set_saturation= set_dummy; - sensor->set_denoise = set_dummy; - sensor->set_quality = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_xclk = set_xclk; - - ESP_LOGD(TAG, "sc031gs Attached"); - - return 0; -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c deleted file mode 100644 index 310a04768b..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/sensors/sc101iot.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * SC101IOT driver. - * - * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include -#include -#include -#include -#include "sccb.h" -#include "xclk.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#include "sc101iot.h" -#include "sc101iot_settings.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "sc101"; -#endif - -#define SC101_SENSOR_ID_HIGH_REG 0XF7 -#define SC101_SENSOR_ID_LOW_REG 0XF8 -#define SC101_MAX_FRAME_WIDTH (1280) -#define SC101_MAX_FRAME_HIGH (720) - -// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. -// For more information please refer to the Technical Reference Manual. -static int get_reg(sensor_t *sensor, int reg, int mask) -{ - int ret = 0; - uint8_t reg_high = (reg>>8) & 0xFF; - uint8_t reg_low = reg & 0xFF; - - if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { - return -1; - } - - ret = SCCB_Read(sensor->slv_addr, reg_low); - if(ret > 0){ - ret &= mask; - } - return ret; -} - -// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. -// For more information please refer to the Technical Reference Manual. -static int set_reg(sensor_t *sensor, int reg, int mask, int value) -{ - int ret = 0; - uint8_t reg_high = (reg>>8) & 0xFF; - uint8_t reg_low = reg & 0xFF; - - if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { - return -1; - } - - ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF); - return ret; -} - -static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len) -{ - int i=0, res = 0; - while (islv_addr, regs[i][0], regs[i][1]); - if (res) { - return res; - } - i++; - } - return res; -} - -static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value) -{ - int ret = 0; - ret = get_reg(sensor, reg, 0xff); - if(ret < 0){ - return ret; - } - uint8_t mask = ((1 << length) - 1) << offset; - value = (ret & ~mask) | ((value << offset) & mask); - ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value); - return ret; -} - -#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;} -#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} -#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} - -static int set_hmirror(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // enable mirror - } else { - SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // disable mirror - } - - return ret; -} - -static int set_vflip(sensor_t *sensor, int enable) -{ - int ret = 0; - if(enable) { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on - } else { - SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off - } - - return ret; -} - -static int set_colorbar(sensor_t *sensor, int enable) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable colorbar mode - return ret; -} - -static int set_raw_gma(sensor_t *sensor, int enable) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00f5, 1, 1, enable & 0xff); // enable gamma compensation - - return ret; -} - -static int set_sharpness(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement - WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value - WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit - - return ret; -} - -static int set_agc_gain(sensor_t *sensor, int gain) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control - WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1 - WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2 - WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3 - WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4 - - return ret; -} - -static int set_aec_value(sensor_t *sensor, int value) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control - WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target - - return ret; -} - -static int set_awb_gain(sensor_t *sensor, int value) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control - WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain - WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain - return ret; -} - -static int set_saturation(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control - WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128) - WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128) - return ret; -} - -static int set_contrast(sensor_t *sensor, int level) -{ - int ret = 0; - SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control - WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64) - return ret; -} - -static int reset(sensor_t *sensor) -{ - int ret = set_regs(sensor, sc101iot_default_init_regs, sizeof(sc101iot_default_init_regs)/(sizeof(uint8_t) * 2)); - - // Delay - vTaskDelay(50 / portTICK_PERIOD_MS); - - // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor - // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff)); - if (ret) { - ESP_LOGE(TAG, "reset fail"); - } - return ret; -} - -static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) -{ - int ret = 0; - //sc:H_start={0x0172[3:0],0x0170},H_end={0x0172[7:4],0x0171}, - WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff); - WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff); - WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x0f) | (((offset_x+w)>>4)&0xf0)); - - //sc:V_start={0x0175[3:0],0x0173},H_end={0x0175[7:4],0x0174}, - WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff); - WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff); - WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x0f) | (((offset_y+h)>>4)&0xf0)); - - vTaskDelay(10 / portTICK_PERIOD_MS); - - return ret; -} - -static int set_framesize(sensor_t *sensor, framesize_t framesize) -{ - uint16_t w = resolution[framesize].width; - uint16_t h = resolution[framesize].height; - if(w>SC101_MAX_FRAME_WIDTH || h > SC101_MAX_FRAME_HIGH) { - goto err; - } - - uint16_t offset_x = (SC101_MAX_FRAME_WIDTH-w) /2; - uint16_t offset_y = (SC101_MAX_FRAME_HIGH-h) /2; - - if(set_window(sensor, offset_x, offset_y, w, h)) { - goto err; - } - - sensor->status.framesize = framesize; - return 0; -err: - ESP_LOGE(TAG, "frame size err"); - return -1; -} - -static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) -{ - int ret=0; - sensor->pixformat = pixformat; - - switch (pixformat) { - case PIXFORMAT_RGB565: - case PIXFORMAT_RAW: - case PIXFORMAT_GRAYSCALE: - ESP_LOGE(TAG, "Not support"); - break; - case PIXFORMAT_YUV422: // For now, sc101 sensor only support YUV422. - break; - default: - ret = -1; - } - - return ret; -} - -static int init_status(sensor_t *sensor) -{ - return 0; -} - -static int set_dummy(sensor_t *sensor, int val){ return -1; } - -static int set_xclk(sensor_t *sensor, int timer, int xclk) -{ - int ret = 0; - sensor->xclk_freq_hz = xclk * 1000000U; - ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); - return ret; -} - -int sc101iot_detect(int slv_addr, sensor_id_t *id) -{ - if (SC101IOT_SCCB_ADDR == slv_addr) { - uint8_t MIDL = SCCB_Read(slv_addr, SC101_SENSOR_ID_LOW_REG); - uint8_t MIDH = SCCB_Read(slv_addr, SC101_SENSOR_ID_HIGH_REG); - uint16_t PID = MIDH << 8 | MIDL; - if (SC101IOT_PID == PID) { - id->PID = PID; - return PID; - } else { - ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); - } - } - return 0; -} - -int sc101iot_init(sensor_t *sensor) -{ - // Set function pointers - sensor->reset = reset; - sensor->init_status = init_status; - sensor->set_pixformat = set_pixformat; - sensor->set_framesize = set_framesize; - sensor->set_hmirror = set_hmirror; - sensor->set_vflip = set_vflip; - sensor->set_colorbar = set_colorbar; - sensor->set_raw_gma = set_raw_gma; - sensor->set_sharpness = set_sharpness; - sensor->set_agc_gain = set_agc_gain; - sensor->set_aec_value = set_aec_value; - sensor->set_awb_gain = set_awb_gain; - sensor->set_saturation= set_saturation; - sensor->set_contrast = set_contrast; - - sensor->set_denoise = set_dummy; - sensor->set_quality = set_dummy; - sensor->set_special_effect = set_dummy; - sensor->set_wb_mode = set_dummy; - sensor->set_ae_level = set_dummy; - - - sensor->get_reg = get_reg; - sensor->set_reg = set_reg; - sensor->set_xclk = set_xclk; - - ESP_LOGD(TAG, "sc101iot Attached"); - - return 0; -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c deleted file mode 100644 index e1a2fee719..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32/ll_cam.c +++ /dev/null @@ -1,539 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include "soc/i2s_struct.h" -#include "esp_idf_version.h" -#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR > 1) -#include "hal/gpio_ll.h" -#else -#include "soc/gpio_periph.h" -#define esp_rom_delay_us ets_delay_us -static inline int gpio_ll_get_level(gpio_dev_t *hw, int gpio_num) -{ - if (gpio_num < 32) { - return (hw->in >> gpio_num) & 0x1; - } else { - return (hw->in1.data >> (gpio_num - 32)) & 0x1; - } -} -#endif -#include "ll_cam.h" -#include "xclk.h" -#include "cam_hal.h" - -#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3) -#include "esp_rom_gpio.h" -#endif - -#if (ESP_IDF_VERSION_MAJOR >= 5) -#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE -#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE -#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) -#endif - -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 2) -#define ets_delay_us esp_rom_delay_us -#endif - -static const char *TAG = "esp32 ll_cam"; - -#define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;} -#define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;} - -typedef union { - struct { - uint32_t sample2:8; - uint32_t unused2:8; - uint32_t sample1:8; - uint32_t unused1:8; - }; - uint32_t val; -} dma_elem_t; - -typedef enum { - /* camera sends byte sequence: s1, s2, s3, s4, ... - * fifo receives: 00 s1 00 s2, 00 s2 00 s3, 00 s3 00 s4, ... - */ - SM_0A0B_0B0C = 0, - /* camera sends byte sequence: s1, s2, s3, s4, ... - * fifo receives: 00 s1 00 s2, 00 s3 00 s4, ... - */ - SM_0A0B_0C0D = 1, - /* camera sends byte sequence: s1, s2, s3, s4, ... - * fifo receives: 00 s1 00 00, 00 s2 00 00, 00 s3 00 00, ... - */ - SM_0A00_0B00 = 3, -} i2s_sampling_mode_t; - -typedef size_t (*dma_filter_t)(uint8_t* dst, const uint8_t* src, size_t len); - -static i2s_sampling_mode_t sampling_mode = SM_0A00_0B00; - -static size_t ll_cam_bytes_per_sample(i2s_sampling_mode_t mode) -{ - switch(mode) { - case SM_0A00_0B00: - return 4; - case SM_0A0B_0B0C: - return 4; - case SM_0A0B_0C0D: - return 2; - default: - assert(0 && "invalid sampling mode"); - return 0; - } -} - -static size_t IRAM_ATTR ll_cam_dma_filter_jpeg(uint8_t* dst, const uint8_t* src, size_t len) -{ - const dma_elem_t* dma_el = (const dma_elem_t*)src; - size_t elements = len / sizeof(dma_elem_t); - size_t end = elements / 4; - // manually unrolling 4 iterations of the loop here - for (size_t i = 0; i < end; ++i) { - dst[0] = dma_el[0].sample1; - dst[1] = dma_el[1].sample1; - dst[2] = dma_el[2].sample1; - dst[3] = dma_el[3].sample1; - dma_el += 4; - dst += 4; - } - return elements; -} - -static size_t IRAM_ATTR ll_cam_dma_filter_grayscale(uint8_t* dst, const uint8_t* src, size_t len) -{ - const dma_elem_t* dma_el = (const dma_elem_t*)src; - size_t elements = len / sizeof(dma_elem_t); - size_t end = elements / 4; - for (size_t i = 0; i < end; ++i) { - // manually unrolling 4 iterations of the loop here - dst[0] = dma_el[0].sample1; - dst[1] = dma_el[1].sample1; - dst[2] = dma_el[2].sample1; - dst[3] = dma_el[3].sample1; - dma_el += 4; - dst += 4; - } - return elements; -} - -static size_t IRAM_ATTR ll_cam_dma_filter_grayscale_highspeed(uint8_t* dst, const uint8_t* src, size_t len) -{ - const dma_elem_t* dma_el = (const dma_elem_t*)src; - size_t elements = len / sizeof(dma_elem_t); - size_t end = elements / 8; - for (size_t i = 0; i < end; ++i) { - // manually unrolling 4 iterations of the loop here - dst[0] = dma_el[0].sample1; - dst[1] = dma_el[2].sample1; - dst[2] = dma_el[4].sample1; - dst[3] = dma_el[6].sample1; - dma_el += 8; - dst += 4; - } - // the final sample of a line in SM_0A0B_0B0C sampling mode needs special handling - if ((elements & 0x7) != 0) { - dst[0] = dma_el[0].sample1; - dst[1] = dma_el[2].sample1; - elements += 1; - } - return elements / 2; -} - -static size_t IRAM_ATTR ll_cam_dma_filter_yuyv(uint8_t* dst, const uint8_t* src, size_t len) -{ - const dma_elem_t* dma_el = (const dma_elem_t*)src; - size_t elements = len / sizeof(dma_elem_t); - size_t end = elements / 4; - for (size_t i = 0; i < end; ++i) { - dst[0] = dma_el[0].sample1;//y0 - dst[1] = dma_el[0].sample2;//u - dst[2] = dma_el[1].sample1;//y1 - dst[3] = dma_el[1].sample2;//v - - dst[4] = dma_el[2].sample1;//y0 - dst[5] = dma_el[2].sample2;//u - dst[6] = dma_el[3].sample1;//y1 - dst[7] = dma_el[3].sample2;//v - dma_el += 4; - dst += 8; - } - return elements * 2; -} - -static size_t IRAM_ATTR ll_cam_dma_filter_yuyv_highspeed(uint8_t* dst, const uint8_t* src, size_t len) -{ - const dma_elem_t* dma_el = (const dma_elem_t*)src; - size_t elements = len / sizeof(dma_elem_t); - size_t end = elements / 8; - for (size_t i = 0; i < end; ++i) { - dst[0] = dma_el[0].sample1;//y0 - dst[1] = dma_el[1].sample1;//u - dst[2] = dma_el[2].sample1;//y1 - dst[3] = dma_el[3].sample1;//v - - dst[4] = dma_el[4].sample1;//y0 - dst[5] = dma_el[5].sample1;//u - dst[6] = dma_el[6].sample1;//y1 - dst[7] = dma_el[7].sample1;//v - dma_el += 8; - dst += 8; - } - if ((elements & 0x7) != 0) { - dst[0] = dma_el[0].sample1;//y0 - dst[1] = dma_el[1].sample1;//u - dst[2] = dma_el[2].sample1;//y1 - dst[3] = dma_el[2].sample2;//v - elements += 4; - } - return elements; -} - -static void IRAM_ATTR ll_cam_vsync_isr(void *arg) -{ - //DBG_PIN_SET(1); - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - // filter - ets_delay_us(1); - if (gpio_ll_get_level(&GPIO, cam->vsync_pin) == !cam->vsync_invert) { - ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } - } - //DBG_PIN_SET(0); -} - -static void IRAM_ATTR ll_cam_dma_isr(void *arg) -{ - //DBG_PIN_SET(1); - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - - typeof(I2S0.int_st) status = I2S0.int_st; - if (status.val == 0) { - return; - } - - I2S0.int_clr.val = status.val; - - if (status.in_suc_eof) { - ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); - } - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } - //DBG_PIN_SET(0); -} - -bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) -{ - I2S0.conf.rx_start = 0; - I2S_ISR_DISABLE(in_suc_eof); - I2S0.in_link.stop = 1; - return true; -} - -esp_err_t ll_cam_deinit(cam_obj_t *cam) -{ - gpio_isr_handler_remove(cam->vsync_pin); - - if (cam->cam_intr_handle) { - esp_intr_free(cam->cam_intr_handle); - cam->cam_intr_handle = NULL; - } - gpio_uninstall_isr_service(); - return ESP_OK; -} - -bool ll_cam_start(cam_obj_t *cam, int frame_pos) -{ - I2S0.conf.rx_start = 0; - - I2S_ISR_ENABLE(in_suc_eof); - - I2S0.conf.rx_reset = 1; - I2S0.conf.rx_reset = 0; - I2S0.conf.rx_fifo_reset = 1; - I2S0.conf.rx_fifo_reset = 0; - I2S0.lc_conf.in_rst = 1; - I2S0.lc_conf.in_rst = 0; - I2S0.lc_conf.ahbm_fifo_rst = 1; - I2S0.lc_conf.ahbm_fifo_rst = 0; - I2S0.lc_conf.ahbm_rst = 1; - I2S0.lc_conf.ahbm_rst = 0; - - I2S0.rx_eof_num = cam->dma_half_buffer_size / sizeof(dma_elem_t); - I2S0.in_link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; - - I2S0.in_link.start = 1; - I2S0.conf.rx_start = 1; - return true; -} - -esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) -{ - // Enable and configure I2S peripheral - periph_module_enable(PERIPH_I2S0_MODULE); - - I2S0.conf.rx_reset = 1; - I2S0.conf.rx_reset = 0; - I2S0.conf.rx_fifo_reset = 1; - I2S0.conf.rx_fifo_reset = 0; - I2S0.lc_conf.in_rst = 1; - I2S0.lc_conf.in_rst = 0; - I2S0.lc_conf.ahbm_fifo_rst = 1; - I2S0.lc_conf.ahbm_fifo_rst = 0; - I2S0.lc_conf.ahbm_rst = 1; - I2S0.lc_conf.ahbm_rst = 0; - - I2S0.conf.rx_slave_mod = 1; - I2S0.conf.rx_right_first = 0; - I2S0.conf.rx_msb_right = 0; - I2S0.conf.rx_msb_shift = 0; - I2S0.conf.rx_mono = 0; - I2S0.conf.rx_short_sync = 0; - - I2S0.conf2.lcd_en = 1; - I2S0.conf2.camera_en = 1; - - // Configure clock divider - I2S0.clkm_conf.clkm_div_a = 0; - I2S0.clkm_conf.clkm_div_b = 0; - I2S0.clkm_conf.clkm_div_num = 2; - - I2S0.fifo_conf.dscr_en = 1; - I2S0.fifo_conf.rx_fifo_mod = sampling_mode; - I2S0.fifo_conf.rx_fifo_mod_force_en = 1; - - I2S0.conf_chan.rx_chan_mod = 1; - I2S0.sample_rate_conf.rx_bits_mod = 0; - I2S0.timing.val = 0; - I2S0.timing.rx_dsync_sw = 1; - - return ESP_OK; -} - -void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) -{ - if (en) { - gpio_intr_enable(cam->vsync_pin); - } else { - gpio_intr_disable(cam->vsync_pin); - } -} - -esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) -{ - gpio_config_t io_conf = {0}; - io_conf.intr_type = cam->vsync_invert ? GPIO_PIN_INTR_NEGEDGE : GPIO_PIN_INTR_POSEDGE; - io_conf.pin_bit_mask = 1ULL << config->pin_vsync; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM); - gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam); - gpio_intr_disable(config->pin_vsync); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); - gpio_matrix_in(config->pin_pclk, I2S0I_WS_IN_IDX, false); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); - gpio_matrix_in(config->pin_vsync, I2S0I_V_SYNC_IDX, false); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); - gpio_matrix_in(config->pin_href, I2S0I_H_SYNC_IDX, false); - - int data_pins[8] = { - config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, - }; - for (int i = 0; i < 8; i++) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); - gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); - gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); - gpio_matrix_in(data_pins[i], I2S0I_DATA_IN0_IDX + i, false); - } - - gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX, false); - return ESP_OK; -} - -esp_err_t ll_cam_init_isr(cam_obj_t *cam) -{ - return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, ll_cam_dma_isr, cam, &cam->cam_intr_handle); -} - -void ll_cam_do_vsync(cam_obj_t *cam) -{ -} - -uint8_t ll_cam_get_dma_align(cam_obj_t *cam) -{ - return 0; -} - -static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ - size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; - size_t dma_buffer_max = 2 * dma_half_buffer_max; - size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; - - size_t line_width = cam->width * cam->in_bytes_per_pixel; - size_t image_size = cam->height * line_width; - if (image_size > (4 * 1024 * 1024) || (line_width > dma_half_buffer_max)) { - ESP_LOGE(TAG, "Resolution too high"); - return 0; - } - - size_t node_size = node_max; - size_t nodes_per_line = 1; - size_t lines_per_node = 1; - size_t lines_per_half_buffer = 1; - size_t dma_half_buffer_min = node_max; - size_t dma_half_buffer = dma_half_buffer_max; - size_t dma_buffer_size = dma_buffer_max; - - // Calculate DMA Node Size so that it's divisable by or divisor of the line width - if(line_width >= node_max){ - // One or more nodes will be requied for one line - for(size_t i = node_max; i > 0; i=i-1){ - if ((line_width % i) == 0) { - node_size = i; - nodes_per_line = line_width / node_size; - break; - } - } - } else { - // One or more lines can fit into one node - for(size_t i = node_max; i > 0; i=i-1){ - if ((i % line_width) == 0) { - node_size = i; - lines_per_node = node_size / line_width; - while((cam->height % lines_per_node) != 0){ - lines_per_node = lines_per_node - 1; - node_size = lines_per_node * line_width; - } - break; - } - } - } - // Calculate minimum EOF size = max(mode_size, line_size) - dma_half_buffer_min = node_size * nodes_per_line; - // Calculate max EOF size divisable by node size - dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; - // Adjust EOF size so that height will be divisable by the number of lines in each EOF - lines_per_half_buffer = dma_half_buffer / line_width; - while((cam->height % lines_per_half_buffer) != 0){ - dma_half_buffer = dma_half_buffer - dma_half_buffer_min; - lines_per_half_buffer = dma_half_buffer / line_width; - } - // Calculate DMA size - dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; - - ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u, dma_half_buffer_min: %5u, dma_half_buffer: %5u," - "lines_per_half_buffer: %2u, dma_buffer_size: %5u, image_size: %u", - (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node, - (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), - (unsigned) (lines_per_half_buffer), (unsigned) (dma_buffer_size * cam->dma_bytes_per_item), (unsigned) image_size); - - cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; - cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; - cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; - cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; - return 1; -} - -bool ll_cam_dma_sizes(cam_obj_t *cam) -{ - cam->dma_bytes_per_item = ll_cam_bytes_per_sample(sampling_mode); - if (cam->jpeg_mode) { - cam->dma_half_buffer_cnt = 8; - cam->dma_node_buffer_size = 2048; - cam->dma_half_buffer_size = cam->dma_node_buffer_size * 2; - cam->dma_buffer_size = cam->dma_half_buffer_cnt * cam->dma_half_buffer_size; - } else { - return ll_cam_calc_rgb_dma(cam); - } - return 1; -} - -static dma_filter_t dma_filter = ll_cam_dma_filter_jpeg; - -size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) -{ - //DBG_PIN_SET(1); - size_t r = dma_filter(out, in, len); - //DBG_PIN_SET(0); - return r; -} - -esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) -{ - if (pix_format == PIXFORMAT_GRAYSCALE) { - if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { - if (xclk_freq_hz > 10000000) { - sampling_mode = SM_0A00_0B00; - dma_filter = ll_cam_dma_filter_yuyv_highspeed; - } else { - sampling_mode = SM_0A0B_0C0D; - dma_filter = ll_cam_dma_filter_yuyv; - } - cam->in_bytes_per_pixel = 1; // camera sends Y8 - } else { - if (xclk_freq_hz > 10000000 && sensor_pid != OV7725_PID) { - sampling_mode = SM_0A00_0B00; - dma_filter = ll_cam_dma_filter_grayscale_highspeed; - } else { - sampling_mode = SM_0A0B_0C0D; - dma_filter = ll_cam_dma_filter_grayscale; - } - cam->in_bytes_per_pixel = 2; // camera sends YU/YV - } - cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 - } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { - if (xclk_freq_hz > 10000000 && sensor_pid != OV7725_PID) { - if (sensor_pid == OV7670_PID) { - sampling_mode = SM_0A0B_0B0C; - } else { - sampling_mode = SM_0A00_0B00; - } - dma_filter = ll_cam_dma_filter_yuyv_highspeed; - } else { - sampling_mode = SM_0A0B_0C0D; - dma_filter = ll_cam_dma_filter_yuyv; - } - cam->in_bytes_per_pixel = 2; // camera sends YU/YV - cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 - } else if (pix_format == PIXFORMAT_JPEG) { - cam->in_bytes_per_pixel = 1; - cam->fb_bytes_per_pixel = 1; - dma_filter = ll_cam_dma_filter_jpeg; - sampling_mode = SM_0A00_0B00; - } else { - ESP_LOGE(TAG, "Requested format is not supported"); - return ESP_ERR_NOT_SUPPORTED; - } - I2S0.fifo_conf.rx_fifo_mod = sampling_mode; - return ESP_OK; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c deleted file mode 100644 index 93313e8f38..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/ll_cam.c +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include "soc/system_reg.h" -#include "soc/i2s_struct.h" -#include "hal/gpio_ll.h" -#include "ll_cam.h" -#include "xclk.h" -#include "cam_hal.h" - -#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3) -#include "esp_rom_gpio.h" -#endif - -#if (ESP_IDF_VERSION_MAJOR >= 5) -#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE -#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE -#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) -#define ets_delay_us(a) esp_rom_delay_us(a) -#endif - -static const char *TAG = "s2 ll_cam"; - -#define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;} -#define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;} - -static void IRAM_ATTR ll_cam_vsync_isr(void *arg) -{ - //DBG_PIN_SET(1); - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - // filter - ets_delay_us(1); - if (gpio_ll_get_level(&GPIO, cam->vsync_pin) == !cam->vsync_invert) { - ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); - } - - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } - //DBG_PIN_SET(0); -} - -static void IRAM_ATTR ll_cam_dma_isr(void *arg) -{ - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - - typeof(I2S0.int_st) status = I2S0.int_st; - if (status.val == 0) { - return; - } - - I2S0.int_clr.val = status.val; - - if (status.in_suc_eof) { - ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); - } - - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) -{ - I2S0.conf.rx_start = 0; - - if (cam->jpeg_mode || !cam->psram_mode) { - I2S_ISR_DISABLE(in_suc_eof); - } - - I2S0.in_link.stop = 1; - return true; -} - -esp_err_t ll_cam_deinit(cam_obj_t *cam) -{ - gpio_isr_handler_remove(cam->vsync_pin); - - if (cam->cam_intr_handle) { - esp_intr_free(cam->cam_intr_handle); - cam->cam_intr_handle = NULL; - } - gpio_uninstall_isr_service(); - return ESP_OK; -} - -bool ll_cam_start(cam_obj_t *cam, int frame_pos) -{ - I2S0.conf.rx_start = 0; - - if (cam->jpeg_mode || !cam->psram_mode) { - I2S_ISR_ENABLE(in_suc_eof); - } - - I2S0.conf.rx_reset = 1; - I2S0.conf.rx_reset = 0; - I2S0.conf.rx_fifo_reset = 1; - I2S0.conf.rx_fifo_reset = 0; - I2S0.lc_conf.in_rst = 1; - I2S0.lc_conf.in_rst = 0; - I2S0.lc_conf.ahbm_fifo_rst = 1; - I2S0.lc_conf.ahbm_fifo_rst = 0; - I2S0.lc_conf.ahbm_rst = 1; - I2S0.lc_conf.ahbm_rst = 0; - - I2S0.rx_eof_num = cam->dma_half_buffer_size; // Ping pong operation - if (!cam->psram_mode) { - I2S0.in_link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; - } else { - I2S0.in_link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff; - } - - I2S0.in_link.start = 1; - I2S0.conf.rx_start = 1; - return true; -} - -esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) -{ - esp_err_t err = camera_enable_out_clock(config); - if(err != ESP_OK) { - return err; - } - periph_module_enable(PERIPH_I2S0_MODULE); - // Configure the clock - I2S0.clkm_conf.clkm_div_num = 2; // 160MHz / 2 = 80MHz - I2S0.clkm_conf.clkm_div_b = 0; - I2S0.clkm_conf.clkm_div_a = 0; - I2S0.clkm_conf.clk_sel = 2; - I2S0.clkm_conf.clk_en = 1; - - - I2S0.conf.val = 0; - I2S0.fifo_conf.val = 0; - I2S0.fifo_conf.dscr_en = 1; - - I2S0.lc_conf.ahbm_fifo_rst = 1; - I2S0.lc_conf.ahbm_fifo_rst = 0; - I2S0.lc_conf.ahbm_rst = 1; - I2S0.lc_conf.ahbm_rst = 0; - I2S0.lc_conf.check_owner = 0; - //I2S0.lc_conf.indscr_burst_en = 1; - //I2S0.lc_conf.ext_mem_bk_size = 0; // DMA access external memory block size. 0: 16 bytes, 1: 32 bytes, 2:64 bytes, 3:reserved - - I2S0.timing.val = 0; - - I2S0.int_ena.val = 0; - I2S0.int_clr.val = ~0; - - I2S0.conf2.lcd_en = 1; - I2S0.conf2.camera_en = 1; - - // Configuration data format - I2S0.conf.rx_slave_mod = 1; - I2S0.conf.rx_right_first = 0; - I2S0.conf.rx_msb_right = cam->swap_data; - I2S0.conf.rx_short_sync = 0; - I2S0.conf.rx_mono = 0; - I2S0.conf.rx_msb_shift = 0; - I2S0.conf.rx_dma_equal = 1; - - // Configure sampling rate - I2S0.sample_rate_conf.rx_bck_div_num = 1; - I2S0.sample_rate_conf.rx_bits_mod = 8; - - I2S0.conf1.rx_pcm_bypass = 1; - - I2S0.conf2.i_v_sync_filter_en = 1; - I2S0.conf2.i_v_sync_filter_thres = 4; - I2S0.conf2.cam_sync_fifo_reset = 1; - I2S0.conf2.cam_sync_fifo_reset = 0; - - I2S0.conf_chan.rx_chan_mod = 1; - - I2S0.fifo_conf.rx_fifo_mod_force_en = 1; - I2S0.fifo_conf.rx_data_num = 32; - I2S0.fifo_conf.rx_fifo_mod = 2; - - I2S0.lc_conf.in_rst = 1; - I2S0.lc_conf.in_rst = 0; - - I2S0.conf.rx_start = 1; - - return ESP_OK; -} - -void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) -{ - if (en) { - gpio_intr_enable(cam->vsync_pin); - } else { - gpio_intr_disable(cam->vsync_pin); - } -} - -esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) -{ - gpio_config_t io_conf = {0}; - io_conf.intr_type = cam->vsync_invert ? GPIO_PIN_INTR_NEGEDGE : GPIO_PIN_INTR_POSEDGE; - io_conf.pin_bit_mask = 1ULL << config->pin_vsync; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pull_up_en = 1; - io_conf.pull_down_en = 0; - gpio_config(&io_conf); - gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM); - gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam); - gpio_intr_disable(config->pin_vsync); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); - gpio_matrix_in(config->pin_pclk, I2S0I_WS_IN_IDX, false); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); - gpio_matrix_in(config->pin_vsync, I2S0I_V_SYNC_IDX, cam->vsync_invert); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); - gpio_matrix_in(config->pin_href, I2S0I_H_SYNC_IDX, false); - - int data_pins[8] = { - config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, - }; - for (int i = 0; i < 8; i++) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); - gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); - gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); - // High bit alignment, IN16 is always the highest bit - // fifo accesses data by bit, when rx_bits_mod is 8, the data needs to be aligned by 8 bits - gpio_matrix_in(data_pins[i], I2S0I_DATA_IN0_IDX + 8 + i, false); - } - - gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX, false); - - return ESP_OK; -} - -esp_err_t ll_cam_init_isr(cam_obj_t *cam) -{ - return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, ll_cam_dma_isr, cam, &cam->cam_intr_handle); -} - -void ll_cam_do_vsync(cam_obj_t *cam) -{ - ll_cam_vsync_intr_enable(cam, false); - gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, !cam->vsync_invert); - ets_delay_us(10); - gpio_matrix_in(cam->vsync_pin, I2S0I_V_SYNC_IDX, cam->vsync_invert); - ll_cam_vsync_intr_enable(cam, true); -} - -uint8_t ll_cam_get_dma_align(cam_obj_t *cam) -{ - return 64;//16 << I2S0.lc_conf.ext_mem_bk_size; -} - -static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ - size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; - size_t line_width = cam->width * cam->in_bytes_per_pixel; - size_t node_size = node_max; - size_t nodes_per_line = 1; - size_t lines_per_node = 1; - - // Calculate DMA Node Size so that it's divisable by or divisor of the line width - if(line_width >= node_max){ - // One or more nodes will be requied for one line - for(size_t i = node_max; i > 0; i=i-1){ - if ((line_width % i) == 0) { - node_size = i; - nodes_per_line = line_width / node_size; - break; - } - } - } else { - // One or more lines can fit into one node - for(size_t i = node_max; i > 0; i=i-1){ - if ((i % line_width) == 0) { - node_size = i; - lines_per_node = node_size / line_width; - while((cam->height % lines_per_node) != 0){ - lines_per_node = lines_per_node - 1; - node_size = lines_per_node * line_width; - } - break; - } - } - } - - ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u", - (unsigned) (node_size * cam->dma_bytes_per_item), nodes_per_line, lines_per_node); - - cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; - - if (cam->psram_mode) { - cam->dma_buffer_size = cam->recv_size * cam->dma_bytes_per_item; - cam->dma_half_buffer_cnt = 2; - cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; - } else { - size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; - if (line_width > dma_half_buffer_max) { - ESP_LOGE(TAG, "Resolution too high"); - return 0; - } - - // Calculate minimum EOF size = max(mode_size, line_size) - size_t dma_half_buffer_min = node_size * nodes_per_line; - - // Calculate max EOF size divisable by node size - size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; - - // Adjust EOF size so that height will be divisable by the number of lines in each EOF - size_t lines_per_half_buffer = dma_half_buffer / line_width; - while((cam->height % lines_per_half_buffer) != 0){ - dma_half_buffer = dma_half_buffer - dma_half_buffer_min; - lines_per_half_buffer = dma_half_buffer / line_width; - } - - // Calculate DMA size - size_t dma_buffer_max = 2 * dma_half_buffer_max; - size_t dma_buffer_size = dma_buffer_max; - dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; - - ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u", - (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), - (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item)); - - cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; - cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; - cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; - } - return 1; -} - -bool ll_cam_dma_sizes(cam_obj_t *cam) -{ - cam->dma_bytes_per_item = 1; - if (cam->jpeg_mode) { - if (cam->psram_mode) { - cam->dma_buffer_size = cam->recv_size; - cam->dma_half_buffer_size = 1024; - cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; - cam->dma_node_buffer_size = cam->dma_half_buffer_size; - } else { - cam->dma_half_buffer_cnt = 16; - cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024; - cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; - cam->dma_node_buffer_size = cam->dma_half_buffer_size; - } - } else { - return ll_cam_calc_rgb_dma(cam); - } - return 1; -} - -size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) -{ - // YUV to Grayscale - if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) { - size_t end = len / 8; - for (size_t i = 0; i < end; ++i) { - out[0] = in[0]; - out[1] = in[2]; - out[2] = in[4]; - out[3] = in[6]; - out += 4; - in += 8; - } - return len / 2; - } - - // just memcpy - memcpy(out, in, len); - return len; -} - -esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) -{ - if (pix_format == PIXFORMAT_GRAYSCALE) { - if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { - cam->in_bytes_per_pixel = 1; // camera sends Y8 - } else { - cam->in_bytes_per_pixel = 2; // camera sends YU/YV - } - cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 - } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { - cam->in_bytes_per_pixel = 2; // camera sends YU/YV - cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 - } else if (pix_format == PIXFORMAT_JPEG) { - cam->in_bytes_per_pixel = 1; - cam->fb_bytes_per_pixel = 1; - } else { - ESP_LOGE(TAG, "Requested format is not supported"); - return ESP_ERR_NOT_SUPPORTED; - } - return ESP_OK; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h deleted file mode 100644 index 31fbc97cce..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s2/private_include/tjpgd.h +++ /dev/null @@ -1,99 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 -/----------------------------------------------------------------------------*/ -#ifndef _TJPGDEC -#define _TJPGDEC -/*---------------------------------------------------------------------------*/ -/* System Configurations */ - -#define JD_SZBUF 512 /* Size of stream input buffer */ -#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ -#define JD_USE_SCALE 1 /* Use descaling feature for output */ -#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ - -/*---------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; - -/* These types must be 8-bit integer */ -typedef char CHAR; -typedef unsigned char UCHAR; -typedef unsigned char BYTE; - -/* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - - -/* Error code */ -typedef enum { - JDR_OK = 0, /* 0: Succeeded */ - JDR_INTR, /* 1: Interrupted by output function */ - JDR_INP, /* 2: Device error or wrong termination of input stream */ - JDR_MEM1, /* 3: Insufficient memory pool for the image */ - JDR_MEM2, /* 4: Insufficient stream input buffer */ - JDR_PAR, /* 5: Parameter error */ - JDR_FMT1, /* 6: Data format error (may be damaged data) */ - JDR_FMT2, /* 7: Right format but not supported */ - JDR_FMT3 /* 8: Not supported JPEG standard */ -} JRESULT; - - - -/* Rectangular structure */ -typedef struct { - WORD left, right, top, bottom; -} JRECT; - - - -/* Decompressor object structure */ -typedef struct JDEC JDEC; -struct JDEC { - UINT dctr; /* Number of bytes available in the input buffer */ - BYTE* dptr; /* Current data read ptr */ - BYTE* inbuf; /* Bit stream input buffer */ - BYTE dmsk; /* Current bit in the current read byte */ - BYTE scale; /* Output scaling ratio */ - BYTE msx, msy; /* MCU size in unit of block (width, height) */ - BYTE qtid[3]; /* Quantization table ID of each component */ - SHORT dcv[3]; /* Previous DC element of each component */ - WORD nrst; /* Restart inverval */ - UINT width, height; /* Size of the input image (pixel) */ - BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ - WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ - BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ - LONG* qttbl[4]; /* Dequaitizer tables [id] */ - void* workbuf; /* Working buffer for IDCT and RGB output */ - BYTE* mcubuf; /* Working buffer for the MCU */ - void* pool; /* Pointer to available memory pool */ - UINT sz_pool; /* Size of momory pool (bytes available) */ - UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ - void* device; /* Pointer to I/O device identifiler for the session */ -}; - - - -/* TJpgDec API functions */ -JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); -JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TJPGDEC */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c deleted file mode 100644 index 28a260384d..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/esp32s3/ll_cam.c +++ /dev/null @@ -1,538 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include "soc/system_reg.h" -#include "soc/lcd_cam_struct.h" -#include "soc/lcd_cam_reg.h" -#include "soc/gdma_struct.h" -#include "soc/gdma_periph.h" -#include "soc/gdma_reg.h" -#include "ll_cam.h" -#include "cam_hal.h" -#include "esp_rom_gpio.h" - -#if (ESP_IDF_VERSION_MAJOR >= 5) -#include "soc/gpio_sig_map.h" -#include "soc/gpio_periph.h" -#include "soc/io_mux_reg.h" -#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c) -#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d) -#define ets_delay_us(a) esp_rom_delay_us(a) -#endif - -#if !defined(SOC_GDMA_PAIRS_PER_GROUP) && defined(SOC_GDMA_PAIRS_PER_GROUP_MAX) -#define SOC_GDMA_PAIRS_PER_GROUP SOC_GDMA_PAIRS_PER_GROUP_MAX -#endif - -static const char *TAG = "s3 ll_cam"; - -static void IRAM_ATTR ll_cam_vsync_isr(void *arg) -{ - //DBG_PIN_SET(1); - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - - typeof(LCD_CAM.lc_dma_int_st) status = LCD_CAM.lc_dma_int_st; - if (status.val == 0) { - return; - } - - LCD_CAM.lc_dma_int_clr.val = status.val; - - if (status.cam_vsync_int_st) { - ll_cam_send_event(cam, CAM_VSYNC_EVENT, &HPTaskAwoken); - } - - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } - //DBG_PIN_SET(0); -} - -static void IRAM_ATTR ll_cam_dma_isr(void *arg) -{ - cam_obj_t *cam = (cam_obj_t *)arg; - BaseType_t HPTaskAwoken = pdFALSE; - - typeof(GDMA.channel[cam->dma_num].in.int_st) status = GDMA.channel[cam->dma_num].in.int_st; - if (status.val == 0) { - return; - } - - GDMA.channel[cam->dma_num].in.int_clr.val = status.val; - - if (status.in_suc_eof) { - ll_cam_send_event(cam, CAM_IN_SUC_EOF_EVENT, &HPTaskAwoken); - } - - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) -{ - if (cam->jpeg_mode || !cam->psram_mode) { - GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 0; - GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1; - } - GDMA.channel[cam->dma_num].in.link.stop = 1; - return true; -} - -esp_err_t ll_cam_deinit(cam_obj_t *cam) -{ - if (cam->cam_intr_handle) { - esp_intr_free(cam->cam_intr_handle); - cam->cam_intr_handle = NULL; - } - - if (cam->dma_intr_handle) { - esp_intr_free(cam->dma_intr_handle); - cam->dma_intr_handle = NULL; - } - GDMA.channel[cam->dma_num].in.link.addr = 0x0; - - LCD_CAM.cam_ctrl1.cam_start = 0; - LCD_CAM.cam_ctrl1.cam_reset = 1; - LCD_CAM.cam_ctrl1.cam_reset = 0; - return ESP_OK; -} - -bool ll_cam_start(cam_obj_t *cam, int frame_pos) -{ - LCD_CAM.cam_ctrl1.cam_start = 0; - - if (cam->jpeg_mode || !cam->psram_mode) { - GDMA.channel[cam->dma_num].in.int_clr.in_suc_eof = 1; - GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 1; - } - - LCD_CAM.cam_ctrl1.cam_reset = 1; - LCD_CAM.cam_ctrl1.cam_reset = 0; - LCD_CAM.cam_ctrl1.cam_afifo_reset = 1; - LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; - GDMA.channel[cam->dma_num].in.conf0.in_rst = 1; - GDMA.channel[cam->dma_num].in.conf0.in_rst = 0; - - LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = cam->dma_half_buffer_size - 1; // Ping pong operation - - if (!cam->psram_mode) { - GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->dma[0]) & 0xfffff; - } else { - GDMA.channel[cam->dma_num].in.link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff; - } - - GDMA.channel[cam->dma_num].in.link.start = 1; - - LCD_CAM.cam_ctrl.cam_update = 1; - LCD_CAM.cam_ctrl1.cam_start = 1; - return true; -} - -static esp_err_t ll_cam_dma_init(cam_obj_t *cam) -{ - for (int x = (SOC_GDMA_PAIRS_PER_GROUP - 1); x >= 0; x--) { - if (GDMA.channel[x].in.link.addr == 0x0) { - cam->dma_num = x; - ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num); - break; - } - if (x == 0) { - cam_deinit(); - ESP_LOGE(TAG, "Can't found available GDMA channel"); - return ESP_FAIL; - } - } - - if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) { - REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); - REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); - } - - GDMA.channel[cam->dma_num].in.int_clr.val = ~0; - GDMA.channel[cam->dma_num].in.int_ena.val = 0; - - GDMA.channel[cam->dma_num].in.conf0.val = 0; - GDMA.channel[cam->dma_num].in.conf0.in_rst = 1; - GDMA.channel[cam->dma_num].in.conf0.in_rst = 0; - - //internal SRAM only - if (!cam->psram_mode) { - GDMA.channel[cam->dma_num].in.conf0.indscr_burst_en = 1; - GDMA.channel[cam->dma_num].in.conf0.in_data_burst_en = 1; - } - - GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0; - // GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2; - - GDMA.channel[cam->dma_num].in.peri_sel.sel = 5; - //GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15 - //GDMA.channel[cam->dma_num].in.sram_size.in_size = 6;//This register is used to configure the size of L2 Tx FIFO for Rx channel. 0:16 bytes, 1:24 bytes, 2:32 bytes, 3: 40 bytes, 4: 48 bytes, 5:56 bytes, 6: 64 bytes, 7: 72 bytes, 8: 80 bytes. - //GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15 - return ESP_OK; -} - -#if CONFIG_CAMERA_CONVERTER_ENABLED -static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t *config) -{ - esp_err_t ret = ESP_OK; - - switch (config->conv_mode) { - case YUV422_TO_YUV420: - if (config->pixel_format != PIXFORMAT_YUV422) { - ret = ESP_FAIL; - } else { - ESP_LOGI(TAG, "YUV422 to YUV420 mode"); - LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1; - LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0; - LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 1; - } - break; - case YUV422_TO_RGB565: - if (config->pixel_format != PIXFORMAT_YUV422) { - ret = ESP_FAIL; - } else { - ESP_LOGI(TAG, "YUV422 to RGB565 mode"); - LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3; - LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0; - LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0; - } - break; - default: - break; - } -#if CONFIG_LCD_CAM_CONV_BT709_ENABLED - LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 1; -#else - LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0; -#endif -#if CONFIG_LCD_CAM_CONV_FULL_RANGE_ENABLED - LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1; - LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1; -#else - LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0; - LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0; -#endif - LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1; - LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 1; - cam->conv_mode = config->conv_mode; - return ret; -} -#endif - -esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) -{ - esp_err_t ret = ESP_OK; - if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) { - REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); - REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); - } - - LCD_CAM.cam_ctrl.val = 0; - - LCD_CAM.cam_ctrl.cam_clkm_div_b = 0; - LCD_CAM.cam_ctrl.cam_clkm_div_a = 0; - LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / config->xclk_freq_hz; - LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. - - LCD_CAM.cam_ctrl.cam_stop_en = 0; - LCD_CAM.cam_ctrl.cam_vsync_filter_thres = 4; // Filter by LCD_CAM clock - LCD_CAM.cam_ctrl.cam_update = 0; - LCD_CAM.cam_ctrl.cam_byte_order = cam->swap_data; - LCD_CAM.cam_ctrl.cam_bit_order = 0; - LCD_CAM.cam_ctrl.cam_line_int_en = 0; - LCD_CAM.cam_ctrl.cam_vs_eof_en = 0; //1: CAM_VSYNC to generate in_suc_eof. 0: in_suc_eof is controlled by reg_cam_rec_data_cyclelen - - LCD_CAM.cam_ctrl1.val = 0; - LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE - 1; // Cannot be assigned to 0, and it is easy to overflow - LCD_CAM.cam_ctrl1.cam_line_int_num = 0; // The number of hsyncs that generate hs interrupts - LCD_CAM.cam_ctrl1.cam_clk_inv = 0; - LCD_CAM.cam_ctrl1.cam_vsync_filter_en = 1; - LCD_CAM.cam_ctrl1.cam_2byte_en = 0; - LCD_CAM.cam_ctrl1.cam_de_inv = 0; - LCD_CAM.cam_ctrl1.cam_hsync_inv = 0; - LCD_CAM.cam_ctrl1.cam_vsync_inv = 0; - LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 0; - - LCD_CAM.cam_rgb_yuv.val = 0; - -#if CONFIG_CAMERA_CONVERTER_ENABLED - if (config->conv_mode) { - ret = ll_cam_converter_config(cam, config); - if(ret != ESP_OK) { - return ret; - } - } -#endif - - LCD_CAM.cam_ctrl.cam_update = 1; - LCD_CAM.cam_ctrl1.cam_start = 1; - - ret = ll_cam_dma_init(cam); - - return ret; -} - -void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en) -{ - LCD_CAM.lc_dma_int_clr.cam_vsync_int_clr = 1; - if (en) { - LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1; - } else { - LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 0; - } -} - -esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) -{ - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_pclk], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_pclk, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_pclk, GPIO_FLOATING); - gpio_matrix_in(config->pin_pclk, CAM_PCLK_IDX, false); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_vsync], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_vsync, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_vsync, GPIO_FLOATING); - gpio_matrix_in(config->pin_vsync, CAM_V_SYNC_IDX, cam->vsync_invert); - - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_href], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_href, GPIO_MODE_INPUT); - gpio_set_pull_mode(config->pin_href, GPIO_FLOATING); - gpio_matrix_in(config->pin_href, CAM_H_ENABLE_IDX, false); - - int data_pins[8] = { - config->pin_d0, config->pin_d1, config->pin_d2, config->pin_d3, config->pin_d4, config->pin_d5, config->pin_d6, config->pin_d7, - }; - for (int i = 0; i < 8; i++) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[data_pins[i]], PIN_FUNC_GPIO); - gpio_set_direction(data_pins[i], GPIO_MODE_INPUT); - gpio_set_pull_mode(data_pins[i], GPIO_FLOATING); - gpio_matrix_in(data_pins[i], CAM_DATA_IN0_IDX + i, false); - } - if (config->pin_xclk >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_xclk], PIN_FUNC_GPIO); - gpio_set_direction(config->pin_xclk, GPIO_MODE_OUTPUT); - gpio_set_pull_mode(config->pin_xclk, GPIO_FLOATING); - gpio_matrix_out(config->pin_xclk, CAM_CLK_IDX, false, false); - } - - return ESP_OK; -} - -esp_err_t ll_cam_init_isr(cam_obj_t *cam) -{ - esp_err_t ret = ESP_OK; - ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[0].pairs[cam->dma_num].rx_irq_id, - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, - (uint32_t)&GDMA.channel[cam->dma_num].in.int_st, GDMA_IN_SUC_EOF_CH0_INT_ST_M, - ll_cam_dma_isr, cam, &cam->dma_intr_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "DMA interrupt allocation of camera failed"); - return ret; - } - - ret = esp_intr_alloc_intrstatus(ETS_LCD_CAM_INTR_SOURCE, - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, - (uint32_t)&LCD_CAM.lc_dma_int_st.val, LCD_CAM_CAM_VSYNC_INT_ST_M, - ll_cam_vsync_isr, cam, &cam->cam_intr_handle); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "LCD_CAM interrupt allocation of camera failed"); - return ret; - } - return ESP_OK; -} - -void ll_cam_do_vsync(cam_obj_t *cam) -{ - gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, !cam->vsync_invert); - ets_delay_us(10); - gpio_matrix_in(cam->vsync_pin, CAM_V_SYNC_IDX, cam->vsync_invert); -} - -uint8_t ll_cam_get_dma_align(cam_obj_t *cam) -{ - return 16 << GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size; -} - -static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){ - size_t node_max = LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE / cam->dma_bytes_per_item; - size_t line_width = cam->width * cam->in_bytes_per_pixel; - size_t node_size = node_max; - size_t nodes_per_line = 1; - size_t lines_per_node = 1; - - // Calculate DMA Node Size so that it's divisable by or divisor of the line width - if(line_width >= node_max){ - // One or more nodes will be requied for one line - for(size_t i = node_max; i > 0; i=i-1){ - if ((line_width % i) == 0) { - node_size = i; - nodes_per_line = line_width / node_size; - break; - } - } - } else { - // One or more lines can fit into one node - for(size_t i = node_max; i > 0; i=i-1){ - if ((i % line_width) == 0) { - node_size = i; - lines_per_node = node_size / line_width; - while((cam->height % lines_per_node) != 0){ - lines_per_node = lines_per_node - 1; - node_size = lines_per_node * line_width; - } - break; - } - } - } - - ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u", - (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node); - - cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item; - - size_t dma_half_buffer_max = CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX / 2 / cam->dma_bytes_per_item; - if (line_width > dma_half_buffer_max) { - ESP_LOGE(TAG, "Resolution too high"); - return 0; - } - - // Calculate minimum EOF size = max(mode_size, line_size) - size_t dma_half_buffer_min = node_size * nodes_per_line; - - // Calculate max EOF size divisable by node size - size_t dma_half_buffer = (dma_half_buffer_max / dma_half_buffer_min) * dma_half_buffer_min; - - // Adjust EOF size so that height will be divisable by the number of lines in each EOF - size_t lines_per_half_buffer = dma_half_buffer / line_width; - while((cam->height % lines_per_half_buffer) != 0){ - dma_half_buffer = dma_half_buffer - dma_half_buffer_min; - lines_per_half_buffer = dma_half_buffer / line_width; - } - - // Calculate DMA size - size_t dma_buffer_max = 2 * dma_half_buffer_max; - if (cam->psram_mode) { - dma_buffer_max = cam->recv_size / cam->dma_bytes_per_item; - } - size_t dma_buffer_size = dma_buffer_max; - if (!cam->psram_mode) { - dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer; - } - - ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u", - (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item), - (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item)); - - cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item; - cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item; - cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; - return 1; -} - -bool ll_cam_dma_sizes(cam_obj_t *cam) -{ - cam->dma_bytes_per_item = 1; - if (cam->jpeg_mode) { - if (cam->psram_mode) { - cam->dma_buffer_size = cam->recv_size; - cam->dma_half_buffer_size = 1024; - cam->dma_half_buffer_cnt = cam->dma_buffer_size / cam->dma_half_buffer_size; - cam->dma_node_buffer_size = cam->dma_half_buffer_size; - } else { - cam->dma_half_buffer_cnt = 16; - cam->dma_buffer_size = cam->dma_half_buffer_cnt * 1024; - cam->dma_half_buffer_size = cam->dma_buffer_size / cam->dma_half_buffer_cnt; - cam->dma_node_buffer_size = cam->dma_half_buffer_size; - } - } else { - return ll_cam_calc_rgb_dma(cam); - } - return 1; -} - -size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len) -{ - // YUV to Grayscale - if (cam->in_bytes_per_pixel == 2 && cam->fb_bytes_per_pixel == 1) { - size_t end = len / 8; - for (size_t i = 0; i < end; ++i) { - out[0] = in[0]; - out[1] = in[2]; - out[2] = in[4]; - out[3] = in[6]; - out += 4; - in += 8; - } - return len / 2; - } - - // just memcpy - memcpy(out, in, len); - return len; -} - -esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid) -{ - if (pix_format == PIXFORMAT_GRAYSCALE) { - if (sensor_pid == OV3660_PID || sensor_pid == OV5640_PID || sensor_pid == NT99141_PID || sensor_pid == SC031GS_PID || sensor_pid == BF20A6_PID) { - cam->in_bytes_per_pixel = 1; // camera sends Y8 - } else { - cam->in_bytes_per_pixel = 2; // camera sends YU/YV - } - cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8 - } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) { -#if CONFIG_CAMERA_CONVERTER_ENABLED - switch (cam->conv_mode) { - case YUV422_TO_YUV420: - cam->in_bytes_per_pixel = 1.5; // for DMA receive - cam->fb_bytes_per_pixel = 1.5; // frame buffer stores YUV420 - break; - case YUV422_TO_RGB565: - default: - cam->in_bytes_per_pixel = 2; // for DMA receive - cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 - break; - } -#else - cam->in_bytes_per_pixel = 2; // for DMA receive - cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565 -#endif - } else if (pix_format == PIXFORMAT_JPEG) { - cam->in_bytes_per_pixel = 1; - cam->fb_bytes_per_pixel = 1; - } else { - ESP_LOGE(TAG, "Requested format is not supported"); - return ESP_ERR_NOT_SUPPORTED; - } - return ESP_OK; -} - -// implements function from xclk.c to allow dynamic XCLK change -esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) -{ - LCD_CAM.cam_ctrl.cam_clkm_div_b = 0; - LCD_CAM.cam_ctrl.cam_clkm_div_a = 0; - LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / xclk_freq_hz; - LCD_CAM.cam_ctrl.cam_clk_sel = 3;//Select Camera module source clock. 0: no clock. 1: APLL. 2: CLK160. 3: no clock. - LCD_CAM.cam_ctrl.cam_update = 1; - return ESP_OK; -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h deleted file mode 100644 index 31fbc97cce..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/jpeg_include/tjpgd.h +++ /dev/null @@ -1,99 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 -/----------------------------------------------------------------------------*/ -#ifndef _TJPGDEC -#define _TJPGDEC -/*---------------------------------------------------------------------------*/ -/* System Configurations */ - -#define JD_SZBUF 512 /* Size of stream input buffer */ -#define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ -#define JD_USE_SCALE 1 /* Use descaling feature for output */ -#define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ - -/*---------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; - -/* These types must be 8-bit integer */ -typedef char CHAR; -typedef unsigned char UCHAR; -typedef unsigned char BYTE; - -/* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - - -/* Error code */ -typedef enum { - JDR_OK = 0, /* 0: Succeeded */ - JDR_INTR, /* 1: Interrupted by output function */ - JDR_INP, /* 2: Device error or wrong termination of input stream */ - JDR_MEM1, /* 3: Insufficient memory pool for the image */ - JDR_MEM2, /* 4: Insufficient stream input buffer */ - JDR_PAR, /* 5: Parameter error */ - JDR_FMT1, /* 6: Data format error (may be damaged data) */ - JDR_FMT2, /* 7: Right format but not supported */ - JDR_FMT3 /* 8: Not supported JPEG standard */ -} JRESULT; - - - -/* Rectangular structure */ -typedef struct { - WORD left, right, top, bottom; -} JRECT; - - - -/* Decompressor object structure */ -typedef struct JDEC JDEC; -struct JDEC { - UINT dctr; /* Number of bytes available in the input buffer */ - BYTE* dptr; /* Current data read ptr */ - BYTE* inbuf; /* Bit stream input buffer */ - BYTE dmsk; /* Current bit in the current read byte */ - BYTE scale; /* Output scaling ratio */ - BYTE msx, msy; /* MCU size in unit of block (width, height) */ - BYTE qtid[3]; /* Quantization table ID of each component */ - SHORT dcv[3]; /* Previous DC element of each component */ - WORD nrst; /* Restart inverval */ - UINT width, height; /* Size of the input image (pixel) */ - BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ - WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ - BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ - LONG* qttbl[4]; /* Dequaitizer tables [id] */ - void* workbuf; /* Working buffer for IDCT and RGB output */ - BYTE* mcubuf; /* Working buffer for the MCU */ - void* pool; /* Pointer to available memory pool */ - UINT sz_pool; /* Size of momory pool (bytes available) */ - UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ - void* device; /* Pointer to I/O device identifiler for the session */ -}; - - - -/* TJpgDec API functions */ -JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); -JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); - - -#ifdef __cplusplus -} -#endif - -#endif /* _TJPGDEC */ diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h deleted file mode 100644 index 34c8da36dd..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/private_include/ll_cam.h +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#pragma once - -#include -#include "sdkconfig.h" -#include "esp_idf_version.h" -#if CONFIG_IDF_TARGET_ESP32 -#if ESP_IDF_VERSION_MAJOR >= 4 -#include "esp32/rom/lldesc.h" -#else -#include "rom/lldesc.h" -#endif -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/lldesc.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/lldesc.h" -#endif -#include "esp_log.h" -#include "esp_camera.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "freertos/semphr.h" - -#if __has_include("esp_private/periph_ctrl.h") -# include "esp_private/periph_ctrl.h" -#endif - -#define CAMERA_DBG_PIN_ENABLE 0 -#if CAMERA_DBG_PIN_ENABLE - #if CONFIG_IDF_TARGET_ESP32 - #define DBG_PIN_NUM 26 - #else - #define DBG_PIN_NUM 7 - #endif - #include "hal/gpio_ll.h" - #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) -#else - #define DBG_PIN_SET(v) -#endif - -#define CAM_CHECK(a, str, ret) if (!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - return (ret); \ - } - -#define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ - ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ - goto lab; \ - } - -#define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) - -typedef enum { - CAM_IN_SUC_EOF_EVENT = 0, - CAM_VSYNC_EVENT -} cam_event_t; - -typedef enum { - CAM_STATE_IDLE = 0, - CAM_STATE_READ_BUF = 1, -} cam_state_t; - -typedef struct { - camera_fb_t fb; - uint8_t en; - //for RGB/YUV modes - lldesc_t *dma; - size_t fb_offset; -} cam_frame_t; - -typedef struct { - uint32_t dma_bytes_per_item; - uint32_t dma_buffer_size; - uint32_t dma_half_buffer_size; - uint32_t dma_half_buffer_cnt; - uint32_t dma_node_buffer_size; - uint32_t dma_node_cnt; - uint32_t frame_copy_cnt; - - //for JPEG mode - lldesc_t *dma; - uint8_t *dma_buffer; - - cam_frame_t *frames; - - QueueHandle_t event_queue; - QueueHandle_t frame_buffer_queue; - TaskHandle_t task_handle; - intr_handle_t cam_intr_handle; - - uint8_t dma_num;//ESP32-S3 - intr_handle_t dma_intr_handle;//ESP32-S3 - - uint8_t jpeg_mode; - uint8_t vsync_pin; - uint8_t vsync_invert; - uint32_t frame_cnt; - uint32_t recv_size; - bool swap_data; - bool psram_mode; - - //for RGB/YUV modes - uint16_t width; - uint16_t height; -#if CONFIG_CAMERA_CONVERTER_ENABLED - float in_bytes_per_pixel; - float fb_bytes_per_pixel; - camera_conv_mode_t conv_mode; -#else - uint8_t in_bytes_per_pixel; - uint8_t fb_bytes_per_pixel; -#endif - uint32_t fb_size; - - cam_state_t state; -} cam_obj_t; - - -bool ll_cam_stop(cam_obj_t *cam); -bool ll_cam_start(cam_obj_t *cam, int frame_pos); -esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); -esp_err_t ll_cam_deinit(cam_obj_t *cam); -void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); -esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); -esp_err_t ll_cam_init_isr(cam_obj_t *cam); -void ll_cam_do_vsync(cam_obj_t *cam); -uint8_t ll_cam_get_dma_align(cam_obj_t *cam); -bool ll_cam_dma_sizes(cam_obj_t *cam); -size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); -esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid); - -// implemented in cam_hal -void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c deleted file mode 100644 index 5a983c4c7f..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/tjpgd.c +++ /dev/null @@ -1,970 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ TJpgDec - Tiny JPEG Decompressor R0.01b (C)ChaN, 2012 -/-----------------------------------------------------------------------------/ -/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. -/ This is a free software that opened for education, research and commercial -/ developments under license policy of following terms. -/ -/ Copyright (C) 2012, ChaN, all right reserved. -/ -/ * The TJpgDec module is a free software and there is NO WARRANTY. -/ * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. -/ * Redistributions of source code must retain the above copyright notice. -/ -/-----------------------------------------------------------------------------/ -/ Oct 04,'11 R0.01 First release. -/ Feb 19,'12 R0.01a Fixed decompression fails when scan starts with an escape seq. -/ Sep 03,'12 R0.01b Added JD_TBLCLIP option. -/----------------------------------------------------------------------------*/ - -#include "tjpgd.h" - -#define SUPPORT_JPEG 1 - -#ifdef SUPPORT_JPEG -/*-----------------------------------------------*/ -/* Zigzag-order to raster-order conversion table */ -/*-----------------------------------------------*/ - -#define ZIG(n) Zig[n] - -static -const BYTE Zig[64] = { /* Zigzag-order to raster-order conversion table */ - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 -}; - - - -/*-------------------------------------------------*/ -/* Input scale factor of Arai algorithm */ -/* (scaled up 16 bits for fixed point operations) */ -/*-------------------------------------------------*/ - -#define IPSF(n) Ipsf[n] - -static -const WORD Ipsf[64] = { /* See also aa_idct.png */ - (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), - (WORD)(1.38704*8192), (WORD)(1.92388*8192), (WORD)(1.81226*8192), (WORD)(1.63099*8192), (WORD)(1.38704*8192), (WORD)(1.08979*8192), (WORD)(0.75066*8192), (WORD)(0.38268*8192), - (WORD)(1.30656*8192), (WORD)(1.81226*8192), (WORD)(1.70711*8192), (WORD)(1.53636*8192), (WORD)(1.30656*8192), (WORD)(1.02656*8192), (WORD)(0.70711*8192), (WORD)(0.36048*8192), - (WORD)(1.17588*8192), (WORD)(1.63099*8192), (WORD)(1.53636*8192), (WORD)(1.38268*8192), (WORD)(1.17588*8192), (WORD)(0.92388*8192), (WORD)(0.63638*8192), (WORD)(0.32442*8192), - (WORD)(1.00000*8192), (WORD)(1.38704*8192), (WORD)(1.30656*8192), (WORD)(1.17588*8192), (WORD)(1.00000*8192), (WORD)(0.78570*8192), (WORD)(0.54120*8192), (WORD)(0.27590*8192), - (WORD)(0.78570*8192), (WORD)(1.08979*8192), (WORD)(1.02656*8192), (WORD)(0.92388*8192), (WORD)(0.78570*8192), (WORD)(0.61732*8192), (WORD)(0.42522*8192), (WORD)(0.21677*8192), - (WORD)(0.54120*8192), (WORD)(0.75066*8192), (WORD)(0.70711*8192), (WORD)(0.63638*8192), (WORD)(0.54120*8192), (WORD)(0.42522*8192), (WORD)(0.29290*8192), (WORD)(0.14932*8192), - (WORD)(0.27590*8192), (WORD)(0.38268*8192), (WORD)(0.36048*8192), (WORD)(0.32442*8192), (WORD)(0.27590*8192), (WORD)(0.21678*8192), (WORD)(0.14932*8192), (WORD)(0.07612*8192) -}; - - - -/*---------------------------------------------*/ -/* Conversion table for fast clipping process */ -/*---------------------------------------------*/ - -#if JD_TBLCLIP - -#define BYTECLIP(v) Clip8[(UINT)(v) & 0x3FF] - -static -const BYTE Clip8[1024] = { - /* 0..255 */ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - /* 256..511 */ - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - /* -512..-257 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* -256..-1 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#else /* JD_TBLCLIP */ - -inline -BYTE BYTECLIP ( - INT val -) -{ - if (val < 0) val = 0; - if (val > 255) val = 255; - - return (BYTE)val; -} - -#endif - - - -/*-----------------------------------------------------------------------*/ -/* Allocate a memory block from memory pool */ -/*-----------------------------------------------------------------------*/ - -static -void* alloc_pool ( /* Pointer to allocated memory block (NULL:no memory available) */ - JDEC* jd, /* Pointer to the decompressor object */ - UINT nd /* Number of bytes to allocate */ -) -{ - char *rp = 0; - - - nd = (nd + 3) & ~3; /* Align block size to the word boundary */ - - if (jd->sz_pool >= nd) { - jd->sz_pool -= nd; - rp = (char*)jd->pool; /* Get start of available memory pool */ - jd->pool = (void*)(rp + nd); /* Allocate requierd bytes */ - } - - return (void*)rp; /* Return allocated memory block (NULL:no memory to allocate) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create de-quantization and prescaling tables with a DQT segment */ -/*-----------------------------------------------------------------------*/ - -static -UINT create_qt_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const BYTE* data, /* Pointer to the quantizer tables */ - UINT ndata /* Size of input data */ -) -{ - UINT i; - BYTE d, z; - LONG *pb; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 65) return JDR_FMT1; /* Err: table size is unaligned */ - ndata -= 65; - d = *data++; /* Get table property */ - if (d & 0xF0) return JDR_FMT1; /* Err: not 8-bit resolution */ - i = d & 3; /* Get table ID */ - pb = alloc_pool(jd, 64 * sizeof (LONG));/* Allocate a memory block for the table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->qttbl[i] = pb; /* Register the table */ - for (i = 0; i < 64; i++) { /* Load the table */ - z = ZIG(i); /* Zigzag-order to raster-order conversion */ - pb[z] = (LONG)((DWORD)*data++ * IPSF(z)); /* Apply scale factor of Arai algorithm to the de-quantizers */ - } - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create huffman code tables with a DHT segment */ -/*-----------------------------------------------------------------------*/ - -static -UINT create_huffman_tbl ( /* 0:OK, !0:Failed */ - JDEC* jd, /* Pointer to the decompressor object */ - const BYTE* data, /* Pointer to the packed huffman tables */ - UINT ndata /* Size of input data */ -) -{ - UINT i, j, b, np, cls, num; - BYTE d, *pb, *pd; - WORD hc, *ph; - - - while (ndata) { /* Process all tables in the segment */ - if (ndata < 17) return JDR_FMT1; /* Err: wrong data size */ - ndata -= 17; - d = *data++; /* Get table number and class */ - cls = (d >> 4); num = d & 0x0F; /* class = dc(0)/ac(1), table number = 0/1 */ - if (d & 0xEE) return JDR_FMT1; /* Err: invalid class/number */ - pb = alloc_pool(jd, 16); /* Allocate a memory block for the bit distribution table */ - if (!pb) return JDR_MEM1; /* Err: not enough memory */ - jd->huffbits[num][cls] = pb; - for (np = i = 0; i < 16; i++) { /* Load number of patterns for 1 to 16-bit code */ - pb[i] = b = *data++; - np += b; /* Get sum of code words for each code */ - } - - ph = alloc_pool(jd, np * sizeof (WORD));/* Allocate a memory block for the code word table */ - if (!ph) return JDR_MEM1; /* Err: not enough memory */ - jd->huffcode[num][cls] = ph; - hc = 0; - for (j = i = 0; i < 16; i++) { /* Re-build huffman code word table */ - b = pb[i]; - while (b--) ph[j++] = hc++; - hc <<= 1; - } - - if (ndata < np) return JDR_FMT1; /* Err: wrong data size */ - ndata -= np; - pd = alloc_pool(jd, np); /* Allocate a memory block for the decoded data */ - if (!pd) return JDR_MEM1; /* Err: not enough memory */ - jd->huffdata[num][cls] = pd; - for (i = 0; i < np; i++) { /* Load decoded data corresponds to each code ward */ - d = *data++; - if (!cls && d > 11) return JDR_FMT1; - *pd++ = d; - } - } - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract N bits from input stream */ -/*-----------------------------------------------------------------------*/ - -static -INT bitext ( /* >=0: extracted data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - UINT nbit /* Number of bits to extract (1 to 11) */ -) -{ - BYTE msk, s, *dp; - UINT dc, v, f; - - - msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ - s = *dp; v = f = 0; - do { - if (!msk) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (INT)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (f) { /* In flag sequence? */ - f = 0; /* Exit flag sequence */ - if (*dp != 0) return 0 - (INT)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = s = 0xFF; /* The flag is a data 0xFF */ - } else { - s = *dp; /* Get next data byte */ - if (s == 0xFF) { /* Is start of flag sequence? */ - f = 1; continue; /* Enter flag sequence */ - } - } - msk = 0x80; /* Read from MSB */ - } - v <<= 1; /* Get a bit */ - if (s & msk) v++; - msk >>= 1; - nbit--; - } while (nbit); - jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; - - return (INT)v; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Extract a huffman decoded data from input stream */ -/*-----------------------------------------------------------------------*/ - -static -INT huffext ( /* >=0: decoded data, <0: error code */ - JDEC* jd, /* Pointer to the decompressor object */ - const BYTE* hbits, /* Pointer to the bit distribution table */ - const WORD* hcode, /* Pointer to the code word table */ - const BYTE* hdata /* Pointer to the data table */ -) -{ - BYTE msk, s, *dp; - UINT dc, v, f, bl, nd; - - - msk = jd->dmsk; dc = jd->dctr; dp = jd->dptr; /* Bit mask, number of data available, read ptr */ - s = *dp; v = f = 0; - bl = 16; /* Max code length */ - do { - if (!msk) { /* Next byte? */ - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; /* Top of input buffer */ - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return 0 - (INT)JDR_INP; /* Err: read error or wrong stream termination */ - } else { - dp++; /* Next data ptr */ - } - dc--; /* Decrement number of available bytes */ - if (f) { /* In flag sequence? */ - f = 0; /* Exit flag sequence */ - if (*dp != 0) - return 0 - (INT)JDR_FMT1; /* Err: unexpected flag is detected (may be collapted data) */ - *dp = s = 0xFF; /* The flag is a data 0xFF */ - } else { - s = *dp; /* Get next data byte */ - if (s == 0xFF) { /* Is start of flag sequence? */ - f = 1; continue; /* Enter flag sequence, get trailing byte */ - } - } - msk = 0x80; /* Read from MSB */ - } - v <<= 1; /* Get a bit */ - if (s & msk) v++; - msk >>= 1; - - for (nd = *hbits++; nd; nd--) { /* Search the code word in this bit length */ - if (v == *hcode++) { /* Matched? */ - jd->dmsk = msk; jd->dctr = dc; jd->dptr = dp; - return *hdata; /* Return the decoded data */ - } - hdata++; - } - bl--; - } while (bl); - - return 0 - (INT)JDR_FMT1; /* Err: code not found (may be collapted data) */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Apply Inverse-DCT in Arai Algorithm (see also aa_idct.png) */ -/*-----------------------------------------------------------------------*/ - -static -void block_idct ( - LONG* src, /* Input block data (de-quantized and pre-scaled for Arai Algorithm) */ - BYTE* dst /* Pointer to the destination to store the block as byte array */ -) -{ - const LONG M13 = (LONG)(1.41421*4096), M2 = (LONG)(1.08239*4096), M4 = (LONG)(2.61313*4096), M5 = (LONG)(1.84776*4096); - LONG v0, v1, v2, v3, v4, v5, v6, v7; - LONG t10, t11, t12, t13; - UINT i; - - /* Process columns */ - for (i = 0; i < 8; i++) { - v0 = src[8 * 0]; /* Get even elements */ - v1 = src[8 * 2]; - v2 = src[8 * 4]; - v3 = src[8 * 6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[8 * 7]; /* Get odd elements */ - v5 = src[8 * 1]; - v6 = src[8 * 5]; - v7 = src[8 * 3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - src[8 * 0] = v0 + v7; /* Write-back transformed values */ - src[8 * 7] = v0 - v7; - src[8 * 1] = v1 + v6; - src[8 * 6] = v1 - v6; - src[8 * 2] = v2 + v5; - src[8 * 5] = v2 - v5; - src[8 * 3] = v3 + v4; - src[8 * 4] = v3 - v4; - - src++; /* Next column */ - } - - /* Process rows */ - src -= 8; - for (i = 0; i < 8; i++) { - v0 = src[0] + (128L << 8); /* Get even elements (remove DC offset (-128) here) */ - v1 = src[2]; - v2 = src[4]; - v3 = src[6]; - - t10 = v0 + v2; /* Process the even elements */ - t12 = v0 - v2; - t11 = (v1 - v3) * M13 >> 12; - v3 += v1; - t11 -= v3; - v0 = t10 + v3; - v3 = t10 - v3; - v1 = t11 + t12; - v2 = t12 - t11; - - v4 = src[7]; /* Get odd elements */ - v5 = src[1]; - v6 = src[5]; - v7 = src[3]; - - t10 = v5 - v4; /* Process the odd elements */ - t11 = v5 + v4; - t12 = v6 - v7; - v7 += v6; - v5 = (t11 - v7) * M13 >> 12; - v7 += t11; - t13 = (t10 + t12) * M5 >> 12; - v4 = t13 - (t10 * M2 >> 12); - v6 = t13 - (t12 * M4 >> 12) - v7; - v5 -= v6; - v4 -= v5; - - dst[0] = BYTECLIP((v0 + v7) >> 8); /* Descale the transformed values 8 bits and output */ - dst[7] = BYTECLIP((v0 - v7) >> 8); - dst[1] = BYTECLIP((v1 + v6) >> 8); - dst[6] = BYTECLIP((v1 - v6) >> 8); - dst[2] = BYTECLIP((v2 + v5) >> 8); - dst[5] = BYTECLIP((v2 - v5) >> 8); - dst[3] = BYTECLIP((v3 + v4) >> 8); - dst[4] = BYTECLIP((v3 - v4) >> 8); - dst += 8; - - src += 8; /* Next row */ - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load all blocks in the MCU into working buffer */ -/*-----------------------------------------------------------------------*/ - -static -JRESULT mcu_load ( - JDEC* jd /* Pointer to the decompressor object */ -) -{ - LONG *tmp = (LONG*)jd->workbuf; /* Block working buffer for de-quantize and IDCT */ - UINT blk, nby, nbc, i, z, id, cmp; - INT b, d, e; - BYTE *bp; - const BYTE *hb, *hd; - const WORD *hc; - const LONG *dqf; - - - nby = jd->msx * jd->msy; /* Number of Y blocks (1, 2 or 4) */ - nbc = 2; /* Number of C blocks (2) */ - bp = jd->mcubuf; /* Pointer to the first block */ - - for (blk = 0; blk < nby + nbc; blk++) { - cmp = (blk < nby) ? 0 : blk - nby + 1; /* Component number 0:Y, 1:Cb, 2:Cr */ - id = cmp ? 1 : 0; /* Huffman table ID of the component */ - - /* Extract a DC element from input stream */ - hb = jd->huffbits[id][0]; /* Huffman table for the DC element */ - hc = jd->huffcode[id][0]; - hd = jd->huffdata[id][0]; - b = huffext(jd, hb, hc, hd); /* Extract a huffman coded data (bit length) */ - if (b < 0) return 0 - b; /* Err: invalid code or input */ - d = jd->dcv[cmp]; /* DC value of previous block */ - if (b) { /* If there is any difference from previous block */ - e = bitext(jd, b); /* Extract data bits */ - if (e < 0) return 0 - e; /* Err: input */ - b = 1 << (b - 1); /* MSB position */ - if (!(e & b)) e -= (b << 1) - 1; /* Restore sign if needed */ - d += e; /* Get current value */ - jd->dcv[cmp] = (SHORT)d; /* Save current DC value for next block */ - } - dqf = jd->qttbl[jd->qtid[cmp]]; /* De-quantizer table ID for this component */ - tmp[0] = d * dqf[0] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - - /* Extract following 63 AC elements from input stream */ - for (i = 1; i < 64; i++) tmp[i] = 0; /* Clear rest of elements */ - hb = jd->huffbits[id][1]; /* Huffman table for the AC elements */ - hc = jd->huffcode[id][1]; - hd = jd->huffdata[id][1]; - i = 1; /* Top of the AC elements */ - do { - b = huffext(jd, hb, hc, hd); /* Extract a huffman coded value (zero runs and bit length) */ - if (b == 0) break; /* EOB? */ - if (b < 0) return 0 - b; /* Err: invalid code or input error */ - z = (UINT)b >> 4; /* Number of leading zero elements */ - if (z) { - i += z; /* Skip zero elements */ - if (i >= 64) return JDR_FMT1; /* Too long zero run */ - } - if (b &= 0x0F) { /* Bit length */ - d = bitext(jd, b); /* Extract data bits */ - if (d < 0) return 0 - d; /* Err: input device */ - b = 1 << (b - 1); /* MSB position */ - if (!(d & b)) d -= (b << 1) - 1;/* Restore negative value if needed */ - z = ZIG(i); /* Zigzag-order to raster-order converted index */ - tmp[z] = d * dqf[z] >> 8; /* De-quantize, apply scale factor of Arai algorithm and descale 8 bits */ - } - } while (++i < 64); /* Next AC element */ - - if (JD_USE_SCALE && jd->scale == 3) - *bp = (*tmp / 256) + 128; /* If scale ratio is 1/8, IDCT can be ommited and only DC element is used */ - else - block_idct(tmp, bp); /* Apply IDCT and store the block to the MCU buffer */ - - bp += 64; /* Next block */ - } - - return JDR_OK; /* All blocks have been loaded successfully */ -} - - - - -/*-----------------------------------------------------------------------*/ -/* Output an MCU: Convert YCrCb to RGB and output it in RGB form */ -/*-----------------------------------------------------------------------*/ - -static -JRESULT mcu_output ( - JDEC* jd, /* Pointer to the decompressor object */ - UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - UINT x, /* MCU position in the image (left of the MCU) */ - UINT y /* MCU position in the image (top of the MCU) */ -) -{ - const INT CVACC = (sizeof (INT) > 2) ? 1024 : 128; - UINT ix, iy, mx, my, rx, ry; - INT yy, cb, cr; - BYTE *py, *pc, *rgb24; - JRECT rect; - - - mx = jd->msx * 8; my = jd->msy * 8; /* MCU size (pixel) */ - rx = (x + mx <= jd->width) ? mx : jd->width - x; /* Output rectangular size (it may be clipped at right/bottom end) */ - ry = (y + my <= jd->height) ? my : jd->height - y; - if (JD_USE_SCALE) { - rx >>= jd->scale; ry >>= jd->scale; - if (!rx || !ry) return JDR_OK; /* Skip this MCU if all pixel is to be rounded off */ - x >>= jd->scale; y >>= jd->scale; - } - rect.left = x; rect.right = x + rx - 1; /* Rectangular area in the frame buffer */ - rect.top = y; rect.bottom = y + ry - 1; - - - if (!JD_USE_SCALE || jd->scale != 3) { /* Not for 1/8 scaling */ - - /* Build an RGB MCU from discrete comopnents */ - rgb24 = (BYTE*)jd->workbuf; - for (iy = 0; iy < my; iy++) { - pc = jd->mcubuf; - py = pc + iy * 8; - if (my == 16) { /* Double block height? */ - pc += 64 * 4 + (iy >> 1) * 8; - if (iy >= 8) py += 64; - } else { /* Single block height */ - pc += mx * 8 + iy * 8; - } - for (ix = 0; ix < mx; ix++) { - cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ - cr = pc[64] - 128; - if (mx == 16) { /* Double block width? */ - if (ix == 8) py += 64 - 8; /* Jump to next block if double block heigt */ - pc += ix & 1; /* Increase chroma pointer every two pixels */ - } else { /* Single block width */ - pc++; /* Increase chroma pointer every pixel */ - } - yy = *py++; /* Get Y component */ - - /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr) / CVACC); - *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((INT)(1.772 * CVACC) * cb) / CVACC); - } - } - - /* Descale the MCU rectangular if needed */ - if (JD_USE_SCALE && jd->scale) { - UINT x, y, r, g, b, s, w, a; - BYTE *op; - - /* Get averaged RGB value of each square correcponds to a pixel */ - s = jd->scale * 2; /* Bumber of shifts for averaging */ - w = 1 << jd->scale; /* Width of square */ - a = (mx - w) * 3; /* Bytes to skip for next line in the square */ - op = (BYTE*)jd->workbuf; - for (iy = 0; iy < my; iy += w) { - for (ix = 0; ix < mx; ix += w) { - rgb24 = (BYTE*)jd->workbuf + (iy * mx + ix) * 3; - r = g = b = 0; - for (y = 0; y < w; y++) { /* Accumulate RGB value in the square */ - for (x = 0; x < w; x++) { - r += *rgb24++; - g += *rgb24++; - b += *rgb24++; - } - rgb24 += a; - } /* Put the averaged RGB value as a pixel */ - *op++ = (BYTE)(r >> s); - *op++ = (BYTE)(g >> s); - *op++ = (BYTE)(b >> s); - } - } - } - - } else { /* For only 1/8 scaling (left-top pixel in each block are the DC value of the block) */ - - /* Build a 1/8 descaled RGB MCU from discrete comopnents */ - rgb24 = (BYTE*)jd->workbuf; - pc = jd->mcubuf + mx * my; - cb = pc[0] - 128; /* Get Cb/Cr component and restore right level */ - cr = pc[64] - 128; - for (iy = 0; iy < my; iy += 8) { - py = jd->mcubuf; - if (iy == 8) py += 64 * 2; - for (ix = 0; ix < mx; ix += 8) { - yy = *py; /* Get Y component */ - py += 64; - - /* Convert YCbCr to RGB */ - *rgb24++ = /* R */ BYTECLIP(yy + ((INT)(1.402 * CVACC) * cr / CVACC)); - *rgb24++ = /* G */ BYTECLIP(yy - ((INT)(0.344 * CVACC) * cb + (INT)(0.714 * CVACC) * cr) / CVACC); - *rgb24++ = /* B */ BYTECLIP(yy + ((INT)(1.772 * CVACC) * cb / CVACC)); - } - } - } - - /* Squeeze up pixel table if a part of MCU is to be truncated */ - mx >>= jd->scale; - if (rx < mx) { - BYTE *s, *d; - UINT x, y; - - s = d = (BYTE*)jd->workbuf; - for (y = 0; y < ry; y++) { - for (x = 0; x < rx; x++) { /* Copy effective pixels */ - *d++ = *s++; - *d++ = *s++; - *d++ = *s++; - } - s += (mx - rx) * 3; /* Skip truncated pixels */ - } - } - - /* Convert RGB888 to RGB565 if needed */ - if (JD_FORMAT == 1) { - BYTE *s = (BYTE*)jd->workbuf; - WORD w, *d = (WORD*)s; - UINT n = rx * ry; - - do { - w = (*s++ & 0xF8) << 8; /* RRRRR----------- */ - w |= (*s++ & 0xFC) << 3; /* -----GGGGGG----- */ - w |= *s++ >> 3; /* -----------BBBBB */ - *d++ = w; - } while (--n); - } - - /* Output the RGB rectangular */ - return outfunc(jd, jd->workbuf, &rect) ? JDR_OK : JDR_INTR; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Process restart interval */ -/*-----------------------------------------------------------------------*/ - -static -JRESULT restart ( - JDEC* jd, /* Pointer to the decompressor object */ - WORD rstn /* Expected restert sequense number */ -) -{ - UINT i, dc; - WORD d; - BYTE *dp; - - - /* Discard padding bits and get two bytes from the input stream */ - dp = jd->dptr; dc = jd->dctr; - d = 0; - for (i = 0; i < 2; i++) { - if (!dc) { /* No input data is available, re-fill input buffer */ - dp = jd->inbuf; - dc = jd->infunc(jd, dp, JD_SZBUF); - if (!dc) return JDR_INP; - } else { - dp++; - } - dc--; - d = (d << 8) | *dp; /* Get a byte */ - } - jd->dptr = dp; jd->dctr = dc; jd->dmsk = 0; - - /* Check the marker */ - if ((d & 0xFFD8) != 0xFFD0 || (d & 7) != (rstn & 7)) - return JDR_FMT1; /* Err: expected RSTn marker is not detected (may be collapted data) */ - - /* Reset DC offset */ - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; - - return JDR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Analyze the JPEG image and Initialize decompressor object */ -/*-----------------------------------------------------------------------*/ - -#define LDB_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr))<<8)|(WORD)*(BYTE*)((ptr)+1)) - - -JRESULT jd_prepare ( - JDEC* jd, /* Blank decompressor object */ - UINT (*infunc)(JDEC*, BYTE*, UINT), /* JPEG strem input function */ - void* pool, /* Working buffer for the decompression session */ - UINT sz_pool, /* Size of working buffer */ - void* dev /* I/O device identifier for the session */ -) -{ - BYTE *seg, b; - WORD marker; - DWORD ofs; - UINT n, i, j, len; - JRESULT rc; - - - if (!pool) return JDR_PAR; - - jd->pool = pool; /* Work memroy */ - jd->sz_pool = sz_pool; /* Size of given work memory */ - jd->infunc = infunc; /* Stream input function */ - jd->device = dev; /* I/O device identifier */ - jd->nrst = 0; /* No restart interval (default) */ - - for (i = 0; i < 2; i++) { /* Nulls pointers */ - for (j = 0; j < 2; j++) { - jd->huffbits[i][j] = 0; - jd->huffcode[i][j] = 0; - jd->huffdata[i][j] = 0; - } - } - for (i = 0; i < 4; i++) jd->qttbl[i] = 0; - - jd->inbuf = seg = alloc_pool(jd, JD_SZBUF); /* Allocate stream input buffer */ - if (!seg) return JDR_MEM1; - - if (jd->infunc(jd, seg, 2) != 2) return JDR_INP;/* Check SOI marker */ - if (LDB_WORD(seg) != 0xFFD8) return JDR_FMT1; /* Err: SOI is not detected */ - ofs = 2; - - for (;;) { - /* Get a JPEG marker */ - if (jd->infunc(jd, seg, 4) != 4) return JDR_INP; - marker = LDB_WORD(seg); /* Marker */ - len = LDB_WORD(seg + 2); /* Length field */ - if (len <= 2 || (marker >> 8) != 0xFF) return JDR_FMT1; - len -= 2; /* Content size excluding length field */ - ofs += 4 + len; /* Number of bytes loaded */ - - switch (marker & 0xFF) { - case 0xC0: /* SOF0 (baseline JPEG) */ - /* Load segment data */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; - - jd->width = LDB_WORD(seg+3); /* Image width in unit of pixel */ - jd->height = LDB_WORD(seg+1); /* Image height in unit of pixel */ - if (seg[5] != 3) return JDR_FMT3; /* Err: Supports only Y/Cb/Cr format */ - - /* Check three image components */ - for (i = 0; i < 3; i++) { - b = seg[7 + 3 * i]; /* Get sampling factor */ - if (!i) { /* Y component */ - if (b != 0x11 && b != 0x22 && b != 0x21)/* Check sampling factor */ - return JDR_FMT3; /* Err: Supports only 4:4:4, 4:2:0 or 4:2:2 */ - jd->msx = b >> 4; jd->msy = b & 15; /* Size of MCU [blocks] */ - } else { /* Cb/Cr component */ - if (b != 0x11) return JDR_FMT3; /* Err: Sampling factor of Cr/Cb must be 1 */ - } - b = seg[8 + 3 * i]; /* Get dequantizer table ID for this component */ - if (b > 3) return JDR_FMT3; /* Err: Invalid ID */ - jd->qtid[i] = b; - } - break; - - case 0xDD: /* DRI */ - /* Load segment data */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; - - /* Get restart interval (MCUs) */ - jd->nrst = LDB_WORD(seg); - break; - - case 0xC4: /* DHT */ - /* Load segment data */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; - - /* Create huffman tables */ - rc = create_huffman_tbl(jd, seg, len); - if (rc) return rc; - break; - - case 0xDB: /* DQT */ - /* Load segment data */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; - - /* Create de-quantizer tables */ - rc = create_qt_tbl(jd, seg, len); - if (rc) return rc; - break; - - case 0xDA: /* SOS */ - /* Load segment data */ - if (len > JD_SZBUF) return JDR_MEM2; - if (jd->infunc(jd, seg, len) != len) return JDR_INP; - - if (!jd->width || !jd->height) return JDR_FMT1; /* Err: Invalid image size */ - - if (seg[0] != 3) return JDR_FMT3; /* Err: Supports only three color components format */ - - /* Check if all tables corresponding to each components have been loaded */ - for (i = 0; i < 3; i++) { - b = seg[2 + 2 * i]; /* Get huffman table ID */ - if (b != 0x00 && b != 0x11) return JDR_FMT3; /* Err: Different table number for DC/AC element */ - b = i ? 1 : 0; - if (!jd->huffbits[b][0] || !jd->huffbits[b][1]) /* Check huffman table for this component */ - return JDR_FMT1; /* Err: Huffman table not loaded */ - if (!jd->qttbl[jd->qtid[i]]) return JDR_FMT1; /* Err: Dequantizer table not loaded */ - } - - /* Allocate working buffer for MCU and RGB */ - n = jd->msy * jd->msx; /* Number of Y blocks in the MCU */ - if (!n) return JDR_FMT1; /* Err: SOF0 has not been loaded */ - len = n * 64 * 2 + 64; /* Allocate buffer for IDCT and RGB output */ - if (len < 256) len = 256; /* but at least 256 byte is required for IDCT */ - jd->workbuf = alloc_pool(jd, len); /* and it may occupy a part of following MCU working buffer for RGB output */ - if (!jd->workbuf) return JDR_MEM1; /* Err: not enough memory */ - jd->mcubuf = alloc_pool(jd, (n + 2) * 64); /* Allocate MCU working buffer */ - if (!jd->mcubuf) return JDR_MEM1; /* Err: not enough memory */ - - /* Pre-load the JPEG data to extract it from the bit stream */ - jd->dptr = seg; jd->dctr = 0; jd->dmsk = 0; /* Prepare to read bit stream */ - if (ofs %= JD_SZBUF) { /* Align read offset to JD_SZBUF */ - jd->dctr = jd->infunc(jd, seg + ofs, JD_SZBUF - (UINT)ofs); - jd->dptr = seg + ofs - 1; - } - - return JDR_OK; /* Initialization succeeded. Ready to decompress the JPEG image. */ - - case 0xC1: /* SOF1 */ - case 0xC2: /* SOF2 */ - case 0xC3: /* SOF3 */ - case 0xC5: /* SOF5 */ - case 0xC6: /* SOF6 */ - case 0xC7: /* SOF7 */ - case 0xC9: /* SOF9 */ - case 0xCA: /* SOF10 */ - case 0xCB: /* SOF11 */ - case 0xCD: /* SOF13 */ - case 0xCE: /* SOF14 */ - case 0xCF: /* SOF15 */ - case 0xD9: /* EOI */ - return JDR_FMT3; /* Unsuppoted JPEG standard (may be progressive JPEG) */ - - default: /* Unknown segment (comment, exif or etc..) */ - /* Skip segment data */ - if (jd->infunc(jd, 0, len) != len) /* Null pointer specifies to skip bytes of stream */ - return JDR_INP; - } - } -} - - - - -/*-----------------------------------------------------------------------*/ -/* Start to decompress the JPEG picture */ -/*-----------------------------------------------------------------------*/ - -JRESULT jd_decomp ( - JDEC* jd, /* Initialized decompression object */ - UINT (*outfunc)(JDEC*, void*, JRECT*), /* RGB output function */ - BYTE scale /* Output de-scaling factor (0 to 3) */ -) -{ - UINT x, y, mx, my; - WORD rst, rsc; - JRESULT rc; - - - if (scale > (JD_USE_SCALE ? 3 : 0)) return JDR_PAR; - jd->scale = scale; - - mx = jd->msx * 8; my = jd->msy * 8; /* Size of the MCU (pixel) */ - - jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */ - rst = rsc = 0; - - rc = JDR_OK; - for (y = 0; y < jd->height; y += my) { /* Vertical loop of MCUs */ - for (x = 0; x < jd->width; x += mx) { /* Horizontal loop of MCUs */ - if (jd->nrst && rst++ == jd->nrst) { /* Process restart interval if enabled */ - rc = restart(jd, rsc++); - if (rc != JDR_OK) return rc; - rst = 1; - } - rc = mcu_load(jd); /* Load an MCU (decompress huffman coded stream and apply IDCT) */ - if (rc != JDR_OK) return rc; - rc = mcu_output(jd, outfunc, x, y); /* Output the MCU (color space conversion, scaling and output) */ - if (rc != JDR_OK) return rc; - } - } - - return rc; -} -#endif//SUPPORT_JPEG - - diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c b/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c deleted file mode 100644 index cb67b677a5..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/target/xclk.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "driver/gpio.h" -#include "driver/ledc.h" -#include "esp_err.h" -#include "esp_log.h" -#include "esp_system.h" -#include "xclk.h" -#include "esp_camera.h" - -#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) -#include "esp32-hal-log.h" -#else -#include "esp_log.h" -static const char* TAG = "camera_xclk"; -#endif - -#define NO_CAMERA_LEDC_CHANNEL 0xFF -static ledc_channel_t g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; - -esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) -{ - ledc_timer_config_t timer_conf; - timer_conf.duty_resolution = LEDC_TIMER_1_BIT; - timer_conf.freq_hz = xclk_freq_hz; - timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; - -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) - timer_conf.deconfigure = false; -#endif - -#if ESP_IDF_VERSION_MAJOR >= 4 - timer_conf.clk_cfg = LEDC_AUTO_CLK; -#endif - timer_conf.timer_num = (ledc_timer_t)ledc_timer; - esp_err_t err = ledc_timer_config(&timer_conf); - if (err != ESP_OK) { - ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); - } - return err; -} - -esp_err_t camera_enable_out_clock(const camera_config_t* config) -{ - esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); - if (err != ESP_OK) { - ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); - return err; - } - - g_ledc_channel = config->ledc_channel; - ledc_channel_config_t ch_conf; - ch_conf.gpio_num = config->pin_xclk; - ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; - ch_conf.channel = config->ledc_channel; - ch_conf.intr_type = LEDC_INTR_DISABLE; - ch_conf.timer_sel = config->ledc_timer; - ch_conf.duty = 1; - ch_conf.hpoint = 0; - err = ledc_channel_config(&ch_conf); - if (err != ESP_OK) { - ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); - return err; - } - return ESP_OK; -} - -void camera_disable_out_clock() -{ - if (g_ledc_channel != NO_CAMERA_LEDC_CHANNEL) { - ledc_stop(LEDC_LOW_SPEED_MODE, g_ledc_channel, 0); - g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; - } -} diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt deleted file mode 100644 index a8c3d16b75..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register(SRC_DIRS . - PRIV_INCLUDE_DIRS . - PRIV_REQUIRES test_utils esp32-camera nvs_flash - EMBED_TXTFILES pictures/testimg.jpeg pictures/test_outside.jpeg pictures/test_inside.jpeg) diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk deleted file mode 100644 index 5fb883650e..0000000000 --- a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -#Component Makefile -# - -COMPONENT_SRCDIRS += ./ -COMPONENT_PRIV_INCLUDEDIRS += ./ - -COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_inside.jpeg deleted file mode 100644 index 92e7bc3694e8568be514673432c3601a8c1c4126..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18832 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 F|Jg`@ubTh> diff --git a/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg b/quirc/examples/esp-eye-qrcode/components/esp32-camera/test/pictures/test_outside.jpeg deleted file mode 100644 index dcb4bf1b3c82c9aa3858223414be90a54a1ff4c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 81744 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 -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "unity.h" -#include -#include "esp_log.h" -#include "driver/i2c.h" - -#include "esp_camera.h" - -#ifdef CONFIG_IDF_TARGET_ESP32 -#define BOARD_WROVER_KIT 1 -#elif defined CONFIG_IDF_TARGET_ESP32S2 -#define BOARD_CAMERA_MODEL_ESP32S2 1 -#elif defined CONFIG_IDF_TARGET_ESP32S3 -#define BOARD_CAMERA_MODEL_ESP32_S3_EYE 1 -#endif - -// WROVER-KIT PIN Map -#if BOARD_WROVER_KIT - -#define PWDN_GPIO_NUM -1 //power down is not used -#define RESET_GPIO_NUM -1 //software reset will be performed -#define XCLK_GPIO_NUM 21 -#define SIOD_GPIO_NUM 26 -#define SIOC_GPIO_NUM 27 - -#define Y9_GPIO_NUM 35 -#define Y8_GPIO_NUM 34 -#define Y7_GPIO_NUM 39 -#define Y6_GPIO_NUM 36 -#define Y5_GPIO_NUM 19 -#define Y4_GPIO_NUM 18 -#define Y3_GPIO_NUM 5 -#define Y2_GPIO_NUM 4 -#define VSYNC_GPIO_NUM 25 -#define HREF_GPIO_NUM 23 -#define PCLK_GPIO_NUM 22 - -// ESP32Cam (AiThinker) PIN Map -#elif BOARD_ESP32CAM_AITHINKER - -#define PWDN_GPIO_NUM 32 -#define RESET_GPIO_NUM -1 //software reset will be performed -#define XCLK_GPIO_NUM 0 -#define SIOD_GPIO_NUM 26 -#define SIOC_GPIO_NUM 27 - -#define Y9_GPIO_NUM 35 -#define Y8_GPIO_NUM 34 -#define Y7_GPIO_NUM 39 -#define Y6_GPIO_NUM 36 -#define Y5_GPIO_NUM 21 -#define Y4_GPIO_NUM 19 -#define Y3_GPIO_NUM 18 -#define Y2_GPIO_NUM 5 -#define VSYNC_GPIO_NUM 25 -#define HREF_GPIO_NUM 23 -#define PCLK_GPIO_NUM 22 - -#elif BOARD_CAMERA_MODEL_ESP32S2 - -#define PWDN_GPIO_NUM -1 -#define RESET_GPIO_NUM -1 - -#define VSYNC_GPIO_NUM 21 -#define HREF_GPIO_NUM 38 -#define PCLK_GPIO_NUM 11 -#define XCLK_GPIO_NUM 40 - -#define SIOD_GPIO_NUM 17 -#define SIOC_GPIO_NUM 18 - -#define Y9_GPIO_NUM 39 -#define Y8_GPIO_NUM 41 -#define Y7_GPIO_NUM 42 -#define Y6_GPIO_NUM 12 -#define Y5_GPIO_NUM 3 -#define Y4_GPIO_NUM 14 -#define Y3_GPIO_NUM 37 -#define Y2_GPIO_NUM 13 - -#elif BOARD_CAMERA_MODEL_ESP32_S3_EYE - -#define PWDN_GPIO_NUM 43 -#define RESET_GPIO_NUM 44 - -#define VSYNC_GPIO_NUM 6 -#define HREF_GPIO_NUM 7 -#define PCLK_GPIO_NUM 13 -#define XCLK_GPIO_NUM 15 - -#define SIOD_GPIO_NUM 4 -#define SIOC_GPIO_NUM 5 - -#define Y9_GPIO_NUM 16 -#define Y8_GPIO_NUM 17 -#define Y7_GPIO_NUM 18 -#define Y6_GPIO_NUM 12 -#define Y5_GPIO_NUM 11 -#define Y4_GPIO_NUM 10 -#define Y3_GPIO_NUM 9 -#define Y2_GPIO_NUM 8 - -#endif - -#define I2C_MASTER_SCL_IO 4 /*!< GPIO number used for I2C master clock */ -#define I2C_MASTER_SDA_IO 5 /*!< GPIO number used for I2C master data */ -#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ -#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ - -static const char *TAG = "test camera"; - -typedef void (*decode_func_t)(uint8_t *jpegbuffer, uint32_t size, uint8_t *outbuffer); - -static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count, int sccb_sda_gpio_num, int sccb_port) -{ - framesize_t size_bak = frame_size; - if (PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > frame_size) { - frame_size = FRAMESIZE_HD; - } - camera_config_t camera_config = { - .pin_pwdn = PWDN_GPIO_NUM, - .pin_reset = RESET_GPIO_NUM, - .pin_xclk = XCLK_GPIO_NUM, - .pin_sccb_sda = sccb_sda_gpio_num, // If pin_sccb_sda is -1, sccb will use the already initialized i2c port specified by `sccb_i2c_port`. - .pin_sccb_scl = SIOC_GPIO_NUM, - .sccb_i2c_port = sccb_port, - - .pin_d7 = Y9_GPIO_NUM, - .pin_d6 = Y8_GPIO_NUM, - .pin_d5 = Y7_GPIO_NUM, - .pin_d4 = Y6_GPIO_NUM, - .pin_d3 = Y5_GPIO_NUM, - .pin_d2 = Y4_GPIO_NUM, - .pin_d1 = Y3_GPIO_NUM, - .pin_d0 = Y2_GPIO_NUM, - .pin_vsync = VSYNC_GPIO_NUM, - .pin_href = HREF_GPIO_NUM, - .pin_pclk = PCLK_GPIO_NUM, - - //EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode - .xclk_freq_hz = xclk_freq_hz, - .ledc_timer = LEDC_TIMER_0, - .ledc_channel = LEDC_CHANNEL_0, - - .pixel_format = pixel_format, //YUV422,GRAYSCALE,RGB565,JPEG - .frame_size = frame_size, //QQVGA-UXGAQQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. - - .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality - .fb_count = fb_count, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. - .grab_mode = CAMERA_GRAB_WHEN_EMPTY - }; - - //initialize the camera - esp_err_t ret = esp_camera_init(&camera_config); - - if (ESP_OK == ret && PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > size_bak) { - sensor_t *s = esp_camera_sensor_get(); - s->set_framesize(s, size_bak); - } - - return ret; -} - -static bool camera_test_fps(uint16_t times, float *fps, uint32_t *size) -{ - *fps = 0.0f; - *size = 0; - uint32_t s = 0; - uint32_t num = 0; - uint64_t total_time = esp_timer_get_time(); - for (size_t i = 0; i < times; i++) { - camera_fb_t *pic = esp_camera_fb_get(); - if (NULL == pic) { - ESP_LOGW(TAG, "fb get failed"); - return 0; - } else { - s += pic->len; - num++; - } - esp_camera_fb_return(pic); - } - total_time = esp_timer_get_time() - total_time; - if (num) { - *fps = num * 1000000.0f / total_time ; - *size = s / num; - } - return 1; -} - -static const char *get_cam_format_name(pixformat_t pixel_format) -{ - switch (pixel_format) { - case PIXFORMAT_JPEG: return "JPEG"; - case PIXFORMAT_RGB565: return "RGB565"; - case PIXFORMAT_RGB888: return "RGB888"; - case PIXFORMAT_YUV422: return "YUV422"; - default: - break; - } - return "UNKNOW"; -} - -static void printf_img_base64(const camera_fb_t *pic) -{ - uint8_t *outbuffer = NULL; - size_t outsize = 0; - if (PIXFORMAT_JPEG != pic->format) { - fmt2jpg(pic->buf, pic->width * pic->height * 2, pic->width, pic->height, pic->format, 50, &outbuffer, &outsize); - } else { - outbuffer = pic->buf; - outsize = pic->len; - } - - uint8_t *base64_buf = calloc(1, outsize * 4); - if (NULL != base64_buf) { - size_t out_len = 0; - mbedtls_base64_encode(base64_buf, outsize * 4, &out_len, outbuffer, outsize); - printf("%s\n", base64_buf); - free(base64_buf); - if (PIXFORMAT_JPEG != pic->format) { - free(outbuffer); - } - } else { - ESP_LOGE(TAG, "malloc for base64 buffer failed"); - } -} - -static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num) -{ - esp_err_t ret = ESP_OK; - //detect sensor information - TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); - sensor_t *s = esp_camera_sensor_get(); - camera_sensor_info_t *info = esp_camera_sensor_get_info(&s->id); - TEST_ASSERT_NOT_NULL(info); - TEST_ESP_OK(esp_camera_deinit()); - vTaskDelay(500 / portTICK_RATE_MS); - framesize_t max_size = info->max_size; - pixformat_t all_format[] = {PIXFORMAT_JPEG, PIXFORMAT_RGB565, PIXFORMAT_YUV422, }; - pixformat_t *format_s = &all_format[0]; - pixformat_t *format_e = &all_format[2]; - if (false == info->support_jpeg) { - format_s++; // skip jpeg - } - - struct fps_result { - float fps[FRAMESIZE_INVALID]; - uint32_t size[FRAMESIZE_INVALID]; - }; - struct fps_result results[3] = {0}; - - for (; format_s <= format_e; format_s++) { - for (size_t i = 0; i <= max_size; i++) { - ESP_LOGI(TAG, "\n\n===> Testing format:%s resolution: %d x %d <===", get_cam_format_name(*format_s), resolution[i].width, resolution[i].height); - ret = init_camera(xclk_freq, *format_s, i, 2, SIOD_GPIO_NUM, -1); - vTaskDelay(100 / portTICK_RATE_MS); - if (ESP_OK != ret) { - ESP_LOGW(TAG, "Testing init failed :-(, skip this item"); - vTaskDelay(500 / portTICK_RATE_MS); - continue; - } - camera_test_fps(pic_num, &results[format_s - all_format].fps[i], &results[format_s - all_format].size[i]); - TEST_ESP_OK(esp_camera_deinit()); - } - } - - printf("FPS Result\n"); - printf("resolution , JPEG fps, JPEG size, RGB565 fps, RGB565 size, YUV422 fps, YUV422 size \n"); - for (size_t i = 0; i <= max_size; i++) { - printf("%4d x %4d , %5.2f, %6d, %5.2f, %7d, %5.2f, %7d \n", - resolution[i].width, resolution[i].height, - results[0].fps[i], results[0].size[i], - results[1].fps[i], results[1].size[i], - results[2].fps[i], results[2].size[i]); - } - printf("----------------------------------------------------------------------------------------\n"); -} - -TEST_CASE("Camera driver init, deinit test", "[camera]") -{ - uint64_t t1 = esp_timer_get_time(); - TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); - uint64_t t2 = esp_timer_get_time(); - ESP_LOGI(TAG, "Camera init time %llu ms", (t2 - t1) / 1000); - - TEST_ESP_OK(esp_camera_deinit()); -} - -TEST_CASE("Camera driver take RGB565 picture test", "[camera]") -{ - TEST_ESP_OK(init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); - vTaskDelay(500 / portTICK_RATE_MS); - ESP_LOGI(TAG, "Taking picture..."); - camera_fb_t *pic = esp_camera_fb_get(); - if (pic) { - ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); - printf_img_base64(pic); - esp_camera_fb_return(pic); - } - - TEST_ESP_OK(esp_camera_deinit()); - TEST_ASSERT_NOT_NULL(pic); -} - -TEST_CASE("Camera driver take YUV422 picture test", "[camera]") -{ - TEST_ESP_OK(init_camera(10000000, PIXFORMAT_YUV422, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); - vTaskDelay(500 / portTICK_RATE_MS); - ESP_LOGI(TAG, "Taking picture..."); - camera_fb_t *pic = esp_camera_fb_get(); - if (pic) { - ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); - printf_img_base64(pic); - esp_camera_fb_return(pic); - } - - TEST_ESP_OK(esp_camera_deinit()); - TEST_ASSERT_NOT_NULL(pic); -} - -TEST_CASE("Camera driver take JPEG picture test", "[camera]") -{ - TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1)); - vTaskDelay(500 / portTICK_RATE_MS); - ESP_LOGI(TAG, "Taking picture..."); - camera_fb_t *pic = esp_camera_fb_get(); - if (pic) { - ESP_LOGI(TAG, "picture: %d x %d, size: %u", pic->width, pic->height, pic->len); - printf_img_base64(pic); - esp_camera_fb_return(pic); - } - - TEST_ESP_OK(esp_camera_deinit()); - TEST_ASSERT_NOT_NULL(pic); -} - -TEST_CASE("Camera driver performance test", "[camera]") -{ - camera_performance_test(20 * 1000000, 16); -} - - -static void print_rgb565_img(uint8_t *img, int width, int height) -{ - uint16_t *p = (uint16_t *)img; - const char temp2char[17] = "@MNHQ&#UJ*x7^i;."; - for (size_t j = 0; j < height; j++) { - for (size_t i = 0; i < width; i++) { - uint32_t c = p[j * width + i]; - uint8_t r = c >> 11; - uint8_t g = (c >> 6) & 0x1f; - uint8_t b = c & 0x1f; - c = (r + g + b) / 3; - c >>= 1; - printf("%c", temp2char[15 - c]); - } - printf("\n"); - } -} - -static void print_rgb888_img(uint8_t *img, int width, int height) -{ - uint8_t *p = (uint8_t *)img; - const char temp2char[17] = "@MNHQ&#UJ*x7^i;."; - for (size_t j = 0; j < height; j++) { - for (size_t i = 0; i < width; i++) { - uint8_t *c = p + 3 * (j * width + i); - uint8_t r = *c++; - uint8_t g = *c++; - uint8_t b = *c; - uint32_t v = (r + g + b) / 3; - v >>= 4; - printf("%c", temp2char[15 - v]); - } - printf("\n"); - } -} - -static void tjpgd_decode_rgb565(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer) -{ - jpg2rgb565(mjpegbuffer, size, outbuffer, JPG_SCALE_NONE); -} - -static void tjpgd_decode_rgb888(uint8_t *mjpegbuffer, uint32_t size, uint8_t *outbuffer) -{ - fmt2rgb888(mjpegbuffer, size, PIXFORMAT_JPEG, outbuffer); -} - -typedef enum { - DECODE_RGB565, - DECODE_RGB888, -} decode_type_t; - -static const decode_func_t g_decode_func[2][2] = { - {tjpgd_decode_rgb565,}, - {tjpgd_decode_rgb888,}, -}; - - -static float jpg_decode_test(uint8_t decoder_index, decode_type_t type, const uint8_t *jpg, uint32_t length, uint32_t img_w, uint32_t img_h, uint32_t times) -{ - uint8_t *jpg_buf = malloc(length); - if (NULL == jpg_buf) { - ESP_LOGE(TAG, "malloc for jpg buffer failed"); - return 0; - } - memcpy(jpg_buf, jpg, length); - - uint8_t *rgb_buf = heap_caps_malloc(img_w * img_h * 3, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (NULL == rgb_buf) { - free(jpg_buf); - ESP_LOGE(TAG, "malloc for rgb buffer failed"); - return 0; - } - decode_func_t decode = g_decode_func[type][decoder_index]; - decode(jpg_buf, length, rgb_buf); - if (DECODE_RGB565 == type) { - ESP_LOGI(TAG, "jpeg decode to rgb565"); - print_rgb565_img(rgb_buf, img_w, img_h); - } else { - ESP_LOGI(TAG, "jpeg decode to rgb888"); - print_rgb888_img(rgb_buf, img_w, img_h); - } - - uint64_t t_decode[times]; - for (size_t i = 0; i < times; i++) { - uint64_t t1 = esp_timer_get_time(); - decode(jpg_buf, length, rgb_buf); - t_decode[i] = esp_timer_get_time() - t1; - } - - printf("resolution , t \n"); - uint64_t t_total = 0; - for (size_t i = 0; i < times; i++) { - t_total += t_decode[i]; - float t = t_decode[i] / 1000.0f; - printf("%4d x %4d , %5.2f ms \n", img_w, img_h, t); - } - - float fps = times / (t_total / 1000000.0f); - printf("Decode FPS Result\n"); - printf("resolution , fps \n"); - printf("%4d x %4d , %5.2f \n", img_w, img_h, fps); - - free(jpg_buf); - heap_caps_free(rgb_buf); - return fps; -} - -static void img_jpeg_decode_test(uint16_t pic_index, uint16_t lib_index) -{ - extern const uint8_t img1_start[] asm("_binary_testimg_jpeg_start"); - extern const uint8_t img1_end[] asm("_binary_testimg_jpeg_end"); - extern const uint8_t img2_start[] asm("_binary_test_inside_jpeg_start"); - extern const uint8_t img2_end[] asm("_binary_test_inside_jpeg_end"); - extern const uint8_t img3_start[] asm("_binary_test_outside_jpeg_start"); - extern const uint8_t img3_end[] asm("_binary_test_outside_jpeg_end"); - - struct img_t { - const uint8_t *buf; - uint32_t length; - uint16_t w, h; - }; - struct img_t imgs[3] = { - { - .buf = img1_start, - .length = img1_end - img1_start, - .w = 227, - .h = 149, - }, - { - .buf = img2_start, - .length = img2_end - img2_start, - .w = 320, - .h = 240, - }, - { - .buf = img3_start, - .length = img3_end - img3_start, - .w = 480, - .h = 320, - }, - }; - - ESP_LOGI(TAG, "pic_index:%d", pic_index); - ESP_LOGI(TAG, "lib_index:%d", lib_index); - jpg_decode_test(lib_index, DECODE_RGB565, imgs[pic_index].buf, imgs[pic_index].length, imgs[pic_index].w, imgs[pic_index].h, 16); -} - -/** - * @brief i2c master initialization - */ -static esp_err_t i2c_master_init(int i2c_port) -{ - i2c_config_t conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = I2C_MASTER_SDA_IO, - .scl_io_num = I2C_MASTER_SCL_IO, - .sda_pullup_en = GPIO_PULLUP_ENABLE, - .scl_pullup_en = GPIO_PULLUP_ENABLE, - .master.clk_speed = I2C_MASTER_FREQ_HZ, - }; - - i2c_param_config(i2c_port, &conf); - - return i2c_driver_install(i2c_port, conf.mode, 0, 0, 0); -} - -TEST_CASE("Conversions image 227x149 jpeg decode test", "[camera]") -{ - img_jpeg_decode_test(0, 0); -} - -TEST_CASE("Conversions image 320x240 jpeg decode test", "[camera]") -{ - img_jpeg_decode_test(1, 0); -} - -TEST_CASE("Conversions image 480x320 jpeg decode test", "[camera]") -{ - img_jpeg_decode_test(2, 0); -} - -TEST_CASE("Camera driver uses an i2c port initialized by other devices test", "[camera]") -{ - TEST_ESP_OK(i2c_master_init(I2C_MASTER_NUM)); - TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, -1, I2C_MASTER_NUM)); - vTaskDelay(500 / portTICK_RATE_MS); - TEST_ESP_OK(esp_camera_deinit()); - TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM)); -} diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c index ec8779fd77..351656fcfa 100644 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -66,9 +66,9 @@ static void decode_task() /* Decoding stage */ err = quirc_decode(&code, &data); if (err) - printf("%d/%d] DECODE FAILED: %s\n", i,num_codes,quirc_strerror(err)); + printf("%d/%d] DECODE FAILED: %s\n", i+1,num_codes,quirc_strerror(err)); else - printf("%d/%d]Data: %s\n",i,num_codes,data.payload); + printf("%d/%d] DATA: %s\n",i+1,num_codes,data.payload); } esp_camera_fb_return(fb); diff --git a/quirc/examples/esp-eye-qrcode/main/idf_component.yml b/quirc/examples/esp-eye-qrcode/main/idf_component.yml index 03f3c26f84..6a01280d60 100644 --- a/quirc/examples/esp-eye-qrcode/main/idf_component.yml +++ b/quirc/examples/esp-eye-qrcode/main/idf_component.yml @@ -1,5 +1,6 @@ ## IDF Component Manager Manifest File dependencies: + espressif/esp32-camera: "^2.0.5" espressif/quirc: version: "^1.2.0" # This line define the local path of the component because this From e4616b866f5790e2464726b5c41a3bbcaa79726c Mon Sep 17 00:00:00 2001 From: fbez Date: Tue, 19 Sep 2023 16:09:24 +0200 Subject: [PATCH 03/14] Changed output string, updated readme --- quirc/examples/esp-eye-qrcode/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quirc/examples/esp-eye-qrcode/README.md b/quirc/examples/esp-eye-qrcode/README.md index 9fa021bb89..dea4d6a284 100644 --- a/quirc/examples/esp-eye-qrcode/README.md +++ b/quirc/examples/esp-eye-qrcode/README.md @@ -1,6 +1,6 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| x | ----- | -------- | -------- | -------- | -------- | -------- | -------- | - +| ------ | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| X | | | | | | | | # ESP-EYE QR-CODE with QUIRC In this example the esp-eye takes a picture every few ms and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). From 70ee9c4b8d5d1f8fed54b7014e29201657c20e97 Mon Sep 17 00:00:00 2001 From: fbez Date: Tue, 19 Sep 2023 16:09:58 +0200 Subject: [PATCH 04/14] Changed output string, updated readme --- quirc/examples/esp-eye-qrcode/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quirc/examples/esp-eye-qrcode/README.md b/quirc/examples/esp-eye-qrcode/README.md index dea4d6a284..22baab6794 100644 --- a/quirc/examples/esp-eye-qrcode/README.md +++ b/quirc/examples/esp-eye-qrcode/README.md @@ -1,6 +1,6 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | ------ | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -| X | | | | | | | | +| | X | | | | | | | # ESP-EYE QR-CODE with QUIRC In this example the esp-eye takes a picture every few ms and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). From 018a68931ec5b4b4797d8776cd934bdaadddd5bd Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 20 Sep 2023 09:31:26 +0200 Subject: [PATCH 05/14] removed .devcontainers --- .../esp-eye-qrcode/.devcontainer/Dockerfile | 48 ------------------- .../.devcontainer/devcontainer.json | 47 ------------------ quirc/examples/esp-eye-qrcode/main/app_main.c | 44 +++++++++-------- .../main/include/app_peripherals.h | 3 +- 4 files changed, 24 insertions(+), 118 deletions(-) delete mode 100644 quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile delete mode 100644 quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json diff --git a/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile b/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile deleted file mode 100644 index f146d1d888..0000000000 --- a/quirc/examples/esp-eye-qrcode/.devcontainer/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -FROM espressif/idf - -ARG DEBIAN_FRONTEND=nointeractive -ARG CONTAINER_USER=esp -ARG USER_UID=1000 -ARG USER_GID=$USER_UID - -RUN apt-get update \ - && apt install -y -q \ - cmake \ - git \ - hwdata \ - libglib2.0-0 \ - libnuma1 \ - libpixman-1-0 \ - linux-tools-virtual \ - && rm -rf /var/lib/apt/lists/* - -RUN update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20 - -# QEMU -ENV QEMU_REL=esp-develop-20220919 -ENV QEMU_SHA256=f6565d3f0d1e463a63a7f81aec94cce62df662bd42fc7606de4b4418ed55f870 -ENV QEMU_DIST=qemu-${QEMU_REL}.tar.bz2 -ENV QEMU_URL=https://github.com/espressif/qemu/releases/download/${QEMU_REL}/${QEMU_DIST} - -ENV LC_ALL=C.UTF-8 -ENV LANG=C.UTF-8 - -RUN wget --no-verbose ${QEMU_URL} \ - && echo "${QEMU_SHA256} *${QEMU_DIST}" | sha256sum --check --strict - \ - && tar -xf $QEMU_DIST -C /opt \ - && rm ${QEMU_DIST} - -ENV PATH=/opt/qemu/bin:${PATH} - -RUN groupadd --gid $USER_GID $CONTAINER_USER \ - && adduser --uid $USER_UID --gid $USER_GID --disabled-password --gecos "" ${CONTAINER_USER} \ - && usermod -a -G dialout $CONTAINER_USER -USER ${CONTAINER_USER} -ENV USER=${CONTAINER_USER} -WORKDIR /home/${CONTAINER_USER} - -RUN echo "source /opt/esp/idf/export.sh > /dev/null 2>&1" >> ~/.bashrc - -ENTRYPOINT [ "/opt/esp/entrypoint.sh" ] - -CMD ["/bin/bash", "-c"] \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json b/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json deleted file mode 100644 index e7b65465f0..0000000000 --- a/quirc/examples/esp-eye-qrcode/.devcontainer/devcontainer.json +++ /dev/null @@ -1,47 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.183.0/containers/ubuntu -{ - "name": "ESP-IDF QEMU", - "build": { - "dockerfile": "Dockerfile" - }, - // Add the IDs of extensions you want installed when the container is created - "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind", - /* the path of workspace folder to be opened after container is running - */ - "workspaceFolder": "${localWorkspaceFolder}", - "mounts": [ - "source=extensionCache,target=/root/.vscode-server/extensions,type=volume" - ], - "customizations": { - "vscode": { - "settings": { - "terminal.integrated.defaultProfile.linux": "bash", - "idf.espIdfPath": "/opt/esp/idf", - "idf.customExtraPaths": "", - "idf.pythonBinPath": "/opt/esp/python_env/idf5.1_py3.8_env/bin/python", - "idf.toolsPath": "/opt/esp", - "idf.gitPath": "/usr/bin/git" - }, - "extensions": [ - "ms-vscode.cpptools", - "espressif.esp-idf-extension" - ], - }, - "codespaces": { - "settings": { - "terminal.integrated.defaultProfile.linux": "bash", - "idf.espIdfPath": "/opt/esp/idf", - "idf.customExtraPaths": "", - "idf.pythonBinPath": "/opt/esp/python_env/idf5.1_py3.8_env/bin/python", - "idf.toolsPath": "/opt/esp", - "idf.gitPath": "/usr/bin/git" - }, - "extensions": [ - "ms-vscode.cpptools", - "espressif.esp-idf-extension" - ], - } - }, - "runArgs": ["--privileged"] -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c index 351656fcfa..e50a590d3c 100644 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -10,11 +10,11 @@ static const char *TAG = "APP_CODE_SCANNER"; -static void decode_task() +static void decode_task(void *args) { - if(ESP_OK != app_camera_init()) { - vTaskDelete(NULL); - return; + if (app_camera_init() != ESP_OK) { + ESP_LOGE(TAG, "Failed to init camera"); + exit(1); } camera_fb_t *fb = NULL; @@ -22,40 +22,41 @@ static void decode_task() // Initializing the quirc handle struct quirc *q = quirc_new(); if (!q) { - ESP_LOGE(TAG,"Failed to allocate memory\n"); + ESP_LOGE(TAG, "Failed to allocate memory"); exit(1); } // Get image size through fb parameters fb = esp_camera_fb_get(); - if(fb == NULL){ - ESP_LOGI(TAG, "camera get failed\n"); + if (fb == NULL) { + ESP_LOGE(TAG, "Camera get failed"); + exit(1); } uint16_t p_width = fb->width; uint16_t p_height = fb->height; - if (quirc_resize(q, p_width,p_height) < 0) { - ESP_LOGE(TAG,"Failed to allocate video memory\n"); + if (quirc_resize(q, p_width, p_height) < 0) { + ESP_LOGE(TAG, "Failed to allocate video memory\n"); exit(1); - } + } struct quirc_code code; struct quirc_data data; quirc_decode_error_t err; uint16_t num_codes; - while (1) - { + while (1) { fb = esp_camera_fb_get(); - if(fb == NULL){ - ESP_LOGI(TAG, "camera get failed\n"); - continue; + if (fb == NULL) { + ESP_LOGE(TAG, "Camera get failed"); + exit(1); } + // Decode Progress - + memcpy(quirc_begin(q, NULL, NULL), fb->buf, fb->len); quirc_end(q); @@ -65,10 +66,11 @@ static void decode_task() quirc_extract(q, i, &code); /* Decoding stage */ err = quirc_decode(&code, &data); - if (err) - printf("%d/%d] DECODE FAILED: %s\n", i+1,num_codes,quirc_strerror(err)); - else - printf("%d/%d] DATA: %s\n",i+1,num_codes,data.payload); + if (err) { + printf("%d/%d] DECODE FAILED: %s\n", i + 1, num_codes, quirc_strerror(err)); + } else { + printf("%d/%d] DATA: %s\n", i + 1, num_codes, data.payload); + } } esp_camera_fb_return(fb); @@ -79,7 +81,7 @@ static void decode_task() } -void app_main() +void app_main(void) { xTaskCreatePinnedToCore(decode_task, TAG, 40 * 1024, NULL, 6, NULL, 0); } \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h index e7fe3df17d..c033c6ce0b 100644 --- a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h +++ b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h @@ -241,8 +241,7 @@ extern "C" { #endif - esp_err_t app_camera_init(); - esp_err_t app_lcd_init(); +esp_err_t app_camera_init(void); #ifdef __cplusplus } #endif \ No newline at end of file From 88a3f3191a2a0809a779c7c8a2ae7397ff01c178 Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 20 Sep 2023 12:46:06 +0200 Subject: [PATCH 06/14] removed unreachable code --- quirc/examples/esp-eye-qrcode/main/app_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c index e50a590d3c..5b4ba7b38e 100644 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -77,7 +77,6 @@ static void decode_task(void *args) vTaskDelay(10 / portTICK_PERIOD_MS); } - quirc_destroy(q); } From f3e91329a7555b267aec6dec0eeb172a5e0637e3 Mon Sep 17 00:00:00 2001 From: fbez Date: Mon, 16 Oct 2023 17:08:59 +0200 Subject: [PATCH 07/14] moved to esp32-s3 eye - decode failed ecc failure --- quirc/examples/esp-eye-qrcode/main/app_main.c | 27 +++++++++++++++---- .../esp-eye-qrcode/main/idf_component.yml | 1 + .../main/include/app_peripherals.h | 2 +- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c index 5b4ba7b38e..a589f6a273 100644 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -3,23 +3,37 @@ #include #include "esp_log.h" #include "esp_system.h" +#include "bsp/esp-bsp.h" #include "freertos/FreeRTOS.h" +#include "esp_camera.h" #include "freertos/task.h" -#include "app_peripherals.h" +//#include "app_peripherals.h" #include "quirc.h" static const char *TAG = "APP_CODE_SCANNER"; static void decode_task(void *args) { - if (app_camera_init() != ESP_OK) { - ESP_LOGE(TAG, "Failed to init camera"); + + bsp_i2c_init(); + bsp_leds_init(); + bsp_led_set(BSP_LED_GREEN, false); + /* Camera init start*/ + camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG; + camera_config.pixel_format = PIXFORMAT_GRAYSCALE; + camera_config.xclk_freq_hz = 20000000; + if (esp_camera_init(&camera_config) != ESP_OK) { + ESP_LOGE(TAG, "Camera Init Failed"); exit(1); } + sensor_t *s = esp_camera_sensor_get(); + s->set_vflip(s, 1); + ESP_LOGI(TAG, "Camera Init done"); + /* Camera init end*/ camera_fb_t *fb = NULL; - // Initializing the quirc handle + /* Initializing the quirc handle */ struct quirc *q = quirc_new(); if (!q) { ESP_LOGE(TAG, "Failed to allocate memory"); @@ -27,7 +41,7 @@ static void decode_task(void *args) } - // Get image size through fb parameters + /* Get image size through fb parameters */ fb = esp_camera_fb_get(); if (fb == NULL) { ESP_LOGE(TAG, "Camera get failed"); @@ -37,6 +51,7 @@ static void decode_task(void *args) uint16_t p_width = fb->width; uint16_t p_height = fb->height; + printf("Detected width:%d \t height:%d \n\n", p_width, p_height); if (quirc_resize(q, p_width, p_height) < 0) { ESP_LOGE(TAG, "Failed to allocate video memory\n"); @@ -70,11 +85,13 @@ static void decode_task(void *args) printf("%d/%d] DECODE FAILED: %s\n", i + 1, num_codes, quirc_strerror(err)); } else { printf("%d/%d] DATA: %s\n", i + 1, num_codes, data.payload); + bsp_led_set(BSP_LED_GREEN, true); } } esp_camera_fb_return(fb); vTaskDelay(10 / portTICK_PERIOD_MS); + bsp_led_set(BSP_LED_GREEN, false); } } diff --git a/quirc/examples/esp-eye-qrcode/main/idf_component.yml b/quirc/examples/esp-eye-qrcode/main/idf_component.yml index 6a01280d60..edb1e48326 100644 --- a/quirc/examples/esp-eye-qrcode/main/idf_component.yml +++ b/quirc/examples/esp-eye-qrcode/main/idf_component.yml @@ -1,5 +1,6 @@ ## IDF Component Manager Manifest File dependencies: + espressif/esp32_s3_eye: "^3.0.2" espressif/esp32-camera: "^2.0.5" espressif/quirc: version: "^1.2.0" diff --git a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h index c033c6ce0b..047d9c57c0 100644 --- a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h +++ b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h @@ -196,7 +196,7 @@ #define XCLK_FREQ_HZ 20000000 #define CAMERA_PIXFORMAT PIXFORMAT_GRAYSCALE -#define CAMERA_FRAME_SIZE FRAMESIZE_240X240 +#define CAMERA_FRAME_SIZE FRAMESIZE_VGA #define CAMERA_FB_COUNT 2 From e2f8508b4f3263a47747e67d27baded49c284422 Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 16:20:11 +0200 Subject: [PATCH 08/14] added example for esp32-s3 --- quirc/examples/esp-eye-qrcode/main/app_main.c | 28 +++- .../esp-eye-qrcode/sdkconfig.defaults.esp32s3 | 32 +++-- .../esp32-s3-eye-qrcode/CMakeLists.txt | 9 ++ quirc/examples/esp32-s3-eye-qrcode/README.md | 10 ++ .../esp32-s3-eye-qrcode/main/CMakeLists.txt | 2 + .../main/esp32-s3-eye-example.c | 127 ++++++++++++++++++ .../main/idf_component.yml | 6 + .../sdkconfig.bsp.esp32_s3_eye | 23 ++++ .../esp32-s3-eye-qrcode/sdkconfig.defaults | 14 ++ 9 files changed, 237 insertions(+), 14 deletions(-) create mode 100644 quirc/examples/esp32-s3-eye-qrcode/CMakeLists.txt create mode 100644 quirc/examples/esp32-s3-eye-qrcode/README.md create mode 100644 quirc/examples/esp32-s3-eye-qrcode/main/CMakeLists.txt create mode 100644 quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c create mode 100644 quirc/examples/esp32-s3-eye-qrcode/main/idf_component.yml create mode 100644 quirc/examples/esp32-s3-eye-qrcode/sdkconfig.bsp.esp32_s3_eye create mode 100644 quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c index a589f6a273..c1c72af4b8 100644 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ b/quirc/examples/esp-eye-qrcode/main/app_main.c @@ -2,6 +2,7 @@ #include #include #include "esp_log.h" +#include "sdkconfig.h" #include "esp_system.h" #include "bsp/esp-bsp.h" #include "freertos/FreeRTOS.h" @@ -16,21 +17,34 @@ static void decode_task(void *args) { bsp_i2c_init(); + bsp_display_start(); + bsp_display_backlight_on(); // Set display brightness to 100% + bsp_leds_init(); bsp_led_set(BSP_LED_GREEN, false); + /* Camera init start*/ camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG; - camera_config.pixel_format = PIXFORMAT_GRAYSCALE; - camera_config.xclk_freq_hz = 20000000; + //camera_config.pixel_format = PIXFORMAT_GRAYSCALE; + //camera_config.xclk_freq_hz = 20000000; if (esp_camera_init(&camera_config) != ESP_OK) { ESP_LOGE(TAG, "Camera Init Failed"); exit(1); } sensor_t *s = esp_camera_sensor_get(); s->set_vflip(s, 1); + + ESP_LOGI(TAG, "Camera Init done"); /* Camera init end*/ + + bsp_display_lock(0); + lv_obj_t *camera_canvas = lv_canvas_create(lv_scr_act()); + assert(camera_canvas); + lv_obj_center(camera_canvas); + bsp_display_unlock(); + camera_fb_t *fb = NULL; /* Initializing the quirc handle */ @@ -47,7 +61,9 @@ static void decode_task(void *args) ESP_LOGE(TAG, "Camera get failed"); exit(1); } - + bsp_display_lock(1000); + lv_canvas_set_buffer(camera_canvas, fb->buf, fb->width, fb->height, LV_IMG_CF_TRUE_COLOR); + bsp_display_unlock(); uint16_t p_width = fb->width; uint16_t p_height = fb->height; @@ -57,6 +73,11 @@ static void decode_task(void *args) ESP_LOGE(TAG, "Failed to allocate video memory\n"); exit(1); } + bsp_display_lock(1000); + lv_canvas_set_buffer(camera_canvas, fb->buf, fb->width, fb->height, LV_IMG_CF_TRUE_COLOR); + bsp_display_unlock(); + esp_camera_fb_return(fb); + struct quirc_code code; struct quirc_data data; @@ -99,5 +120,6 @@ static void decode_task(void *args) void app_main(void) { + xTaskCreatePinnedToCore(decode_task, TAG, 40 * 1024, NULL, 6, NULL, 0); } \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 index b95f661535..64e26b9ed0 100644 --- a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 +++ b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 @@ -1,13 +1,23 @@ -CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32s3" +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_ESP_DEFAULT_CPU_FREQ_240=y +CONFIG_SPIRAM=y CONFIG_ESP32S3_SPIRAM_SUPPORT=y - -CONFIG_ESP32S3_DATA_CACHE_64KB=y -CONFIG_ESP32S3_DATA_CACHE_8WAYS=y -CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y - -CONFIG_CAMERA_MODULE_ESP_S3_EYE=y -CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y -CONFIG_ESPTOOLPY_NO_STUB=y -CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y - CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_LV_COLOR_16_SWAP=y +CONFIG_LV_MEM_CUSTOM=y +CONFIG_LV_MEMCPY_MEMSET_STD=y +CONFIG_LV_USE_PERF_MONITOR=y +CONFIG_LV_SPRINTF_CUSTOM=y +# CONFIG_LV_BUILD_EXAMPLES is not set \ No newline at end of file diff --git a/quirc/examples/esp32-s3-eye-qrcode/CMakeLists.txt b/quirc/examples/esp32-s3-eye-qrcode/CMakeLists.txt new file mode 100644 index 0000000000..4614d7b692 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/CMakeLists.txt @@ -0,0 +1,9 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +set(COMPONENTS main) # "Trim" the build. Include the minimal set of components; main and anything it depends on. +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ESP32-S3-EYE-QRCODE) diff --git a/quirc/examples/esp32-s3-eye-qrcode/README.md b/quirc/examples/esp32-s3-eye-qrcode/README.md new file mode 100644 index 0000000000..4065deefa4 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/README.md @@ -0,0 +1,10 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ------ | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| | | | | | | | |X| +# ESP32-S3-EYE QR-CODE with QUIRC + +In this example the esp-eye takes a picture every few ms, show them on the display and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). + +## How to use example + +Build and flash on an esp32-s3-eye. It may work with small changes also on ESP32-CAM and ESP32-S3-EYE. diff --git a/quirc/examples/esp32-s3-eye-qrcode/main/CMakeLists.txt b/quirc/examples/esp32-s3-eye-qrcode/main/CMakeLists.txt new file mode 100644 index 0000000000..cc69dd1797 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "esp32-s3-eye-example" + INCLUDE_DIRS ".") diff --git a/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c b/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c new file mode 100644 index 0000000000..ba4b7f54fc --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c @@ -0,0 +1,127 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include "sdkconfig.h" +#include "bsp/esp-bsp.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "driver/spi_master.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_lcd_panel_io.h" +#include "esp_lcd_panel_vendor.h" +#include "esp_lcd_panel_ops.h" +#include "esp_camera.h" +#include "quirc.h" + +static const char *TAG = "example"; + +lv_obj_t *camera_canvas = NULL; + +void grayscale_to_rgb565(uint8_t *grayscale_buf, uint8_t *rgb565_buf, uint16_t length) +{ + uint8_t reduced = 0; + uint32_t rgb565_counter = 0; + uint16_t k = 0; + for (k = 0; k < length; k++) { + reduced = (grayscale_buf[k] >> 3) & 0b00011111; + //rgb565_buf[rgb565_counter] = ((reduced << 6) | (reduced)); // G2 G1 G0(=0) B4 B3 B2 B1 B0 + rgb565_buf[rgb565_counter] = ((reduced << 3) | (reduced >> 2)); + rgb565_counter++; + //rgb565_buf[rgb565_counter] = ((reduced << 3) | (reduced>>2)); // R4 R3 R2 R1 R0 G4 G3 G2 + rgb565_buf[rgb565_counter] = ((reduced << 6) | (reduced)); + rgb565_counter++; + } +} + +static void decode_task(void *args) +{ + bsp_i2c_init(); + bsp_display_start(); + bsp_display_backlight_on(); // Set display brightness to 100% + + // Initialize the camera + camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG; + camera_config.pixel_format = PIXFORMAT_GRAYSCALE; + esp_err_t err = esp_camera_init(&camera_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Camera Init Failed"); + return; + } + sensor_t *s = esp_camera_sensor_get(); + s->set_vflip(s, 1); + s->set_hmirror(s, 1); + s->set_contrast(s, 2); + ESP_LOGI(TAG, "Camera Init done"); + + // Create LVGL canvas for camera image + bsp_display_lock(0); + camera_canvas = lv_canvas_create(lv_scr_act()); + + assert(camera_canvas); + lv_obj_center(camera_canvas); + bsp_display_unlock(); + + camera_fb_t *pic = esp_camera_fb_get(); + uint8_t *buf_shown = (uint8_t *)lv_mem_alloc(pic->len * 2); // double the size because the canvas requires a color RGB565 + esp_camera_fb_return(pic); + + /* Initializing the quirc handle */ + struct quirc *q = quirc_new(); + if (!q) { + ESP_LOGE(TAG, "Failed to allocate memory"); + exit(1); + } + if (quirc_resize(q, pic->width, pic->height) < 0) { + ESP_LOGE(TAG, "Failed to allocate video memory\n"); + exit(1); + } + + struct quirc_code code; + struct quirc_data data; + quirc_decode_error_t q_err; + uint16_t num_codes; + + while (1) { + pic = esp_camera_fb_get(); + //printf("w: %d\th: %d\tbytes: %d\tformat: %d\n", pic->width, pic->height,pic->len, pic->format); + if (pic) { + + bsp_display_lock(0); + grayscale_to_rgb565(pic->buf, buf_shown, pic->len); + lv_canvas_set_buffer(camera_canvas, buf_shown, pic->width, pic->height, LV_IMG_CF_TRUE_COLOR); + bsp_display_unlock(); + + memcpy(quirc_begin(q, NULL, NULL), pic->buf, pic->len); + quirc_end(q); + + num_codes = quirc_count(q); + for (uint16_t i = 0; i < num_codes; i++) { + + quirc_extract(q, i, &code); + /* Decoding stage */ + q_err = quirc_decode(&code, &data); + if (q_err != 0) { + printf("%d/%d] DECODE FAILED: %s\n", i + 1, num_codes, quirc_strerror(q_err)); + } else { + printf("%d/%d] DATA: %s\n", i + 1, num_codes, data.payload); + } + } + + esp_camera_fb_return(pic); + } else { + ESP_LOGE(TAG, "Get frame failed"); + } + + } +} +void app_main(void) +{ + xTaskCreatePinnedToCore(decode_task, TAG, 40 * 1024, NULL, 6, NULL, 0); +} + diff --git a/quirc/examples/esp32-s3-eye-qrcode/main/idf_component.yml b/quirc/examples/esp32-s3-eye-qrcode/main/idf_component.yml new file mode 100644 index 0000000000..83b4dc2014 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/main/idf_component.yml @@ -0,0 +1,6 @@ +description: Quirc example using ESP32-S3-EYE board + +dependencies: + espressif/esp32_s3_eye: "^3.0.2" + espressif/quirc: + version: "^1.2.0" diff --git a/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.bsp.esp32_s3_eye b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.bsp.esp32_s3_eye new file mode 100644 index 0000000000..1dbdec8e45 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.bsp.esp32_s3_eye @@ -0,0 +1,23 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32s3" +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_ESP_DEFAULT_CPU_FREQ_240=y +CONFIG_SPIRAM=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_LV_COLOR_16_SWAP=y +CONFIG_LV_MEM_CUSTOM=y +CONFIG_LV_MEMCPY_MEMSET_STD=y +CONFIG_LV_USE_PERF_MONITOR=y +CONFIG_LV_SPRINTF_CUSTOM=y +# CONFIG_LV_BUILD_EXAMPLES is not set diff --git a/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults new file mode 100644 index 0000000000..d14403491a --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults @@ -0,0 +1,14 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32s2" +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_LV_MEM_CUSTOM=y +CONFIG_LV_MEMCPY_MEMSET_STD=y +# CONFIG_LV_BUILD_EXAMPLES is not set From eff35ade2e996118ee1c0355bb078da4ca7ae4db Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 16:20:46 +0200 Subject: [PATCH 09/14] removed esp-eye example --- quirc/examples/esp-eye-qrcode/CMakeLists.txt | 8 - quirc/examples/esp-eye-qrcode/README.md | 10 - .../esp-eye-qrcode/main/CMakeLists.txt | 6 - quirc/examples/esp-eye-qrcode/main/app_main.c | 125 --------- .../esp-eye-qrcode/main/app_peripherals.c | 65 ----- .../esp-eye-qrcode/main/idf_component.yml | 12 - .../main/include/app_peripherals.h | 247 ------------------ .../esp-eye-qrcode/sdkconfig.defaults | 6 - .../esp-eye-qrcode/sdkconfig.defaults.esp32 | 4 - .../esp-eye-qrcode/sdkconfig.defaults.esp32s2 | 8 - .../esp-eye-qrcode/sdkconfig.defaults.esp32s3 | 23 -- 11 files changed, 514 deletions(-) delete mode 100644 quirc/examples/esp-eye-qrcode/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/README.md delete mode 100644 quirc/examples/esp-eye-qrcode/main/CMakeLists.txt delete mode 100644 quirc/examples/esp-eye-qrcode/main/app_main.c delete mode 100644 quirc/examples/esp-eye-qrcode/main/app_peripherals.c delete mode 100644 quirc/examples/esp-eye-qrcode/main/idf_component.yml delete mode 100644 quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h delete mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults delete mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 delete mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 delete mode 100644 quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 diff --git a/quirc/examples/esp-eye-qrcode/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/CMakeLists.txt deleted file mode 100644 index efb143f8d3..0000000000 --- a/quirc/examples/esp-eye-qrcode/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# For more information about build system see -# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.16) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(app_main) diff --git a/quirc/examples/esp-eye-qrcode/README.md b/quirc/examples/esp-eye-qrcode/README.md deleted file mode 100644 index 22baab6794..0000000000 --- a/quirc/examples/esp-eye-qrcode/README.md +++ /dev/null @@ -1,10 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ------ | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -| | X | | | | | | | -# ESP-EYE QR-CODE with QUIRC - -In this example the esp-eye takes a picture every few ms and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). - -## How to use example - -Build and flash on an esp-eye. It may work with small changes also on ESP32-CAM and ESP32-S3-EYE. diff --git a/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt b/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt deleted file mode 100644 index b779e24d3c..0000000000 --- a/quirc/examples/esp-eye-qrcode/main/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -idf_component_register( SRCS - app_peripherals.c - app_main.c - INCLUDE_DIRS - include - ) \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/app_main.c b/quirc/examples/esp-eye-qrcode/main/app_main.c deleted file mode 100644 index c1c72af4b8..0000000000 --- a/quirc/examples/esp-eye-qrcode/main/app_main.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include "esp_log.h" -#include "sdkconfig.h" -#include "esp_system.h" -#include "bsp/esp-bsp.h" -#include "freertos/FreeRTOS.h" -#include "esp_camera.h" -#include "freertos/task.h" -//#include "app_peripherals.h" -#include "quirc.h" - -static const char *TAG = "APP_CODE_SCANNER"; - -static void decode_task(void *args) -{ - - bsp_i2c_init(); - bsp_display_start(); - bsp_display_backlight_on(); // Set display brightness to 100% - - bsp_leds_init(); - bsp_led_set(BSP_LED_GREEN, false); - - /* Camera init start*/ - camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG; - //camera_config.pixel_format = PIXFORMAT_GRAYSCALE; - //camera_config.xclk_freq_hz = 20000000; - if (esp_camera_init(&camera_config) != ESP_OK) { - ESP_LOGE(TAG, "Camera Init Failed"); - exit(1); - } - sensor_t *s = esp_camera_sensor_get(); - s->set_vflip(s, 1); - - - ESP_LOGI(TAG, "Camera Init done"); - /* Camera init end*/ - - - bsp_display_lock(0); - lv_obj_t *camera_canvas = lv_canvas_create(lv_scr_act()); - assert(camera_canvas); - lv_obj_center(camera_canvas); - bsp_display_unlock(); - - camera_fb_t *fb = NULL; - - /* Initializing the quirc handle */ - struct quirc *q = quirc_new(); - if (!q) { - ESP_LOGE(TAG, "Failed to allocate memory"); - exit(1); - } - - - /* Get image size through fb parameters */ - fb = esp_camera_fb_get(); - if (fb == NULL) { - ESP_LOGE(TAG, "Camera get failed"); - exit(1); - } - bsp_display_lock(1000); - lv_canvas_set_buffer(camera_canvas, fb->buf, fb->width, fb->height, LV_IMG_CF_TRUE_COLOR); - bsp_display_unlock(); - uint16_t p_width = fb->width; - uint16_t p_height = fb->height; - - printf("Detected width:%d \t height:%d \n\n", p_width, p_height); - - if (quirc_resize(q, p_width, p_height) < 0) { - ESP_LOGE(TAG, "Failed to allocate video memory\n"); - exit(1); - } - bsp_display_lock(1000); - lv_canvas_set_buffer(camera_canvas, fb->buf, fb->width, fb->height, LV_IMG_CF_TRUE_COLOR); - bsp_display_unlock(); - esp_camera_fb_return(fb); - - - struct quirc_code code; - struct quirc_data data; - quirc_decode_error_t err; - uint16_t num_codes; - - while (1) { - fb = esp_camera_fb_get(); - if (fb == NULL) { - ESP_LOGE(TAG, "Camera get failed"); - exit(1); - } - - // Decode Progress - - memcpy(quirc_begin(q, NULL, NULL), fb->buf, fb->len); - quirc_end(q); - - num_codes = quirc_count(q); - for (uint16_t i = 0; i < num_codes; i++) { - - quirc_extract(q, i, &code); - /* Decoding stage */ - err = quirc_decode(&code, &data); - if (err) { - printf("%d/%d] DECODE FAILED: %s\n", i + 1, num_codes, quirc_strerror(err)); - } else { - printf("%d/%d] DATA: %s\n", i + 1, num_codes, data.payload); - bsp_led_set(BSP_LED_GREEN, true); - } - } - - esp_camera_fb_return(fb); - vTaskDelay(10 / portTICK_PERIOD_MS); - bsp_led_set(BSP_LED_GREEN, false); - } - -} - - -void app_main(void) -{ - - xTaskCreatePinnedToCore(decode_task, TAG, 40 * 1024, NULL, 6, NULL, 0); -} \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/app_peripherals.c b/quirc/examples/esp-eye-qrcode/main/app_peripherals.c deleted file mode 100644 index 734c73cfb1..0000000000 --- a/quirc/examples/esp-eye-qrcode/main/app_peripherals.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "app_peripherals.h" -#include "esp_log.h" -#include "esp_system.h" - -static const char *TAG = "app_peripherals"; - -esp_err_t app_camera_init() -{ - ESP_LOGI(TAG, "Camera module is %s", CAMERA_MODULE_NAME); - - camera_config_t config; - config.ledc_channel = LEDC_CHANNEL_0; - config.ledc_timer = LEDC_TIMER_0; - config.pin_d0 = CAMERA_PIN_D0; - config.pin_d1 = CAMERA_PIN_D1; - config.pin_d2 = CAMERA_PIN_D2; - config.pin_d3 = CAMERA_PIN_D3; - config.pin_d4 = CAMERA_PIN_D4; - config.pin_d5 = CAMERA_PIN_D5; - config.pin_d6 = CAMERA_PIN_D6; - config.pin_d7 = CAMERA_PIN_D7; - config.pin_xclk = CAMERA_PIN_XCLK; - config.pin_pclk = CAMERA_PIN_PCLK; - config.pin_vsync = CAMERA_PIN_VSYNC; - config.pin_href = CAMERA_PIN_HREF; - config.pin_sccb_sda = CAMERA_PIN_SIOD; - config.pin_sccb_scl = CAMERA_PIN_SIOC; - config.pin_pwdn = CAMERA_PIN_PWDN; - config.pin_reset = CAMERA_PIN_RESET; - config.xclk_freq_hz = XCLK_FREQ_HZ; - config.pixel_format = CAMERA_PIXFORMAT; - config.frame_size = CAMERA_FRAME_SIZE; - config.jpeg_quality = 5; - config.fb_count = CAMERA_FB_COUNT; - config.fb_location = CAMERA_FB_IN_PSRAM; - config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; - - // camera init - esp_err_t err = esp_camera_init(&config); - if (err != ESP_OK) - { - ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); - return ESP_FAIL; - } - - sensor_t *s = esp_camera_sensor_get(); - if (s->id.PID == OV3660_PID || s->id.PID == OV2640_PID) - s->set_vflip(s, 1); //flip it back - else if (s->id.PID == GC0308_PID){ - s->set_hmirror(s, 0); - } - else if (s->id.PID == GC032A_PID){ - s->set_vflip(s, 1); - } - - if (s->id.PID == OV3660_PID) - { - s->set_brightness(s, 2); - s->set_contrast(s, 3); - } - - return ESP_OK; -} - - diff --git a/quirc/examples/esp-eye-qrcode/main/idf_component.yml b/quirc/examples/esp-eye-qrcode/main/idf_component.yml deleted file mode 100644 index edb1e48326..0000000000 --- a/quirc/examples/esp-eye-qrcode/main/idf_component.yml +++ /dev/null @@ -1,12 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - espressif/esp32_s3_eye: "^3.0.2" - espressif/esp32-camera: "^2.0.5" - espressif/quirc: - version: "^1.2.0" - # This line define the local path of the component because this - # example is part of the component. This line is optional. - override_path: "../../.." - ## Required IDF version - idf: - version: ">=4.3.0" \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h b/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h deleted file mode 100644 index 047d9c57c0..0000000000 --- a/quirc/examples/esp-eye-qrcode/main/include/app_peripherals.h +++ /dev/null @@ -1,247 +0,0 @@ -#pragma once - -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "freertos/semphr.h" - -#include "esp_camera.h" - -#define CONFIG_CAMERA_MODULE_ESP_EYE 1 -// camera pins -#if CONFIG_CAMERA_MODULE_WROVER_KIT -#define CAMERA_MODULE_NAME "Wrover Kit" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET -1 -#define CAMERA_PIN_XCLK 21 -#define CAMERA_PIN_SIOD 26 -#define CAMERA_PIN_SIOC 27 - -#define CAMERA_PIN_D7 35 -#define CAMERA_PIN_D6 34 -#define CAMERA_PIN_D5 39 -#define CAMERA_PIN_D4 36 -#define CAMERA_PIN_D3 19 -#define CAMERA_PIN_D2 18 -#define CAMERA_PIN_D1 5 -#define CAMERA_PIN_D0 4 -#define CAMERA_PIN_VSYNC 25 -#define CAMERA_PIN_HREF 23 -#define CAMERA_PIN_PCLK 22 - -#elif CONFIG_CAMERA_MODULE_ESP_EYE -#define CAMERA_MODULE_NAME "ESP-EYE" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET -1 -#define CAMERA_PIN_XCLK 4 -#define CAMERA_PIN_SIOD 18 -#define CAMERA_PIN_SIOC 23 - -#define CAMERA_PIN_D7 36 -#define CAMERA_PIN_D6 37 -#define CAMERA_PIN_D5 38 -#define CAMERA_PIN_D4 39 -#define CAMERA_PIN_D3 35 -#define CAMERA_PIN_D2 14 -#define CAMERA_PIN_D1 13 -#define CAMERA_PIN_D0 34 -#define CAMERA_PIN_VSYNC 5 -#define CAMERA_PIN_HREF 27 -#define CAMERA_PIN_PCLK 25 - -#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA -#define CAMERA_MODULE_NAME "ESP-S2-KALUGA" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET -1 -#define CAMERA_PIN_XCLK 1 -#define CAMERA_PIN_SIOD 8 -#define CAMERA_PIN_SIOC 7 - -#define CAMERA_PIN_D7 38 -#define CAMERA_PIN_D6 21 -#define CAMERA_PIN_D5 40 -#define CAMERA_PIN_D4 39 -#define CAMERA_PIN_D3 42 -#define CAMERA_PIN_D2 41 -#define CAMERA_PIN_D1 37 -#define CAMERA_PIN_D0 36 -#define CAMERA_PIN_VSYNC 2 -#define CAMERA_PIN_HREF 3 -#define CAMERA_PIN_PCLK 33 - -#elif CONFIG_CAMERA_MODULE_ESP_S3_EYE -#define CAMERA_MODULE_NAME "ESP-S3-EYE" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET -1 - -#define CAMERA_PIN_VSYNC 6 -#define CAMERA_PIN_HREF 7 -#define CAMERA_PIN_PCLK 13 -#define CAMERA_PIN_XCLK 15 - -#define CAMERA_PIN_SIOD 4 -#define CAMERA_PIN_SIOC 5 - -#define CAMERA_PIN_D0 11 -#define CAMERA_PIN_D1 9 -#define CAMERA_PIN_D2 8 -#define CAMERA_PIN_D3 10 -#define CAMERA_PIN_D4 12 -#define CAMERA_PIN_D5 18 -#define CAMERA_PIN_D6 17 -#define CAMERA_PIN_D7 16 - -#elif CONFIG_CAMERA_MODULE_ESP32_CAM_BOARD -#define CAMERA_MODULE_NAME "ESP-DEVCAM" -#define CAMERA_PIN_PWDN 32 -#define CAMERA_PIN_RESET 33 - -#define CAMERA_PIN_XCLK 4 -#define CAMERA_PIN_SIOD 18 -#define CAMERA_PIN_SIOC 23 - -#define CAMERA_PIN_D7 36 -#define CAMERA_PIN_D6 19 -#define CAMERA_PIN_D5 21 -#define CAMERA_PIN_D4 39 -#define CAMERA_PIN_D3 35 -#define CAMERA_PIN_D2 14 -#define CAMERA_PIN_D1 13 -#define CAMERA_PIN_D0 34 -#define CAMERA_PIN_VSYNC 5 -#define CAMERA_PIN_HREF 27 -#define CAMERA_PIN_PCLK 25 - -#elif CONFIG_CAMERA_MODULE_M5STACK_PSRAM -#define CAMERA_MODULE_NAME "M5STACK-PSRAM" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET 15 - -#define CAMERA_PIN_XCLK 27 -#define CAMERA_PIN_SIOD 25 -#define CAMERA_PIN_SIOC 23 - -#define CAMERA_PIN_D7 19 -#define CAMERA_PIN_D6 36 -#define CAMERA_PIN_D5 18 -#define CAMERA_PIN_D4 39 -#define CAMERA_PIN_D3 5 -#define CAMERA_PIN_D2 34 -#define CAMERA_PIN_D1 35 -#define CAMERA_PIN_D0 32 -#define CAMERA_PIN_VSYNC 22 -#define CAMERA_PIN_HREF 26 -#define CAMERA_PIN_PCLK 21 - -#elif CONFIG_CAMERA_MODULE_M5STACK_WIDE -#define CAMERA_MODULE_NAME "M5STACK-WIDE" -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET 15 -#define CAMERA_PIN_XCLK 27 -#define CAMERA_PIN_SIOD 22 -#define CAMERA_PIN_SIOC 23 - -#define CAMERA_PIN_D7 19 -#define CAMERA_PIN_D6 36 -#define CAMERA_PIN_D5 18 -#define CAMERA_PIN_D4 39 -#define CAMERA_PIN_D3 5 -#define CAMERA_PIN_D2 34 -#define CAMERA_PIN_D1 35 -#define CAMERA_PIN_D0 32 -#define CAMERA_PIN_VSYNC 25 -#define CAMERA_PIN_HREF 26 -#define CAMERA_PIN_PCLK 21 - -#elif CONFIG_CAMERA_MODULE_AI_THINKER -#define CAMERA_MODULE_NAME "AI-THINKER" -#define CAMERA_PIN_PWDN 32 -#define CAMERA_PIN_RESET -1 -#define CAMERA_PIN_XCLK 0 -#define CAMERA_PIN_SIOD 26 -#define CAMERA_PIN_SIOC 27 - -#define CAMERA_PIN_D7 35 -#define CAMERA_PIN_D6 34 -#define CAMERA_PIN_D5 39 -#define CAMERA_PIN_D4 36 -#define CAMERA_PIN_D3 21 -#define CAMERA_PIN_D2 19 -#define CAMERA_PIN_D1 18 -#define CAMERA_PIN_D0 5 -#define CAMERA_PIN_VSYNC 25 -#define CAMERA_PIN_HREF 23 -#define CAMERA_PIN_PCLK 22 - -#elif CONFIG_CAMERA_MODULE_CUSTOM -#define CAMERA_MODULE_NAME "CUSTOM" -#define CAMERA_PIN_PWDN CONFIG_CAMERA_PIN_PWDN -#define CAMERA_PIN_RESET CONFIG_CAMERA_PIN_RESET -#define CAMERA_PIN_XCLK CONFIG_CAMERA_PIN_XCLK -#define CAMERA_PIN_SIOD CONFIG_CAMERA_PIN_SIOD -#define CAMERA_PIN_SIOC CONFIG_CAMERA_PIN_SIOC - -#define CAMERA_PIN_D7 CONFIG_CAMERA_PIN_Y9 -#define CAMERA_PIN_D6 CONFIG_CAMERA_PIN_Y8 -#define CAMERA_PIN_D5 CONFIG_CAMERA_PIN_Y7 -#define CAMERA_PIN_D4 CONFIG_CAMERA_PIN_Y6 -#define CAMERA_PIN_D3 CONFIG_CAMERA_PIN_Y5 -#define CAMERA_PIN_D2 CONFIG_CAMERA_PIN_Y4 -#define CAMERA_PIN_D1 CONFIG_CAMERA_PIN_Y3 -#define CAMERA_PIN_D0 CONFIG_CAMERA_PIN_Y2 -#define CAMERA_PIN_VSYNC CONFIG_CAMERA_PIN_VSYNC -#define CAMERA_PIN_HREF CONFIG_CAMERA_PIN_HREF -#define CAMERA_PIN_PCLK CONFIG_CAMERA_PIN_PCLK -#endif - -#define XCLK_FREQ_HZ 20000000 -#define CAMERA_PIXFORMAT PIXFORMAT_GRAYSCALE -#define CAMERA_FRAME_SIZE FRAMESIZE_VGA -#define CAMERA_FB_COUNT 2 - - - -// lcd pins and setting -#if CONFIG_CAMERA_MODULE_ESP_S3_EYE -#define LCD_CONTROLLER SCREEN_CONTROLLER_ST7789 - -#define LCD_MOSI 47 -#define LCD_MISO -1 -#define LCD_SCLK 21 -#define LCD_CS 44 -#define LCD_DC 43 -#define LCD_RST -1 -#define LCD_BCKL 48 - -#define LCD_WIDTH 240 -#define LCD_HEIGHT 240 -#define LCD_ROTATE 0 -#elif CONFIG_CAMERA_MODULE_ESP_S2_KALUGA -#define LCD_CONTROLLER SCREEN_CONTROLLER_ST7789 - -#define LCD_MOSI 9 -#define LCD_MISO -1 -#define LCD_SCLK 15 -#define LCD_CS 11 -#define LCD_DC 13 -#define LCD_RST 16 -#define LCD_BCKL 6 - -// LCD display width and height -#define LCD_WIDTH 240 -#define LCD_HEIGHT 320 -#define LCD_ROTATE SCR_SWAP_XY|SCR_MIRROR_X -#endif - - - - -#ifdef __cplusplus -extern "C" -{ -#endif - -esp_err_t app_camera_init(void); -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults deleted file mode 100644 index d53e9f466d..0000000000 --- a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y - -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y - -CONFIG_SPIRAM_SPEED_80M=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 deleted file mode 100644 index ecc2d87564..0000000000 --- a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32 +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32_SPIRAM_SUPPORT=y - -CONFIG_CAMERA_MODULE_ESP_EYE=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 deleted file mode 100644 index 93fe3e9675..0000000000 --- a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s2 +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y -CONFIG_ESP32S2_SPIRAM_SUPPORT=y - -CONFIG_ESP32S2_DATA_CACHE_16KB=y -ESP32S2_DATA_CACHE_LINE_32B=y - -CONFIG_CAMERA_MODULE_ESP_S2_KALUGA=y -CONFIG_LCD_DRIVER_SCREEN_CONTROLLER_ST7789=y \ No newline at end of file diff --git a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 b/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 deleted file mode 100644 index 64e26b9ed0..0000000000 --- a/quirc/examples/esp-eye-qrcode/sdkconfig.defaults.esp32s3 +++ /dev/null @@ -1,23 +0,0 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration -# -CONFIG_IDF_TARGET="esp32s3" -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -CONFIG_SPIRAM=y -CONFIG_SPIRAM_SPEED_80M=y -CONFIG_SPIRAM_MODE_OCT=y -CONFIG_ESP_DEFAULT_CPU_FREQ_240=y -CONFIG_SPIRAM=y -CONFIG_ESP32S3_SPIRAM_SUPPORT=y -CONFIG_SPIRAM_MODE_OCT=y -CONFIG_SPIRAM_SPEED_80M=y -CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 -CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y -CONFIG_LV_COLOR_16_SWAP=y -CONFIG_LV_MEM_CUSTOM=y -CONFIG_LV_MEMCPY_MEMSET_STD=y -CONFIG_LV_USE_PERF_MONITOR=y -CONFIG_LV_SPRINTF_CUSTOM=y -# CONFIG_LV_BUILD_EXAMPLES is not set \ No newline at end of file From 4f787d0b8a9ccafccb1571219dd608a31c36021f Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 16:34:35 +0200 Subject: [PATCH 10/14] cleaned code, updated readme --- quirc/examples/esp32-s3-eye-qrcode/README.md | 4 +++- .../esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c | 13 ++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/quirc/examples/esp32-s3-eye-qrcode/README.md b/quirc/examples/esp32-s3-eye-qrcode/README.md index 4065deefa4..436b2d9c38 100644 --- a/quirc/examples/esp32-s3-eye-qrcode/README.md +++ b/quirc/examples/esp32-s3-eye-qrcode/README.md @@ -5,6 +5,8 @@ In this example the esp-eye takes a picture every few ms, show them on the display and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). +Quirc requires a grayscale image, hence the picture is directly taken grayscale. Since the `lvgl` expects a color picture, the grayscale image is converted to RGB565 before giving it to the `lv_canvas_set_buffer`. + ## How to use example -Build and flash on an esp32-s3-eye. It may work with small changes also on ESP32-CAM and ESP32-S3-EYE. +Build and flash on an esp32-s3-eye. Start a monitor and watch for decoding messages. It may work with small changes also on ESP32-CAM and ESP-EYE. diff --git a/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c b/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c index ba4b7f54fc..4d91b61520 100644 --- a/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c +++ b/quirc/examples/esp32-s3-eye-qrcode/main/esp32-s3-eye-example.c @@ -30,10 +30,8 @@ void grayscale_to_rgb565(uint8_t *grayscale_buf, uint8_t *rgb565_buf, uint16_t l uint16_t k = 0; for (k = 0; k < length; k++) { reduced = (grayscale_buf[k] >> 3) & 0b00011111; - //rgb565_buf[rgb565_counter] = ((reduced << 6) | (reduced)); // G2 G1 G0(=0) B4 B3 B2 B1 B0 rgb565_buf[rgb565_counter] = ((reduced << 3) | (reduced >> 2)); rgb565_counter++; - //rgb565_buf[rgb565_counter] = ((reduced << 3) | (reduced>>2)); // R4 R3 R2 R1 R0 G4 G3 G2 rgb565_buf[rgb565_counter] = ((reduced << 6) | (reduced)); rgb565_counter++; } @@ -47,12 +45,13 @@ static void decode_task(void *args) // Initialize the camera camera_config_t camera_config = BSP_CAMERA_DEFAULT_CONFIG; - camera_config.pixel_format = PIXFORMAT_GRAYSCALE; + camera_config.pixel_format = PIXFORMAT_GRAYSCALE; // required by quirc esp_err_t err = esp_camera_init(&camera_config); if (err != ESP_OK) { ESP_LOGE(TAG, "Camera Init Failed"); - return; + exit(1); } + sensor_t *s = esp_camera_sensor_get(); s->set_vflip(s, 1); s->set_hmirror(s, 1); @@ -68,7 +67,7 @@ static void decode_task(void *args) bsp_display_unlock(); camera_fb_t *pic = esp_camera_fb_get(); - uint8_t *buf_shown = (uint8_t *)lv_mem_alloc(pic->len * 2); // double the size because the canvas requires a color RGB565 + uint8_t *buf_shown = (uint8_t *)lv_mem_alloc(pic->len * 2); // double the size because the canvas requires a RGB565, i.e. 2 bytes per pixel esp_camera_fb_return(pic); /* Initializing the quirc handle */ @@ -89,9 +88,8 @@ static void decode_task(void *args) while (1) { pic = esp_camera_fb_get(); - //printf("w: %d\th: %d\tbytes: %d\tformat: %d\n", pic->width, pic->height,pic->len, pic->format); - if (pic) { + if (pic) { bsp_display_lock(0); grayscale_to_rgb565(pic->buf, buf_shown, pic->len); lv_canvas_set_buffer(camera_canvas, buf_shown, pic->width, pic->height, LV_IMG_CF_TRUE_COLOR); @@ -116,6 +114,7 @@ static void decode_task(void *args) esp_camera_fb_return(pic); } else { ESP_LOGE(TAG, "Get frame failed"); + exit(1); } } From d9f2fb608e95437eaa334549bdeeb75540aa1ff2 Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 16:43:52 +0200 Subject: [PATCH 11/14] Updated readme --- quirc/examples/esp32-s3-eye-qrcode/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quirc/examples/esp32-s3-eye-qrcode/README.md b/quirc/examples/esp32-s3-eye-qrcode/README.md index 436b2d9c38..e1335d61b2 100644 --- a/quirc/examples/esp32-s3-eye-qrcode/README.md +++ b/quirc/examples/esp32-s3-eye-qrcode/README.md @@ -3,10 +3,10 @@ | | | | | | | | |X| # ESP32-S3-EYE QR-CODE with QUIRC -In this example the esp-eye takes a picture every few ms, show them on the display and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). +In this example the [ESP32-S3-EYE](https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP32-S3-EYE_Getting_Started_Guide.md) takes a picture every few ms, show them on the display and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). -Quirc requires a grayscale image, hence the picture is directly taken grayscale. Since the `lvgl` expects a color picture, the grayscale image is converted to RGB565 before giving it to the `lv_canvas_set_buffer`. +Quirc requires a grayscale image, hence the picture is directly taken grayscale. Since the `lvgl` expects a color picture, the grayscale image is converted to RGB565 before giving it to the `lv_canvas_set_buffer`. The conversion is done by setting all three RGB values to the grayscale value (reduced to 5 or 6 bit respectively). ## How to use example -Build and flash on an esp32-s3-eye. Start a monitor and watch for decoding messages. It may work with small changes also on ESP32-CAM and ESP-EYE. +Set ESP32-S3 target, build and flash on an esp32-s3-eye. Start a monitor and watch for decoding messages. It may work with small changes also on ESP32-CAM and ESP-EYE. From d0043a2af6e694dc2aa814c32fead8031664dcfc Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 16:55:54 +0200 Subject: [PATCH 12/14] removed sdconfig.defaults --- .../esp32-s3-eye-qrcode/sdkconfig.defaults | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults diff --git a/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults deleted file mode 100644 index d14403491a..0000000000 --- a/quirc/examples/esp32-s3-eye-qrcode/sdkconfig.defaults +++ /dev/null @@ -1,14 +0,0 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration -# -CONFIG_IDF_TARGET="esp32s2" -CONFIG_ESPTOOLPY_FLASHMODE_QIO=y -CONFIG_SPIRAM=y -CONFIG_SPIRAM_SPEED_80M=y -CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y -CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 -CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y -CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y -CONFIG_LV_MEM_CUSTOM=y -CONFIG_LV_MEMCPY_MEMSET_STD=y -# CONFIG_LV_BUILD_EXAMPLES is not set From 9b3ae061232144f85cec39c29e408a7074c0c55f Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 17:07:45 +0200 Subject: [PATCH 13/14] added config --- quirc/examples/esp32-s3-eye-qrcode/sdkconfig | 1852 ++++++++++++++++++ 1 file changed, 1852 insertions(+) create mode 100644 quirc/examples/esp32-s3-eye-qrcode/sdkconfig diff --git a/quirc/examples/esp32-s3-eye-qrcode/sdkconfig b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig new file mode 100644 index 0000000000..c96b17e056 --- /dev/null +++ b/quirc/examples/esp32-s3-eye-qrcode/sdkconfig @@ -0,0 +1,1852 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_CACHE_SUPPORT_WRAP=y +CONFIG_SOC_ULP_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_RISCV_COPROC_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_USB_OTG_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_SDMMC_HOST_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_PSRAM_DMA_CAPABLE=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_APPCPU_HAS_CLOCK_GATING_BUG=y +CONFIG_SOC_ADC_RTC_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=10 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=2 +CONFIG_SOC_ADC_PATT_LEN_MAX=24 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_CACHE_WRITEBACK_SUPPORTED=y +CONFIG_SOC_CACHE_FREEZE_SUPPORTED=y +CONFIG_SOC_CPU_CORES_NUM=2 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_SIZE=64 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_GDMA_GROUPS=y +CONFIG_SOC_GDMA_PAIRS_PER_GROUP=5 +CONFIG_SOC_GDMA_SUPPORT_PSRAM=y +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=49 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_RTC_INDEPENDENT=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_VALID_GPIO_MASK=0x1FFFFFFFFFFFF +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x0001FFFFFC000000 +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_OUT_AUTO_ENABLE=y +CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2S_NUM=2 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=4 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_CHANNEL_NUM=8 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MCPWM_GROUPS=2 +CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 +CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 +CONFIG_SOC_MCPWM_COMPARATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GENERATORS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_TRIGGERS_PER_OPERATOR=2 +CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 +CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y +CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 +CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MCPWM_SWSYNC_CAN_PROPAGATE=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_PCNT_GROUPS=1 +CONFIG_SOC_PCNT_UNITS_PER_GROUP=4 +CONFIG_SOC_PCNT_CHANNELS_PER_UNIT=2 +CONFIG_SOC_PCNT_THRES_POINT_PER_UNIT=2 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=4 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=8 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_DMA=y +CONFIG_SOC_LCD_I80_SUPPORTED=y +CONFIG_SOC_LCD_RGB_SUPPORTED=y +CONFIG_SOC_LCD_I80_BUSES=1 +CONFIG_SOC_LCD_RGB_PANELS=1 +CONFIG_SOC_LCD_I80_BUS_WIDTH=16 +CONFIG_SOC_LCD_RGB_DATA_WIDTH=16 +CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=549 +CONFIG_SOC_RTC_CNTL_TAGMEM_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTCIO_PIN_COUNT=22 +CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y +CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y +CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_SDM_GROUPS=y +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=3 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_SUPPORT_OCT=y +CONFIG_SOC_MEMSPI_SRC_FREQ_120M=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SPIRAM_SUPPORTED=y +CONFIG_SOC_SPIRAM_XIP_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 +CONFIG_SOC_TOUCH_VERSION_2=y +CONFIG_SOC_TOUCH_SENSOR_NUM=15 +CONFIG_SOC_TOUCH_PROXIMITY_CHANNEL_NUM=3 +CONFIG_SOC_TOUCH_PROXIMITY_MEAS_DONE_SUPPORTED=y +CONFIG_SOC_TOUCH_PAD_THRESHOLD_MAX=0x1FFFFF +CONFIG_SOC_TOUCH_PAD_MEASURE_WAIT_MAX=0xFF +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_REQUIRE_CORE_RESET=y +CONFIG_SOC_USB_PERIPH_NUM=y +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SHA_SUPPORT_SHA384=y +CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_SHA_SUPPORT_SHA512_224=y +CONFIG_SOC_SHA_SUPPORT_SHA512_256=y +CONFIG_SOC_SHA_SUPPORT_SHA512_T=y +CONFIG_SOC_RSA_MAX_BIT_LEN=4096 +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_TAGMEM_PD=y +CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_DCACHE=y +CONFIG_SOC_EFUSE_HARD_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=64 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_256=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=256 +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_OPI_MODE=y +CONFIG_SOC_SPI_MEM_SUPPORT_TIME_TUNING=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_SDMMC_USE_GPIO_MATRIX=y +CONFIG_SOC_SDMMC_NUM_SLOTS=2 +CONFIG_SOC_SDMMC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TARGET_ARCH_XTENSA=y +CONFIG_IDF_TARGET_ARCH="xtensa" +CONFIG_IDF_TARGET="esp32s3" +CONFIG_IDF_TARGET_ESP32S3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0009 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +# CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=4 +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_HAS_HAL_WDT=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_OCT_FLASH is not set +CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=y +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ_80M_DEFAULT=y +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +# end of Compiler options + +# +# Component config +# + +# +# Driver Configurations +# + +# +# Legacy ADC Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Configuration + +# +# SPI Configuration +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of SPI Configuration + +# +# TWAI Configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of TWAI Configuration + +# +# Temperature sensor Configuration +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of Temperature sensor Configuration + +# +# UART Configuration +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of UART Configuration + +# +# GPIO Configuration +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of GPIO Configuration + +# +# Sigma Delta Modulator Configuration +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of Sigma Delta Modulator Configuration + +# +# GPTimer Configuration +# +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of GPTimer Configuration + +# +# PCNT Configuration +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of PCNT Configuration + +# +# RMT Configuration +# +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of RMT Configuration + +# +# MCPWM Configuration +# +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of MCPWM Configuration + +# +# I2S Configuration +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of I2S Configuration + +# +# USB Serial/JTAG Configuration +# +# end of USB Serial/JTAG Configuration +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# end of ADC and ADC Calibration + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# end of Common ESP-related + +# +# Hardware Settings +# + +# +# Chip revision +# +CONFIG_ESP32S3_REV_MIN_0=y +# CONFIG_ESP32S3_REV_MIN_1 is not set +# CONFIG_ESP32S3_REV_MIN_2 is not set +CONFIG_ESP32S3_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 + +# +# Maximum Supported ESP32-S3 Revision (Rev v0.99) +# +CONFIG_ESP32S3_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +# CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES=4 +# end of MAC Config + +# +# Sleep Config +# +CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU=y +CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configuration +# +# CONFIG_GDMA_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# end of GDMA Configuration + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config +# end of Hardware Settings + +# +# LCD and Touch Panel +# + +# +# LCD Touch Drivers are maintained in the IDF Component Registry +# + +# +# LCD Peripheral Configuration +# +CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# CONFIG_LCD_RGB_ISR_IRAM_SAFE is not set +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set +# end of LCD Peripheral Configuration +# end of LCD and Touch Panel + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# +CONFIG_SPIRAM=y + +# +# SPI RAM config +# +# CONFIG_SPIRAM_MODE_QUAD is not set +CONFIG_SPIRAM_MODE_OCT=y +CONFIG_SPIRAM_TYPE_AUTO=y +# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set +CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y +CONFIG_SPIRAM_CLK_IO=30 +CONFIG_SPIRAM_CS_IO=26 +# CONFIG_SPIRAM_FETCH_INSTRUCTIONS is not set +# CONFIG_SPIRAM_RODATA is not set +CONFIG_SPIRAM_SPEED_80M=y +# CONFIG_SPIRAM_SPEED_40M is not set +CONFIG_SPIRAM_SPEED=80 +CONFIG_SPIRAM_BOOT_INIT=y +# CONFIG_SPIRAM_USE_MEMMAP is not set +# CONFIG_SPIRAM_USE_CAPS_ALLOC is not set +CONFIG_SPIRAM_USE_MALLOC=y +CONFIG_SPIRAM_MEMTEST=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 +CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y +CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=8192 +CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y +# CONFIG_SPIRAM_ECC_ENABLE is not set +# end of SPI RAM config +# end of ESP PSRAM + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240 + +# +# Cache config +# +CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB=y +# CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE=0x4000 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_8WAYS=y +CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B is not set +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y +CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE=32 +# CONFIG_ESP32S3_DATA_CACHE_16KB is not set +CONFIG_ESP32S3_DATA_CACHE_32KB=y +# CONFIG_ESP32S3_DATA_CACHE_64KB is not set +CONFIG_ESP32S3_DATA_CACHE_SIZE=0x8000 +# CONFIG_ESP32S3_DATA_CACHE_4WAYS is not set +CONFIG_ESP32S3_DATA_CACHE_8WAYS=y +CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS=8 +# CONFIG_ESP32S3_DATA_CACHE_LINE_16B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_32B=y +# CONFIG_ESP32S3_DATA_CACHE_LINE_64B is not set +CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE=32 +# end of Cache config + +# +# Memory +# +# CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM is not set +# CONFIG_ESP32S3_USE_FIXED_STATIC_RAM_SIZE is not set +# end of Memory + +# +# Trace memory +# +# CONFIG_ESP32S3_TRAX is not set +CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM=0x0 +# end of Trace memory + +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_CDC is not set +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_MULTIPLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +# end of Brownout Detector + +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1280 +CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y +CONFIG_ESP_IPC_ISR_ENABLE=y +# end of IPC (Inter-Processor Call) + +# +# High resolution timer (esp_timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY=0x1 +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of High resolution timer (esp_timer) + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +# CONFIG_FREERTOS_UNICORE is not set +CONFIG_FREERTOS_HZ=100 +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +# end of Port + +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_WDT_USE_ROM_IMPL=y +CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y +CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log output +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 +CONFIG_LOG_COLORS=y +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Log output + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 is not set +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +# CONFIG_MBEDTLS_CMAC_C is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +# CONFIG_MBEDTLS_SECURITY_RISKS is not set +# end of mbedTLS + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# end of NVS + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y +# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set +# CONFIG_PTHREAD_DEFAULT_CORE_1 is not set +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_VFS_SUPPORT_TERMIOS=y + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# IoT Button +# +CONFIG_BUTTON_PERIOD_TIME_MS=5 +CONFIG_BUTTON_DEBOUNCE_TICKS=2 +CONFIG_BUTTON_SHORT_PRESS_TIME_MS=180 +CONFIG_BUTTON_LONG_PRESS_TIME_MS=1500 +CONFIG_BUTTON_SERIAL_TIME_MS=20 +CONFIG_ADC_BUTTON_MAX_CHANNEL=3 +CONFIG_ADC_BUTTON_MAX_BUTTON_PER_CHANNEL=8 +CONFIG_ADC_BUTTON_SAMPLE_TIMES=1 +# end of IoT Button + +# +# CMake Utilities +# +# CONFIG_CU_RELINKER_ENABLE is not set +# CONFIG_CU_DIAGNOSTICS_COLOR_NEVER is not set +CONFIG_CU_DIAGNOSTICS_COLOR_ALWAYS=y +# CONFIG_CU_DIAGNOSTICS_COLOR_AUTO is not set +# CONFIG_CU_GCC_LTO_ENABLE is not set +# CONFIG_CU_GCC_STRING_1BYTE_ALIGN is not set +# end of CMake Utilities + +# +# Camera configuration +# +CONFIG_OV7670_SUPPORT=y +CONFIG_OV7725_SUPPORT=y +CONFIG_NT99141_SUPPORT=y +CONFIG_OV2640_SUPPORT=y +CONFIG_OV3660_SUPPORT=y +CONFIG_OV5640_SUPPORT=y +CONFIG_GC2145_SUPPORT=y +CONFIG_GC032A_SUPPORT=y +CONFIG_GC0308_SUPPORT=y +CONFIG_BF3005_SUPPORT=y +CONFIG_BF20A6_SUPPORT=y +# CONFIG_SC101IOT_SUPPORT is not set +CONFIG_SC030IOT_SUPPORT=y +# CONFIG_SC031GS_SUPPORT is not set +# CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set +CONFIG_SCCB_HARDWARE_I2C_PORT1=y +CONFIG_SCCB_CLK_FREQ=100000 +# CONFIG_GC_SENSOR_WINDOWING_MODE is not set +CONFIG_GC_SENSOR_SUBSAMPLE_MODE=y +CONFIG_CAMERA_TASK_STACK_SIZE=2048 +CONFIG_CAMERA_CORE0=y +# CONFIG_CAMERA_CORE1 is not set +# CONFIG_CAMERA_NO_AFFINITY is not set +CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 +# CONFIG_CAMERA_CONVERTER_ENABLED is not set +# end of Camera configuration + +# +# Board Support Package +# +CONFIG_BSP_ERROR_CHECK=y + +# +# I2C +# +CONFIG_BSP_I2C_NUM=1 +CONFIG_BSP_I2C_FAST_MODE=y +CONFIG_BSP_I2C_CLK_SPEED_HZ=400000 +# end of I2C + +# +# SPIFFS - Virtual File System +# +# CONFIG_BSP_SPIFFS_FORMAT_ON_MOUNT_FAIL is not set +CONFIG_BSP_SPIFFS_MOUNT_POINT="/spiffs" +CONFIG_BSP_SPIFFS_PARTITION_LABEL="storage" +CONFIG_BSP_SPIFFS_MAX_FILES=2 +# end of SPIFFS - Virtual File System + +# +# uSD card - Virtual File System +# +# CONFIG_BSP_SD_FORMAT_ON_MOUNT_FAIL is not set +CONFIG_BSP_SD_MOUNT_POINT="/sdcard" +# end of uSD card - Virtual File System + +# +# Display +# +CONFIG_BSP_DISPLAY_LVGL_TASK_PRIORITY=2 +CONFIG_BSP_DISPLAY_LVGL_TICK=5 +CONFIG_BSP_DISPLAY_LVGL_MAX_SLEEP=1 +CONFIG_BSP_DISPLAY_BRIGHTNESS_LEDC_CH=1 +# end of Display + +CONFIG_BSP_I2S_NUM=1 +# end of Board Support Package + +# +# Audio Codec Device Configuration +# +CONFIG_CODEC_ES8311_SUPPORT=y +CONFIG_CODEC_ES7210_SUPPORT=y +CONFIG_CODEC_ES7243_SUPPORT=y +CONFIG_CODEC_ES7243E_SUPPORT=y +CONFIG_CODEC_ES8156_SUPPORT=y +CONFIG_CODEC_ES8374_SUPPORT=y +CONFIG_CODEC_ES8388_SUPPORT=y +CONFIG_CODEC_TAS5805M_SUPPORT=y +# CONFIG_CODEC_ZL38063_SUPPORT is not set +# end of Audio Codec Device Configuration + +# +# LVGL configuration +# +CONFIG_LV_CONF_SKIP=y +# CONFIG_LV_CONF_MINIMAL is not set + +# +# Color settings +# +# CONFIG_LV_COLOR_DEPTH_32 is not set +CONFIG_LV_COLOR_DEPTH_16=y +# CONFIG_LV_COLOR_DEPTH_8 is not set +# CONFIG_LV_COLOR_DEPTH_1 is not set +CONFIG_LV_COLOR_DEPTH=16 +# CONFIG_LV_COLOR_16_SWAP is not set +# CONFIG_LV_COLOR_SCREEN_TRANSP is not set +CONFIG_LV_COLOR_MIX_ROUND_OFS=128 +CONFIG_LV_COLOR_CHROMA_KEY_HEX=0x00FF00 +# end of Color settings + +# +# Memory settings +# +CONFIG_LV_MEM_CUSTOM=y +CONFIG_LV_MEM_CUSTOM_INCLUDE="stdlib.h" +CONFIG_LV_MEM_BUF_MAX_NUM=16 +CONFIG_LV_MEMCPY_MEMSET_STD=y +# end of Memory settings + +# +# HAL Settings +# +CONFIG_LV_DISP_DEF_REFR_PERIOD=30 +CONFIG_LV_INDEV_DEF_READ_PERIOD=30 +# CONFIG_LV_TICK_CUSTOM is not set +CONFIG_LV_DPI_DEF=130 +# end of HAL Settings + +# +# Feature configuration +# + +# +# Drawing +# +CONFIG_LV_DRAW_COMPLEX=y +CONFIG_LV_SHADOW_CACHE_SIZE=0 +CONFIG_LV_CIRCLE_CACHE_SIZE=4 +CONFIG_LV_LAYER_SIMPLE_BUF_SIZE=24576 +CONFIG_LV_IMG_CACHE_DEF_SIZE=0 +CONFIG_LV_GRADIENT_MAX_STOPS=2 +CONFIG_LV_GRAD_CACHE_DEF_SIZE=0 +# CONFIG_LV_DITHER_GRADIENT is not set +CONFIG_LV_DISP_ROT_MAX_BUF=10240 +# end of Drawing + +# +# GPU +# +# CONFIG_LV_USE_GPU_ARM2D is not set +# CONFIG_LV_USE_GPU_STM32_DMA2D is not set +# CONFIG_LV_USE_GPU_RA6M3_G2D is not set +# CONFIG_LV_USE_GPU_SWM341_DMA2D is not set +# CONFIG_LV_USE_GPU_NXP_PXP is not set +# CONFIG_LV_USE_GPU_NXP_VG_LITE is not set +# CONFIG_LV_USE_GPU_SDL is not set +# end of GPU + +# +# Logging +# +# CONFIG_LV_USE_LOG is not set +# end of Logging + +# +# Asserts +# +CONFIG_LV_USE_ASSERT_NULL=y +CONFIG_LV_USE_ASSERT_MALLOC=y +# CONFIG_LV_USE_ASSERT_STYLE is not set +# CONFIG_LV_USE_ASSERT_MEM_INTEGRITY is not set +# CONFIG_LV_USE_ASSERT_OBJ is not set +CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h" +# end of Asserts + +# +# Others +# +# CONFIG_LV_USE_PERF_MONITOR is not set +# CONFIG_LV_USE_REFR_DEBUG is not set +# CONFIG_LV_SPRINTF_CUSTOM is not set +# CONFIG_LV_SPRINTF_USE_FLOAT is not set +CONFIG_LV_USE_USER_DATA=y +# CONFIG_LV_ENABLE_GC is not set +# end of Others + +# +# Compiler settings +# +# CONFIG_LV_BIG_ENDIAN_SYSTEM is not set +CONFIG_LV_ATTRIBUTE_MEM_ALIGN_SIZE=1 +# CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM is not set +# CONFIG_LV_USE_LARGE_COORD is not set +# end of Compiler settings +# end of Feature configuration + +# +# Font usage +# + +# +# Enable built-in fonts +# +# CONFIG_LV_FONT_MONTSERRAT_8 is not set +# CONFIG_LV_FONT_MONTSERRAT_10 is not set +# CONFIG_LV_FONT_MONTSERRAT_12 is not set +CONFIG_LV_FONT_MONTSERRAT_14=y +# CONFIG_LV_FONT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_MONTSERRAT_30 is not set +# CONFIG_LV_FONT_MONTSERRAT_32 is not set +# CONFIG_LV_FONT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_MONTSERRAT_46 is not set +# CONFIG_LV_FONT_MONTSERRAT_48 is not set +# CONFIG_LV_FONT_MONTSERRAT_12_SUBPX is not set +# CONFIG_LV_FONT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_SIMSUN_16_CJK is not set +# CONFIG_LV_FONT_UNSCII_8 is not set +# CONFIG_LV_FONT_UNSCII_16 is not set +# CONFIG_LV_FONT_CUSTOM is not set +# end of Enable built-in fonts + +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_8 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12 is not set +CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14=y +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_16 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_18 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_20 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_22 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_24 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_26 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_30 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_32 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_34 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_36 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_38 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_40 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_42 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_44 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_46 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_48 is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_12_SUBPX is not set +# CONFIG_LV_FONT_DEFAULT_MONTSERRAT_28_COMPRESSED is not set +# CONFIG_LV_FONT_DEFAULT_DEJAVU_16_PERSIAN_HEBREW is not set +# CONFIG_LV_FONT_DEFAULT_SIMSUN_16_CJK is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_8 is not set +# CONFIG_LV_FONT_DEFAULT_UNSCII_16 is not set +# CONFIG_LV_FONT_FMT_TXT_LARGE is not set +# CONFIG_LV_USE_FONT_COMPRESSED is not set +# CONFIG_LV_USE_FONT_SUBPX is not set +CONFIG_LV_USE_FONT_PLACEHOLDER=y +# end of Font usage + +# +# Text Settings +# +CONFIG_LV_TXT_ENC_UTF8=y +# CONFIG_LV_TXT_ENC_ASCII is not set +CONFIG_LV_TXT_BREAK_CHARS=" ,.;:-_" +CONFIG_LV_TXT_LINE_BREAK_LONG_LEN=0 +CONFIG_LV_TXT_COLOR_CMD="#" +# CONFIG_LV_USE_BIDI is not set +# CONFIG_LV_USE_ARABIC_PERSIAN_CHARS is not set +# end of Text Settings + +# +# Widget usage +# +CONFIG_LV_USE_ARC=y +CONFIG_LV_USE_BAR=y +CONFIG_LV_USE_BTN=y +CONFIG_LV_USE_BTNMATRIX=y +CONFIG_LV_USE_CANVAS=y +CONFIG_LV_USE_CHECKBOX=y +CONFIG_LV_USE_DROPDOWN=y +CONFIG_LV_USE_IMG=y +CONFIG_LV_USE_LABEL=y +CONFIG_LV_LABEL_TEXT_SELECTION=y +CONFIG_LV_LABEL_LONG_TXT_HINT=y +CONFIG_LV_USE_LINE=y +CONFIG_LV_USE_ROLLER=y +CONFIG_LV_ROLLER_INF_PAGES=7 +CONFIG_LV_USE_SLIDER=y +CONFIG_LV_USE_SWITCH=y +CONFIG_LV_USE_TEXTAREA=y +CONFIG_LV_TEXTAREA_DEF_PWD_SHOW_TIME=1500 +CONFIG_LV_USE_TABLE=y +# end of Widget usage + +# +# Extra Widgets +# +CONFIG_LV_USE_ANIMIMG=y +CONFIG_LV_USE_CALENDAR=y +# CONFIG_LV_CALENDAR_WEEK_STARTS_MONDAY is not set +CONFIG_LV_USE_CALENDAR_HEADER_ARROW=y +CONFIG_LV_USE_CALENDAR_HEADER_DROPDOWN=y +CONFIG_LV_USE_CHART=y +CONFIG_LV_USE_COLORWHEEL=y +CONFIG_LV_USE_IMGBTN=y +CONFIG_LV_USE_KEYBOARD=y +CONFIG_LV_USE_LED=y +CONFIG_LV_USE_LIST=y +CONFIG_LV_USE_MENU=y +CONFIG_LV_USE_METER=y +CONFIG_LV_USE_MSGBOX=y +CONFIG_LV_USE_SPAN=y +CONFIG_LV_SPAN_SNIPPET_STACK_SIZE=64 +CONFIG_LV_USE_SPINBOX=y +CONFIG_LV_USE_SPINNER=y +CONFIG_LV_USE_TABVIEW=y +CONFIG_LV_USE_TILEVIEW=y +CONFIG_LV_USE_WIN=y +# end of Extra Widgets + +# +# Themes +# +CONFIG_LV_USE_THEME_DEFAULT=y +# CONFIG_LV_THEME_DEFAULT_DARK is not set +CONFIG_LV_THEME_DEFAULT_GROW=y +CONFIG_LV_THEME_DEFAULT_TRANSITION_TIME=80 +CONFIG_LV_USE_THEME_BASIC=y +# CONFIG_LV_USE_THEME_MONO is not set +# end of Themes + +# +# Layouts +# +CONFIG_LV_USE_FLEX=y +CONFIG_LV_USE_GRID=y +# end of Layouts + +# +# 3rd Party Libraries +# +# CONFIG_LV_USE_FS_STDIO is not set +# CONFIG_LV_USE_FS_POSIX is not set +# CONFIG_LV_USE_FS_WIN32 is not set +# CONFIG_LV_USE_FS_FATFS is not set +# CONFIG_LV_USE_PNG is not set +# CONFIG_LV_USE_BMP is not set +# CONFIG_LV_USE_SJPG is not set +# CONFIG_LV_USE_GIF is not set +# CONFIG_LV_USE_QRCODE is not set +# CONFIG_LV_USE_FREETYPE is not set +# CONFIG_LV_USE_RLOTTIE is not set +# CONFIG_LV_USE_FFMPEG is not set +# end of 3rd Party Libraries + +# +# Others +# +CONFIG_LV_USE_SNAPSHOT=y +# CONFIG_LV_USE_MONKEY is not set +# CONFIG_LV_USE_GRIDNAV is not set +# CONFIG_LV_USE_FRAGMENT is not set +# CONFIG_LV_USE_IMGFONT is not set +# CONFIG_LV_USE_MSG is not set +# CONFIG_LV_USE_IME_PINYIN is not set +# end of Others + +# +# Examples +# +# CONFIG_LV_BUILD_EXAMPLES is not set +# end of Examples + +# +# Demos +# +# CONFIG_LV_USE_DEMO_WIDGETS is not set +# CONFIG_LV_USE_DEMO_KEYPAD_AND_ENCODER is not set +# CONFIG_LV_USE_DEMO_BENCHMARK is not set +# CONFIG_LV_USE_DEMO_STRESS is not set +# CONFIG_LV_USE_DEMO_MUSIC is not set +# end of Demos +# end of LVGL configuration +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +CONFIG_FLASHMODE_QIO=y +# CONFIG_FLASHMODE_QOUT is not set +# CONFIG_FLASHMODE_DIO is not set +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_MCPWM_ISR_IN_IRAM is not set +CONFIG_ESP32S3_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32S3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32S3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +CONFIG_ESP32S3_SPIRAM_SUPPORT=y +CONFIG_DEFAULT_PSRAM_CLK_IO=30 +CONFIG_DEFAULT_PSRAM_CS_IO=26 +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set +# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_160 is not set +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32S3_DEBUG_OCDAWARE=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_ESP32S3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_ESP32S3_BROWNOUT_DET_LVL_SEL_1 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32S3_BROWNOUT_DET_LVL=7 +CONFIG_IPC_TASK_STACK_SIZE=1280 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1=y +# CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_FRC1 is not set +# CONFIG_ESP32S3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options From 0cbc4af4ba8f7d482b8a54dd367dde39661af7eb Mon Sep 17 00:00:00 2001 From: fbez Date: Wed, 18 Oct 2023 17:16:24 +0200 Subject: [PATCH 14/14] updated readme --- quirc/examples/esp32-s3-eye-qrcode/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quirc/examples/esp32-s3-eye-qrcode/README.md b/quirc/examples/esp32-s3-eye-qrcode/README.md index e1335d61b2..b871e62bdf 100644 --- a/quirc/examples/esp32-s3-eye-qrcode/README.md +++ b/quirc/examples/esp32-s3-eye-qrcode/README.md @@ -1,6 +1,6 @@ | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | ------ | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -| | | | | | | | |X| +| | | | | | | | X| # ESP32-S3-EYE QR-CODE with QUIRC In this example the [ESP32-S3-EYE](https://github.com/espressif/esp-who/blob/master/docs/en/get-started/ESP32-S3-EYE_Getting_Started_Guide.md) takes a picture every few ms, show them on the display and check if the image contains valid qr-codes. If detected, it shows a message on the terminal (e.g. `Data: This is an esp-eye test`). It may not decode correctly the qr-code and in this case an error message is shown (`DECODE FAILED: ECC failure`). @@ -9,4 +9,4 @@ Quirc requires a grayscale image, hence the picture is directly taken grayscale. ## How to use example -Set ESP32-S3 target, build and flash on an esp32-s3-eye. Start a monitor and watch for decoding messages. It may work with small changes also on ESP32-CAM and ESP-EYE. +Build and flash on an esp32-s3-eye. Start a monitor and watch for decoding messages. It may work with small changes also on ESP32-CAM and ESP-EYE.