فهرست منبع

Rolling 20220716

jomjol 3 سال پیش
والد
کامیت
9f72bf117e
42فایلهای تغییر یافته به همراه2457 افزوده شده و 100 حذف شده
  1. 5 0
      README.md
  2. BIN
      code/components/esp32-camera-master.zip
  3. 14 15
      code/components/esp32-camera-master/.github/workflows/build.yml
  4. 1 3
      code/components/esp32-camera-master/.github/workflows/upload_component.yml
  5. 36 15
      code/components/esp32-camera-master/CMakeLists.txt
  6. 58 0
      code/components/esp32-camera-master/Kconfig
  7. 3 0
      code/components/esp32-camera-master/README.md
  8. 6 2
      code/components/esp32-camera-master/conversions/esp_jpg_decode.c
  9. 5 0
      code/components/esp32-camera-master/conversions/jpge.cpp
  10. 6 14
      code/components/esp32-camera-master/conversions/to_bmp.c
  11. 5 15
      code/components/esp32-camera-master/conversions/to_jpg.cpp
  12. 15 2
      code/components/esp32-camera-master/driver/cam_hal.c
  13. 41 0
      code/components/esp32-camera-master/driver/esp_camera.c
  14. 17 0
      code/components/esp32-camera-master/driver/include/esp_camera.h
  15. 10 0
      code/components/esp32-camera-master/driver/include/sensor.h
  16. 5 0
      code/components/esp32-camera-master/driver/sccb.c
  17. 3 0
      code/components/esp32-camera-master/driver/sensor.c
  18. 5 0
      code/components/esp32-camera-master/examples/main/take_picture.c
  19. 1 4
      code/components/esp32-camera-master/idf_component.yml
  20. 404 0
      code/components/esp32-camera-master/sensors/bf20a6.c
  21. 6 5
      code/components/esp32-camera-master/sensors/gc0308.c
  22. 27 0
      code/components/esp32-camera-master/sensors/private_include/bf20a6.h
  23. 12 0
      code/components/esp32-camera-master/sensors/private_include/bf20a6_regs.h
  24. 158 0
      code/components/esp32-camera-master/sensors/private_include/bf20a6_settings.h
  25. 17 4
      code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h
  26. 2 1
      code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h
  27. 31 0
      code/components/esp32-camera-master/sensors/private_include/sc030iot.h
  28. 491 0
      code/components/esp32-camera-master/sensors/private_include/sc030iot_settings.h
  29. 31 0
      code/components/esp32-camera-master/sensors/private_include/sc101iot.h
  30. 257 0
      code/components/esp32-camera-master/sensors/private_include/sc101iot_settings.h
  31. 335 0
      code/components/esp32-camera-master/sensors/sc030iot.c
  32. 342 0
      code/components/esp32-camera-master/sensors/sc101iot.c
  33. 6 2
      code/components/esp32-camera-master/target/esp32/ll_cam.c
  34. 7 2
      code/components/esp32-camera-master/target/esp32s2/ll_cam.c
  35. 80 9
      code/components/esp32-camera-master/target/esp32s3/ll_cam.c
  36. 6 0
      code/components/esp32-camera-master/target/private_include/ll_cam.h
  37. 2 2
      code/main/version.cpp
  38. 2 3
      code/platformio.ini
  39. 3 0
      code/sdkconfig.esp32cam
  40. 2 2
      code/version.cpp
  41. BIN
      firmware/bootloader.bin
  42. BIN
      firmware/firmware.bin

+ 5 - 0
README.md

@@ -52,6 +52,11 @@ In other cases you can contact the developer via email: <img src="https://raw.gi
 
 
 
+##### Rolling (2022-07-16)
+
+- Updated esp32cam
+- Integrated new analog classificational CNN (from @haverland)
+
 ##### Rolling (2022-07-01)
 
 - Updated analog neural network file (`ana1000s2.tflite`)

BIN
code/components/esp32-camera-master.zip


+ 14 - 15
code/components/esp32-camera-master/.github/workflows/build.yml

@@ -8,26 +8,37 @@ on:
 jobs:
   build-master:
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        idf_target: ["esp32", "esp32s2", "esp32s3"]
     steps:
     - name: Checkout repo
       uses: actions/checkout@v2
       with:
         submodules: 'recursive'
     - name: esp-idf build
-      uses: espressif/esp-idf-ci-action@latest
+      uses: espressif/esp-idf-ci-action@main
       with:
+        target: ${{ matrix.idf_target }}
         path: 'examples'
 
-  build-release-v4_0:
+  build-release-v4_4:
+    name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }}
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        idf_ver: ["v4.4"]
+        idf_target: ["esp32", "esp32s2", "esp32s3"]
     steps:
     - name: Checkout repo
       uses: actions/checkout@v2
       with:
         submodules: 'recursive'
     - name: esp-idf build
-      uses: espressif/esp-idf-ci-action@release-v4.0
+      uses: espressif/esp-idf-ci-action@main
       with:
+        esp_idf_version: ${{ matrix.idf_ver }}
+        target: ${{ matrix.idf_target }}
         path: 'examples'
 
   build-release-v4_1:
@@ -65,15 +76,3 @@ jobs:
       uses: espressif/esp-idf-ci-action@release-v4.3
       with:
         path: 'examples'
-
-  build-release-v3_3:
-    runs-on: ubuntu-latest
-    steps:
-    - name: Checkout repo
-      uses: actions/checkout@v2
-      with:
-        submodules: 'recursive'
-    - name: esp-idf build
-      uses: espressif/esp-idf-ci-action@release-v3.3
-      with:
-        path: 'examples'

+ 1 - 3
code/components/esp32-camera-master/.github/workflows/upload_component.yml

@@ -10,12 +10,10 @@ jobs:
       - uses: actions/checkout@master
         with:
           submodules: "recursive"
-
       - name: Upload component to the component registry
         uses: espressif/github-actions/upload_components@master
         with:
           name: "esp32-camera"
-          version: "git"
           namespace: "espressif"
-          service_url: ${{ secrets.IDF_COMPONENT_API_URL }}
+          version: ${{ github.ref_name }}
           api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}

+ 36 - 15
code/components/esp32-camera-master/CMakeLists.txt

@@ -1,5 +1,29 @@
+# get IDF version for comparison
+set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")
+
+# set conversion sources
+set(COMPONENT_SRCS
+  conversions/yuv.c
+  conversions/to_jpg.cpp
+  conversions/to_bmp.c
+  conversions/jpge.cpp
+  conversions/esp_jpg_decode.c
+  )
+
+set(COMPONENT_PRIV_INCLUDEDIRS
+  conversions/private_include
+  )
+
+set(COMPONENT_ADD_INCLUDEDIRS
+  driver/include
+  conversions/include
+  )
+
+set(COMPONENT_REQUIRES driver)
+
+# set driver sources only for supported platforms
 if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
-  set(COMPONENT_SRCS
+  list(APPEND COMPONENT_SRCS
     driver/esp_camera.c
     driver/cam_hal.c
     driver/sccb.c
@@ -14,22 +38,14 @@ if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET ST
     sensors/gc2145.c
     sensors/gc032a.c
     sensors/bf3005.c
-    conversions/yuv.c
-    conversions/to_jpg.cpp
-    conversions/to_bmp.c
-    conversions/jpge.cpp
-    conversions/esp_jpg_decode.c
+    sensors/bf20a6.c
+    sensors/sc101iot.c
+    sensors/sc030iot.c
     )
 
-  set(COMPONENT_ADD_INCLUDEDIRS
-    driver/include
-    conversions/include
-    )
-
-  set(COMPONENT_PRIV_INCLUDEDIRS
+  list(APPEND COMPONENT_PRIV_INCLUDEDIRS
     driver/private_include
     sensors/private_include
-    conversions/private_include
     target/private_include
     )
 
@@ -58,8 +74,13 @@ if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET ST
       )
   endif()
 
-  set(COMPONENT_REQUIRES driver)
   set(COMPONENT_PRIV_REQUIRES freertos nvs_flash)
 
-  register_component()
+  set(min_version_for_esp_timer "4.2")
+  if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer)
+    list(APPEND COMPONENT_PRIV_REQUIRES esp_timer)
+  endif()
+
 endif()
+
+register_component()

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

@@ -69,6 +69,45 @@ menu "Camera configuration"
         help
             Enable this option if you want to use the BF3005.
             Disable this option to save memory.
+            
+    config BF20A6_SUPPORT
+        bool "Support BF20A6(BYD20A6) VGA"
+        default y
+        help
+            Enable this option if you want to use the BF20A6.
+            Disable this option to save memory.
+
+    config SC101IOT_SUPPORT
+        bool "Support SC101IOT HD"
+        default n
+        help
+            Enable this option if you want to use the SC101IOT.
+            Disable this option to save memory.
+
+    choice SC101_REGS_SELECT
+        prompt "SC101iot default regs"
+        default SC101IOT_720P_15FPS_ENABLED
+        depends on SC101IOT_SUPPORT
+        help
+            Currently SC010iot has several register sets available.
+            Select the one that matches your needs.
+
+        config SC101IOT_720P_15FPS_ENABLED
+            bool "xclk20M_720p_15fps"
+        help
+            Select this option means that when xclk is 20M, the frame rate is 15fps at 720p resolution.
+        config SC101IOT_VGA_25FPS_ENABLED
+            bool "xclk20M_VGA_25fps"
+        help
+            Select this option means that when xclk is 20M, the frame rate is 25fps at VGA resolution.
+    endchoice
+
+    config SC030IOT_SUPPORT
+        bool "Support SC030IOT VGA"
+        default y
+        help
+            Enable this option if you want to use the SC030IOT.
+            Disable this option to save memory.
 
     choice SCCB_HARDWARE_I2C_PORT
         bool "I2C peripheral to use for SCCB"
@@ -125,5 +164,24 @@ menu "Camera configuration"
         help
             Maximum value of DMA buffer
             Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent
+    
+    config CAMERA_CONVERTER_ENABLED
+        bool "Enable camera RGB/YUV converter"
+        depends on IDF_TARGET_ESP32S3
+        default n
+        help
+            Enable this option if you want to use RGB565/YUV422/YUV420/YUV411 format conversion.
 
+    choice CAMERA_CONV_PROTOCOL
+        bool "Camera converter protocol"
+        depends on CAMERA_CONVERTER_ENABLED
+        default LCD_CAM_CONV_BT601_ENABLED
+        help
+            Supports format conversion under both BT601 and BT709 standards.
+
+        config LCD_CAM_CONV_BT601_ENABLED
+            bool "BT601"
+        config LCD_CAM_CONV_BT709_ENABLED
+            bool "BT709"
+    endchoice
 endmenu

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

@@ -25,6 +25,9 @@ This repository hosts ESP32 series Soc compatible driver for image sensors. Addi
 | GC0308  | 640 x 480      | color      | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565                        | 1/6.5"   |
 | GC2145  | 1600 x 1200    | color      | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565                        | 1/5"     |
 | BF3005  | 640 x 480      | color      | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565                        | 1/4"     |
