├── .github └── workflows │ ├── build.yml │ ├── stale.yml │ └── upload_component.yml ├── .gitignore ├── CMakeLists.txt ├── Kconfig ├── LICENSE ├── README.md ├── conversions ├── esp_jpg_decode.c ├── include │ ├── esp_jpg_decode.h │ └── img_converters.h ├── jpge.cpp ├── private_include │ ├── jpge.h │ └── yuv.h ├── to_bmp.c ├── to_jpg.cpp └── yuv.c ├── driver ├── cam_hal.c ├── esp_camera.c ├── include │ ├── esp_camera.h │ └── sensor.h ├── private_include │ ├── cam_hal.h │ ├── sccb.h │ └── xclk.h ├── sccb-ng.c ├── sccb.c └── sensor.c ├── examples └── camera_example │ ├── CMakeLists.txt │ ├── main │ ├── CMakeLists.txt │ ├── idf_component.yml │ └── take_picture.c │ └── sdkconfig.defaults ├── idf_component.yml ├── library.json ├── sensors ├── bf20a6.c ├── bf3005.c ├── gc0308.c ├── gc032a.c ├── gc2145.c ├── mega_ccm.c ├── nt99141.c ├── ov2640.c ├── ov3660.c ├── ov5640.c ├── ov7670.c ├── ov7725.c ├── private_include │ ├── bf20a6.h │ ├── bf20a6_regs.h │ ├── bf20a6_settings.h │ ├── bf3005.h │ ├── bf3005_regs.h │ ├── gc0308.h │ ├── gc0308_regs.h │ ├── gc0308_settings.h │ ├── gc032a.h │ ├── gc032a_regs.h │ ├── gc032a_settings.h │ ├── gc2145.h │ ├── gc2145_regs.h │ ├── gc2145_settings.h │ ├── mega_ccm.h │ ├── mega_ccm_regs.h │ ├── mega_ccm_settings.h │ ├── nt99141.h │ ├── nt99141_regs.h │ ├── nt99141_settings.h │ ├── ov2640.h │ ├── ov2640_regs.h │ ├── ov2640_settings.h │ ├── ov3660.h │ ├── ov3660_regs.h │ ├── ov3660_settings.h │ ├── ov5640.h │ ├── ov5640_regs.h │ ├── ov5640_settings.h │ ├── ov7670.h │ ├── ov7670_regs.h │ ├── ov7725.h │ ├── ov7725_regs.h │ ├── sc030iot.h │ ├── sc030iot_settings.h │ ├── sc031gs.h │ ├── sc031gs_settings.h │ ├── sc101iot.h │ └── sc101iot_settings.h ├── sc030iot.c ├── sc031gs.c └── sc101iot.c ├── target ├── esp32 │ └── ll_cam.c ├── esp32s2 │ ├── ll_cam.c │ └── private_include │ │ └── tjpgd.h ├── esp32s3 │ └── ll_cam.c ├── jpeg_include │ └── tjpgd.h ├── private_include │ └── ll_cam.h ├── tjpgd.c └── xclk.c └── test ├── CMakeLists.txt ├── component.mk ├── pictures ├── test_inside.jpeg ├── test_outside.jpeg └── testimg.jpeg └── test_camera.c /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build examples 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | 8 | jobs: 9 | build-examples: 10 | name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }} 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | idf_ver: ["release-v5.0", "release-v5.1", "release-v5.2", "release-v5.3", "latest"] 15 | idf_target: ["esp32", "esp32s2", "esp32s3", "esp32c2", "esp32c3"] 16 | container: espressif/idf:${{ matrix.idf_ver }} 17 | steps: 18 | - uses: actions/checkout@v1 19 | with: 20 | submodules: 'true' 21 | - name: esp-idf build 22 | env: 23 | IDF_TARGET: ${{ matrix.idf_target }} 24 | shell: bash 25 | working-directory: examples/camera_example 26 | run: | 27 | . ${IDF_PATH}/export.sh 28 | export PEDANTIC_FLAGS="-DIDF_CI_BUILD -Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" 29 | export EXTRA_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" 30 | export EXTRA_CXXFLAGS="${PEDANTIC_FLAGS}" 31 | idf.py build 32 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Mark stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | - cron: '20 9 * * *' 11 | 12 | jobs: 13 | stale: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | issues: write 18 | pull-requests: write 19 | 20 | steps: 21 | - uses: actions/stale@v3 22 | with: 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | stale-issue-message: 'This issue appears to be stale. Please close it if its no longer valid.' 25 | stale-pr-message: 'This pull request appears to be stale. Please close it if its no longer valid.' 26 | stale-issue-label: 'no-issue-activity' 27 | stale-pr-label: 'no-pr-activity' 28 | -------------------------------------------------------------------------------- /.github/workflows/upload_component.yml: -------------------------------------------------------------------------------- 1 | name: Push component to https://components.espressif.com 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | jobs: 7 | upload_components: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@master 11 | with: 12 | submodules: "recursive" 13 | - name: Upload component to the component registry 14 | uses: espressif/upload-components-ci-action@v1 15 | with: 16 | name: "esp32-camera" 17 | namespace: "espressif" 18 | version: ${{ github.ref_name }} 19 | api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | .vscode 3 | **/build 4 | **/sdkconfig 5 | **/sdkconfig.old 6 | **/dependencies.lock -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # get IDF version for comparison 2 | set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") 3 | 4 | # set conversion sources 5 | set(srcs 6 | conversions/yuv.c 7 | conversions/to_jpg.cpp 8 | conversions/to_bmp.c 9 | conversions/jpge.cpp 10 | conversions/esp_jpg_decode.c 11 | ) 12 | 13 | set(priv_include_dirs 14 | conversions/private_include 15 | ) 16 | 17 | set(include_dirs 18 | driver/include 19 | conversions/include 20 | ) 21 | 22 | set(COMPONENT_REQUIRES driver) 23 | 24 | # set driver sources only for supported platforms 25 | if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") 26 | list(APPEND srcs 27 | driver/esp_camera.c 28 | driver/cam_hal.c 29 | driver/sensor.c 30 | sensors/ov2640.c 31 | sensors/ov3660.c 32 | sensors/ov5640.c 33 | sensors/ov7725.c 34 | sensors/ov7670.c 35 | sensors/nt99141.c 36 | sensors/gc0308.c 37 | sensors/gc2145.c 38 | sensors/gc032a.c 39 | sensors/bf3005.c 40 | sensors/bf20a6.c 41 | sensors/sc101iot.c 42 | sensors/sc030iot.c 43 | sensors/sc031gs.c 44 | sensors/mega_ccm.c 45 | ) 46 | 47 | list(APPEND priv_include_dirs 48 | driver/private_include 49 | sensors/private_include 50 | target/private_include 51 | ) 52 | 53 | if(IDF_TARGET STREQUAL "esp32") 54 | list(APPEND srcs 55 | target/xclk.c 56 | target/esp32/ll_cam.c 57 | ) 58 | endif() 59 | 60 | if(IDF_TARGET STREQUAL "esp32s2") 61 | list(APPEND srcs 62 | target/xclk.c 63 | target/esp32s2/ll_cam.c 64 | target/tjpgd.c 65 | ) 66 | 67 | list(APPEND priv_include_dirs 68 | target/esp32s2/private_include 69 | ) 70 | endif() 71 | 72 | if(IDF_TARGET STREQUAL "esp32s3") 73 | list(APPEND srcs 74 | target/esp32s3/ll_cam.c 75 | ) 76 | endif() 77 | 78 | set(priv_requires freertos nvs_flash) 79 | 80 | set(min_version_for_esp_timer "4.2") 81 | if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer) 82 | list(APPEND priv_requires esp_timer) 83 | endif() 84 | 85 | # include the SCCB I2C driver 86 | # this uses either the legacy I2C API or the newwer version from IDF v5.4 87 | # as this features a method to obtain the I2C driver from a port number 88 | if (idf_version VERSION_GREATER_EQUAL "5.4") 89 | list(APPEND srcs driver/sccb-ng.c) 90 | else() 91 | list(APPEND srcs driver/sccb.c) 92 | endif() 93 | 94 | endif() 95 | 96 | # CONFIG_ESP_ROM_HAS_JPEG_DECODE is available from IDF v4.4 but 97 | # previous IDF supported chips already support JPEG decoder, hence okay to use this 98 | if(idf_version VERSION_GREATER_EQUAL "4.4" AND NOT CONFIG_ESP_ROM_HAS_JPEG_DECODE) 99 | list(APPEND srcs 100 | target/tjpgd.c 101 | ) 102 | list(APPEND priv_include_dirs 103 | target/jpeg_include/ 104 | ) 105 | endif() 106 | 107 | idf_component_register( 108 | SRCS ${srcs} 109 | INCLUDE_DIRS ${include_dirs} 110 | PRIV_INCLUDE_DIRS ${priv_include_dirs} 111 | REQUIRES driver # due to include of driver/gpio.h in esp_camera.h 112 | PRIV_REQUIRES ${priv_requires} 113 | ) 114 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "Camera configuration" 2 | 3 | config OV7670_SUPPORT 4 | bool "Support OV7670 VGA" 5 | default y 6 | help 7 | Enable this option if you want to use the OV7670. 8 | Disable this option to save memory. 9 | 10 | config OV7725_SUPPORT 11 | bool "Support OV7725 VGA" 12 | default y 13 | help 14 | Enable this option if you want to use the OV7725. 15 | Disable this option to save memory. 16 | 17 | config NT99141_SUPPORT 18 | bool "Support NT99141 HD" 19 | default y 20 | help 21 | Enable this option if you want to use the NT99141. 22 | Disable this option to save memory. 23 | 24 | config OV2640_SUPPORT 25 | bool "Support OV2640 2MP" 26 | default y 27 | help 28 | Enable this option if you want to use the OV2640. 29 | Disable this option to save memory. 30 | 31 | config OV3660_SUPPORT 32 | bool "Support OV3660 3MP" 33 | default y 34 | help 35 | Enable this option if you want to use the OV3360. 36 | Disable this option to save memory. 37 | 38 | config OV5640_SUPPORT 39 | bool "Support OV5640 5MP" 40 | default y 41 | help 42 | Enable this option if you want to use the OV5640. 43 | Disable this option to save memory. 44 | 45 | config GC2145_SUPPORT 46 | bool "Support GC2145 2MP" 47 | default y 48 | help 49 | Enable this option if you want to use the GC2145. 50 | Disable this option to save memory. 51 | 52 | config GC032A_SUPPORT 53 | bool "Support GC032A VGA" 54 | default y 55 | help 56 | Enable this option if you want to use the GC032A. 57 | Disable this option to save memory. 58 | 59 | config GC0308_SUPPORT 60 | bool "Support GC0308 VGA" 61 | default y 62 | help 63 | Enable this option if you want to use the GC0308. 64 | Disable this option to save memory. 65 | 66 | config BF3005_SUPPORT 67 | bool "Support BF3005(BYD3005) VGA" 68 | default y 69 | help 70 | Enable this option if you want to use the BF3005. 71 | Disable this option to save memory. 72 | 73 | config BF20A6_SUPPORT 74 | bool "Support BF20A6(BYD20A6) VGA" 75 | default y 76 | help 77 | Enable this option if you want to use the BF20A6. 78 | Disable this option to save memory. 79 | 80 | config SC101IOT_SUPPORT 81 | bool "Support SC101IOT HD" 82 | default n 83 | help 84 | Enable this option if you want to use the SC101IOT. 85 | Disable this option to save memory. 86 | 87 | choice SC101_REGS_SELECT 88 | prompt "SC101iot default regs" 89 | default SC101IOT_720P_15FPS_ENABLED 90 | depends on SC101IOT_SUPPORT 91 | help 92 | Currently SC010iot has several register sets available. 93 | Select the one that matches your needs. 94 | 95 | config SC101IOT_720P_15FPS_ENABLED 96 | bool "xclk20M_720p_15fps" 97 | help 98 | Select this option means that when xclk is 20M, the frame rate is 15fps at 720p resolution. 99 | config SC101IOT_VGA_25FPS_ENABLED 100 | bool "xclk20M_VGA_25fps" 101 | help 102 | Select this option means that when xclk is 20M, the frame rate is 25fps at VGA resolution. 103 | endchoice 104 | 105 | config SC030IOT_SUPPORT 106 | bool "Support SC030IOT VGA" 107 | default y 108 | help 109 | Enable this option if you want to use the SC030IOT. 110 | Disable this option to save memory. 111 | 112 | config SC031GS_SUPPORT 113 | bool "Support SC031GS VGA" 114 | default n 115 | help 116 | SC031GS is a global shutter CMOS sensor with high frame rate and single-frame HDR. 117 | Enable this option if you want to use the SC031GS. 118 | Disable this option to save memory. 119 | 120 | config MEGA_CCM_SUPPORT 121 | bool "Support MEGA CCM 5MP" 122 | default y 123 | help 124 | Enable this option if you want to use the MEGA CCM. 125 | Disable this option to save memory. 126 | 127 | choice SCCB_HARDWARE_I2C_PORT 128 | bool "I2C peripheral to use for SCCB" 129 | default SCCB_HARDWARE_I2C_PORT1 130 | 131 | config SCCB_HARDWARE_I2C_PORT0 132 | bool "I2C0" 133 | config SCCB_HARDWARE_I2C_PORT1 134 | bool "I2C1" 135 | 136 | endchoice 137 | 138 | config SCCB_CLK_FREQ 139 | int "SCCB clk frequency" 140 | default 100000 141 | range 100000 400000 142 | help 143 | Increasing this value can reduce the initialization time of the sensor. 144 | Please refer to the relevant instructions of the sensor to adjust the value. 145 | 146 | choice GC_SENSOR_WINDOW_MODE 147 | bool "GalaxyCore Sensor Window Mode" 148 | depends on (GC2145_SUPPORT || GC032A_SUPPORT || GC0308_SUPPORT) 149 | default GC_SENSOR_SUBSAMPLE_MODE 150 | help 151 | This option determines how to reduce the output size when the resolution you set is less than the maximum resolution. 152 | SUBSAMPLE_MODE has a bigger perspective and WINDOWING_MODE has a higher frame rate. 153 | 154 | config GC_SENSOR_WINDOWING_MODE 155 | bool "Windowing Mode" 156 | config GC_SENSOR_SUBSAMPLE_MODE 157 | bool "Subsample Mode" 158 | endchoice 159 | 160 | config CAMERA_TASK_STACK_SIZE 161 | int "CAM task stack size" 162 | default 2048 163 | help 164 | Camera task stack size 165 | 166 | choice CAMERA_TASK_PINNED_TO_CORE 167 | bool "Camera task pinned to core" 168 | default CAMERA_CORE0 169 | help 170 | Pin the camera handle task to a certain core(0/1). It can also be done automatically choosing NO_AFFINITY. 171 | 172 | config CAMERA_CORE0 173 | bool "CORE0" 174 | config CAMERA_CORE1 175 | bool "CORE1" 176 | config CAMERA_NO_AFFINITY 177 | bool "NO_AFFINITY" 178 | 179 | endchoice 180 | 181 | config CAMERA_DMA_BUFFER_SIZE_MAX 182 | int "DMA buffer size" 183 | range 8192 32768 184 | default 32768 185 | help 186 | Maximum value of DMA buffer 187 | Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent. 188 | 189 | choice CAMERA_JPEG_MODE_FRAME_SIZE_OPTION 190 | prompt "JPEG mode frame size option" 191 | default CAMERA_JPEG_MODE_FRAME_SIZE_AUTO 192 | help 193 | Select whether to use automatic calculation for JPEG mode frame size or specify a custom value. 194 | 195 | config CAMERA_JPEG_MODE_FRAME_SIZE_AUTO 196 | bool "Use automatic calculation (width * height / 5)" 197 | help 198 | Use the default calculation for JPEG mode frame size. 199 | Note: In very low resolutions like QQVGA, the default calculation tends to result in insufficient buffer size. 200 | 201 | config CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM 202 | bool "Specify custom frame size" 203 | help 204 | Specify a custom frame size in bytes for JPEG mode. 205 | 206 | endchoice 207 | 208 | config CAMERA_JPEG_MODE_FRAME_SIZE 209 | int "Custom JPEG mode frame size (bytes)" 210 | default 8192 211 | depends on CAMERA_JPEG_MODE_FRAME_SIZE_CUSTOM 212 | help 213 | This option sets the custom frame size in JPEG mode. 214 | Specify the desired buffer size in bytes. 215 | 216 | config CAMERA_CONVERTER_ENABLED 217 | bool "Enable camera RGB/YUV converter" 218 | depends on IDF_TARGET_ESP32S3 219 | default n 220 | help 221 | Enable this option if you want to use RGB565/YUV422/YUV420/YUV411 format conversion. 222 | 223 | choice CAMERA_CONV_PROTOCOL 224 | bool "Camera converter protocol" 225 | depends on CAMERA_CONVERTER_ENABLED 226 | default LCD_CAM_CONV_BT601_ENABLED 227 | help 228 | Supports format conversion under both BT601 and BT709 standards. 229 | 230 | config LCD_CAM_CONV_BT601_ENABLED 231 | bool "BT601" 232 | config LCD_CAM_CONV_BT709_ENABLED 233 | bool "BT709" 234 | endchoice 235 | 236 | config LCD_CAM_CONV_FULL_RANGE_ENABLED 237 | bool "Camera converter full range mode" 238 | depends on CAMERA_CONVERTER_ENABLED 239 | default y 240 | help 241 | Supports format conversion under both full color range mode and limited color range mode. 242 | If full color range mode is selected, the color range of RGB or YUV is 0~255. 243 | If limited color range mode is selected, the color range of RGB is 16~240, and the color range of YUV is Y[16~240], UV[16~235]. 244 | Full color range mode has a wider color range, so details in the image show more clearly. 245 | Please confirm the color range mode of the current camera sensor, incorrect color range mode may cause color difference in the final converted image. 246 | Full range mode is used by default. If this option is not selected, the format conversion function will be done using the limited range mode. 247 | 248 | config LCD_CAM_ISR_IRAM_SAFE 249 | bool "Execute camera ISR from IRAM" 250 | depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) 251 | default n 252 | help 253 | If this option is enabled, camera ISR will execute from IRAM. 254 | endmenu 255 | -------------------------------------------------------------------------------- /conversions/esp_jpg_decode.c: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "esp_jpg_decode.h" 15 | 16 | #include "esp_system.h" 17 | #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+ 18 | #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 19 | #include "esp32/rom/tjpgd.h" 20 | #elif CONFIG_IDF_TARGET_ESP32S3 21 | #include "esp32s3/rom/tjpgd.h" 22 | #elif CONFIG_IDF_TARGET_ESP32C3 23 | #include "esp32c3/rom/tjpgd.h" 24 | #elif CONFIG_ESP_ROM_HAS_JPEG_DECODE // available since IDF 4.4 25 | #include "rom/tjpgd.h" // latest IDFs have `rom/` includes available 26 | #else 27 | #include "tjpgd.h" // using software decoder 28 | #endif 29 | #else // ESP32 Before IDF 4.0 30 | #include "rom/tjpgd.h" 31 | #endif 32 | 33 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 34 | #include "esp32-hal-log.h" 35 | #define TAG "" 36 | #else 37 | #include "esp_log.h" 38 | static const char* TAG = "esp_jpg_decode"; 39 | #endif 40 | 41 | typedef struct { 42 | jpg_scale_t scale; 43 | jpg_reader_cb reader; 44 | jpg_writer_cb writer; 45 | void * arg; 46 | size_t len; 47 | size_t index; 48 | } esp_jpg_decoder_t; 49 | 50 | static const char * jd_errors[] = { 51 | "Succeeded", 52 | "Interrupted by output function", 53 | "Device error or wrong termination of input stream", 54 | "Insufficient memory pool for the image", 55 | "Insufficient stream input buffer", 56 | "Parameter error", 57 | "Data format error", 58 | "Right format but not supported", 59 | "Not supported JPEG standard" 60 | }; 61 | 62 | static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect) 63 | { 64 | uint16_t x = rect->left; 65 | uint16_t y = rect->top; 66 | uint16_t w = rect->right + 1 - x; 67 | uint16_t h = rect->bottom + 1 - y; 68 | uint8_t *data = (uint8_t *)bitmap; 69 | 70 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 71 | 72 | if (jpeg->writer) { 73 | return jpeg->writer(jpeg->arg, x, y, w, h, data); 74 | } 75 | return 0; 76 | } 77 | 78 | static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len) 79 | { 80 | esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device; 81 | if (jpeg->len && len > (jpeg->len - jpeg->index)) { 82 | len = jpeg->len - jpeg->index; 83 | } 84 | if (len) { 85 | len = jpeg->reader(jpeg->arg, jpeg->index, buf, len); 86 | if (!len) { 87 | ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len); 88 | } 89 | jpeg->index += len; 90 | } 91 | return len; 92 | } 93 | 94 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg) 95 | { 96 | static uint8_t work[3100]; 97 | JDEC decoder; 98 | esp_jpg_decoder_t jpeg; 99 | 100 | jpeg.len = len; 101 | jpeg.reader = reader; 102 | jpeg.writer = writer; 103 | jpeg.arg = arg; 104 | jpeg.scale = scale; 105 | jpeg.index = 0; 106 | 107 | JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg); 108 | if(jres != JDR_OK){ 109 | ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]); 110 | return ESP_FAIL; 111 | } 112 | 113 | uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale)); 114 | uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale)); 115 | 116 | //output start 117 | if (!writer(arg, 0, 0, output_width, output_height, NULL)) { 118 | ESP_LOGE(TAG, "JPG Writer Start Failed!"); 119 | return ESP_FAIL; 120 | } 121 | //output write 122 | jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale); 123 | //output end 124 | if (!writer(arg, output_width, output_height, output_width, output_height, NULL)) { 125 | ESP_LOGE(TAG, "JPG Writer End Failed!"); 126 | return ESP_FAIL; 127 | } 128 | 129 | if (jres != JDR_OK) { 130 | ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]); 131 | return ESP_FAIL; 132 | } 133 | //check if all data has been consumed. 134 | if (len && jpeg.index < len) { 135 | _jpg_read(&decoder, NULL, len - jpeg.index); 136 | } 137 | 138 | return ESP_OK; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /conversions/include/esp_jpg_decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _ESP_JPG_DECODE_H_ 15 | #define _ESP_JPG_DECODE_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_err.h" 25 | 26 | typedef enum { 27 | JPG_SCALE_NONE, 28 | JPG_SCALE_2X, 29 | JPG_SCALE_4X, 30 | JPG_SCALE_8X, 31 | JPG_SCALE_MAX = JPG_SCALE_8X 32 | } jpg_scale_t; 33 | 34 | typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len); 35 | typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data); 36 | 37 | esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* _ESP_JPG_DECODE_H_ */ 44 | -------------------------------------------------------------------------------- /conversions/include/img_converters.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _IMG_CONVERTERS_H_ 15 | #define _IMG_CONVERTERS_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include 23 | #include 24 | #include "esp_camera.h" 25 | #include "esp_jpg_decode.h" 26 | 27 | typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len); 28 | 29 | /** 30 | * @brief Convert image buffer to JPEG 31 | * 32 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 33 | * @param src_len Length in bytes of the source buffer 34 | * @param width Width in pixels of the source image 35 | * @param height Height in pixels of the source image 36 | * @param format Format of the source image 37 | * @param quality JPEG quality of the resulting image 38 | * @param cp Callback to be called to write the bytes of the output JPEG 39 | * @param arg Pointer to be passed to the callback 40 | * 41 | * @return true on success 42 | */ 43 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg); 44 | 45 | /** 46 | * @brief Convert camera frame buffer to JPEG 47 | * 48 | * @param fb Source camera frame buffer 49 | * @param quality JPEG quality of the resulting image 50 | * @param cp Callback to be called to write the bytes of the output JPEG 51 | * @param arg Pointer to be passed to the callback 52 | * 53 | * @return true on success 54 | */ 55 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg); 56 | 57 | /** 58 | * @brief Convert image buffer to JPEG buffer 59 | * 60 | * @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format 61 | * @param src_len Length in bytes of the source buffer 62 | * @param width Width in pixels of the source image 63 | * @param height Height in pixels of the source image 64 | * @param format Format of the source image 65 | * @param quality JPEG quality of the resulting image 66 | * @param out Pointer to be populated with the address of the resulting buffer. 67 | * You MUST free the pointer once you are done with it. 68 | * @param out_len Pointer to be populated with the length of the output buffer 69 | * 70 | * @return true on success 71 | */ 72 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len); 73 | 74 | /** 75 | * @brief Convert camera frame buffer to JPEG buffer 76 | * 77 | * @param fb Source camera frame buffer 78 | * @param quality JPEG quality of the resulting image 79 | * @param out Pointer to be populated with the address of the resulting buffer 80 | * @param out_len Pointer to be populated with the length of the output buffer 81 | * 82 | * @return true on success 83 | */ 84 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len); 85 | 86 | /** 87 | * @brief Convert image buffer to BMP buffer 88 | * 89 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 90 | * @param src_len Length in bytes of the source buffer 91 | * @param width Width in pixels of the source image 92 | * @param height Height in pixels of the source image 93 | * @param format Format of the source image 94 | * @param out Pointer to be populated with the address of the resulting buffer 95 | * @param out_len Pointer to be populated with the length of the output buffer 96 | * 97 | * @return true on success 98 | */ 99 | bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len); 100 | 101 | /** 102 | * @brief Convert camera frame buffer to BMP buffer 103 | * 104 | * @param fb Source camera frame buffer 105 | * @param out Pointer to be populated with the address of the resulting buffer 106 | * @param out_len Pointer to be populated with the length of the output buffer 107 | * 108 | * @return true on success 109 | */ 110 | bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len); 111 | 112 | /** 113 | * @brief Convert image buffer to RGB888 buffer (used for face detection) 114 | * 115 | * @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format 116 | * @param src_len Length in bytes of the source buffer 117 | * @param format Format of the source image 118 | * @param rgb_buf Pointer to the output buffer (width * height * 3) 119 | * 120 | * @return true on success 121 | */ 122 | bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf); 123 | 124 | bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale); 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | 130 | #endif /* _IMG_CONVERTERS_H_ */ 131 | -------------------------------------------------------------------------------- /conversions/private_include/jpge.h: -------------------------------------------------------------------------------- 1 | // jpge.h - C++ class for JPEG compression. 2 | // Public domain, Rich Geldreich 3 | // Alex Evans: Added RGBA support, linear memory allocator. 4 | #ifndef JPEG_ENCODER_H 5 | #define JPEG_ENCODER_H 6 | 7 | namespace jpge 8 | { 9 | typedef unsigned char uint8; 10 | typedef signed short int16; 11 | typedef signed int int32; 12 | typedef unsigned short uint16; 13 | typedef unsigned int uint32; 14 | typedef unsigned int uint; 15 | 16 | // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common. 17 | enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 }; 18 | 19 | // JPEG compression parameters structure. 20 | struct params { 21 | inline params() : m_quality(85), m_subsampling(H2V2) { } 22 | 23 | inline bool check() const { 24 | if ((m_quality < 1) || (m_quality > 100)) { 25 | return false; 26 | } 27 | if ((uint)m_subsampling > (uint)H2V2) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | // Quality: 1-100, higher is better. Typical values are around 50-95. 34 | int m_quality; 35 | 36 | // m_subsampling: 37 | // 0 = Y (grayscale) only 38 | // 1 = H1V1 subsampling (YCbCr 1x1x1, 3 blocks per MCU) 39 | // 2 = H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU) 40 | // 3 = H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common) 41 | subsampling_t m_subsampling; 42 | }; 43 | 44 | // Output stream abstract class - used by the jpeg_encoder class to write to the output stream. 45 | // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts. 46 | class output_stream { 47 | public: 48 | virtual ~output_stream() { }; 49 | virtual bool put_buf(const void* Pbuf, int len) = 0; 50 | virtual uint get_size() const = 0; 51 | }; 52 | 53 | // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions. 54 | class jpeg_encoder { 55 | public: 56 | jpeg_encoder(); 57 | ~jpeg_encoder(); 58 | 59 | // Initializes the compressor. 60 | // pStream: The stream object to use for writing compressed data. 61 | // params - Compression parameters structure, defined above. 62 | // width, height - Image dimensions. 63 | // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data. 64 | // Returns false on out of memory or if a stream write fails. 65 | bool init(output_stream *pStream, int width, int height, int src_channels, const params &comp_params = params()); 66 | 67 | // Call this method with each source scanline. 68 | // width * src_channels bytes per scanline is expected (RGB or Y format). 69 | // You must call with NULL after all scanlines are processed to finish compression. 70 | // Returns false on out of memory or if a stream write fails. 71 | bool process_scanline(const void* pScanline); 72 | 73 | // Deinitializes the compressor, freeing any allocated memory. May be called at any time. 74 | void deinit(); 75 | 76 | private: 77 | jpeg_encoder(const jpeg_encoder &); 78 | jpeg_encoder &operator =(const jpeg_encoder &); 79 | 80 | typedef int32 sample_array_t; 81 | enum { JPGE_OUT_BUF_SIZE = 512 }; 82 | 83 | output_stream *m_pStream; 84 | params m_params; 85 | uint8 m_num_components; 86 | uint8 m_comp_h_samp[3], m_comp_v_samp[3]; 87 | int m_image_x, m_image_y, m_image_bpp, m_image_bpl; 88 | int m_image_x_mcu, m_image_y_mcu; 89 | int m_image_bpl_xlt, m_image_bpl_mcu; 90 | int m_mcus_per_row; 91 | int m_mcu_x, m_mcu_y; 92 | uint8 *m_mcu_lines[16]; 93 | uint8 m_mcu_y_ofs; 94 | sample_array_t m_sample_array[64]; 95 | int16 m_coefficient_array[64]; 96 | 97 | int m_last_dc_val[3]; 98 | uint8 m_out_buf[JPGE_OUT_BUF_SIZE]; 99 | uint8 *m_pOut_buf; 100 | uint m_out_buf_left; 101 | uint32 m_bit_buffer; 102 | uint m_bits_in; 103 | uint8 m_pass_num; 104 | bool m_all_stream_writes_succeeded; 105 | 106 | bool jpg_open(int p_x_res, int p_y_res, int src_channels); 107 | 108 | void flush_output_buffer(); 109 | void put_bits(uint bits, uint len); 110 | 111 | void emit_byte(uint8 i); 112 | void emit_word(uint i); 113 | void emit_marker(int marker); 114 | 115 | void emit_jfif_app0(); 116 | void emit_dqt(); 117 | void emit_sof(); 118 | void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag); 119 | void emit_dhts(); 120 | void emit_sos(); 121 | 122 | void compute_quant_table(int32 *dst, const int16 *src); 123 | void load_quantized_coefficients(int component_num); 124 | 125 | void load_block_8_8_grey(int x); 126 | void load_block_8_8(int x, int y, int c); 127 | void load_block_16_8(int x, int c); 128 | void load_block_16_8_8(int x, int c); 129 | 130 | void code_coefficients_pass_two(int component_num); 131 | void code_block(int component_num); 132 | 133 | void process_mcu_row(); 134 | bool process_end_of_image(); 135 | void load_mcu(const void* src); 136 | void clear(); 137 | void init(); 138 | }; 139 | 140 | } // namespace jpge 141 | 142 | #endif // JPEG_ENCODER 143 | -------------------------------------------------------------------------------- /conversions/private_include/yuv.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef _CONVERSIONS_YUV_H_ 15 | #define _CONVERSIONS_YUV_H_ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | 23 | void yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* _CONVERSIONS_YUV_H_ */ 30 | -------------------------------------------------------------------------------- /conversions/to_jpg.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include 15 | #include 16 | #include "esp_attr.h" 17 | #include "soc/efuse_reg.h" 18 | #include "esp_heap_caps.h" 19 | #include "esp_camera.h" 20 | #include "img_converters.h" 21 | #include "jpge.h" 22 | #include "yuv.h" 23 | 24 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 25 | #include "esp32-hal-log.h" 26 | #define TAG "" 27 | #else 28 | #include "esp_log.h" 29 | static const char* TAG = "to_jpg"; 30 | #endif 31 | 32 | static void *_malloc(size_t size) 33 | { 34 | void * res = malloc(size); 35 | if(res) { 36 | return res; 37 | } 38 | 39 | // check if SPIRAM is enabled and is allocatable 40 | #if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) 41 | return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); 42 | #endif 43 | return NULL; 44 | } 45 | 46 | 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) 47 | { 48 | int i=0, o=0, l=0; 49 | if(format == PIXFORMAT_GRAYSCALE) { 50 | memcpy(dst, src + line * width, width); 51 | } else if(format == PIXFORMAT_RGB888) { 52 | l = width * 3; 53 | src += l * line; 54 | for(i=0; i> 3; 65 | dst[o++] = (src[i+1] & 0x1F) << 3; 66 | } 67 | } else if(format == PIXFORMAT_YUV422) { 68 | uint8_t y0, y1, u, v; 69 | uint8_t r, g, b; 70 | l = width * 2; 71 | src += l * line; 72 | for(i=0; i 100) { 104 | quality = 100; 105 | } 106 | 107 | jpge::params comp_params = jpge::params(); 108 | comp_params.m_subsampling = subsampling; 109 | comp_params.m_quality = quality; 110 | 111 | jpge::jpeg_encoder dst_image; 112 | 113 | if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) { 114 | ESP_LOGE(TAG, "JPG encoder init failed"); 115 | return false; 116 | } 117 | 118 | uint8_t* line = (uint8_t*)_malloc(width * num_channels); 119 | if(!line) { 120 | ESP_LOGE(TAG, "Scan line malloc failed"); 121 | return false; 122 | } 123 | 124 | for (int i = 0; i < height; i++) { 125 | convert_line_format(src, format, line, width, num_channels, i); 126 | if (!dst_image.process_scanline(line)) { 127 | ESP_LOGE(TAG, "JPG process line %u failed", i); 128 | free(line); 129 | return false; 130 | } 131 | } 132 | free(line); 133 | 134 | if (!dst_image.process_scanline(NULL)) { 135 | ESP_LOGE(TAG, "JPG image finish failed"); 136 | return false; 137 | } 138 | dst_image.deinit(); 139 | return true; 140 | } 141 | 142 | class callback_stream : public jpge::output_stream { 143 | protected: 144 | jpg_out_cb ocb; 145 | void * oarg; 146 | size_t index; 147 | 148 | public: 149 | callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { } 150 | virtual ~callback_stream() { } 151 | virtual bool put_buf(const void* data, int len) 152 | { 153 | index += ocb(oarg, index, data, len); 154 | return true; 155 | } 156 | virtual size_t get_size() const 157 | { 158 | return index; 159 | } 160 | }; 161 | 162 | bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg) 163 | { 164 | callback_stream dst_stream(cb, arg); 165 | return convert_image(src, width, height, format, quality, &dst_stream); 166 | } 167 | 168 | bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg) 169 | { 170 | return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg); 171 | } 172 | 173 | 174 | 175 | class memory_stream : public jpge::output_stream { 176 | protected: 177 | uint8_t *out_buf; 178 | size_t max_len, index; 179 | 180 | public: 181 | memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast(pBuf)), max_len(buf_size), index(0) { } 182 | 183 | virtual ~memory_stream() { } 184 | 185 | virtual bool put_buf(const void* pBuf, int len) 186 | { 187 | if (!pBuf) { 188 | //end of image 189 | return true; 190 | } 191 | if ((size_t)len > (max_len - index)) { 192 | //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len); 193 | len = max_len - index; 194 | } 195 | if (len) { 196 | memcpy(out_buf + index, pBuf, len); 197 | index += len; 198 | } 199 | return true; 200 | } 201 | 202 | virtual size_t get_size() const 203 | { 204 | return index; 205 | } 206 | }; 207 | 208 | bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len) 209 | { 210 | //todo: allocate proper buffer for holding JPEG data 211 | //this should be enough for CIF frame size 212 | int jpg_buf_len = 128*1024; 213 | 214 | 215 | uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len); 216 | if(jpg_buf == NULL) { 217 | ESP_LOGE(TAG, "JPG buffer malloc failed"); 218 | return false; 219 | } 220 | memory_stream dst_stream(jpg_buf, jpg_buf_len); 221 | 222 | if(!convert_image(src, width, height, format, quality, &dst_stream)) { 223 | free(jpg_buf); 224 | return false; 225 | } 226 | 227 | *out = jpg_buf; 228 | *out_len = dst_stream.get_size(); 229 | return true; 230 | } 231 | 232 | bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len) 233 | { 234 | return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len); 235 | } 236 | -------------------------------------------------------------------------------- /driver/include/esp_camera.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | /* 15 | * Example Use 16 | * 17 | static camera_config_t camera_example_config = { 18 | .pin_pwdn = PIN_PWDN, 19 | .pin_reset = PIN_RESET, 20 | .pin_xclk = PIN_XCLK, 21 | .pin_sccb_sda = PIN_SIOD, 22 | .pin_sccb_scl = PIN_SIOC, 23 | .pin_d7 = PIN_D7, 24 | .pin_d6 = PIN_D6, 25 | .pin_d5 = PIN_D5, 26 | .pin_d4 = PIN_D4, 27 | .pin_d3 = PIN_D3, 28 | .pin_d2 = PIN_D2, 29 | .pin_d1 = PIN_D1, 30 | .pin_d0 = PIN_D0, 31 | .pin_vsync = PIN_VSYNC, 32 | .pin_href = PIN_HREF, 33 | .pin_pclk = PIN_PCLK, 34 | 35 | .xclk_freq_hz = 20000000, 36 | .ledc_timer = LEDC_TIMER_0, 37 | .ledc_channel = LEDC_CHANNEL_0, 38 | .pixel_format = PIXFORMAT_JPEG, 39 | .frame_size = FRAMESIZE_SVGA, 40 | .jpeg_quality = 10, 41 | .fb_count = 2, 42 | .grab_mode = CAMERA_GRAB_WHEN_EMPTY 43 | }; 44 | 45 | esp_err_t camera_example_init(){ 46 | return esp_camera_init(&camera_example_config); 47 | } 48 | 49 | esp_err_t camera_example_capture(){ 50 | //capture a frame 51 | camera_fb_t * fb = esp_camera_fb_get(); 52 | if (!fb) { 53 | ESP_LOGE(TAG, "Frame buffer could not be acquired"); 54 | return ESP_FAIL; 55 | } 56 | 57 | //replace this with your own function 58 | display_image(fb->width, fb->height, fb->pixformat, fb->buf, fb->len); 59 | 60 | //return the frame buffer back to be reused 61 | esp_camera_fb_return(fb); 62 | 63 | return ESP_OK; 64 | } 65 | */ 66 | 67 | #pragma once 68 | 69 | #include "esp_err.h" 70 | #include "driver/ledc.h" 71 | #include "sensor.h" 72 | #include "sys/time.h" 73 | #include "sdkconfig.h" 74 | 75 | /** 76 | * @brief define for if chip supports camera 77 | */ 78 | #define ESP_CAMERA_SUPPORTED (CONFIG_IDF_TARGET_ESP32 | CONFIG_IDF_TARGET_ESP32S3 | \ 79 | CONFIG_IDF_TARGET_ESP32S2) 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | /** 86 | * @brief Configuration structure for camera initialization 87 | */ 88 | typedef enum { 89 | CAMERA_GRAB_WHEN_EMPTY, /*!< Fills buffers when they are empty. Less resources but first 'fb_count' frames might be old */ 90 | CAMERA_GRAB_LATEST /*!< Except when 1 frame buffer is used, queue will always contain the last 'fb_count' frames */ 91 | } camera_grab_mode_t; 92 | 93 | /** 94 | * @brief Camera frame buffer location 95 | */ 96 | typedef enum { 97 | CAMERA_FB_IN_PSRAM, /*!< Frame buffer is placed in external PSRAM */ 98 | CAMERA_FB_IN_DRAM /*!< Frame buffer is placed in internal DRAM */ 99 | } camera_fb_location_t; 100 | 101 | #if CONFIG_CAMERA_CONVERTER_ENABLED 102 | /** 103 | * @brief Camera RGB\YUV conversion mode 104 | */ 105 | typedef enum { 106 | CONV_DISABLE, 107 | RGB565_TO_YUV422, 108 | 109 | YUV422_TO_RGB565, 110 | YUV422_TO_YUV420 111 | } camera_conv_mode_t; 112 | #endif 113 | 114 | /** 115 | * @brief Configuration structure for camera initialization 116 | */ 117 | typedef struct { 118 | int pin_pwdn; /*!< GPIO pin for camera power down line */ 119 | int pin_reset; /*!< GPIO pin for camera reset line */ 120 | int pin_xclk; /*!< GPIO pin for camera XCLK line */ 121 | union { 122 | int pin_sccb_sda; /*!< GPIO pin for camera SDA line */ 123 | int pin_sscb_sda __attribute__((deprecated("please use pin_sccb_sda instead"))); /*!< GPIO pin for camera SDA line (legacy name) */ 124 | }; 125 | union { 126 | int pin_sccb_scl; /*!< GPIO pin for camera SCL line */ 127 | int pin_sscb_scl __attribute__((deprecated("please use pin_sccb_scl instead"))); /*!< GPIO pin for camera SCL line (legacy name) */ 128 | }; 129 | int pin_d7; /*!< GPIO pin for camera D7 line */ 130 | int pin_d6; /*!< GPIO pin for camera D6 line */ 131 | int pin_d5; /*!< GPIO pin for camera D5 line */ 132 | int pin_d4; /*!< GPIO pin for camera D4 line */ 133 | int pin_d3; /*!< GPIO pin for camera D3 line */ 134 | int pin_d2; /*!< GPIO pin for camera D2 line */ 135 | int pin_d1; /*!< GPIO pin for camera D1 line */ 136 | int pin_d0; /*!< GPIO pin for camera D0 line */ 137 | int pin_vsync; /*!< GPIO pin for camera VSYNC line */ 138 | int pin_href; /*!< GPIO pin for camera HREF line */ 139 | int pin_pclk; /*!< GPIO pin for camera PCLK line */ 140 | 141 | int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. EXPERIMENTAL: Set to 16MHz on ESP32-S2 or ESP32-S3 to enable EDMA mode */ 142 | 143 | ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */ 144 | ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */ 145 | 146 | pixformat_t pixel_format; /*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */ 147 | framesize_t frame_size; /*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */ 148 | 149 | int jpeg_quality; /*!< Quality of JPEG output. 0-63 lower means higher quality */ 150 | size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */ 151 | camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */ 152 | camera_grab_mode_t grab_mode; /*!< When buffers should be filled */ 153 | #if CONFIG_CAMERA_CONVERTER_ENABLED 154 | camera_conv_mode_t conv_mode; /*!< RGB<->YUV Conversion mode */ 155 | #endif 156 | 157 | int sccb_i2c_port; /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */ 158 | } camera_config_t; 159 | 160 | /** 161 | * @brief Data structure of camera frame buffer 162 | */ 163 | typedef struct { 164 | uint8_t * buf; /*!< Pointer to the pixel data */ 165 | size_t len; /*!< Length of the buffer in bytes */ 166 | size_t width; /*!< Width of the buffer in pixels */ 167 | size_t height; /*!< Height of the buffer in pixels */ 168 | pixformat_t format; /*!< Format of the pixel data */ 169 | struct timeval timestamp; /*!< Timestamp since boot of the first DMA buffer of the frame */ 170 | } camera_fb_t; 171 | 172 | #define ESP_ERR_CAMERA_BASE 0x20000 173 | #define ESP_ERR_CAMERA_NOT_DETECTED (ESP_ERR_CAMERA_BASE + 1) 174 | #define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2) 175 | #define ESP_ERR_CAMERA_FAILED_TO_SET_OUT_FORMAT (ESP_ERR_CAMERA_BASE + 3) 176 | #define ESP_ERR_CAMERA_NOT_SUPPORTED (ESP_ERR_CAMERA_BASE + 4) 177 | 178 | /** 179 | * @brief Initialize the camera driver 180 | * 181 | * This function detects and configures camera over I2C interface, 182 | * allocates framebuffer and DMA buffers, 183 | * initializes parallel I2S input, and sets up DMA descriptors. 184 | * 185 | * Currently this function can only be called once and there is 186 | * no way to de-initialize this module. 187 | * 188 | * @param config Camera configuration parameters 189 | * 190 | * @return ESP_OK on success 191 | */ 192 | esp_err_t esp_camera_init(const camera_config_t* config); 193 | 194 | /** 195 | * @brief Deinitialize the camera driver 196 | * 197 | * @return 198 | * - ESP_OK on success 199 | * - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet 200 | */ 201 | esp_err_t esp_camera_deinit(void); 202 | 203 | /** 204 | * @brief Obtain pointer to a frame buffer. 205 | * 206 | * @return pointer to the frame buffer 207 | */ 208 | camera_fb_t* esp_camera_fb_get(void); 209 | 210 | /** 211 | * @brief Return the frame buffer to be reused again. 212 | * 213 | * @param fb Pointer to the frame buffer 214 | */ 215 | void esp_camera_fb_return(camera_fb_t * fb); 216 | 217 | /** 218 | * @brief Get a pointer to the image sensor control structure 219 | * 220 | * @return pointer to the sensor 221 | */ 222 | sensor_t * esp_camera_sensor_get(void); 223 | 224 | /** 225 | * @brief Save camera settings to non-volatile-storage (NVS) 226 | * 227 | * @param key A unique nvs key name for the camera settings 228 | */ 229 | esp_err_t esp_camera_save_to_nvs(const char *key); 230 | 231 | /** 232 | * @brief Load camera settings from non-volatile-storage (NVS) 233 | * 234 | * @param key A unique nvs key name for the camera settings 235 | */ 236 | esp_err_t esp_camera_load_from_nvs(const char *key); 237 | 238 | /** 239 | * @brief Return all frame buffers to be reused again. 240 | */ 241 | void esp_camera_return_all(void); 242 | 243 | 244 | #ifdef __cplusplus 245 | } 246 | #endif 247 | 248 | #include "img_converters.h" 249 | 250 | -------------------------------------------------------------------------------- /driver/include/sensor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * Sensor abstraction layer. 7 | * 8 | */ 9 | #ifndef __SENSOR_H__ 10 | #define __SENSOR_H__ 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | typedef enum { 19 | OV9650_PID = 0x96, 20 | OV7725_PID = 0x77, 21 | OV2640_PID = 0x26, 22 | OV3660_PID = 0x3660, 23 | OV5640_PID = 0x5640, 24 | OV7670_PID = 0x76, 25 | NT99141_PID = 0x1410, 26 | GC2145_PID = 0x2145, 27 | GC032A_PID = 0x232a, 28 | GC0308_PID = 0x9b, 29 | BF3005_PID = 0x30, 30 | BF20A6_PID = 0x20a6, 31 | SC101IOT_PID = 0xda4a, 32 | SC030IOT_PID = 0x9a46, 33 | SC031GS_PID = 0x0031, 34 | MEGA_CCM_PID =0x039E, 35 | } camera_pid_t; 36 | 37 | typedef enum { 38 | CAMERA_OV7725, 39 | CAMERA_OV2640, 40 | CAMERA_OV3660, 41 | CAMERA_OV5640, 42 | CAMERA_OV7670, 43 | CAMERA_NT99141, 44 | CAMERA_GC2145, 45 | CAMERA_GC032A, 46 | CAMERA_GC0308, 47 | CAMERA_BF3005, 48 | CAMERA_BF20A6, 49 | CAMERA_SC101IOT, 50 | CAMERA_SC030IOT, 51 | CAMERA_SC031GS, 52 | CAMERA_MEGA_CCM, 53 | CAMERA_MODEL_MAX, 54 | CAMERA_NONE, 55 | } camera_model_t; 56 | 57 | typedef enum { 58 | OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1 59 | OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1 60 | OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1 61 | OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1 62 | OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1 63 | NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1 64 | GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1 65 | GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1 66 | GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1 67 | BF3005_SCCB_ADDR = 0x6E, 68 | BF20A6_SCCB_ADDR = 0x6E, 69 | SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 70 | SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1 71 | SC031GS_SCCB_ADDR = 0x30, 72 | MEGA_CCM_SCCB_ADDR = 0x1F, // 0x3E >> 1 73 | } camera_sccb_addr_t; 74 | 75 | typedef enum { 76 | PIXFORMAT_RGB565, // 2BPP/RGB565 77 | PIXFORMAT_YUV422, // 2BPP/YUV422 78 | PIXFORMAT_YUV420, // 1.5BPP/YUV420 79 | PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE 80 | PIXFORMAT_JPEG, // JPEG/COMPRESSED 81 | PIXFORMAT_RGB888, // 3BPP/RGB888 82 | PIXFORMAT_RAW, // RAW 83 | PIXFORMAT_RGB444, // 3BP2P/RGB444 84 | PIXFORMAT_RGB555, // 3BP2P/RGB555 85 | } pixformat_t; 86 | 87 | typedef enum { 88 | FRAMESIZE_96X96, // 96x96 89 | FRAMESIZE_QQVGA, // 160x120 90 | FRAMESIZE_128X128, // 128x128 91 | FRAMESIZE_QCIF, // 176x144 92 | FRAMESIZE_HQVGA, // 240x176 93 | FRAMESIZE_240X240, // 240x240 94 | FRAMESIZE_QVGA, // 320x240 95 | FRAMESIZE_320X320, // 320x320 96 | FRAMESIZE_CIF, // 400x296 97 | FRAMESIZE_HVGA, // 480x320 98 | FRAMESIZE_VGA, // 640x480 99 | FRAMESIZE_SVGA, // 800x600 100 | FRAMESIZE_XGA, // 1024x768 101 | FRAMESIZE_HD, // 1280x720 102 | FRAMESIZE_SXGA, // 1280x1024 103 | FRAMESIZE_UXGA, // 1600x1200 104 | // 3MP Sensors 105 | FRAMESIZE_FHD, // 1920x1080 106 | FRAMESIZE_P_HD, // 720x1280 107 | FRAMESIZE_P_3MP, // 864x1536 108 | FRAMESIZE_QXGA, // 2048x1536 109 | // 5MP Sensors 110 | FRAMESIZE_QHD, // 2560x1440 111 | FRAMESIZE_WQXGA, // 2560x1600 112 | FRAMESIZE_P_FHD, // 1080x1920 113 | FRAMESIZE_QSXGA, // 2560x1920 114 | FRAMESIZE_5MP, // 2592x1944 115 | FRAMESIZE_INVALID 116 | } framesize_t; 117 | 118 | typedef struct { 119 | const camera_model_t model; 120 | const char *name; 121 | const camera_sccb_addr_t sccb_addr; 122 | const camera_pid_t pid; 123 | const framesize_t max_size; 124 | const bool support_jpeg; 125 | } camera_sensor_info_t; 126 | 127 | typedef enum { 128 | ASPECT_RATIO_4X3, 129 | ASPECT_RATIO_3X2, 130 | ASPECT_RATIO_16X10, 131 | ASPECT_RATIO_5X3, 132 | ASPECT_RATIO_16X9, 133 | ASPECT_RATIO_21X9, 134 | ASPECT_RATIO_5X4, 135 | ASPECT_RATIO_1X1, 136 | ASPECT_RATIO_9X16 137 | } aspect_ratio_t; 138 | 139 | typedef enum { 140 | GAINCEILING_2X, 141 | GAINCEILING_4X, 142 | GAINCEILING_8X, 143 | GAINCEILING_16X, 144 | GAINCEILING_32X, 145 | GAINCEILING_64X, 146 | GAINCEILING_128X, 147 | } gainceiling_t; 148 | 149 | typedef struct { 150 | uint16_t max_width; 151 | uint16_t max_height; 152 | uint16_t start_x; 153 | uint16_t start_y; 154 | uint16_t end_x; 155 | uint16_t end_y; 156 | uint16_t offset_x; 157 | uint16_t offset_y; 158 | uint16_t total_x; 159 | uint16_t total_y; 160 | } ratio_settings_t; 161 | 162 | typedef struct { 163 | const uint16_t width; 164 | const uint16_t height; 165 | const aspect_ratio_t aspect_ratio; 166 | } resolution_info_t; 167 | 168 | // Resolution table (in sensor.c) 169 | extern const resolution_info_t resolution[]; 170 | // camera sensor table (in sensor.c) 171 | extern const camera_sensor_info_t camera_sensor[]; 172 | 173 | typedef struct { 174 | uint8_t MIDH; 175 | uint8_t MIDL; 176 | uint16_t PID; 177 | uint8_t VER; 178 | } sensor_id_t; 179 | 180 | typedef struct { 181 | framesize_t framesize;//0 - 10 182 | bool scale; 183 | bool binning; 184 | uint8_t quality;//0 - 63 185 | int8_t brightness;//-2 - 2 186 | int8_t contrast;//-2 - 2 187 | int8_t saturation;//-2 - 2 188 | int8_t sharpness;//-2 - 2 189 | uint8_t denoise; 190 | uint8_t special_effect;//0 - 6 191 | uint8_t wb_mode;//0 - 4 192 | uint8_t awb; 193 | uint8_t awb_gain; 194 | uint8_t aec; 195 | uint8_t aec2; 196 | int8_t ae_level;//-2 - 2 197 | uint16_t aec_value;//0 - 1200 198 | uint8_t agc; 199 | uint8_t agc_gain;//0 - 30 200 | uint8_t gainceiling;//0 - 6 201 | uint8_t bpc; 202 | uint8_t wpc; 203 | uint8_t raw_gma; 204 | uint8_t lenc; 205 | uint8_t hmirror; 206 | uint8_t vflip; 207 | uint8_t dcw; 208 | uint8_t colorbar; 209 | } camera_status_t; 210 | 211 | typedef struct _sensor sensor_t; 212 | typedef struct _sensor { 213 | sensor_id_t id; // Sensor ID. 214 | uint8_t slv_addr; // Sensor I2C slave address. 215 | pixformat_t pixformat; 216 | camera_status_t status; 217 | int xclk_freq_hz; 218 | 219 | // Sensor function pointers 220 | int (*init_status) (sensor_t *sensor); 221 | int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful 222 | int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat); 223 | int (*set_framesize) (sensor_t *sensor, framesize_t framesize); 224 | int (*set_contrast) (sensor_t *sensor, int level); 225 | int (*set_brightness) (sensor_t *sensor, int level); 226 | int (*set_saturation) (sensor_t *sensor, int level); 227 | int (*set_sharpness) (sensor_t *sensor, int level); 228 | int (*set_denoise) (sensor_t *sensor, int level); 229 | int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling); 230 | int (*set_quality) (sensor_t *sensor, int quality); 231 | int (*set_colorbar) (sensor_t *sensor, int enable); 232 | int (*set_whitebal) (sensor_t *sensor, int enable); 233 | int (*set_gain_ctrl) (sensor_t *sensor, int enable); 234 | int (*set_exposure_ctrl) (sensor_t *sensor, int enable); 235 | int (*set_hmirror) (sensor_t *sensor, int enable); 236 | int (*set_vflip) (sensor_t *sensor, int enable); 237 | 238 | int (*set_aec2) (sensor_t *sensor, int enable); 239 | int (*set_awb_gain) (sensor_t *sensor, int enable); 240 | int (*set_agc_gain) (sensor_t *sensor, int gain); 241 | int (*set_aec_value) (sensor_t *sensor, int gain); 242 | 243 | int (*set_special_effect) (sensor_t *sensor, int effect); 244 | int (*set_wb_mode) (sensor_t *sensor, int mode); 245 | int (*set_ae_level) (sensor_t *sensor, int level); 246 | 247 | int (*set_dcw) (sensor_t *sensor, int enable); 248 | int (*set_bpc) (sensor_t *sensor, int enable); 249 | int (*set_wpc) (sensor_t *sensor, int enable); 250 | 251 | int (*set_raw_gma) (sensor_t *sensor, int enable); 252 | int (*set_lenc) (sensor_t *sensor, int enable); 253 | 254 | int (*get_reg) (sensor_t *sensor, int reg, int mask); 255 | int (*set_reg) (sensor_t *sensor, int reg, int mask, int value); 256 | 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); 257 | int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk); 258 | int (*set_xclk) (sensor_t *sensor, int timer, int xclk); 259 | } sensor_t; 260 | 261 | camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id); 262 | 263 | #ifdef __cplusplus 264 | } 265 | #endif 266 | 267 | #endif /* __SENSOR_H__ */ 268 | -------------------------------------------------------------------------------- /driver/private_include/cam_hal.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_camera.h" 18 | 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Uninitialize the lcd_cam module 26 | * 27 | * @param handle Provide handle pointer to release resources 28 | * 29 | * @return 30 | * - ESP_OK Success 31 | * - ESP_FAIL Uninitialize fail 32 | */ 33 | esp_err_t cam_deinit(void); 34 | 35 | /** 36 | * @brief Initialize the lcd_cam module 37 | * 38 | * @param config Configurations - see lcd_cam_config_t struct 39 | * 40 | * @return 41 | * - ESP_OK Success 42 | * - ESP_ERR_INVALID_ARG Parameter error 43 | * - ESP_ERR_NO_MEM No memory to initialize lcd_cam 44 | * - ESP_FAIL Initialize fail 45 | */ 46 | esp_err_t cam_init(const camera_config_t *config); 47 | 48 | esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint16_t sensor_pid); 49 | 50 | void cam_stop(void); 51 | 52 | void cam_start(void); 53 | 54 | camera_fb_t *cam_take(TickType_t timeout); 55 | 56 | void cam_give(camera_fb_t *dma_buffer); 57 | 58 | void cam_give_all(void); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /driver/private_include/sccb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | #ifndef __SCCB_H__ 10 | #define __SCCB_H__ 11 | #include 12 | int SCCB_Init(int pin_sda, int pin_scl); 13 | int SCCB_Use_Port(int sccb_i2c_port); 14 | int SCCB_Deinit(void); 15 | uint8_t SCCB_Probe(void); 16 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg); 17 | int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data); 18 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg); 19 | int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data); 20 | uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg); 21 | int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data); 22 | #endif // __SCCB_H__ 23 | -------------------------------------------------------------------------------- /driver/private_include/xclk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "esp_system.h" 4 | #include "esp_camera.h" 5 | 6 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz); 7 | 8 | esp_err_t camera_enable_out_clock(const camera_config_t *config); 9 | 10 | void camera_disable_out_clock(void); 11 | -------------------------------------------------------------------------------- /driver/sccb-ng.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver with the new esp-idf I2C API. 7 | * 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "sccb.h" 14 | #include "sensor.h" 15 | #include 16 | #include "sdkconfig.h" 17 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 18 | #include "esp32-hal-log.h" 19 | #else 20 | #include "esp_log.h" 21 | static const char *TAG = "sccb-ng"; 22 | #endif 23 | 24 | #define LITTLETOBIG(x) ((x << 8) | (x >> 8)) 25 | 26 | #include "esp_private/i2c_platform.h" 27 | #include "driver/i2c_master.h" 28 | #include "driver/i2c_types.h" 29 | 30 | // support IDF 5.x 31 | #ifndef portTICK_RATE_MS 32 | #define portTICK_RATE_MS portTICK_PERIOD_MS 33 | #endif 34 | 35 | #define TIMEOUT_MS 1000 /*!< I2C timeout duration */ 36 | #define SCCB_FREQ CONFIG_SCCB_CLK_FREQ /*!< I2C master frequency */ 37 | #if CONFIG_SCCB_HARDWARE_I2C_PORT1 38 | const int SCCB_I2C_PORT_DEFAULT = 1; 39 | #else 40 | const int SCCB_I2C_PORT_DEFAULT = 0; 41 | #endif 42 | 43 | #define MAX_DEVICES UINT8_MAX-1 44 | 45 | /* 46 | The legacy I2C driver used addresses to differentiate between devices, whereas the new driver uses 47 | i2c_master_dev_handle_t structs which are registed to the bus. 48 | To avoid re-writing all camera dependant code, we simply translate the devices address to the corresponding 49 | device_handle. This keeps all interfaces to the drivers identical. 50 | To perform this conversion the following local struct is used. 51 | */ 52 | typedef struct 53 | { 54 | i2c_master_dev_handle_t dev_handle; 55 | uint16_t address; 56 | } device_t; 57 | 58 | static device_t devices[MAX_DEVICES]; 59 | static uint8_t device_count = 0; 60 | static int sccb_i2c_port; 61 | static bool sccb_owns_i2c_port; 62 | 63 | i2c_master_dev_handle_t *get_handle_from_address(uint8_t slv_addr) 64 | { 65 | for (uint8_t i = 0; i < device_count; i++) 66 | { 67 | 68 | if (slv_addr == devices[i].address) 69 | { 70 | return &(devices[i].dev_handle); 71 | } 72 | } 73 | 74 | ESP_LOGE(TAG, "Device with address %02x not found", slv_addr); 75 | return NULL; 76 | } 77 | 78 | int SCCB_Install_Device(uint8_t slv_addr) 79 | { 80 | esp_err_t ret; 81 | i2c_master_bus_handle_t bus_handle; 82 | 83 | if (device_count > MAX_DEVICES) 84 | { 85 | ESP_LOGE(TAG, "cannot add more than %d devices", MAX_DEVICES); 86 | return ESP_FAIL; 87 | } 88 | 89 | ret = i2c_master_get_bus_handle(sccb_i2c_port, &bus_handle); 90 | if (ret != ESP_OK) 91 | { 92 | ESP_LOGE(TAG, "failed to get SCCB I2C Bus handle for port %d", sccb_i2c_port); 93 | return ret; 94 | } 95 | 96 | i2c_device_config_t dev_cfg = { 97 | .dev_addr_length = I2C_ADDR_BIT_LEN_7, 98 | .device_address = slv_addr, // not yet set 99 | .scl_speed_hz = SCCB_FREQ, 100 | }; 101 | 102 | ret = i2c_master_bus_add_device(bus_handle, &dev_cfg, &(devices[device_count].dev_handle)); 103 | if (ret != ESP_OK) 104 | { 105 | ESP_LOGE(TAG, "failed to install SCCB I2C device: %s", esp_err_to_name(ret)); 106 | return -1; 107 | } 108 | 109 | devices[device_count].address = slv_addr; 110 | device_count++; 111 | return 0; 112 | } 113 | 114 | int SCCB_Init(int pin_sda, int pin_scl) 115 | { 116 | ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); 117 | // i2c_config_t conf; 118 | esp_err_t ret; 119 | 120 | sccb_i2c_port = SCCB_I2C_PORT_DEFAULT; 121 | sccb_owns_i2c_port = true; 122 | ESP_LOGI(TAG, "sccb_i2c_port=%d", sccb_i2c_port); 123 | 124 | i2c_master_bus_config_t i2c_mst_config = { 125 | .clk_source = I2C_CLK_SRC_DEFAULT, 126 | .i2c_port = SCCB_I2C_PORT_DEFAULT, 127 | .scl_io_num = pin_scl, 128 | .sda_io_num = pin_sda, 129 | .glitch_ignore_cnt = 7, 130 | .flags.enable_internal_pullup = 1}; 131 | 132 | i2c_master_bus_handle_t bus_handle; 133 | ret = i2c_new_master_bus(&i2c_mst_config, &bus_handle); 134 | 135 | if (ret != ESP_OK) 136 | { 137 | ESP_LOGE(TAG, "failed to install SCCB I2C master bus on port %d: %s", sccb_i2c_port, esp_err_to_name(ret)); 138 | return ret; 139 | } 140 | 141 | return ESP_OK; 142 | } 143 | 144 | int SCCB_Use_Port(int i2c_num) 145 | { // sccb use an already initialized I2C port 146 | if (sccb_owns_i2c_port) 147 | { 148 | SCCB_Deinit(); 149 | } 150 | if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) 151 | { 152 | return ESP_ERR_INVALID_ARG; 153 | } 154 | sccb_i2c_port = i2c_num; 155 | 156 | return ESP_OK; 157 | } 158 | 159 | int SCCB_Deinit(void) 160 | { 161 | esp_err_t ret; 162 | 163 | for (uint8_t i = 0; i < device_count; i++) 164 | { 165 | ret = i2c_master_bus_rm_device(devices[i].dev_handle); 166 | if (ret != ESP_OK) 167 | { 168 | ESP_LOGE(TAG, "failed to remove SCCB I2C Device"); 169 | return ret; 170 | } 171 | 172 | devices[i].dev_handle = NULL; 173 | devices[i].address = 0; 174 | } 175 | device_count = 0; 176 | 177 | if (!sccb_owns_i2c_port) 178 | { 179 | return ESP_OK; 180 | } 181 | sccb_owns_i2c_port = false; 182 | 183 | i2c_master_bus_handle_t bus_handle; 184 | ret = i2c_master_get_bus_handle(sccb_i2c_port, &bus_handle); 185 | if (ret != ESP_OK) 186 | { 187 | ESP_LOGE(TAG, "failed to get SCCB I2C Bus handle for port %d", sccb_i2c_port); 188 | return ret; 189 | } 190 | 191 | ret = i2c_del_master_bus(bus_handle); 192 | if (ret != ESP_OK) 193 | { 194 | ESP_LOGE(TAG, "failed to get delete SCCB I2C Master Bus at port %d", sccb_i2c_port); 195 | return ret; 196 | } 197 | 198 | return ESP_OK; 199 | } 200 | 201 | uint8_t SCCB_Probe(void) 202 | { 203 | uint8_t slave_addr = 0x0; 204 | esp_err_t ret; 205 | i2c_master_bus_handle_t bus_handle; 206 | 207 | ret = i2c_master_get_bus_handle(sccb_i2c_port, &bus_handle); 208 | if (ret != ESP_OK) 209 | { 210 | ESP_LOGE(TAG, "failed to get SCCB I2C Bus handle for port %d", sccb_i2c_port); 211 | return ret; 212 | } 213 | 214 | for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) 215 | { 216 | if (slave_addr == camera_sensor[i].sccb_addr) 217 | { 218 | continue; 219 | } 220 | slave_addr = camera_sensor[i].sccb_addr; 221 | 222 | ret = i2c_master_probe(bus_handle, slave_addr, TIMEOUT_MS); 223 | 224 | if (ret == ESP_OK) 225 | { 226 | if (SCCB_Install_Device(slave_addr) != 0) 227 | { 228 | return 0; 229 | } 230 | return slave_addr; 231 | } 232 | } 233 | return 0; 234 | } 235 | 236 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) 237 | { 238 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 239 | 240 | uint8_t tx_buffer[1]; 241 | uint8_t rx_buffer[1]; 242 | 243 | tx_buffer[0] = reg; 244 | 245 | esp_err_t ret = i2c_master_transmit_receive(dev_handle, tx_buffer, 1, rx_buffer, 1, TIMEOUT_MS); 246 | 247 | if (ret != ESP_OK) 248 | { 249 | ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, rx_buffer[0], ret); 250 | } 251 | 252 | return rx_buffer[0]; 253 | } 254 | 255 | int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) 256 | { 257 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 258 | 259 | uint8_t tx_buffer[2]; 260 | tx_buffer[0] = reg; 261 | tx_buffer[1] = data; 262 | 263 | esp_err_t ret = i2c_master_transmit(dev_handle, tx_buffer, 2, TIMEOUT_MS); 264 | 265 | if (ret != ESP_OK) 266 | { 267 | ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 268 | } 269 | 270 | return ret == ESP_OK ? 0 : -1; 271 | } 272 | 273 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) 274 | { 275 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 276 | 277 | uint8_t rx_buffer[1]; 278 | 279 | uint16_t reg_htons = LITTLETOBIG(reg); 280 | uint8_t *reg_u8 = (uint8_t *)®_htons; 281 | 282 | esp_err_t ret = i2c_master_transmit_receive(dev_handle, reg_u8, 2, rx_buffer, 1, TIMEOUT_MS); 283 | 284 | if (ret != ESP_OK) 285 | { 286 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, rx_buffer[0]); 287 | } 288 | 289 | return rx_buffer[0]; 290 | } 291 | 292 | int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) 293 | { 294 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 295 | 296 | uint8_t tx_buffer[3]; 297 | tx_buffer[0] = reg >> 8; 298 | tx_buffer[1] = reg & 0x00ff; 299 | tx_buffer[2] = data; 300 | 301 | esp_err_t ret = i2c_master_transmit(dev_handle, tx_buffer, 3, TIMEOUT_MS); 302 | 303 | if (ret != ESP_OK) 304 | { 305 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 306 | } 307 | return ret == ESP_OK ? 0 : -1; 308 | } 309 | 310 | uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg) 311 | { 312 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 313 | 314 | uint8_t rx_buffer[2]; 315 | 316 | uint16_t reg_htons = LITTLETOBIG(reg); 317 | uint8_t *reg_u8 = (uint8_t *)®_htons; 318 | 319 | esp_err_t ret = i2c_master_transmit_receive(dev_handle, reg_u8, 2, rx_buffer, 2, TIMEOUT_MS); 320 | uint16_t data = ((uint16_t)rx_buffer[0] << 8) | (uint16_t)rx_buffer[1]; 321 | 322 | if (ret != ESP_OK) 323 | { 324 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 325 | } 326 | 327 | return data; 328 | } 329 | 330 | int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data) 331 | { 332 | i2c_master_dev_handle_t dev_handle = *(get_handle_from_address(slv_addr)); 333 | 334 | uint8_t tx_buffer[4]; 335 | tx_buffer[0] = reg >> 8; 336 | tx_buffer[1] = reg & 0x00ff; 337 | tx_buffer[2] = data >> 8; 338 | tx_buffer[3] = data & 0x00ff; 339 | 340 | esp_err_t ret = i2c_master_transmit(dev_handle, tx_buffer, 4, TIMEOUT_MS); 341 | 342 | if (ret != ESP_OK) 343 | { 344 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 345 | } 346 | return ret == ESP_OK ? 0 : -1; 347 | } 348 | -------------------------------------------------------------------------------- /driver/sccb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * SCCB (I2C like) driver. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "sccb.h" 15 | #include "sensor.h" 16 | #include 17 | #include "sdkconfig.h" 18 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 19 | #include "esp32-hal-log.h" 20 | #else 21 | #include "esp_log.h" 22 | static const char* TAG = "sccb"; 23 | #endif 24 | 25 | #define LITTLETOBIG(x) ((x<<8)|(x>>8)) 26 | 27 | #include "driver/i2c.h" 28 | 29 | // support IDF 5.x 30 | #ifndef portTICK_RATE_MS 31 | #define portTICK_RATE_MS portTICK_PERIOD_MS 32 | #endif 33 | 34 | #define SCCB_FREQ CONFIG_SCCB_CLK_FREQ /*!< I2C master frequency*/ 35 | #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ 36 | #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ 37 | #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ 38 | #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ 39 | #define ACK_VAL 0x0 /*!< I2C ack value */ 40 | #define NACK_VAL 0x1 /*!< I2C nack value */ 41 | #if CONFIG_SCCB_HARDWARE_I2C_PORT1 42 | const int SCCB_I2C_PORT_DEFAULT = 1; 43 | #else 44 | const int SCCB_I2C_PORT_DEFAULT = 0; 45 | #endif 46 | 47 | static int sccb_i2c_port; 48 | static bool sccb_owns_i2c_port; 49 | 50 | int SCCB_Init(int pin_sda, int pin_scl) 51 | { 52 | ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl); 53 | i2c_config_t conf; 54 | esp_err_t ret; 55 | 56 | memset(&conf, 0, sizeof(i2c_config_t)); 57 | 58 | sccb_i2c_port = SCCB_I2C_PORT_DEFAULT; 59 | sccb_owns_i2c_port = true; 60 | ESP_LOGI(TAG, "sccb_i2c_port=%d", sccb_i2c_port); 61 | 62 | conf.mode = I2C_MODE_MASTER; 63 | conf.sda_io_num = pin_sda; 64 | conf.sda_pullup_en = GPIO_PULLUP_ENABLE; 65 | conf.scl_io_num = pin_scl; 66 | conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 67 | conf.master.clk_speed = SCCB_FREQ; 68 | 69 | if ((ret = i2c_param_config(sccb_i2c_port, &conf)) != ESP_OK) { 70 | return ret; 71 | } 72 | 73 | return i2c_driver_install(sccb_i2c_port, conf.mode, 0, 0, 0); 74 | } 75 | 76 | int SCCB_Use_Port(int i2c_num) { // sccb use an already initialized I2C port 77 | if (sccb_owns_i2c_port) { 78 | SCCB_Deinit(); 79 | } 80 | if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) { 81 | return ESP_ERR_INVALID_ARG; 82 | } 83 | sccb_i2c_port = i2c_num; 84 | return ESP_OK; 85 | } 86 | 87 | int SCCB_Deinit(void) 88 | { 89 | if (!sccb_owns_i2c_port) { 90 | return ESP_OK; 91 | } 92 | sccb_owns_i2c_port = false; 93 | return i2c_driver_delete(sccb_i2c_port); 94 | } 95 | 96 | uint8_t SCCB_Probe(void) 97 | { 98 | uint8_t slave_addr = 0x0; 99 | 100 | for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) { 101 | if (slave_addr == camera_sensor[i].sccb_addr) { 102 | continue; 103 | } 104 | slave_addr = camera_sensor[i].sccb_addr; 105 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 106 | i2c_master_start(cmd); 107 | i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 108 | i2c_master_stop(cmd); 109 | esp_err_t ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 110 | i2c_cmd_link_delete(cmd); 111 | if( ret == ESP_OK) { 112 | return slave_addr; 113 | } 114 | } 115 | return 0; 116 | } 117 | 118 | uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg) 119 | { 120 | uint8_t data=0; 121 | esp_err_t ret = ESP_FAIL; 122 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 123 | i2c_master_start(cmd); 124 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 125 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 126 | i2c_master_stop(cmd); 127 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 128 | i2c_cmd_link_delete(cmd); 129 | if(ret != ESP_OK) return -1; 130 | cmd = i2c_cmd_link_create(); 131 | i2c_master_start(cmd); 132 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 133 | i2c_master_read_byte(cmd, &data, NACK_VAL); 134 | i2c_master_stop(cmd); 135 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 136 | i2c_cmd_link_delete(cmd); 137 | if(ret != ESP_OK) { 138 | ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 139 | } 140 | return data; 141 | } 142 | 143 | int SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data) 144 | { 145 | esp_err_t ret = ESP_FAIL; 146 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 147 | i2c_master_start(cmd); 148 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 149 | i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); 150 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 151 | i2c_master_stop(cmd); 152 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 153 | i2c_cmd_link_delete(cmd); 154 | if(ret != ESP_OK) { 155 | ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret); 156 | } 157 | return ret == ESP_OK ? 0 : -1; 158 | } 159 | 160 | uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg) 161 | { 162 | uint8_t data=0; 163 | esp_err_t ret = ESP_FAIL; 164 | uint16_t reg_htons = LITTLETOBIG(reg); 165 | uint8_t *reg_u8 = (uint8_t *)®_htons; 166 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 167 | i2c_master_start(cmd); 168 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 169 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 170 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 171 | i2c_master_stop(cmd); 172 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 173 | i2c_cmd_link_delete(cmd); 174 | if(ret != ESP_OK) return -1; 175 | cmd = i2c_cmd_link_create(); 176 | i2c_master_start(cmd); 177 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 178 | i2c_master_read_byte(cmd, &data, NACK_VAL); 179 | i2c_master_stop(cmd); 180 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 181 | i2c_cmd_link_delete(cmd); 182 | if(ret != ESP_OK) { 183 | ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data); 184 | } 185 | return data; 186 | } 187 | 188 | int SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data) 189 | { 190 | static uint16_t i = 0; 191 | esp_err_t ret = ESP_FAIL; 192 | uint16_t reg_htons = LITTLETOBIG(reg); 193 | uint8_t *reg_u8 = (uint8_t *)®_htons; 194 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 195 | i2c_master_start(cmd); 196 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 197 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 198 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 199 | i2c_master_write_byte(cmd, data, ACK_CHECK_EN); 200 | i2c_master_stop(cmd); 201 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 202 | i2c_cmd_link_delete(cmd); 203 | if(ret != ESP_OK) { 204 | ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++); 205 | } 206 | return ret == ESP_OK ? 0 : -1; 207 | } 208 | 209 | uint16_t SCCB_Read_Addr16_Val16(uint8_t slv_addr, uint16_t reg) 210 | { 211 | uint16_t data = 0; 212 | uint8_t *data_u8 = (uint8_t *)&data; 213 | esp_err_t ret = ESP_FAIL; 214 | uint16_t reg_htons = LITTLETOBIG(reg); 215 | uint8_t *reg_u8 = (uint8_t *)®_htons; 216 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 217 | i2c_master_start(cmd); 218 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 219 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 220 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 221 | i2c_master_stop(cmd); 222 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 223 | i2c_cmd_link_delete(cmd); 224 | if(ret != ESP_OK) return -1; 225 | 226 | cmd = i2c_cmd_link_create(); 227 | i2c_master_start(cmd); 228 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN); 229 | i2c_master_read_byte(cmd, &data_u8[1], ACK_VAL); 230 | i2c_master_read_byte(cmd, &data_u8[0], NACK_VAL); 231 | i2c_master_stop(cmd); 232 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 233 | i2c_cmd_link_delete(cmd); 234 | if(ret != ESP_OK) { 235 | ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); 236 | } 237 | return data; 238 | } 239 | 240 | int SCCB_Write_Addr16_Val16(uint8_t slv_addr, uint16_t reg, uint16_t data) 241 | { 242 | esp_err_t ret = ESP_FAIL; 243 | uint16_t reg_htons = LITTLETOBIG(reg); 244 | uint8_t *reg_u8 = (uint8_t *)®_htons; 245 | uint16_t data_htons = LITTLETOBIG(data); 246 | uint8_t *data_u8 = (uint8_t *)&data_htons; 247 | i2c_cmd_handle_t cmd = i2c_cmd_link_create(); 248 | i2c_master_start(cmd); 249 | i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN); 250 | i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN); 251 | i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN); 252 | i2c_master_write_byte(cmd, data_u8[0], ACK_CHECK_EN); 253 | i2c_master_write_byte(cmd, data_u8[1], ACK_CHECK_EN); 254 | i2c_master_stop(cmd); 255 | ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS); 256 | i2c_cmd_link_delete(cmd); 257 | if(ret != ESP_OK) { 258 | ESP_LOGE(TAG, "W [%04x]=%04x fail\n", reg, data); 259 | } 260 | return ret == ESP_OK ? 0 : -1; 261 | } 262 | -------------------------------------------------------------------------------- /driver/sensor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sensor.h" 3 | 4 | const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = { 5 | // The sequence must be consistent with camera_model_t 6 | {CAMERA_OV7725, "OV7725", OV7725_SCCB_ADDR, OV7725_PID, FRAMESIZE_VGA, false}, 7 | {CAMERA_OV2640, "OV2640", OV2640_SCCB_ADDR, OV2640_PID, FRAMESIZE_UXGA, true}, 8 | {CAMERA_OV3660, "OV3660", OV3660_SCCB_ADDR, OV3660_PID, FRAMESIZE_QXGA, true}, 9 | {CAMERA_OV5640, "OV5640", OV5640_SCCB_ADDR, OV5640_PID, FRAMESIZE_QSXGA, true}, 10 | {CAMERA_OV7670, "OV7670", OV7670_SCCB_ADDR, OV7670_PID, FRAMESIZE_VGA, false}, 11 | {CAMERA_NT99141, "NT99141", NT99141_SCCB_ADDR, NT99141_PID, FRAMESIZE_HD, true}, 12 | {CAMERA_GC2145, "GC2145", GC2145_SCCB_ADDR, GC2145_PID, FRAMESIZE_UXGA, false}, 13 | {CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false}, 14 | {CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false}, 15 | {CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false}, 16 | {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false}, 17 | {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false}, 18 | {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false}, 19 | {CAMERA_SC031GS, "SC031GS", SC031GS_SCCB_ADDR, SC031GS_PID, FRAMESIZE_VGA, false}, 20 | {CAMERA_MEGA_CCM, "MEGA_CCM", MEGA_CCM_SCCB_ADDR, MEGA_CCM_PID, FRAMESIZE_5MP, true}, 21 | }; 22 | 23 | const resolution_info_t resolution[FRAMESIZE_INVALID] = { 24 | { 96, 96, ASPECT_RATIO_1X1 }, /* 96x96 */ 25 | { 160, 120, ASPECT_RATIO_4X3 }, /* QQVGA */ 26 | { 128, 128, ASPECT_RATIO_1X1 }, /* 128x128 */ 27 | { 176, 144, ASPECT_RATIO_5X4 }, /* QCIF */ 28 | { 240, 176, ASPECT_RATIO_4X3 }, /* HQVGA */ 29 | { 240, 240, ASPECT_RATIO_1X1 }, /* 240x240 */ 30 | { 320, 240, ASPECT_RATIO_4X3 }, /* QVGA */ 31 | { 320, 320, ASPECT_RATIO_1X1 }, /* 320x320 */ 32 | { 400, 296, ASPECT_RATIO_4X3 }, /* CIF */ 33 | { 480, 320, ASPECT_RATIO_3X2 }, /* HVGA */ 34 | { 640, 480, ASPECT_RATIO_4X3 }, /* VGA */ 35 | { 800, 600, ASPECT_RATIO_4X3 }, /* SVGA */ 36 | { 1024, 768, ASPECT_RATIO_4X3 }, /* XGA */ 37 | { 1280, 720, ASPECT_RATIO_16X9 }, /* HD */ 38 | { 1280, 1024, ASPECT_RATIO_5X4 }, /* SXGA */ 39 | { 1600, 1200, ASPECT_RATIO_4X3 }, /* UXGA */ 40 | // 3MP Sensors 41 | { 1920, 1080, ASPECT_RATIO_16X9 }, /* FHD */ 42 | { 720, 1280, ASPECT_RATIO_9X16 }, /* Portrait HD */ 43 | { 864, 1536, ASPECT_RATIO_9X16 }, /* Portrait 3MP */ 44 | { 2048, 1536, ASPECT_RATIO_4X3 }, /* QXGA */ 45 | // 5MP Sensors 46 | { 2560, 1440, ASPECT_RATIO_16X9 }, /* QHD */ 47 | { 2560, 1600, ASPECT_RATIO_16X10 }, /* WQXGA */ 48 | { 1088, 1920, ASPECT_RATIO_9X16 }, /* Portrait FHD */ 49 | { 2560, 1920, ASPECT_RATIO_4X3 }, /* QSXGA */ 50 | { 2592, 1944, ASPECT_RATIO_4X3 }, /* 5MP */ 51 | }; 52 | 53 | camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id) 54 | { 55 | for (int i = 0; i < CAMERA_MODEL_MAX; i++) { 56 | if (id->PID == camera_sensor[i].pid) { 57 | return (camera_sensor_info_t *)&camera_sensor[i]; 58 | } 59 | } 60 | return NULL; 61 | } 62 | -------------------------------------------------------------------------------- /examples/camera_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | set(COMPONENTS main) 6 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 7 | project(camera_example) 8 | -------------------------------------------------------------------------------- /examples/camera_example/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS take_picture.c 2 | PRIV_INCLUDE_DIRS . 3 | PRIV_REQUIRES nvs_flash esp_psram) 4 | -------------------------------------------------------------------------------- /examples/camera_example/main/idf_component.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | espressif/esp32-camera: 3 | version: "*" 4 | override_path: "../../../" 5 | 6 | -------------------------------------------------------------------------------- /examples/camera_example/main/take_picture.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This example takes a picture every 5s and print its size on serial monitor. 3 | */ 4 | 5 | // =============================== SETUP ====================================== 6 | 7 | // 1. Board setup (Uncomment): 8 | // #define BOARD_WROVER_KIT 9 | // #define BOARD_ESP32CAM_AITHINKER 10 | // #define BOARD_ESP32S3_WROOM 11 | 12 | /** 13 | * 2. Kconfig setup 14 | * 15 | * If you have a Kconfig file, copy the content from 16 | * https://github.com/espressif/esp32-camera/blob/master/Kconfig into it. 17 | * In case you haven't, copy and paste this Kconfig file inside the src directory. 18 | * This Kconfig file has definitions that allows more control over the camera and 19 | * how it will be initialized. 20 | */ 21 | 22 | /** 23 | * 3. Enable PSRAM on sdkconfig: 24 | * 25 | * CONFIG_ESP32_SPIRAM_SUPPORT=y 26 | * 27 | * More info on 28 | * https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support 29 | */ 30 | 31 | // ================================ CODE ====================================== 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "freertos/FreeRTOS.h" 40 | #include "freertos/task.h" 41 | 42 | // support IDF 5.x 43 | #ifndef portTICK_RATE_MS 44 | #define portTICK_RATE_MS portTICK_PERIOD_MS 45 | #endif 46 | 47 | #include "esp_camera.h" 48 | 49 | #define BOARD_WROVER_KIT 1 50 | 51 | // WROVER-KIT PIN Map 52 | #ifdef BOARD_WROVER_KIT 53 | 54 | #define CAM_PIN_PWDN -1 //power down is not used 55 | #define CAM_PIN_RESET -1 //software reset will be performed 56 | #define CAM_PIN_XCLK 21 57 | #define CAM_PIN_SIOD 26 58 | #define CAM_PIN_SIOC 27 59 | 60 | #define CAM_PIN_D7 35 61 | #define CAM_PIN_D6 34 62 | #define CAM_PIN_D5 39 63 | #define CAM_PIN_D4 36 64 | #define CAM_PIN_D3 19 65 | #define CAM_PIN_D2 18 66 | #define CAM_PIN_D1 5 67 | #define CAM_PIN_D0 4 68 | #define CAM_PIN_VSYNC 25 69 | #define CAM_PIN_HREF 23 70 | #define CAM_PIN_PCLK 22 71 | 72 | #endif 73 | 74 | // ESP32Cam (AiThinker) PIN Map 75 | #ifdef BOARD_ESP32CAM_AITHINKER 76 | 77 | #define CAM_PIN_PWDN 32 78 | #define CAM_PIN_RESET -1 //software reset will be performed 79 | #define CAM_PIN_XCLK 0 80 | #define CAM_PIN_SIOD 26 81 | #define CAM_PIN_SIOC 27 82 | 83 | #define CAM_PIN_D7 35 84 | #define CAM_PIN_D6 34 85 | #define CAM_PIN_D5 39 86 | #define CAM_PIN_D4 36 87 | #define CAM_PIN_D3 21 88 | #define CAM_PIN_D2 19 89 | #define CAM_PIN_D1 18 90 | #define CAM_PIN_D0 5 91 | #define CAM_PIN_VSYNC 25 92 | #define CAM_PIN_HREF 23 93 | #define CAM_PIN_PCLK 22 94 | 95 | #endif 96 | // ESP32S3 (WROOM) PIN Map 97 | #ifdef BOARD_ESP32S3_WROOM 98 | #define CAM_PIN_PWDN 38 99 | #define CAM_PIN_RESET -1 //software reset will be performed 100 | #define CAM_PIN_VSYNC 6 101 | #define CAM_PIN_HREF 7 102 | #define CAM_PIN_PCLK 13 103 | #define CAM_PIN_XCLK 15 104 | #define CAM_PIN_SIOD 4 105 | #define CAM_PIN_SIOC 5 106 | #define CAM_PIN_D0 11 107 | #define CAM_PIN_D1 9 108 | #define CAM_PIN_D2 8 109 | #define CAM_PIN_D3 10 110 | #define CAM_PIN_D4 12 111 | #define CAM_PIN_D5 18 112 | #define CAM_PIN_D6 17 113 | #define CAM_PIN_D7 16 114 | #endif 115 | static const char *TAG = "example:take_picture"; 116 | 117 | #if ESP_CAMERA_SUPPORTED 118 | static camera_config_t camera_config = { 119 | .pin_pwdn = CAM_PIN_PWDN, 120 | .pin_reset = CAM_PIN_RESET, 121 | .pin_xclk = CAM_PIN_XCLK, 122 | .pin_sccb_sda = CAM_PIN_SIOD, 123 | .pin_sccb_scl = CAM_PIN_SIOC, 124 | 125 | .pin_d7 = CAM_PIN_D7, 126 | .pin_d6 = CAM_PIN_D6, 127 | .pin_d5 = CAM_PIN_D5, 128 | .pin_d4 = CAM_PIN_D4, 129 | .pin_d3 = CAM_PIN_D3, 130 | .pin_d2 = CAM_PIN_D2, 131 | .pin_d1 = CAM_PIN_D1, 132 | .pin_d0 = CAM_PIN_D0, 133 | .pin_vsync = CAM_PIN_VSYNC, 134 | .pin_href = CAM_PIN_HREF, 135 | .pin_pclk = CAM_PIN_PCLK, 136 | 137 | //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) 138 | .xclk_freq_hz = 20000000, 139 | .ledc_timer = LEDC_TIMER_0, 140 | .ledc_channel = LEDC_CHANNEL_0, 141 | 142 | .pixel_format = PIXFORMAT_RGB565, //YUV422,GRAYSCALE,RGB565,JPEG 143 | .frame_size = FRAMESIZE_QVGA, //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. 144 | 145 | .jpeg_quality = 12, //0-63, for OV series camera sensors, lower number means higher quality 146 | .fb_count = 1, //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode. 147 | .fb_location = CAMERA_FB_IN_PSRAM, 148 | .grab_mode = CAMERA_GRAB_WHEN_EMPTY, 149 | }; 150 | 151 | static esp_err_t init_camera(void) 152 | { 153 | //initialize the camera 154 | esp_err_t err = esp_camera_init(&camera_config); 155 | if (err != ESP_OK) 156 | { 157 | ESP_LOGE(TAG, "Camera Init Failed"); 158 | return err; 159 | } 160 | 161 | return ESP_OK; 162 | } 163 | #endif 164 | 165 | void app_main(void) 166 | { 167 | #if ESP_CAMERA_SUPPORTED 168 | if(ESP_OK != init_camera()) { 169 | return; 170 | } 171 | 172 | while (1) 173 | { 174 | ESP_LOGI(TAG, "Taking picture..."); 175 | camera_fb_t *pic = esp_camera_fb_get(); 176 | 177 | // use pic->buf to access the image 178 | ESP_LOGI(TAG, "Picture taken! Its size was: %zu bytes", pic->len); 179 | esp_camera_fb_return(pic); 180 | 181 | vTaskDelay(5000 / portTICK_RATE_MS); 182 | } 183 | #else 184 | ESP_LOGE(TAG, "Camera support is not available for this chip"); 185 | return; 186 | #endif 187 | } 188 | -------------------------------------------------------------------------------- /examples/camera_example/sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y 2 | CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y 3 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y 4 | 5 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y 6 | CONFIG_PARTITION_TABLE_OFFSET=0x10000 7 | 8 | CONFIG_FREERTOS_HZ=1000 9 | CONFIG_ESPTOOLPY_FLASHFREQ_80M=y 10 | CONFIG_ESPTOOLPY_FLASHMODE_QIO=y 11 | 12 | CONFIG_SPIRAM_SUPPORT=y 13 | CONFIG_ESP32_SPIRAM_SUPPORT=y 14 | CONFIG_ESP32S2_SPIRAM_SUPPORT=y 15 | CONFIG_ESP32S3_SPIRAM_SUPPORT=y 16 | CONFIG_SPIRAM_SPEED_80M=y 17 | 18 | -------------------------------------------------------------------------------- /idf_component.yml: -------------------------------------------------------------------------------- 1 | description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors. 2 | url: https://github.com/espressif/esp32-camera 3 | issues: https://github.com/espressif/esp32-camera/issues 4 | documentation: https://github.com/espressif/esp32-camera/tree/main/README.md 5 | repository: https://github.com/espressif/esp32-camera.git 6 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "esp32-camera", 3 | "version": "2.0.0", 4 | "keywords": "esp32, camera, espressif, esp32-cam", 5 | "description": "ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/espressif/esp32-camera" 9 | }, 10 | "frameworks": "espidf", 11 | "platforms": "*", 12 | "build": { 13 | "flags": [ 14 | "-Idriver/include", 15 | "-Iconversions/include", 16 | "-Idriver/private_include", 17 | "-Iconversions/private_include", 18 | "-Isensors/private_include", 19 | "-Itarget/private_include", 20 | "-fno-rtti" 21 | ], 22 | "includeDir": ".", 23 | "srcDir": ".", 24 | "srcFilter": ["-<*>", "+", "+", "+"] 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /sensors/private_include/bf20a6.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __BF20A6_H__ 3 | #define __BF20A6_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int bf20a6_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int bf20a6_init(sensor_t *sensor); 26 | 27 | #endif // __BF20A6_H__ 28 | -------------------------------------------------------------------------------- /sensors/private_include/bf20a6_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BF20A6 register definitions. 3 | */ 4 | #ifndef __BF20A6_REG_REGS_H__ 5 | #define __BF20A6_REG_REGS_H__ 6 | 7 | #define SENSOR_ID_HIGH 0XFC 8 | #define SENSOR_ID_LOW 0XFD 9 | #define RESET_RELATED 0XF2 10 | 11 | 12 | #endif //__BF20A6_REG_REGS_H__ 13 | -------------------------------------------------------------------------------- /sensors/private_include/bf20a6_settings.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #define REG_DLY 0xffff 5 | #define REGLIST_TAIL 0xffff /* Array end token */ 6 | 7 | static const uint16_t bf20a6_default_init_regs[][2] = { 8 | {0xf2,0x01}, 9 | {0x12,0x20}, 10 | {0x3a,0x00}, 11 | {0xe1,0x92}, 12 | {0xe3,0x12},// PLL Control, important for framerate(choice: 0x02\0x12\0x22\0x32\0x82) 13 | {0xe0,0x00}, 14 | {0x2a,0x98}, 15 | {0xcd,0x17}, 16 | {0xc0,0x10}, 17 | {0xc6,0x1d}, 18 | {0x10,0x35}, 19 | {0xe2,0x09}, 20 | {0xe4,0x72}, 21 | {0xe5,0x22}, 22 | {0xe6,0x24}, 23 | {0xe7,0x64}, 24 | {0xe8,0xa2}, // DVP:a2}, SPI:f2 VDDIO=1.8V,E8[2]=1},VDDIO=2.8V,E8[2]=0}, 25 | {0x4a,0x00}, 26 | {0x00,0x03}, 27 | {0x1f,0x02}, 28 | {0x22,0x02}, 29 | {0x0c,0x31}, 30 | 31 | {0x00,0x00}, 32 | {0x60,0x81}, 33 | {0x61,0x81}, 34 | 35 | {0xa0,0x08}, 36 | {0x01,0x1a}, 37 | // {0x01,0x1a}, 38 | // {0x01,0x1a}, 39 | // {0x02,0x15}, 40 | // {0x02,0x15}, 41 | {0x02,0x15}, 42 | {0x13,0x08}, 43 | {0x8a,0x96}, 44 | {0x8b,0x06}, 45 | {0x87,0x18}, 46 | 47 | 48 | {0x34,0x48}, // lens 49 | {0x35,0x40}, 50 | {0x36,0x40}, 51 | 52 | {0x71,0x44}, 53 | {0x72,0x48}, 54 | {0x74,0xa2}, 55 | {0x75,0xa9}, 56 | {0x78,0x12}, 57 | {0x79,0xa0}, 58 | {0x7a,0x94}, 59 | {0x7c,0x97}, 60 | {0x40,0x30}, 61 | {0x41,0x30}, 62 | {0x42,0x28}, 63 | {0x43,0x1f}, 64 | {0x44,0x1c}, 65 | {0x45,0x16}, 66 | {0x46,0x13}, 67 | {0x47,0x10}, 68 | {0x48,0x0D}, 69 | {0x49,0x0C}, 70 | {0x4B,0x0A}, 71 | {0x4C,0x0B}, 72 | {0x4E,0x09}, 73 | {0x4F,0x08}, 74 | {0x50,0x08}, 75 | 76 | 77 | {0x5f,0x29}, 78 | {0x23,0x33}, 79 | {0xa1,0x10}, // AWB 80 | {0xa2,0x0d}, 81 | {0xa3,0x30}, 82 | {0xa4,0x06}, 83 | {0xa5,0x22}, 84 | {0xa6,0x56}, 85 | {0xa7,0x18}, 86 | {0xa8,0x1a}, 87 | {0xa9,0x12}, 88 | {0xaa,0x12}, 89 | {0xab,0x16}, 90 | {0xac,0xb1}, 91 | {0xba,0x12}, 92 | {0xbb,0x12}, 93 | {0xad,0x12}, 94 | {0xae,0x56}, 95 | {0xaf,0x0a}, 96 | {0x3b,0x30}, 97 | {0x3c,0x12}, 98 | {0x3d,0x22}, 99 | {0x3e,0x3f}, 100 | {0x3f,0x28}, 101 | {0xb8,0xc3}, 102 | {0xb9,0xa3}, 103 | {0x39,0x47}, // pure color threshold 104 | {0x26,0x13}, 105 | {0x27,0x16}, 106 | {0x28,0x14}, 107 | {0x29,0x18}, 108 | {0xee,0x0d}, 109 | 110 | 111 | {0x13,0x05}, 112 | {0x24,0x3C}, 113 | {0x81,0x20}, 114 | {0x82,0x40}, 115 | {0x83,0x30}, 116 | {0x84,0x58}, 117 | {0x85,0x30}, 118 | {0x92,0x08}, 119 | {0x86,0x80}, 120 | {0x8a,0x96}, 121 | {0x91,0xff}, 122 | {0x94,0x62}, 123 | {0x9a,0x18}, // outdoor threshold 124 | {0xf0,0x45}, // integral time control, important for framerate(choice: 0x46\0x45\0x44..) 125 | {0x51,0x17}, // color normal 126 | {0x52,0x03}, 127 | {0x53,0x5F}, 128 | {0x54,0x47}, 129 | {0x55,0x66}, 130 | {0x56,0x0F}, 131 | {0x7e,0x14}, 132 | {0x57,0x36}, // color 133 | {0x58,0x2A}, 134 | {0x59,0xAA}, 135 | {0x5a,0xA8}, 136 | {0x5b,0x43}, 137 | {0x5c,0x10}, 138 | {0x5d,0x00}, 139 | {0x7d,0x36}, 140 | {0x5e,0x10}, 141 | 142 | {0xd6,0x88}, // contrast 143 | {0xd5,0x20}, // bright 144 | {0xb0,0x84}, // low light ctrl in gray section 145 | {0xb5,0x08}, // the threshold of GLB_GAIN 146 | {0xb1,0xc8}, // saturation 147 | {0xb2,0xc0}, 148 | {0xb3,0xd0}, 149 | {0xb4,0xB0}, 150 | 151 | {0x32,0x10}, 152 | // {0x8a,0x00}, 153 | // {0x8b,0x10}, 154 | {0xa0,0x09}, 155 | {0x00,0x03}, 156 | {0x0b,0x02}, 157 | {REGLIST_TAIL, 0x00}, 158 | }; 159 | -------------------------------------------------------------------------------- /sensors/private_include/bf3005.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * BF3005 driver. 7 | * 8 | */ 9 | #ifndef __BF3005_H__ 10 | #define __BF3005_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int bf3005_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int bf3005_init(sensor_t *sensor); 32 | 33 | #endif // __BF3005_H__ -------------------------------------------------------------------------------- /sensors/private_include/bf3005_regs.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-camera/4467667b71f22a4c7db226f24105a9350abe7a05/sensors/private_include/bf3005_regs.h -------------------------------------------------------------------------------- /sensors/private_include/gc0308.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sensor.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /** 10 | * @brief Detect sensor pid 11 | * 12 | * @param slv_addr SCCB address 13 | * @param id Detection result 14 | * @return 15 | * 0: Can't detect this sensor 16 | * Nonzero: This sensor has been detected 17 | */ 18 | int gc0308_detect(int slv_addr, sensor_id_t *id); 19 | 20 | /** 21 | * @brief initialize sensor function pointers 22 | * 23 | * @param sensor pointer of sensor 24 | * @return 25 | * Always 0 26 | */ 27 | int gc0308_init(sensor_t *sensor); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /sensors/private_include/gc0308_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC0308 register definitions. 3 | */ 4 | #ifndef __GC0308_REG_REGS_H__ 5 | #define __GC0308_REG_REGS_H__ 6 | 7 | #define RESET_RELATED 0xfe // Bit[7]: Software reset 8 | // Bit[6:5]: NA 9 | // Bit[4]: CISCTL_restart_n 10 | // Bit[3:1]: NA 11 | // Bit[0]: page select 12 | // 0:page0 13 | // 1:page1 14 | 15 | 16 | // page0: 17 | 18 | 19 | 20 | /** 21 | * @brief register value 22 | */ 23 | 24 | 25 | #endif // __GC0308_REG_REGS_H__ 26 | -------------------------------------------------------------------------------- /sensors/private_include/gc0308_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _GC0308_SETTINGS_H_ 2 | #define _GC0308_SETTINGS_H_ 3 | 4 | #include 5 | 6 | #define REG_DLY 0xff 7 | 8 | static const uint8_t gc0308_sensor_default_regs[][2] = { 9 | {0xfe, 0x00}, 10 | {0xec, 0x20}, 11 | {0x05, 0x00}, 12 | {0x06, 0x00}, 13 | {0x07, 0x00}, 14 | {0x08, 0x00}, 15 | {0x09, 0x01}, 16 | {0x0a, 0xe8}, 17 | {0x0b, 0x02}, 18 | {0x0c, 0x88}, 19 | {0x0d, 0x02}, 20 | {0x0e, 0x02}, 21 | {0x10, 0x26}, 22 | {0x11, 0x0d}, 23 | {0x12, 0x2a}, 24 | {0x13, 0x00}, 25 | {0x14, 0x11}, 26 | {0x15, 0x0a}, 27 | {0x16, 0x05}, 28 | {0x17, 0x01}, 29 | {0x18, 0x44}, 30 | {0x19, 0x44}, 31 | {0x1a, 0x2a}, 32 | {0x1b, 0x00}, 33 | {0x1c, 0x49}, 34 | {0x1d, 0x9a}, 35 | {0x1e, 0x61}, 36 | {0x1f, 0x00}, //pad drv <=24MHz, use 0x00 is ok 37 | {0x20, 0x7f}, 38 | {0x21, 0xfa}, 39 | {0x22, 0x57}, 40 | {0x24, 0xa2}, //YCbYCr 41 | {0x25, 0x0f}, 42 | {0x26, 0x03}, // 0x01 43 | {0x28, 0x00}, 44 | {0x2d, 0x0a}, 45 | {0x2f, 0x01}, 46 | {0x30, 0xf7}, 47 | {0x31, 0x50}, 48 | {0x32, 0x00}, 49 | {0x33, 0x28}, 50 | {0x34, 0x2a}, 51 | {0x35, 0x28}, 52 | {0x39, 0x04}, 53 | {0x3a, 0x20}, 54 | {0x3b, 0x20}, 55 | {0x3c, 0x00}, 56 | {0x3d, 0x00}, 57 | {0x3e, 0x00}, 58 | {0x3f, 0x00}, 59 | {0x50, 0x14}, // 0x14 60 | {0x52, 0x41}, 61 | {0x53, 0x80}, 62 | {0x54, 0x80}, 63 | {0x55, 0x80}, 64 | {0x56, 0x80}, 65 | {0x8b, 0x20}, 66 | {0x8c, 0x20}, 67 | {0x8d, 0x20}, 68 | {0x8e, 0x14}, 69 | {0x8f, 0x10}, 70 | {0x90, 0x14}, 71 | {0x91, 0x3c}, 72 | {0x92, 0x50}, 73 | //{0x8b,0x10}, 74 | //{0x8c,0x10}, 75 | //{0x8d,0x10}, 76 | //{0x8e,0x10}, 77 | //{0x8f,0x10}, 78 | //{0x90,0x10}, 79 | //{0x91,0x3c}, 80 | //{0x92,0x50}, 81 | {0x5d, 0x12}, 82 | {0x5e, 0x1a}, 83 | {0x5f, 0x24}, 84 | {0x60, 0x07}, 85 | {0x61, 0x15}, 86 | {0x62, 0x08}, // 0x08 87 | {0x64, 0x03}, // 0x03 88 | {0x66, 0xe8}, 89 | {0x67, 0x86}, 90 | {0x68, 0x82}, 91 | {0x69, 0x18}, 92 | {0x6a, 0x0f}, 93 | {0x6b, 0x00}, 94 | {0x6c, 0x5f}, 95 | {0x6d, 0x8f}, 96 | {0x6e, 0x55}, 97 | {0x6f, 0x38}, 98 | {0x70, 0x15}, 99 | {0x71, 0x33}, 100 | {0x72, 0xdc}, 101 | {0x73, 0x00}, 102 | {0x74, 0x02}, 103 | {0x75, 0x3f}, 104 | {0x76, 0x02}, 105 | {0x77, 0x38}, // 0x47 106 | {0x78, 0x88}, 107 | {0x79, 0x81}, 108 | {0x7a, 0x81}, 109 | {0x7b, 0x22}, 110 | {0x7c, 0xff}, 111 | {0x93, 0x48}, //color matrix default 112 | {0x94, 0x02}, 113 | {0x95, 0x07}, 114 | {0x96, 0xe0}, 115 | {0x97, 0x40}, 116 | {0x98, 0xf0}, 117 | {0xb1, 0x40}, 118 | {0xb2, 0x40}, 119 | {0xb3, 0x40}, //0x40 120 | {0xb6, 0xe0}, 121 | {0xbd, 0x38}, 122 | {0xbe, 0x36}, 123 | {0xd0, 0xCB}, 124 | {0xd1, 0x10}, 125 | {0xd2, 0x90}, 126 | {0xd3, 0x48}, 127 | {0xd5, 0xF2}, 128 | {0xd6, 0x16}, 129 | {0xdb, 0x92}, 130 | {0xdc, 0xA5}, 131 | {0xdf, 0x23}, 132 | {0xd9, 0x00}, 133 | {0xda, 0x00}, 134 | {0xe0, 0x09}, 135 | {0xed, 0x04}, 136 | {0xee, 0xa0}, 137 | {0xef, 0x40}, 138 | {0x80, 0x03}, 139 | 140 | {0x9F, 0x10}, 141 | {0xA0, 0x20}, 142 | {0xA1, 0x38}, 143 | {0xA2, 0x4e}, 144 | {0xA3, 0x63}, 145 | {0xA4, 0x76}, 146 | {0xA5, 0x87}, 147 | {0xA6, 0xa2}, 148 | {0xA7, 0xb8}, 149 | {0xA8, 0xca}, 150 | {0xA9, 0xd8}, 151 | {0xAA, 0xe3}, 152 | {0xAB, 0xeb}, 153 | {0xAC, 0xf0}, 154 | {0xAD, 0xF8}, 155 | {0xAE, 0xFd}, 156 | {0xAF, 0xFF}, 157 | 158 | {0xc0, 0x00}, 159 | {0xc1, 0x10}, 160 | {0xc2, 0x1c}, 161 | {0xc3, 0x30}, 162 | {0xc4, 0x43}, 163 | {0xc5, 0x54}, 164 | {0xc6, 0x65}, 165 | {0xc7, 0x75}, 166 | {0xc8, 0x93}, 167 | {0xc9, 0xB0}, 168 | {0xca, 0xCB}, 169 | {0xcb, 0xE6}, 170 | {0xcc, 0xFF}, 171 | {0xf0, 0x02}, 172 | {0xf1, 0x01}, 173 | {0xf2, 0x02}, 174 | {0xf3, 0x30}, 175 | {0xf7, 0x04}, 176 | {0xf8, 0x02}, 177 | {0xf9, 0x9f}, 178 | {0xfa, 0x78}, 179 | {0xfe, 0x01}, 180 | {0x00, 0xf5}, 181 | {0x02, 0x20}, 182 | {0x04, 0x10}, 183 | {0x05, 0x08}, 184 | {0x06, 0x20}, 185 | {0x08, 0x0a}, 186 | {0x0a, 0xa0}, 187 | {0x0b, 0x60}, 188 | {0x0c, 0x08}, 189 | {0x0e, 0x44}, 190 | {0x0f, 0x32}, 191 | {0x10, 0x41}, 192 | {0x11, 0x37}, 193 | {0x12, 0x22}, 194 | {0x13, 0x19}, 195 | {0x14, 0x44}, 196 | {0x15, 0x44}, 197 | {0x16, 0xc2}, 198 | {0x17, 0xA8}, 199 | {0x18, 0x18}, 200 | {0x19, 0x50}, 201 | {0x1a, 0xd8}, 202 | {0x1b, 0xf5}, 203 | {0x70, 0x40}, 204 | {0x71, 0x58}, 205 | {0x72, 0x30}, 206 | {0x73, 0x48}, 207 | {0x74, 0x20}, 208 | {0x75, 0x60}, 209 | {0x77, 0x20}, 210 | {0x78, 0x32}, 211 | {0x30, 0x03}, 212 | {0x31, 0x40}, 213 | {0x32, 0x10}, 214 | {0x33, 0xe0}, 215 | {0x34, 0xe0}, 216 | {0x35, 0x00}, 217 | {0x36, 0x80}, 218 | {0x37, 0x00}, 219 | {0x38, 0x04}, 220 | {0x39, 0x09}, 221 | {0x3a, 0x12}, 222 | {0x3b, 0x1C}, 223 | {0x3c, 0x28}, 224 | {0x3d, 0x31}, 225 | {0x3e, 0x44}, 226 | {0x3f, 0x57}, 227 | {0x40, 0x6C}, 228 | {0x41, 0x81}, 229 | {0x42, 0x94}, 230 | {0x43, 0xA7}, 231 | {0x44, 0xB8}, 232 | {0x45, 0xD6}, 233 | {0x46, 0xEE}, 234 | {0x47, 0x0d}, 235 | {0x62, 0xf7}, 236 | {0x63, 0x68}, 237 | {0x64, 0xd3}, 238 | {0x65, 0xd3}, 239 | {0x66, 0x60}, 240 | {0xfe, 0x00}, 241 | 242 | {0x01, 0x32}, //frame setting 243 | {0x02, 0x0c}, 244 | {0x0f, 0x01}, 245 | {0xe2, 0x00}, 246 | {0xe3, 0x78}, 247 | {0xe4, 0x00}, 248 | {0xe5, 0xfe}, 249 | {0xe6, 0x01}, 250 | {0xe7, 0xe0}, 251 | {0xe8, 0x01}, 252 | {0xe9, 0xe0}, 253 | {0xea, 0x01}, 254 | {0xeb, 0xe0}, 255 | {0xfe, 0x00}, 256 | }; 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /sensors/private_include/gc032a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * GC032A driver. 4 | * 5 | */ 6 | #ifndef __GC032A_H__ 7 | #define __GC032A_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int gc032a_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int gc032a_init(sensor_t *sensor); 30 | 31 | #endif // __GC032A_H__ 32 | -------------------------------------------------------------------------------- /sensors/private_include/gc032a_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC032A register definitions. 3 | */ 4 | #ifndef __GC032A_REG_REGS_H__ 5 | #define __GC032A_REG_REGS_H__ 6 | 7 | #define SENSOR_ID_HIGH 0XF0 8 | #define SENSOR_ID_LOW 0XF1 9 | #define PAD_VB_HIZ_MODE 0XF2 10 | #define SYNC_OUTPUT 0XF3 11 | #define I2C_CONFIG 0XF4 12 | #define PLL_MODE1 0XF7 13 | #define PLL_MODE2 0XF8 14 | #define CM_MODE 0XF9 15 | #define ISP_DIV_MODE 0XFA 16 | #define I2C_DEVICE_ID 0XFB 17 | #define ANALOG_PWC 0XFC 18 | #define ISP_DIV_MODE2 0XFD 19 | #define RESET_RELATED 0XFE // Bit[7]: Software reset 20 | // Bit[6]: cm reset 21 | // Bit[5]: spi reset 22 | // Bit[4]: CISCTL_restart_n 23 | // Bit[3]: PLL_rst 24 | // Bit[2:0]: page select 25 | // 000:page0 26 | // 001:page1 27 | // 010:page2 28 | // 011:page3 29 | 30 | //----page0----------------------------- 31 | #define P0_EXPOSURE_HIGH 0X03 32 | #define P0_EXPOSURE_LOW 0X04 33 | #define P0_HB_HIGH 0X05 34 | #define P0_HB_LOW 0X06 35 | #define P0_VB_HIGH 0X07 36 | #define P0_VB_LOW 0X08 37 | #define P0_ROW_START_HIGH 0X09 38 | #define P0_ROW_START_LOW 0X0A 39 | #define P0_COLUMN_START_HIGH 0X0B 40 | #define P0_COLUMN_START_LOW 0X0C 41 | #define P0_WINDOW_HEIGHT_HIGH 0X0D 42 | #define P0_WINDOW_HEIGHT_LOW 0X0E 43 | #define P0_WINDOW_WIDTH_HIGH 0X0F 44 | #define P0_WINDOW_WIDTH_LOW 0X10 45 | #define P0_SH_DELAY 0X11 46 | #define P0_VS_ST 0X12 47 | #define P0_VS_ET 0X13 48 | #define P0_CISCTL_MODE1 0X17 49 | 50 | #define P0_BLOCK_ENABLE_1 0X40 51 | #define P0_AAAA_ENABLE 0X42 52 | #define P0_SPECIAL_EFFECT 0X43 53 | #define P0_SYNC_MODE 0X46 54 | #define P0_GAIN_CODE 0X48 55 | #define P0_DEBUG_MODE2 0X4C 56 | #define P0_WIN_MODE 0X50 57 | #define P0_OUT_WIN_Y1_HIGH 0X51 58 | #define P0_OUT_WIN_Y1_LOW 0X52 59 | #define P0_OUT_WIN_X1_HIGH 0X53 60 | #define P0_OUT_WIN_X1_LOW 0X54 61 | #define P0_OUT_WIN_HEIGHT_HIGH 0X55 62 | #define P0_OUT_WIN_HEIGHT_LOW 0X56 63 | #define P0_OUT_WIN_WIDTH_HIGH 0X57 64 | #define P0_OUT_WIN_WIDTH_LOW 0X58 65 | 66 | #define P0_GLOBAL_SATURATION 0XD0 67 | #define P0_SATURATION_CB 0XD1 68 | #define P0_SATURATION_CR 0XD2 69 | #define P0_LUMA_CONTRAST 0XD3 70 | #define P0_CONTRAST_CENTER 0XD4 71 | #define P0_LUMA_OFFSET 0XD5 72 | #define P0_FIXED_CB 0XDA 73 | #define P0_FIXED_CR 0XDB 74 | 75 | //----page3----------------------------- 76 | #define P3_IMAGE_WIDTH_LOW 0X5B 77 | #define P3_IMAGE_WIDTH_HIGH 0X5C 78 | #define P3_IMAGE_HEIGHT_LOW 0X5D 79 | #define P3_IMAGE_HEIGHT_HIGH 0X5E 80 | 81 | 82 | #endif //__GC032A_REG_REGS_H__ 83 | -------------------------------------------------------------------------------- /sensors/private_include/gc032a_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _GC032A_SETTINGS_H_ 2 | #define _GC032A_SETTINGS_H_ 3 | 4 | #include 5 | #include 6 | #include "esp_attr.h" 7 | #include "gc032a_regs.h" 8 | 9 | 10 | #define REG_DLY 0xffff 11 | #define REGLIST_TAIL 0x0000 12 | 13 | 14 | /* 15 | * The default register settings, as obtained from OmniVision. There 16 | * is really no making sense of most of these - lots of "reserved" values 17 | * and such. 18 | * 19 | */ 20 | static const uint16_t gc032a_default_regs[][2] = { 21 | /*System*/ 22 | {0xf3, 0xff}, 23 | {0xf5, 0x06}, 24 | {0xf7, 0x01}, 25 | {0xf8, 0x03}, 26 | {0xf9, 0xce}, 27 | {0xfa, 0x00}, 28 | {0xfc, 0x02}, 29 | {0xfe, 0x02}, 30 | {0x81, 0x03}, 31 | 32 | {0xfe, 0x00}, 33 | {0x77, 0x64}, 34 | {0x78, 0x40}, 35 | {0x79, 0x60}, 36 | /*ANALOG & CISCTL*/ 37 | {0xfe, 0x00}, 38 | {0x03, 0x01}, 39 | {0x04, 0xce}, 40 | {0x05, 0x01}, 41 | {0x06, 0xad}, 42 | {0x07, 0x00}, 43 | {0x08, 0x10}, 44 | {0x0a, 0x00}, 45 | {0x0c, 0x00}, 46 | {0x0d, 0x01}, 47 | {0x0e, 0xe8}, // height 488 48 | {0x0f, 0x02}, 49 | {0x10, 0x88}, // width 648 50 | {0x17, 0x54}, 51 | {0x19, 0x08}, 52 | {0x1a, 0x0a}, 53 | {0x1f, 0x40}, 54 | {0x20, 0x30}, 55 | {0x2e, 0x80}, 56 | {0x2f, 0x2b}, 57 | {0x30, 0x1a}, 58 | {0xfe, 0x02}, 59 | {0x03, 0x02}, 60 | {0x05, 0xd7}, 61 | {0x06, 0x60}, 62 | {0x08, 0x80}, 63 | {0x12, 0x89}, 64 | 65 | /*blk*/ 66 | {0xfe, 0x00}, 67 | {0x18, 0x02}, 68 | {0xfe, 0x02}, 69 | {0x40, 0x22}, 70 | {0x45, 0x00}, 71 | {0x46, 0x00}, 72 | {0x49, 0x20}, 73 | {0x4b, 0x3c}, 74 | {0x50, 0x20}, 75 | {0x42, 0x10}, 76 | 77 | /*isp*/ 78 | {0xfe, 0x01}, 79 | {0x0a, 0xc5}, 80 | {0x45, 0x00}, 81 | {0xfe, 0x00}, 82 | {0x40, 0xff}, 83 | {0x41, 0x25}, 84 | {0x42, 0xcf}, 85 | {0x43, 0x10}, 86 | {0x44, 0x83}, 87 | {0x46, 0x23}, 88 | {0x49, 0x03}, 89 | {0x52, 0x02}, 90 | {0x54, 0x00}, 91 | {0xfe, 0x02}, 92 | {0x22, 0xf6}, 93 | 94 | /*Shading*/ 95 | {0xfe, 0x01}, 96 | {0xc1, 0x38}, 97 | {0xc2, 0x4c}, 98 | {0xc3, 0x00}, 99 | {0xc4, 0x32}, 100 | {0xc5, 0x24}, 101 | {0xc6, 0x16}, 102 | {0xc7, 0x08}, 103 | {0xc8, 0x08}, 104 | {0xc9, 0x00}, 105 | {0xca, 0x20}, 106 | {0xdc, 0x8a}, 107 | {0xdd, 0xa0}, 108 | {0xde, 0xa6}, 109 | {0xdf, 0x75}, 110 | 111 | /*AWB*/ 112 | {0xfe, 0x01}, 113 | {0x7c, 0x09}, 114 | {0x65, 0x06}, 115 | {0x7c, 0x08}, 116 | {0x56, 0xf4}, 117 | {0x66, 0x0f}, 118 | {0x67, 0x84}, 119 | {0x6b, 0x80}, 120 | {0x6d, 0x12}, 121 | {0x6e, 0xb0}, 122 | {0x86, 0x00}, 123 | {0x87, 0x00}, 124 | {0x88, 0x00}, 125 | {0x89, 0x00}, 126 | {0x8a, 0x00}, 127 | {0x8b, 0x00}, 128 | {0x8c, 0x00}, 129 | {0x8d, 0x00}, 130 | {0x8e, 0x00}, 131 | {0x8f, 0x00}, 132 | {0x90, 0x00}, 133 | {0x91, 0x00}, 134 | {0x92, 0xf4}, 135 | {0x93, 0xd5}, 136 | {0x94, 0x50}, 137 | {0x95, 0x0f}, 138 | {0x96, 0xf4}, 139 | {0x97, 0x2d}, 140 | {0x98, 0x0f}, 141 | {0x99, 0xa6}, 142 | {0x9a, 0x2d}, 143 | {0x9b, 0x0f}, 144 | {0x9c, 0x59}, 145 | {0x9d, 0x2d}, 146 | {0x9e, 0xaa}, 147 | {0x9f, 0x67}, 148 | {0xa0, 0x59}, 149 | {0xa1, 0x00}, 150 | {0xa2, 0x00}, 151 | {0xa3, 0x0a}, 152 | {0xa4, 0x00}, 153 | {0xa5, 0x00}, 154 | {0xa6, 0xd4}, 155 | {0xa7, 0x9f}, 156 | {0xa8, 0x55}, 157 | {0xa9, 0xd4}, 158 | {0xaa, 0x9f}, 159 | {0xab, 0xac}, 160 | {0xac, 0x9f}, 161 | {0xad, 0x55}, 162 | {0xae, 0xd4}, 163 | {0xaf, 0xac}, 164 | {0xb0, 0xd4}, 165 | {0xb1, 0xa3}, 166 | {0xb2, 0x55}, 167 | {0xb3, 0xd4}, 168 | {0xb4, 0xac}, 169 | {0xb5, 0x00}, 170 | {0xb6, 0x00}, 171 | {0xb7, 0x05}, 172 | {0xb8, 0xd6}, 173 | {0xb9, 0x8c}, 174 | 175 | /*CC*/ 176 | {0xfe, 0x01}, 177 | {0xd0, 0x40}, 178 | {0xd1, 0xf8}, 179 | {0xd2, 0x00}, 180 | {0xd3, 0xfa}, 181 | {0xd4, 0x45}, 182 | {0xd5, 0x02}, 183 | 184 | {0xd6, 0x30}, 185 | {0xd7, 0xfa}, 186 | {0xd8, 0x08}, 187 | {0xd9, 0x08}, 188 | {0xda, 0x58}, 189 | {0xdb, 0x02}, 190 | {0xfe, 0x00}, 191 | 192 | /*Gamma*/ 193 | {0xfe, 0x00}, 194 | {0xba, 0x00}, 195 | {0xbb, 0x04}, 196 | {0xbc, 0x0a}, 197 | {0xbd, 0x0e}, 198 | {0xbe, 0x22}, 199 | {0xbf, 0x30}, 200 | {0xc0, 0x3d}, 201 | {0xc1, 0x4a}, 202 | {0xc2, 0x5d}, 203 | {0xc3, 0x6b}, 204 | {0xc4, 0x7a}, 205 | {0xc5, 0x85}, 206 | {0xc6, 0x90}, 207 | {0xc7, 0xa5}, 208 | {0xc8, 0xb5}, 209 | {0xc9, 0xc2}, 210 | {0xca, 0xcc}, 211 | {0xcb, 0xd5}, 212 | {0xcc, 0xde}, 213 | {0xcd, 0xea}, 214 | {0xce, 0xf5}, 215 | {0xcf, 0xff}, 216 | 217 | /*Auto Gamma*/ 218 | {0xfe, 0x00}, 219 | {0x5a, 0x08}, 220 | {0x5b, 0x0f}, 221 | {0x5c, 0x15}, 222 | {0x5d, 0x1c}, 223 | {0x5e, 0x28}, 224 | {0x5f, 0x36}, 225 | {0x60, 0x45}, 226 | {0x61, 0x51}, 227 | {0x62, 0x6a}, 228 | {0x63, 0x7d}, 229 | {0x64, 0x8d}, 230 | {0x65, 0x98}, 231 | {0x66, 0xa2}, 232 | {0x67, 0xb5}, 233 | {0x68, 0xc3}, 234 | {0x69, 0xcd}, 235 | {0x6a, 0xd4}, 236 | {0x6b, 0xdc}, 237 | {0x6c, 0xe3}, 238 | {0x6d, 0xf0}, 239 | {0x6e, 0xf9}, 240 | {0x6f, 0xff}, 241 | 242 | /*Gain*/ 243 | {0xfe, 0x00}, 244 | {0x70, 0x50}, 245 | 246 | /*AEC*/ 247 | {0xfe, 0x00}, 248 | {0x4f, 0x01}, 249 | {0xfe, 0x01}, 250 | {0x0d, 0x00}, 251 | {0x12, 0xa0}, 252 | {0x13, 0x3a}, 253 | {0x44, 0x04}, 254 | {0x1f, 0x30}, 255 | {0x20, 0x40}, 256 | {0x26, 0x9a}, 257 | {0x3e, 0x20}, 258 | {0x3f, 0x2d}, 259 | {0x40, 0x40}, 260 | {0x41, 0x5b}, 261 | {0x42, 0x82}, 262 | {0x43, 0xb7}, 263 | {0x04, 0x0a}, 264 | {0x02, 0x79}, 265 | {0x03, 0xc0}, 266 | 267 | /*measure window*/ 268 | {0xfe, 0x01}, 269 | {0xcc, 0x08}, 270 | {0xcd, 0x08}, 271 | {0xce, 0xa4}, 272 | {0xcf, 0xec}, 273 | 274 | /*DNDD*/ 275 | {0xfe, 0x00}, 276 | {0x81, 0xb8}, 277 | {0x82, 0x12}, 278 | {0x83, 0x0a}, 279 | {0x84, 0x01}, 280 | {0x86, 0x50}, 281 | {0x87, 0x18}, 282 | {0x88, 0x10}, 283 | {0x89, 0x70}, 284 | {0x8a, 0x20}, 285 | {0x8b, 0x10}, 286 | {0x8c, 0x08}, 287 | {0x8d, 0x0a}, 288 | 289 | /*Intpee*/ 290 | {0xfe, 0x00}, 291 | {0x8f, 0xaa}, 292 | {0x90, 0x9c}, 293 | {0x91, 0x52}, 294 | {0x92, 0x03}, 295 | {0x93, 0x03}, 296 | {0x94, 0x08}, 297 | {0x95, 0x44}, 298 | {0x97, 0x00}, 299 | {0x98, 0x00}, 300 | 301 | /*ASDE*/ 302 | {0xfe, 0x00}, 303 | {0xa1, 0x30}, 304 | {0xa2, 0x41}, 305 | {0xa4, 0x30}, 306 | {0xa5, 0x20}, 307 | {0xaa, 0x30}, 308 | {0xac, 0x32}, 309 | 310 | /*YCP*/ 311 | {0xfe, 0x00}, 312 | {0xd1, 0x3c}, 313 | {0xd2, 0x3c}, 314 | {0xd3, 0x38}, 315 | {0xd6, 0xf4}, 316 | {0xd7, 0x1d}, 317 | {0xdd, 0x73}, 318 | {0xde, 0x84}, 319 | 320 | /*Banding*/ 321 | {0xfe, 0x00}, 322 | {0x05, 0x01}, 323 | {0x06, 0xad}, 324 | {0x07, 0x00}, 325 | {0x08, 0x10}, 326 | 327 | {0xfe, 0x01}, 328 | {0x25, 0x00}, 329 | {0x26, 0x9a}, 330 | 331 | {0x27, 0x01}, 332 | {0x28, 0xce}, 333 | {0x29, 0x02}, 334 | {0x2a, 0x68}, 335 | {0x2b, 0x02}, 336 | {0x2c, 0x68}, 337 | {0x2d, 0x07}, 338 | {0x2e, 0xd2}, 339 | {0x2f, 0x0b}, 340 | {0x30, 0x6e}, 341 | {0x31, 0x0e}, 342 | {0x32, 0x70}, 343 | {0x33, 0x12}, 344 | {0x34, 0x0c}, 345 | {0x3c, 0x30}, 346 | 347 | /*Analog&Cisctl*/ 348 | {0xfe, 0x00}, 349 | {0x05, 0x01}, 350 | {0x06, 0xa0}, 351 | {0x07, 0x00}, 352 | {0x08, 0x20}, 353 | {0x0a, 0x78}, 354 | {0x0c, 0xa0}, 355 | {0x0d, 0x00}, //window_height [8] 356 | {0x0e, 0xf8}, //window_height [7:0] 248 357 | {0x0f, 0x01}, //window_width [9:8] 358 | {0x10, 0x48}, //window_width [7:0] 328 359 | 360 | {0x55, 0x00}, 361 | {0x56, 0xf0}, // 240 362 | {0x57, 0x01}, 363 | {0x58, 0x40}, // 320 364 | 365 | /*SPI*/ 366 | {0xfe, 0x03}, 367 | {0x5b, 0x40}, 368 | {0x5c, 0x01}, 369 | {0x5d, 0xf0}, 370 | {0x5e, 0x00}, 371 | 372 | /*AEC*/ 373 | {0xfe, 0x01}, 374 | {0x25, 0x00}, //step 375 | {0x26, 0x63}, 376 | {0x27, 0x01}, 377 | {0x28, 0x29}, 378 | {0x29, 0x01}, 379 | {0x2a, 0x29}, 380 | {0x2b, 0x01}, 381 | {0x2c, 0x29}, 382 | {0x2d, 0x01}, 383 | {0x2e, 0x29}, 384 | {0x2f, 0x01}, 385 | {0x30, 0x29}, 386 | {0x31, 0x01}, 387 | {0x32, 0x29}, 388 | {0x33, 0x01}, 389 | {0x34, 0x29}, 390 | {0x3c, 0x00}, 391 | 392 | /*measure window*/ 393 | {0xfe, 0x01}, 394 | {0xcc, 0x04}, 395 | {0xcd, 0x04}, 396 | {0xce, 0x72}, 397 | {0xcf, 0x52}, 398 | {REGLIST_TAIL, 0x00}, 399 | }; 400 | 401 | #endif 402 | -------------------------------------------------------------------------------- /sensors/private_include/gc2145.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __GC2145_H__ 3 | #define __GC2145_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int gc2145_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int gc2145_init(sensor_t *sensor); 26 | 27 | #endif // __GC2145_H__ 28 | -------------------------------------------------------------------------------- /sensors/private_include/gc2145_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GC2145 register definitions. 3 | */ 4 | #ifndef __GC2145_REG_REGS_H__ 5 | #define __GC2145_REG_REGS_H__ 6 | 7 | #define CHIP_ID_HIGH 0XF0 8 | #define CHIP_ID_LOW 0XF1 9 | #define PLL_MODE1 0XF7 10 | #define PLL_MODE2 0XF8 11 | #define CM_MODE 0XF9 12 | #define CLK_DIV_MODE 0XFA 13 | #define RESET_RELATED 0xfe // Bit[7]: Software reset 14 | // Bit[6]: cm reset 15 | // Bit[5]: mipi reset 16 | // Bit[4]: CISCTL_restart_n 17 | // Bit[3]: NA 18 | // Bit[2:0]: page select 19 | // 000:page0 20 | // 001:page1 21 | // 010:page2 22 | // 011:page3 23 | 24 | //-page0---------------- 25 | 26 | #define P0_EXPOSURE_HIGH 0X03 27 | #define P0_EXPOSURE_LOW 0X04 28 | #define P0_HB_HIGH 0X05 29 | #define P0_HB_LOW 0X06 30 | #define P0_VB_HIGH 0X07 31 | #define P0_VB_LOW 0X08 32 | #define P0_ROW_START_HIGH 0X09 33 | #define P0_ROW_START_LOW 0X0A 34 | #define P0_COL_START_HIGH 0X0B 35 | #define P0_COL_START_LOW 0X0C 36 | 37 | #define P0_WIN_HEIGHT_HIGH 0X0D 38 | #define P0_WIN_HEIGHT_LOW 0X0E 39 | #define P0_WIN_WIDTH_HIGH 0X0F 40 | #define P0_WIN_WIDTH_LOW 0X10 41 | #define P0_ANALOG_MODE1 0X17 42 | #define P0_ANALOG_MODE2 0X18 43 | 44 | #define P0_SPECIAL_EFFECT 0X83 45 | #define P0_OUTPUT_FORMAT 0x84 // Format select 46 | // Bit[7]:YUV420 row switch 47 | // Bit[6]:YUV420 col switch 48 | // Bit[7]:YUV420_legacy 49 | // Bit[4:0]:output data mode 50 | // 5’h00 Cb Y Cr Y 51 | // 5’h01 Cr Y Cb Y 52 | // 5’h02 Y Cb Y Cr 53 | // 5’h03 Y Cr Y Cb 54 | // 5’h04 LSC bypass, C/Y 55 | // 5’h05 LSC bypass, Y/C 56 | // 5’h06 RGB 565 57 | // 5’h0f bypass 10bits 58 | // 5’h17 switch odd/even column /row to controls output Bayer pattern 59 | // 00 RGBG 60 | // 01 RGGB 61 | // 10 BGGR 62 | // 11 GBRG 63 | // 5'h18 DNDD out mode 64 | // 5'h19 LSC out mode 65 | // 5;h1b EEINTP out mode 66 | #define P0_FRAME_START 0X85 67 | #define P0_SYNC_MODE 0X86 68 | #define P0_MODULE_GATING 0X88 69 | #define P0_BYPASS_MODE 0X89 70 | #define P0_DEBUG_MODE2 0X8C 71 | #define P0_DEBUG_MODE3 0X8D 72 | #define P0_CROP_ENABLE 0X90 73 | #define P0_OUT_WIN_Y1_HIGH 0X91 74 | #define P0_OUT_WIN_Y1_LOW 0X92 75 | #define P0_OUT_WIN_X1_HIGH 0X93 76 | #define P0_OUT_WIN_X1_LOW 0X94 77 | #define P0_OUT_WIN_HEIGHT_HIGH 0X95 78 | #define P0_OUT_WIN_HEIGHT_LOW 0X96 79 | #define P0_OUT_WIN_WIDTH_HIGH 0X97 80 | #define P0_OUT_WIN_WIDTH_LOW 0X98 81 | #define P0_SUBSAMPLE 0X99 82 | #define P0_SUBSAMPLE_MODE 0X9A 83 | 84 | 85 | #endif // __GC2145_REG_REGS_H__ 86 | -------------------------------------------------------------------------------- /sensors/private_include/mega_ccm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * MEGA_CCM driver. 4 | * 5 | */ 6 | #ifndef __MEGA_CCM_H__ 7 | #define __MEGA_CCM_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int mega_ccm_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int mega_ccm_init(sensor_t *sensor); 30 | 31 | #endif // __MEGA_CCM_H__ 32 | -------------------------------------------------------------------------------- /sensors/private_include/mega_ccm_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MEGA_CCM register definitions. 3 | */ 4 | #ifndef __MEGA_CCM_REG_REGS_H__ 5 | #define __MEGA_CCM_REG_REGS_H__ 6 | 7 | #define ID_BASE 0x0000 8 | #define SENSOR_BASE 0x0100 9 | #define SYS_CLK_BASE 0x0200 10 | #define BYPASS_BASE 0XFFF0 11 | 12 | #define SENSOR_ID_HIGH ID_BASE | 0x00 13 | #define SENSOR_ID_LOW ID_BASE | 0x01 14 | #define FIRMWARE_VER ID_BASE | 0x02 15 | 16 | #define CAMERA_RST_REG SENSOR_BASE|0x02 17 | 18 | 19 | #define PIXEL_FMT_REG SENSOR_BASE|0x20 20 | #define RESOLUTION_REG SENSOR_BASE|0x21 21 | #define BRIGHTNESS_REG SENSOR_BASE|0x22 22 | #define CONTRAST_REG SENSOR_BASE|0x23 23 | #define SATURATION_REG SENSOR_BASE|0x24 24 | #define EXP_COMPENSATE_REG SENSOR_BASE|0x25 25 | #define AWB_MODE_REG SENSOR_BASE|0x26 26 | #define SPECIAL_REG SENSOR_BASE|0x27 27 | #define SHARPNESS_REG SENSOR_BASE|0x28 28 | #define FOCUS_REG SENSOR_BASE|0x29 29 | #define IMAGE_QUALITY_REG SENSOR_BASE|0x2A 30 | #define IMAGE_FLIP_REG SENSOR_BASE|0x2B 31 | #define IMAGE_MIRROR_REG SENSOR_BASE|0x2C 32 | 33 | 34 | #define AGC_MODE_REG SENSOR_BASE|0x30 35 | #define MANUAL_AGC_REG SENSOR_BASE|0x31 36 | #define MANUAL_EXP_H_REG SENSOR_BASE|0x33 37 | #define MANUAL_EXP_L_REG SENSOR_BASE|0x34 38 | 39 | 40 | #define SYSTEM_CLK_DIV_REG SYS_CLK_BASE|0x00 41 | #define SYSTEM_PLL_DIV_REG SYS_CLK_BASE|0x01 42 | 43 | #endif //__MEGA_CCM_REG_REGS_H__ 44 | -------------------------------------------------------------------------------- /sensors/private_include/mega_ccm_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _GC032A_SETTINGS_H_ 2 | #define _GC032A_SETTINGS_H_ 3 | 4 | #include 5 | #include 6 | #include "esp_attr.h" 7 | #include "mega_ccm_regs.h" 8 | 9 | 10 | #define REG_DLY 0xffff 11 | #define REGLIST_TAIL 0x0000 12 | 13 | static const uint16_t mega_ccm_default_regs[][2] = { 14 | {0x0120, 0x01 }, // JPEG 15 | {0x0121, 0x01 }, // 320X240 16 | {REGLIST_TAIL, 0x00}, 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /sensors/private_include/nt99141.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * NT99141 driver. 7 | * 8 | */ 9 | #ifndef __NT99141_H__ 10 | #define __NT99141_H__ 11 | 12 | #include "sensor.h" 13 | 14 | /** 15 | * @brief Detect sensor pid 16 | * 17 | * @param slv_addr SCCB address 18 | * @param id Detection result 19 | * @return 20 | * 0: Can't detect this sensor 21 | * Nonzero: This sensor has been detected 22 | */ 23 | int nt99141_detect(int slv_addr, sensor_id_t *id); 24 | 25 | /** 26 | * @brief initialize sensor function pointers 27 | * 28 | * @param sensor pointer of sensor 29 | * @return 30 | * Always 0 31 | */ 32 | int nt99141_init(sensor_t *sensor); 33 | 34 | #endif // __NT99141_H__ 35 | -------------------------------------------------------------------------------- /sensors/private_include/ov2640.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 driver. 7 | * 8 | */ 9 | #ifndef __OV2640_H__ 10 | #define __OV2640_H__ 11 | #include "sensor.h" 12 | /** 13 | * @brief Detect sensor pid 14 | * 15 | * @param slv_addr SCCB address 16 | * @param id Detection result 17 | * @return 18 | * 0: Can't detect this sensor 19 | * Nonzero: This sensor has been detected 20 | */ 21 | int ov2640_detect(int slv_addr, sensor_id_t *id); 22 | 23 | /** 24 | * @brief initialize sensor function pointers 25 | * 26 | * @param sensor pointer of sensor 27 | * @return 28 | * Always 0 29 | */ 30 | int ov2640_init(sensor_t *sensor); 31 | 32 | #endif // __OV2640_H__ 33 | -------------------------------------------------------------------------------- /sensors/private_include/ov2640_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV2640 register definitions. 7 | */ 8 | #ifndef __REG_REGS_H__ 9 | #define __REG_REGS_H__ 10 | /* DSP register bank FF=0x00*/ 11 | #define R_BYPASS 0x05 12 | #define QS 0x44 13 | #define CTRLI 0x50 14 | #define HSIZE 0x51 15 | #define VSIZE 0x52 16 | #define XOFFL 0x53 17 | #define YOFFL 0x54 18 | #define VHYX 0x55 19 | #define DPRP 0x56 20 | #define TEST 0x57 21 | #define ZMOW 0x5A 22 | #define ZMOH 0x5B 23 | #define ZMHH 0x5C 24 | #define BPADDR 0x7C 25 | #define BPDATA 0x7D 26 | #define CTRL2 0x86 27 | #define CTRL3 0x87 28 | #define SIZEL 0x8C 29 | #define HSIZE8 0xC0 30 | #define VSIZE8 0xC1 31 | #define CTRL0 0xC2 32 | #define CTRL1 0xC3 33 | #define R_DVP_SP 0xD3 34 | #define IMAGE_MODE 0xDA 35 | #define RESET 0xE0 36 | #define MS_SP 0xF0 37 | #define SS_ID 0xF7 38 | #define SS_CTRL 0xF7 39 | #define MC_BIST 0xF9 40 | #define MC_AL 0xFA 41 | #define MC_AH 0xFB 42 | #define MC_D 0xFC 43 | #define P_CMD 0xFD 44 | #define P_STATUS 0xFE 45 | #define BANK_SEL 0xFF 46 | 47 | #define CTRLI_LP_DP 0x80 48 | #define CTRLI_ROUND 0x40 49 | 50 | #define CTRL0_AEC_EN 0x80 51 | #define CTRL0_AEC_SEL 0x40 52 | #define CTRL0_STAT_SEL 0x20 53 | #define CTRL0_VFIRST 0x10 54 | #define CTRL0_YUV422 0x08 55 | #define CTRL0_YUV_EN 0x04 56 | #define CTRL0_RGB_EN 0x02 57 | #define CTRL0_RAW_EN 0x01 58 | 59 | #define CTRL2_DCW_EN 0x20 60 | #define CTRL2_SDE_EN 0x10 61 | #define CTRL2_UV_ADJ_EN 0x08 62 | #define CTRL2_UV_AVG_EN 0x04 63 | #define CTRL2_CMX_EN 0x01 64 | 65 | #define CTRL3_BPC_EN 0x80 66 | #define CTRL3_WPC_EN 0x40 67 | 68 | #define R_DVP_SP_AUTO_MODE 0x80 69 | 70 | #define R_BYPASS_DSP_EN 0x00 71 | #define R_BYPASS_DSP_BYPAS 0x01 72 | 73 | #define IMAGE_MODE_Y8_DVP_EN 0x40 74 | #define IMAGE_MODE_JPEG_EN 0x10 75 | #define IMAGE_MODE_YUV422 0x00 76 | #define IMAGE_MODE_RAW10 0x04 77 | #define IMAGE_MODE_RGB565 0x08 78 | #define IMAGE_MODE_HREF_VSYNC 0x02 79 | #define IMAGE_MODE_LBYTE_FIRST 0x01 80 | 81 | #define RESET_MICROC 0x40 82 | #define RESET_SCCB 0x20 83 | #define RESET_JPEG 0x10 84 | #define RESET_DVP 0x04 85 | #define RESET_IPU 0x02 86 | #define RESET_CIF 0x01 87 | 88 | #define MC_BIST_RESET 0x80 89 | #define MC_BIST_BOOT_ROM_SEL 0x40 90 | #define MC_BIST_12KB_SEL 0x20 91 | #define MC_BIST_12KB_MASK 0x30 92 | #define MC_BIST_512KB_SEL 0x08 93 | #define MC_BIST_512KB_MASK 0x0C 94 | #define MC_BIST_BUSY_BIT_R 0x02 95 | #define MC_BIST_MC_RES_ONE_SH_W 0x02 96 | #define MC_BIST_LAUNCH 0x01 97 | 98 | 99 | typedef enum { 100 | BANK_DSP, BANK_SENSOR, BANK_MAX 101 | } ov2640_bank_t; 102 | 103 | /* Sensor register bank FF=0x01*/ 104 | #define GAIN 0x00 105 | #define COM1 0x03 106 | #define REG04 0x04 107 | #define REG08 0x08 108 | #define COM2 0x09 109 | #define REG_PID 0x0A 110 | #define REG_VER 0x0B 111 | #define COM3 0x0C 112 | #define COM4 0x0D 113 | #define AEC 0x10 114 | #define CLKRC 0x11 115 | #define COM7 0x12 116 | #define COM8 0x13 117 | #define COM9 0x14 /* AGC gain ceiling */ 118 | #define COM10 0x15 119 | #define HSTART 0x17 120 | #define HSTOP 0x18 121 | #define VSTART 0x19 122 | #define VSTOP 0x1A 123 | #define REG_MIDH 0x1C 124 | #define REG_MIDL 0x1D 125 | #define AEW 0x24 126 | #define AEB 0x25 127 | #define VV 0x26 128 | #define REG2A 0x2A 129 | #define FRARL 0x2B 130 | #define ADDVSL 0x2D 131 | #define ADDVSH 0x2E 132 | #define YAVG 0x2F 133 | #define HSDY 0x30 134 | #define HEDY 0x31 135 | #define REG32 0x32 136 | #define ARCOM2 0x34 137 | #define REG45 0x45 138 | #define FLL 0x46 139 | #define FLH 0x47 140 | #define COM19 0x48 141 | #define ZOOMS 0x49 142 | #define COM22 0x4B 143 | #define COM25 0x4E 144 | #define BD50 0x4F 145 | #define BD60 0x50 146 | #define REG5D 0x5D 147 | #define REG5E 0x5E 148 | #define REG5F 0x5F 149 | #define REG60 0x60 150 | #define HISTO_LOW 0x61 151 | #define HISTO_HIGH 0x62 152 | 153 | #define REG04_DEFAULT 0x28 154 | #define REG04_HFLIP_IMG 0x80 155 | #define REG04_VFLIP_IMG 0x40 156 | #define REG04_VREF_EN 0x10 157 | #define REG04_HREF_EN 0x08 158 | #define REG04_SET(x) (REG04_DEFAULT|x) 159 | 160 | #define COM2_STDBY 0x10 161 | #define COM2_OUT_DRIVE_1x 0x00 162 | #define COM2_OUT_DRIVE_2x 0x01 163 | #define COM2_OUT_DRIVE_3x 0x02 164 | #define COM2_OUT_DRIVE_4x 0x03 165 | 166 | #define COM3_DEFAULT 0x38 167 | #define COM3_BAND_50Hz 0x04 168 | #define COM3_BAND_60Hz 0x00 169 | #define COM3_BAND_AUTO 0x02 170 | #define COM3_BAND_SET(x) (COM3_DEFAULT|x) 171 | 172 | #define COM7_SRST 0x80 173 | #define COM7_RES_UXGA 0x00 /* UXGA */ 174 | #define COM7_RES_SVGA 0x40 /* SVGA */ 175 | #define COM7_RES_CIF 0x20 /* CIF */ 176 | #define COM7_ZOOM_EN 0x04 /* Enable Zoom */ 177 | #define COM7_COLOR_BAR 0x02 /* Enable Color Bar Test */ 178 | 179 | #define COM8_DEFAULT 0xC0 180 | #define COM8_BNDF_EN 0x20 /* Enable Banding filter */ 181 | #define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ 182 | #define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ 183 | #define COM8_SET(x) (COM8_DEFAULT|x) 184 | 185 | #define COM9_DEFAULT 0x08 186 | #define COM9_AGC_GAIN_2x 0x00 /* AGC: 2x */ 187 | #define COM9_AGC_GAIN_4x 0x01 /* AGC: 4x */ 188 | #define COM9_AGC_GAIN_8x 0x02 /* AGC: 8x */ 189 | #define COM9_AGC_GAIN_16x 0x03 /* AGC: 16x */ 190 | #define COM9_AGC_GAIN_32x 0x04 /* AGC: 32x */ 191 | #define COM9_AGC_GAIN_64x 0x05 /* AGC: 64x */ 192 | #define COM9_AGC_GAIN_128x 0x06 /* AGC: 128x */ 193 | #define COM9_AGC_SET(x) (COM9_DEFAULT|(x<<5)) 194 | 195 | #define COM10_HREF_EN 0x80 /* HSYNC changes to HREF */ 196 | #define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ 197 | #define COM10_PCLK_FREE 0x20 /* PCLK output option: free running PCLK */ 198 | #define COM10_PCLK_EDGE 0x10 /* Data is updated at the rising edge of PCLK */ 199 | #define COM10_HREF_NEG 0x08 /* HREF negative */ 200 | #define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ 201 | #define COM10_HSYNC_NEG 0x01 /* HSYNC negative */ 202 | 203 | #define CTRL1_AWB 0x08 /* Enable AWB */ 204 | 205 | #define VV_AGC_TH_SET(h,l) ((h<<4)|(l&0x0F)) 206 | 207 | #define REG32_UXGA 0x36 208 | #define REG32_SVGA 0x09 209 | #define REG32_CIF 0x89 210 | 211 | #define CLKRC_2X 0x80 212 | #define CLKRC_2X_UXGA (0x01 | CLKRC_2X) 213 | #define CLKRC_2X_SVGA CLKRC_2X 214 | #define CLKRC_2X_CIF CLKRC_2X 215 | 216 | #endif //__REG_REGS_H__ 217 | -------------------------------------------------------------------------------- /sensors/private_include/ov3660.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV3660 driver. 7 | * 8 | */ 9 | #ifndef __OV3660_H__ 10 | #define __OV3660_H__ 11 | 12 | #include "sensor.h" 13 | 14 | /** 15 | * @brief Detect sensor pid 16 | * 17 | * @param slv_addr SCCB address 18 | * @param id Detection result 19 | * @return 20 | * 0: Can't detect this sensor 21 | * Nonzero: This sensor has been detected 22 | */ 23 | int ov3660_detect(int slv_addr, sensor_id_t *id); 24 | 25 | /** 26 | * @brief initialize sensor function pointers 27 | * 28 | * @param sensor pointer of sensor 29 | * @return 30 | * Always 0 31 | */ 32 | int ov3660_init(sensor_t *sensor); 33 | 34 | #endif // __OV3660_H__ 35 | -------------------------------------------------------------------------------- /sensors/private_include/ov3660_regs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OV3660 register definitions. 3 | */ 4 | #ifndef __OV3660_REG_REGS_H__ 5 | #define __OV3660_REG_REGS_H__ 6 | 7 | /* system control registers */ 8 | #define SYSTEM_CTROL0 0x3008 // Bit[7]: Software reset 9 | // Bit[6]: Software power down 10 | // Bit[5]: Reserved 11 | // Bit[4]: SRB clock SYNC enable 12 | // Bit[3]: Isolation suspend select 13 | // Bit[2:0]: Not used 14 | 15 | /* output format control registers */ 16 | #define FORMAT_CTRL 0x501F // Format select 17 | // Bit[2:0]: 18 | // 000: YUV422 19 | // 001: RGB 20 | // 010: Dither 21 | // 011: RAW after DPC 22 | // 101: RAW after CIP 23 | 24 | /* format control registers */ 25 | #define FORMAT_CTRL00 0x4300 26 | 27 | /* frame control registers */ 28 | #define FRAME_CTRL01 0x4201 // Control Passed Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode 29 | // Bit[7:4]: Not used 30 | // Bit[3:0]: Frame ON number 31 | #define FRAME_CTRL02 0x4202 // Control Masked Frame Number When both ON and OFF number set to 0x00,frame control is in bypass mode 32 | // Bit[7:4]: Not used 33 | // BIT[3:0]: Frame OFF number 34 | 35 | /* ISP top control registers */ 36 | #define PRE_ISP_TEST_SETTING_1 0x503D // Bit[7]: Test enable 37 | // 0: Test disable 38 | // 1: Color bar enable 39 | // Bit[6]: Rolling 40 | // Bit[5]: Transparent 41 | // Bit[4]: Square black and white 42 | // Bit[3:2]: Color bar style 43 | // 00: Standard 8 color bar 44 | // 01: Gradual change at vertical mode 1 45 | // 10: Gradual change at horizontal 46 | // 11: Gradual change at vertical mode 2 47 | // Bit[1:0]: Test select 48 | // 00: Color bar 49 | // 01: Random data 50 | // 10: Square data 51 | // 11: Black image 52 | 53 | //exposure = {0x3500[3:0], 0x3501[7:0], 0x3502[7:0]} / 16 × tROW 54 | 55 | /* AEC/AGC control functions */ 56 | #define AEC_PK_MANUAL 0x3503 // AEC Manual Mode Control 57 | // Bit[7:6]: Reserved 58 | // Bit[5]: Gain delay option 59 | // Valid when 0x3503[4]=1’b0 60 | // 0: Delay one frame latch 61 | // 1: One frame latch 62 | // Bit[4:2]: Reserved 63 | // Bit[1]: AGC manual 64 | // 0: Auto enable 65 | // 1: Manual enable 66 | // Bit[0]: AEC manual 67 | // 0: Auto enable 68 | // 1: Manual enable 69 | 70 | //gain = {0x350A[1:0], 0x350B[7:0]} / 16 71 | 72 | /* mirror and flip registers */ 73 | #define TIMING_TC_REG20 0x3820 // Timing Control Register 74 | // Bit[2:1]: Vertical flip enable 75 | // 00: Normal 76 | // 11: Vertical flip 77 | // Bit[0]: Vertical binning enable 78 | #define TIMING_TC_REG21 0x3821 // Timing Control Register 79 | // Bit[5]: Compression Enable 80 | // Bit[2:1]: Horizontal mirror enable 81 | // 00: Normal 82 | // 11: Horizontal mirror 83 | // Bit[0]: Horizontal binning enable 84 | 85 | #define CLOCK_POL_CONTROL 0x4740// Bit[5]: PCLK polarity 0: active low 86 | // 1: active high 87 | // Bit[3]: Gate PCLK under VSYNC 88 | // Bit[2]: Gate PCLK under HREF 89 | // Bit[1]: HREF polarity 90 | // 0: active low 91 | // 1: active high 92 | // Bit[0] VSYNC polarity 93 | // 0: active low 94 | // 1: active high 95 | #define DRIVE_CAPABILITY 0x302c // Bit[7:6]: 96 | // 00: 1x 97 | // 01: 2x 98 | // 10: 3x 99 | // 11: 4x 100 | 101 | 102 | #define X_ADDR_ST_H 0x3800 //Bit[3:0]: X address start[11:8] 103 | #define X_ADDR_ST_L 0x3801 //Bit[7:0]: X address start[7:0] 104 | #define Y_ADDR_ST_H 0x3802 //Bit[2:0]: Y address start[10:8] 105 | #define Y_ADDR_ST_L 0x3803 //Bit[7:0]: Y address start[7:0] 106 | #define X_ADDR_END_H 0x3804 //Bit[3:0]: X address end[11:8] 107 | #define X_ADDR_END_L 0x3805 //Bit[7:0]: 108 | #define Y_ADDR_END_H 0x3806 //Bit[2:0]: Y address end[10:8] 109 | #define Y_ADDR_END_L 0x3807 //Bit[7:0]: 110 | // Size after scaling 111 | #define X_OUTPUT_SIZE_H 0x3808 //Bit[3:0]: DVP output horizontal width[11:8] 112 | #define X_OUTPUT_SIZE_L 0x3809 //Bit[7:0]: 113 | #define Y_OUTPUT_SIZE_H 0x380a //Bit[2:0]: DVP output vertical height[10:8] 114 | #define Y_OUTPUT_SIZE_L 0x380b //Bit[7:0]: 115 | #define X_TOTAL_SIZE_H 0x380c //Bit[3:0]: Total horizontal size[11:8] 116 | #define X_TOTAL_SIZE_L 0x380d //Bit[7:0]: 117 | #define Y_TOTAL_SIZE_H 0x380e //Bit[7:0]: Total vertical size[15:8] 118 | #define Y_TOTAL_SIZE_L 0x380f //Bit[7:0]: 119 | #define X_OFFSET_H 0x3810 //Bit[3:0]: ISP horizontal offset[11:8] 120 | #define X_OFFSET_L 0x3811 //Bit[7:0]: 121 | #define Y_OFFSET_H 0x3812 //Bit[2:0]: ISP vertical offset[10:8] 122 | #define Y_OFFSET_L 0x3813 //Bit[7:0]: 123 | #define X_INCREMENT 0x3814 //Bit[7:4]: Horizontal odd subsample increment 124 | //Bit[3:0]: Horizontal even subsample increment 125 | #define Y_INCREMENT 0x3815 //Bit[7:4]: Vertical odd subsample increment 126 | //Bit[3:0]: Vertical even subsample increment 127 | // Size before scaling 128 | //#define X_INPUT_SIZE (X_ADDR_END - X_ADDR_ST + 1 - (2 * X_OFFSET)) 129 | //#define Y_INPUT_SIZE (Y_ADDR_END - Y_ADDR_ST + 1 - (2 * Y_OFFSET)) 130 | 131 | #define ISP_CONTROL_01 0x5001 // Bit[5]: Scale enable 132 | // 0: Disable 133 | // 1: Enable 134 | 135 | #define SCALE_CTRL_1 0x5601 // Bit[6:4]: HDIV RW 136 | // DCW scale times 137 | // 000: DCW 1 time 138 | // 001: DCW 2 times 139 | // 010: DCW 4 times 140 | // 100: DCW 8 times 141 | // 101: DCW 16 times 142 | // Others: DCW 16 times 143 | // Bit[2:0]: VDIV RW 144 | // DCW scale times 145 | // 000: DCW 1 time 146 | // 001: DCW 2 times 147 | // 010: DCW 4 times 148 | // 100: DCW 8 times 149 | // 101: DCW 16 times 150 | // Others: DCW 16 times 151 | 152 | #define SCALE_CTRL_2 0x5602 // X_SCALE High Bits 153 | #define SCALE_CTRL_3 0x5603 // X_SCALE Low Bits 154 | #define SCALE_CTRL_4 0x5604 // Y_SCALE High Bits 155 | #define SCALE_CTRL_5 0x5605 // Y_SCALE Low Bits 156 | #define SCALE_CTRL_6 0x5606 // Bit[3:0]: V Offset 157 | 158 | #define PCLK_RATIO 0x3824 // Bit[4:0]: PCLK ratio manual 159 | #define VFIFO_CTRL0C 0x460C // Bit[1]: PCLK manual enable 160 | // 0: Auto 161 | // 1: Manual by PCLK_RATIO 162 | 163 | #define VFIFO_X_SIZE_H 0x4602 164 | #define VFIFO_X_SIZE_L 0x4603 165 | #define VFIFO_Y_SIZE_H 0x4604 166 | #define VFIFO_Y_SIZE_L 0x4605 167 | 168 | #define SC_PLLS_CTRL0 0x303a // Bit[7]: PLLS bypass 169 | #define SC_PLLS_CTRL1 0x303b // Bit[4:0]: PLLS multiplier 170 | #define SC_PLLS_CTRL2 0x303c // Bit[6:4]: PLLS charge pump control 171 | // Bit[3:0]: PLLS system divider 172 | #define SC_PLLS_CTRL3 0x303d // Bit[5:4]: PLLS pre-divider 173 | // 00: 1 174 | // 01: 1.5 175 | // 10: 2 176 | // 11: 3 177 | // Bit[2]: PLLS root-divider - 1 178 | // Bit[1:0]: PLLS seld5 179 | // 00: 1 180 | // 01: 1 181 | // 10: 2 182 | // 11: 2.5 183 | 184 | #define COMPRESSION_CTRL00 0x4400 // 185 | #define COMPRESSION_CTRL01 0x4401 // 186 | #define COMPRESSION_CTRL02 0x4402 // 187 | #define COMPRESSION_CTRL03 0x4403 // 188 | #define COMPRESSION_CTRL04 0x4404 // 189 | #define COMPRESSION_CTRL05 0x4405 // 190 | #define COMPRESSION_CTRL06 0x4406 // 191 | #define COMPRESSION_CTRL07 0x4407 // Bit[5:0]: QS 192 | #define COMPRESSION_ISI_CTRL 0x4408 // 193 | #define COMPRESSION_CTRL09 0x4409 // 194 | #define COMPRESSION_CTRL0a 0x440a // 195 | #define COMPRESSION_CTRL0b 0x440b // 196 | #define COMPRESSION_CTRL0c 0x440c // 197 | #define COMPRESSION_CTRL0d 0x440d // 198 | #define COMPRESSION_CTRL0E 0x440e // 199 | 200 | /** 201 | * @brief register value 202 | */ 203 | #define TEST_COLOR_BAR 0xC0 /* Enable Color Bar roling Test */ 204 | 205 | #define AEC_PK_MANUAL_AGC_MANUALEN 0x02 /* Enable AGC Manual enable */ 206 | #define AEC_PK_MANUAL_AEC_MANUALEN 0x01 /* Enable AEC Manual enable */ 207 | 208 | #define TIMING_TC_REG20_VFLIP 0x06 /* Vertical flip enable */ 209 | #define TIMING_TC_REG21_HMIRROR 0x06 /* Horizontal mirror enable */ 210 | 211 | #endif // __OV3660_REG_REGS_H__ 212 | -------------------------------------------------------------------------------- /sensors/private_include/ov3660_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _OV3660_SETTINGS_H_ 2 | #define _OV3660_SETTINGS_H_ 3 | 4 | #include 5 | #include 6 | #include "esp_attr.h" 7 | #include "ov3660_regs.h" 8 | 9 | static const ratio_settings_t ratio_table[] = { 10 | // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty 11 | { 2048, 1536, 0, 0, 2079, 1547, 16, 6, 2300, 1564 }, //4x3 12 | { 1920, 1280, 64, 128, 2015, 1419, 16, 6, 2172, 1436 }, //3x2 13 | { 2048, 1280, 0, 128, 2079, 1419, 16, 6, 2300, 1436 }, //16x10 14 | { 1920, 1152, 64, 192, 2015, 1355, 16, 6, 2172, 1372 }, //5x3 15 | { 1920, 1080, 64, 242, 2015, 1333, 16, 6, 2172, 1322 }, //16x9 16 | { 2048, 880, 0, 328, 2079, 1219, 16, 6, 2300, 1236 }, //21x9 17 | { 1920, 1536, 64, 0, 2015, 1547, 16, 6, 2172, 1564 }, //5x4 18 | { 1536, 1536, 256, 0, 1823, 1547, 16, 6, 2044, 1564 }, //1x1 19 | { 864, 1536, 592, 0, 1487, 1547, 16, 6, 2044, 1564 } //9x16 20 | }; 21 | 22 | #define REG_DLY 0xffff 23 | #define REGLIST_TAIL 0x0000 24 | 25 | static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { 26 | {SYSTEM_CTROL0, 0x82}, // software reset 27 | {REG_DLY, 10}, // delay 10ms 28 | 29 | {0x3103, 0x13}, 30 | {SYSTEM_CTROL0, 0x42}, 31 | {0x3017, 0xff}, 32 | {0x3018, 0xff}, 33 | {DRIVE_CAPABILITY, 0xc3}, 34 | {CLOCK_POL_CONTROL, 0x21}, 35 | 36 | {0x3611, 0x01}, 37 | {0x3612, 0x2d}, 38 | 39 | {0x3032, 0x00}, 40 | {0x3614, 0x80}, 41 | {0x3618, 0x00}, 42 | {0x3619, 0x75}, 43 | {0x3622, 0x80}, 44 | {0x3623, 0x00}, 45 | {0x3624, 0x03}, 46 | {0x3630, 0x52}, 47 | {0x3632, 0x07}, 48 | {0x3633, 0xd2}, 49 | {0x3704, 0x80}, 50 | {0x3708, 0x66}, 51 | {0x3709, 0x12}, 52 | {0x370b, 0x12}, 53 | {0x3717, 0x00}, 54 | {0x371b, 0x60}, 55 | {0x371c, 0x00}, 56 | {0x3901, 0x13}, 57 | 58 | {0x3600, 0x08}, 59 | {0x3620, 0x43}, 60 | {0x3702, 0x20}, 61 | {0x3739, 0x48}, 62 | {0x3730, 0x20}, 63 | {0x370c, 0x0c}, 64 | 65 | {0x3a18, 0x00}, 66 | {0x3a19, 0xf8}, 67 | 68 | {0x3000, 0x10}, 69 | {0x3004, 0xef}, 70 | 71 | {0x6700, 0x05}, 72 | {0x6701, 0x19}, 73 | {0x6702, 0xfd}, 74 | {0x6703, 0xd1}, 75 | {0x6704, 0xff}, 76 | {0x6705, 0xff}, 77 | 78 | {0x3c01, 0x80}, 79 | {0x3c00, 0x04}, 80 | {0x3a08, 0x00}, {0x3a09, 0x62}, //50Hz Band Width Step (10bit) 81 | {0x3a0e, 0x08}, //50Hz Max Bands in One Frame (6 bit) 82 | {0x3a0a, 0x00}, {0x3a0b, 0x52}, //60Hz Band Width Step (10bit) 83 | {0x3a0d, 0x09}, //60Hz Max Bands in One Frame (6 bit) 84 | 85 | {0x3a00, 0x3a},//night mode off 86 | {0x3a14, 0x09}, 87 | {0x3a15, 0x30}, 88 | {0x3a02, 0x09}, 89 | {0x3a03, 0x30}, 90 | 91 | {COMPRESSION_CTRL0E, 0x08}, 92 | {0x4520, 0x0b}, 93 | {0x460b, 0x37}, 94 | {0x4713, 0x02}, 95 | {0x471c, 0xd0}, 96 | {0x5086, 0x00}, 97 | 98 | {0x5002, 0x00}, 99 | {0x501f, 0x00}, 100 | 101 | {SYSTEM_CTROL0, 0x02}, 102 | 103 | {0x5180, 0xff}, 104 | {0x5181, 0xf2}, 105 | {0x5182, 0x00}, 106 | {0x5183, 0x14}, 107 | {0x5184, 0x25}, 108 | {0x5185, 0x24}, 109 | {0x5186, 0x16}, 110 | {0x5187, 0x16}, 111 | {0x5188, 0x16}, 112 | {0x5189, 0x68}, 113 | {0x518a, 0x60}, 114 | {0x518b, 0xe0}, 115 | {0x518c, 0xb2}, 116 | {0x518d, 0x42}, 117 | {0x518e, 0x35}, 118 | {0x518f, 0x56}, 119 | {0x5190, 0x56}, 120 | {0x5191, 0xf8}, 121 | {0x5192, 0x04}, 122 | {0x5193, 0x70}, 123 | {0x5194, 0xf0}, 124 | {0x5195, 0xf0}, 125 | {0x5196, 0x03}, 126 | {0x5197, 0x01}, 127 | {0x5198, 0x04}, 128 | {0x5199, 0x12}, 129 | {0x519a, 0x04}, 130 | {0x519b, 0x00}, 131 | {0x519c, 0x06}, 132 | {0x519d, 0x82}, 133 | {0x519e, 0x38}, 134 | 135 | {0x5381, 0x1d}, 136 | {0x5382, 0x60}, 137 | {0x5383, 0x03}, 138 | {0x5384, 0x0c}, 139 | {0x5385, 0x78}, 140 | {0x5386, 0x84}, 141 | {0x5387, 0x7d}, 142 | {0x5388, 0x6b}, 143 | {0x5389, 0x12}, 144 | {0x538a, 0x01}, 145 | {0x538b, 0x98}, 146 | 147 | {0x5480, 0x01}, 148 | // {0x5481, 0x05}, 149 | // {0x5482, 0x09}, 150 | // {0x5483, 0x10}, 151 | // {0x5484, 0x3a}, 152 | // {0x5485, 0x4c}, 153 | // {0x5486, 0x5a}, 154 | // {0x5487, 0x68}, 155 | // {0x5488, 0x74}, 156 | // {0x5489, 0x80}, 157 | // {0x548a, 0x8e}, 158 | // {0x548b, 0xa4}, 159 | // {0x548c, 0xb4}, 160 | // {0x548d, 0xc8}, 161 | // {0x548e, 0xde}, 162 | // {0x548f, 0xf0}, 163 | // {0x5490, 0x15}, 164 | 165 | {0x5000, 0xa7}, 166 | {0x5800, 0x0C}, 167 | {0x5801, 0x09}, 168 | {0x5802, 0x0C}, 169 | {0x5803, 0x0C}, 170 | {0x5804, 0x0D}, 171 | {0x5805, 0x17}, 172 | {0x5806, 0x06}, 173 | {0x5807, 0x05}, 174 | {0x5808, 0x04}, 175 | {0x5809, 0x06}, 176 | {0x580a, 0x09}, 177 | {0x580b, 0x0E}, 178 | {0x580c, 0x05}, 179 | {0x580d, 0x01}, 180 | {0x580e, 0x01}, 181 | {0x580f, 0x01}, 182 | {0x5810, 0x05}, 183 | {0x5811, 0x0D}, 184 | {0x5812, 0x05}, 185 | {0x5813, 0x01}, 186 | {0x5814, 0x01}, 187 | {0x5815, 0x01}, 188 | {0x5816, 0x05}, 189 | {0x5817, 0x0D}, 190 | {0x5818, 0x08}, 191 | {0x5819, 0x06}, 192 | {0x581a, 0x05}, 193 | {0x581b, 0x07}, 194 | {0x581c, 0x0B}, 195 | {0x581d, 0x0D}, 196 | {0x581e, 0x12}, 197 | {0x581f, 0x0D}, 198 | {0x5820, 0x0E}, 199 | {0x5821, 0x10}, 200 | {0x5822, 0x10}, 201 | {0x5823, 0x1E}, 202 | {0x5824, 0x53}, 203 | {0x5825, 0x15}, 204 | {0x5826, 0x05}, 205 | {0x5827, 0x14}, 206 | {0x5828, 0x54}, 207 | {0x5829, 0x25}, 208 | {0x582a, 0x33}, 209 | {0x582b, 0x33}, 210 | {0x582c, 0x34}, 211 | {0x582d, 0x16}, 212 | {0x582e, 0x24}, 213 | {0x582f, 0x41}, 214 | {0x5830, 0x50}, 215 | {0x5831, 0x42}, 216 | {0x5832, 0x15}, 217 | {0x5833, 0x25}, 218 | {0x5834, 0x34}, 219 | {0x5835, 0x33}, 220 | {0x5836, 0x24}, 221 | {0x5837, 0x26}, 222 | {0x5838, 0x54}, 223 | {0x5839, 0x25}, 224 | {0x583a, 0x15}, 225 | {0x583b, 0x25}, 226 | {0x583c, 0x53}, 227 | {0x583d, 0xCF}, 228 | 229 | {0x3a0f, 0x30}, 230 | {0x3a10, 0x28}, 231 | {0x3a1b, 0x30}, 232 | {0x3a1e, 0x28}, 233 | {0x3a11, 0x60}, 234 | {0x3a1f, 0x14}, 235 | 236 | {0x5302, 0x28}, 237 | {0x5303, 0x20}, 238 | 239 | {0x5306, 0x1c}, //de-noise offset 1 240 | {0x5307, 0x28}, //de-noise offset 2 241 | 242 | {0x4002, 0xc5}, 243 | {0x4003, 0x81}, 244 | {0x4005, 0x12}, 245 | 246 | {0x5688, 0x11}, 247 | {0x5689, 0x11}, 248 | {0x568a, 0x11}, 249 | {0x568b, 0x11}, 250 | {0x568c, 0x11}, 251 | {0x568d, 0x11}, 252 | {0x568e, 0x11}, 253 | {0x568f, 0x11}, 254 | 255 | {0x5580, 0x06}, 256 | {0x5588, 0x00}, 257 | {0x5583, 0x40}, 258 | {0x5584, 0x2c}, 259 | 260 | {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE 261 | {REGLIST_TAIL, 0x00}, // tail 262 | }; 263 | 264 | static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { 265 | {FORMAT_CTRL, 0x00}, // YUV422 266 | {FORMAT_CTRL00, 0x30}, // YUYV 267 | {0x3002, 0x00},//0x1c to 0x00 !!! 268 | {0x3006, 0xff},//0xc3 to 0xff !!! 269 | {0x471c, 0x50},//0xd0 to 0x50 !!! 270 | {REGLIST_TAIL, 0x00}, // tail 271 | }; 272 | 273 | static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { 274 | {FORMAT_CTRL00, 0x00}, // RAW 275 | {REGLIST_TAIL, 0x00} 276 | }; 277 | 278 | static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { 279 | {FORMAT_CTRL, 0x00}, // YUV422 280 | {FORMAT_CTRL00, 0x10}, // Y8 281 | {REGLIST_TAIL, 0x00} 282 | }; 283 | 284 | static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { 285 | {FORMAT_CTRL, 0x00}, // YUV422 286 | {FORMAT_CTRL00, 0x30}, // YUYV 287 | {REGLIST_TAIL, 0x00} 288 | }; 289 | 290 | static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { 291 | {FORMAT_CTRL, 0x01}, // RGB 292 | {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) 293 | {REGLIST_TAIL, 0x00} 294 | }; 295 | 296 | static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { 297 | {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 298 | {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 299 | {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 300 | {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 301 | {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 302 | {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 303 | {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 304 | {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 305 | {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 306 | }; 307 | 308 | static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { 309 | {0x06, 0x40, 0x2c, 0x08},//Normal 310 | {0x46, 0x40, 0x28, 0x08},//Negative 311 | {0x1e, 0x80, 0x80, 0x08},//Grayscale 312 | {0x1e, 0x80, 0xc0, 0x08},//Red Tint 313 | {0x1e, 0x60, 0x60, 0x08},//Green Tint 314 | {0x1e, 0xa0, 0x40, 0x08},//Blue Tint 315 | {0x1e, 0x40, 0xa0, 0x08},//Sepia 316 | }; 317 | 318 | #endif 319 | -------------------------------------------------------------------------------- /sensors/private_include/ov5640.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __OV5640_H__ 3 | #define __OV5640_H__ 4 | 5 | #include "sensor.h" 6 | 7 | /** 8 | * @brief Detect sensor pid 9 | * 10 | * @param slv_addr SCCB address 11 | * @param id Detection result 12 | * @return 13 | * 0: Can't detect this sensor 14 | * Nonzero: This sensor has been detected 15 | */ 16 | int ov5640_detect(int slv_addr, sensor_id_t *id); 17 | 18 | /** 19 | * @brief initialize sensor function pointers 20 | * 21 | * @param sensor pointer of sensor 22 | * @return 23 | * Always 0 24 | */ 25 | int ov5640_init(sensor_t *sensor); 26 | 27 | #endif // __OV5640_H__ 28 | -------------------------------------------------------------------------------- /sensors/private_include/ov5640_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef _OV5640_SETTINGS_H_ 2 | #define _OV5640_SETTINGS_H_ 3 | 4 | #include 5 | #include 6 | #include "esp_attr.h" 7 | #include "ov5640_regs.h" 8 | 9 | static const ratio_settings_t ratio_table[] = { 10 | // mw, mh, sx, sy, ex, ey, ox, oy, tx, ty 11 | { 2560, 1920, 0, 0, 2623, 1951, 32, 16, 2844, 1968 }, //4x3 12 | { 2560, 1704, 0, 110, 2623, 1843, 32, 16, 2844, 1752 }, //3x2 13 | { 2560, 1600, 0, 160, 2623, 1791, 32, 16, 2844, 1648 }, //16x10 14 | { 2560, 1536, 0, 192, 2623, 1759, 32, 16, 2844, 1584 }, //5x3 15 | { 2560, 1440, 0, 240, 2623, 1711, 32, 16, 2844, 1488 }, //16x9 16 | { 2560, 1080, 0, 420, 2623, 1531, 32, 16, 2844, 1128 }, //21x9 17 | { 2400, 1920, 80, 0, 2543, 1951, 32, 16, 2684, 1968 }, //5x4 18 | { 1920, 1920, 320, 0, 2543, 1951, 32, 16, 2684, 1968 }, //1x1 19 | { 1088, 1920, 736, 0, 1887, 1951, 32, 16, 1884, 1968 } //9x16 20 | }; 21 | 22 | #define REG_DLY 0xffff 23 | #define REGLIST_TAIL 0x0000 24 | 25 | static const DRAM_ATTR uint16_t sensor_default_regs[][2] = { 26 | {SYSTEM_CTROL0, 0x82}, // software reset 27 | {REG_DLY, 10}, // delay 10ms 28 | {SYSTEM_CTROL0, 0x42}, // power down 29 | 30 | //enable pll 31 | {0x3103, 0x13}, 32 | 33 | //io direction 34 | {0x3017, 0xff}, 35 | {0x3018, 0xff}, 36 | 37 | {DRIVE_CAPABILITY, 0xc3}, 38 | {CLOCK_POL_CONTROL, 0x21}, 39 | 40 | {0x4713, 0x02},//jpg mode select 41 | 42 | {ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE 43 | 44 | //sys reset 45 | {0x3000, 0x20}, // reset MCU 46 | {REG_DLY, 10}, // delay 10ms 47 | {0x3002, 0x1c}, 48 | 49 | //clock enable 50 | {0x3004, 0xff}, 51 | {0x3006, 0xc3}, 52 | 53 | //isp control 54 | {0x5000, 0xa7}, 55 | {ISP_CONTROL_01, 0xa3},//+scaling? 56 | {0x5003, 0x08},//special_effect 57 | 58 | //unknown 59 | {0x370c, 0x02},//!!IMPORTANT 60 | {0x3634, 0x40},//!!IMPORTANT 61 | 62 | //AEC/AGC 63 | {0x3a02, 0x03}, 64 | {0x3a03, 0xd8}, 65 | {0x3a08, 0x01}, 66 | {0x3a09, 0x27}, 67 | {0x3a0a, 0x00}, 68 | {0x3a0b, 0xf6}, 69 | {0x3a0d, 0x04}, 70 | {0x3a0e, 0x03}, 71 | {0x3a0f, 0x30},//ae_level 72 | {0x3a10, 0x28},//ae_level 73 | {0x3a11, 0x60},//ae_level 74 | {0x3a13, 0x43}, 75 | {0x3a14, 0x03}, 76 | {0x3a15, 0xd8}, 77 | {0x3a18, 0x00},//gainceiling 78 | {0x3a19, 0xf8},//gainceiling 79 | {0x3a1b, 0x30},//ae_level 80 | {0x3a1e, 0x26},//ae_level 81 | {0x3a1f, 0x14},//ae_level 82 | 83 | //vcm debug 84 | {0x3600, 0x08}, 85 | {0x3601, 0x33}, 86 | 87 | //50/60Hz 88 | {0x3c01, 0xa4}, 89 | {0x3c04, 0x28}, 90 | {0x3c05, 0x98}, 91 | {0x3c06, 0x00}, 92 | {0x3c07, 0x08}, 93 | {0x3c08, 0x00}, 94 | {0x3c09, 0x1c}, 95 | {0x3c0a, 0x9c}, 96 | {0x3c0b, 0x40}, 97 | 98 | {0x460c, 0x22},//disable jpeg footer 99 | 100 | //BLC 101 | {0x4001, 0x02}, 102 | {0x4004, 0x02}, 103 | 104 | //AWB 105 | {0x5180, 0xff}, 106 | {0x5181, 0xf2}, 107 | {0x5182, 0x00}, 108 | {0x5183, 0x14}, 109 | {0x5184, 0x25}, 110 | {0x5185, 0x24}, 111 | {0x5186, 0x09}, 112 | {0x5187, 0x09}, 113 | {0x5188, 0x09}, 114 | {0x5189, 0x75}, 115 | {0x518a, 0x54}, 116 | {0x518b, 0xe0}, 117 | {0x518c, 0xb2}, 118 | {0x518d, 0x42}, 119 | {0x518e, 0x3d}, 120 | {0x518f, 0x56}, 121 | {0x5190, 0x46}, 122 | {0x5191, 0xf8}, 123 | {0x5192, 0x04}, 124 | {0x5193, 0x70}, 125 | {0x5194, 0xf0}, 126 | {0x5195, 0xf0}, 127 | {0x5196, 0x03}, 128 | {0x5197, 0x01}, 129 | {0x5198, 0x04}, 130 | {0x5199, 0x12}, 131 | {0x519a, 0x04}, 132 | {0x519b, 0x00}, 133 | {0x519c, 0x06}, 134 | {0x519d, 0x82}, 135 | {0x519e, 0x38}, 136 | 137 | //color matrix (Saturation) 138 | {0x5381, 0x1e}, 139 | {0x5382, 0x5b}, 140 | {0x5383, 0x08}, 141 | {0x5384, 0x0a}, 142 | {0x5385, 0x7e}, 143 | {0x5386, 0x88}, 144 | {0x5387, 0x7c}, 145 | {0x5388, 0x6c}, 146 | {0x5389, 0x10}, 147 | {0x538a, 0x01}, 148 | {0x538b, 0x98}, 149 | 150 | //CIP control (Sharpness) 151 | {0x5300, 0x10},//sharpness 152 | {0x5301, 0x10},//sharpness 153 | {0x5302, 0x18},//sharpness 154 | {0x5303, 0x19},//sharpness 155 | {0x5304, 0x10}, 156 | {0x5305, 0x10}, 157 | {0x5306, 0x08},//denoise 158 | {0x5307, 0x16}, 159 | {0x5308, 0x40}, 160 | {0x5309, 0x10},//sharpness 161 | {0x530a, 0x10},//sharpness 162 | {0x530b, 0x04},//sharpness 163 | {0x530c, 0x06},//sharpness 164 | 165 | //GAMMA 166 | {0x5480, 0x01}, 167 | {0x5481, 0x00}, 168 | {0x5482, 0x1e}, 169 | {0x5483, 0x3b}, 170 | {0x5484, 0x58}, 171 | {0x5485, 0x66}, 172 | {0x5486, 0x71}, 173 | {0x5487, 0x7d}, 174 | {0x5488, 0x83}, 175 | {0x5489, 0x8f}, 176 | {0x548a, 0x98}, 177 | {0x548b, 0xa6}, 178 | {0x548c, 0xb8}, 179 | {0x548d, 0xca}, 180 | {0x548e, 0xd7}, 181 | {0x548f, 0xe3}, 182 | {0x5490, 0x1d}, 183 | 184 | //Special Digital Effects (SDE) (UV adjust) 185 | {0x5580, 0x06},//enable brightness and contrast 186 | {0x5583, 0x40},//special_effect 187 | {0x5584, 0x10},//special_effect 188 | {0x5586, 0x20},//contrast 189 | {0x5587, 0x00},//brightness 190 | {0x5588, 0x00},//brightness 191 | {0x5589, 0x10}, 192 | {0x558a, 0x00}, 193 | {0x558b, 0xf8}, 194 | {0x501d, 0x40},// enable manual offset of contrast 195 | 196 | //power on 197 | {0x3008, 0x02}, 198 | 199 | //50Hz 200 | {0x3c00, 0x04}, 201 | 202 | {REG_DLY, 300}, 203 | {REGLIST_TAIL, 0x00}, // tail 204 | }; 205 | 206 | static const DRAM_ATTR uint16_t sensor_fmt_jpeg[][2] = { 207 | {FORMAT_CTRL, 0x00}, // YUV422 208 | {FORMAT_CTRL00, 0x30}, // YUYV 209 | {0x3002, 0x00},//0x1c to 0x00 !!! 210 | {0x3006, 0xff},//0xc3 to 0xff !!! 211 | {0x471c, 0x50},//0xd0 to 0x50 !!! 212 | {REGLIST_TAIL, 0x00}, // tail 213 | }; 214 | 215 | static const DRAM_ATTR uint16_t sensor_fmt_raw[][2] = { 216 | {FORMAT_CTRL, 0x03}, // RAW (DPC) 217 | {FORMAT_CTRL00, 0x00}, // RAW 218 | {REGLIST_TAIL, 0x00} 219 | }; 220 | 221 | static const DRAM_ATTR uint16_t sensor_fmt_grayscale[][2] = { 222 | {FORMAT_CTRL, 0x00}, // YUV422 223 | {FORMAT_CTRL00, 0x10}, // Y8 224 | {REGLIST_TAIL, 0x00} 225 | }; 226 | 227 | static const DRAM_ATTR uint16_t sensor_fmt_yuv422[][2] = { 228 | {FORMAT_CTRL, 0x00}, // YUV422 229 | {FORMAT_CTRL00, 0x30}, // YUYV 230 | {REGLIST_TAIL, 0x00} 231 | }; 232 | 233 | static const DRAM_ATTR uint16_t sensor_fmt_rgb565[][2] = { 234 | {FORMAT_CTRL, 0x01}, // RGB 235 | {FORMAT_CTRL00, 0x61}, // RGB565 (BGR) 236 | {REGLIST_TAIL, 0x00} 237 | }; 238 | 239 | static const DRAM_ATTR uint8_t sensor_saturation_levels[9][11] = { 240 | {0x1d, 0x60, 0x03, 0x07, 0x48, 0x4f, 0x4b, 0x40, 0x0b, 0x01, 0x98},//-4 241 | {0x1d, 0x60, 0x03, 0x08, 0x54, 0x5c, 0x58, 0x4b, 0x0d, 0x01, 0x98},//-3 242 | {0x1d, 0x60, 0x03, 0x0a, 0x60, 0x6a, 0x64, 0x56, 0x0e, 0x01, 0x98},//-2 243 | {0x1d, 0x60, 0x03, 0x0b, 0x6c, 0x77, 0x70, 0x60, 0x10, 0x01, 0x98},//-1 244 | {0x1d, 0x60, 0x03, 0x0c, 0x78, 0x84, 0x7d, 0x6b, 0x12, 0x01, 0x98},//0 245 | {0x1d, 0x60, 0x03, 0x0d, 0x84, 0x91, 0x8a, 0x76, 0x14, 0x01, 0x98},//+1 246 | {0x1d, 0x60, 0x03, 0x0e, 0x90, 0x9e, 0x96, 0x80, 0x16, 0x01, 0x98},//+2 247 | {0x1d, 0x60, 0x03, 0x10, 0x9c, 0xac, 0xa2, 0x8b, 0x17, 0x01, 0x98},//+3 248 | {0x1d, 0x60, 0x03, 0x11, 0xa8, 0xb9, 0xaf, 0x96, 0x19, 0x01, 0x98},//+4 249 | }; 250 | 251 | static const DRAM_ATTR uint8_t sensor_special_effects[7][4] = { 252 | {0x06, 0x40, 0x2c, 0x08},//Normal 253 | {0x46, 0x40, 0x28, 0x08},//Negative 254 | {0x1e, 0x80, 0x80, 0x08},//Grayscale 255 | {0x1e, 0x80, 0xc0, 0x08},//Red Tint 256 | {0x1e, 0x60, 0x60, 0x08},//Green Tint 257 | {0x1e, 0xa0, 0x40, 0x08},//Blue Tint 258 | {0x1e, 0x40, 0xa0, 0x08},//Sepia 259 | }; 260 | 261 | static const DRAM_ATTR uint16_t sensor_regs_gamma0[][2] = { 262 | {0x5480, 0x01}, 263 | {0x5481, 0x08}, 264 | {0x5482, 0x14}, 265 | {0x5483, 0x28}, 266 | {0x5484, 0x51}, 267 | {0x5485, 0x65}, 268 | {0x5486, 0x71}, 269 | {0x5487, 0x7d}, 270 | {0x5488, 0x87}, 271 | {0x5489, 0x91}, 272 | {0x548a, 0x9a}, 273 | {0x548b, 0xaa}, 274 | {0x548c, 0xb8}, 275 | {0x548d, 0xcd}, 276 | {0x548e, 0xdd}, 277 | {0x548f, 0xea}, 278 | {0x5490, 0x1d} 279 | }; 280 | 281 | static const DRAM_ATTR uint16_t sensor_regs_gamma1[][2] = { 282 | {0x5480, 0x1}, 283 | {0x5481, 0x0}, 284 | {0x5482, 0x1e}, 285 | {0x5483, 0x3b}, 286 | {0x5484, 0x58}, 287 | {0x5485, 0x66}, 288 | {0x5486, 0x71}, 289 | {0x5487, 0x7d}, 290 | {0x5488, 0x83}, 291 | {0x5489, 0x8f}, 292 | {0x548a, 0x98}, 293 | {0x548b, 0xa6}, 294 | {0x548c, 0xb8}, 295 | {0x548d, 0xca}, 296 | {0x548e, 0xd7}, 297 | {0x548f, 0xe3}, 298 | {0x5490, 0x1d} 299 | }; 300 | 301 | static const DRAM_ATTR uint16_t sensor_regs_awb0[][2] = { 302 | {0x5180, 0xff}, 303 | {0x5181, 0xf2}, 304 | {0x5182, 0x00}, 305 | {0x5183, 0x14}, 306 | {0x5184, 0x25}, 307 | {0x5185, 0x24}, 308 | {0x5186, 0x09}, 309 | {0x5187, 0x09}, 310 | {0x5188, 0x09}, 311 | {0x5189, 0x75}, 312 | {0x518a, 0x54}, 313 | {0x518b, 0xe0}, 314 | {0x518c, 0xb2}, 315 | {0x518d, 0x42}, 316 | {0x518e, 0x3d}, 317 | {0x518f, 0x56}, 318 | {0x5190, 0x46}, 319 | {0x5191, 0xf8}, 320 | {0x5192, 0x04}, 321 | {0x5193, 0x70}, 322 | {0x5194, 0xf0}, 323 | {0x5195, 0xf0}, 324 | {0x5196, 0x03}, 325 | {0x5197, 0x01}, 326 | {0x5198, 0x04}, 327 | {0x5199, 0x12}, 328 | {0x519a, 0x04}, 329 | {0x519b, 0x00}, 330 | {0x519c, 0x06}, 331 | {0x519d, 0x82}, 332 | {0x519e, 0x38} 333 | }; 334 | 335 | #endif 336 | -------------------------------------------------------------------------------- /sensors/private_include/ov7670.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * author: Juan Schiavoni 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7670 driver. 7 | * 8 | */ 9 | #ifndef __OV7670_H__ 10 | #define __OV7670_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int ov7670_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int ov7670_init(sensor_t *sensor); 32 | 33 | #endif // __OV7670_H__ 34 | -------------------------------------------------------------------------------- /sensors/private_include/ov7725.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenMV project. 3 | * Copyright (c) 2013/2014 Ibrahim Abdelkader 4 | * This work is licensed under the MIT license, see the file LICENSE for details. 5 | * 6 | * OV7725 driver. 7 | * 8 | */ 9 | #ifndef __OV7725_H__ 10 | #define __OV7725_H__ 11 | #include "sensor.h" 12 | 13 | /** 14 | * @brief Detect sensor pid 15 | * 16 | * @param slv_addr SCCB address 17 | * @param id Detection result 18 | * @return 19 | * 0: Can't detect this sensor 20 | * Nonzero: This sensor has been detected 21 | */ 22 | int ov7725_detect(int slv_addr, sensor_id_t *id); 23 | 24 | /** 25 | * @brief initialize sensor function pointers 26 | * 27 | * @param sensor pointer of sensor 28 | * @return 29 | * Always 0 30 | */ 31 | int ov7725_init(sensor_t *sensor); 32 | 33 | #endif // __OV7725_H__ 34 | -------------------------------------------------------------------------------- /sensors/private_include/sc030iot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC030IOT DVP driver. 4 | * 5 | */ 6 | #ifndef __SC030IOT_H__ 7 | #define __SC030IOT_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc030iot_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc030iot_init(sensor_t *sensor); 30 | 31 | #endif // __SC030IOT_H__ 32 | -------------------------------------------------------------------------------- /sensors/private_include/sc031gs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC031GS DVP driver. 4 | * 5 | */ 6 | #ifndef __SC031GS_H__ 7 | #define __SC030GS_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc031gs_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc031gs_init(sensor_t *sensor); 30 | 31 | #endif // __SC031GS_H__ 32 | -------------------------------------------------------------------------------- /sensors/private_include/sc031gs_settings.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022-2023 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 16 | //Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI 17 | //port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P 18 | //I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data 19 | //I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data 20 | //Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR 21 | //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 22 | //pin :BIT0 pwdn// BIT1:reset 23 | //avdd 0:2.8V// 1:2.5V// 2:1.8V 24 | //dovdd 0:2.8V// 1:2.5V// 2:1.8V 25 | //dvdd 0:1.8V// 1:1.5V// 2:1.2V 26 | 27 | /* 28 | [database] 29 | DBName=Dothinkey 30 | 31 | [vendor] 32 | VendorName=SmartSens 33 | 34 | [sensor] 35 | SensorName=SC031GS 36 | width=200 37 | height=200 38 | port=1 39 | type=1 40 | pin=2 41 | SlaveID=0x60 42 | mode=3 43 | FlagReg=0x36FF 44 | FlagMask=0xff 45 | FlagData=0x00 46 | FlagReg1=0x36FF 47 | FlagMask1=0xff 48 | FlagData1=0x00 49 | outformat=3 50 | mclk=10 51 | avdd=2.800000 52 | dovdd=2.800000 53 | dvdd=1.500000 54 | 55 | Ext0=0 56 | Ext1=0 57 | Ext2=0 58 | AFVCC=2.513000 59 | VPP=0.000000 60 | */ 61 | #include 62 | 63 | #define SC031GS_OUTPUT_WINDOW_START_X_H_REG 0x3212 64 | #define SC031GS_OUTPUT_WINDOW_START_X_L_REG 0x3213 65 | #define SC031GS_OUTPUT_WINDOW_START_Y_H_REG 0x3210 66 | #define SC031GS_OUTPUT_WINDOW_START_Y_L_REG 0x3211 67 | #define SC031GS_OUTPUT_WINDOW_WIDTH_H_REG 0x3208 68 | #define SC031GS_OUTPUT_WINDOW_WIDTH_L_REG 0x3209 69 | #define SC031GS_OUTPUT_WINDOW_HIGH_H_REG 0x320a 70 | #define SC031GS_OUTPUT_WINDOW_HIGH_L_REG 0x320b 71 | #define SC031GS_LED_STROBE_ENABLE_REG 0x3361 // When the camera is in exposure, this PAD LEDSTROBE will be high to drive the external LED. 72 | 73 | #define REG_NULL 0xFFFF 74 | #define REG_DELAY 0X0000 75 | 76 | struct sc031gs_regval { 77 | uint16_t addr; 78 | uint8_t val; 79 | }; 80 | 81 | static const struct sc031gs_regval sc031gs_reset_regs[] = { 82 | {0x0103, 0x01}, // soft reset. 83 | {REG_DELAY, 10}, // delay. 84 | }; 85 | 86 | // 200*200, xclk=10M, fps=120fps 87 | static const struct sc031gs_regval sc031gs_200x200_init_regs[] = { 88 | {0x0100, 0x00}, 89 | {0x36e9, 0x80}, 90 | {0x36f9, 0x80}, 91 | {0x300f, 0x0f}, 92 | {0x3018, 0x1f}, 93 | {0x3019, 0xff}, 94 | {0x301c, 0xb4}, 95 | {0x301f, 0x7b}, 96 | {0x3028, 0x82}, 97 | {0x3200, 0x00}, 98 | {0x3201, 0xdc}, 99 | {0x3202, 0x00}, 100 | {0x3203, 0x98}, 101 | {0x3204, 0x01}, 102 | {0x3205, 0xb3}, 103 | {0x3206, 0x01}, 104 | {0x3207, 0x67}, 105 | {SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, 0x00}, 106 | {SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, 0xc8}, 107 | {SC031GS_OUTPUT_WINDOW_HIGH_H_REG, 0x00}, 108 | {SC031GS_OUTPUT_WINDOW_HIGH_L_REG, 0xc8}, 109 | {0x320c, 0x03}, 110 | {0x320d, 0x6b}, 111 | {0x320e, 0x01}, //default 120fps: {0x320e, 0x01},{0x320f, 0x40}, 58fps: {0x320e, 0x02},{0x320f, 0xab}; 30fps: {0x320e, 0x05}, {0x320f, 0x34} 112 | {0x320f, 0x40}, 113 | {SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x00}, 114 | {SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08}, 115 | {SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x00}, 116 | {SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x04}, 117 | {0x3220, 0x10}, 118 | {0x3223, 0x50}, 119 | {0x3250, 0xf0}, 120 | {0x3251, 0x02}, 121 | {0x3252, 0x01}, 122 | {0x3253, 0x3b}, 123 | {0x3254, 0x02}, 124 | {0x3255, 0x07}, 125 | {0x3304, 0x48}, 126 | {0x3306, 0x38}, 127 | {0x3309, 0x50}, 128 | {0x330b, 0xe0}, 129 | {0x330c, 0x18}, 130 | {0x330f, 0x20}, 131 | {0x3310, 0x10}, 132 | {0x3314, 0x70}, 133 | {0x3315, 0x38}, 134 | {0x3316, 0x68}, 135 | {0x3317, 0x0d}, 136 | {0x3329, 0x5c}, 137 | {0x332d, 0x5c}, 138 | {0x332f, 0x60}, 139 | {0x3335, 0x64}, 140 | {0x3344, 0x64}, 141 | {0x335b, 0x80}, 142 | {0x335f, 0x80}, 143 | {0x3366, 0x06}, 144 | {0x3385, 0x41}, 145 | {0x3387, 0x49}, 146 | {0x3389, 0x01}, 147 | {0x33b1, 0x03}, 148 | {0x33b2, 0x06}, 149 | {0x3621, 0xa4}, 150 | {0x3622, 0x05}, 151 | {0x3624, 0x47}, 152 | {0x3631, 0x48}, 153 | {0x3633, 0x52}, 154 | {0x3635, 0x18}, 155 | {0x3636, 0x25}, 156 | {0x3637, 0x89}, 157 | {0x3638, 0x0f}, 158 | {0x3639, 0x08}, 159 | {0x363a, 0x00}, 160 | {0x363b, 0x48}, 161 | {0x363c, 0x06}, 162 | {0x363e, 0xf8}, 163 | {0x3640, 0x00}, 164 | {0x3641, 0x01}, 165 | {0x36ea, 0x39}, 166 | {0x36eb, 0x1e}, 167 | {0x36ec, 0x0e}, 168 | {0x36ed, 0x23}, 169 | {0x36fa, 0x39}, 170 | {0x36fb, 0x10}, 171 | {0x36fc, 0x01}, 172 | {0x36fd, 0x03}, 173 | {0x3908, 0x91}, 174 | {0x3d08, 0x01}, 175 | {0x3d04, 0x04}, 176 | {0x3e01, 0x13}, 177 | {0x3e02, 0xa0}, 178 | {0x3e06, 0x0c}, 179 | {0x3f04, 0x03}, 180 | {0x3f05, 0x4b}, 181 | {0x4500, 0x59}, 182 | {0x4501, 0xc4}, 183 | {0x4809, 0x01}, 184 | {0x4837, 0x39}, 185 | {0x5011, 0x00}, 186 | {0x36e9, 0x04}, 187 | {0x36f9, 0x04}, 188 | {0x0100, 0x01}, 189 | 190 | //delay 10ms 191 | {REG_DELAY, 0X0a}, 192 | {0x4418, 0x08}, 193 | {0x4419, 0x80}, 194 | {0x363d, 0x10}, 195 | {0x3630, 0x48}, 196 | 197 | // [gain<4] 198 | {0x3317, 0x0d}, 199 | {0x3314, 0x70}, 200 | 201 | // [gain>=4] 202 | {0x3314, 0x68}, 203 | {0x3317, 0x0e}, 204 | {REG_NULL, 0x00}, 205 | }; 206 | 207 | // 640*480, xclk=20M, fps=50fps, xclk=10M, fps=25fps 208 | static const struct sc031gs_regval sc031gs_640x480_50fps_init_regs[] = { 209 | {0x0100, 0x00}, 210 | {0x36e9, 0x80}, 211 | {0x36f9, 0x80}, 212 | {0x300f, 0x0f}, 213 | {0x3018, 0x1f}, 214 | {0x3019, 0xff}, 215 | {0x301c, 0xb4}, 216 | {0x301f, 0x6c}, 217 | {0x3028, 0x82}, 218 | {0x3200, 0x00}, 219 | {0x3201, 0x00}, 220 | {0x3202, 0x00}, 221 | {0x3203, 0x08}, 222 | {0x3204, 0x02}, 223 | {0x3205, 0x8f}, 224 | {0x3206, 0x01}, 225 | {0x3207, 0xf7}, 226 | {SC031GS_OUTPUT_WINDOW_WIDTH_H_REG, 0x02}, 227 | {SC031GS_OUTPUT_WINDOW_WIDTH_L_REG, 0x80}, 228 | {SC031GS_OUTPUT_WINDOW_HIGH_H_REG, 0x01}, 229 | {SC031GS_OUTPUT_WINDOW_HIGH_L_REG, 0xe0}, 230 | {0x320c, 0x03}, 231 | {0x320d, 0x6e}, 232 | {0x320e, 0x04}, 233 | {0x320f, 0x72}, 234 | {SC031GS_OUTPUT_WINDOW_START_Y_H_REG, 0x00}, 235 | {SC031GS_OUTPUT_WINDOW_START_Y_L_REG, 0x08}, 236 | {SC031GS_OUTPUT_WINDOW_START_X_H_REG, 0x00}, 237 | {SC031GS_OUTPUT_WINDOW_START_X_L_REG, 0x08}, 238 | {0x3220, 0x10}, 239 | {0x3223, 0x50}, 240 | {0x3250, 0xf0}, 241 | {0x3251, 0x02}, 242 | {0x3252, 0x03}, 243 | {0x3253, 0xb0}, 244 | {0x3254, 0x02}, 245 | {0x3255, 0x07}, 246 | {0x3304, 0x48}, 247 | {0x3306, 0x38}, 248 | {0x3309, 0x68}, 249 | {0x330b, 0xe0}, 250 | {0x330c, 0x18}, 251 | {0x330f, 0x20}, 252 | {0x3310, 0x10}, 253 | {0x3314, 0x6d}, 254 | {0x3315, 0x38}, 255 | {0x3316, 0x68}, 256 | {0x3317, 0x0f}, 257 | {0x3329, 0x5c}, 258 | {0x332d, 0x5c}, 259 | {0x332f, 0x60}, 260 | {0x3335, 0x64}, 261 | {0x3344, 0x64}, 262 | {0x335b, 0x80}, 263 | {0x335f, 0x80}, 264 | {0x3366, 0x06}, 265 | {0x3385, 0x31}, 266 | {0x3387, 0x51}, 267 | {0x3389, 0x01}, 268 | {0x33b1, 0x03}, 269 | {0x33b2, 0x06}, 270 | {0x3621, 0xa4}, 271 | {0x3622, 0x05}, 272 | {0x3624, 0x47}, 273 | {0x3631, 0x48}, 274 | {0x3633, 0x52}, 275 | {0x3635, 0x18}, 276 | {0x3636, 0x25}, 277 | {0x3637, 0x89}, 278 | {0x3638, 0x0f}, 279 | {0x3639, 0x08}, 280 | {0x363a, 0x00}, 281 | {0x363b, 0x48}, 282 | {0x363c, 0x06}, 283 | {0x363e, 0xf8}, 284 | {0x3640, 0x00}, 285 | {0x3641, 0x01}, 286 | {0x36ea, 0x36}, 287 | {0x36eb, 0x1a}, 288 | {0x36ec, 0x0a}, 289 | {0x36ed, 0x23}, 290 | {0x36fa, 0x36}, 291 | {0x36fb, 0x10}, 292 | {0x36fc, 0x01}, 293 | {0x36fd, 0x03}, 294 | {0x3908, 0x91}, 295 | {0x3d08, 0x01}, 296 | {0x3e01, 0x14}, 297 | {0x3e02, 0x80}, 298 | {0x3e06, 0x0c}, 299 | {0x3f04, 0x03}, 300 | {0x3f05, 0x4e}, 301 | {0x4500, 0x59}, 302 | {0x4501, 0xc4}, 303 | {0x4809, 0x01}, 304 | {0x4837, 0x1b}, 305 | {0x5011, 0x00}, 306 | {0x36e9, 0x20}, 307 | {0x36f9, 0x24}, 308 | {0x0100, 0x01}, // must write 0x0100 with 0x01, must delay no less then 7ms 309 | //delay 10ms 310 | {REG_DELAY, 0X0a}, 311 | {0x4418, 0x08}, 312 | {0x4419, 0x80}, 313 | {0x363d, 0x10}, 314 | {0x3630, 0x48}, 315 | {REG_NULL, 0x00}, 316 | }; -------------------------------------------------------------------------------- /sensors/private_include/sc101iot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * SC101IOT DVP driver. 4 | * 5 | */ 6 | #ifndef __SC101IOT_H__ 7 | #define __SC101IOT_H__ 8 | 9 | #include "sensor.h" 10 | 11 | /** 12 | * @brief Detect sensor pid 13 | * 14 | * @param slv_addr SCCB address 15 | * @param id Detection result 16 | * @return 17 | * 0: Can't detect this sensor 18 | * Nonzero: This sensor has been detected 19 | */ 20 | int sc101iot_detect(int slv_addr, sensor_id_t *id); 21 | 22 | /** 23 | * @brief initialize sensor function pointers 24 | * 25 | * @param sensor pointer of sensor 26 | * @return 27 | * Always 0 28 | */ 29 | int sc101iot_init(sensor_t *sensor); 30 | 31 | #endif // __SC101IOT_H__ 32 | -------------------------------------------------------------------------------- /sensors/private_include/sc101iot_settings.h: -------------------------------------------------------------------------------- 1 | //Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16 2 | //Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI 3 | //port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P 4 | //I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data 5 | //I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data 6 | //Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR 7 | //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 8 | //pin :BIT0 pwdn// BIT1:reset 9 | //avdd 0:2.8V// 1:2.5V// 2:1.8V 10 | //dovdd 0:2.8V// 1:2.5V// 2:1.8V 11 | //dvdd 0:1.8V// 1:1.5V// 2:1.2V 12 | /* 13 | [DataBase] 14 | DBName=DemoSens 15 | 16 | [Vendor] 17 | VendorName=SmartSens 18 | I2C_CRC=0 19 | 20 | [Sensor] 21 | SensorName=SC101AP_raw 22 | width=1280 23 | height=720 24 | port=1 25 | type=2 26 | pin=3 27 | SlaveID=0xd0 28 | mode=0 29 | FlagReg=0xf7 30 | FlagMask=0xff 31 | FlagData=0xda 32 | FlagReg1=0xf8 33 | FlagMask1=0xff 34 | FlagData1=0x4a 35 | outformat=0 36 | mclk=20 37 | avdd=2.800000 38 | dovdd=2.800000 39 | dvdd=1.200000 40 | 41 | Ext0=0 42 | Ext1=0 43 | Ext2=0 44 | AFVCC=0.00 45 | VPP=0.000000 46 | */ 47 | #include 48 | 49 | static const uint8_t sc101iot_default_init_regs[][2] = { 50 | #if CONFIG_SC101IOT_720P_15FPS_ENABLED // 720P+YUV422+15FPS sensor default regs 51 | /* Here are some test results: 52 | # size xclk fps pic pclk 53 | # ------- ------- ------ --------- ------- --- --- --- --- --- 54 | # 720p 4 3 err 55 | # 720p 8 5 normal 15 56 | # 720p 10 7.8 normal 19 57 | # 720p 20 15 warning 37.5 58 | # VGA 8 6 normal 59 | # VGA 20 16 normal 60 | 61 | */ 62 | {0xf0, 0x30}, 63 | {0x01, 0xff}, 64 | {0x02, 0xe0}, 65 | {0x30, 0x10}, 66 | {0x3f, 0x81}, 67 | {0xf0, 0x00}, 68 | {0x70, 0x6b}, 69 | {0x72, 0x30}, 70 | {0x84, 0xb4}, 71 | {0x8b, 0x00}, 72 | {0x8c, 0x20}, 73 | {0x8d, 0x02}, 74 | {0x8e, 0xec}, 75 | {0x9e, 0x10}, 76 | {0xb0, 0xc1}, 77 | {0xc8, 0x10}, 78 | {0xc9, 0x10}, 79 | {0xc6, 0x00}, 80 | {0xe0, 0x0f}, 81 | {0xb5, 0xf0}, 82 | {0xde, 0x80}, 83 | {0xb5, 0xf0}, 84 | {0xde, 0x80}, 85 | {0xb2, 0x50}, 86 | {0xb3, 0xfc}, 87 | {0xb4, 0x40}, 88 | {0xb5, 0xc0}, 89 | {0xb6, 0x50}, 90 | {0xb7, 0xfc}, 91 | {0xb8, 0x40}, 92 | {0xb9, 0xc0}, 93 | {0xba, 0xff}, 94 | {0xbb, 0xcc}, 95 | {0xbc, 0xa9}, 96 | {0xbd, 0x7d}, 97 | {0xc1, 0x77}, 98 | {0xf0, 0x01}, 99 | {0x70, 0x02}, 100 | {0x71, 0x02}, 101 | {0x72, 0x50}, 102 | {0x73, 0x02}, 103 | {0x74, 0xd2}, 104 | {0x75, 0x20}, 105 | {0x76, 0x81}, 106 | {0x77, 0x8c}, 107 | {0x78, 0x81}, 108 | {0xf4, 0x01}, 109 | {0xf5, 0x00}, 110 | {0xf6, 0x00}, 111 | {0xf0, 0x36}, 112 | {0x40, 0x03}, 113 | {0x41, 0x01}, 114 | {0xf0, 0x39}, 115 | {0x02, 0x70}, 116 | {0xf0, 0x32}, 117 | {0x41, 0x00}, 118 | {0x43, 0x01}, 119 | {0x48, 0x02}, 120 | {0xf0, 0x45}, 121 | {0x09, 0x20}, 122 | {0xf0, 0x33}, 123 | {0x33, 0x10}, 124 | {0xf0, 0x30}, 125 | {0x38, 0x44}, 126 | {0xf0, 0x39}, 127 | {0x07, 0x00}, 128 | {0x08, 0x19}, 129 | {0x47, 0x00}, 130 | {0x48, 0x00}, 131 | {0xf0, 0x37}, 132 | {0x24, 0x31}, 133 | {0xf0, 0x34}, 134 | {0x9f, 0x02}, 135 | {0xa6, 0x51}, 136 | {0xa7, 0x57}, 137 | {0xe8, 0x5f}, 138 | {0xa8, 0x50}, 139 | {0xa9, 0x50}, 140 | {0xe9, 0x50}, 141 | {0xf0, 0x33}, 142 | {0xb3, 0x58}, 143 | {0xb2, 0x78}, 144 | {0xf0, 0x34}, 145 | {0x9f, 0x03}, 146 | {0xa6, 0x51}, 147 | {0xa7, 0x57}, 148 | {0xaa, 0x01}, 149 | {0xab, 0x28}, 150 | {0xac, 0x01}, 151 | {0xad, 0x38}, 152 | {0xf0, 0x33}, 153 | {0x0a, 0x01}, 154 | {0x0b, 0x28}, 155 | {0xf0, 0x33}, 156 | {0x64, 0x0f}, 157 | {0xec, 0x51}, 158 | {0xed, 0x57}, 159 | {0x06, 0x58}, 160 | {0xe9, 0x58}, 161 | {0xeb, 0x68}, 162 | {0xf0, 0x33}, 163 | {0x64, 0x0f}, 164 | {0xf0, 0x36}, 165 | {0x70, 0xdf}, 166 | {0xb6, 0x40}, 167 | {0xb7, 0x51}, 168 | {0xb8, 0x53}, 169 | {0xb9, 0x57}, 170 | {0xba, 0x5f}, 171 | {0xb0, 0x84}, 172 | {0xb1, 0x82}, 173 | {0xb2, 0x84}, 174 | {0xb3, 0x88}, 175 | {0xb4, 0x90}, 176 | {0xb5, 0x90}, 177 | {0xf0, 0x36}, 178 | {0x7e, 0x50}, 179 | {0x7f, 0x51}, 180 | {0x77, 0x81}, 181 | {0x78, 0x86}, 182 | {0x79, 0x89}, 183 | {0xf0, 0x36}, 184 | {0x70, 0xdf}, 185 | {0x9c, 0x51}, 186 | {0x9d, 0x57}, 187 | {0x90, 0x54}, 188 | {0x91, 0x54}, 189 | {0x92, 0x56}, 190 | {0xf0, 0x36}, 191 | {0xa0, 0x51}, 192 | {0xa1, 0x57}, 193 | {0x96, 0x33}, 194 | {0x97, 0x43}, 195 | {0x98, 0x43}, 196 | {0xf0, 0x36}, 197 | {0x70, 0xdf}, 198 | {0x7c, 0x40}, 199 | {0x7d, 0x53}, 200 | {0x74, 0xd0}, 201 | {0x75, 0xf0}, 202 | {0x76, 0xf0}, 203 | {0xf0, 0x37}, 204 | {0x0f, 0xd5}, 205 | {0x7a, 0x40}, 206 | {0x7b, 0x57}, 207 | {0x71, 0x09}, 208 | {0x72, 0x09}, 209 | {0x73, 0x05}, 210 | {0xf0, 0x33}, 211 | {0x01, 0x44}, 212 | {0xf0, 0x36}, 213 | {0x37, 0xfb}, 214 | {0xf0, 0x36}, 215 | {0x3c, 0x0d}, 216 | {0xf0, 0x33}, 217 | {0x14, 0x95}, 218 | {0xf0, 0x33}, 219 | {0x8f, 0x80}, 220 | {0xf0, 0x37}, 221 | {0x27, 0x14}, 222 | {0x28, 0x03}, 223 | {0xf0, 0x36}, 224 | {0x37, 0xf4}, 225 | {0xf0, 0x33}, 226 | {0x01, 0x44}, 227 | {0xf0, 0x36}, 228 | {0x79, 0x89}, 229 | {0xf0, 0x34}, 230 | {0xac, 0x01}, 231 | {0xad, 0x40}, 232 | {0xf0, 0x33}, 233 | {0xeb, 0x70}, 234 | {0xf0, 0x34}, 235 | {0xa8, 0x50}, 236 | {0xa9, 0x50}, 237 | {0xf0, 0x33}, 238 | {0xb3, 0x58}, 239 | {0xf0, 0x36}, 240 | {0x11, 0x80}, 241 | {0xf0, 0x36}, 242 | {0x41, 0x51}, 243 | {0xf0, 0x3f}, 244 | {0x03, 0x09}, 245 | {0xf0, 0x32}, 246 | {0x0c, 0x06}, 247 | {0x0d, 0x82}, 248 | {0x0e, 0x02}, 249 | {0x0f, 0xee}, 250 | {0xf0, 0x36}, 251 | {0xea, 0x09}, 252 | {0xeb, 0xf5}, 253 | {0xec, 0x11}, 254 | {0xed, 0x27}, 255 | {0xe9, 0x20}, 256 | #endif 257 | }; 258 | -------------------------------------------------------------------------------- /sensors/sc030iot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SC030IOT driver. 3 | * 4 | * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "sccb.h" 24 | #include "xclk.h" 25 | #include "freertos/FreeRTOS.h" 26 | #include "freertos/task.h" 27 | 28 | #include "sc030iot.h" 29 | #include "sc030iot_settings.h" 30 | 31 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 32 | #include "esp32-hal-log.h" 33 | #else 34 | #include "esp_log.h" 35 | static const char* TAG = "sc030"; 36 | #endif 37 | 38 | #define SC030_SENSOR_ID_HIGH_REG 0XF7 39 | #define SC030_SENSOR_ID_LOW_REG 0XF8 40 | #define SC030_MAX_FRAME_WIDTH (640) 41 | #define SC030_MAX_FRAME_HIGH (480) 42 | 43 | // sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. 44 | // For more information please refer to the Technical Reference Manual. 45 | static int get_reg(sensor_t *sensor, int reg, int reg_value_mask) 46 | { 47 | int ret = 0; 48 | uint8_t reg_high = (reg>>8) & 0xFF; 49 | uint8_t reg_low = reg & 0xFF; 50 | 51 | if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { 52 | return -1; 53 | } 54 | 55 | ret = SCCB_Read(sensor->slv_addr, reg_low); 56 | if(ret > 0){ 57 | ret &= reg_value_mask; 58 | } 59 | return ret; 60 | } 61 | 62 | // sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg. 63 | // For more information please refer to the Technical Reference Manual. 64 | static int set_reg(sensor_t *sensor, int reg, int mask, int value) 65 | { 66 | int ret = 0; 67 | uint8_t reg_high = (reg>>8) & 0xFF; 68 | uint8_t reg_low = reg & 0xFF; 69 | 70 | if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) { 71 | return -1; 72 | } 73 | 74 | ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF); 75 | return ret; 76 | } 77 | 78 | static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len) 79 | { 80 | int i=0, res = 0; 81 | while (islv_addr, regs[i][0], regs[i][1]); 83 | if (res) { 84 | return res; 85 | } 86 | i++; 87 | } 88 | return res; 89 | } 90 | 91 | static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value) 92 | { 93 | int ret = 0; 94 | ret = get_reg(sensor, reg, 0xff); 95 | if(ret < 0){ 96 | return ret; 97 | } 98 | uint8_t mask = ((1 << length) - 1) << offset; 99 | value = (ret & ~mask) | ((value << offset) & mask); 100 | ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value); 101 | return ret; 102 | } 103 | 104 | #define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;} 105 | #define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;} 106 | #define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;} 107 | 108 | static int set_hmirror(sensor_t *sensor, int enable) 109 | { 110 | int ret = 0; 111 | if(enable) { 112 | SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on 113 | } else { 114 | SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off 115 | } 116 | 117 | return ret; 118 | } 119 | 120 | static int set_vflip(sensor_t *sensor, int enable) 121 | { 122 | int ret = 0; 123 | if(enable) { 124 | SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on 125 | } else { 126 | SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off 127 | } 128 | 129 | return ret; 130 | } 131 | 132 | static int set_colorbar(sensor_t *sensor, int enable) 133 | { 134 | int ret = 0; 135 | SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable test pattern mode 136 | 137 | return ret; 138 | } 139 | 140 | static int set_sharpness(sensor_t *sensor, int level) 141 | { 142 | int ret = 0; 143 | SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement 144 | WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value 145 | WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit 146 | 147 | return ret; 148 | } 149 | 150 | static int set_agc_gain(sensor_t *sensor, int gain) 151 | { 152 | int ret = 0; 153 | SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control 154 | WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1 155 | WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2 156 | WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3 157 | WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4 158 | 159 | return ret; 160 | } 161 | 162 | static int set_aec_value(sensor_t *sensor, int value) 163 | { 164 | int ret = 0; 165 | SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control 166 | WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target 167 | 168 | return ret; 169 | } 170 | 171 | static int set_awb_gain(sensor_t *sensor, int value) 172 | { 173 | int ret = 0; 174 | SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control 175 | WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain 176 | WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain 177 | return ret; 178 | } 179 | 180 | static int set_saturation(sensor_t *sensor, int level) 181 | { 182 | int ret = 0; 183 | SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control 184 | WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128) 185 | WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128) 186 | return ret; 187 | } 188 | 189 | static int set_contrast(sensor_t *sensor, int level) 190 | { 191 | int ret = 0; 192 | SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control 193 | WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64) 194 | return ret; 195 | } 196 | 197 | static int reset(sensor_t *sensor) 198 | { 199 | int ret = set_regs(sensor, sc030iot_default_init_regs, sizeof(sc030iot_default_init_regs)/(sizeof(uint8_t) * 2)); 200 | 201 | // Delay 202 | vTaskDelay(50 / portTICK_PERIOD_MS); 203 | 204 | // 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 205 | // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff)); 206 | if (ret) { 207 | ESP_LOGE(TAG, "reset fail"); 208 | } 209 | return ret; 210 | } 211 | 212 | static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h) 213 | { 214 | int ret = 0; 215 | //sc:H_start={0x0172[1:0],0x0170},H_end={0x0172[5:4],0x0171}, 216 | WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff); 217 | WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff); 218 | WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x03) | (((offset_x+w)>>4)&0x30)); 219 | 220 | //sc:V_start={0x0175[1:0],0x0173},H_end={0x0175[5:4],0x0174}, 221 | WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff); 222 | WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff); 223 | WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x03) | (((offset_y+h)>>4)&0x30)); 224 | 225 | vTaskDelay(10 / portTICK_PERIOD_MS); 226 | 227 | return ret; 228 | } 229 | 230 | static int set_framesize(sensor_t *sensor, framesize_t framesize) 231 | { 232 | uint16_t w = resolution[framesize].width; 233 | uint16_t h = resolution[framesize].height; 234 | if(w>SC030_MAX_FRAME_WIDTH || h > SC030_MAX_FRAME_HIGH) { 235 | goto err; 236 | } 237 | 238 | uint16_t offset_x = (640-w) /2; 239 | uint16_t offset_y = (480-h) /2; 240 | 241 | if(set_window(sensor, offset_x, offset_y, w, h)) { 242 | goto err; 243 | } 244 | 245 | sensor->status.framesize = framesize; 246 | return 0; 247 | err: 248 | ESP_LOGE(TAG, "frame size err"); 249 | return -1; 250 | } 251 | 252 | static int set_pixformat(sensor_t *sensor, pixformat_t pixformat) 253 | { 254 | int ret=0; 255 | sensor->pixformat = pixformat; 256 | 257 | switch (pixformat) { 258 | case PIXFORMAT_RGB565: 259 | case PIXFORMAT_RAW: 260 | case PIXFORMAT_GRAYSCALE: 261 | ESP_LOGE(TAG, "Not support"); 262 | break; 263 | case PIXFORMAT_YUV422: // For now, sc030/sc031 sensor only support YUV422. 264 | break; 265 | default: 266 | return -1; 267 | } 268 | 269 | return ret; 270 | } 271 | 272 | static int init_status(sensor_t *sensor) 273 | { 274 | return 0; 275 | } 276 | 277 | static int set_dummy(sensor_t *sensor, int val){ return -1; } 278 | 279 | static int set_xclk(sensor_t *sensor, int timer, int xclk) 280 | { 281 | int ret = 0; 282 | sensor->xclk_freq_hz = xclk * 1000000U; 283 | ret = xclk_timer_conf(timer, sensor->xclk_freq_hz); 284 | return ret; 285 | } 286 | 287 | int sc030iot_detect(int slv_addr, sensor_id_t *id) 288 | { 289 | if (SC030IOT_SCCB_ADDR == slv_addr) { 290 | uint8_t MIDL = SCCB_Read(slv_addr, SC030_SENSOR_ID_LOW_REG); 291 | uint8_t MIDH = SCCB_Read(slv_addr, SC030_SENSOR_ID_HIGH_REG); 292 | uint16_t PID = MIDH << 8 | MIDL; 293 | if (SC030IOT_PID == PID) { 294 | id->PID = PID; 295 | return PID; 296 | } else { 297 | ESP_LOGI(TAG, "Mismatch PID=0x%x", PID); 298 | } 299 | } 300 | return 0; 301 | } 302 | 303 | int sc030iot_init(sensor_t *sensor) 304 | { 305 | // Set function pointers 306 | sensor->reset = reset; 307 | sensor->init_status = init_status; 308 | sensor->set_pixformat = set_pixformat; 309 | sensor->set_framesize = set_framesize; 310 | 311 | sensor->set_saturation= set_saturation; 312 | sensor->set_colorbar = set_colorbar; 313 | sensor->set_hmirror = set_hmirror; 314 | sensor->set_vflip = set_vflip; 315 | sensor->set_sharpness = set_sharpness; 316 | sensor->set_agc_gain = set_agc_gain; 317 | sensor->set_aec_value = set_aec_value; 318 | sensor->set_awb_gain = set_awb_gain; 319 | sensor->set_contrast = set_contrast; 320 | //not supported 321 | sensor->set_denoise = set_dummy; 322 | sensor->set_quality = set_dummy; 323 | sensor->set_special_effect = set_dummy; 324 | sensor->set_wb_mode = set_dummy; 325 | sensor->set_ae_level = set_dummy; 326 | 327 | 328 | sensor->get_reg = get_reg; 329 | sensor->set_reg = set_reg; 330 | sensor->set_xclk = set_xclk; 331 | 332 | ESP_LOGD(TAG, "sc030iot Attached"); 333 | 334 | return 0; 335 | } -------------------------------------------------------------------------------- /target/esp32s2/private_include/tjpgd.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 3 | /----------------------------------------------------------------------------*/ 4 | #ifndef _TJPGDEC 5 | #define _TJPGDEC 6 | /*---------------------------------------------------------------------------*/ 7 | /* System Configurations */ 8 | 9 | #define JD_SZBUF 512 /* Size of stream input buffer */ 10 | #define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ 11 | #define JD_USE_SCALE 1 /* Use descaling feature for output */ 12 | #define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ 13 | 14 | /*---------------------------------------------------------------------------*/ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /* These types must be 16-bit, 32-bit or larger integer */ 21 | typedef int INT; 22 | typedef unsigned int UINT; 23 | 24 | /* These types must be 8-bit integer */ 25 | typedef char CHAR; 26 | typedef unsigned char UCHAR; 27 | typedef unsigned char BYTE; 28 | 29 | /* These types must be 16-bit integer */ 30 | typedef short SHORT; 31 | typedef unsigned short USHORT; 32 | typedef unsigned short WORD; 33 | typedef unsigned short WCHAR; 34 | 35 | /* These types must be 32-bit integer */ 36 | typedef long LONG; 37 | typedef unsigned long ULONG; 38 | typedef unsigned long DWORD; 39 | 40 | 41 | /* Error code */ 42 | typedef enum { 43 | JDR_OK = 0, /* 0: Succeeded */ 44 | JDR_INTR, /* 1: Interrupted by output function */ 45 | JDR_INP, /* 2: Device error or wrong termination of input stream */ 46 | JDR_MEM1, /* 3: Insufficient memory pool for the image */ 47 | JDR_MEM2, /* 4: Insufficient stream input buffer */ 48 | JDR_PAR, /* 5: Parameter error */ 49 | JDR_FMT1, /* 6: Data format error (may be damaged data) */ 50 | JDR_FMT2, /* 7: Right format but not supported */ 51 | JDR_FMT3 /* 8: Not supported JPEG standard */ 52 | } JRESULT; 53 | 54 | 55 | 56 | /* Rectangular structure */ 57 | typedef struct { 58 | WORD left, right, top, bottom; 59 | } JRECT; 60 | 61 | 62 | 63 | /* Decompressor object structure */ 64 | typedef struct JDEC JDEC; 65 | struct JDEC { 66 | UINT dctr; /* Number of bytes available in the input buffer */ 67 | BYTE* dptr; /* Current data read ptr */ 68 | BYTE* inbuf; /* Bit stream input buffer */ 69 | BYTE dmsk; /* Current bit in the current read byte */ 70 | BYTE scale; /* Output scaling ratio */ 71 | BYTE msx, msy; /* MCU size in unit of block (width, height) */ 72 | BYTE qtid[3]; /* Quantization table ID of each component */ 73 | SHORT dcv[3]; /* Previous DC element of each component */ 74 | WORD nrst; /* Restart inverval */ 75 | UINT width, height; /* Size of the input image (pixel) */ 76 | BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ 77 | WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ 78 | BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ 79 | LONG* qttbl[4]; /* Dequaitizer tables [id] */ 80 | void* workbuf; /* Working buffer for IDCT and RGB output */ 81 | BYTE* mcubuf; /* Working buffer for the MCU */ 82 | void* pool; /* Pointer to available memory pool */ 83 | UINT sz_pool; /* Size of momory pool (bytes available) */ 84 | UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ 85 | void* device; /* Pointer to I/O device identifiler for the session */ 86 | }; 87 | 88 | 89 | 90 | /* TJpgDec API functions */ 91 | JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); 92 | JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); 93 | 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif /* _TJPGDEC */ 100 | -------------------------------------------------------------------------------- /target/jpeg_include/tjpgd.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------/ 2 | / TJpgDec - Tiny JPEG Decompressor include file (C)ChaN, 2012 3 | /----------------------------------------------------------------------------*/ 4 | #ifndef _TJPGDEC 5 | #define _TJPGDEC 6 | /*---------------------------------------------------------------------------*/ 7 | /* System Configurations */ 8 | 9 | #define JD_SZBUF 512 /* Size of stream input buffer */ 10 | #define JD_FORMAT 0 /* Output pixel format 0:RGB888 (3 BYTE/pix), 1:RGB565 (1 WORD/pix) */ 11 | #define JD_USE_SCALE 1 /* Use descaling feature for output */ 12 | #define JD_TBLCLIP 1 /* Use table for saturation (might be a bit faster but increases 1K bytes of code size) */ 13 | 14 | /*---------------------------------------------------------------------------*/ 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /* These types must be 16-bit, 32-bit or larger integer */ 21 | typedef int INT; 22 | typedef unsigned int UINT; 23 | 24 | /* These types must be 8-bit integer */ 25 | typedef char CHAR; 26 | typedef unsigned char UCHAR; 27 | typedef unsigned char BYTE; 28 | 29 | /* These types must be 16-bit integer */ 30 | typedef short SHORT; 31 | typedef unsigned short USHORT; 32 | typedef unsigned short WORD; 33 | typedef unsigned short WCHAR; 34 | 35 | /* These types must be 32-bit integer */ 36 | typedef long LONG; 37 | typedef unsigned long ULONG; 38 | typedef unsigned long DWORD; 39 | 40 | 41 | /* Error code */ 42 | typedef enum { 43 | JDR_OK = 0, /* 0: Succeeded */ 44 | JDR_INTR, /* 1: Interrupted by output function */ 45 | JDR_INP, /* 2: Device error or wrong termination of input stream */ 46 | JDR_MEM1, /* 3: Insufficient memory pool for the image */ 47 | JDR_MEM2, /* 4: Insufficient stream input buffer */ 48 | JDR_PAR, /* 5: Parameter error */ 49 | JDR_FMT1, /* 6: Data format error (may be damaged data) */ 50 | JDR_FMT2, /* 7: Right format but not supported */ 51 | JDR_FMT3 /* 8: Not supported JPEG standard */ 52 | } JRESULT; 53 | 54 | 55 | 56 | /* Rectangular structure */ 57 | typedef struct { 58 | WORD left, right, top, bottom; 59 | } JRECT; 60 | 61 | 62 | 63 | /* Decompressor object structure */ 64 | typedef struct JDEC JDEC; 65 | struct JDEC { 66 | UINT dctr; /* Number of bytes available in the input buffer */ 67 | BYTE* dptr; /* Current data read ptr */ 68 | BYTE* inbuf; /* Bit stream input buffer */ 69 | BYTE dmsk; /* Current bit in the current read byte */ 70 | BYTE scale; /* Output scaling ratio */ 71 | BYTE msx, msy; /* MCU size in unit of block (width, height) */ 72 | BYTE qtid[3]; /* Quantization table ID of each component */ 73 | SHORT dcv[3]; /* Previous DC element of each component */ 74 | WORD nrst; /* Restart inverval */ 75 | UINT width, height; /* Size of the input image (pixel) */ 76 | BYTE* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ 77 | WORD* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ 78 | BYTE* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ 79 | LONG* qttbl[4]; /* Dequaitizer tables [id] */ 80 | void* workbuf; /* Working buffer for IDCT and RGB output */ 81 | BYTE* mcubuf; /* Working buffer for the MCU */ 82 | void* pool; /* Pointer to available memory pool */ 83 | UINT sz_pool; /* Size of momory pool (bytes available) */ 84 | UINT (*infunc)(JDEC*, BYTE*, UINT);/* Pointer to jpeg stream input function */ 85 | void* device; /* Pointer to I/O device identifiler for the session */ 86 | }; 87 | 88 | 89 | 90 | /* TJpgDec API functions */ 91 | JRESULT jd_prepare (JDEC*, UINT(*)(JDEC*,BYTE*,UINT), void*, UINT, void*); 92 | JRESULT jd_decomp (JDEC*, UINT(*)(JDEC*,void*,JRECT*), BYTE); 93 | 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif /* _TJPGDEC */ 100 | -------------------------------------------------------------------------------- /target/private_include/ll_cam.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "sdkconfig.h" 19 | #include "esp_idf_version.h" 20 | #if CONFIG_IDF_TARGET_ESP32 21 | #if ESP_IDF_VERSION_MAJOR >= 4 22 | #include "esp32/rom/lldesc.h" 23 | #else 24 | #include "rom/lldesc.h" 25 | #endif 26 | #elif CONFIG_IDF_TARGET_ESP32S2 27 | #include "esp32s2/rom/lldesc.h" 28 | #elif CONFIG_IDF_TARGET_ESP32S3 29 | #include "esp32s3/rom/lldesc.h" 30 | #endif 31 | #include "esp_log.h" 32 | #include "esp_camera.h" 33 | #include "freertos/FreeRTOS.h" 34 | #include "freertos/queue.h" 35 | #include "freertos/task.h" 36 | #include "freertos/semphr.h" 37 | 38 | #if __has_include("esp_private/periph_ctrl.h") 39 | # include "esp_private/periph_ctrl.h" 40 | #endif 41 | #if __has_include("esp_private/gdma.h") 42 | # include "esp_private/gdma.h" 43 | #endif 44 | 45 | #if CONFIG_LCD_CAM_ISR_IRAM_SAFE 46 | #define CAMERA_ISR_IRAM_FLAG ESP_INTR_FLAG_IRAM 47 | #define CAMERA_ISR_IRAM_ATTR IRAM_ATTR 48 | #else 49 | #define CAMERA_ISR_IRAM_FLAG 0 50 | #define CAMERA_ISR_IRAM_ATTR 51 | #endif 52 | 53 | #define CAMERA_DBG_PIN_ENABLE 0 54 | #if CAMERA_DBG_PIN_ENABLE 55 | #if CONFIG_IDF_TARGET_ESP32 56 | #define DBG_PIN_NUM 26 57 | #else 58 | #define DBG_PIN_NUM 7 59 | #endif 60 | #include "hal/gpio_ll.h" 61 | #define DBG_PIN_SET(v) gpio_ll_set_level(&GPIO, DBG_PIN_NUM, v) 62 | #else 63 | #define DBG_PIN_SET(v) 64 | #endif 65 | 66 | #define CAM_CHECK(a, str, ret) if (!(a)) { \ 67 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 68 | return (ret); \ 69 | } 70 | 71 | #define CAM_CHECK_GOTO(a, str, lab) if (!(a)) { \ 72 | ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ 73 | goto lab; \ 74 | } 75 | 76 | #define LCD_CAM_DMA_NODE_BUFFER_MAX_SIZE (4092) 77 | 78 | typedef enum { 79 | CAM_IN_SUC_EOF_EVENT = 0, 80 | CAM_VSYNC_EVENT 81 | } cam_event_t; 82 | 83 | typedef enum { 84 | CAM_STATE_IDLE = 0, 85 | CAM_STATE_READ_BUF = 1, 86 | } cam_state_t; 87 | 88 | typedef struct { 89 | camera_fb_t fb; 90 | uint8_t en; 91 | //for RGB/YUV modes 92 | lldesc_t *dma; 93 | size_t fb_offset; 94 | } cam_frame_t; 95 | 96 | typedef struct { 97 | uint32_t dma_bytes_per_item; 98 | uint32_t dma_buffer_size; 99 | uint32_t dma_half_buffer_size; 100 | uint32_t dma_half_buffer_cnt; 101 | uint32_t dma_node_buffer_size; 102 | uint32_t dma_node_cnt; 103 | uint32_t frame_copy_cnt; 104 | 105 | //for JPEG mode 106 | lldesc_t *dma; 107 | uint8_t *dma_buffer; 108 | 109 | cam_frame_t *frames; 110 | 111 | QueueHandle_t event_queue; 112 | QueueHandle_t frame_buffer_queue; 113 | TaskHandle_t task_handle; 114 | intr_handle_t cam_intr_handle; 115 | 116 | uint8_t dma_num;//ESP32-S3 117 | intr_handle_t dma_intr_handle;//ESP32-S3 118 | #if SOC_GDMA_SUPPORTED 119 | gdma_channel_handle_t dma_channel_handle;//ESP32-S3 120 | #endif 121 | 122 | uint8_t jpeg_mode; 123 | uint8_t vsync_pin; 124 | uint8_t vsync_invert; 125 | uint32_t frame_cnt; 126 | uint32_t recv_size; 127 | bool swap_data; 128 | bool psram_mode; 129 | 130 | //for RGB/YUV modes 131 | uint16_t width; 132 | uint16_t height; 133 | #if CONFIG_CAMERA_CONVERTER_ENABLED 134 | float in_bytes_per_pixel; 135 | float fb_bytes_per_pixel; 136 | camera_conv_mode_t conv_mode; 137 | #else 138 | uint8_t in_bytes_per_pixel; 139 | uint8_t fb_bytes_per_pixel; 140 | #endif 141 | uint32_t fb_size; 142 | 143 | cam_state_t state; 144 | } cam_obj_t; 145 | 146 | 147 | bool ll_cam_stop(cam_obj_t *cam); 148 | bool ll_cam_start(cam_obj_t *cam, int frame_pos); 149 | esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config); 150 | esp_err_t ll_cam_deinit(cam_obj_t *cam); 151 | void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en); 152 | esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config); 153 | esp_err_t ll_cam_init_isr(cam_obj_t *cam); 154 | void ll_cam_do_vsync(cam_obj_t *cam); 155 | uint8_t ll_cam_get_dma_align(cam_obj_t *cam); 156 | bool ll_cam_dma_sizes(cam_obj_t *cam); 157 | size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len); 158 | esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid); 159 | #if CONFIG_IDF_TARGET_ESP32S3 160 | void ll_cam_dma_print_state(cam_obj_t *cam); 161 | void ll_cam_dma_reset(cam_obj_t *cam); 162 | #endif 163 | 164 | // implemented in cam_hal 165 | void ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType_t * HPTaskAwoken); 166 | -------------------------------------------------------------------------------- /target/xclk.c: -------------------------------------------------------------------------------- 1 | #include "driver/gpio.h" 2 | #include "driver/ledc.h" 3 | #include "esp_err.h" 4 | #include "esp_log.h" 5 | #include "esp_system.h" 6 | #include "xclk.h" 7 | #include "esp_camera.h" 8 | 9 | #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG) 10 | #include "esp32-hal-log.h" 11 | #else 12 | #include "esp_log.h" 13 | static const char* TAG = "camera_xclk"; 14 | #endif 15 | 16 | #define NO_CAMERA_LEDC_CHANNEL 0xFF 17 | static ledc_channel_t g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; 18 | 19 | esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz) 20 | { 21 | ledc_timer_config_t timer_conf; 22 | timer_conf.duty_resolution = LEDC_TIMER_1_BIT; 23 | timer_conf.freq_hz = xclk_freq_hz; 24 | timer_conf.speed_mode = LEDC_LOW_SPEED_MODE; 25 | 26 | #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) 27 | timer_conf.deconfigure = false; 28 | #endif 29 | 30 | #if ESP_IDF_VERSION_MAJOR >= 4 31 | timer_conf.clk_cfg = LEDC_AUTO_CLK; 32 | #endif 33 | timer_conf.timer_num = (ledc_timer_t)ledc_timer; 34 | esp_err_t err = ledc_timer_config(&timer_conf); 35 | if (err != ESP_OK) { 36 | ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err); 37 | } 38 | return err; 39 | } 40 | 41 | esp_err_t camera_enable_out_clock(const camera_config_t* config) 42 | { 43 | esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz); 44 | if (err != ESP_OK) { 45 | ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err); 46 | return err; 47 | } 48 | 49 | g_ledc_channel = config->ledc_channel; 50 | ledc_channel_config_t ch_conf = {0}; 51 | ch_conf.gpio_num = config->pin_xclk; 52 | ch_conf.speed_mode = LEDC_LOW_SPEED_MODE; 53 | ch_conf.channel = config->ledc_channel; 54 | ch_conf.intr_type = LEDC_INTR_DISABLE; 55 | ch_conf.timer_sel = config->ledc_timer; 56 | ch_conf.duty = 1; 57 | ch_conf.hpoint = 0; 58 | err = ledc_channel_config(&ch_conf); 59 | if (err != ESP_OK) { 60 | ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err); 61 | return err; 62 | } 63 | return ESP_OK; 64 | } 65 | 66 | void camera_disable_out_clock() 67 | { 68 | if (g_ledc_channel != NO_CAMERA_LEDC_CHANNEL) { 69 | ledc_stop(LEDC_LOW_SPEED_MODE, g_ledc_channel, 0); 70 | g_ledc_channel = NO_CAMERA_LEDC_CHANNEL; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRC_DIRS . 2 | PRIV_INCLUDE_DIRS . 3 | PRIV_REQUIRES test_utils esp32-camera nvs_flash 4 | EMBED_TXTFILES pictures/testimg.jpeg pictures/test_outside.jpeg pictures/test_inside.jpeg) 5 | -------------------------------------------------------------------------------- /test/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | #Component Makefile 3 | # 4 | 5 | COMPONENT_SRCDIRS += ./ 6 | COMPONENT_PRIV_INCLUDEDIRS += ./ 7 | 8 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive 9 | -------------------------------------------------------------------------------- /test/pictures/test_inside.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-camera/4467667b71f22a4c7db226f24105a9350abe7a05/test/pictures/test_inside.jpeg -------------------------------------------------------------------------------- /test/pictures/test_outside.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-camera/4467667b71f22a4c7db226f24105a9350abe7a05/test/pictures/test_outside.jpeg -------------------------------------------------------------------------------- /test/pictures/testimg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp32-camera/4467667b71f22a4c7db226f24105a9350abe7a05/test/pictures/testimg.jpeg --------------------------------------------------------------------------------