Bläddra i källkod

Merge pull request #65 from jomjol/rolling

Update to v4.1.0
jomjol 5 år sedan
förälder
incheckning
2753552997
100 ändrade filer med 4008 tillägg och 176 borttagningar
  1. 0 1
      .gitignore
  2. 14 3
      README.md
  3. BIN
      code/.DS_Store
  4. 0 1
      code/.gitignore
  5. 1 1
      code/CMakeLists.txt
  6. 7 0
      code/components/connect_wlan/CMakeLists.txt
  7. 0 0
      code/components/connect_wlan/connect_wlan.cpp
  8. 0 0
      code/components/connect_wlan/connect_wlan.h
  9. 1 0
      code/components/esp32-camera-master/.gitignore
  10. 35 0
      code/components/esp32-camera-master/CMakeLists.txt
  11. 71 0
      code/components/esp32-camera-master/Kconfig
  12. 0 0
      code/components/esp32-camera-master/LICENSE
  13. 358 0
      code/components/esp32-camera-master/README.md
  14. 4 0
      code/components/esp32-camera-master/component.mk
  15. 0 0
      code/components/esp32-camera-master/conversions/esp_jpg_decode.c
  16. 0 0
      code/components/esp32-camera-master/conversions/include/esp_jpg_decode.h
  17. 0 0
      code/components/esp32-camera-master/conversions/include/img_converters.h
  18. 0 0
      code/components/esp32-camera-master/conversions/jpge.cpp
  19. 0 0
      code/components/esp32-camera-master/conversions/private_include/jpge.h
  20. 0 0
      code/components/esp32-camera-master/conversions/private_include/yuv.h
  21. 11 0
      code/components/esp32-camera-master/conversions/to_bmp.c
  22. 2 3
      code/components/esp32-camera-master/conversions/to_jpg.cpp
  23. 0 0
      code/components/esp32-camera-master/conversions/yuv.c
  24. 109 37
      code/components/esp32-camera-master/driver/camera.c
  25. 0 5
      code/components/esp32-camera-master/driver/include/esp_camera.h
  26. 2 0
      code/components/esp32-camera-master/driver/include/sensor.h
  27. 0 0
      code/components/esp32-camera-master/driver/private_include/camera_common.h
  28. 0 0
      code/components/esp32-camera-master/driver/private_include/sccb.h
  29. 0 0
      code/components/esp32-camera-master/driver/private_include/xclk.h
  30. 0 95
      code/components/esp32-camera-master/driver/sccb.c
  31. 0 0
      code/components/esp32-camera-master/driver/sensor.c
  32. 0 3
      code/components/esp32-camera-master/driver/xclk.c
  33. 150 0
      code/components/esp32-camera-master/examples/take_picture.c
  34. 5 0
      code/components/esp32-camera-master/idf_component.yml
  35. 25 0
      code/components/esp32-camera-master/library.json
  36. 1032 0
      code/components/esp32-camera-master/sensors/nt99141.c
  37. 0 0
      code/components/esp32-camera-master/sensors/ov2640.c
  38. 0 0
      code/components/esp32-camera-master/sensors/ov3660.c
  39. 0 0
      code/components/esp32-camera-master/sensors/ov5640.c
  40. 439 0
      code/components/esp32-camera-master/sensors/ov7670.c
  41. 0 0
      code/components/esp32-camera-master/sensors/ov7725.c
  42. 16 0
      code/components/esp32-camera-master/sensors/private_include/nt99141.h
  43. 211 0
      code/components/esp32-camera-master/sensors/private_include/nt99141_regs.h
  44. 825 0
      code/components/esp32-camera-master/sensors/private_include/nt99141_settings.h
  45. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov2640.h
  46. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov2640_regs.h
  47. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov2640_settings.h
  48. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov3660.h
  49. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov3660_regs.h
  50. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov3660_settings.h
  51. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov5640.h
  52. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov5640_regs.h
  53. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h
  54. 14 0
      code/components/esp32-camera-master/sensors/private_include/ov7670.h
  55. 354 0
      code/components/esp32-camera-master/sensors/private_include/ov7670_regs.h
  56. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov7725.h
  57. 0 0
      code/components/esp32-camera-master/sensors/private_include/ov7725_regs.h
  58. 9 0
      code/components/jomjol_controlcamera/CMakeLists.txt
  59. 126 5
      code/components/jomjol_controlcamera/ClassControllCamera.cpp
  60. 1 1
      code/components/jomjol_controlcamera/ClassControllCamera.h
  61. 0 0
      code/components/jomjol_controlcamera/img_converters.h
  62. 0 0
      code/components/jomjol_controlcamera/sensor.h
  63. 0 0
      code/components/jomjol_controlcamera/server_camera.cpp
  64. 0 0
      code/components/jomjol_controlcamera/server_camera.h
  65. 7 0
      code/components/jomjol_fileserver_ota/CMakeLists.txt
  66. 0 0
      code/components/jomjol_fileserver_ota/miniz.c
  67. 0 0
      code/components/jomjol_fileserver_ota/miniz.h
  68. 76 1
      code/components/jomjol_fileserver_ota/server_file.cpp
  69. 0 0
      code/components/jomjol_fileserver_ota/server_file.h
  70. 0 0
      code/components/jomjol_fileserver_ota/server_help.cpp
  71. 0 0
      code/components/jomjol_fileserver_ota/server_help.h
  72. 3 3
      code/components/jomjol_fileserver_ota/server_ota.cpp
  73. 0 0
      code/components/jomjol_fileserver_ota/server_ota.h
  74. 7 0
      code/components/jomjol_flowcontroll/CMakeLists.txt
  75. 4 2
      code/components/jomjol_flowcontroll/ClassFlow.cpp
  76. 2 1
      code/components/jomjol_flowcontroll/ClassFlow.h
  77. 0 0
      code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
  78. 0 0
      code/components/jomjol_flowcontroll/ClassFlowAlignment.h
  79. 0 0
      code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp
  80. 0 0
      code/components/jomjol_flowcontroll/ClassFlowAnalog.h
  81. 20 2
      code/components/jomjol_flowcontroll/ClassFlowControll.cpp
  82. 1 0
      code/components/jomjol_flowcontroll/ClassFlowControll.h
  83. 0 0
      code/components/jomjol_flowcontroll/ClassFlowDigit.cpp
  84. 0 0
      code/components/jomjol_flowcontroll/ClassFlowDigit.h
  85. 0 0
      code/components/jomjol_flowcontroll/ClassFlowImage.cpp
  86. 0 0
      code/components/jomjol_flowcontroll/ClassFlowImage.h
  87. 13 1
      code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
  88. 1 1
      code/components/jomjol_flowcontroll/ClassFlowMQTT.h
  89. 0 0
      code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp
  90. 0 0
      code/components/jomjol_flowcontroll/ClassFlowMakeImage.h
  91. 36 10
      code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
  92. 2 0
      code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h
  93. 0 0
      code/components/jomjol_flowcontroll/camera_define.h
  94. 7 0
      code/components/jomjol_helper/CMakeLists.txt
  95. 0 0
      code/components/jomjol_helper/Helper.cpp
  96. 0 0
      code/components/jomjol_helper/Helper.h
  97. 0 0
      code/components/jomjol_image_proc/CFindTemplate.cpp
  98. 0 0
      code/components/jomjol_image_proc/CFindTemplate.h
  99. 7 0
      code/components/jomjol_image_proc/CMakeLists.txt
  100. 0 0
      code/components/jomjol_image_proc/bitmap_image.hpp

+ 0 - 1
.gitignore

@@ -9,7 +9,6 @@ CMakeLists.txt.user
 CMakeCache.txt
 CMakeFiles
 CMakeScripts
-Testing
 Makefile
 cmake_install.cmake
 install_manifest.txt

+ 14 - 3
README.md