+| BF20A6  | 640 x 480      | color      | YUV/YCbCr422<br/>RAW Bayer                                   | 1/10"    |
+| SC101IOT| 1280 x 720     | color      | YUV/YCbCr422<br/>Raw RGB                                     | 1/4.2"   |
+| SC030IOT| 640 x 480      | color      | YUV/YCbCr422<br/>RAW Bayer                                   | 1/6.5"   |
 
 ## Important to Remember
 

+ 6 - 2
code/components/esp32-camera-master/conversions/esp_jpg_decode.c

@@ -21,6 +21,10 @@
 #include "tjpgd.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/tjpgd.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#include "esp32c3/rom/tjpgd.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/tjpgd.h"
 #else
 #error Target CONFIG_IDF_TARGET is not supported
 #endif
@@ -57,7 +61,7 @@ static const char * jd_errors[] = {
     "Not supported JPEG standard"
 };
 
-static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
+static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
 {
     uint16_t x = rect->left;
     uint16_t y = rect->top;
@@ -73,7 +77,7 @@ static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
     return 0;
 }
 
-static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len)
+static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len)
 {
     esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device;
     if (jpeg->len && len > (jpeg->len - jpeg->index)) {

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

@@ -29,7 +29,12 @@ namespace jpge {
         if(b){
             return b;
         }
+    // check if SPIRAM is enabled and allocate on SPIRAM if allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
         return heap_caps_malloc(nSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#else
+        return NULL;
+#endif
     }
     static inline void jpge_free(void *p) { free(p); }
 

+ 6 - 14
code/components/esp32-camera-master/conversions/to_bmp.c

@@ -21,19 +21,6 @@
 #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"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/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"
@@ -72,7 +59,12 @@ typedef struct {
 
 static void *_malloc(size_t size)
 {
+    // check if SPIRAM is enabled and allocate on SPIRAM if allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
     return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#endif
+    // try allocating in internal memory
+    return malloc(size);
 }
 
 //output buffer and image width
@@ -168,7 +160,7 @@ static bool _rgb565_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16
 }
 
 //input buffer
-static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
+static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
 {
     rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
     if(buf) {

+ 5 - 15
code/components/esp32-camera-master/conversions/to_jpg.cpp

@@ -21,21 +21,6 @@
 #include "jpge.h"
 #include "yuv.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"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/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 ""
@@ -50,7 +35,12 @@ static void *_malloc(size_t size)
     if(res) {
         return res;
     }
+
+    // check if SPIRAM is enabled and is allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
     return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#endif
+    return NULL;
 }
 
 static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line)

+ 15 - 2
code/components/esp32-camera-master/driver/cam_hal.c

@@ -18,8 +18,21 @@
 #include "ll_cam.h"
 #include "cam_hal.h"
 
-static const char *TAG = "cam_hal";
+#if (ESP_IDF_VERSION_MAJOR == 3) && (ESP_IDF_VERSION_MINOR == 3)
+#include "rom/ets_sys.h"
+#else
+#include "esp_timer.h"
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rom/ets_sys.h"  // will be removed in idf v5.0
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/ets_sys.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/ets_sys.h"
+#endif
+#endif // ESP_IDF_VERSION_MAJOR
+#define ESP_CAMERA_ETS_PRINTF ets_printf
 
+static const char *TAG = "cam_hal";
 static cam_obj_t *cam_obj = NULL;
 
 static const uint32_t JPEG_SOI_MARKER = 0xFFD8FF;  // written in little-endian for esp32
@@ -93,7 +106,7 @@ void IRAM_ATTR ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType
     if (xQueueSendFromISR(cam->event_queue, (void *)&cam_event, HPTaskAwoken) != pdTRUE) {
         ll_cam_stop(cam);
         cam->state = CAM_STATE_IDLE;
-        ESP_EARLY_LOGE(TAG, "EV-%s-OVF", cam_event==CAM_IN_SUC_EOF_EVENT ? "EOF" : "VSYNC");
+        ESP_CAMERA_ETS_PRINTF(DRAM_STR("cam_hal: EV-%s-OVF\r\n"), cam_event==CAM_IN_SUC_EOF_EVENT ? DRAM_STR("EOF") : DRAM_STR("VSYNC"));
     }
 }
 

+ 41 - 0
code/components/esp32-camera-master/driver/esp_camera.c

@@ -57,6 +57,15 @@
 #if CONFIG_BF3005_SUPPORT
 #include "bf3005.h"
 #endif
+#if CONFIG_BF20A6_SUPPORT
+#include "bf20a6.h"
+#endif
+#if CONFIG_SC101IOT_SUPPORT
+#include "sc101iot.h"
+#endif
+#if CONFIG_SC030IOT_SUPPORT
+#include "sc030iot.h"
+#endif
 
 #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
 #include "esp32-hal-log.h"
@@ -119,6 +128,15 @@ static const sensor_func_t g_sensors[] = {
 #if CONFIG_BF3005_SUPPORT
     {bf3005_detect, bf3005_init},
 #endif
+#if CONFIG_BF20A6_SUPPORT
+    {bf20a6_detect, bf20a6_init},
+#endif
+#if CONFIG_SC101IOT_SUPPORT
+    {sc101iot_detect, sc101iot_init},
+#endif
+#if CONFIG_SC030IOT_SUPPORT
+    {sc030iot_detect, sc030iot_init},
+#endif
 };
 
 static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model)
@@ -218,6 +236,23 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
     return ESP_OK;
 }
 
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+static pixformat_t get_output_data_format(camera_conv_mode_t conv_mode)
+{
+    pixformat_t format = PIXFORMAT_RGB565;
+    switch (conv_mode) {
+    case YUV422_TO_YUV420:
+        format = PIXFORMAT_YUV420;
+        break;
+    case YUV422_TO_RGB565: // default format is RGB565
+    default:
+        break;
+    }
+    ESP_LOGD(TAG, "Convert to %d format enabled", format);
+    return format;
+}
+#endif
+
 esp_err_t esp_camera_init(const camera_config_t *config)
 {
     esp_err_t err;
@@ -256,6 +291,7 @@ esp_err_t esp_camera_init(const camera_config_t *config)
 
     s_state->sensor.status.framesize = frame_size;
     s_state->sensor.pixformat = pix_format;
+
     ESP_LOGD(TAG, "Setting frame size to %dx%d", resolution[frame_size].width, resolution[frame_size].height);
     if (s_state->sensor.set_framesize(&s_state->sensor, frame_size) != 0) {
         ESP_LOGE(TAG, "Failed to set frame size");
@@ -263,6 +299,11 @@ esp_err_t esp_camera_init(const camera_config_t *config)
         goto fail;
     }
     s_state->sensor.set_pixformat(&s_state->sensor, pix_format);
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+    if(config->conv_mode) {
+        s_state->sensor.pixformat = get_output_data_format(config->conv_mode); // If conversion enabled, change the out data format by conversion mode
+    }
+#endif
 
     if (s_state->sensor.id.PID == OV2640_PID) {
         s_state->sensor.set_gainceiling(&s_state->sensor, GAINCEILING_2X);

+ 17 - 0
code/components/esp32-camera-master/driver/include/esp_camera.h

@@ -70,6 +70,7 @@
 #include "driver/ledc.h"
 #include "sensor.h"
 #include "sys/time.h"
+#include "sdkconfig.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -91,6 +92,19 @@ typedef enum {
     CAMERA_FB_IN_DRAM           /*!< Frame buffer is placed in internal DRAM */
 } camera_fb_location_t;
 
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+/**
+ * @brief Camera RGB\YUV conversion mode
+ */
+typedef enum {
+    CONV_DISABLE,
+    RGB565_TO_YUV422,
+        
+    YUV422_TO_RGB565,
+    YUV422_TO_YUV420
+} camera_conv_mode_t;
+#endif
+
 /**
  * @brief Configuration structure for camera initialization
  */
@@ -124,6 +138,9 @@ typedef struct {
     size_t fb_count;                /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed)  */
     camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */
     camera_grab_mode_t grab_mode;   /*!< When buffers should be filled */
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+    camera_conv_mode_t conv_mode;   /*!< RGB<->YUV Conversion mode */
+#endif
 } camera_config_t;
 
 /**

+ 10 - 0
code/components/esp32-camera-master/driver/include/sensor.h

@@ -27,6 +27,9 @@ typedef enum {
     GC032A_PID = 0x232a,
     GC0308_PID = 0x9b,
     BF3005_PID = 0x30,
+    BF20A6_PID = 0x20a6,
+    SC101IOT_PID = 0xda4a,
+    SC030IOT_PID = 0x9a46,
 } camera_pid_t;
 
 typedef enum {
@@ -40,6 +43,9 @@ typedef enum {
     CAMERA_GC032A,
     CAMERA_GC0308,
     CAMERA_BF3005,
+    CAMERA_BF20A6,
+    CAMERA_SC101IOT,
+    CAMERA_SC030IOT,
     CAMERA_MODEL_MAX,
     CAMERA_NONE,
 } camera_model_t;
@@ -55,11 +61,15 @@ typedef enum {
     GC032A_SCCB_ADDR   = 0x21,// 0x42 >> 1
     GC0308_SCCB_ADDR   = 0x21,// 0x42 >> 1
     BF3005_SCCB_ADDR   = 0x6E,
+    BF20A6_SCCB_ADDR   = 0x6E,
+    SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1
+    SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1
 } camera_sccb_addr_t;
 
 typedef enum {
     PIXFORMAT_RGB565,    // 2BPP/RGB565
     PIXFORMAT_YUV422,    // 2BPP/YUV422
+    PIXFORMAT_YUV420,    // 1.5BPP/YUV420
     PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
     PIXFORMAT_JPEG,      // JPEG/COMPRESSED
     PIXFORMAT_RGB888,    // 3BPP/RGB888

+ 5 - 0
code/components/esp32-camera-master/driver/sccb.c

@@ -25,6 +25,11 @@ static const char* TAG = "sccb";
 
 #include "driver/i2c.h"
 
+// support IDF 5.x
+#ifndef portTICK_RATE_MS
+#define portTICK_RATE_MS portTICK_PERIOD_MS
+#endif
+
 #define SCCB_FREQ               CONFIG_SCCB_CLK_FREQ  /*!< I2C master frequency*/
 #define WRITE_BIT               I2C_MASTER_WRITE      /*!< I2C master write */
 #define READ_BIT                I2C_MASTER_READ       /*!< I2C master read */

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

@@ -13,6 +13,9 @@ const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = {
     {CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false},
     {CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false},
     {CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false},
+    {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false},
+    {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false},
+    {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false},
 };
 
 const resolution_info_t resolution[FRAMESIZE_INVALID] = {

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

@@ -38,6 +38,11 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 
+// support IDF 5.x
+#ifndef portTICK_RATE_MS
+#define portTICK_RATE_MS portTICK_PERIOD_MS
+#endif
+
 #include "esp_camera.h"
 
 #define BOARD_WROVER_KIT 1

+ 1 - 4
code/components/esp32-camera-master/idf_component.yml

@@ -1,5 +1,2 @@
 description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.
-targets:
-  - esp32
-  - esp32s2
-  - esp32s3
+url: https://github.com/espressif/esp32-camera

+ 404 - 0
code/components/esp32-camera-master/sensors/bf20a6.c

@@ -0,0 +1,404 @@
+// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "sccb.h"
+#include "bf20a6.h"
+#include "bf20a6_regs.h"
+#include "bf20a6_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char *TAG = "bf20a6";
+#endif
+
+#define H8(v) ((v)>>8)
+#define L8(v) ((v)&0xff)
+
+//#define REG_DEBUG_ON
+
+static int read_reg(uint8_t slv_addr, const uint16_t reg)
+{
+    int ret = SCCB_Read(slv_addr, reg);
+    // ESP_LOGI(TAG, "READ Register 0x%02x VALUE: 0x%02x", reg, ret);
+#ifdef REG_DEBUG_ON
+    if (ret < 0) {
+        ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret);
+    }
+#endif
+    return ret;
+}
+
+static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value)
+{
+    int ret = SCCB_Write(slv_addr, reg, value);
+#ifdef REG_DEBUG_ON
+    if (ret < 0) {
+        ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret);
+    }
+#endif
+    return ret;
+}
+
+#ifdef DEBUG_PRINT_REG
+static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask)
+{
+    return (read_reg(slv_addr, reg) & mask) == mask;
+}
+
+static void print_regs(uint8_t slv_addr)
+{
+    vTaskDelay(pdMS_TO_TICKS(100));
+    ESP_LOGI(TAG, "REG list look ======================");
+    for (size_t i = 0xf0; i <= 0xfe; i++) {
+        ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+    }
+    ESP_LOGI(TAG, "\npage 0 ===");
+    write_reg(slv_addr, 0xfe, 0x00); // page 0
+    for (size_t i = 0x03; i <= 0x24; i++) {
+        ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+    }
+    for (size_t i = 0x40; i <= 0x95; i++) {
+        ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+    }
+    ESP_LOGI(TAG, "\npage 3 ===");
+    write_reg(slv_addr, 0xfe, 0x03); // page 3
+    for (size_t i = 0x01; i <= 0x43; i++) {
+        ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+    }
+}
+
+static int read_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
+{
+    int i = 0, ret = 0;
+    while (regs[i][0] != REGLIST_TAIL) {
+        if (regs[i][0] == REG_DLY) {
+            vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
+        } else {
+            ret = read_reg(slv_addr, regs[i][0]);
+        }
+        i++;
+    }
+    return ret;
+}
+#endif
+
+static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+    int ret = 0;
+
+    ret = SCCB_Read(sensor->slv_addr, reg);
+    if (ret < 0) {
+        return ret;
+    }
+    uint8_t mask = ((1 << length) - 1) << offset;
+    value = (ret & ~mask) | ((value << offset) & mask);
+    ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value);
+    return ret;
+}
+
+static int write_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
+{
+    int i = 0, ret = 0;
+    while (!ret && regs[i][0] != REGLIST_TAIL) {
+        if (regs[i][0] == REG_DLY) {
+            vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
+        } else {
+            ret = write_reg(slv_addr, regs[i][0], regs[i][1]);
+        }
+        i++;
+    }
+    return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+    int ret;
+    // Software Reset: clear all registers and reset them to their default values
+    ret = write_reg(sensor->slv_addr, RESET_RELATED, 0x01);
+    if (ret) {
+        ESP_LOGE(TAG, "Software Reset FAILED!");
+        return ret;
+    }
+    vTaskDelay(100 / portTICK_PERIOD_MS);
+
+    ret = write_regs(sensor->slv_addr, bf20a6_default_init_regs);
+    if (ret == 0) {
+        ESP_LOGD(TAG, "Camera defaults loaded");
+        vTaskDelay(100 / portTICK_PERIOD_MS);
+    }
+
+    // int test_value = read_regs(sensor->slv_addr, bf20a6_default_init_regs);
+
+    return ret;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+    int ret = 0;
+    switch (pixformat) {
+    case PIXFORMAT_YUV422:
+        set_reg_bits(sensor, 0x12, 0, 1, 0);
+        break;
+    case PIXFORMAT_RAW:
+        set_reg_bits(sensor, 0x12, 0, 1, 0x1);
+        break;
+    default:
+        ESP_LOGW(TAG, "set_pix unsupport format");
+        ret = -1;
+        break;
+    }
+    if (ret == 0) {
+        sensor->pixformat = pixformat;
+        ESP_LOGD(TAG, "Set pixformat to: %u", pixformat);
+    }
+
+    return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+    int ret = 0;
+    if (framesize > FRAMESIZE_VGA) {
+        return -1;
+    }
+    uint16_t w = resolution[framesize].width;
+    uint16_t h = resolution[framesize].height;
+
+    sensor->status.framesize = framesize;
+
+    // Write MSBs
+    ret |= SCCB_Write(sensor->slv_addr, 0x17, 0);
+    ret |= SCCB_Write(sensor->slv_addr, 0x18, w >> 2);
+
+    ret |= SCCB_Write(sensor->slv_addr, 0x19, 0);
+    ret |= SCCB_Write(sensor->slv_addr, 0x1a, h >> 2);
+
+    // Write LSBs
+    ret |= SCCB_Write(sensor->slv_addr, 0x1b, 0);
+
+    if ((w <= 320) && (h <= 240))     {
+        ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 4));
+        ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 4));
+
+        ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 4));
+
+        ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 4));
+
+    } else if ((w <= 640) && (h <= 480))     {
+        ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 8));
+        ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 8));
+
+        ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 8));
+
+        ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 8));
+    }
+
+    // Delay
+    vTaskDelay(30 / portTICK_PERIOD_MS);
+
+    return ret;
+}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    sensor->status.hmirror = enable;
+    //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
+    ret |= set_reg_bits(sensor, 0x4a, 3, 0x01, enable);
+    if (ret == 0) {
+        ESP_LOGD(TAG, "Set h-mirror to: %d", enable);
+    }
+    return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    sensor->status.vflip = enable;
+    //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
+    ret |= set_reg_bits(sensor, 0x4a, 2, 0x01, enable);
+    if (ret == 0) {
+        ESP_LOGD(TAG, "Set v-flip to: %d", enable);
+    }
+    return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int value)
+{
+    int ret = 0;
+    ret = write_reg(sensor->slv_addr, 0xb6, value);
+    if (ret == 0) {
+        sensor->status.colorbar = value;
+        ESP_LOGD(TAG, "Set colorbar to: %d", value);
+    }
+    return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    ret = SCCB_Write(sensor->slv_addr, 0x70, level);
+    if (ret == 0) {
+        ESP_LOGD(TAG, "Set sharpness to: %d", level);
+        sensor->status.sharpness = level;
+    }
+    return ret;
+}
+
+static int get_reg(sensor_t *sensor, int reg, int mask)
+{
+    int ret = 0;
+    if (mask > 0xFF) {
+        ESP_LOGE(TAG, "mask should not more than 0xff");
+    } else {
+        ret = read_reg(sensor->slv_addr, reg);
+    }
+    if (ret > 0) {
+        ret &= mask;
+    }
+    return ret;
+}
+
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+    int ret = 0;
+    if (mask > 0xFF) {
+        ESP_LOGE(TAG, "mask should not more than 0xff");
+    } else {
+        ret = read_reg(sensor->slv_addr, reg);
+    }
+    if (ret < 0) {
+        return ret;
+    }
+    value = (ret & ~mask) | (value & mask);
+
+    if (mask > 0xFF) {
+
+    } else {
+        ret = write_reg(sensor->slv_addr, reg, value);
+    }
+    return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+    // write_reg(sensor->slv_addr, 0xfe, 0x00);
+    sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x6f);
+    sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0xd6);
+    sensor->status.saturation = 0;
+    sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70);
+    sensor->status.denoise = 0;
+    sensor->status.ae_level = 0;
+    sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x13);
+    sensor->status.awb = 0;
+    sensor->status.dcw = 0;
+    sensor->status.agc = 0;
+    sensor->status.aec = 0;
+    sensor->status.hmirror = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01);
+    sensor->status.vflip = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02);
+    sensor->status.colorbar = 0;
+    sensor->status.bpc = 0;
+    sensor->status.wpc = 0;
+    sensor->status.raw_gma = 0;
+    sensor->status.lenc = 0;
+    sensor->status.quality = 0;
+    sensor->status.special_effect = 0;
+    sensor->status.wb_mode = 0;
+    sensor->status.awb_gain = 0;
+    sensor->status.agc_gain = 0;
+    sensor->status.aec_value = 0;
+    sensor->status.aec2 = 0;
+    return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val)
+{
+    ESP_LOGW(TAG, "dummy Unsupported");
+    return -1;
+}
+static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val)
+{
+    ESP_LOGW(TAG, "gainceiling Unsupported");
+    return -1;
+}
+
+int bf20a6_detect(int slv_addr, sensor_id_t *id)
+{
+    if (BF20A6_SCCB_ADDR == slv_addr) {
+        uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW);
+        uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH);
+        uint16_t PID = MIDH << 8 | MIDL;
+        if (BF20A6_PID == PID) {
+            id->PID = PID;
+            return PID;
+        } else {
+            ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+        }
+    }
+    return 0;
+}
+
+int bf20a6_init(sensor_t *sensor)
+{
+    sensor->init_status = init_status;
+    sensor->reset = reset;
+    sensor->set_pixformat = set_pixformat;
+    sensor->set_framesize = set_framesize;
+    sensor->set_contrast = set_dummy;
+    sensor->set_brightness = set_dummy;
+    sensor->set_saturation = set_dummy;
+    sensor->set_sharpness = set_sharpness;
+    sensor->set_denoise = set_dummy;
+    sensor->set_gainceiling = set_gainceiling_dummy;
+    sensor->set_quality = set_dummy;
+    sensor->set_colorbar = set_colorbar;
+    sensor->set_whitebal = set_dummy;
+    sensor->set_gain_ctrl = set_dummy;
+    sensor->set_exposure_ctrl = set_dummy;
+    sensor->set_hmirror = set_hmirror; // set_hmirror;
+    sensor->set_vflip = set_vflip; // set_vflip;
+
+    sensor->set_aec2 = set_dummy;
+    sensor->set_awb_gain = set_dummy;
+    sensor->set_agc_gain = set_dummy;
+    sensor->set_aec_value = set_dummy;
+
+    sensor->set_special_effect = set_dummy;
+    sensor->set_wb_mode = set_dummy;
+    sensor->set_ae_level = set_dummy;
+
+    sensor->set_dcw = set_dummy;
+    sensor->set_bpc = set_dummy;
+    sensor->set_wpc = set_dummy;
+
+    sensor->set_raw_gma = set_dummy;
+    sensor->set_lenc = set_dummy;
+
+    sensor->get_reg = get_reg;
+    sensor->set_reg = set_reg;
+    sensor->set_res_raw = NULL;
+    sensor->set_pll = NULL;
+    sensor->set_xclk = NULL;
+
+    ESP_LOGD(TAG, "BF20A6 Attached");
+    return 0;
+}