@@ -9,7 +9,7 @@ A 3d-printable housing can be found here: https://www.thingiverse.com/thing:4571
 <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter_all.jpg" width="200"><img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/main.jpg" width="200"><img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/size.png" width="200"> 
 
 <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter.jpg" width="600"> 
-<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/edit_reference.jpg" width="600"> 
+
 
 
 
@@ -27,12 +27,23 @@ A 3d-printable housing can be found here: https://www.thingiverse.com/thing:4571
 
 
 
-##### Rolling - (2020-11-15)
+##### 4.1.0 Configuration editor- (2020-11-30)
+
+* Implementation of configuration editor (including basic and expert mode)
+
+* Adjustable time zone to adjust to local time setting (incl. daylight saving time)
+
+* MQTT: additional topic for error reporting
 
-* based on v4.0.0 (2020-11-15)
+* standardized access to current logfile via `http://IP-ADRESS/logfileact`
+
+* Update digital CNN to v7.2.0, analog CNN to 6.3.0
+
+* Bug fixing: truncation error,  CheckDigitConsistency & PreValue implementation
 
   
 
+
 ##### 4.0.0 Tflite Core - (2020-11-15)
 * Implementation of rolling log-files
 

BIN
code/.DS_Store


+ 0 - 1
code/.gitignore

@@ -3,4 +3,3 @@
 .vscode/c_cpp_properties.json
 .vscode/launch.json
 .vscode/ipch
-.helper

+ 1 - 1
code/CMakeLists.txt

@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.16.0)
+cmake_minimum_required(VERSION 3.13.4)
 
 list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 

+ 7 - 0
code/components/connect_wlan/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES jomjol_helper)
+
+

+ 0 - 0
code/lib/connect_wlan/connect_wlan.cpp → code/components/connect_wlan/connect_wlan.cpp


+ 0 - 0
code/lib/connect_wlan/connect_wlan.h → code/components/connect_wlan/connect_wlan.h


+ 1 - 0
code/components/esp32-camera-master/.gitignore

@@ -0,0 +1 @@
+*.DS_Store

+ 35 - 0
code/components/esp32-camera-master/CMakeLists.txt

@@ -0,0 +1,35 @@
+if(IDF_TARGET STREQUAL "esp32")
+  set(COMPONENT_SRCS
+    driver/camera.c
+    driver/sccb.c
+    driver/sensor.c
+    driver/xclk.c
+    sensors/ov2640.c
+    sensors/ov3660.c
+    sensors/ov5640.c
+    sensors/ov7725.c
+    sensors/ov7670.c
+    sensors/nt99141.c
+    conversions/yuv.c
+    conversions/to_jpg.cpp
+    conversions/to_bmp.c
+    conversions/jpge.cpp
+    conversions/esp_jpg_decode.c
+    )
+
+  set(COMPONENT_ADD_INCLUDEDIRS
+    driver/include
+    conversions/include
+    )
+
+  set(COMPONENT_PRIV_INCLUDEDIRS
+    driver/private_include
+    sensors/private_include
+    conversions/private_include
+    )
+
+  set(COMPONENT_REQUIRES driver)
+  set(COMPONENT_PRIV_REQUIRES freertos nvs_flash)
+
+  register_component()
+endif()

+ 71 - 0
code/components/esp32-camera-master/Kconfig

@@ -0,0 +1,71 @@
+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 safe memory.
+
+    config OV7725_SUPPORT
+        bool "Support OV7725 SVGA"
+        default n
+        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.
+
+    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
+
+    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
+
+endmenu

+ 0 - 0
code/lib/tfmicro/LICENSE → code/components/esp32-camera-master/LICENSE


+ 358 - 0
code/components/esp32-camera-master/README.md

@@ -0,0 +1,358 @@
+# ESP32 Camera Driver
+
+## General Information
+
+This repository hosts ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors. Additionally it provides a few tools, which allow converting the captured frame data to the more common BMP and JPEG formats.
+
+## 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`
+- 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'?!  </rant> 
+
+## 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! 
+
+### Kconfig options
+
+| config                            | description                                                                                                                                                  | default                        |
+| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
+| CONFIG_OV2640_SUPPORT             | Support for OV2640 camera                                                                                                                                    | enabled                        |
+| CONFIG_OV7725_SUPPORT             | Support for OV7725 camera                                                                                                                                    | disabled                       |
+| CONFIG_OV3660_SUPPORT             | Support for OV3660 camera                                                                                                                                    | enabled                        |
+| CONFIG_OV5640_SUPPORT             | Support for OV5640 camera                                                                                                                                    | enabled                        |
+| CONFIG_SCCB_HARDWARE_I2C          | Enable this option if you want to use hardware I2C to control the camera. Disable this option to use software I2C.                                           | enabled                        |
+| CONFIG_SCCB_HARDWARE_I2C_PORT     | I2C peripheral to use for SCCB. Can be I2C0 and I2C1.                                                                                                        | CONFIG_SCCB_HARDWARE_I2C_PORT1 |
+| CONFIG_CAMERA_TASK_PINNED_TO_CORE | Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. Can be CAMERA_CORE0, CAMERA_CORE1 or NO_AFFINITY. | CONFIG_CAMERA_CORE0            |
+
+## 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_sscb_sda = CAM_PIN_SIOD,
+    .pin_sscb_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_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG
+    .frame_size = FRAMESIZE_UXGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
+
+    .jpeg_quality = 12, //0-63 lower number means higher quality
+    .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG
+};
+
+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;
+}
+```
+
+
+

+ 4 - 0
code/components/esp32-camera-master/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
+COMPONENT_SRCDIRS := driver conversions sensors
+CXXFLAGS += -fno-rtti

+ 0 - 0
code/lib/conversions/esp_jpg_decode.c → code/components/esp32-camera-master/conversions/esp_jpg_decode.c


+ 0 - 0
code/lib/conversions/esp_jpg_decode.h → code/components/esp32-camera-master/conversions/include/esp_jpg_decode.h


+ 0 - 0
code/lib/conversions/img_converters.h → code/components/esp32-camera-master/conversions/include/img_converters.h


+ 0 - 0
code/lib/conversions/jpge.cpp → code/components/esp32-camera-master/conversions/jpge.cpp


+ 0 - 0
code/lib/conversions/jpge.h → code/components/esp32-camera-master/conversions/private_include/jpge.h


+ 0 - 0
code/lib/conversions/yuv.h → code/components/esp32-camera-master/conversions/private_include/yuv.h


+ 11 - 0
code/lib/conversions/to_bmp.c → code/components/esp32-camera-master/conversions/to_bmp.c

@@ -20,6 +20,17 @@
 #include "sdkconfig.h"
 #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/spiram.h"
+#else 
+#error Target CONFIG_IDF_TARGET is not supported
+#endif
+#else // ESP32 Before IDF 4.0
+#include "esp_spiram.h"
+#endif
+
 #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
 #include "esp32-hal-log.h"
 #define TAG ""

+ 2 - 3
code/lib/conversions/to_jpg.cpp → code/components/esp32-camera-master/conversions/to_jpg.cpp

@@ -16,7 +16,7 @@
 #include "esp_attr.h"
 #include "soc/efuse_reg.h"
 #include "esp_heap_caps.h"
-#include <esp_camera.h>
+#include "esp_camera.h"
 #include "img_converters.h"
 #include "jpge.h"
 #include "yuv.h"
@@ -215,8 +215,7 @@ bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
 {
     //todo: allocate proper buffer for holding JPEG data
     //this should be enough for CIF frame size
-//    int jpg_buf_len = 64*1024;
-    int jpg_buf_len = 256*1024;     // Anpassung wg. zu kleiner Bitmaps
+    int jpg_buf_len = 64*1024;
 
 
     uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len);

+ 0 - 0
code/lib/conversions/yuv.c → code/components/esp32-camera-master/conversions/yuv.c


+ 109 - 37
code/lib/driver/camera.c → code/components/esp32-camera-master/driver/camera.c

@@ -36,14 +36,6 @@
 #include "esp_camera.h"
 #include "camera_common.h"
 #include "xclk.h"
-
-#define CONFIG_OV2640_SUPPORT 1
-//#define CONFIG_OV7725_SUPPORT 1
-//#define CONFIG_OV7725_SUPPORT 1
-//#define CONFIG_OV3660_SUPPORT 1
-//#define CONFIG_OV5640_SUPPORT 1
-
-
 #if CONFIG_OV2640_SUPPORT
 #include "ov2640.h"
 #endif
@@ -56,6 +48,12 @@
 #if CONFIG_OV5640_SUPPORT
 #include "ov5640.h"
 #endif
+#if CONFIG_NT99141_SUPPORT
+#include "nt99141.h"
+#endif
+#if CONFIG_OV7670_SUPPORT
+#include "ov7670.h"
+#endif
 
 typedef enum {
     CAMERA_NONE = 0,
@@ -64,6 +62,8 @@ typedef enum {
     CAMERA_OV2640 = 2640,
     CAMERA_OV3660 = 3660,
     CAMERA_OV5640 = 5640,
+    CAMERA_OV7670 = 7670,
+    CAMERA_NT99141 = 9141,
 } camera_model_t;
 
 #define REG_PID        0x0A
@@ -377,12 +377,10 @@ static inline void IRAM_ATTR i2s_conf_reset()
     }
 }
 
-static void i2s_init()
+static void i2s_gpio_init(const camera_config_t* config)
 {
-    camera_config_t* config = &s_state->config;
-
     // Configure input GPIOs
-    gpio_num_t pins[] = {
+    const gpio_num_t pins[] = {
         config->pin_d7,
         config->pin_d6,
         config->pin_d5,
@@ -399,15 +397,21 @@ static void i2s_init()
         .mode = GPIO_MODE_INPUT,
         .pull_up_en = GPIO_PULLUP_ENABLE,
         .pull_down_en = GPIO_PULLDOWN_DISABLE,
-        .intr_type = GPIO_INTR_DISABLE
+        .intr_type = GPIO_INTR_DISABLE,
+        .pin_bit_mask = 0LL
     };
     for (int i = 0; i < sizeof(pins) / sizeof(gpio_num_t); ++i) {
         if (rtc_gpio_is_valid_gpio(pins[i])) {
             rtc_gpio_deinit(pins[i]);
         }
-        conf.pin_bit_mask = 1LL << pins[i];
-        gpio_config(&conf);
+        conf.pin_bit_mask |= 1LL << pins[i];
     }
+    gpio_config(&conf);
+}
+
+static void i2s_init()
+{
+    camera_config_t* config = &s_state->config;
 
     // Route input GPIOs to I2S peripheral using GPIO matrix
     gpio_matrix_in(config->pin_d0, I2S0I_DATA_IN0_IDX, false);
@@ -963,11 +967,15 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
         return ESP_ERR_NO_MEM;
     }
 
-    ESP_LOGD(TAG, "Enabling XCLK output");
-    camera_enable_out_clock(config);
+    if(config->pin_xclk >= 0) {
+      ESP_LOGD(TAG, "Enabling XCLK output");
+      camera_enable_out_clock(config);
+    }
 
-    ESP_LOGD(TAG, "Initializing SSCB");
-    SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
+    if (config->pin_sscb_sda != -1) {
+      ESP_LOGD(TAG, "Initializing SSCB");
+      SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
+    }
 	
     if(config->pin_pwdn >= 0) {
         ESP_LOGD(TAG, "Resetting camera by power down line");
@@ -1019,16 +1027,33 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
         slv_addr = SCCB_Probe();
     }
 #endif
+#if CONFIG_NT99141_SUPPORT
+   if (slv_addr == 0x2a)
+    {
+        ESP_LOGD(TAG, "Resetting NT99141");
+        SCCB_Write16(0x2a, 0x3008, 0x01);//bank sensor
+    }
+#endif 
 
     s_state->sensor.slv_addr = slv_addr;
     s_state->sensor.xclk_freq_hz = config->xclk_freq_hz;
 
-#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT)
+#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_SUPPORT)
     if(s_state->sensor.slv_addr == 0x3c){
         id->PID = SCCB_Read16(s_state->sensor.slv_addr, REG16_CHIDH);
         id->VER = SCCB_Read16(s_state->sensor.slv_addr, REG16_CHIDL);
         vTaskDelay(10 / portTICK_PERIOD_MS);
         ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
+    } else if(s_state->sensor.slv_addr == 0x2a){
+        id->PID = SCCB_Read16(s_state->sensor.slv_addr, 0x3000);
+        id->VER = SCCB_Read16(s_state->sensor.slv_addr, 0x3001);
+        vTaskDelay(10 / portTICK_PERIOD_MS);
+        ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x", id->PID, id->VER);
+        if(config->xclk_freq_hz > 10000000)
+        {
+            ESP_LOGE(TAG, "NT99141: only XCLK under 10MHz is supported, and XCLK is now set to 10M");
+            s_state->sensor.xclk_freq_hz = 10000000;
+        }    
     } else {
 #endif
         id->PID = SCCB_Read(s_state->sensor.slv_addr, REG_PID);
@@ -1039,7 +1064,7 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
         ESP_LOGD(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x",
                  id->PID, id->VER, id->MIDH, id->MIDL);
 
-#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT)
+#if (CONFIG_OV3660_SUPPORT || CONFIG_OV5640_SUPPORT || CONFIG_NT99141_SUPPORT)
     }
 #endif
 
@@ -1068,6 +1093,18 @@ esp_err_t camera_probe(const camera_config_t* config, camera_model_t* out_camera
         *out_camera_model = CAMERA_OV5640;
         ov5640_init(&s_state->sensor);
         break;
+#endif
+#if CONFIG_OV7670_SUPPORT
+    case OV7670_PID:
+        *out_camera_model = CAMERA_OV7670;
+        ov7670_init(&s_state->sensor);
+        break;
+#endif
+#if CONFIG_NT99141_SUPPORT
+        case NT99141_PID:
+        *out_camera_model = CAMERA_NT99141;
+        NT99141_init(&s_state->sensor);
+        break;
 #endif
     default:
         id->PID = 0;
@@ -1124,6 +1161,20 @@ esp_err_t camera_init(const camera_config_t* config)
                 frame_size = FRAMESIZE_QSXGA;
             }
             break;
+#endif
+#if CONFIG_OV7670_SUPPORT
+        case OV7670_PID:
+            if (frame_size > FRAMESIZE_VGA) {
+                frame_size = FRAMESIZE_VGA;
+            }
+            break;
+#endif
+#if CONFIG_NT99141_SUPPORT
+        case NT99141_PID:
+            if (frame_size > FRAMESIZE_HD) {
+                frame_size = FRAMESIZE_HD;
+            }
+            break;
 #endif
         default:
             return ESP_ERR_CAMERA_NOT_SUPPORTED;
@@ -1134,7 +1185,7 @@ esp_err_t camera_init(const camera_config_t* config)
 
     if (pix_format == PIXFORMAT_GRAYSCALE) {
         s_state->fb_size = s_state->width * s_state->height;
-        if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID) {
+        if (s_state->sensor.id.PID == OV3660_PID || s_state->sensor.id.PID == OV5640_PID || s_state->sensor.id.PID == NT99141_PID) {
             if (is_hs_mode()) {
                 s_state->sampling_mode = SM_0A00_0B00;
                 s_state->dma_filter = &dma_filter_yuyv_highspeed;
@@ -1155,20 +1206,28 @@ esp_err_t camera_init(const camera_config_t* config)
         }
         s_state->fb_bytes_per_pixel = 1;       // frame buffer stores Y8
     } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
-        s_state->fb_size = s_state->width * s_state->height * 2;
-        if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
-            s_state->sampling_mode = SM_0A00_0B00;
-            s_state->dma_filter = &dma_filter_yuyv_highspeed;
-        } else {
-            s_state->sampling_mode = SM_0A0B_0C0D;
-            s_state->dma_filter = &dma_filter_yuyv;
-        }
-        s_state->in_bytes_per_pixel = 2;       // camera sends YU/YV
-        s_state->fb_bytes_per_pixel = 2;       // frame buffer stores YU/YV/RGB565
+            s_state->fb_size = s_state->width * s_state->height * 2;
+            if (is_hs_mode() && s_state->sensor.id.PID != OV7725_PID) {
+                if(s_state->sensor.id.PID == OV7670_PID) {
+                    s_state->sampling_mode = SM_0A0B_0B0C;
+                }else{
+                    s_state->sampling_mode = SM_0A00_0B00;
+                }
+                s_state->dma_filter = &dma_filter_yuyv_highspeed;
+            } else {
+                s_state->sampling_mode = SM_0A0B_0C0D;
+                s_state->dma_filter = &dma_filter_yuyv;
+            }
+            s_state->in_bytes_per_pixel = 2;       // camera sends YU/YV
+            s_state->fb_bytes_per_pixel = 2;       // frame buffer stores YU/YV/RGB565
     } else if (pix_format == PIXFORMAT_RGB888) {
         s_state->fb_size = s_state->width * s_state->height * 3;
         if (is_hs_mode()) {
-            s_state->sampling_mode = SM_0A00_0B00;
+            if(s_state->sensor.id.PID == OV7670_PID) {
+                s_state->sampling_mode = SM_0A0B_0B0C;
+            }else{
+                s_state->sampling_mode = SM_0A00_0B00;
+            }
             s_state->dma_filter = &dma_filter_rgb888_highspeed;
         } else {
             s_state->sampling_mode = SM_0A0B_0C0D;
@@ -1177,7 +1236,7 @@ esp_err_t camera_init(const camera_config_t* config)
         s_state->in_bytes_per_pixel = 2;       // camera sends RGB565
         s_state->fb_bytes_per_pixel = 3;       // frame buffer stores RGB888
     } else if (pix_format == PIXFORMAT_JPEG) {
-        if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID) {
+        if (s_state->sensor.id.PID != OV2640_PID && s_state->sensor.id.PID != OV3660_PID && s_state->sensor.id.PID != OV5640_PID  && s_state->sensor.id.PID != NT99141_PID) {
             ESP_LOGE(TAG, "JPEG format is only supported for ov2640, ov3660 and ov5640");
             err = ESP_ERR_NOT_SUPPORTED;
             goto fail;
@@ -1264,8 +1323,13 @@ esp_err_t camera_init(const camera_config_t* config)
     vsync_intr_disable();
     err = gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM);
     if (err != ESP_OK) {
-        ESP_LOGE(TAG, "gpio_install_isr_service failed (%x)", err);
-        goto fail;
+    	if (err != ESP_ERR_INVALID_STATE) {
+    		ESP_LOGE(TAG, "gpio_install_isr_service failed (%x)", err);
+        	goto fail;
+    	}
+    	else {
+    		ESP_LOGW(TAG, "gpio_install_isr_service already installed");
+    	}
     }
     err = gpio_isr_handler_add(s_state->config.pin_vsync, &vsync_isr, NULL);
     if (err != ESP_OK) {
@@ -1309,6 +1373,7 @@ fail:
 esp_err_t esp_camera_init(const camera_config_t* config)
 {
     camera_model_t camera_model = CAMERA_NONE;
+    i2s_gpio_init(config);
     esp_err_t err = camera_probe(config, &camera_model);
     if (err != ESP_OK) {
         ESP_LOGE(TAG, "Camera probe failed with error 0x%x", err);
@@ -1327,6 +1392,10 @@ esp_err_t esp_camera_init(const camera_config_t* config)
         ESP_LOGI(TAG, "Detected OV3660 camera");
     } else if (camera_model == CAMERA_OV5640) {
         ESP_LOGI(TAG, "Detected OV5640 camera");
+    } else if (camera_model == CAMERA_OV7670) {
+        ESP_LOGI(TAG, "Detected OV7670 camera");
+    } else if (camera_model == CAMERA_NT99141) {
+        ESP_LOGI(TAG, "Detected NT99141 camera");
     } else {
         ESP_LOGI(TAG, "Camera not supported");
         err = ESP_ERR_CAMERA_NOT_SUPPORTED;
@@ -1373,9 +1442,12 @@ esp_err_t esp_camera_deinit()
     }
     dma_desc_deinit();
     camera_fb_deinit();
+
+    if(s_state->config.pin_xclk >= 0) {
+      camera_disable_out_clock();
+    }
     free(s_state);
     s_state = NULL;
-    camera_disable_out_clock();
     periph_module_disable(PERIPH_I2S0_MODULE);
     return ESP_OK;
 }

+ 0 - 5
code/lib/driver/esp_camera.h → code/components/esp32-camera-master/driver/include/esp_camera.h

@@ -65,9 +65,6 @@
 
 #pragma once
 
-#ifndef ESPCAMERADEF
-#define ESPCAMERADEF
-
 #include "esp_err.h"
 #include "driver/ledc.h"
 #include "sensor.h"
@@ -196,5 +193,3 @@ esp_err_t esp_camera_load_from_nvs(const char *key);
 
 #include "img_converters.h"
 
-#endif
-

+ 2 - 0
code/lib/jomjol_controlcamera/sensor.h → code/components/esp32-camera-master/driver/include/sensor.h

@@ -11,11 +11,13 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#define NT99141_PID     (0x14)
 #define OV9650_PID     (0x96)
 #define OV7725_PID     (0x77)
 #define OV2640_PID     (0x26)
 #define OV3660_PID     (0x36)
 #define OV5640_PID     (0x56)
+#define OV7670_PID     (0x76)
 
 typedef enum {
     PIXFORMAT_RGB565,    // 2BPP/RGB565

+ 0 - 0
code/lib/driver/camera_common.h → code/components/esp32-camera-master/driver/private_include/camera_common.h


+ 0 - 0
code/lib/driver/sccb.h → code/components/esp32-camera-master/driver/private_include/sccb.h


+ 0 - 0
code/lib/driver/xclk.h → code/components/esp32-camera-master/driver/private_include/xclk.h


+ 0 - 95
code/lib/driver/sccb.c → code/components/esp32-camera-master/driver/sccb.c

@@ -19,11 +19,8 @@
 static const char* TAG = "sccb";
 #endif
 
-//#undef CONFIG_SCCB_HARDWARE_I2C
-
 #define LITTLETOBIG(x)          ((x<<8)|(x>>8))
 
-#ifdef CONFIG_SCCB_HARDWARE_I2C
 #include "driver/i2c.h"
 
 #define SCCB_FREQ               100000           /*!< I2C master frequency*/
@@ -39,14 +36,10 @@ const int SCCB_I2C_PORT         = 1;
 const int SCCB_I2C_PORT         = 0;
 #endif
 static uint8_t ESP_SLAVE_ADDR   = 0x3c;
-#else
-#include "twi.h"
-#endif
 
 int SCCB_Init(int pin_sda, int pin_scl)
 {
     ESP_LOGI(TAG, "pin_sda %d pin_scl %d\n", pin_sda, pin_scl);
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     //log_i("SCCB_Init start");
     i2c_config_t conf;
     conf.mode = I2C_MODE_MASTER;
@@ -58,15 +51,11 @@ int SCCB_Init(int pin_sda, int pin_scl)
 
     i2c_param_config(SCCB_I2C_PORT, &conf);
     i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
-#else
-    twi_init(pin_sda, pin_scl);
-#endif
     return 0;
 }
 
 uint8_t SCCB_Probe()
 {
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     uint8_t slave_addr = 0x0;
     while(slave_addr < 0x7f) {
         i2c_cmd_handle_t cmd = i2c_cmd_link_create();
@@ -82,28 +71,10 @@ uint8_t SCCB_Probe()
         slave_addr++;
     }
     return ESP_SLAVE_ADDR;
-#else
-    uint8_t reg = 0x00;
-    uint8_t slv_addr = 0x00;
-
-    ESP_LOGI(TAG, "SCCB_Probe start");
-    for (uint8_t i = 0; i < 127; i++) {
-        if (twi_writeTo(i, &reg, 1, true) == 0) {
-            slv_addr = i;
-            break;
-        }
-
-        if (i!=126) {
-            vTaskDelay(10 / portTICK_PERIOD_MS); // Necessary for OV7725 camera (not for OV2640).
-        }
-    }
-    return slv_addr;
-#endif
 }
 
 uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
 {
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     uint8_t data=0;
     esp_err_t ret = ESP_FAIL;
     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
@@ -125,28 +96,10 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
         ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
     }
     return data;
-#else
-    uint8_t data=0;
-
-    int rc = twi_writeTo(slv_addr, &reg, 1, true);
-    if (rc != 0) {
-        data = 0xff;
-    } else {
-        rc = twi_readFrom(slv_addr, &data, 1, true);
-        if (rc != 0) {
-            data=0xFF;
-        }
-    }
-    if (rc != 0) {
-        ESP_LOGE(TAG, "SCCB_Read [%02x] failed rc=%d\n", reg, rc);
-    }
-    return data;
-#endif
 }
 
 uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
 {
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     esp_err_t ret = ESP_FAIL;
     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
     i2c_master_start(cmd);
@@ -160,23 +113,10 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
         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;
-#else
-    uint8_t ret=0;
-    uint8_t buf[] = {reg, data};
-
-    if(twi_writeTo(slv_addr, buf, 2, true) != 0) {
-        ret=0xFF;
-    }
-    if (ret != 0) {
-        ESP_LOGE(TAG, "SCCB_Write [%02x]=%02x failed\n", reg, data);
-    }
-    return ret;
-#endif
 }
 
 uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
 {
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     uint8_t data=0;
     esp_err_t ret = ESP_FAIL;
     uint16_t reg_htons = LITTLETOBIG(reg);
@@ -201,32 +141,11 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
         ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
     }
     return data;
-#else
-    uint8_t data=0;
-    uint16_t reg_htons = LITTLETOBIG(reg);
-    uint8_t *reg_u8 = (uint8_t *)&reg_htons;
-    uint8_t buf[] = {reg_u8[0], reg_u8[1]};
-
-    int rc = twi_writeTo(slv_addr, buf, 2, true);
-    if (rc != 0) {
-        data = 0xff;
-    } else {
-        rc = twi_readFrom(slv_addr, &data, 1, true);
-        if (rc != 0) {
-            data=0xFF;
-        }
-    }
-    if (rc != 0) {
-        ESP_LOGE(TAG, "R [%04x] fail rc=%d\n", reg, rc);
-    }
-    return data;
-#endif
 }
 
 uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
 {
     static uint16_t i = 0;
-#ifdef CONFIG_SCCB_HARDWARE_I2C
     esp_err_t ret = ESP_FAIL;
     uint16_t reg_htons = LITTLETOBIG(reg);
     uint8_t *reg_u8 = (uint8_t *)&reg_htons;
@@ -243,18 +162,4 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
         ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
     }
     return ret == ESP_OK ? 0 : -1;
-#else
-    uint8_t ret=0;
-    uint16_t reg_htons = LITTLETOBIG(reg);
-    uint8_t *reg_u8 = (uint8_t *)&reg_htons;
-    uint8_t buf[] = {reg_u8[0], reg_u8[1], data};
-
-    if(twi_writeTo(slv_addr, buf, 3, true) != 0) {
-        ret = 0xFF;
-    }
-    if (ret != 0) {
-        ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
-    }
-    return ret;
-#endif
 }

+ 0 - 0
code/lib/driver/sensor.c → code/components/esp32-camera-master/driver/sensor.c


+ 0 - 3
code/lib/driver/xclk.c → code/components/esp32-camera-master/driver/xclk.c

@@ -18,12 +18,9 @@ esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz)
     timer_conf.duty_resolution = 2;
     timer_conf.freq_hz = xclk_freq_hz;
     timer_conf.speed_mode = LEDC_HIGH_SPEED_MODE;
-
 #if ESP_IDF_VERSION_MAJOR >= 4
     timer_conf.clk_cfg = LEDC_AUTO_CLK;
 #endif
-//    timer_conf.clk_cfg = LEDC_USE_APB_CLK;
-
     timer_conf.timer_num = (ledc_timer_t)ledc_timer;
     esp_err_t err = ledc_timer_config(&timer_conf);
     if (err != ESP_OK) {

+ 150 - 0
code/components/esp32-camera-master/examples/take_picture.c

@@ -0,0 +1,150 @@
+/**
+ * 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 <esp_event_loop.h>
+#include <esp_log.h>
+#include <esp_system.h>
+#include <nvs_flash.h>
+#include <sys/param.h>
+#include <string.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "esp_camera.h"
+
+// 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";
+
+static camera_config_t camera_config = {
+    .pin_pwdn = CAM_PIN_PWDN,
+    .pin_reset = CAM_PIN_RESET,
+    .pin_xclk = CAM_PIN_XCLK,
+    .pin_sscb_sda = CAM_PIN_SIOD,
+    .pin_sscb_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_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
+    .frame_size = FRAMESIZE_VGA,    //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
+
+    .jpeg_quality = 12, //0-63 lower number means higher quality
+    .fb_count = 1       //if more than one, i2s runs in continuous mode. Use only with JPEG
+};
+
+static esp_err_t init_camera()
+{
+    //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;
+}
+
+void app_main()
+{
+    init_camera();
+
+    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);
+
+        vTaskDelay(5000 / portTICK_RATE_MS);
+    }
+}

+ 5 - 0
code/components/esp32-camera-master/idf_component.yml

@@ -0,0 +1,5 @@
+name: "esp32-camera"
+
+version: "1.0.0"
+
+description: This package hosts ESP32 compatible driver for OV2640 image sensors. Additionally it provides a few tools, which allow converting the captured frame data to the more common BMP and JPEG formats.

+ 25 - 0
code/components/esp32-camera-master/library.json

@@ -0,0 +1,25 @@
+{
+  "name": "esp32-camera",
+  "version": "1.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",
+      "-fno-rtti"
+    ],
+    "includeDir": ".",
+    "srcDir": ".",
+    "srcFilter": ["-<*>", "+<driver>", "+<conversions>", "+<sensors>"]
+  }
+}

+ 1032 - 0
code/components/esp32-camera-master/sensors/nt99141.c

@@ -0,0 +1,1032 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * NT99141 driver.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "sccb.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 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_LOGD(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)
+{
+    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 0;
+}
+
+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;
+    bool negative = false;
+
+    switch (level) {
+        case 3:
+            value = 0xA0;
+            break;
+
+        case 2:
+            value = 0x90;
+            break;
+
+        case 1:
+            value = 0x88;
+            break;
+
+        case -1:
+            value = 0x78;
+            negative = true;
+            break;
+
+        case -2:
+            value = 0x70;
+            negative = true;
+            break;
+
+        case -3:
+            value = 0x60;
+            negative = true;
+            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 ;
+    bool negative = false;
+
+    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);
+}
+
+esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz);
+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;
+}
+
+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;
+}

+ 0 - 0
code/lib/sensors/ov2640.c → code/components/esp32-camera-master/sensors/ov2640.c


+ 0 - 0
code/lib/sensors/ov3660.c → code/components/esp32-camera-master/sensors/ov3660.c


+ 0 - 0
code/lib/sensors/ov5640.c → code/components/esp32-camera-master/sensors/ov5640.c


+ 439 - 0
code/components/esp32-camera-master/sensors/ov7670.c

@@ -0,0 +1,439 @@
+/*
+ * This file is part of the OpenMV project.
+ * author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
+ * This work is licensed under the MIT license, see the file LICENSE for details.
+ *
+ * OV7725 driver.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "sccb.h"
+#include "ov7670.h"
+#include "ov7670_regs.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include <stdio.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 = "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_MASK},
+
+    /* 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[5].reg_num = 0xFF;
+    frame[5].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, 10, 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_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;
+}

+ 0 - 0
code/lib/sensors/ov7725.c → code/components/esp32-camera-master/sensors/ov7725.c


+ 16 - 0
code/components/esp32-camera-master/sensors/private_include/nt99141.h

@@ -0,0 +1,16 @@
+/*
+ * This file is part of the OpenMV project.
+ * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
+ * 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"
+
+int NT99141_init(sensor_t *sensor);
+
+#endif // __NT99141_H__

+ 211 - 0
code/components/esp32-camera-master/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__

+ 825 - 0
code/components/esp32-camera-master/sensors/private_include/nt99141_settings.h

@@ -0,0 +1,825 @@
+#ifndef _NT99141_SETTINGS_H_
+#define _NT99141_SETTINGS_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#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
+
+

+ 0 - 0
code/lib/sensors/ov2640.h → code/components/esp32-camera-master/sensors/private_include/ov2640.h


+ 0 - 0
code/lib/sensors/ov2640_regs.h → code/components/esp32-camera-master/sensors/private_include/ov2640_regs.h


+ 0 - 0
code/lib/sensors/ov2640_settings.h → code/components/esp32-camera-master/sensors/private_include/ov2640_settings.h


+ 0 - 0
code/lib/sensors/ov3660.h → code/components/esp32-camera-master/sensors/private_include/ov3660.h


+ 0 - 0
code/lib/sensors/ov3660_regs.h → code/components/esp32-camera-master/sensors/private_include/ov3660_regs.h


+ 0 - 0
code/lib/sensors/ov3660_settings.h → code/components/esp32-camera-master/sensors/private_include/ov3660_settings.h


+ 0 - 0
code/lib/sensors/ov5640.h → code/components/esp32-camera-master/sensors/private_include/ov5640.h


+ 0 - 0
code/lib/sensors/ov5640_regs.h → code/components/esp32-camera-master/sensors/private_include/ov5640_regs.h


+ 0 - 0
code/lib/sensors/ov5640_settings.h → code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h


+ 14 - 0
code/components/esp32-camera-master/sensors/private_include/ov7670.h

@@ -0,0 +1,14 @@
+/*
+ * This file is part of the OpenMV project.
+ * author: Juan Schiavoni <juanjoseschiavoni@hotmail.com>
+ * 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"
+
+int ov7670_init(sensor_t *sensor);
+#endif // __OV7670_H__

+ 354 - 0
code/components/esp32-camera-master/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 <juanjoseschiavoni@hotmail.com>
+ *
+ * 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__

+ 0 - 0
code/lib/sensors/ov7725.h → code/components/esp32-camera-master/sensors/private_include/ov7725.h


+ 0 - 0
code/lib/sensors/ov7725_regs.h → code/components/esp32-camera-master/sensors/private_include/ov7725_regs.h


+ 9 - 0
code/components/jomjol_controlcamera/CMakeLists.txt

@@ -0,0 +1,9 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES esp32-camera-master esp_http_server jomjol_logfile jomjol_image_proc nvs_flash)
+
+

+ 126 - 5
code/lib/jomjol_controlcamera/ClassControllCamera.cpp → code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -8,7 +8,128 @@
 #include "Helper.h"
 #include "CFindTemplate.h"
 
-#include "camera_define.h"
+// #include "camera_define.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+#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 <esp_event_loop.h>
+#include <esp_log.h>
+#include <esp_system.h>
+#include <nvs_flash.h>
+#include <sys/param.h>
+#include <string.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "esp_camera.h"
+
+// 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 (gpio_num_t) 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";
+
+static camera_config_t camera_config = {
+    .pin_pwdn = CAM_PIN_PWDN,
+    .pin_reset = CAM_PIN_RESET,
+    .pin_xclk = CAM_PIN_XCLK,
+    .pin_sscb_sda = CAM_PIN_SIOD,
+    .pin_sscb_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_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
+    .frame_size = FRAMESIZE_UXGA,    //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
+
+    
+
+    .jpeg_quality = 5, //0-63 lower number means higher quality
+    .fb_count = 1       //if more than one, i2s runs in continuous mode. Use only with JPEG
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
 
 #include "driver/ledc.h"
 
@@ -270,12 +391,12 @@ esp_err_t CCamera::InitCam()
 {
     printf("Init Flash\n");
     //power up the camera if PWDN pin is defined
-    if(PWDN_GPIO_NUM != -1){
+    if(CAM_PIN_PWDN != -1){
         // Init the GPIO
-        gpio_pad_select_gpio(PWDN_GPIO_NUM);
+        gpio_pad_select_gpio(CAM_PIN_PWDN);
         /* Set the GPIO as a push/pull output */
-        gpio_set_direction(PWDN_GPIO_NUM, GPIO_MODE_OUTPUT);
-        gpio_set_level(PWDN_GPIO_NUM, 0);
+        gpio_set_direction(CAM_PIN_PWDN, GPIO_MODE_OUTPUT);
+        gpio_set_level(CAM_PIN_PWDN, 0);
     }
 
     printf("Init Camera\n");

+ 1 - 1
code/lib/jomjol_controlcamera/ClassControllCamera.h → code/components/jomjol_controlcamera/ClassControllCamera.h

@@ -9,7 +9,7 @@
 
 #include "esp_camera.h"
 #include <string>
-#include "esp_http_server.h"
+#include <esp_http_server.h>
 
 
 #define CAMERA_MODEL_AI_THINKER

+ 0 - 0
code/lib/jomjol_controlcamera/img_converters.h → code/components/jomjol_controlcamera/img_converters.h


+ 0 - 0
code/lib/driver/sensor.h → code/components/jomjol_controlcamera/sensor.h


+ 0 - 0
code/lib/jomjol_controlcamera/server_camera.cpp → code/components/jomjol_controlcamera/server_camera.cpp


+ 0 - 0
code/lib/jomjol_controlcamera/server_camera.h → code/components/jomjol_controlcamera/server_camera.h


+ 7 - 0
code/components/jomjol_fileserver_ota/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES tfmicro esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper)
+
+

+ 0 - 0
code/lib/jomjol_fileserver_ota/miniz.c → code/components/jomjol_fileserver_ota/miniz.c


+ 0 - 0
code/lib/jomjol_fileserver_ota/miniz.h → code/components/jomjol_fileserver_ota/miniz.h


+ 76 - 1
code/lib/jomjol_fileserver_ota/server_file.cpp → code/components/jomjol_fileserver_ota/server_file.cpp

@@ -23,7 +23,7 @@
 #include "esp_log.h"
 
 #include "esp_vfs.h"
-#include "esp_spiffs.h"
+#include <esp_spiffs.h>
 #include "esp_http_server.h"
 
 #include "ClassLogFile.h"
@@ -216,6 +216,70 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
     (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
 
 
+static esp_err_t logfileact_get_handler(httpd_req_t *req)
+{
+    LogFile.WriteToFile("logfileact_get_handler");
+    char filepath[FILE_PATH_MAX];
+    FILE *fd = NULL;
+    struct stat file_stat;
+    printf("uri: %s\n", req->uri);
+
+    const char filename = 'log_current.txt'; 
+
+    printf("uri: %s, filename: %s, filepath: %s\n", req->uri, &filename, filepath);
+
+    std::string currentfilename = LogFile.GetCurrentFileName();
+
+
+    fd = fopen(currentfilename.c_str(), "r");
+    if (!fd) {
+        ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
+        /* Respond with 500 Internal Server Error */
+        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
+        return ESP_FAIL;
+    }
+
+    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+
+//    ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
+    set_content_type_from_file(req, &filename);
+
+    /* Retrieve the pointer to scratch buffer for temporary storage */
+    char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
+    size_t chunksize;
+    do {
+        /* Read file in chunks into the scratch buffer */
+        chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
+
+        /* Send the buffer contents as HTTP response chunk */
+        if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
+            fclose(fd);
+            ESP_LOGE(TAG, "File sending failed!");
+            /* Abort sending file */
+            httpd_resp_sendstr_chunk(req, NULL);
+            /* Respond with 500 Internal Server Error */
+            httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
+            return ESP_FAIL;
+        }
+
+        /* Keep looping till the whole file is sent */
+    } while (chunksize != 0);
+
+    /* Close file after sending complete */
+    fclose(fd);
+    ESP_LOGI(TAG, "File sending complete");
+
+    /* Respond with an empty chunk to signal HTTP response completion */
+    httpd_resp_send_chunk(req, NULL, 0);
+    return ESP_OK;
+}
+
+
+
+
+
+
+
 /* Handler to download a file kept on the server */
 static esp_err_t download_get_handler(httpd_req_t *req)
 {
@@ -707,6 +771,17 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
     };
     httpd_register_uri_handler(server, &file_download);
 
+
+
+    httpd_uri_t file_logfileact = {
+        .uri       = "/logfileact",  // Match all URIs of type /path/to/file
+        .method    = HTTP_GET,
+        .handler   = logfileact_get_handler,
+        .user_ctx  = server_data    // Pass server data as context
+    };
+    httpd_register_uri_handler(server, &file_logfileact);
+
+
     /* URI handler for uploading files to server */
     httpd_uri_t file_upload = {
         .uri       = "/upload/*",   // Match all URIs of type /upload/path/to/file

+ 0 - 0
code/lib/jomjol_fileserver_ota/server_file.h → code/components/jomjol_fileserver_ota/server_file.h


+ 0 - 0
code/src/server_help.cpp → code/components/jomjol_fileserver_ota/server_help.cpp


+ 0 - 0
code/src/server_help.h → code/components/jomjol_fileserver_ota/server_help.h


+ 3 - 3
code/lib/jomjol_fileserver_ota/server_ota.cpp → code/components/jomjol_fileserver_ota/server_ota.cpp

@@ -14,14 +14,14 @@
 #include "esp_event.h"
 #include "esp_event_loop.h"
 #include "esp_log.h"
-#include "esp_ota_ops.h"
+#include <esp_ota_ops.h>
 #include "esp_http_client.h"
 #include "esp_flash_partitions.h"
 #include "esp_partition.h"
-#include "nvs.h"
+#include <nvs.h>
 #include "nvs_flash.h"
 #include "driver/gpio.h"
-#include "protocol_examples_common.h"
+// #include "protocol_examples_common.h"
 #include "errno.h"
 
 #include <sys/stat.h>

+ 0 - 0
code/lib/jomjol_fileserver_ota/server_ota.h → code/components/jomjol_fileserver_ota/server_ota.h


+ 7 - 0
code/components/jomjol_flowcontroll/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota)
+
+

+ 4 - 2
code/lib/jomjol_flowcontroll/ClassFlow.cpp → code/components/jomjol_flowcontroll/ClassFlow.cpp

@@ -11,10 +11,12 @@ void ClassFlow::SetInitialParameter(void)
 	ListFlowControll = NULL;
 }
 
-std::vector<string> ClassFlow::ZerlegeZeile(std::string input)
+//std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter);
+
+std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter)
 {
 	std::vector<string> Output;
-	std::string delimiter = " =,";
+//	std::string delimiter = " =,";
 
 	input = trim(input, delimiter);
 	size_t pos = findDelimiterPos(input, delimiter);

+ 2 - 1
code/lib/jomjol_flowcontroll/ClassFlow.h → code/components/jomjol_flowcontroll/ClassFlow.h

@@ -23,7 +23,8 @@ struct HTMLInfo
 class ClassFlow
 {
 protected:
-	std::vector<string> ZerlegeZeile(string input);
+//	std::vector<string> ZerlegeZeile(string input);
+	std::vector<string> ZerlegeZeile(string input, string delimiter = " =, ");
 	bool isNewParagraph(string input);
 	bool GetNextParagraph(FILE* pfile, string& aktparamgraph);
 	bool getNextLine(FILE* pfile, string* rt);

+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowAlignment.cpp → code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowAlignment.h → code/components/jomjol_flowcontroll/ClassFlowAlignment.h


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowAnalog.cpp → code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowAnalog.h → code/components/jomjol_flowcontroll/ClassFlowAnalog.h


+ 20 - 2
code/lib/jomjol_flowcontroll/ClassFlowControll.cpp → code/components/jomjol_flowcontroll/ClassFlowControll.cpp

@@ -1,5 +1,7 @@
 #include "ClassFlowControll.h"
 
+#include "freertos/task.h"
+
 #include <sys/stat.h>
 #include <dirent.h>
 #include "ClassLogFile.h"
@@ -104,6 +106,9 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
     if (toUpper(_type).compare("[DEBUG]") == 0)
         cfc = this;  
 
+    if (toUpper(_type).compare("[SYSTEM]") == 0)
+        cfc = this;          
+
     return cfc;
 }
 
@@ -259,12 +264,12 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
             return false;
 
 
-    if ((toUpper(aktparamgraph).compare("[AUTOTIMER]") != 0) && (toUpper(aktparamgraph).compare("[DEBUG]") != 0))      // Paragraph passt nicht zu MakeImage
+    if ((toUpper(aktparamgraph).compare("[AUTOTIMER]") != 0) && (toUpper(aktparamgraph).compare("[DEBUG]") != 0) && (toUpper(aktparamgraph).compare("[SYSTEM]") != 0))      // Paragraph passt nicht zu MakeImage
         return false;
 
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     {
-        zerlegt = this->ZerlegeZeile(aktparamgraph);
+        zerlegt = this->ZerlegeZeile(aktparamgraph, " =");
         if ((toUpper(zerlegt[0]) == "AUTOSTART") && (zerlegt.size() > 1))
         {
             if (toUpper(zerlegt[1]) == "TRUE")
@@ -291,6 +296,19 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
         {
             LogFile.SetRetention(std::stoi(zerlegt[1]));
         }      
+
+        if ((toUpper(zerlegt[0]) == "TIMEZONE") && (zerlegt.size() > 1))
+        {
+            string zw = "Set TimeZone: " + zerlegt[1];
+            setTimeZone(zerlegt[1]);
+        }      
+
+        if ((toUpper(zerlegt[0]) == "TIMEUPDATEINTERVALL") && (zerlegt.size() > 1))
+        {
+            TimeUpdateIntervall = stof(zerlegt[1]);
+            xTaskCreate(&task_doTimeSync, "update_time", configMINIMAL_STACK_SIZE * 16, &TimeUpdateIntervall, tskIDLE_PRIORITY, NULL);
+        }      
+
     }
     return true;
 }

+ 1 - 0
code/lib/jomjol_flowcontroll/ClassFlowControll.h → code/components/jomjol_flowcontroll/ClassFlowControll.h

@@ -23,6 +23,7 @@ protected:
 	float AutoIntervall;
 	void SetInitialParameter(void);	
 	std::string aktstatus;
+	int TimeUpdateIntervall;
 
 
 public:

+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowDigit.cpp → code/components/jomjol_flowcontroll/ClassFlowDigit.cpp


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowDigit.h → code/components/jomjol_flowcontroll/ClassFlowDigit.h


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowImage.cpp → code/components/jomjol_flowcontroll/ClassFlowImage.cpp


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowImage.h → code/components/jomjol_flowcontroll/ClassFlowImage.h


+ 13 - 1
code/lib/jomjol_flowcontroll/ClassFlowMQTT.cpp → code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp

@@ -10,6 +10,7 @@ ClassFlowMQTT::ClassFlowMQTT()
 {
     uri = "";
     topic = "";
+    topicError = "";
     clientname = "watermeter";
     OldValue = "";
     flowpostprocessing = NULL;  
@@ -21,6 +22,7 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
 {
     uri = "";
     topic = "";
+    topicError = "";
     clientname = "watermeter";
     OldValue = "";
     flowpostprocessing = NULL;
@@ -71,6 +73,10 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
         {
             this->topic = zerlegt[1];
         }
+        if ((toUpper(zerlegt[0]) == "TOPICERROR") && (zerlegt.size() > 1))
+        {
+            this->topicError = zerlegt[1];
+        }
         if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
         {
             this->clientname = zerlegt[1];
@@ -90,11 +96,13 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
 bool ClassFlowMQTT::doFlow(string zwtime)
 {
     std::string result;
+    std::string resulterror = "";
     string zw = "";
     
     if (flowpostprocessing)
     {
         result =  flowpostprocessing->getReadoutParam(false, true);
+        resulterror = flowpostprocessing->getReadoutError();
     }
     else
     {
@@ -110,9 +118,13 @@ bool ClassFlowMQTT::doFlow(string zwtime)
             }
         }
     }
-
+    
     MQTTPublish(topic, result);
 
+    if (topicError.length() > 0) {
+        MQTTPublish(topicError, resulterror);
+    }
+
     OldValue = result;
 
 

+ 1 - 1
code/lib/jomjol_flowcontroll/ClassFlowMQTT.h → code/components/jomjol_flowcontroll/ClassFlowMQTT.h

@@ -9,7 +9,7 @@ class ClassFlowMQTT :
     public ClassFlow
 {
 protected:
-    std::string uri, topic, clientname;
+    std::string uri, topic, topicError, clientname;
     std::string OldValue;
 	ClassFlowPostProcessing* flowpostprocessing;  
     std::string user, password;  

+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowMakeImage.cpp → code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp


+ 0 - 0
code/lib/jomjol_flowcontroll/ClassFlowMakeImage.h → code/components/jomjol_flowcontroll/ClassFlowMakeImage.h


+ 36 - 10
code/lib/jomjol_flowcontroll/ClassFlowPostProcessing.cpp → code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp

@@ -13,7 +13,7 @@
 string ClassFlowPostProcessing::GetPreValue()
 {
     std::string result;
-    result = to_string(PreValue);
+    result = RundeOutput(PreValue, -DecimalShift);
 
     for (int i = 0; i < ListFlowControll->size(); ++i)
     {
@@ -90,7 +90,6 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
 void ClassFlowPostProcessing::SavePreValue(float value, string zwtime)
 {
     FILE* pFile;
-    PreValue = value;
 
     pFile = fopen(FilePreValue.c_str(), "w");
 
@@ -131,6 +130,7 @@ ClassFlowPostProcessing::ClassFlowPostProcessing()
     useMaxRateValue = false;
     checkDigitIncreaseConsistency = false;
     DecimalShift = 0;
+    ErrorMessageText = "";
     FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
 }
 
@@ -146,6 +146,7 @@ ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc)
     useMaxRateValue = false;
     checkDigitIncreaseConsistency = false;
     DecimalShift = 0;    
+    ErrorMessageText = "";
     FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
     ListFlowControll = lfc;
 }
@@ -264,9 +265,10 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
     bool isanalog = false;
     int AnzahlAnalog = 0;
     string zw;
-    string error = "";
     time_t imagetime = 0;
 
+    ErrorMessageText = "";
+
     for (int i = 0; i < ListFlowControll->size(); ++i)
     {
         if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0)
@@ -323,6 +325,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
             }
             Value = std::stof(ReturnValue);
             ReturnValueNoError = ReturnValue;
+
+            PreValueOkay = true;
+            PreValue = Value;
             
             SavePreValue(Value, zwtime);
         }
@@ -342,25 +347,29 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
 
     if ((!AllowNegativeRates) && (Value < PreValue))
     {
-        error = error + "Negative Rate - Returned old value - read value: " + zwvalue + " ";
+        ErrorMessageText = ErrorMessageText + "Negative Rate - Returned old value - read value: " + zwvalue + " ";
         Value = PreValue;
         zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
     }
 
     if (useMaxRateValue && (abs(Value - PreValue) > MaxRateValue))
     {
-        error = error + "Rate too high - Returned old value - read value: " + zwvalue + " ";
+        ErrorMessageText = ErrorMessageText + "Rate too high - Returned old value - read value: " + zwvalue + " ";
         Value = PreValue;
         zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
     }
 
     ReturnValueNoError = zwvalue;
     ReturnValue = zwvalue;
-    if (ErrorMessage && (error.length() > 0))
-        ReturnValue = ReturnValue + "\t" + error;
+    if (ErrorMessage && (ErrorMessageText.length() > 0))
+        ReturnValue = ReturnValue + "\t" + ErrorMessageText;
 
-    if (error.length() == 0)
+    if (ErrorMessageText.length() == 0)
+    {
+        PreValue = Value;
         SavePreValue(Value, zwtime);
+    }
+
 
     return true;
 }
@@ -422,6 +431,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
     int aktdigit_before, olddigit_before;
     int pot, pot_max;
     float zw;
+    bool no_nulldurchgang = false;
 
     pot = _decilamshift;
     if (!_isanalog)             // falls es keine analogwerte gibt, kann die letzte nicht bewertet werden
@@ -442,15 +452,31 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
         zw = PreValue / pow(10, pot);
         olddigit = ((int) zw) % 10;
 
-        if (aktdigit != olddigit) {
-            if (olddigit_before <= aktdigit_before)         // stelle vorher hat noch keinen Nulldurchgang --> nachfolgestelle sollte sich nicht verändern
+        no_nulldurchgang = (olddigit_before <= aktdigit_before);
+
+        if (no_nulldurchgang)
+        {
+            if (aktdigit != olddigit) 
             {
                 input = input + ((float) (olddigit - aktdigit)) * pow(10, pot);     // Neue Digit wird durch alte Digit ersetzt;
             }
         }
+        else
+        {
+            if (aktdigit == olddigit)                   // trotz Nulldurchgang wurde Stelle nicht hochgezählt --> addiere 1
+            {
+                input = input + ((float) (1)) * pow(10, pot);   // addiere 1 an der Stelle
+            }
+        }
 
         pot++;
     }
 
     return input;
 }
+
+
+string ClassFlowPostProcessing::getReadoutError() 
+{
+    return ErrorMessageText;
+}

+ 2 - 0
code/lib/jomjol_flowcontroll/ClassFlowPostProcessing.h → code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h

@@ -24,6 +24,7 @@ protected:
     string ReturnRawValue;      // Rohwert (mit N & führenden 0)    
     string ReturnValue;         // korrigierter Rückgabewert, ggf. mit Fehlermeldung
     string ReturnValueNoError;  // korrigierter Rückgabewert ohne Fehlermeldung
+    string ErrorMessageText;        // Fehlermeldung bei Consistency Check
 
     bool LoadPreValue(void);
     string ShiftDecimal(string in, int _decShift);
@@ -39,6 +40,7 @@ public:
     bool doFlow(string time);
     string getReadout();
     string getReadoutParam(bool _rawValue, bool _noerror);
+    string getReadoutError();
     void SavePreValue(float value, string time = "");
     string GetPreValue();
 

+ 0 - 0
code/lib/jomjol_flowcontroll/camera_define.h → code/components/jomjol_flowcontroll/camera_define.h


+ 7 - 0
code/components/jomjol_helper/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES tfmicro)
+
+

+ 0 - 0
code/lib/jomjol_helper/Helper.cpp → code/components/jomjol_helper/Helper.cpp


+ 0 - 0
code/lib/jomjol_helper/Helper.h → code/components/jomjol_helper/Helper.h


+ 0 - 0
code/lib/jomjol_image_proc/CFindTemplate.cpp → code/components/jomjol_image_proc/CFindTemplate.cpp


+ 0 - 0
code/lib/jomjol_image_proc/CFindTemplate.h → code/components/jomjol_image_proc/CFindTemplate.h


+ 7 - 0
code/components/jomjol_image_proc/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES jomjol_helper jomjol_logfile)
+
+

+ 0 - 0
code/lib/jomjol_image_proc/bitmap_image.hpp → code/components/jomjol_image_proc/bitmap_image.hpp


Vissa filer visades inte eftersom för många filer har ändrats