+ 6 - 5
code/components/esp32-camera-master/sensors/gc0308.c

@@ -88,10 +88,10 @@ static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t
     return ret;
 }
 
-static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2])
+static int write_regs(uint8_t slv_addr, const uint8_t (*regs)[2], size_t regs_size)
 {
     int i = 0, ret = 0;
-    while (!ret && regs[i][0] != REGLIST_TAIL) {
+    while (!ret && (i < regs_size)) {
         if (regs[i][0] == REG_DLY) {
             vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
         } else {
@@ -132,11 +132,12 @@ static int reset(sensor_t *sensor)
         ESP_LOGE(TAG, "Software Reset FAILED!");
         return ret;
     }
-    vTaskDelay(100 / portTICK_PERIOD_MS);
-    ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs);
+
+    vTaskDelay(80 / portTICK_PERIOD_MS);
+    ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs, sizeof(gc0308_sensor_default_regs)/(sizeof(uint8_t) * 2));
     if (ret == 0) {
         ESP_LOGD(TAG, "Camera defaults loaded");
-        vTaskDelay(100 / portTICK_PERIOD_MS);
+        vTaskDelay(80 / portTICK_PERIOD_MS);
         write_reg(sensor->slv_addr, 0xfe, 0x00);
 #ifdef CONFIG_IDF_TARGET_ESP32
         set_reg_bits(sensor->slv_addr, 0x28, 4, 0x07, 1);  //frequency division for esp32, ensure pclk <= 15MHz

+ 27 - 0
code/components/esp32-camera-master/sensors/private_include/bf20a6.h

@@ -0,0 +1,27 @@
+
+#ifndef __BF20A6_H__
+#define __BF20A6_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ *     0:       Can't detect this sensor
+ *     Nonzero: This sensor has been detected
+ */
+int bf20a6_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ *      Always 0
+ */
+int bf20a6_init(sensor_t *sensor);
+
+#endif // __BF20A6_H__

+ 12 - 0
code/components/esp32-camera-master/sensors/private_include/bf20a6_regs.h

@@ -0,0 +1,12 @@
+/*
+ * BF20A6 register definitions.
+ */
+#ifndef __BF20A6_REG_REGS_H__
+#define __BF20A6_REG_REGS_H__
+
+#define SENSOR_ID_HIGH 0XFC
+#define SENSOR_ID_LOW 0XFD
+#define RESET_RELATED   0XF2
+
+
+#endif //__BF20A6_REG_REGS_H__

+ 158 - 0
code/components/esp32-camera-master/sensors/private_include/bf20a6_settings.h

@@ -0,0 +1,158 @@
+
+#include <stdint.h>
+
+#define REG_DLY 0xffff
+#define REGLIST_TAIL 0xffff /* Array end token */
+
+static const uint16_t bf20a6_default_init_regs[][2] = {
+    {0xf2,0x01},
+    {0x12,0x20},
+    {0x3a,0x00},
+    {0xe1,0x92},
+    {0xe3,0x12},// PLL Control, important for framerate(choice: 0x02\0x12\0x22\0x32\0x82)
+    {0xe0,0x00},
+    {0x2a,0x98},
+    {0xcd,0x17},
+    {0xc0,0x10},
+    {0xc6,0x1d},
+    {0x10,0x35},
+    {0xe2,0x09},
+    {0xe4,0x72},
+    {0xe5,0x22},
+    {0xe6,0x24},
+    {0xe7,0x64},
+    {0xe8,0xa2}, // DVP:a2},  SPI:f2        VDDIO=1.8V,E8[2]=1},VDDIO=2.8V,E8[2]=0},
+    {0x4a,0x00},
+    {0x00,0x03},
+    {0x1f,0x02},
+    {0x22,0x02},
+    {0x0c,0x31},
+
+    {0x00,0x00},
+    {0x60,0x81},
+    {0x61,0x81},
+
+    {0xa0,0x08},
+    {0x01,0x1a},
+    // {0x01,0x1a},
+    // {0x01,0x1a},
+    // {0x02,0x15},
+    // {0x02,0x15},
+    {0x02,0x15},
+    {0x13,0x08},
+    {0x8a,0x96},
+    {0x8b,0x06},
+    {0x87,0x18},
+
+
+    {0x34,0x48}, // lens
+    {0x35,0x40},
+    {0x36,0x40},
+
+    {0x71,0x44},
+    {0x72,0x48},
+    {0x74,0xa2},
+    {0x75,0xa9},
+    {0x78,0x12},
+    {0x79,0xa0},
+    {0x7a,0x94},
+    {0x7c,0x97},
+    {0x40,0x30},
+    {0x41,0x30},
+    {0x42,0x28},
+    {0x43,0x1f},
+    {0x44,0x1c},
+    {0x45,0x16},
+    {0x46,0x13},
+    {0x47,0x10},
+    {0x48,0x0D},
+    {0x49,0x0C},
+    {0x4B,0x0A},
+    {0x4C,0x0B},
+    {0x4E,0x09},
+    {0x4F,0x08},
+    {0x50,0x08},
+
+
+    {0x5f,0x29},
+    {0x23,0x33},
+    {0xa1,0x10}, // AWB
+    {0xa2,0x0d},
+    {0xa3,0x30},
+    {0xa4,0x06},
+    {0xa5,0x22},
+    {0xa6,0x56},
+    {0xa7,0x18},
+    {0xa8,0x1a},
+    {0xa9,0x12},
+    {0xaa,0x12},
+    {0xab,0x16},
+    {0xac,0xb1},
+    {0xba,0x12},
+    {0xbb,0x12},
+    {0xad,0x12},
+    {0xae,0x56},
+    {0xaf,0x0a},
+    {0x3b,0x30},
+    {0x3c,0x12},
+    {0x3d,0x22},
+    {0x3e,0x3f},
+    {0x3f,0x28},
+    {0xb8,0xc3},
+    {0xb9,0xa3},
+    {0x39,0x47}, // pure color threshold
+    {0x26,0x13},
+    {0x27,0x16},
+    {0x28,0x14},
+    {0x29,0x18},
+    {0xee,0x0d},
+
+        
+    {0x13,0x05},
+    {0x24,0x3C},
+    {0x81,0x20},
+    {0x82,0x40},
+    {0x83,0x30},
+    {0x84,0x58},
+    {0x85,0x30},
+    {0x92,0x08},
+    {0x86,0x80},
+    {0x8a,0x96},
+    {0x91,0xff},
+    {0x94,0x62},
+    {0x9a,0x18}, // outdoor threshold
+    {0xf0,0x45}, // integral time control, important for framerate(choice: 0x46\0x45\0x44..)
+    {0x51,0x17}, // color normal
+    {0x52,0x03},
+    {0x53,0x5F},
+    {0x54,0x47},
+    {0x55,0x66},
+    {0x56,0x0F},
+    {0x7e,0x14},
+    {0x57,0x36}, // color
+    {0x58,0x2A},
+    {0x59,0xAA},
+    {0x5a,0xA8},
+    {0x5b,0x43},
+    {0x5c,0x10},
+    {0x5d,0x00},
+    {0x7d,0x36},
+    {0x5e,0x10},
+
+    {0xd6,0x88}, // contrast
+    {0xd5,0x20}, // bright
+    {0xb0,0x84}, // low light ctrl in gray section
+    {0xb5,0x08}, // the threshold of GLB_GAIN
+    {0xb1,0xc8}, // saturation
+    {0xb2,0xc0},
+    {0xb3,0xd0},
+    {0xb4,0xB0},
+
+    {0x32,0x10},
+    // {0x8a,0x00},
+    // {0x8b,0x10},
+    {0xa0,0x09},
+    {0x00,0x03},
+    {0x0b,0x02},
+    {REGLIST_TAIL, 0x00},
+};

+ 17 - 4
code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h

@@ -3,10 +3,9 @@
 
 #include <stdint.h>
 
-#define REG_DLY 0xffff
-#define REGLIST_TAIL 0x0000 /* Array end token */
+#define REG_DLY 0xff
 
-static const uint16_t gc0308_sensor_default_regs[][2] = {
+static const uint8_t gc0308_sensor_default_regs[][2] = {
     {0xfe, 0x00},
     {0xec, 0x20},
     {0x05, 0x00},
@@ -239,7 +238,21 @@ static const uint16_t gc0308_sensor_default_regs[][2] = {
     {0x65, 0xd3},
     {0x66, 0x60},
     {0xfe, 0x00},
-    {REGLIST_TAIL, 0x00},
+
+    {0x01, 0x32},   //frame setting                            
+	{0x02, 0x0c},                                  
+	{0x0f, 0x01},                                                                                                                     
+	{0xe2, 0x00},  
+	{0xe3, 0x78},                                                             
+	{0xe4, 0x00},      
+	{0xe5, 0xfe},  
+	{0xe6, 0x01},  
+	{0xe7, 0xe0},  
+	{0xe8, 0x01},  
+	{0xe9, 0xe0},  
+	{0xea, 0x01},  
+	{0xeb, 0xe0},
+	{0xfe, 0x00},
 };
 
 #endif

+ 2 - 1
code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h

@@ -42,7 +42,8 @@ static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
     {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE
 
     //sys reset
-    {0x3000, 0x00},
+    {0x3000, 0x20}, // reset MCU
+    {REG_DLY, 10}, // delay 10ms
     {0x3002, 0x1c},
 
     //clock enable

+ 31 - 0
code/components/esp32-camera-master/sensors/private_include/sc030iot.h

@@ -0,0 +1,31 @@
+/*
+ *
+ * SC030IOT DVP driver.
+ *
+ */
+#ifndef __SC030IOT_H__
+#define __SC030IOT_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ *     0:       Can't detect this sensor
+ *     Nonzero: This sensor has been detected
+ */
+int sc030iot_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ *      Always 0
+ */
+int sc030iot_init(sensor_t *sensor);
+
+#endif // __SC030IOT_H__

+ 491 - 0
code/components/esp32-camera-master/sensors/private_include/sc030iot_settings.h

@@ -0,0 +1,491 @@
+//version: V01P00_20220303
+//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16
+//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI
+//port  0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P
+//I2C Mode    :0:Normal 8Addr,8Data//  1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data
+//I2C Mode    :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data
+//Out Format  :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR
+//MCLK Speed  :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M
+//pin  :BIT0 pwdn// BIT1:reset
+//avdd  0:3.3V// 1:2.5V// 2:1.8V
+//dovdd  0:2.8V// 1:2.5V// 2:1.8V
+//dvdd  0:1.8V// 1:1.5V// 2:1.2V
+
+/*
+[DataBase]
+DBName=Dothinkey
+
+[Vendor]
+VendorName=SmartSens
+
+[Sensor]
+SensorName=SC031IOT
+width=640
+height=480
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xfa
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x46
+outformat=0
+mclk=20
+avdd=2.80000
+dovdd=2.800000
+dvdd=1.5
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.0000
+VPP=0.000000
+*/
+#include <stdint.h>
+
+static const uint8_t sc030iot_default_init_regs[][2] = {
+    {0xf0, 0x30},
+    {0x01, 0xff},
+    {0x02, 0xff},
+    {0x22, 0x07},
+    {0x19, 0xff},
+    {0x3f, 0x82},
+    {0x30, 0x02},
+    {0xf0, 0x01},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0x72, 0x20},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x75, 0x10},
+    {0x76, 0x81},
+    {0x77, 0x88},
+    {0x78, 0xe1},
+    {0x79, 0x01},
+    {0xf5, 0x01},
+    {0xf4, 0x0a},
+    {0xf0, 0x36},
+    {0x37, 0x79},
+    {0x31, 0x82},
+    {0x3e, 0x60},
+    {0x30, 0xf0},
+    {0x33, 0x33},
+    {0xf0, 0x32},
+    {0x48, 0x02},
+    {0xf0, 0x33},
+    {0x02, 0x12},
+    {0x7c, 0x02},
+    {0x7d, 0x0e},
+    {0xa2, 0x04},
+    {0x5e, 0x06},
+    {0x5f, 0x0a},
+    {0x0b, 0x58},
+    {0x06, 0x38},
+    {0xf0, 0x32},
+    {0x48, 0x02},
+    {0xf0, 0x39},
+    {0x02, 0x70},
+    {0xf0, 0x45},
+    {0x09, 0x1c},
+    {0xf0, 0x37},
+    {0x22, 0x0d},
+    {0xf0, 0x33},
+    {0x33, 0x10},
+    {0xb1, 0x80},
+    {0x34, 0x40},
+    {0x0b, 0x54},
+    {0xb2, 0x78},
+    {0xf0, 0x36},
+    {0x11, 0x80},
+    {0xf0, 0x30},
+    {0x38, 0x44},
+    {0xf0, 0x33},
+    {0xb3, 0x51},
+    {0x01, 0x10},
+    {0x0b, 0x6c},
+    {0x06, 0x24},
+    {0xf0, 0x36},
+    {0x31, 0x82},
+    {0x3e, 0x60},
+    {0x30, 0xf0},
+    {0x33, 0x33},
+    {0xf0, 0x34},
+    {0x9f, 0x02},
+    {0xa6, 0x40},
+    {0xa7, 0x47},
+    {0xe8, 0x5f},
+    {0xa8, 0x51},
+    {0xa9, 0x44},
+    {0xe9, 0x36},
+    {0xf0, 0x33},
+    {0xb3, 0x51},
+    {0x64, 0x17},
+    {0x90, 0x01},
+    {0x91, 0x03},
+    {0x92, 0x07},
+    {0x01, 0x10},
+    {0x93, 0x10},
+    {0x94, 0x10},
+    {0x95, 0x10},
+    {0x96, 0x01},
+    {0x97, 0x07},
+    {0x98, 0x1f},
+    {0x99, 0x10},
+    {0x9a, 0x20},
+    {0x9b, 0x28},
+    {0x9c, 0x28},
+    {0xf0, 0x36},
+    {0x70, 0x54},
+    {0xb6, 0x40},
+    {0xb7, 0x41},
+    {0xb8, 0x43},
+    {0xb9, 0x47},
+    {0xba, 0x4f},
+    {0xb0, 0x8b},
+    {0xb1, 0x8b},
+    {0xb2, 0x8b},
+    {0xb3, 0x9b},
+    {0xb4, 0xb8},
+    {0xb5, 0xf0},
+    {0x7e, 0x41},
+    {0x7f, 0x47},
+    {0x77, 0x80},
+    {0x78, 0x84},
+    {0x79, 0x8a},
+    {0xa0, 0x47},
+    {0xa1, 0x5f},
+    {0x96, 0x43},
+    {0x97, 0x44},
+    {0x98, 0x54},
+    {0xf0, 0x00},
+    {0xf0, 0x01},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0xf0, 0x36},
+    {0x37, 0x74},
+    {0xf0, 0x3f},
+    {0x03, 0xa1},
+    {0xf0, 0x36},//cvbs_off
+    {0x11, 0x80},
+    {0xf0, 0x01},
+    {0x79, 0xc1},
+    {0xf0, 0x37},
+    {0x24, 0x21},
+    {0xf0, 0x36},
+    {0x41, 0x00},
+    {0xea, 0x09},
+    {0xeb, 0x03},
+    {0xec, 0x19},
+    {0xed, 0x38},
+    {0xe9, 0x30},
+    {0xf0, 0x33},
+    {0x33, 0x00},
+    {0x34, 0x00},
+    {0xb1, 0x00},
+    {0xf0, 0x00},
+    {0xe0, 0x04},
+    {0xf0, 0x01},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0xf0, 0x36},
+    {0x32, 0x44},
+    {0xf0, 0x36},
+    {0x3e, 0xe0},
+    {0x70, 0x56},
+    {0x7c, 0x43},
+    {0x7d, 0x47},
+    {0x74, 0x00},
+    {0x75, 0x00},
+    {0x76, 0x00},
+    {0xa0, 0x47},
+    {0xa1, 0x5f},
+    {0x96, 0x22},
+    {0x97, 0x22},
+    {0x98, 0x22},
+    {0xf0, 0x00},
+    {0x72, 0x38},
+    {0x7a, 0x80},
+    {0x85, 0x18},
+    {0x9b, 0x35},
+    {0x9e, 0x20},
+    {0xd0, 0x66},
+    {0xd1, 0x34},
+    {0Xd3, 0x44},
+    {0xd6, 0x44},
+    {0xb0, 0x41},
+    {0xb2, 0x48},
+    {0xb3, 0xf4},
+    {0xb4, 0x0b},
+    {0xb5, 0x78},
+    {0xba, 0xff},
+    {0xbb, 0xc0},
+    {0xbc, 0x90},
+    {0xbd, 0x3a},
+    {0xc1, 0x67},
+    {0xf0, 0x01},
+    {0x20, 0x11},
+    {0x23, 0x90},
+    {0x24, 0x15},
+    {0x25, 0x87},
+    {0xbc, 0x9f},
+    {0xbd, 0x3a},
+    {0x48, 0xe6},
+    {0x49, 0xc0},
+    {0x4a, 0xd0},
+    {0x4b, 0x48},
+
+    // [cvbs_on]
+    {0xf0, 0x36},
+    {0x11, 0x00},
+    {0xf0, 0x01},
+    {0x79, 0xf1},
+
+    // [cvbs_off]
+    {0xf0, 0x36},
+    {0x11, 0x80},
+    {0xf0, 0x01},
+    {0x79, 0xc1},
+};
+
+/*
+[Sensor]
+SensorName=SC031IOT
+width=640
+height=480
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xfa
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x46
+outformat=0
+mclk=27
+avdd=2.80000
+dovdd=2.800000
+dvdd=1.5
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.0000
+VPP=0.000000
+*/
+/* 27M MCLK, 30fps
+static const uint8_t sc030iot_default_init_regs[][2] = {
+    {0xf0, 0x30},
+    {0x01, 0xff},
+    {0x02, 0xff},
+    {0x22, 0x07},
+    {0x19, 0xff},
+    {0x3f, 0x82},
+    {0x30, 0x02},
+    {0xf0, 0x01},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0x72, 0x20},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x75, 0x10},
+    {0x76, 0x81},
+    {0x77, 0x88},
+    {0x78, 0xe1},
+    {0x79, 0x01},
+    {0xf5, 0x01},
+    {0xf4, 0x0a},
+    {0xf0, 0x36},
+    {0x37, 0x79},
+    {0x31, 0x82},
+    {0x3e, 0x60},
+    {0x30, 0xf0},
+    {0x33, 0x33},
+    {0xf0, 0x32},
+    {0x48, 0x02},
+    {0xf0, 0x33},
+    {0x02, 0x12},
+    {0x7c, 0x02},
+    {0x7d, 0x0e},
+    {0xa2, 0x04},
+    {0x5e, 0x06},
+    {0x5f, 0x0a},
+    {0x0b, 0x58},
+    {0x06, 0x38},
+    {0xf0, 0x32},
+    {0x48, 0x02},
+    {0xf0, 0x39},
+    {0x02, 0x70},
+    {0xf0, 0x45},
+    {0x09, 0x1c},
+    {0xf0, 0x37},
+    {0x22, 0x0d},
+    {0xf0, 0x33},
+    {0x33, 0x10},
+    {0xb1, 0x80},
+    {0x34, 0x40},
+    {0x0b, 0x54},
+    {0xb2, 0x78},
+    {0xf0, 0x36},
+    {0x11, 0x80},
+    {0xf0, 0x30},
+    {0x38, 0x44},
+    {0xf0, 0x33},
+    {0xb3, 0x51},
+    {0x01, 0x10},
+    {0x0b, 0x6c},
+    {0x06, 0x24},
+    {0xf0, 0x36},
+    {0x31, 0x82},
+    {0x3e, 0x60},
+    {0x30, 0xf0},
+    {0x33, 0x33},
+    {0xf0, 0x34},
+    {0x9f, 0x02},
+    {0xa6, 0x40},
+    {0xa7, 0x47},
+    {0xe8, 0x5f},
+    {0xa8, 0x51},
+    {0xa9, 0x44},
+    {0xe9, 0x36},
+    {0xf0, 0x33},
+    {0xb3, 0x51},
+    {0x64, 0x17},
+    {0x90, 0x01},
+    {0x91, 0x03},
+    {0x92, 0x07},
+    {0x01, 0x10},
+    {0x93, 0x10},
+    {0x94, 0x10},
+    {0x95, 0x10},
+    {0x96, 0x01},
+    {0x97, 0x07},
+    {0x98, 0x1f},
+    {0x99, 0x10},
+    {0x9a, 0x20},
+    {0x9b, 0x28},
+    {0x9c, 0x28},
+    {0xf0, 0x36},
+    {0x70, 0x54},
+    {0xb6, 0x40},
+    {0xb7, 0x41},
+    {0xb8, 0x43},
+    {0xb9, 0x47},
+    {0xba, 0x4f},
+    {0xb0, 0x8b},
+    {0xb1, 0x8b},
+    {0xb2, 0x8b},
+    {0xb3, 0x9b},
+    {0xb4, 0xb8},
+    {0xb5, 0xf0},
+    {0x7e, 0x41},
+    {0x7f, 0x47},
+    {0x77, 0x80},
+    {0x78, 0x84},
+    {0x79, 0x8a},
+    {0xa0, 0x47},
+    {0xa1, 0x5f},
+    {0x96, 0x43},
+    {0x97, 0x44},
+    {0x98, 0x54},
+    {0xf0, 0x00},
+    {0xf0, 0x01},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0xf0, 0x36},
+    {0x37, 0x74},
+    {0xf0, 0x3f},
+    {0x03, 0x93},
+    {0xf0, 0x36},//cvbs_off
+    {0x11, 0x80},
+    {0xf0, 0x01},
+    {0x79, 0xc1},
+    {0xf0, 0x37},
+    {0x24, 0x21},
+    {0xf0, 0x36},
+    {0x41, 0x00},
+    {0xe9, 0x2c},
+    {0xf0, 0x33},
+    {0x33, 0x00},
+    {0x34, 0x00},
+    {0xb1, 0x00},
+    {0xf0, 0x00},
+    {0xe0, 0x04},
+    {0xf0, 0x01},
+    {0x73, 0x00},
+    {0x74, 0xe0},
+    {0x70, 0x00},
+    {0x71, 0x80},
+    {0xf0, 0x36},
+    {0x32, 0x44},
+    {0xf0, 0x36},
+    {0x3e, 0xe0},
+    {0x70, 0x56},
+    {0x7c, 0x43},
+    {0x7d, 0x47},
+    {0x74, 0x00},
+    {0x75, 0x00},
+    {0x76, 0x00},
+    {0xa0, 0x47},
+    {0xa1, 0x5f},
+    {0x96, 0x22},
+    {0x97, 0x22},
+    {0x98, 0x22},
+    {0xf0, 0x00},
+    {0x72, 0x38},
+    {0x7a, 0x80},
+    {0x85, 0x18},
+    {0x9b, 0x35},
+    {0x9e, 0x20},
+    {0xd0, 0x66},
+    {0xd1, 0x34},
+    {0Xd3, 0x44},
+    {0xd6, 0x44},
+    {0xb0, 0x41},
+    {0xb2, 0x48},
+    {0xb3, 0xf4},
+    {0xb4, 0x0b},
+    {0xb5, 0x78},
+    {0xba, 0xff},
+    {0xbb, 0xc0},
+    {0xbc, 0x90},
+    {0xbd, 0x3a},
+    {0xc1, 0x67},
+    {0xf0, 0x01},
+    {0x20, 0x11},
+    {0x23, 0x90},
+    {0x24, 0x15},
+    {0x25, 0x87},
+    {0xbc, 0x9f},
+    {0xbd, 0x3a},
+    {0x48, 0xe6},
+    {0x49, 0xc0},
+    {0x4a, 0xd0},
+    {0x4b, 0x48},
+
+    // [cvbs_on]
+    {0xf0, 0x36},
+    {0x11, 0x00},
+    {0xf0, 0x01},
+    {0x79, 0xf1},
+
+    // [cvbs_off]
+    {0xf0, 0x36},
+    {0x11, 0x80},
+    {0xf0, 0x01},
+    {0x79, 0xc1},
+};
+
+*/

+ 31 - 0
code/components/esp32-camera-master/sensors/private_include/sc101iot.h

@@ -0,0 +1,31 @@
+/*
+ *
+ * SC101IOT DVP driver.
+ *
+ */
+#ifndef __SC101IOT_H__
+#define __SC101IOT_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ *     0:       Can't detect this sensor
+ *     Nonzero: This sensor has been detected
+ */
+int sc101iot_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ *      Always 0
+ */
+int sc101iot_init(sensor_t *sensor);
+
+#endif // __SC101IOT_H__

+ 257 - 0
code/components/esp32-camera-master/sensors/private_include/sc101iot_settings.h

@@ -0,0 +1,257 @@
+//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16
+//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI
+//port  0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P
+//I2C Mode    :0:Normal 8Addr,8Data//  1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data
+//I2C Mode    :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data
+//Out Format  :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR
+//MCLK Speed  :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M
+//pin  :BIT0 pwdn// BIT1:reset
+//avdd  0:2.8V// 1:2.5V// 2:1.8V
+//dovdd  0:2.8V// 1:2.5V// 2:1.8V
+//dvdd  0:1.8V// 1:1.5V// 2:1.2V
+/*
+[DataBase]
+DBName=DemoSens
+
+[Vendor]
+VendorName=SmartSens
+I2C_CRC=0
+
+[Sensor]
+SensorName=SC101AP_raw
+width=1280
+height=720
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xda
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x4a
+outformat=0
+mclk=20
+avdd=2.800000
+dovdd=2.800000
+dvdd=1.200000
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.00
+VPP=0.000000
+*/
+#include <stdint.h>
+
+static const uint8_t sc101iot_default_init_regs[][2] = {
+#if CONFIG_SC101IOT_720P_15FPS_ENABLED // 720P+YUV422+15FPS sensor default regs
+/* Here are some test results:
+#   size    xclk    fps    pic       pclk                       
+#  ------- ------- ------ --------- ------- --- --- --- --- --- 
+#   720p    4       3      err                                  
+#   720p    8       5      normal    15                         
+#   720p    10      7.8    normal    19                         
+#   720p    20      15     warning   37.5                       
+#   VGA     8       6      normal    
+#   VGA     20      16     normal    
+
+*/
+    {0xf0, 0x30},
+    {0x01, 0xff},
+    {0x02, 0xe0},
+    {0x30, 0x10},
+    {0x3f, 0x81},
+    {0xf0, 0x00},
+    {0x70, 0x6b},
+    {0x72, 0x30},
+    {0x84, 0xb4},
+    {0x8b, 0x00},
+    {0x8c, 0x20},
+    {0x8d, 0x02},
+    {0x8e, 0xec},
+    {0x9e, 0x10},
+    {0xb0, 0xc1},
+    {0xc8, 0x10},
+    {0xc9, 0x10},
+    {0xc6, 0x00},
+    {0xe0, 0x0f},
+    {0xb5, 0xf0},
+    {0xde, 0x80},
+    {0xb5, 0xf0},
+    {0xde, 0x80},
+    {0xb2, 0x50},
+    {0xb3, 0xfc},
+    {0xb4, 0x40},
+    {0xb5, 0xc0},
+    {0xb6, 0x50},
+    {0xb7, 0xfc},
+    {0xb8, 0x40},
+    {0xb9, 0xc0},
+    {0xba, 0xff},
+    {0xbb, 0xcc},
+    {0xbc, 0xa9},
+    {0xbd, 0x7d},
+    {0xc1, 0x77},
+    {0xf0, 0x01},
+    {0x70, 0x02},
+    {0x71, 0x02},
+    {0x72, 0x50},
+    {0x73, 0x02},
+    {0x74, 0xd2},
+    {0x75, 0x20},
+    {0x76, 0x81},
+    {0x77, 0x8c},
+    {0x78, 0x81},
+    {0xf4, 0x01},
+    {0xf5, 0x00},
+    {0xf6, 0x00},
+    {0xf0, 0x36},
+    {0x40, 0x03},
+    {0x41, 0x01},
+    {0xf0, 0x39},
+    {0x02, 0x70},
+    {0xf0, 0x32},
+    {0x41, 0x00},
+    {0x43, 0x01},
+    {0x48, 0x02},
+    {0xf0, 0x45},
+    {0x09, 0x20},
+    {0xf0, 0x33},
+    {0x33, 0x10},
+    {0xf0, 0x30},
+    {0x38, 0x44},
+    {0xf0, 0x39},
+    {0x07, 0x00},
+    {0x08, 0x19},
+    {0x47, 0x00},
+    {0x48, 0x00},
+    {0xf0, 0x37},
+    {0x24, 0x31},
+    {0xf0, 0x34},
+    {0x9f, 0x02},
+    {0xa6, 0x51},
+    {0xa7, 0x57},
+    {0xe8, 0x5f},
+    {0xa8, 0x50},
+    {0xa9, 0x50},
+    {0xe9, 0x50},
+    {0xf0, 0x33},
+    {0xb3, 0x58},
+    {0xb2, 0x78},
+    {0xf0, 0x34},
+    {0x9f, 0x03},
+    {0xa6, 0x51},
+    {0xa7, 0x57},
+    {0xaa, 0x01},
+    {0xab, 0x28},
+    {0xac, 0x01},
+    {0xad, 0x38},
+    {0xf0, 0x33},
+    {0x0a, 0x01},
+    {0x0b, 0x28},
+    {0xf0, 0x33},
+    {0x64, 0x0f},
+    {0xec, 0x51},
+    {0xed, 0x57},
+    {0x06, 0x58},
+    {0xe9, 0x58},
+    {0xeb, 0x68},
+    {0xf0, 0x33},
+    {0x64, 0x0f},
+    {0xf0, 0x36},
+    {0x70, 0xdf},
+    {0xb6, 0x40},
+    {0xb7, 0x51},
+    {0xb8, 0x53},
+    {0xb9, 0x57},
+    {0xba, 0x5f},
+    {0xb0, 0x84},
+    {0xb1, 0x82},
+    {0xb2, 0x84},
+    {0xb3, 0x88},
+    {0xb4, 0x90},
+    {0xb5, 0x90},
+    {0xf0, 0x36},
+    {0x7e, 0x50},
+    {0x7f, 0x51},
+    {0x77, 0x81},
+    {0x78, 0x86},
+    {0x79, 0x89},
+    {0xf0, 0x36},
+    {0x70, 0xdf},
+    {0x9c, 0x51},
+    {0x9d, 0x57},
+    {0x90, 0x54},
+    {0x91, 0x54},
+    {0x92, 0x56},
+    {0xf0, 0x36},
+    {0xa0, 0x51},
+    {0xa1, 0x57},
+    {0x96, 0x33},
+    {0x97, 0x43},
+    {0x98, 0x43},
+    {0xf0, 0x36},
+    {0x70, 0xdf},
+    {0x7c, 0x40},
+    {0x7d, 0x53},
+    {0x74, 0xd0},
+    {0x75, 0xf0},
+    {0x76, 0xf0},
+    {0xf0, 0x37},
+    {0x0f, 0xd5},
+    {0x7a, 0x40},
+    {0x7b, 0x57},
+    {0x71, 0x09},
+    {0x72, 0x09},
+    {0x73, 0x05},
+    {0xf0, 0x33},
+    {0x01, 0x44},
+    {0xf0, 0x36},
+    {0x37, 0xfb},
+    {0xf0, 0x36},
+    {0x3c, 0x0d},
+    {0xf0, 0x33},
+    {0x14, 0x95},
+    {0xf0, 0x33},
+    {0x8f, 0x80},
+    {0xf0, 0x37},
+    {0x27, 0x14},
+    {0x28, 0x03},
+    {0xf0, 0x36},
+    {0x37, 0xf4},
+    {0xf0, 0x33},
+    {0x01, 0x44},
+    {0xf0, 0x36},
+    {0x79, 0x89},
+    {0xf0, 0x34},
+    {0xac, 0x01},
+    {0xad, 0x40},
+    {0xf0, 0x33},
+    {0xeb, 0x70},
+    {0xf0, 0x34},
+    {0xa8, 0x50},
+    {0xa9, 0x50},
+    {0xf0, 0x33},
+    {0xb3, 0x58},
+    {0xf0, 0x36},
+    {0x11, 0x80},
+    {0xf0, 0x36},
+    {0x41, 0x51},
+    {0xf0, 0x3f},
+    {0x03, 0x09},	  
+    {0xf0, 0x32},
+    {0x0c, 0x06},
+    {0x0d, 0x82},
+    {0x0e, 0x02},
+    {0x0f, 0xee},
+    {0xf0, 0x36},
+    {0xea, 0x09},
+    {0xeb, 0xf5},
+    {0xec, 0x11},
+    {0xed, 0x27},
+    {0xe9, 0x20},
+#endif
+};

+ 335 - 0
code/components/esp32-camera-master/sensors/sc030iot.c

@@ -0,0 +1,335 @@
+/*
+ * SC030IOT driver.
+ * 
+ * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "sccb.h"
+#include "xclk.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "sc030iot.h"
+#include "sc030iot_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char* TAG = "sc030";
+#endif
+
+#define SC030_SENSOR_ID_HIGH_REG    0XF7
+#define SC030_SENSOR_ID_LOW_REG     0XF8
+#define SC030_MAX_FRAME_WIDTH       (640)
+#define SC030_MAX_FRAME_HIGH        (480)
+
+// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int get_reg(sensor_t *sensor, int reg, int reg_value_mask)
+{
+    int ret = 0;
+    uint8_t reg_high = (reg>>8) & 0xFF;
+    uint8_t reg_low = reg & 0xFF;
+
+    if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+        return -1;
+    }
+
+    ret = SCCB_Read(sensor->slv_addr, reg_low);
+    if(ret > 0){
+        ret &= reg_value_mask;
+    }
+    return ret;
+}
+
+// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+    int ret = 0;
+    uint8_t reg_high = (reg>>8) & 0xFF;
+    uint8_t reg_low = reg & 0xFF;
+
+    if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+        return -1;
+    }
+    
+    ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF);
+    return ret;
+}
+
+static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len)
+{
+    int i=0, res = 0;
+    while (i<regs_entry_len) {
+        res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]);
+        if (res) {
+            return res;
+        }
+        i++;
+    }
+    return res;
+}
+
+static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+    int ret = 0;
+    ret = get_reg(sensor, reg, 0xff);
+    if(ret < 0){
+        return ret;
+    }
+    uint8_t mask = ((1 << length) - 1) << offset;
+    value = (ret & ~mask) | ((value << offset) & mask);
+    ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value);
+    return ret;
+}
+
+#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;}
+#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;}
+#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    if(enable) {
+        SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on
+    } else {
+        SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off
+    }
+
+    return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    if(enable) {
+        SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on
+    } else {
+        SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off
+    }
+
+    return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable test pattern mode
+
+    return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement
+    WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value
+    WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit
+
+    return ret;
+}
+
+static int set_agc_gain(sensor_t *sensor, int gain)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control
+    WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1
+    WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2
+    WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3
+    WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4
+    
+    return ret;
+}
+
+static int set_aec_value(sensor_t *sensor, int value)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control
+    WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target
+
+    return ret;
+}
+
+static int set_awb_gain(sensor_t *sensor, int value)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control
+    WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain
+    WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain
+    return ret;
+}
+
+static int set_saturation(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control
+    WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128)
+    WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128)
+    return ret;
+}
+
+static int set_contrast(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control
+    WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64)
+    return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+    int ret = set_regs(sensor, sc030iot_default_init_regs, sizeof(sc030iot_default_init_regs)/(sizeof(uint8_t) * 2));
+    
+    // Delay
+    vTaskDelay(50 / portTICK_PERIOD_MS);
+
+    // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor
+    // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff));
+    if (ret) {
+        ESP_LOGE(TAG, "reset fail");
+    }
+    return ret;
+}
+
+static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h)
+{
+    int ret = 0;
+    //sc:H_start={0x0172[1:0],0x0170},H_end={0x0172[5:4],0x0171},
+    WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff);
+    WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff);
+    WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x03) | (((offset_x+w)>>4)&0x30));
+
+    //sc:V_start={0x0175[1:0],0x0173},H_end={0x0175[5:4],0x0174},
+    WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff);
+    WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff);
+    WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x03) | (((offset_y+h)>>4)&0x30));
+
+    vTaskDelay(10 / portTICK_PERIOD_MS);
+
+    return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+    uint16_t w = resolution[framesize].width;
+    uint16_t h = resolution[framesize].height;
+    if(w>SC030_MAX_FRAME_WIDTH || h > SC030_MAX_FRAME_HIGH) {
+        goto err; 
+    }
+
+    uint16_t offset_x = (640-w) /2;   
+    uint16_t offset_y = (480-h) /2;
+    
+    if(set_window(sensor, offset_x, offset_y, w, h)) {
+        goto err; 
+    }
+    
+    sensor->status.framesize = framesize;
+    return 0;
+err:
+    ESP_LOGE(TAG, "frame size err");
+    return -1;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+    int ret=0;
+    sensor->pixformat = pixformat;
+
+    switch (pixformat) {
+    case PIXFORMAT_RGB565:
+    case PIXFORMAT_RAW:
+    case PIXFORMAT_GRAYSCALE:
+        ESP_LOGE(TAG, "Not support");
+        break;
+    case PIXFORMAT_YUV422: // For now, sc030/sc031 sensor only support YUV422.
+        break;
+    default:
+        return -1;
+    }
+
+    return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+    return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val){ return -1; }
+
+static int set_xclk(sensor_t *sensor, int timer, int xclk)
+{
+    int ret = 0;
+    sensor->xclk_freq_hz = xclk * 1000000U;
+    ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
+    return ret;
+}
+
+int sc030iot_detect(int slv_addr, sensor_id_t *id)
+{
+    if (SC030IOT_SCCB_ADDR == slv_addr) {
+        uint8_t MIDL = SCCB_Read(slv_addr, SC030_SENSOR_ID_LOW_REG);
+        uint8_t MIDH = SCCB_Read(slv_addr, SC030_SENSOR_ID_HIGH_REG);
+        uint16_t PID = MIDH << 8 | MIDL;
+        if (SC030IOT_PID == PID) {
+            id->PID = PID;
+            return PID;
+        } else {
+            ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+        }
+    }
+    return 0;
+}
+
+int sc030iot_init(sensor_t *sensor)
+{
+    // Set function pointers
+    sensor->reset = reset;
+    sensor->init_status = init_status;
+    sensor->set_pixformat = set_pixformat;
+    sensor->set_framesize = set_framesize;
+    
+    sensor->set_saturation= set_saturation;
+    sensor->set_colorbar = set_colorbar;
+    sensor->set_hmirror = set_hmirror;
+    sensor->set_vflip = set_vflip;
+    sensor->set_sharpness = set_sharpness;
+    sensor->set_agc_gain = set_agc_gain;
+    sensor->set_aec_value = set_aec_value;
+    sensor->set_awb_gain = set_awb_gain;
+    sensor->set_contrast = set_contrast;
+    //not supported
+    sensor->set_denoise = set_dummy;
+    sensor->set_quality = set_dummy;
+    sensor->set_special_effect = set_dummy;
+    sensor->set_wb_mode = set_dummy;
+    sensor->set_ae_level = set_dummy;
+    
+
+    sensor->get_reg = get_reg;
+    sensor->set_reg = set_reg;
+    sensor->set_xclk = set_xclk;
+    
+    ESP_LOGD(TAG, "sc030iot Attached");
+
+    return 0;
+}

+ 342 - 0
code/components/esp32-camera-master/sensors/sc101iot.c

@@ -0,0 +1,342 @@
+/*
+ * SC101IOT driver.
+ * 
+ * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "sccb.h"
+#include "xclk.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "sc101iot.h"
+#include "sc101iot_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char* TAG = "sc101";
+#endif
+
+#define SC101_SENSOR_ID_HIGH_REG    0XF7
+#define SC101_SENSOR_ID_LOW_REG     0XF8
+#define SC101_MAX_FRAME_WIDTH       (1280)
+#define SC101_MAX_FRAME_HIGH        (720)
+
+// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int get_reg(sensor_t *sensor, int reg, int mask)
+{
+    int ret = 0;
+    uint8_t reg_high = (reg>>8) & 0xFF;
+    uint8_t reg_low = reg & 0xFF;
+
+    if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+        return -1;
+    }
+
+    ret = SCCB_Read(sensor->slv_addr, reg_low);
+    if(ret > 0){
+        ret &= mask;
+    }
+    return ret;
+}
+
+// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+    int ret = 0;
+    uint8_t reg_high = (reg>>8) & 0xFF;
+    uint8_t reg_low = reg & 0xFF;
+
+    if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+        return -1;
+    }
+    
+    ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF);
+    return ret;
+}
+
+static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len)
+{
+    int i=0, res = 0;
+    while (i<regs_entry_len) {
+        res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]);
+        if (res) {
+            return res;
+        }
+        i++;
+    }
+    return res;
+}
+
+static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+    int ret = 0;
+    ret = get_reg(sensor, reg, 0xff);
+    if(ret < 0){
+        return ret;
+    }
+    uint8_t mask = ((1 << length) - 1) << offset;
+    value = (ret & ~mask) | ((value << offset) & mask);
+    ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value);
+    return ret;
+}
+
+#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;}
+#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;}
+#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    if(enable) {
+        SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // enable mirror
+    } else {
+        SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // disable mirror
+    }
+
+    return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    if(enable) {
+        SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on
+    } else {
+        SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off
+    }
+
+    return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable colorbar mode
+    return ret;
+}
+
+static int set_raw_gma(sensor_t *sensor, int enable)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00f5, 1, 1, enable & 0xff); // enable gamma compensation
+
+    return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement
+    WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value
+    WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit
+
+    return ret;
+}
+
+static int set_agc_gain(sensor_t *sensor, int gain)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control
+    WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1
+    WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2
+    WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3
+    WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4
+    
+    return ret;
+}
+
+static int set_aec_value(sensor_t *sensor, int value)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control
+    WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target
+
+    return ret;
+}
+
+static int set_awb_gain(sensor_t *sensor, int value)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control
+    WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain
+    WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain
+    return ret;
+}
+
+static int set_saturation(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control
+    WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128)
+    WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128)
+    return ret;
+}
+
+static int set_contrast(sensor_t *sensor, int level)
+{
+    int ret = 0;
+    SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control
+    WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64)
+    return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+    int ret = set_regs(sensor, sc101iot_default_init_regs, sizeof(sc101iot_default_init_regs)/(sizeof(uint8_t) * 2));
+    
+    // Delay
+    vTaskDelay(50 / portTICK_PERIOD_MS);
+
+    // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor
+    // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff));
+    if (ret) {
+        ESP_LOGE(TAG, "reset fail");
+    }
+    return ret;
+}
+
+static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h)
+{
+    int ret = 0;
+    //sc:H_start={0x0172[3:0],0x0170},H_end={0x0172[7:4],0x0171},
+    WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff);
+    WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff);
+    WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x0f) | (((offset_x+w)>>4)&0xf0));
+
+    //sc:V_start={0x0175[3:0],0x0173},H_end={0x0175[7:4],0x0174},
+    WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff);
+    WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff);
+    WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x0f) | (((offset_y+h)>>4)&0xf0));
+
+    vTaskDelay(10 / portTICK_PERIOD_MS);
+
+    return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+    uint16_t w = resolution[framesize].width;
+    uint16_t h = resolution[framesize].height;
+    if(w>SC101_MAX_FRAME_WIDTH || h > SC101_MAX_FRAME_HIGH) {
+        goto err; 
+    }
+
+    uint16_t offset_x = (SC101_MAX_FRAME_WIDTH-w) /2;   
+    uint16_t offset_y = (SC101_MAX_FRAME_HIGH-h) /2;
+    
+    if(set_window(sensor, offset_x, offset_y, w, h)) {
+        goto err; 
+    }
+    
+    sensor->status.framesize = framesize;
+    return 0;
+err:
+    ESP_LOGE(TAG, "frame size err");
+    return -1;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+    int ret=0;
+    sensor->pixformat = pixformat;
+
+    switch (pixformat) {
+    case PIXFORMAT_RGB565:
+    case PIXFORMAT_RAW:
+    case PIXFORMAT_GRAYSCALE:
+        ESP_LOGE(TAG, "Not support");
+        break;
+    case PIXFORMAT_YUV422: // For now, sc101 sensor only support YUV422.
+        break;
+    default:
+        ret = -1;
+    }
+
+    return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+    return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val){ return -1; }
+
+static int set_xclk(sensor_t *sensor, int timer, int xclk)
+{
+    int ret = 0;
+    sensor->xclk_freq_hz = xclk * 1000000U;
+    ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
+    return ret;
+}
+
+int sc101iot_detect(int slv_addr, sensor_id_t *id)
+{
+    if (SC101IOT_SCCB_ADDR == slv_addr) {
+        uint8_t MIDL = SCCB_Read(slv_addr, SC101_SENSOR_ID_LOW_REG);
+        uint8_t MIDH = SCCB_Read(slv_addr, SC101_SENSOR_ID_HIGH_REG);
+        uint16_t PID = MIDH << 8 | MIDL;
+        if (SC101IOT_PID == PID) {
+            id->PID = PID;
+            return PID;
+        } else {
+            ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+        }
+    }
+    return 0;
+}
+
+int sc101iot_init(sensor_t *sensor)
+{
+    // Set function pointers
+    sensor->reset = reset;
+    sensor->init_status = init_status;
+    sensor->set_pixformat = set_pixformat;
+    sensor->set_framesize = set_framesize;
+    sensor->set_hmirror = set_hmirror;
+    sensor->set_vflip = set_vflip;
+    sensor->set_colorbar = set_colorbar;
+    sensor->set_raw_gma = set_raw_gma;
+    sensor->set_sharpness = set_sharpness;
+    sensor->set_agc_gain = set_agc_gain;
+    sensor->set_aec_value = set_aec_value;
+    sensor->set_awb_gain = set_awb_gain;
+    sensor->set_saturation= set_saturation;
+    sensor->set_contrast = set_contrast;
+
+    sensor->set_denoise = set_dummy;
+    sensor->set_quality = set_dummy;
+    sensor->set_special_effect = set_dummy;
+    sensor->set_wb_mode = set_dummy;
+    sensor->set_ae_level = set_dummy;
+
+
+    sensor->get_reg = get_reg;
+    sensor->set_reg = set_reg;
+    sensor->set_xclk = set_xclk;
+    
+    ESP_LOGD(TAG, "sc101iot Attached");
+
+    return 0;
+}

+ 6 - 2
code/components/esp32-camera-master/target/esp32/ll_cam.c

@@ -34,10 +34,14 @@ static inline int gpio_ll_get_level(gpio_dev_t *hw, int gpio_num)
 #include "xclk.h"
 #include "cam_hal.h"
 
+#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3)
+#include "esp_rom_gpio.h"
+#endif
+
 #if (ESP_IDF_VERSION_MAJOR >= 5)
 #define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE
 #define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
 #endif
 
 static const char *TAG = "esp32 ll_cam";
@@ -233,7 +237,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
     //DBG_PIN_SET(0);
 }
 
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
 {
     I2S0.conf.rx_start = 0;
     I2S_ISR_DISABLE(in_suc_eof);

+ 7 - 2
code/components/esp32-camera-master/target/esp32s2/ll_cam.c

@@ -21,10 +21,15 @@
 #include "xclk.h"
 #include "cam_hal.h"
 
+#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3)
+#include "esp_rom_gpio.h"
+#endif
+
 #if (ESP_IDF_VERSION_MAJOR >= 5)
 #define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE
 #define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
+#define ets_delay_us(a) esp_rom_delay_us(a)
 #endif
 
 static const char *TAG = "s2 ll_cam";
@@ -70,7 +75,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
     }
 }
 
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
 {
     I2S0.conf.rx_start = 0;
 

+ 80 - 9
code/components/esp32-camera-master/target/esp32s3/ll_cam.c

@@ -22,10 +22,15 @@
 #include "soc/gdma_reg.h"
 #include "ll_cam.h"
 #include "cam_hal.h"
+#include "esp_rom_gpio.h"
 
 #if (ESP_IDF_VERSION_MAJOR >= 5)
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
-#define gpio_matrix_out(a,b,c,d) gpio_iomux_out(a,b,c)
+#include "soc/gpio_sig_map.h"
+#include "soc/gpio_periph.h"
+#include "soc/io_mux_reg.h"
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
+#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d)
+#define ets_delay_us(a) esp_rom_delay_us(a)
 #endif
 
 static const char *TAG = "s3 ll_cam";
@@ -74,7 +79,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
     }
 }
 
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
 {
     if (cam->jpeg_mode || !cam->psram_mode) {
         GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 0;
@@ -170,6 +175,7 @@ static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
     }
 
     GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0;
+    // GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2;
 
     GDMA.channel[cam->dma_num].in.peri_sel.sel = 5;
     //GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15
@@ -178,8 +184,52 @@ static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
     return ESP_OK;
 }
 
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t *config)
+{
+    esp_err_t ret = ESP_OK;
+
+    switch (config->conv_mode) {
+    case YUV422_TO_YUV420:
+        if (config->pixel_format != PIXFORMAT_YUV422) {
+            ret = ESP_FAIL;
+        } else {
+            ESP_LOGI(TAG, "YUV422 to YUV420 mode");
+            LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1;
+            LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
+            LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 1;
+        }
+        break;
+    case YUV422_TO_RGB565:
+        if (config->pixel_format != PIXFORMAT_YUV422) {
+            ret = ESP_FAIL;
+        } else {
+            ESP_LOGI(TAG, "YUV422 to RGB565 mode");
+            LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
+            LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
+            LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0;
+        }
+        break;
+    default:
+        break;
+    }
+#if CONFIG_LCD_CAM_CONV_BT709_ENABLED
+    LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 1;
+#else
+    LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0;
+#endif
+    LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0;
+    LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0;
+    LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1;
+    LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 1;
+    cam->conv_mode = config->conv_mode;
+    return ret;
+}
+#endif
+
 esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
 {
+    esp_err_t ret = ESP_OK;
     if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) {
         REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
         REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
@@ -215,15 +265,21 @@ esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
 
     LCD_CAM.cam_rgb_yuv.val = 0;
 
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+    if (config->conv_mode) {
+        ret = ll_cam_converter_config(cam, config);
+        if(ret != ESP_OK) {
+            return ret;
+        }
+    }
+#endif
+
     LCD_CAM.cam_ctrl.cam_update = 1;
     LCD_CAM.cam_ctrl1.cam_start = 1;
 
-    esp_err_t err = ll_cam_dma_init(cam);
-    if(err != ESP_OK) {
-        return err;
-    }
+    ret = ll_cam_dma_init(cam);
     
-    return ESP_OK;
+    return ret;
 }
 
 void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en)
@@ -417,6 +473,7 @@ size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in,
         }
         return len / 2;
     }
+    
 
     // just memcpy
     memcpy(out, in, len);
@@ -433,8 +490,22 @@ esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_
         }
         cam->fb_bytes_per_pixel = 1;       // frame buffer stores Y8
     } else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
-            cam->in_bytes_per_pixel = 2;       // camera sends YU/YV
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+        switch (cam->conv_mode) {
+        case YUV422_TO_YUV420:
+            cam->in_bytes_per_pixel = 1.5;       // for DMA receive
+            cam->fb_bytes_per_pixel = 1.5;       // frame buffer stores YUV420
+            break;
+        case YUV422_TO_RGB565:
+        default:
+            cam->in_bytes_per_pixel = 2;       // for DMA receive
             cam->fb_bytes_per_pixel = 2;       // frame buffer stores YU/YV/RGB565
+            break;
+        }
+#else 
+        cam->in_bytes_per_pixel = 2;       // for DMA receive
+        cam->fb_bytes_per_pixel = 2;       // frame buffer stores YU/YV/RGB565
+#endif
     } else if (pix_format == PIXFORMAT_JPEG) {
         cam->in_bytes_per_pixel = 1;
         cam->fb_bytes_per_pixel = 1;

+ 6 - 0
code/components/esp32-camera-master/target/private_include/ll_cam.h

@@ -116,8 +116,14 @@ typedef struct {
     //for RGB/YUV modes
     uint16_t width;
     uint16_t height;
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+    float in_bytes_per_pixel;
+    float fb_bytes_per_pixel;
+    camera_conv_mode_t conv_mode;
+#else 
     uint8_t in_bytes_per_pixel;
     uint8_t fb_bytes_per_pixel;
+#endif
     uint32_t fb_size;
 
     cam_state_t state;

+ 2 - 2
code/main/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="60cdee2";
+const char* GIT_REV="058e943";
 const char* GIT_TAG="";
 const char* GIT_BRANCH="rolling";
-const char* BUILD_TIME="2022-06-26 21:24";
+const char* BUILD_TIME="2022-07-16 07:55";

+ 2 - 3
code/platformio.ini

@@ -14,9 +14,8 @@ src_dir = main
 
 
 [env:esp32cam]
-;platform = espressif32@2.1.0
-;platform = espressif32@3.5.0
-platform = espressif32
+platform = espressif32@4.4.0
+;platform = espressif32
 board = esp32cam
 framework = espidf
 

+ 3 - 0
code/sdkconfig.esp32cam

@@ -1233,6 +1233,9 @@ CONFIG_OV2640_SUPPORT=y
 # CONFIG_GC032A_SUPPORT is not set
 # CONFIG_GC0308_SUPPORT is not set
 # CONFIG_BF3005_SUPPORT is not set
+CONFIG_BF20A6_SUPPORT=y
+# CONFIG_SC101IOT_SUPPORT is not set
+CONFIG_SC030IOT_SUPPORT=y
 # CONFIG_SCCB_HARDWARE_I2C_PORT0 is not set
 CONFIG_SCCB_HARDWARE_I2C_PORT1=y
 CONFIG_SCCB_CLK_FREQ=100000

+ 2 - 2
code/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="60cdee2";
+const char* GIT_REV="058e943";
 const char* GIT_TAG="";
 const char* GIT_BRANCH="rolling";
-const char* BUILD_TIME="2022-06-26 21:23";
+const char* BUILD_TIME="2022-07-16 07:54";

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin