0e8ae456e6e18f9b7ba9150a21c7397538ff2f6d
Board-new-dat/ESP32-S3-cam-dat/ESP32-S3-cam-code-dat/adafruit_ov2640.py
| ... | ... | @@ -0,0 +1,1364 @@ |
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | +# |
|
| 4 | +# SPDX-License-Identifier: MIT |
|
| 5 | +""" |
|
| 6 | +`adafruit_ov2640` |
|
| 7 | +================================================================================ |
|
| 8 | + |
|
| 9 | +CircuitPython driver for OV2640 Camera. |
|
| 10 | + |
|
| 11 | + |
|
| 12 | +* Author(s): Jeff Epler |
|
| 13 | + |
|
| 14 | +Implementation Notes |
|
| 15 | +-------------------- |
|
| 16 | + |
|
| 17 | +**Hardware:** |
|
| 18 | + |
|
| 19 | +* `ESP32-S2 Kaluga Dev Kit featuring ESP32-S2 WROVER <https://www.adafruit.com/product/4729>`_ |
|
| 20 | + |
|
| 21 | +**Software and Dependencies:** |
|
| 22 | + |
|
| 23 | +* Adafruit CircuitPython firmware for the supported boards: |
|
| 24 | + https://github.com/adafruit/circuitpython/releases |
|
| 25 | + |
|
| 26 | +* Adafruit's Bus Device library: https:# github.com/adafruit/Adafruit_CircuitPython_BusDevice |
|
| 27 | +""" |
|
| 28 | + |
|
| 29 | +# imports |
|
| 30 | + |
|
| 31 | +__version__ = "0.0.0+auto.0" |
|
| 32 | +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_OV7670.git" |
|
| 33 | + |
|
| 34 | +import time |
|
| 35 | + |
|
| 36 | +import digitalio |
|
| 37 | +import imagecapture |
|
| 38 | +import pwmio |
|
| 39 | +from adafruit_bus_device.i2c_device import I2CDevice |
|
| 40 | +from micropython import const |
|
| 41 | + |
|
| 42 | +try: |
|
| 43 | + from typing import List, Optional, Type, Union |
|
| 44 | + |
|
| 45 | + from busio import I2C |
|
| 46 | + from circuitpython_typing import WriteableBuffer |
|
| 47 | + from microcontroller import Pin |
|
| 48 | +except ImportError: |
|
| 49 | + pass |
|
| 50 | + |
|
| 51 | +CTRLI = const(0x50) |
|
| 52 | +_R_BYPASS = const(0x05) |
|
| 53 | +_QS = const(0x44) |
|
| 54 | +_CTRLI = const(0x50) |
|
| 55 | +_HSIZE = const(0x51) |
|
| 56 | +_VSIZE = const(0x52) |
|
| 57 | +_XOFFL = const(0x53) |
|
| 58 | +_YOFFL = const(0x54) |
|
| 59 | +_VHYX = const(0x55) |
|
| 60 | +_DPRP = const(0x56) |
|
| 61 | +_TEST = const(0x57) |
|
| 62 | +_ZMOW = const(0x5A) |
|
| 63 | +_ZMOH = const(0x5B) |
|
| 64 | +_ZMHH = const(0x5C) |
|
| 65 | +_BPADDR = const(0x7C) |
|
| 66 | +_BPDATA = const(0x7D) |
|
| 67 | +_CTRL2 = const(0x86) |
|
| 68 | +_CTRL3 = const(0x87) |
|
| 69 | +_SIZEL = const(0x8C) |
|
| 70 | +_HSIZE8 = const(0xC0) |
|
| 71 | +_VSIZE8 = const(0xC1) |
|
| 72 | +_CTRL0 = const(0xC2) |
|
| 73 | +_CTRL1 = const(0xC3) |
|
| 74 | +_R_DVP_SP = const(0xD3) |
|
| 75 | +_IMAGE_MODE = const(0xDA) |
|
| 76 | +_RESET = const(0xE0) |
|
| 77 | +_MS_SP = const(0xF0) |
|
| 78 | +_SS_ID = const(0xF7) |
|
| 79 | +_SS_CTRL = const(0xF7) |
|
| 80 | +_MC_BIST = const(0xF9) |
|
| 81 | +_MC_AL = const(0xFA) |
|
| 82 | +_MC_AH = const(0xFB) |
|
| 83 | +_MC_D = const(0xFC) |
|
| 84 | +_P_CMD = const(0xFD) |
|
| 85 | +_P_STATUS = const(0xFE) |
|
| 86 | +_BANK_SEL = const(0xFF) |
|
| 87 | + |
|
| 88 | +_CTRLI_LP_DP = const(0x80) |
|
| 89 | +_CTRLI_ROUND = const(0x40) |
|
| 90 | + |
|
| 91 | +_CTRL0_AEC_EN = const(0x80) |
|
| 92 | +_CTRL0_AEC_SEL = const(0x40) |
|
| 93 | +_CTRL0_STAT_SEL = const(0x20) |
|
| 94 | +_CTRL0_VFIRST = const(0x10) |
|
| 95 | +_CTRL0_YUV422 = const(0x08) |
|
| 96 | +_CTRL0_YUV_EN = const(0x04) |
|
| 97 | +_CTRL0_RGB_EN = const(0x02) |
|
| 98 | +_CTRL0_RAW_EN = const(0x01) |
|
| 99 | + |
|
| 100 | +_CTRL2_DCW_EN = const(0x20) |
|
| 101 | +_CTRL2_SDE_EN = const(0x10) |
|
| 102 | +_CTRL2_UV_ADJ_EN = const(0x08) |
|
| 103 | +_CTRL2_UV_AVG_EN = const(0x04) |
|
| 104 | +_CTRL2_CMX_EN = const(0x01) |
|
| 105 | + |
|
| 106 | +_CTRL3_BPC_EN = const(0x80) |
|
| 107 | +_CTRL3_WPC_EN = const(0x40) |
|
| 108 | + |
|
| 109 | +_R_DVP_SP_AUTO_MODE = const(0x80) |
|
| 110 | + |
|
| 111 | +_R_BYPASS_DSP_EN = const(0x00) |
|
| 112 | +_R_BYPASS_DSP_BYPAS = const(0x01) |
|
| 113 | + |
|
| 114 | +OV2640_COLOR_RGB = 0 |
|
| 115 | +OV2640_COLOR_YUV = 1 |
|
| 116 | +OV2640_COLOR_JPEG = 2 |
|
| 117 | + |
|
| 118 | +_IMAGE_MODE_Y8_DVP_EN = const(0x40) |
|
| 119 | +_IMAGE_MODE_JPEG_EN = const(0x10) |
|
| 120 | +_IMAGE_MODE_YUV422 = const(0x00) |
|
| 121 | +_IMAGE_MODE_RAW10 = const(0x04) |
|
| 122 | +_IMAGE_MODE_RGB565 = const(0x08) |
|
| 123 | +_IMAGE_MODE_HREF_VSYNC = const(0x02) |
|
| 124 | +_IMAGE_MODE_LBYTE_FIRST = const(0x01) |
|
| 125 | + |
|
| 126 | +_RESET_MICROC = const(0x40) |
|
| 127 | +_RESET_SCCB = const(0x20) |
|
| 128 | +_RESET_JPEG = const(0x10) |
|
| 129 | +_RESET_DVP = const(0x04) |
|
| 130 | +_RESET_IPU = const(0x02) |
|
| 131 | +_RESET_CIF = const(0x01) |
|
| 132 | + |
|
| 133 | +_MC_BIST_RESET = const(0x80) |
|
| 134 | +_MC_BIST_BOOT_ROM_SEL = const(0x40) |
|
| 135 | +_MC_BIST_12KB_SEL = const(0x20) |
|
| 136 | +_MC_BIST_12KB_MASK = const(0x30) |
|
| 137 | +_MC_BIST_512KB_SEL = const(0x08) |
|
| 138 | +_MC_BIST_512KB_MASK = const(0x0C) |
|
| 139 | +_MC_BIST_BUSY_BIT_R = const(0x02) |
|
| 140 | +_MC_BIST_MC_RES_ONE_SH_W = const(0x02) |
|
| 141 | +_MC_BIST_LAUNCH = const(0x01) |
|
| 142 | + |
|
| 143 | + |
|
| 144 | +_BANK_DSP = const(0) |
|
| 145 | +_BANK_SENSOR = const(1) |
|
| 146 | + |
|
| 147 | +# Sensor register bank FF=0x01 |
|
| 148 | +_GAIN = const(0x00) |
|
| 149 | +_COM1 = const(0x03) |
|
| 150 | +_REG04 = const(0x04) |
|
| 151 | +_REG08 = const(0x08) |
|
| 152 | +_COM2 = const(0x09) |
|
| 153 | +_REG_PID = const(0x0A) |
|
| 154 | +_REG_VER = const(0x0B) |
|
| 155 | +_COM3 = const(0x0C) |
|
| 156 | +_COM4 = const(0x0D) |
|
| 157 | +_AEC = const(0x10) |
|
| 158 | +_CLKRC = const(0x11) |
|
| 159 | +_COM7 = const(0x12) |
|
| 160 | +_COM8 = const(0x13) |
|
| 161 | +_COM9 = const(0x14) # AGC gain ceiling |
|
| 162 | +_COM10 = const(0x15) |
|
| 163 | +_HSTART = const(0x17) |
|
| 164 | +_HSTOP = const(0x18) |
|
| 165 | +_VSTART = const(0x19) |
|
| 166 | +_VSTOP = const(0x1A) |
|
| 167 | +_MIDH = const(0x1C) |
|
| 168 | +_MIDL = const(0x1D) |
|
| 169 | +_AEW = const(0x24) |
|
| 170 | +_AEB = const(0x25) |
|
| 171 | +_VV = const(0x26) |
|
| 172 | +_REG2A = const(0x2A) |
|
| 173 | +_FRARL = const(0x2B) |
|
| 174 | +_ADDVSL = const(0x2D) |
|
| 175 | +_ADDVSH = const(0x2E) |
|
| 176 | +_YAVG = const(0x2F) |
|
| 177 | +_HSDY = const(0x30) |
|
| 178 | +_HEDY = const(0x31) |
|
| 179 | +_REG32 = const(0x32) |
|
| 180 | +_ARCOM2 = const(0x34) |
|
| 181 | +_REG45 = const(0x45) |
|
| 182 | +_FLL = const(0x46) |
|
| 183 | +_FLH = const(0x47) |
|
| 184 | +_COM19 = const(0x48) |
|
| 185 | +_ZOOMS = const(0x49) |
|
| 186 | +_COM22 = const(0x4B) |
|
| 187 | +_COM25 = const(0x4E) |
|
| 188 | +_BD50 = const(0x4F) |
|
| 189 | +_BD60 = const(0x50) |
|
| 190 | +_REG5D = const(0x5D) |
|
| 191 | +_REG5E = const(0x5E) |
|
| 192 | +_REG5F = const(0x5F) |
|
| 193 | +_REG60 = const(0x60) |
|
| 194 | +_HISTO_LOW = const(0x61) |
|
| 195 | +_HISTO_HIGH = const(0x62) |
|
| 196 | + |
|
| 197 | +_REG04_DEFAULT = const(0x28) |
|
| 198 | +_REG04_HFLIP_IMG = const(0x80) |
|
| 199 | +_REG04_VFLIP_IMG = const(0x40) |
|
| 200 | +_REG04_VREF_EN = const(0x10) |
|
| 201 | +_REG04_HREF_EN = const(0x08) |
|
| 202 | +_REG04_SET = lambda x: (_REG04_DEFAULT | x) |
|
| 203 | + |
|
| 204 | +_COM2_STDBY = const(0x10) |
|
| 205 | +_COM2_OUT_DRIVE_1x = const(0x00) |
|
| 206 | +_COM2_OUT_DRIVE_2x = const(0x01) |
|
| 207 | +_COM2_OUT_DRIVE_3x = const(0x02) |
|
| 208 | +_COM2_OUT_DRIVE_4x = const(0x03) |
|
| 209 | + |
|
| 210 | +_COM3_DEFAULT = const(0x38) |
|
| 211 | +_COM3_BAND_50Hz = const(0x04) |
|
| 212 | +_COM3_BAND_60Hz = const(0x00) |
|
| 213 | +_COM3_BAND_AUTO = const(0x02) |
|
| 214 | +_COM3_BAND_SET = lambda x: (_COM3_DEFAULT | x) |
|
| 215 | + |
|
| 216 | +_COM7_SRST = const(0x80) |
|
| 217 | +_COM7_RES_UXGA = const(0x00) # UXGA |
|
| 218 | +_COM7_RES_SVGA = const(0x40) # SVGA |
|
| 219 | +_COM7_RES_CIF = const(0x20) # CIF |
|
| 220 | +_COM7_ZOOM_EN = const(0x04) # Enable Zoom |
|
| 221 | +_COM7_COLOR_BAR = const(0x02) # Enable Color Bar Test |
|
| 222 | + |
|
| 223 | +_COM8_DEFAULT = const(0xC0) |
|
| 224 | +_COM8_BNDF_EN = const(0x20) # Enable Banding filter |
|
| 225 | +_COM8_AGC_EN = const(0x04) # AGC Auto/Manual control selection |
|
| 226 | +_COM8_AEC_EN = const(0x01) # Auto/Manual Exposure control |
|
| 227 | +_COM8_SET = lambda x: (_COM8_DEFAULT | x) |
|
| 228 | + |
|
| 229 | +_COM9_DEFAULT = const(0x08) |
|
| 230 | +_COM9_AGC_GAIN_2x = const(0x00) # AGC: 2x |
|
| 231 | +_COM9_AGC_GAIN_4x = const(0x01) # AGC: 4x |
|
| 232 | +_COM9_AGC_GAIN_8x = const(0x02) # AGC: 8x |
|
| 233 | +_COM9_AGC_GAIN_16x = const(0x03) # AGC: 16x |
|
| 234 | +_COM9_AGC_GAIN_32x = const(0x04) # AGC: 32x |
|
| 235 | +_COM9_AGC_GAIN_64x = const(0x05) # AGC: 64x |
|
| 236 | +_COM9_AGC_GAIN_128x = const(0x06) # AGC: 128x |
|
| 237 | +_COM9_AGC_SET = lambda x: (_COM9_DEFAULT | (x << 5)) |
|
| 238 | + |
|
| 239 | +_COM10_HREF_EN = const(0x80) # HSYNC changes to HREF |
|
| 240 | +_COM10_HSYNC_EN = const(0x40) # HREF changes to HSYNC |
|
| 241 | +_COM10_PCLK_FREE = const(0x20) # PCLK output option: free running PCLK |
|
| 242 | +_COM10_PCLK_EDGE = const(0x10) # Data is updated at the rising edge of PCLK |
|
| 243 | +_COM10_HREF_NEG = const(0x08) # HREF negative |
|
| 244 | +_COM10_VSYNC_NEG = const(0x02) # VSYNC negative |
|
| 245 | +_COM10_HSYNC_NEG = const(0x01) # HSYNC negative |
|
| 246 | + |
|
| 247 | +_CTRL1_AWB = const(0x08) # Enable AWB |
|
| 248 | + |
|
| 249 | +_VV_AGC_TH_SET = lambda h, l: ((h << 4) | (l & 0x0F)) |
|
| 250 | + |
|
| 251 | +_REG32_UXGA = const(0x36) |
|
| 252 | +_REG32_SVGA = const(0x09) |
|
| 253 | +_REG32_CIF = const(0x89) |
|
| 254 | + |
|
| 255 | +_CLKRC_2X = const(0x80) |
|
| 256 | +_CLKRC_2X_UXGA = const(0x01 | _CLKRC_2X) |
|
| 257 | +_CLKRC_2X_SVGA = _CLKRC_2X |
|
| 258 | +_CLKRC_2X_CIF = _CLKRC_2X |
|
| 259 | + |
|
| 260 | +_OV2640_MODE_CIF = const(0) |
|
| 261 | +_OV2640_MODE_SVGA = const(1) |
|
| 262 | +_OV2640_MODE_UXGA = const(2) |
|
| 263 | + |
|
| 264 | +OV2640_SIZE_96X96 = 0 # 96x96 |
|
| 265 | +OV2640_SIZE_QQVGA = 1 # 160x120 |
|
| 266 | +OV2640_SIZE_QCIF = 2 # 176x144 |
|
| 267 | +OV2640_SIZE_HQVGA = 3 # 240x176 |
|
| 268 | +OV2640_SIZE_240X240 = 4 # 240x240 |
|
| 269 | +OV2640_SIZE_QVGA = 5 # 320x240 |
|
| 270 | +OV2640_SIZE_CIF = 6 # 400x296 |
|
| 271 | +OV2640_SIZE_HVGA = 7 # 480x320 |
|
| 272 | +OV2640_SIZE_VGA = 8 # 640x480 |
|
| 273 | +OV2640_SIZE_SVGA = 9 # 800x600 |
|
| 274 | +OV2640_SIZE_XGA = 10 # 1024x768 |
|
| 275 | +OV2640_SIZE_HD = 11 # 1280x720 |
|
| 276 | +OV2640_SIZE_SXGA = 12 # 1280x1024 |
|
| 277 | +OV2640_SIZE_UXGA = 13 # 1600x1200 |
|
| 278 | + |
|
| 279 | +_ASPECT_RATIO_4X3 = const(0) |
|
| 280 | +_ASPECT_RATIO_3X2 = const(1) |
|
| 281 | +_ASPECT_RATIO_16X10 = const(2) |
|
| 282 | +_ASPECT_RATIO_5X3 = const(3) |
|
| 283 | +_ASPECT_RATIO_16X9 = const(4) |
|
| 284 | +_ASPECT_RATIO_21X9 = const(5) |
|
| 285 | +_ASPECT_RATIO_5X4 = const(6) |
|
| 286 | +_ASPECT_RATIO_1X1 = const(7) |
|
| 287 | +_ASPECT_RATIO_9X16 = const(8) |
|
| 288 | + |
|
| 289 | +_resolution_info = [ |
|
| 290 | + [96, 96, _ASPECT_RATIO_1X1], # 96x96 |
|
| 291 | + [160, 120, _ASPECT_RATIO_4X3], # QQVGA |
|
| 292 | + [176, 144, _ASPECT_RATIO_5X4], # QCIF |
|
| 293 | + [240, 176, _ASPECT_RATIO_4X3], # HQVGA |
|
| 294 | + [240, 240, _ASPECT_RATIO_1X1], # 240x240 |
|
| 295 | + [320, 240, _ASPECT_RATIO_4X3], # QVGA |
|
| 296 | + [400, 296, _ASPECT_RATIO_4X3], # CIF |
|
| 297 | + [480, 320, _ASPECT_RATIO_3X2], # HVGA |
|
| 298 | + [640, 480, _ASPECT_RATIO_4X3], # VGA |
|
| 299 | + [800, 600, _ASPECT_RATIO_4X3], # SVGA |
|
| 300 | + [1024, 768, _ASPECT_RATIO_4X3], # XGA |
|
| 301 | + [1280, 720, _ASPECT_RATIO_16X9], # HD |
|
| 302 | + [1280, 1024, _ASPECT_RATIO_5X4], # SXGA |
|
| 303 | + [1600, 1200, _ASPECT_RATIO_4X3], # UXGA |
|
| 304 | +] |
|
| 305 | + |
|
| 306 | +_ratio_table = [ |
|
| 307 | + # ox, oy, mx, my |
|
| 308 | + [0, 0, 1600, 1200], # 4x3 |
|
| 309 | + [8, 72, 1584, 1056], # 3x2 |
|
| 310 | + [0, 100, 1600, 1000], # 16x10 |
|
| 311 | + [0, 120, 1600, 960], # 5x3 |
|
| 312 | + [0, 150, 1600, 900], # 16x9 |
|
| 313 | + [2, 258, 1596, 684], # 21x9 |
|
| 314 | + [50, 0, 1500, 1200], # 5x4 |
|
| 315 | + [200, 0, 1200, 1200], # 1x1 |
|
| 316 | + [462, 0, 676, 1200], # 9x16 |
|
| 317 | +] |
|
| 318 | + |
|
| 319 | +# 30fps@24MHz |
|
| 320 | +_ov2640_settings_cif = bytes( |
|
| 321 | + [ |
|
| 322 | + _BANK_SEL, |
|
| 323 | + _BANK_DSP, |
|
| 324 | + 0x2C, |
|
| 325 | + 0xFF, |
|
| 326 | + 0x2E, |
|
| 327 | + 0xDF, |
|
| 328 | + _BANK_SEL, |
|
| 329 | + _BANK_SENSOR, |
|
| 330 | + 0x3C, |
|
| 331 | + 0x32, |
|
| 332 | + _CLKRC, |
|
| 333 | + 0x01, |
|
| 334 | + _COM2, |
|
| 335 | + _COM2_OUT_DRIVE_3x, |
|
| 336 | + _REG04, |
|
| 337 | + _REG04_DEFAULT, |
|
| 338 | + _COM8, |
|
| 339 | + _COM8_DEFAULT | _COM8_BNDF_EN | _COM8_AGC_EN | _COM8_AEC_EN, |
|
| 340 | + _COM9, |
|
| 341 | + _COM9_AGC_SET(_COM9_AGC_GAIN_8x), |
|
| 342 | + 0x2C, |
|
| 343 | + 0x0C, |
|
| 344 | + 0x33, |
|
| 345 | + 0x78, |
|
| 346 | + 0x3A, |
|
| 347 | + 0x33, |
|
| 348 | + 0x3B, |
|
| 349 | + 0xFB, |
|
| 350 | + 0x3E, |
|
| 351 | + 0x00, |
|
| 352 | + 0x43, |
|
| 353 | + 0x11, |
|
| 354 | + 0x16, |
|
| 355 | + 0x10, |
|
| 356 | + 0x39, |
|
| 357 | + 0x92, |
|
| 358 | + 0x35, |
|
| 359 | + 0xDA, |
|
| 360 | + 0x22, |
|
| 361 | + 0x1A, |
|
| 362 | + 0x37, |
|
| 363 | + 0xC3, |
|
| 364 | + 0x23, |
|
| 365 | + 0x00, |
|
| 366 | + _ARCOM2, |
|
| 367 | + 0xC0, |
|
| 368 | + 0x06, |
|
| 369 | + 0x88, |
|
| 370 | + 0x07, |
|
| 371 | + 0xC0, |
|
| 372 | + _COM4, |
|
| 373 | + 0x87, |
|
| 374 | + 0x0E, |
|
| 375 | + 0x41, |
|
| 376 | + 0x4C, |
|
| 377 | + 0x00, |
|
| 378 | + 0x4A, |
|
| 379 | + 0x81, |
|
| 380 | + 0x21, |
|
| 381 | + 0x99, |
|
| 382 | + _AEW, |
|
| 383 | + 0x40, |
|
| 384 | + _AEB, |
|
| 385 | + 0x38, |
|
| 386 | + _VV, |
|
| 387 | + _VV_AGC_TH_SET(8, 2), |
|
| 388 | + 0x5C, |
|
| 389 | + 0x00, |
|
| 390 | + 0x63, |
|
| 391 | + 0x00, |
|
| 392 | + _HISTO_LOW, |
|
| 393 | + 0x70, |
|
| 394 | + _HISTO_HIGH, |
|
| 395 | + 0x80, |
|
| 396 | + 0x7C, |
|
| 397 | + 0x05, |
|
| 398 | + 0x20, |
|
| 399 | + 0x80, |
|
| 400 | + 0x28, |
|
| 401 | + 0x30, |
|
| 402 | + 0x6C, |
|
| 403 | + 0x00, |
|
| 404 | + 0x6D, |
|
| 405 | + 0x80, |
|
| 406 | + 0x6E, |
|
| 407 | + 0x00, |
|
| 408 | + 0x70, |
|
| 409 | + 0x02, |
|
| 410 | + 0x71, |
|
| 411 | + 0x94, |
|
| 412 | + 0x73, |
|
| 413 | + 0xC1, |
|
| 414 | + 0x3D, |
|
| 415 | + 0x34, |
|
| 416 | + 0x5A, |
|
| 417 | + 0x57, |
|
| 418 | + _BD50, |
|
| 419 | + 0xBB, |
|
| 420 | + _BD60, |
|
| 421 | + 0x9C, |
|
| 422 | + _COM7, |
|
| 423 | + _COM7_RES_CIF, |
|
| 424 | + _HSTART, |
|
| 425 | + 0x11, |
|
| 426 | + _HSTOP, |
|
| 427 | + 0x43, |
|
| 428 | + _VSTART, |
|
| 429 | + 0x00, |
|
| 430 | + _VSTOP, |
|
| 431 | + 0x25, |
|
| 432 | + _REG32, |
|
| 433 | + 0x89, |
|
| 434 | + 0x37, |
|
| 435 | + 0xC0, |
|
| 436 | + _BD50, |
|
| 437 | + 0xCA, |
|
| 438 | + _BD60, |
|
| 439 | + 0xA8, |
|
| 440 | + 0x6D, |
|
| 441 | + 0x00, |
|
| 442 | + 0x3D, |
|
| 443 | + 0x38, |
|
| 444 | + _BANK_SEL, |
|
| 445 | + _BANK_DSP, |
|
| 446 | + 0xE5, |
|
| 447 | + 0x7F, |
|
| 448 | + _MC_BIST, |
|
| 449 | + _MC_BIST_RESET | _MC_BIST_BOOT_ROM_SEL, |
|
| 450 | + 0x41, |
|
| 451 | + 0x24, |
|
| 452 | + _RESET, |
|
| 453 | + _RESET_JPEG | _RESET_DVP, |
|
| 454 | + 0x76, |
|
| 455 | + 0xFF, |
|
| 456 | + 0x33, |
|
| 457 | + 0xA0, |
|
| 458 | + 0x42, |
|
| 459 | + 0x20, |
|
| 460 | + 0x43, |
|
| 461 | + 0x18, |
|
| 462 | + 0x4C, |
|
| 463 | + 0x00, |
|
| 464 | + _CTRL3, |
|
| 465 | + _CTRL3_WPC_EN | 0x10, |
|
| 466 | + 0x88, |
|
| 467 | + 0x3F, |
|
| 468 | + 0xD7, |
|
| 469 | + 0x03, |
|
| 470 | + 0xD9, |
|
| 471 | + 0x10, |
|
| 472 | + _R_DVP_SP, |
|
| 473 | + _R_DVP_SP_AUTO_MODE | 0x02, |
|
| 474 | + 0xC8, |
|
| 475 | + 0x08, |
|
| 476 | + 0xC9, |
|
| 477 | + 0x80, |
|
| 478 | + _BPADDR, |
|
| 479 | + 0x00, |
|
| 480 | + _BPDATA, |
|
| 481 | + 0x00, |
|
| 482 | + _BPADDR, |
|
| 483 | + 0x03, |
|
| 484 | + _BPDATA, |
|
| 485 | + 0x48, |
|
| 486 | + _BPDATA, |
|
| 487 | + 0x48, |
|
| 488 | + _BPADDR, |
|
| 489 | + 0x08, |
|
| 490 | + _BPDATA, |
|
| 491 | + 0x20, |
|
| 492 | + _BPDATA, |
|
| 493 | + 0x10, |
|
| 494 | + _BPDATA, |
|
| 495 | + 0x0E, |
|
| 496 | + 0x90, |
|
| 497 | + 0x00, |
|
| 498 | + 0x91, |
|
| 499 | + 0x0E, |
|
| 500 | + 0x91, |
|
| 501 | + 0x1A, |
|
| 502 | + 0x91, |
|
| 503 | + 0x31, |
|
| 504 | + 0x91, |
|
| 505 | + 0x5A, |
|
| 506 | + 0x91, |
|
| 507 | + 0x69, |
|
| 508 | + 0x91, |
|
| 509 | + 0x75, |
|
| 510 | + 0x91, |
|
| 511 | + 0x7E, |
|
| 512 | + 0x91, |
|
| 513 | + 0x88, |
|
| 514 | + 0x91, |
|
| 515 | + 0x8F, |
|
| 516 | + 0x91, |
|
| 517 | + 0x96, |
|
| 518 | + 0x91, |
|
| 519 | + 0xA3, |
|
| 520 | + 0x91, |
|
| 521 | + 0xAF, |
|
| 522 | + 0x91, |
|
| 523 | + 0xC4, |
|
| 524 | + 0x91, |
|
| 525 | + 0xD7, |
|
| 526 | + 0x91, |
|
| 527 | + 0xE8, |
|
| 528 | + 0x91, |
|
| 529 | + 0x20, |
|
| 530 | + 0x92, |
|
| 531 | + 0x00, |
|
| 532 | + 0x93, |
|
| 533 | + 0x06, |
|
| 534 | + 0x93, |
|
| 535 | + 0xE3, |
|
| 536 | + 0x93, |
|
| 537 | + 0x05, |
|
| 538 | + 0x93, |
|
| 539 | + 0x05, |
|
| 540 | + 0x93, |
|
| 541 | + 0x00, |
|
| 542 | + 0x93, |
|
| 543 | + 0x04, |
|
| 544 | + 0x93, |
|
| 545 | + 0x00, |
|
| 546 | + 0x93, |
|
| 547 | + 0x00, |
|
| 548 | + 0x93, |
|
| 549 | + 0x00, |
|
| 550 | + 0x93, |
|
| 551 | + 0x00, |
|
| 552 | + 0x93, |
|
| 553 | + 0x00, |
|
| 554 | + 0x93, |
|
| 555 | + 0x00, |
|
| 556 | + 0x93, |
|
| 557 | + 0x00, |
|
| 558 | + 0x96, |
|
| 559 | + 0x00, |
|
| 560 | + 0x97, |
|
| 561 | + 0x08, |
|
| 562 | + 0x97, |
|
| 563 | + 0x19, |
|
| 564 | + 0x97, |
|
| 565 | + 0x02, |
|
| 566 | + 0x97, |
|
| 567 | + 0x0C, |
|
| 568 | + 0x97, |
|
| 569 | + 0x24, |
|
| 570 | + 0x97, |
|
| 571 | + 0x30, |
|
| 572 | + 0x97, |
|
| 573 | + 0x28, |
|
| 574 | + 0x97, |
|
| 575 | + 0x26, |
|
| 576 | + 0x97, |
|
| 577 | + 0x02, |
|
| 578 | + 0x97, |
|
| 579 | + 0x98, |
|
| 580 | + 0x97, |
|
| 581 | + 0x80, |
|
| 582 | + 0x97, |
|
| 583 | + 0x00, |
|
| 584 | + 0x97, |
|
| 585 | + 0x00, |
|
| 586 | + 0xA4, |
|
| 587 | + 0x00, |
|
| 588 | + 0xA8, |
|
| 589 | + 0x00, |
|
| 590 | + 0xC5, |
|
| 591 | + 0x11, |
|
| 592 | + 0xC6, |
|
| 593 | + 0x51, |
|
| 594 | + 0xBF, |
|
| 595 | + 0x80, |
|
| 596 | + 0xC7, |
|
| 597 | + 0x10, |
|
| 598 | + 0xB6, |
|
| 599 | + 0x66, |
|
| 600 | + 0xB8, |
|
| 601 | + 0xA5, |
|
| 602 | + 0xB7, |
|
| 603 | + 0x64, |
|
| 604 | + 0xB9, |
|
| 605 | + 0x7C, |
|
| 606 | + 0xB3, |
|
| 607 | + 0xAF, |
|
| 608 | + 0xB4, |
|
| 609 | + 0x97, |
|
| 610 | + 0xB5, |
|
| 611 | + 0xFF, |
|
| 612 | + 0xB0, |
|
| 613 | + 0xC5, |
|
| 614 | + 0xB1, |
|
| 615 | + 0x94, |
|
| 616 | + 0xB2, |
|
| 617 | + 0x0F, |
|
| 618 | + 0xC4, |
|
| 619 | + 0x5C, |
|
| 620 | + _CTRL1, |
|
| 621 | + 0xFD, |
|
| 622 | + 0x7F, |
|
| 623 | + 0x00, |
|
| 624 | + 0xE5, |
|
| 625 | + 0x1F, |
|
| 626 | + 0xE1, |
|
| 627 | + 0x67, |
|
| 628 | + 0xDD, |
|
| 629 | + 0x7F, |
|
| 630 | + _IMAGE_MODE, |
|
| 631 | + 0x00, |
|
| 632 | + _RESET, |
|
| 633 | + 0x00, |
|
| 634 | + _R_BYPASS, |
|
| 635 | + _R_BYPASS_DSP_EN, |
|
| 636 | + ] |
|
| 637 | +) |
|
| 638 | + |
|
| 639 | +_ov2640_settings_to_cif = bytes( |
|
| 640 | + [ |
|
| 641 | + _BANK_SEL, |
|
| 642 | + _BANK_SENSOR, |
|
| 643 | + _COM7, |
|
| 644 | + _COM7_RES_CIF, |
|
| 645 | + # Set the sensor output window |
|
| 646 | + _COM1, |
|
| 647 | + 0x0A, |
|
| 648 | + _REG32, |
|
| 649 | + _REG32_CIF, |
|
| 650 | + _HSTART, |
|
| 651 | + 0x11, |
|
| 652 | + _HSTOP, |
|
| 653 | + 0x43, |
|
| 654 | + _VSTART, |
|
| 655 | + 0x00, |
|
| 656 | + _VSTOP, |
|
| 657 | + 0x25, |
|
| 658 | + # _CLKRC, 0x00, |
|
| 659 | + _BD50, |
|
| 660 | + 0xCA, |
|
| 661 | + _BD60, |
|
| 662 | + 0xA8, |
|
| 663 | + 0x5A, |
|
| 664 | + 0x23, |
|
| 665 | + 0x6D, |
|
| 666 | + 0x00, |
|
| 667 | + 0x3D, |
|
| 668 | + 0x38, |
|
| 669 | + 0x39, |
|
| 670 | + 0x92, |
|
| 671 | + 0x35, |
|
| 672 | + 0xDA, |
|
| 673 | + 0x22, |
|
| 674 | + 0x1A, |
|
| 675 | + 0x37, |
|
| 676 | + 0xC3, |
|
| 677 | + 0x23, |
|
| 678 | + 0x00, |
|
| 679 | + _ARCOM2, |
|
| 680 | + 0xC0, |
|
| 681 | + 0x06, |
|
| 682 | + 0x88, |
|
| 683 | + 0x07, |
|
| 684 | + 0xC0, |
|
| 685 | + _COM4, |
|
| 686 | + 0x87, |
|
| 687 | + 0x0E, |
|
| 688 | + 0x41, |
|
| 689 | + 0x4C, |
|
| 690 | + 0x00, |
|
| 691 | + _BANK_SEL, |
|
| 692 | + _BANK_DSP, |
|
| 693 | + _RESET, |
|
| 694 | + _RESET_DVP, |
|
| 695 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 696 | + _HSIZE8, |
|
| 697 | + 0x32, |
|
| 698 | + _VSIZE8, |
|
| 699 | + 0x25, |
|
| 700 | + _SIZEL, |
|
| 701 | + 0x00, |
|
| 702 | + # Set the image window size >= output size |
|
| 703 | + _HSIZE, |
|
| 704 | + 0x64, |
|
| 705 | + _VSIZE, |
|
| 706 | + 0x4A, |
|
| 707 | + _XOFFL, |
|
| 708 | + 0x00, |
|
| 709 | + _YOFFL, |
|
| 710 | + 0x00, |
|
| 711 | + _VHYX, |
|
| 712 | + 0x00, |
|
| 713 | + _TEST, |
|
| 714 | + 0x00, |
|
| 715 | + _CTRL2, |
|
| 716 | + _CTRL2_DCW_EN | 0x1D, |
|
| 717 | + _CTRLI, |
|
| 718 | + _CTRLI_LP_DP | 0x00, |
|
| 719 | + # _R_DVP_SP, 0x08, |
|
| 720 | + ] |
|
| 721 | +) |
|
| 722 | + |
|
| 723 | +_ov2640_settings_to_svga = bytes( |
|
| 724 | + [ |
|
| 725 | + _BANK_SEL, |
|
| 726 | + _BANK_SENSOR, |
|
| 727 | + _COM7, |
|
| 728 | + _COM7_RES_SVGA, |
|
| 729 | + # Set the sensor output window |
|
| 730 | + _COM1, |
|
| 731 | + 0x0A, |
|
| 732 | + _REG32, |
|
| 733 | + _REG32_SVGA, |
|
| 734 | + _HSTART, |
|
| 735 | + 0x11, |
|
| 736 | + _HSTOP, |
|
| 737 | + 0x43, |
|
| 738 | + _VSTART, |
|
| 739 | + 0x00, |
|
| 740 | + _VSTOP, |
|
| 741 | + 0x4B, |
|
| 742 | + # _CLKRC, 0x00, |
|
| 743 | + 0x37, |
|
| 744 | + 0xC0, |
|
| 745 | + _BD50, |
|
| 746 | + 0xCA, |
|
| 747 | + _BD60, |
|
| 748 | + 0xA8, |
|
| 749 | + 0x5A, |
|
| 750 | + 0x23, |
|
| 751 | + 0x6D, |
|
| 752 | + 0x00, |
|
| 753 | + 0x3D, |
|
| 754 | + 0x38, |
|
| 755 | + 0x39, |
|
| 756 | + 0x92, |
|
| 757 | + 0x35, |
|
| 758 | + 0xDA, |
|
| 759 | + 0x22, |
|
| 760 | + 0x1A, |
|
| 761 | + 0x37, |
|
| 762 | + 0xC3, |
|
| 763 | + 0x23, |
|
| 764 | + 0x00, |
|
| 765 | + _ARCOM2, |
|
| 766 | + 0xC0, |
|
| 767 | + 0x06, |
|
| 768 | + 0x88, |
|
| 769 | + 0x07, |
|
| 770 | + 0xC0, |
|
| 771 | + _COM4, |
|
| 772 | + 0x87, |
|
| 773 | + 0x0E, |
|
| 774 | + 0x41, |
|
| 775 | + 0x42, |
|
| 776 | + 0x03, |
|
| 777 | + 0x4C, |
|
| 778 | + 0x00, |
|
| 779 | + _BANK_SEL, |
|
| 780 | + _BANK_DSP, |
|
| 781 | + _RESET, |
|
| 782 | + _RESET_DVP, |
|
| 783 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 784 | + _HSIZE8, |
|
| 785 | + 0x64, |
|
| 786 | + _VSIZE8, |
|
| 787 | + 0x4B, |
|
| 788 | + _SIZEL, |
|
| 789 | + 0x00, |
|
| 790 | + # Set the image window size >= output size |
|
| 791 | + _HSIZE, |
|
| 792 | + 0xC8, |
|
| 793 | + _VSIZE, |
|
| 794 | + 0x96, |
|
| 795 | + _XOFFL, |
|
| 796 | + 0x00, |
|
| 797 | + _YOFFL, |
|
| 798 | + 0x00, |
|
| 799 | + _VHYX, |
|
| 800 | + 0x00, |
|
| 801 | + _TEST, |
|
| 802 | + 0x00, |
|
| 803 | + _CTRL2, |
|
| 804 | + _CTRL2_DCW_EN | 0x1D, |
|
| 805 | + _CTRLI, |
|
| 806 | + _CTRLI_LP_DP | 0x00, |
|
| 807 | + # _R_DVP_SP, 0x08, |
|
| 808 | + ] |
|
| 809 | +) |
|
| 810 | + |
|
| 811 | +_ov2640_settings_to_uxga = bytes( |
|
| 812 | + [ |
|
| 813 | + _BANK_SEL, |
|
| 814 | + _BANK_SENSOR, |
|
| 815 | + _COM7, |
|
| 816 | + _COM7_RES_UXGA, |
|
| 817 | + # Set the sensor output window |
|
| 818 | + _COM1, |
|
| 819 | + 0x0F, |
|
| 820 | + _REG32, |
|
| 821 | + _REG32_UXGA, |
|
| 822 | + _HSTART, |
|
| 823 | + 0x11, |
|
| 824 | + _HSTOP, |
|
| 825 | + 0x75, |
|
| 826 | + _VSTART, |
|
| 827 | + 0x01, |
|
| 828 | + _VSTOP, |
|
| 829 | + 0x97, |
|
| 830 | + # _CLKRC, 0x00, |
|
| 831 | + 0x3D, |
|
| 832 | + 0x34, |
|
| 833 | + _BD50, |
|
| 834 | + 0xBB, |
|
| 835 | + _BD60, |
|
| 836 | + 0x9C, |
|
| 837 | + 0x5A, |
|
| 838 | + 0x57, |
|
| 839 | + 0x6D, |
|
| 840 | + 0x80, |
|
| 841 | + 0x39, |
|
| 842 | + 0x82, |
|
| 843 | + 0x23, |
|
| 844 | + 0x00, |
|
| 845 | + 0x07, |
|
| 846 | + 0xC0, |
|
| 847 | + 0x4C, |
|
| 848 | + 0x00, |
|
| 849 | + 0x35, |
|
| 850 | + 0x88, |
|
| 851 | + 0x22, |
|
| 852 | + 0x0A, |
|
| 853 | + 0x37, |
|
| 854 | + 0x40, |
|
| 855 | + _ARCOM2, |
|
| 856 | + 0xA0, |
|
| 857 | + 0x06, |
|
| 858 | + 0x02, |
|
| 859 | + _COM4, |
|
| 860 | + 0xB7, |
|
| 861 | + 0x0E, |
|
| 862 | + 0x01, |
|
| 863 | + 0x42, |
|
| 864 | + 0x83, |
|
| 865 | + _BANK_SEL, |
|
| 866 | + _BANK_DSP, |
|
| 867 | + _RESET, |
|
| 868 | + _RESET_DVP, |
|
| 869 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 870 | + _HSIZE8, |
|
| 871 | + 0xC8, |
|
| 872 | + _VSIZE8, |
|
| 873 | + 0x96, |
|
| 874 | + _SIZEL, |
|
| 875 | + 0x00, |
|
| 876 | + # Set the image window size >= output size |
|
| 877 | + _HSIZE, |
|
| 878 | + 0x90, |
|
| 879 | + _VSIZE, |
|
| 880 | + 0x2C, |
|
| 881 | + _XOFFL, |
|
| 882 | + 0x00, |
|
| 883 | + _YOFFL, |
|
| 884 | + 0x00, |
|
| 885 | + _VHYX, |
|
| 886 | + 0x88, |
|
| 887 | + _TEST, |
|
| 888 | + 0x00, |
|
| 889 | + _CTRL2, |
|
| 890 | + _CTRL2_DCW_EN | 0x1D, |
|
| 891 | + _CTRLI, |
|
| 892 | + 0x00, |
|
| 893 | + # _R_DVP_SP, 0x06, |
|
| 894 | + ] |
|
| 895 | +) |
|
| 896 | + |
|
| 897 | +_ov2640_color_settings = { |
|
| 898 | + OV2640_COLOR_JPEG: bytes( |
|
| 899 | + [ |
|
| 900 | + _BANK_SEL, |
|
| 901 | + _BANK_DSP, |
|
| 902 | + _RESET, |
|
| 903 | + _RESET_JPEG | _RESET_DVP, |
|
| 904 | + _IMAGE_MODE, |
|
| 905 | + _IMAGE_MODE_JPEG_EN | _IMAGE_MODE_HREF_VSYNC, |
|
| 906 | + 0xD7, |
|
| 907 | + 0x03, |
|
| 908 | + 0xE1, |
|
| 909 | + 0x77, |
|
| 910 | + 0xE5, |
|
| 911 | + 0x1F, |
|
| 912 | + 0xD9, |
|
| 913 | + 0x10, |
|
| 914 | + 0xDF, |
|
| 915 | + 0x80, |
|
| 916 | + 0x33, |
|
| 917 | + 0x80, |
|
| 918 | + 0x3C, |
|
| 919 | + 0x10, |
|
| 920 | + 0xEB, |
|
| 921 | + 0x30, |
|
| 922 | + 0xDD, |
|
| 923 | + 0x7F, |
|
| 924 | + _RESET, |
|
| 925 | + 0x00, |
|
| 926 | + ] |
|
| 927 | + ), |
|
| 928 | + OV2640_COLOR_YUV: bytes( |
|
| 929 | + [ |
|
| 930 | + _BANK_SEL, |
|
| 931 | + _BANK_DSP, |
|
| 932 | + _RESET, |
|
| 933 | + _RESET_DVP, |
|
| 934 | + _IMAGE_MODE, |
|
| 935 | + _IMAGE_MODE_YUV422, |
|
| 936 | + 0xD7, |
|
| 937 | + 0x01, |
|
| 938 | + 0xE1, |
|
| 939 | + 0x67, |
|
| 940 | + _RESET, |
|
| 941 | + 0x00, |
|
| 942 | + ] |
|
| 943 | + ), |
|
| 944 | + OV2640_COLOR_RGB: bytes( |
|
| 945 | + [ |
|
| 946 | + _BANK_SEL, |
|
| 947 | + _BANK_DSP, |
|
| 948 | + _RESET, |
|
| 949 | + _RESET_DVP, |
|
| 950 | + _IMAGE_MODE, |
|
| 951 | + _IMAGE_MODE_RGB565, |
|
| 952 | + 0xD7, |
|
| 953 | + 0x03, |
|
| 954 | + 0xE1, |
|
| 955 | + 0x77, |
|
| 956 | + _RESET, |
|
| 957 | + 0x00, |
|
| 958 | + ] |
|
| 959 | + ), |
|
| 960 | +} |
|
| 961 | + |
|
| 962 | + |
|
| 963 | +class _RegBits: |
|
| 964 | + def __init__(self, bank: int, reg: int, shift: int, mask: int) -> None: |
|
| 965 | + self.bank = bank |
|
| 966 | + self.reg = reg |
|
| 967 | + self.shift = shift |
|
| 968 | + self.mask = mask |
|
| 969 | + |
|
| 970 | + def __get__(self, obj: "_SCCBCameraBase", objtype: Optional[Type] = None) -> int: |
|
| 971 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 972 | + return (reg_value >> self.shift) & self.mask |
|
| 973 | + |
|
| 974 | + def __set__(self, obj: "_SCCBCameraBase", value: Union[bool, int]) -> None: |
|
| 975 | + if value & ~self.mask: |
|
| 976 | + raise ValueError(f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}") |
|
| 977 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 978 | + reg_value &= ~(self.mask << self.shift) |
|
| 979 | + reg_value |= value << self.shift |
|
| 980 | + obj._write_register(self.reg, reg_value) |
|
| 981 | + |
|
| 982 | + |
|
| 983 | +class _SCCBCameraBase: |
|
| 984 | + def __init__(self, i2c_bus: I2C, i2c_address: int) -> None: |
|
| 985 | + self._i2c_device = I2CDevice(i2c_bus, i2c_address) |
|
| 986 | + self._bank = None |
|
| 987 | + |
|
| 988 | + def _get_reg_bits(self, bank: int, reg: int, shift: int, mask: int) -> int: |
|
| 989 | + return (self._read_bank_register(bank, reg) >> shift) & mask |
|
| 990 | + |
|
| 991 | + def _set_reg_bits(self, bank: int, reg: int, shift: int, mask: int, value: int) -> None: |
|
| 992 | + reg_value = self._read_bank_register(bank, reg) |
|
| 993 | + reg_value &= ~(mask << shift) |
|
| 994 | + reg_value |= value << shift |
|
| 995 | + self._write_register(reg, reg_value) |
|
| 996 | + |
|
| 997 | + def _write_list(self, reg_list: List[int]) -> None: |
|
| 998 | + for i in range(0, len(reg_list), 2): |
|
| 999 | + self._write_register(reg_list[i], reg_list[i + 1]) |
|
| 1000 | + time.sleep(0.001) |
|
| 1001 | + |
|
| 1002 | + def _write_bank_register(self, bank: int, reg: int, value: int) -> None: |
|
| 1003 | + if self._bank != bank: |
|
| 1004 | + self._write_register(_BANK_SEL, bank) |
|
| 1005 | + self._write_register(reg, value) |
|
| 1006 | + |
|
| 1007 | + def _read_bank_register(self, bank: int, reg: int) -> int: |
|
| 1008 | + if self._bank != bank: |
|
| 1009 | + self._write_register(_BANK_SEL, bank) |
|
| 1010 | + result = self._read_register(reg) |
|
| 1011 | + return result |
|
| 1012 | + |
|
| 1013 | + def _write_register(self, reg: int, value: int) -> None: |
|
| 1014 | + if reg == _BANK_SEL: |
|
| 1015 | + if self._bank == value: |
|
| 1016 | + return |
|
| 1017 | + self._bank = value |
|
| 1018 | + # print(f"write_register {reg:02x} {value:02x}") |
|
| 1019 | + b = bytearray(2) |
|
| 1020 | + b[0] = reg |
|
| 1021 | + b[1] = value |
|
| 1022 | + with self._i2c_device as i2c: |
|
| 1023 | + i2c.write(b) |
|
| 1024 | + |
|
| 1025 | + def _read_register(self, reg: int) -> int: |
|
| 1026 | + b = bytearray(1) |
|
| 1027 | + b[0] = reg |
|
| 1028 | + with self._i2c_device as i2c: |
|
| 1029 | + i2c.write(b) |
|
| 1030 | + i2c.readinto(b) |
|
| 1031 | + return b[0] |
|
| 1032 | + |
|
| 1033 | + |
|
| 1034 | +class OV2640(_SCCBCameraBase): |
|
| 1035 | + """Library for the OV2640 digital camera""" |
|
| 1036 | + |
|
| 1037 | + test_pattern = _RegBits(_BANK_SENSOR, _COM7, 1, 1) |
|
| 1038 | + gain_ceiling = _RegBits(_BANK_SENSOR, _COM9, 5, 7) |
|
| 1039 | + bpc = _RegBits(_BANK_DSP, _CTRL3, 7, 1) |
|
| 1040 | + wpc = _RegBits(_BANK_DSP, _CTRL3, 6, 1) |
|
| 1041 | + lenc = _RegBits(_BANK_DSP, _CTRL1, 1, 1) |
|
| 1042 | + |
|
| 1043 | + def __init__( |
|
| 1044 | + self, |
|
| 1045 | + i2c_bus: I2C, |
|
| 1046 | + data_pins: Pin, |
|
| 1047 | + clock: Pin, |
|
| 1048 | + vsync: Pin, |
|
| 1049 | + href: Pin, |
|
| 1050 | + shutdown: Optional[Pin] = None, |
|
| 1051 | + reset: Optional[Pin] = None, |
|
| 1052 | + mclk: Optional[Pin] = None, |
|
| 1053 | + mclk_frequency: int = 20_000_000, |
|
| 1054 | + i2c_address: int = 0x30, |
|
| 1055 | + size: int = OV2640_SIZE_QQVGA, |
|
| 1056 | + ): |
|
| 1057 | + """ |
|
| 1058 | + Args: |
|
| 1059 | + i2c_bus (busio.I2C): The I2C bus used to configure the OV2640 |
|
| 1060 | + data_pins (List[microcontroller.Pin]): A list of 8 data pins, in order. |
|
| 1061 | + clock (microcontroller.Pin): The pixel clock from the OV2640. |
|
| 1062 | + vsync (microcontroller.Pin): The vsync signal from the OV2640. |
|
| 1063 | + href (microcontroller.Pin): The href signal from the OV2640, \ |
|
| 1064 | + sometimes inaccurately called hsync. |
|
| 1065 | + shutdown (Optional[microcontroller.Pin]): If not None, the shutdown |
|
| 1066 | + signal to the camera, also called the powerdown or enable pin. |
|
| 1067 | + reset (Optional[microcontroller.Pin]): If not None, the reset signal |
|
| 1068 | + to the camera. |
|
| 1069 | + mclk (Optional[microcontroller.Pin]): The pin on which to create a |
|
| 1070 | + master clock signal, or None if the master clock signal is |
|
| 1071 | + already being generated. |
|
| 1072 | + mclk_frequency (int): The frequency of the master clock to generate, \ |
|
| 1073 | + ignored if mclk is None, requred if it is specified |
|
| 1074 | + i2c_address (int): The I2C address of the camera. |
|
| 1075 | + """ |
|
| 1076 | + |
|
| 1077 | + # Initialize the master clock |
|
| 1078 | + if mclk: |
|
| 1079 | + self._mclk_pwm = pwmio.PWMOut(mclk, frequency=mclk_frequency) |
|
| 1080 | + self._mclk_pwm.duty_cycle = 32768 |
|
| 1081 | + else: |
|
| 1082 | + self._mclk_pwm = None |
|
| 1083 | + |
|
| 1084 | + if shutdown: |
|
| 1085 | + self._shutdown = digitalio.DigitalInOut(shutdown) |
|
| 1086 | + self._shutdown.switch_to_output(True) |
|
| 1087 | + time.sleep(0.1) |
|
| 1088 | + self._shutdown.switch_to_output(False) |
|
| 1089 | + time.sleep(0.3) |
|
| 1090 | + else: |
|
| 1091 | + self._shutdown = None |
|
| 1092 | + |
|
| 1093 | + if reset: |
|
| 1094 | + self._reset = digitalio.DigitalInOut(reset) |
|
| 1095 | + self._reset.switch_to_output(False) |
|
| 1096 | + time.sleep(0.1) |
|
| 1097 | + self._reset.switch_to_output(True) |
|
| 1098 | + time.sleep(0.1) |
|
| 1099 | + |
|
| 1100 | + super().__init__(i2c_bus, i2c_address) |
|
| 1101 | + |
|
| 1102 | + self._write_bank_register(_BANK_SENSOR, _COM7, _COM7_SRST) |
|
| 1103 | + time.sleep(0.001) |
|
| 1104 | + |
|
| 1105 | + self._write_list(_ov2640_settings_cif) |
|
| 1106 | + |
|
| 1107 | + self._colorspace = OV2640_COLOR_RGB |
|
| 1108 | + self._w = None |
|
| 1109 | + self._h = None |
|
| 1110 | + self._size = None |
|
| 1111 | + self._test_pattern = False |
|
| 1112 | + self.size = size |
|
| 1113 | + |
|
| 1114 | + self._flip_x = False |
|
| 1115 | + self._flip_y = False |
|
| 1116 | + |
|
| 1117 | + self.gain_ceiling = _COM9_AGC_GAIN_2x |
|
| 1118 | + self.bpc = False |
|
| 1119 | + self.wpc = True |
|
| 1120 | + self.lenc = True |
|
| 1121 | + |
|
| 1122 | + # self._sensor_init() |
|
| 1123 | + |
|
| 1124 | + self._imagecapture = imagecapture.ParallelImageCapture( |
|
| 1125 | + data_pins=data_pins, clock=clock, vsync=vsync, href=href |
|
| 1126 | + ) |
|
| 1127 | + |
|
| 1128 | + def capture(self, buf: WriteableBuffer) -> Optional[memoryview]: |
|
| 1129 | + """Capture an image into the buffer. |
|
| 1130 | + |
|
| 1131 | + Args: |
|
| 1132 | + buf (WriteableBuffer): A WritableBuffer to contain the \ |
|
| 1133 | + captured image. Note that this can be a ulab array or a displayio Bitmap. |
|
| 1134 | + """ |
|
| 1135 | + self._imagecapture.capture(buf) |
|
| 1136 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1137 | + eoi = buf.find(b"\xff\xd9") |
|
| 1138 | + if eoi != -1: |
|
| 1139 | + # terminate the JPEG data just after the EOI marker |
|
| 1140 | + return memoryview(buf)[: eoi + 2] |
|
| 1141 | + return None |
|
| 1142 | + |
|
| 1143 | + @property |
|
| 1144 | + def capture_buffer_size(self) -> int: |
|
| 1145 | + """Return the size of capture buffer to use with current resolution & colorspace settings""" |
|
| 1146 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1147 | + return self.width * self.height // 5 |
|
| 1148 | + return self.width * self.height * 2 |
|
| 1149 | + |
|
| 1150 | + @property |
|
| 1151 | + def mclk_frequency(self) -> Optional[int]: |
|
| 1152 | + """Get the actual frequency the generated mclk, or None""" |
|
| 1153 | + return self._mclk_pwm.frequency if self._mclk_pwm else None |
|
| 1154 | + |
|
| 1155 | + @property |
|
| 1156 | + def width(self) -> int: |
|
| 1157 | + """Get the image width in pixels. A buffer of 2*width*height bytes \ |
|
| 1158 | + stores a whole image.""" |
|
| 1159 | + return self._w |
|
| 1160 | + |
|
| 1161 | + @property |
|
| 1162 | + def height(self) -> int: |
|
| 1163 | + """Get the image height in pixels. A buffer of 2*width*height bytes \ |
|
| 1164 | + stores a whole image.""" |
|
| 1165 | + return self._h |
|
| 1166 | + |
|
| 1167 | + @property |
|
| 1168 | + def colorspace(self) -> bytes: |
|
| 1169 | + """Get or set the colorspace, one of the ``OV2640_COLOR_`` constants.""" |
|
| 1170 | + return self._colorspace |
|
| 1171 | + |
|
| 1172 | + @colorspace.setter |
|
| 1173 | + def colorspace(self, colorspace: bytes) -> None: |
|
| 1174 | + self._colorspace = colorspace |
|
| 1175 | + self._set_size_and_colorspace() |
|
| 1176 | + |
|
| 1177 | + def _set_colorspace(self) -> None: |
|
| 1178 | + colorspace = self._colorspace |
|
| 1179 | + settings = _ov2640_color_settings[colorspace] |
|
| 1180 | + |
|
| 1181 | + self._write_list(settings) |
|
| 1182 | + # written twice? |
|
| 1183 | + self._write_list(settings) |
|
| 1184 | + time.sleep(0.01) |
|
| 1185 | + |
|
| 1186 | + def deinit(self) -> None: |
|
| 1187 | + """Deinitialize the camera""" |
|
| 1188 | + self._imagecapture.deinit() |
|
| 1189 | + if self._mclk_pwm: |
|
| 1190 | + self._mclk_pwm.deinit() |
|
| 1191 | + if self._shutdown: |
|
| 1192 | + self._shutdown.deinit() |
|
| 1193 | + if self._reset: |
|
| 1194 | + self._reset.deinit() |
|
| 1195 | + |
|
| 1196 | + @property |
|
| 1197 | + def size(self) -> int: |
|
| 1198 | + """Get or set the captured image size, one of the ``OV2640_SIZE_`` constants.""" |
|
| 1199 | + return self._size |
|
| 1200 | + |
|
| 1201 | + def _set_size_and_colorspace(self) -> None: |
|
| 1202 | + size = self._size |
|
| 1203 | + width, height, ratio = _resolution_info[size] |
|
| 1204 | + offset_x, offset_y, max_x, max_y = _ratio_table[ratio] |
|
| 1205 | + mode = _OV2640_MODE_UXGA |
|
| 1206 | + if size <= OV2640_SIZE_CIF: |
|
| 1207 | + mode = _OV2640_MODE_CIF |
|
| 1208 | + max_x //= 4 |
|
| 1209 | + max_y //= 4 |
|
| 1210 | + offset_x //= 4 |
|
| 1211 | + offset_y //= 4 |
|
| 1212 | + max_y = min(max_y, 296) |
|
| 1213 | + |
|
| 1214 | + elif size <= OV2640_SIZE_SVGA: |
|
| 1215 | + mode = _OV2640_MODE_SVGA |
|
| 1216 | + max_x //= 2 |
|
| 1217 | + max_y //= 2 |
|
| 1218 | + offset_x //= 2 |
|
| 1219 | + offset_y //= 2 |
|
| 1220 | + |
|
| 1221 | + self._set_window(mode, offset_x, offset_y, max_x, max_y, width, height) |
|
| 1222 | + |
|
| 1223 | + @size.setter |
|
| 1224 | + def size(self, size: int) -> None: |
|
| 1225 | + self._size = size |
|
| 1226 | + self._set_size_and_colorspace() |
|
| 1227 | + |
|
| 1228 | + def _set_flip(self) -> None: |
|
| 1229 | + bits = 0 |
|
| 1230 | + if self._flip_x: |
|
| 1231 | + bits |= _REG04_HFLIP_IMG |
|
| 1232 | + if self._flip_y: |
|
| 1233 | + bits |= _REG04_VFLIP_IMG | _REG04_VREF_EN |
|
| 1234 | + self._write_bank_register(_BANK_SENSOR, _REG04, _REG04_SET(bits)) |
|
| 1235 | + |
|
| 1236 | + @property |
|
| 1237 | + def flip_x(self) -> bool: |
|
| 1238 | + """Get or set the X-flip flag""" |
|
| 1239 | + return self._flip_x |
|
| 1240 | + |
|
| 1241 | + @flip_x.setter |
|
| 1242 | + def flip_x(self, value: bool) -> None: |
|
| 1243 | + self._flip_x = bool(value) |
|
| 1244 | + self._set_flip() |
|
| 1245 | + |
|
| 1246 | + @property |
|
| 1247 | + def flip_y(self) -> bool: |
|
| 1248 | + """Get or set the Y-flip flag""" |
|
| 1249 | + return self._flip_y |
|
| 1250 | + |
|
| 1251 | + @flip_y.setter |
|
| 1252 | + def flip_y(self, value: bool) -> None: |
|
| 1253 | + self._flip_y = bool(value) |
|
| 1254 | + self._set_flip() |
|
| 1255 | + |
|
| 1256 | + @property |
|
| 1257 | + def product_id(self) -> int: |
|
| 1258 | + """Get the product id (PID) register. The expected value is 0x26.""" |
|
| 1259 | + return self._read_bank_register(_BANK_SENSOR, _REG_PID) |
|
| 1260 | + |
|
| 1261 | + @property |
|
| 1262 | + def product_version(self) -> int: |
|
| 1263 | + """Get the version (VER) register. The expected value is 0x41.""" |
|
| 1264 | + return self._read_bank_register(_BANK_SENSOR, _REG_VER) |
|
| 1265 | + |
|
| 1266 | + def _set_window( |
|
| 1267 | + self, |
|
| 1268 | + mode: int, |
|
| 1269 | + offset_x: int, |
|
| 1270 | + offset_y: int, |
|
| 1271 | + max_x: int, |
|
| 1272 | + max_y: int, |
|
| 1273 | + width: int, |
|
| 1274 | + height: int, |
|
| 1275 | + ) -> None: |
|
| 1276 | + self._w = width |
|
| 1277 | + self._h = height |
|
| 1278 | + |
|
| 1279 | + max_x //= 4 |
|
| 1280 | + max_y //= 4 |
|
| 1281 | + width //= 4 |
|
| 1282 | + height //= 4 |
|
| 1283 | + |
|
| 1284 | + win_regs = [ |
|
| 1285 | + _BANK_SEL, |
|
| 1286 | + _BANK_DSP, |
|
| 1287 | + _HSIZE, |
|
| 1288 | + max_x & 0xFF, |
|
| 1289 | + _VSIZE, |
|
| 1290 | + max_y & 0xFF, |
|
| 1291 | + _XOFFL, |
|
| 1292 | + offset_x & 0xFF, |
|
| 1293 | + _YOFFL, |
|
| 1294 | + offset_y & 0xFF, |
|
| 1295 | + _VHYX, |
|
| 1296 | + ((max_y >> 1) & 0x80) |
|
| 1297 | + | ((offset_y >> 4) & 0x70) |
|
| 1298 | + | ((max_x >> 5) & 0x08) |
|
| 1299 | + | ((offset_y >> 8) & 0x07), |
|
| 1300 | + _TEST, |
|
| 1301 | + (max_x >> 2) & 0x80, |
|
| 1302 | + _ZMOW, |
|
| 1303 | + (width) & 0xFF, |
|
| 1304 | + _ZMOH, |
|
| 1305 | + (height) & 0xFF, |
|
| 1306 | + _ZMHH, |
|
| 1307 | + ((height >> 6) & 0x04) | ((width >> 8) & 0x03), |
|
| 1308 | + ] |
|
| 1309 | + |
|
| 1310 | + pclk_auto = 0 |
|
| 1311 | + pclk_div = 8 |
|
| 1312 | + clk_2x = 0 |
|
| 1313 | + clk_div = 0 |
|
| 1314 | + |
|
| 1315 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1316 | + pclk_auto = 1 |
|
| 1317 | + clk_div = 7 |
|
| 1318 | + |
|
| 1319 | + if mode == _OV2640_MODE_CIF: |
|
| 1320 | + regs = _ov2640_settings_to_cif |
|
| 1321 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1322 | + clk_div = 3 |
|
| 1323 | + elif mode == _OV2640_MODE_SVGA: |
|
| 1324 | + regs = _ov2640_settings_to_svga |
|
| 1325 | + else: |
|
| 1326 | + regs = _ov2640_settings_to_uxga |
|
| 1327 | + pclk_div = 12 |
|
| 1328 | + |
|
| 1329 | + clk = clk_div | (clk_2x << 7) |
|
| 1330 | + pclk = pclk_div | (pclk_auto << 7) |
|
| 1331 | + |
|
| 1332 | + self._write_bank_register(_BANK_DSP, _R_BYPASS, _R_BYPASS_DSP_BYPAS) |
|
| 1333 | + self._write_list(regs) |
|
| 1334 | + self._write_list(win_regs) |
|
| 1335 | + self._write_bank_register(_BANK_SENSOR, _CLKRC, clk) |
|
| 1336 | + self._write_bank_register(_BANK_DSP, _R_DVP_SP, pclk) |
|
| 1337 | + self._write_register(_R_BYPASS, _R_BYPASS_DSP_EN) |
|
| 1338 | + time.sleep(0.01) |
|
| 1339 | + |
|
| 1340 | + # Reestablish colorspace |
|
| 1341 | + self._set_colorspace() |
|
| 1342 | + |
|
| 1343 | + # Reestablish test pattern |
|
| 1344 | + if self._test_pattern: |
|
| 1345 | + self.test_pattern = self._test_pattern |
|
| 1346 | + |
|
| 1347 | + @property |
|
| 1348 | + def exposure(self) -> int: |
|
| 1349 | + """The exposure level of the sensor""" |
|
| 1350 | + aec_9_2 = self._get_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF) |
|
| 1351 | + aec_15_10 = self._get_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111) |
|
| 1352 | + aec_1_0 = self._get_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11) |
|
| 1353 | + |
|
| 1354 | + return aec_1_0 | (aec_9_2 << 2) | (aec_15_10 << 10) |
|
| 1355 | + |
|
| 1356 | + @exposure.setter |
|
| 1357 | + def exposure(self, exposure: int) -> None: |
|
| 1358 | + aec_1_0 = exposure & 0x11 |
|
| 1359 | + aec_9_2 = (exposure >> 2) & 0b11111111 |
|
| 1360 | + aec_15_10 = exposure >> 10 |
|
| 1361 | + |
|
| 1362 | + self._set_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF, aec_9_2) |
|
| 1363 | + self._set_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111, aec_15_10) |
|
| 1364 | + self._set_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11, aec_1_0) |
Board-new-dat/ESP32-S3-cam-dat/ESP32-S3-cam-code-dat/demo1.py
| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | + |
|
| 2 | +import sys |
|
| 3 | +import time |
|
| 4 | +import board |
|
| 5 | +import busio |
|
| 6 | +import adafruit_ov2640 |
|
| 7 | + |
|
| 8 | +# Pin mapping based on ESP32-S3-cam-dat.md |
|
| 9 | +# D0-D7: GPIO43, GPIO44, GPIO1, GPIO2, GPIO42, GPIO41, GPIO40, GPIO39 |
|
| 10 | +data_pins = [ |
|
| 11 | + board.GP43, # D0 |
|
| 12 | + board.GP44, # D1 |
|
| 13 | + board.GP1, # D2 |
|
| 14 | + board.GP2, # D3 |
|
| 15 | + board.GP42, # D4 |
|
| 16 | + board.GP41, # D5 |
|
| 17 | + board.GP40, # D6 |
|
| 18 | + board.GP39, # D7 |
|
| 19 | +] |
|
| 20 | + |
|
| 21 | +# I2C for camera control (SIOD/SIOC) |
|
| 22 | +bus = busio.I2C(scl=board.GP21, sda=board.GP20) # Adjust if needed |
|
| 23 | + |
|
| 24 | +cam = adafruit_ov2640.OV2640( |
|
| 25 | + bus, |
|
| 26 | + data_pins=data_pins, |
|
| 27 | + clock=board.GP45, # PCLK (example: VSPI, adjust if needed) |
|
| 28 | + vsync=board.GP36, # VSYNC (example: PSRAM, adjust if needed) |
|
| 29 | + href=board.GP35, # HREF (example: PSRAM, adjust if needed) |
|
| 30 | + mclk=board.GP48, # XCLK (example: WS2812, adjust if needed) |
|
| 31 | + mclk_frequency=20_000_000, |
|
| 32 | + size=adafruit_ov2640.OV2640_SIZE_QQVGA, |
|
| 33 | +) |
|
| 34 | +cam.colorspace = adafruit_ov2640.OV2640_COLOR_YUV |
|
| 35 | +cam.flip_y = True |
|
| 36 | +# cam.test_pattern = True |
|
| 37 | + |
|
| 38 | +buf = bytearray(2 * cam.width * cam.height) |
|
| 39 | +chars = b" .:-=+*#%@" |
|
| 40 | +remap = [chars[i * (len(chars) - 1) // 255] for i in range(256)] |
|
| 41 | + |
|
| 42 | +width = cam.width |
|
| 43 | +row = bytearray(2 * width) |
|
| 44 | + |
|
| 45 | +sys.stdout.write("\033[2J") |
|
| 46 | +while True: |
|
| 47 | + cam.capture(buf) |
|
| 48 | + for j in range(cam.height // 2): |
|
| 49 | + sys.stdout.write(f"\033[{j}H") |
|
| 50 | + for i in range(cam.width // 2): |
|
| 51 | + row[i * 2] = row[i * 2 + 1] = remap[buf[4 * (width * j + i)]] |
|
| 52 | + sys.stdout.write(row) |
|
| 53 | + sys.stdout.write("\033[K") |
|
| 54 | + sys.stdout.write("\033[J") |
|
| 55 | + time.sleep(0.05) |
|
| 56 | + |
|
| 57 | + |
Board-new-dat/ESP32-S3-cam-dat/ESP32-S3-cam-code-dat/pycam1.py
| ... | ... | @@ -0,0 +1,299 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# SPDX-FileCopyrightText: 2023 Jeff Epler for Adafruit Industries |
|
| 4 | +# SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries |
|
| 5 | +# |
|
| 6 | +# SPDX-License-Identifier: Unlicense |
|
| 7 | +import os |
|
| 8 | +import ssl |
|
| 9 | +import time |
|
| 10 | + |
|
| 11 | +import adafruit_ntp |
|
| 12 | +import adafruit_requests |
|
| 13 | +import bitmaptools |
|
| 14 | +import displayio |
|
| 15 | +import gifio |
|
| 16 | +import rtc |
|
| 17 | +import socketpool |
|
| 18 | +import ulab.numpy as np |
|
| 19 | +import wifi |
|
| 20 | + |
|
| 21 | +import adafruit_pycamera |
|
| 22 | + |
|
| 23 | +# Wifi details are in settings.toml file, also, |
|
| 24 | +# timezone info should be included to allow local time and DST adjustments |
|
| 25 | +# # UTC_OFFSET, if present, will override TZ and DST and no API query will be done |
|
| 26 | +# UTC_OFFSET=-25200 |
|
| 27 | +# # TZ="America/Phoenix" |
|
| 28 | + |
|
| 29 | +UTC_OFFSET = os.getenv("UTC_OFFSET") |
|
| 30 | +TZ = os.getenv("TZ") |
|
| 31 | + |
|
| 32 | +print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") |
|
| 33 | +SSID = os.getenv("CIRCUITPY_WIFI_SSID") |
|
| 34 | +PASSWORD = os.getenv("CIRCUITPY_WIFI_PASSWORD") |
|
| 35 | + |
|
| 36 | +if SSID and PASSWORD: |
|
| 37 | + wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) |
|
| 38 | + if wifi.radio.connected: |
|
| 39 | + print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") |
|
| 40 | + print("My IP address is", wifi.radio.ipv4_address) |
|
| 41 | + pool = socketpool.SocketPool(wifi.radio) |
|
| 42 | + |
|
| 43 | + if UTC_OFFSET is None: |
|
| 44 | + requests = adafruit_requests.Session(pool, ssl.create_default_context()) |
|
| 45 | + response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ) |
|
| 46 | + response_as_json = response.json() |
|
| 47 | + UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"] |
|
| 48 | + print(f"UTC_OFFSET: {UTC_OFFSET}") |
|
| 49 | + |
|
| 50 | + ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) |
|
| 51 | + |
|
| 52 | + print(f"ntp time: {ntp.datetime}") |
|
| 53 | + rtc.RTC().datetime = ntp.datetime |
|
| 54 | + else: |
|
| 55 | + print("Wifi failed to connect. Time not set.") |
|
| 56 | +else: |
|
| 57 | + print("Wifi config not found in settintgs.toml. Time not set.") |
|
| 58 | + |
|
| 59 | +pycam = adafruit_pycamera.PyCamera() |
|
| 60 | +# pycam.live_preview_mode() |
|
| 61 | + |
|
| 62 | +settings = ( |
|
| 63 | + None, |
|
| 64 | + "resolution", |
|
| 65 | + "effect", |
|
| 66 | + "mode", |
|
| 67 | + "led_level", |
|
| 68 | + "led_color", |
|
| 69 | + "timelapse_rate", |
|
| 70 | +) |
|
| 71 | +curr_setting = 0 |
|
| 72 | + |
|
| 73 | +print("Starting!") |
|
| 74 | +# pycam.tone(200, 0.1) |
|
| 75 | +last_frame = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535) |
|
| 76 | +onionskin = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535) |
|
| 77 | +timelapse_remaining = None |
|
| 78 | +timelapse_timestamp = None |
|
| 79 | + |
|
| 80 | +while True: |
|
| 81 | + if pycam.mode_text == "STOP" and pycam.stop_motion_frame != 0: |
|
| 82 | + # alpha blend |
|
| 83 | + new_frame = pycam.continuous_capture() |
|
| 84 | + bitmaptools.alphablend( |
|
| 85 | + onionskin, last_frame, new_frame, displayio.Colorspace.RGB565_SWAPPED |
|
| 86 | + ) |
|
| 87 | + pycam.blit(onionskin) |
|
| 88 | + elif pycam.mode_text == "GBOY": |
|
| 89 | + bitmaptools.dither( |
|
| 90 | + last_frame, pycam.continuous_capture(), displayio.Colorspace.RGB565_SWAPPED |
|
| 91 | + ) |
|
| 92 | + pycam.blit(last_frame) |
|
| 93 | + elif pycam.mode_text == "LAPS": |
|
| 94 | + if timelapse_remaining is None: |
|
| 95 | + pycam.timelapsestatus_label.text = "STOP" |
|
| 96 | + else: |
|
| 97 | + timelapse_remaining = timelapse_timestamp - time.time() |
|
| 98 | + pycam.timelapsestatus_label.text = f"{timelapse_remaining}s / " |
|
| 99 | + # Manually updating the label text a second time ensures that the label |
|
| 100 | + # is re-painted over the blitted preview. |
|
| 101 | + pycam.timelapse_rate_label.text = pycam.timelapse_rate_label.text |
|
| 102 | + pycam.timelapse_submode_label.text = pycam.timelapse_submode_label.text |
|
| 103 | + |
|
| 104 | + # only in high power mode do we continuously preview |
|
| 105 | + if (timelapse_remaining is None) or (pycam.timelapse_submode_label.text == "HiPwr"): |
|
| 106 | + pycam.blit(pycam.continuous_capture()) |
|
| 107 | + if pycam.timelapse_submode_label.text == "LowPwr" and (timelapse_remaining is not None): |
|
| 108 | + pycam.display.brightness = 0.05 |
|
| 109 | + else: |
|
| 110 | + pycam.display.brightness = 1 |
|
| 111 | + pycam.display.refresh() |
|
| 112 | + |
|
| 113 | + if timelapse_remaining is not None and timelapse_remaining <= 0: |
|
| 114 | + # no matter what, show what was just on the camera |
|
| 115 | + pycam.blit(pycam.continuous_capture()) |
|
| 116 | + # pycam.tone(200, 0.1) # uncomment to add a beep when a photo is taken |
|
| 117 | + try: |
|
| 118 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 119 | + pycam.capture_jpeg() |
|
| 120 | + except TypeError: |
|
| 121 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 122 | + time.sleep(0.5) |
|
| 123 | + except RuntimeError: |
|
| 124 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 125 | + time.sleep(0.5) |
|
| 126 | + pycam.live_preview_mode() |
|
| 127 | + pycam.display.refresh() |
|
| 128 | + pycam.blit(pycam.continuous_capture()) |
|
| 129 | + timelapse_timestamp = time.time() + pycam.timelapse_rates[pycam.timelapse_rate] + 1 |
|
| 130 | + else: |
|
| 131 | + pycam.blit(pycam.continuous_capture()) |
|
| 132 | + # print("\t\t", capture_time, blit_time) |
|
| 133 | + |
|
| 134 | + pycam.keys_debounce() |
|
| 135 | + # test shutter button |
|
| 136 | + if pycam.shutter.long_press: |
|
| 137 | + print("FOCUS") |
|
| 138 | + print(pycam.autofocus_status) |
|
| 139 | + pycam.autofocus() |
|
| 140 | + print(pycam.autofocus_status) |
|
| 141 | + if pycam.shutter.short_count: |
|
| 142 | + print("Shutter released") |
|
| 143 | + if pycam.mode_text == "STOP": |
|
| 144 | + pycam.capture_into_bitmap(last_frame) |
|
| 145 | + pycam.stop_motion_frame += 1 |
|
| 146 | + try: |
|
| 147 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 148 | + pycam.capture_jpeg() |
|
| 149 | + except TypeError: |
|
| 150 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 151 | + time.sleep(0.5) |
|
| 152 | + except RuntimeError: |
|
| 153 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 154 | + time.sleep(0.5) |
|
| 155 | + pycam.live_preview_mode() |
|
| 156 | + |
|
| 157 | + if pycam.mode_text == "GBOY": |
|
| 158 | + try: |
|
| 159 | + f = pycam.open_next_image("gif") |
|
| 160 | + except RuntimeError: |
|
| 161 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 162 | + time.sleep(0.5) |
|
| 163 | + continue |
|
| 164 | + |
|
| 165 | + with gifio.GifWriter( |
|
| 166 | + f, |
|
| 167 | + pycam.camera.width, |
|
| 168 | + pycam.camera.height, |
|
| 169 | + displayio.Colorspace.RGB565_SWAPPED, |
|
| 170 | + dither=True, |
|
| 171 | + ) as g: |
|
| 172 | + g.add_frame(last_frame, 1) |
|
| 173 | + |
|
| 174 | + if pycam.mode_text == "GIF": |
|
| 175 | + try: |
|
| 176 | + f = pycam.open_next_image("gif") |
|
| 177 | + except RuntimeError: |
|
| 178 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 179 | + time.sleep(0.5) |
|
| 180 | + continue |
|
| 181 | + i = 0 |
|
| 182 | + ft = [] |
|
| 183 | + pycam._mode_label.text = "RECORDING" |
|
| 184 | + |
|
| 185 | + pycam.display.refresh() |
|
| 186 | + with gifio.GifWriter( |
|
| 187 | + f, |
|
| 188 | + pycam.camera.width, |
|
| 189 | + pycam.camera.height, |
|
| 190 | + displayio.Colorspace.RGB565_SWAPPED, |
|
| 191 | + dither=True, |
|
| 192 | + ) as g: |
|
| 193 | + t00 = t0 = time.monotonic() |
|
| 194 | + while (i < 15) or not pycam.shutter_button.value: |
|
| 195 | + i += 1 |
|
| 196 | + _gifframe = pycam.continuous_capture() |
|
| 197 | + g.add_frame(_gifframe, 0.12) |
|
| 198 | + pycam.blit(_gifframe) |
|
| 199 | + t1 = time.monotonic() |
|
| 200 | + ft.append(1 / (t1 - t0)) |
|
| 201 | + print(end=".") |
|
| 202 | + t0 = t1 |
|
| 203 | + pycam._mode_label.text = "GIF" |
|
| 204 | + print(f"\nfinal size {f.tell()} for {i} frames") |
|
| 205 | + print(f"average framerate {i / (t1 - t00)}fps") |
|
| 206 | + print(f"best {max(ft)} worst {min(ft)} std. deviation {np.std(ft)}") |
|
| 207 | + f.close() |
|
| 208 | + pycam.display.refresh() |
|
| 209 | + |
|
| 210 | + if pycam.mode_text == "JPEG": |
|
| 211 | + pycam.tone(200, 0.1) |
|
| 212 | + try: |
|
| 213 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 214 | + pycam.capture_jpeg() |
|
| 215 | + pycam.live_preview_mode() |
|
| 216 | + except TypeError: |
|
| 217 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 218 | + time.sleep(0.5) |
|
| 219 | + pycam.live_preview_mode() |
|
| 220 | + except RuntimeError: |
|
| 221 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 222 | + time.sleep(0.5) |
|
| 223 | + |
|
| 224 | + if pycam.card_detect.fell: |
|
| 225 | + print("SD card removed") |
|
| 226 | + pycam.unmount_sd_card() |
|
| 227 | + pycam.display.refresh() |
|
| 228 | + if pycam.card_detect.rose: |
|
| 229 | + print("SD card inserted") |
|
| 230 | + pycam.display_message("Mounting\nSD Card", color=0xFFFFFF) |
|
| 231 | + for _ in range(3): |
|
| 232 | + try: |
|
| 233 | + print("Mounting card") |
|
| 234 | + pycam.mount_sd_card() |
|
| 235 | + print("Success!") |
|
| 236 | + break |
|
| 237 | + except OSError as e: |
|
| 238 | + print("Retrying!", e) |
|
| 239 | + time.sleep(0.5) |
|
| 240 | + else: |
|
| 241 | + pycam.display_message("SD Card\nFailed!", color=0xFF0000) |
|
| 242 | + time.sleep(0.5) |
|
| 243 | + pycam.display.refresh() |
|
| 244 | + |
|
| 245 | + if pycam.up.fell: |
|
| 246 | + print("UP") |
|
| 247 | + key = settings[curr_setting] |
|
| 248 | + if key: |
|
| 249 | + print("getting", key, getattr(pycam, key)) |
|
| 250 | + setattr(pycam, key, getattr(pycam, key) + 1) |
|
| 251 | + if pycam.down.fell: |
|
| 252 | + print("DN") |
|
| 253 | + key = settings[curr_setting] |
|
| 254 | + if key: |
|
| 255 | + setattr(pycam, key, getattr(pycam, key) - 1) |
|
| 256 | + if pycam.right.fell: |
|
| 257 | + print("RT") |
|
| 258 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 259 | + if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelapse_rate": |
|
| 260 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 261 | + print(settings[curr_setting]) |
|
| 262 | + # new_res = min(len(pycam.resolutions)-1, pycam.get_resolution()+1) |
|
| 263 | + # pycam.set_resolution(pycam.resolutions[new_res]) |
|
| 264 | + pycam.select_setting(settings[curr_setting]) |
|
| 265 | + if pycam.left.fell: |
|
| 266 | + print("LF") |
|
| 267 | + curr_setting = (curr_setting - 1 + len(settings)) % len(settings) |
|
| 268 | + if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelaps_rate": |
|
| 269 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 270 | + print(settings[curr_setting]) |
|
| 271 | + pycam.select_setting(settings[curr_setting]) |
|
| 272 | + # new_res = max(1, pycam.get_resolution()-1) |
|
| 273 | + # pycam.set_resolution(pycam.resolutions[new_res]) |
|
| 274 | + if pycam.select.fell: |
|
| 275 | + print("SEL") |
|
| 276 | + if pycam.mode_text == "LAPS": |
|
| 277 | + pycam.timelapse_submode += 1 |
|
| 278 | + pycam.display.refresh() |
|
| 279 | + if pycam.ok.fell: |
|
| 280 | + print("OK") |
|
| 281 | + if pycam.mode_text == "LAPS": |
|
| 282 | + if timelapse_remaining is None: # stopped |
|
| 283 | + print("Starting timelapse") |
|
| 284 | + timelapse_remaining = pycam.timelapse_rates[pycam.timelapse_rate] |
|
| 285 | + timelapse_timestamp = time.time() + timelapse_remaining + 1 |
|
| 286 | + # dont let the camera take over auto-settings |
|
| 287 | + saved_settings = pycam.get_camera_autosettings() |
|
| 288 | + # print(f"Current exposure {saved_settings=}") |
|
| 289 | + pycam.set_camera_exposure(saved_settings["exposure"]) |
|
| 290 | + pycam.set_camera_gain(saved_settings["gain"]) |
|
| 291 | + pycam.set_camera_wb(saved_settings["wb"]) |
|
| 292 | + else: # is running, turn off |
|
| 293 | + print("Stopping timelapse") |
|
| 294 | + |
|
| 295 | + timelapse_remaining = None |
|
| 296 | + pycam.camera.exposure_ctrl = True |
|
| 297 | + pycam.set_camera_gain(None) # go back to autogain |
|
| 298 | + pycam.set_camera_wb(None) # go back to autobalance |
|
| 299 | + pycam.set_camera_exposure(None) # go back to auto shutter |
|
| ... | ... | \ No newline at end of file |
Board-new-dat/ESP32-S3-cam-dat/ESP32-S3-cam-dat.md
| ... | ... | @@ -6,6 +6,57 @@ |
| 6 | 6 | |
| 7 | 7 |  |
| 8 | 8 | |
| 9 | + |
|
| 10 | +| touch | Pin Name | Function | Signal | |
|
| 11 | +| ----- | -------- | --------- | ---------- | |
|
| 12 | +| | | 3V3 | Power 3.3V | |
|
| 13 | +| | | RST | Reset | |
|
| 14 | +| T4 | ADC1_CH3 | CAM_SIOD | GPIO4 | |
|
| 15 | +| T5 | ADC1_CH4 | CAM_SIOC | GPIO5 | |
|
| 16 | +| T6 | ADC1_CH5 | CAM_VSYNC | GPIO6 | |
|
| 17 | +| T7 | ADC1_CH6 | CAM_HREF | GPIO7 | |
|
| 18 | +| UORTS | ADC2_CH4 | CAM_XCLK | GPIO15 | |
|
| 19 | +| UOCTS | ADC2_CH5 | CAM_Y9 | GPIO16 | |
|
| 20 | +| U1TXD | ADC2_CH6 | CAM_Y8 | GPIO17 | |
|
| 21 | +| U1RXD | ADC2_CH7 | CAM_Y7 | GPIO18 | |
|
| 22 | +| T8 | ADC1_CH7 | CAM_Y4 | GPIO8 | |
|
| 23 | +| T3 | ADC1_CH2 | JTAG_EN | GPIO3 | |
|
| 24 | +| | | LOG | GPIO46 | |
|
| 25 | +| T9 | ADC1_CH8 | CAM_Y3 | GPIO9 | |
|
| 26 | +| T10 | ADC1_CH9 | CAM_Y5 | GPIO10 | |
|
| 27 | +| T11 | ADC2_CH0 | CAM_Y2 | GPIO11 | |
|
| 28 | +| T12 | ADC2_CH1 | CAM_Y6 | GPIO12 | |
|
| 29 | +| T13 | ADC2_CH2 | CAM_PCLK | GPIO13 | |
|
| 30 | +| T14 | ADC2_CH3 | | GPIO14 | |
|
| 31 | +| | | 5V | Power 5V | |
|
| 32 | + |
|
| 33 | +| singal | function | pin name | touch | |
|
| 34 | +| ------ | -------- | -------- | ----- | |
|
| 35 | +| GPIO43 | UOTXD | LED TX | | |
|
| 36 | +| GPIO44 | UORXD | | | |
|
| 37 | +| GPIO1 | ADC1_CH0 | | T1 | |
|
| 38 | +| GPIO2 | ADC1_CH1 | LED ON | T2 | |
|
| 39 | +| GPIO42 | | MTMS | | |
|
| 40 | +| GPIO41 | | MTDI | | |
|
| 41 | +| GPIO40 | SD_DATA | MTDO | | |
|
| 42 | +| GPIO39 | SD_CLK | MTCK | | |
|
| 43 | +| GPIO38 | SD_CMD | | | |
|
| 44 | +| GPIO37 | PSRAM | | | |
|
| 45 | +| GPIO36 | PSRAM | | | |
|
| 46 | +| GPIO35 | PSRAM | | | |
|
| 47 | +| GPIO34 | Boot | | | |
|
| 48 | +| GPIO45 | VSPI | | | |
|
| 49 | +| GPIO48 | WS2812 | | | |
|
| 50 | +| GPIO47 | | | | |
|
| 51 | +| GPIO21 | | | | |
|
| 52 | +| GPIO20 | USB_D- | ADC2_CH9 | UCTS | |
|
| 53 | +| GPIO19 | USB_D+ | ADC2_CH8 | URTS | |
|
| 54 | +| GND | | | | |
|
| 55 | + |
|
| 56 | + |
|
| 57 | + |
|
| 58 | + |
|
| 59 | + |
|
| 9 | 60 | ## SCH |
| 10 | 61 | |
| 11 | 62 |  |
| ... | ... | @@ -26,64 +77,64 @@ |
| 26 | 77 | load:0x403b6000,len:0x8c8 |
| 27 | 78 | load:0x403ba000,len:0x2c04 |
| 28 | 79 | entry 0x403b61c4 |
| 29 | - [0;32mI (24) boot: ESP-IDF v4.4-dev-2594-ga20df743f1-dirty 2nd stage bootloader[0m |
|
| 30 | - [0;32mI (25) boot: compile time 16:57:21[0m |
|
| 31 | - [0;32mI (25) boot: chip revision: 0[0m |
|
| 32 | - [0;32mI (28) boot.esp32s3: SPI Speed : 80MHz[0m |
|
| 33 | - [0;32mI (33) boot.esp32s3: SPI Mode : DIO[0m |
|
| 34 | - [0;32mI (38) boot.esp32s3: SPI Flash Size : 2MB[0m |
|
| 35 | - [0;32mI (43) boot: Enabling RNG early entropy source...[0m |
|
| 36 | - [0;33mW (48) bootloader_random: RNG for ESP32-S3 not currently supported[0m |
|
| 37 | - [0;32mI (55) boot: Partition Table:[0m |
|
| 38 | - [0;32mI (59) boot: ## Label Usage Type ST Offset Length[0m |
|
| 39 | - [0;32mI (66) boot: 0 nvs WiFi data 01 02 00009000 00006000[0m |
|
| 40 | - [0;32mI (73) boot: 1 phy_init RF data 01 01 0000f000 00001000[0m |
|
| 41 | - [0;32mI (81) boot: 2 factory factory app 00 00 00010000 00100000[0m |
|
| 42 | - [0;32mI (88) boot: End of partition table[0m |
|
| 43 | - [0;32mI (92) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=090e0h ( 37088) map[0m |
|
| 44 | - [0;32mI (108) esp_image: segment 1: paddr=00019108 vaddr=3fc90dd0 size=0253ch ( 9532) load[0m |
|
| 45 | - [0;32mI (111) esp_image: segment 2: paddr=0001b64c vaddr=40374000 size=049cch ( 18892) load[0m |
|
| 46 | - [0;32mI (122) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1b660h (112224) map[0m |
|
| 47 | - [0;32mI (147) esp_image: segment 4: paddr=0003b688 vaddr=403789cc size=08404h ( 33796) load[0m |
|
| 48 | - [0;32mI (154) esp_image: segment 5: paddr=00043a94 vaddr=50000000 size=00010h ( 16) load[0m |
|
| 49 | - [0;32mI (160) boot: Loaded app from partition at offset 0x10000[0m |
|
| 50 | - [0;32mI (160) boot: Disabling RNG early entropy source...[0m |
|
| 51 | - [0;33mW (164) bootloader_random: RNG for ESP32-S3 not currently supported[0m |
|
| 52 | - [0;32mI (182) cpu_start: Pro cpu up.[0m |
|
| 53 | - [0;32mI (182) cpu_start: Starting app cpu, entry point is 0x40375104[0m |
|
| 54 | - [0;32mI (0) cpu_start: App cpu up.[0m |
|
| 55 | - [0;32mI (196) cpu_start: Pro cpu start user code[0m |
|
| 56 | - [0;32mI (196) cpu_start: cpu freq: 160000000[0m |
|
| 57 | - [0;32mI (196) cpu_start: Application information:[0m |
|
| 58 | - [0;32mI (199) cpu_start: Project name: led_strip[0m |
|
| 59 | - [0;32mI (204) cpu_start: App version: 1[0m |
|
| 60 | - [0;32mI (209) cpu_start: Compile time: Aug 17 2021 17:09:47[0m |
|
| 61 | - [0;32mI (215) cpu_start: ELF file SHA256: bda59acbde3f7a0e...[0m |
|
| 62 | - [0;32mI (221) cpu_start: ESP-IDF: v4.4-dev-2594-ga20df743f1-dirty[0m |
|
| 63 | - [0;32mI (228) heap_init: Initializing. RAM available for dynamic allocation:[0m |
|
| 64 | - [0;32mI (235) heap_init: At 3FC94220 len 0004BDE0 (303 KiB): D/IRAM[0m |
|
| 65 | - [0;32mI (241) heap_init: At 3FCE0000 len 0000EE34 (59 KiB): STACK/DRAM[0m |
|
| 66 | - [0;32mI (248) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[0m |
|
| 67 | - [0;32mI (255) spi_flash: detected chip: generic[0m |
|
| 68 | - [0;32mI (259) spi_flash: flash io: dio[0m |
|
| 69 | - [0;33mW (263) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[0m |
|
| 70 | - [0;32mI (277) cpu_start: Starting scheduler on PRO CPU.[0m |
|
| 71 | - [0;32mI (0) cpu_start: Starting scheduler on APP CPU.[0m |
|
| 72 | - [0;32mI (308) example: LED Rainbow Chase Start[0m |
|
| 73 | - [0;32mI (308) example: USB initialization[0m |
|
| 74 | - [0;32mI (308) tusb_desc: |
|
| 80 | + [0;32mI (24boot: ESP-IDF v4.4-dev-2594-ga20df743f1-dirty 2nd stage bootloader[0m |
|
| 81 | + [0;32mI (25boot: compile time 16:57:21[0m |
|
| 82 | + [0;32mI (25boot: chip revision: 0[0m |
|
| 83 | + [0;32mI (28boot.esp32s3: SPI Speed : 80MHz[0m |
|
| 84 | + [0;32mI (33boot.esp32s3: SPI Mode : DIO[0m |
|
| 85 | + [0;32mI (38boot.esp32s3: SPI Flash Size : 2MB[0m |
|
| 86 | + [0;32mI (43boot: Enabling RNG early entropy source...[0m |
|
| 87 | + [0;33mW (48bootloader_random: RNG for ESP32-S3 not currently supported[0m |
|
| 88 | + [0;32mI (55boot: Partition Table:[0m |
|
| 89 | + [0;32mI (59boot: ## Label Usage Type ST Offset Length[0m |
|
| 90 | + [0;32mI (66boot: 0 nvs WiFi data 01 02 00009000 00006000[0m |
|
| 91 | + [0;32mI (73boot: 1 phy_init RF data 01 01 0000f000 00001000[0m |
|
| 92 | + [0;32mI (81boot: 2 factory factory app 00 00 00010000 00100000[0m |
|
| 93 | + [0;32mI (88boot: End of partition table[0m |
|
| 94 | + [0;32mI (92esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=090e0h ( 37088map[0m |
|
| 95 | + [0;32mI (108esp_image: segment 1: paddr=00019108 vaddr=3fc90dd0 size=0253ch ( 9532load[0m |
|
| 96 | + [0;32mI (111esp_image: segment 2: paddr=0001b64c vaddr=40374000 size=049cch ( 18892load[0m |
|
| 97 | + [0;32mI (122esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1b660h (112224map[0m |
|
| 98 | + [0;32mI (147esp_image: segment 4: paddr=0003b688 vaddr=403789cc size=08404h ( 33796load[0m |
|
| 99 | + [0;32mI (154esp_image: segment 5: paddr=00043a94 vaddr=50000000 size=00010h ( 16load[0m |
|
| 100 | + [0;32mI (160boot: Loaded app from partition at offset 0x10000[0m |
|
| 101 | + [0;32mI (160boot: Disabling RNG early entropy source...[0m |
|
| 102 | + [0;33mW (164bootloader_random: RNG for ESP32-S3 not currently supported[0m |
|
| 103 | + [0;32mI (182cpu_start: Pro cpu up.[0m |
|
| 104 | + [0;32mI (182cpu_start: Starting app cpu, entry point is 0x40375104[0m |
|
| 105 | + [0;32mI (0cpu_start: App cpu up.[0m |
|
| 106 | + [0;32mI (196cpu_start: Pro cpu start user code[0m |
|
| 107 | + [0;32mI (196cpu_start: cpu freq: 160000000[0m |
|
| 108 | + [0;32mI (196cpu_start: Application information:[0m |
|
| 109 | + [0;32mI (199cpu_start: Project name: led_strip[0m |
|
| 110 | + [0;32mI (204cpu_start: App version: 1[0m |
|
| 111 | + [0;32mI (209cpu_start: Compile time: Aug 17 2021 17:09:47[0m |
|
| 112 | + [0;32mI (215cpu_start: ELF file SHA256: bda59acbde3f7a0e...[0m |
|
| 113 | + [0;32mI (221cpu_start: ESP-IDF: v4.4-dev-2594-ga20df743f1-dirty[0m |
|
| 114 | + [0;32mI (228heap_init: Initializing. RAM available for dynamic allocation:[0m |
|
| 115 | + [0;32mI (235heap_init: At 3FC94220 len 0004BDE0 (303 KiB): D/IRAM[0m |
|
| 116 | + [0;32mI (241heap_init: At 3FCE0000 len 0000EE34 (59 KiB): STACK/DRAM[0m |
|
| 117 | + [0;32mI (248heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[0m |
|
| 118 | + [0;32mI (255spi_flash: detected chip: generic[0m |
|
| 119 | + [0;32mI (259spi_flash: flash io: dio[0m |
|
| 120 | + [0;33mW (263spi_flash: Detected size(16384klarger than the size in the binary image header(2048k). Using the size in the binary image header.[0m |
|
| 121 | + [0;32mI (277cpu_start: Starting scheduler on PRO CPU.[0m |
|
| 122 | + [0;32mI (0cpu_start: Starting scheduler on APP CPU.[0m |
|
| 123 | + [0;32mI (308example: LED Rainbow Chase Start[0m |
|
| 124 | + [0;32mI (308example: USB initialization[0m |
|
| 125 | + [0;32mI (308tusb_desc: |
|
| 75 | 126 | |
| 76 | 127 | ... |
| 77 | 128 | |
| 78 | - [0;32mI (478) TinyUSB: TinyUSB Driver installed[0m |
|
| 79 | - [0;32mI (488) example: USB initialization DONE[0m |
|
| 80 | - [0;32mI (1388) example: log -> UART[0m |
|
| 129 | + [0;32mI (478TinyUSB: TinyUSB Driver installed[0m |
|
| 130 | + [0;32mI (488example: USB initialization DONE[0m |
|
| 131 | + [0;32mI (1388example: log -> UART[0m |
|
| 81 | 132 | example: print -> stdout |
| 82 | 133 | example: print -> stderr |
| 83 | - [0;32mI (2888) example: log -> UART[0m |
|
| 134 | + [0;32mI (2888example: log -> UART[0m |
|
| 84 | 135 | example: print -> stdout |
| 85 | 136 | example: print -> stderr |
| 86 | - [0;32mI (4388) example: log -> UART[0m |
|
| 137 | + [0;32mI (4388example: log -> UART[0m |
|
| 87 | 138 | example: print -> stdout |
| 88 | 139 | example: print -> stderr |
| 89 | 140 | |
| ... | ... | @@ -91,6 +142,10 @@ |
| 91 | 142 | |
| 92 | 143 | - [[circuitpython-esp32-s3-dat]] - [[camera-sdk-dat]] |
| 93 | 144 | |
| 145 | +- [[demo1.py]] |
|
| 146 | + |
|
| 147 | + |
|
| 148 | + |
|
| 94 | 149 | |
| 95 | 150 | ## ref |
| 96 | 151 |
Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/2025-07-31-13-03-47.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/2025-07-31-13-03-47.png differ |
Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-DAT.md
| ... | ... | @@ -23,7 +23,11 @@ |
| 23 | 23 | |
| 24 | 24 | - [[JTAG-dat]] |
| 25 | 25 | |
| 26 | -IDF list |
|
| 26 | + |
|
| 27 | + |
|
| 28 | + |
|
| 29 | + |
|
| 30 | +## IDF list |
|
| 27 | 31 | |
| 28 | 32 | - ESP32-S3 chip (via builtin USB-JTAG) |
| 29 | 33 | - ESP32-S3 chip (via builtin USB-JTAG) |
Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-SDK-dat/2025-07-31-13-09-24.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-SDK-dat/2025-07-31-13-09-24.png differ |
Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-SDK-dat/2025-07-31-13-10-33.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-SDK-dat/2025-07-31-13-10-33.png differ |
Chip-cn-dat/Espressif-dat/ESP32-S3-DAT/ESP32-S3-SDK-dat/circuitpython-ESP32-s3-dat.md
| ... | ... | @@ -4,4 +4,20 @@ |
| 4 | 4 | https://circuitpython.org/board/yd_esp32_s3_n16r8/ |
| 5 | 5 | |
| 6 | 6 | |
| 7 | -- [[ESP32-S3-cam-dat]] - [[ESP32-S3-SDK-dat]] |
|
| ... | ... | \ No newline at end of file |
| 0 | +- [[ESP32-S3-cam-dat]] - [[ESP32-S3-SDK-dat]] |
|
| 1 | + |
|
| 2 | + |
|
| 3 | +## install circuitpython and find driver |
|
| 4 | + |
|
| 5 | + |
|
| 6 | + |
|
| 7 | + |
|
| 8 | +Downloading adafruit-circuitpython-yd_esp32_s3_n16r8-en_US-9.2.8.uf2... |
|
| 9 | + |
|
| 10 | + |
|
| 11 | + |
|
| 12 | + |
|
| 13 | + |
|
| 14 | +## ref |
|
| 15 | + |
|
| 16 | +- [[circuitpython-dat]] |
|
| ... | ... | \ No newline at end of file |
SDK-dat/ESP-SDK-dat/ESP-SDK-dat.md
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | - [[esp-idf-dat]] |
| 16 | 16 | |
| 17 | -- [[script-based-SDK-dat]] - [[circuitpython-dat]] - [[micropython-dat]] |
|
| 17 | +- [[script-based-SDK-dat]] - [[circuitpython-dat]] - [[circuitpython-esp32-s3-dat]] - [[micropython-dat]] |
|
| 18 | 18 | |
| 19 | 19 | - [[c-dat]] |
| 20 | 20 |
SDK-dat/ESP-SDK-dat/ESP32-SDK-dat/ESP32-debug-log-dat/ESP32-debug-log-dat.md
SDK-dat/python-dat/circuitpython-dat/adafruit_ov2640.py
| ... | ... | @@ -1,1364 +0,0 @@ |
| 1 | -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | -# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | -# |
|
| 4 | -# SPDX-License-Identifier: MIT |
|
| 5 | -""" |
|
| 6 | -`adafruit_ov2640` |
|
| 7 | -================================================================================ |
|
| 8 | - |
|
| 9 | -CircuitPython driver for OV2640 Camera. |
|
| 10 | - |
|
| 11 | - |
|
| 12 | -* Author(s): Jeff Epler |
|
| 13 | - |
|
| 14 | -Implementation Notes |
|
| 15 | --------------------- |
|
| 16 | - |
|
| 17 | -**Hardware:** |
|
| 18 | - |
|
| 19 | -* `ESP32-S2 Kaluga Dev Kit featuring ESP32-S2 WROVER <https://www.adafruit.com/product/4729>`_ |
|
| 20 | - |
|
| 21 | -**Software and Dependencies:** |
|
| 22 | - |
|
| 23 | -* Adafruit CircuitPython firmware for the supported boards: |
|
| 24 | - https://github.com/adafruit/circuitpython/releases |
|
| 25 | - |
|
| 26 | -* Adafruit's Bus Device library: https:# github.com/adafruit/Adafruit_CircuitPython_BusDevice |
|
| 27 | -""" |
|
| 28 | - |
|
| 29 | -# imports |
|
| 30 | - |
|
| 31 | -__version__ = "0.0.0+auto.0" |
|
| 32 | -__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_OV7670.git" |
|
| 33 | - |
|
| 34 | -import time |
|
| 35 | - |
|
| 36 | -import digitalio |
|
| 37 | -import imagecapture |
|
| 38 | -import pwmio |
|
| 39 | -from adafruit_bus_device.i2c_device import I2CDevice |
|
| 40 | -from micropython import const |
|
| 41 | - |
|
| 42 | -try: |
|
| 43 | - from typing import List, Optional, Type, Union |
|
| 44 | - |
|
| 45 | - from busio import I2C |
|
| 46 | - from circuitpython_typing import WriteableBuffer |
|
| 47 | - from microcontroller import Pin |
|
| 48 | -except ImportError: |
|
| 49 | - pass |
|
| 50 | - |
|
| 51 | -CTRLI = const(0x50) |
|
| 52 | -_R_BYPASS = const(0x05) |
|
| 53 | -_QS = const(0x44) |
|
| 54 | -_CTRLI = const(0x50) |
|
| 55 | -_HSIZE = const(0x51) |
|
| 56 | -_VSIZE = const(0x52) |
|
| 57 | -_XOFFL = const(0x53) |
|
| 58 | -_YOFFL = const(0x54) |
|
| 59 | -_VHYX = const(0x55) |
|
| 60 | -_DPRP = const(0x56) |
|
| 61 | -_TEST = const(0x57) |
|
| 62 | -_ZMOW = const(0x5A) |
|
| 63 | -_ZMOH = const(0x5B) |
|
| 64 | -_ZMHH = const(0x5C) |
|
| 65 | -_BPADDR = const(0x7C) |
|
| 66 | -_BPDATA = const(0x7D) |
|
| 67 | -_CTRL2 = const(0x86) |
|
| 68 | -_CTRL3 = const(0x87) |
|
| 69 | -_SIZEL = const(0x8C) |
|
| 70 | -_HSIZE8 = const(0xC0) |
|
| 71 | -_VSIZE8 = const(0xC1) |
|
| 72 | -_CTRL0 = const(0xC2) |
|
| 73 | -_CTRL1 = const(0xC3) |
|
| 74 | -_R_DVP_SP = const(0xD3) |
|
| 75 | -_IMAGE_MODE = const(0xDA) |
|
| 76 | -_RESET = const(0xE0) |
|
| 77 | -_MS_SP = const(0xF0) |
|
| 78 | -_SS_ID = const(0xF7) |
|
| 79 | -_SS_CTRL = const(0xF7) |
|
| 80 | -_MC_BIST = const(0xF9) |
|
| 81 | -_MC_AL = const(0xFA) |
|
| 82 | -_MC_AH = const(0xFB) |
|
| 83 | -_MC_D = const(0xFC) |
|
| 84 | -_P_CMD = const(0xFD) |
|
| 85 | -_P_STATUS = const(0xFE) |
|
| 86 | -_BANK_SEL = const(0xFF) |
|
| 87 | - |
|
| 88 | -_CTRLI_LP_DP = const(0x80) |
|
| 89 | -_CTRLI_ROUND = const(0x40) |
|
| 90 | - |
|
| 91 | -_CTRL0_AEC_EN = const(0x80) |
|
| 92 | -_CTRL0_AEC_SEL = const(0x40) |
|
| 93 | -_CTRL0_STAT_SEL = const(0x20) |
|
| 94 | -_CTRL0_VFIRST = const(0x10) |
|
| 95 | -_CTRL0_YUV422 = const(0x08) |
|
| 96 | -_CTRL0_YUV_EN = const(0x04) |
|
| 97 | -_CTRL0_RGB_EN = const(0x02) |
|
| 98 | -_CTRL0_RAW_EN = const(0x01) |
|
| 99 | - |
|
| 100 | -_CTRL2_DCW_EN = const(0x20) |
|
| 101 | -_CTRL2_SDE_EN = const(0x10) |
|
| 102 | -_CTRL2_UV_ADJ_EN = const(0x08) |
|
| 103 | -_CTRL2_UV_AVG_EN = const(0x04) |
|
| 104 | -_CTRL2_CMX_EN = const(0x01) |
|
| 105 | - |
|
| 106 | -_CTRL3_BPC_EN = const(0x80) |
|
| 107 | -_CTRL3_WPC_EN = const(0x40) |
|
| 108 | - |
|
| 109 | -_R_DVP_SP_AUTO_MODE = const(0x80) |
|
| 110 | - |
|
| 111 | -_R_BYPASS_DSP_EN = const(0x00) |
|
| 112 | -_R_BYPASS_DSP_BYPAS = const(0x01) |
|
| 113 | - |
|
| 114 | -OV2640_COLOR_RGB = 0 |
|
| 115 | -OV2640_COLOR_YUV = 1 |
|
| 116 | -OV2640_COLOR_JPEG = 2 |
|
| 117 | - |
|
| 118 | -_IMAGE_MODE_Y8_DVP_EN = const(0x40) |
|
| 119 | -_IMAGE_MODE_JPEG_EN = const(0x10) |
|
| 120 | -_IMAGE_MODE_YUV422 = const(0x00) |
|
| 121 | -_IMAGE_MODE_RAW10 = const(0x04) |
|
| 122 | -_IMAGE_MODE_RGB565 = const(0x08) |
|
| 123 | -_IMAGE_MODE_HREF_VSYNC = const(0x02) |
|
| 124 | -_IMAGE_MODE_LBYTE_FIRST = const(0x01) |
|
| 125 | - |
|
| 126 | -_RESET_MICROC = const(0x40) |
|
| 127 | -_RESET_SCCB = const(0x20) |
|
| 128 | -_RESET_JPEG = const(0x10) |
|
| 129 | -_RESET_DVP = const(0x04) |
|
| 130 | -_RESET_IPU = const(0x02) |
|
| 131 | -_RESET_CIF = const(0x01) |
|
| 132 | - |
|
| 133 | -_MC_BIST_RESET = const(0x80) |
|
| 134 | -_MC_BIST_BOOT_ROM_SEL = const(0x40) |
|
| 135 | -_MC_BIST_12KB_SEL = const(0x20) |
|
| 136 | -_MC_BIST_12KB_MASK = const(0x30) |
|
| 137 | -_MC_BIST_512KB_SEL = const(0x08) |
|
| 138 | -_MC_BIST_512KB_MASK = const(0x0C) |
|
| 139 | -_MC_BIST_BUSY_BIT_R = const(0x02) |
|
| 140 | -_MC_BIST_MC_RES_ONE_SH_W = const(0x02) |
|
| 141 | -_MC_BIST_LAUNCH = const(0x01) |
|
| 142 | - |
|
| 143 | - |
|
| 144 | -_BANK_DSP = const(0) |
|
| 145 | -_BANK_SENSOR = const(1) |
|
| 146 | - |
|
| 147 | -# Sensor register bank FF=0x01 |
|
| 148 | -_GAIN = const(0x00) |
|
| 149 | -_COM1 = const(0x03) |
|
| 150 | -_REG04 = const(0x04) |
|
| 151 | -_REG08 = const(0x08) |
|
| 152 | -_COM2 = const(0x09) |
|
| 153 | -_REG_PID = const(0x0A) |
|
| 154 | -_REG_VER = const(0x0B) |
|
| 155 | -_COM3 = const(0x0C) |
|
| 156 | -_COM4 = const(0x0D) |
|
| 157 | -_AEC = const(0x10) |
|
| 158 | -_CLKRC = const(0x11) |
|
| 159 | -_COM7 = const(0x12) |
|
| 160 | -_COM8 = const(0x13) |
|
| 161 | -_COM9 = const(0x14) # AGC gain ceiling |
|
| 162 | -_COM10 = const(0x15) |
|
| 163 | -_HSTART = const(0x17) |
|
| 164 | -_HSTOP = const(0x18) |
|
| 165 | -_VSTART = const(0x19) |
|
| 166 | -_VSTOP = const(0x1A) |
|
| 167 | -_MIDH = const(0x1C) |
|
| 168 | -_MIDL = const(0x1D) |
|
| 169 | -_AEW = const(0x24) |
|
| 170 | -_AEB = const(0x25) |
|
| 171 | -_VV = const(0x26) |
|
| 172 | -_REG2A = const(0x2A) |
|
| 173 | -_FRARL = const(0x2B) |
|
| 174 | -_ADDVSL = const(0x2D) |
|
| 175 | -_ADDVSH = const(0x2E) |
|
| 176 | -_YAVG = const(0x2F) |
|
| 177 | -_HSDY = const(0x30) |
|
| 178 | -_HEDY = const(0x31) |
|
| 179 | -_REG32 = const(0x32) |
|
| 180 | -_ARCOM2 = const(0x34) |
|
| 181 | -_REG45 = const(0x45) |
|
| 182 | -_FLL = const(0x46) |
|
| 183 | -_FLH = const(0x47) |
|
| 184 | -_COM19 = const(0x48) |
|
| 185 | -_ZOOMS = const(0x49) |
|
| 186 | -_COM22 = const(0x4B) |
|
| 187 | -_COM25 = const(0x4E) |
|
| 188 | -_BD50 = const(0x4F) |
|
| 189 | -_BD60 = const(0x50) |
|
| 190 | -_REG5D = const(0x5D) |
|
| 191 | -_REG5E = const(0x5E) |
|
| 192 | -_REG5F = const(0x5F) |
|
| 193 | -_REG60 = const(0x60) |
|
| 194 | -_HISTO_LOW = const(0x61) |
|
| 195 | -_HISTO_HIGH = const(0x62) |
|
| 196 | - |
|
| 197 | -_REG04_DEFAULT = const(0x28) |
|
| 198 | -_REG04_HFLIP_IMG = const(0x80) |
|
| 199 | -_REG04_VFLIP_IMG = const(0x40) |
|
| 200 | -_REG04_VREF_EN = const(0x10) |
|
| 201 | -_REG04_HREF_EN = const(0x08) |
|
| 202 | -_REG04_SET = lambda x: (_REG04_DEFAULT | x) |
|
| 203 | - |
|
| 204 | -_COM2_STDBY = const(0x10) |
|
| 205 | -_COM2_OUT_DRIVE_1x = const(0x00) |
|
| 206 | -_COM2_OUT_DRIVE_2x = const(0x01) |
|
| 207 | -_COM2_OUT_DRIVE_3x = const(0x02) |
|
| 208 | -_COM2_OUT_DRIVE_4x = const(0x03) |
|
| 209 | - |
|
| 210 | -_COM3_DEFAULT = const(0x38) |
|
| 211 | -_COM3_BAND_50Hz = const(0x04) |
|
| 212 | -_COM3_BAND_60Hz = const(0x00) |
|
| 213 | -_COM3_BAND_AUTO = const(0x02) |
|
| 214 | -_COM3_BAND_SET = lambda x: (_COM3_DEFAULT | x) |
|
| 215 | - |
|
| 216 | -_COM7_SRST = const(0x80) |
|
| 217 | -_COM7_RES_UXGA = const(0x00) # UXGA |
|
| 218 | -_COM7_RES_SVGA = const(0x40) # SVGA |
|
| 219 | -_COM7_RES_CIF = const(0x20) # CIF |
|
| 220 | -_COM7_ZOOM_EN = const(0x04) # Enable Zoom |
|
| 221 | -_COM7_COLOR_BAR = const(0x02) # Enable Color Bar Test |
|
| 222 | - |
|
| 223 | -_COM8_DEFAULT = const(0xC0) |
|
| 224 | -_COM8_BNDF_EN = const(0x20) # Enable Banding filter |
|
| 225 | -_COM8_AGC_EN = const(0x04) # AGC Auto/Manual control selection |
|
| 226 | -_COM8_AEC_EN = const(0x01) # Auto/Manual Exposure control |
|
| 227 | -_COM8_SET = lambda x: (_COM8_DEFAULT | x) |
|
| 228 | - |
|
| 229 | -_COM9_DEFAULT = const(0x08) |
|
| 230 | -_COM9_AGC_GAIN_2x = const(0x00) # AGC: 2x |
|
| 231 | -_COM9_AGC_GAIN_4x = const(0x01) # AGC: 4x |
|
| 232 | -_COM9_AGC_GAIN_8x = const(0x02) # AGC: 8x |
|
| 233 | -_COM9_AGC_GAIN_16x = const(0x03) # AGC: 16x |
|
| 234 | -_COM9_AGC_GAIN_32x = const(0x04) # AGC: 32x |
|
| 235 | -_COM9_AGC_GAIN_64x = const(0x05) # AGC: 64x |
|
| 236 | -_COM9_AGC_GAIN_128x = const(0x06) # AGC: 128x |
|
| 237 | -_COM9_AGC_SET = lambda x: (_COM9_DEFAULT | (x << 5)) |
|
| 238 | - |
|
| 239 | -_COM10_HREF_EN = const(0x80) # HSYNC changes to HREF |
|
| 240 | -_COM10_HSYNC_EN = const(0x40) # HREF changes to HSYNC |
|
| 241 | -_COM10_PCLK_FREE = const(0x20) # PCLK output option: free running PCLK |
|
| 242 | -_COM10_PCLK_EDGE = const(0x10) # Data is updated at the rising edge of PCLK |
|
| 243 | -_COM10_HREF_NEG = const(0x08) # HREF negative |
|
| 244 | -_COM10_VSYNC_NEG = const(0x02) # VSYNC negative |
|
| 245 | -_COM10_HSYNC_NEG = const(0x01) # HSYNC negative |
|
| 246 | - |
|
| 247 | -_CTRL1_AWB = const(0x08) # Enable AWB |
|
| 248 | - |
|
| 249 | -_VV_AGC_TH_SET = lambda h, l: ((h << 4) | (l & 0x0F)) |
|
| 250 | - |
|
| 251 | -_REG32_UXGA = const(0x36) |
|
| 252 | -_REG32_SVGA = const(0x09) |
|
| 253 | -_REG32_CIF = const(0x89) |
|
| 254 | - |
|
| 255 | -_CLKRC_2X = const(0x80) |
|
| 256 | -_CLKRC_2X_UXGA = const(0x01 | _CLKRC_2X) |
|
| 257 | -_CLKRC_2X_SVGA = _CLKRC_2X |
|
| 258 | -_CLKRC_2X_CIF = _CLKRC_2X |
|
| 259 | - |
|
| 260 | -_OV2640_MODE_CIF = const(0) |
|
| 261 | -_OV2640_MODE_SVGA = const(1) |
|
| 262 | -_OV2640_MODE_UXGA = const(2) |
|
| 263 | - |
|
| 264 | -OV2640_SIZE_96X96 = 0 # 96x96 |
|
| 265 | -OV2640_SIZE_QQVGA = 1 # 160x120 |
|
| 266 | -OV2640_SIZE_QCIF = 2 # 176x144 |
|
| 267 | -OV2640_SIZE_HQVGA = 3 # 240x176 |
|
| 268 | -OV2640_SIZE_240X240 = 4 # 240x240 |
|
| 269 | -OV2640_SIZE_QVGA = 5 # 320x240 |
|
| 270 | -OV2640_SIZE_CIF = 6 # 400x296 |
|
| 271 | -OV2640_SIZE_HVGA = 7 # 480x320 |
|
| 272 | -OV2640_SIZE_VGA = 8 # 640x480 |
|
| 273 | -OV2640_SIZE_SVGA = 9 # 800x600 |
|
| 274 | -OV2640_SIZE_XGA = 10 # 1024x768 |
|
| 275 | -OV2640_SIZE_HD = 11 # 1280x720 |
|
| 276 | -OV2640_SIZE_SXGA = 12 # 1280x1024 |
|
| 277 | -OV2640_SIZE_UXGA = 13 # 1600x1200 |
|
| 278 | - |
|
| 279 | -_ASPECT_RATIO_4X3 = const(0) |
|
| 280 | -_ASPECT_RATIO_3X2 = const(1) |
|
| 281 | -_ASPECT_RATIO_16X10 = const(2) |
|
| 282 | -_ASPECT_RATIO_5X3 = const(3) |
|
| 283 | -_ASPECT_RATIO_16X9 = const(4) |
|
| 284 | -_ASPECT_RATIO_21X9 = const(5) |
|
| 285 | -_ASPECT_RATIO_5X4 = const(6) |
|
| 286 | -_ASPECT_RATIO_1X1 = const(7) |
|
| 287 | -_ASPECT_RATIO_9X16 = const(8) |
|
| 288 | - |
|
| 289 | -_resolution_info = [ |
|
| 290 | - [96, 96, _ASPECT_RATIO_1X1], # 96x96 |
|
| 291 | - [160, 120, _ASPECT_RATIO_4X3], # QQVGA |
|
| 292 | - [176, 144, _ASPECT_RATIO_5X4], # QCIF |
|
| 293 | - [240, 176, _ASPECT_RATIO_4X3], # HQVGA |
|
| 294 | - [240, 240, _ASPECT_RATIO_1X1], # 240x240 |
|
| 295 | - [320, 240, _ASPECT_RATIO_4X3], # QVGA |
|
| 296 | - [400, 296, _ASPECT_RATIO_4X3], # CIF |
|
| 297 | - [480, 320, _ASPECT_RATIO_3X2], # HVGA |
|
| 298 | - [640, 480, _ASPECT_RATIO_4X3], # VGA |
|
| 299 | - [800, 600, _ASPECT_RATIO_4X3], # SVGA |
|
| 300 | - [1024, 768, _ASPECT_RATIO_4X3], # XGA |
|
| 301 | - [1280, 720, _ASPECT_RATIO_16X9], # HD |
|
| 302 | - [1280, 1024, _ASPECT_RATIO_5X4], # SXGA |
|
| 303 | - [1600, 1200, _ASPECT_RATIO_4X3], # UXGA |
|
| 304 | -] |
|
| 305 | - |
|
| 306 | -_ratio_table = [ |
|
| 307 | - # ox, oy, mx, my |
|
| 308 | - [0, 0, 1600, 1200], # 4x3 |
|
| 309 | - [8, 72, 1584, 1056], # 3x2 |
|
| 310 | - [0, 100, 1600, 1000], # 16x10 |
|
| 311 | - [0, 120, 1600, 960], # 5x3 |
|
| 312 | - [0, 150, 1600, 900], # 16x9 |
|
| 313 | - [2, 258, 1596, 684], # 21x9 |
|
| 314 | - [50, 0, 1500, 1200], # 5x4 |
|
| 315 | - [200, 0, 1200, 1200], # 1x1 |
|
| 316 | - [462, 0, 676, 1200], # 9x16 |
|
| 317 | -] |
|
| 318 | - |
|
| 319 | -# 30fps@24MHz |
|
| 320 | -_ov2640_settings_cif = bytes( |
|
| 321 | - [ |
|
| 322 | - _BANK_SEL, |
|
| 323 | - _BANK_DSP, |
|
| 324 | - 0x2C, |
|
| 325 | - 0xFF, |
|
| 326 | - 0x2E, |
|
| 327 | - 0xDF, |
|
| 328 | - _BANK_SEL, |
|
| 329 | - _BANK_SENSOR, |
|
| 330 | - 0x3C, |
|
| 331 | - 0x32, |
|
| 332 | - _CLKRC, |
|
| 333 | - 0x01, |
|
| 334 | - _COM2, |
|
| 335 | - _COM2_OUT_DRIVE_3x, |
|
| 336 | - _REG04, |
|
| 337 | - _REG04_DEFAULT, |
|
| 338 | - _COM8, |
|
| 339 | - _COM8_DEFAULT | _COM8_BNDF_EN | _COM8_AGC_EN | _COM8_AEC_EN, |
|
| 340 | - _COM9, |
|
| 341 | - _COM9_AGC_SET(_COM9_AGC_GAIN_8x), |
|
| 342 | - 0x2C, |
|
| 343 | - 0x0C, |
|
| 344 | - 0x33, |
|
| 345 | - 0x78, |
|
| 346 | - 0x3A, |
|
| 347 | - 0x33, |
|
| 348 | - 0x3B, |
|
| 349 | - 0xFB, |
|
| 350 | - 0x3E, |
|
| 351 | - 0x00, |
|
| 352 | - 0x43, |
|
| 353 | - 0x11, |
|
| 354 | - 0x16, |
|
| 355 | - 0x10, |
|
| 356 | - 0x39, |
|
| 357 | - 0x92, |
|
| 358 | - 0x35, |
|
| 359 | - 0xDA, |
|
| 360 | - 0x22, |
|
| 361 | - 0x1A, |
|
| 362 | - 0x37, |
|
| 363 | - 0xC3, |
|
| 364 | - 0x23, |
|
| 365 | - 0x00, |
|
| 366 | - _ARCOM2, |
|
| 367 | - 0xC0, |
|
| 368 | - 0x06, |
|
| 369 | - 0x88, |
|
| 370 | - 0x07, |
|
| 371 | - 0xC0, |
|
| 372 | - _COM4, |
|
| 373 | - 0x87, |
|
| 374 | - 0x0E, |
|
| 375 | - 0x41, |
|
| 376 | - 0x4C, |
|
| 377 | - 0x00, |
|
| 378 | - 0x4A, |
|
| 379 | - 0x81, |
|
| 380 | - 0x21, |
|
| 381 | - 0x99, |
|
| 382 | - _AEW, |
|
| 383 | - 0x40, |
|
| 384 | - _AEB, |
|
| 385 | - 0x38, |
|
| 386 | - _VV, |
|
| 387 | - _VV_AGC_TH_SET(8, 2), |
|
| 388 | - 0x5C, |
|
| 389 | - 0x00, |
|
| 390 | - 0x63, |
|
| 391 | - 0x00, |
|
| 392 | - _HISTO_LOW, |
|
| 393 | - 0x70, |
|
| 394 | - _HISTO_HIGH, |
|
| 395 | - 0x80, |
|
| 396 | - 0x7C, |
|
| 397 | - 0x05, |
|
| 398 | - 0x20, |
|
| 399 | - 0x80, |
|
| 400 | - 0x28, |
|
| 401 | - 0x30, |
|
| 402 | - 0x6C, |
|
| 403 | - 0x00, |
|
| 404 | - 0x6D, |
|
| 405 | - 0x80, |
|
| 406 | - 0x6E, |
|
| 407 | - 0x00, |
|
| 408 | - 0x70, |
|
| 409 | - 0x02, |
|
| 410 | - 0x71, |
|
| 411 | - 0x94, |
|
| 412 | - 0x73, |
|
| 413 | - 0xC1, |
|
| 414 | - 0x3D, |
|
| 415 | - 0x34, |
|
| 416 | - 0x5A, |
|
| 417 | - 0x57, |
|
| 418 | - _BD50, |
|
| 419 | - 0xBB, |
|
| 420 | - _BD60, |
|
| 421 | - 0x9C, |
|
| 422 | - _COM7, |
|
| 423 | - _COM7_RES_CIF, |
|
| 424 | - _HSTART, |
|
| 425 | - 0x11, |
|
| 426 | - _HSTOP, |
|
| 427 | - 0x43, |
|
| 428 | - _VSTART, |
|
| 429 | - 0x00, |
|
| 430 | - _VSTOP, |
|
| 431 | - 0x25, |
|
| 432 | - _REG32, |
|
| 433 | - 0x89, |
|
| 434 | - 0x37, |
|
| 435 | - 0xC0, |
|
| 436 | - _BD50, |
|
| 437 | - 0xCA, |
|
| 438 | - _BD60, |
|
| 439 | - 0xA8, |
|
| 440 | - 0x6D, |
|
| 441 | - 0x00, |
|
| 442 | - 0x3D, |
|
| 443 | - 0x38, |
|
| 444 | - _BANK_SEL, |
|
| 445 | - _BANK_DSP, |
|
| 446 | - 0xE5, |
|
| 447 | - 0x7F, |
|
| 448 | - _MC_BIST, |
|
| 449 | - _MC_BIST_RESET | _MC_BIST_BOOT_ROM_SEL, |
|
| 450 | - 0x41, |
|
| 451 | - 0x24, |
|
| 452 | - _RESET, |
|
| 453 | - _RESET_JPEG | _RESET_DVP, |
|
| 454 | - 0x76, |
|
| 455 | - 0xFF, |
|
| 456 | - 0x33, |
|
| 457 | - 0xA0, |
|
| 458 | - 0x42, |
|
| 459 | - 0x20, |
|
| 460 | - 0x43, |
|
| 461 | - 0x18, |
|
| 462 | - 0x4C, |
|
| 463 | - 0x00, |
|
| 464 | - _CTRL3, |
|
| 465 | - _CTRL3_WPC_EN | 0x10, |
|
| 466 | - 0x88, |
|
| 467 | - 0x3F, |
|
| 468 | - 0xD7, |
|
| 469 | - 0x03, |
|
| 470 | - 0xD9, |
|
| 471 | - 0x10, |
|
| 472 | - _R_DVP_SP, |
|
| 473 | - _R_DVP_SP_AUTO_MODE | 0x02, |
|
| 474 | - 0xC8, |
|
| 475 | - 0x08, |
|
| 476 | - 0xC9, |
|
| 477 | - 0x80, |
|
| 478 | - _BPADDR, |
|
| 479 | - 0x00, |
|
| 480 | - _BPDATA, |
|
| 481 | - 0x00, |
|
| 482 | - _BPADDR, |
|
| 483 | - 0x03, |
|
| 484 | - _BPDATA, |
|
| 485 | - 0x48, |
|
| 486 | - _BPDATA, |
|
| 487 | - 0x48, |
|
| 488 | - _BPADDR, |
|
| 489 | - 0x08, |
|
| 490 | - _BPDATA, |
|
| 491 | - 0x20, |
|
| 492 | - _BPDATA, |
|
| 493 | - 0x10, |
|
| 494 | - _BPDATA, |
|
| 495 | - 0x0E, |
|
| 496 | - 0x90, |
|
| 497 | - 0x00, |
|
| 498 | - 0x91, |
|
| 499 | - 0x0E, |
|
| 500 | - 0x91, |
|
| 501 | - 0x1A, |
|
| 502 | - 0x91, |
|
| 503 | - 0x31, |
|
| 504 | - 0x91, |
|
| 505 | - 0x5A, |
|
| 506 | - 0x91, |
|
| 507 | - 0x69, |
|
| 508 | - 0x91, |
|
| 509 | - 0x75, |
|
| 510 | - 0x91, |
|
| 511 | - 0x7E, |
|
| 512 | - 0x91, |
|
| 513 | - 0x88, |
|
| 514 | - 0x91, |
|
| 515 | - 0x8F, |
|
| 516 | - 0x91, |
|
| 517 | - 0x96, |
|
| 518 | - 0x91, |
|
| 519 | - 0xA3, |
|
| 520 | - 0x91, |
|
| 521 | - 0xAF, |
|
| 522 | - 0x91, |
|
| 523 | - 0xC4, |
|
| 524 | - 0x91, |
|
| 525 | - 0xD7, |
|
| 526 | - 0x91, |
|
| 527 | - 0xE8, |
|
| 528 | - 0x91, |
|
| 529 | - 0x20, |
|
| 530 | - 0x92, |
|
| 531 | - 0x00, |
|
| 532 | - 0x93, |
|
| 533 | - 0x06, |
|
| 534 | - 0x93, |
|
| 535 | - 0xE3, |
|
| 536 | - 0x93, |
|
| 537 | - 0x05, |
|
| 538 | - 0x93, |
|
| 539 | - 0x05, |
|
| 540 | - 0x93, |
|
| 541 | - 0x00, |
|
| 542 | - 0x93, |
|
| 543 | - 0x04, |
|
| 544 | - 0x93, |
|
| 545 | - 0x00, |
|
| 546 | - 0x93, |
|
| 547 | - 0x00, |
|
| 548 | - 0x93, |
|
| 549 | - 0x00, |
|
| 550 | - 0x93, |
|
| 551 | - 0x00, |
|
| 552 | - 0x93, |
|
| 553 | - 0x00, |
|
| 554 | - 0x93, |
|
| 555 | - 0x00, |
|
| 556 | - 0x93, |
|
| 557 | - 0x00, |
|
| 558 | - 0x96, |
|
| 559 | - 0x00, |
|
| 560 | - 0x97, |
|
| 561 | - 0x08, |
|
| 562 | - 0x97, |
|
| 563 | - 0x19, |
|
| 564 | - 0x97, |
|
| 565 | - 0x02, |
|
| 566 | - 0x97, |
|
| 567 | - 0x0C, |
|
| 568 | - 0x97, |
|
| 569 | - 0x24, |
|
| 570 | - 0x97, |
|
| 571 | - 0x30, |
|
| 572 | - 0x97, |
|
| 573 | - 0x28, |
|
| 574 | - 0x97, |
|
| 575 | - 0x26, |
|
| 576 | - 0x97, |
|
| 577 | - 0x02, |
|
| 578 | - 0x97, |
|
| 579 | - 0x98, |
|
| 580 | - 0x97, |
|
| 581 | - 0x80, |
|
| 582 | - 0x97, |
|
| 583 | - 0x00, |
|
| 584 | - 0x97, |
|
| 585 | - 0x00, |
|
| 586 | - 0xA4, |
|
| 587 | - 0x00, |
|
| 588 | - 0xA8, |
|
| 589 | - 0x00, |
|
| 590 | - 0xC5, |
|
| 591 | - 0x11, |
|
| 592 | - 0xC6, |
|
| 593 | - 0x51, |
|
| 594 | - 0xBF, |
|
| 595 | - 0x80, |
|
| 596 | - 0xC7, |
|
| 597 | - 0x10, |
|
| 598 | - 0xB6, |
|
| 599 | - 0x66, |
|
| 600 | - 0xB8, |
|
| 601 | - 0xA5, |
|
| 602 | - 0xB7, |
|
| 603 | - 0x64, |
|
| 604 | - 0xB9, |
|
| 605 | - 0x7C, |
|
| 606 | - 0xB3, |
|
| 607 | - 0xAF, |
|
| 608 | - 0xB4, |
|
| 609 | - 0x97, |
|
| 610 | - 0xB5, |
|
| 611 | - 0xFF, |
|
| 612 | - 0xB0, |
|
| 613 | - 0xC5, |
|
| 614 | - 0xB1, |
|
| 615 | - 0x94, |
|
| 616 | - 0xB2, |
|
| 617 | - 0x0F, |
|
| 618 | - 0xC4, |
|
| 619 | - 0x5C, |
|
| 620 | - _CTRL1, |
|
| 621 | - 0xFD, |
|
| 622 | - 0x7F, |
|
| 623 | - 0x00, |
|
| 624 | - 0xE5, |
|
| 625 | - 0x1F, |
|
| 626 | - 0xE1, |
|
| 627 | - 0x67, |
|
| 628 | - 0xDD, |
|
| 629 | - 0x7F, |
|
| 630 | - _IMAGE_MODE, |
|
| 631 | - 0x00, |
|
| 632 | - _RESET, |
|
| 633 | - 0x00, |
|
| 634 | - _R_BYPASS, |
|
| 635 | - _R_BYPASS_DSP_EN, |
|
| 636 | - ] |
|
| 637 | -) |
|
| 638 | - |
|
| 639 | -_ov2640_settings_to_cif = bytes( |
|
| 640 | - [ |
|
| 641 | - _BANK_SEL, |
|
| 642 | - _BANK_SENSOR, |
|
| 643 | - _COM7, |
|
| 644 | - _COM7_RES_CIF, |
|
| 645 | - # Set the sensor output window |
|
| 646 | - _COM1, |
|
| 647 | - 0x0A, |
|
| 648 | - _REG32, |
|
| 649 | - _REG32_CIF, |
|
| 650 | - _HSTART, |
|
| 651 | - 0x11, |
|
| 652 | - _HSTOP, |
|
| 653 | - 0x43, |
|
| 654 | - _VSTART, |
|
| 655 | - 0x00, |
|
| 656 | - _VSTOP, |
|
| 657 | - 0x25, |
|
| 658 | - # _CLKRC, 0x00, |
|
| 659 | - _BD50, |
|
| 660 | - 0xCA, |
|
| 661 | - _BD60, |
|
| 662 | - 0xA8, |
|
| 663 | - 0x5A, |
|
| 664 | - 0x23, |
|
| 665 | - 0x6D, |
|
| 666 | - 0x00, |
|
| 667 | - 0x3D, |
|
| 668 | - 0x38, |
|
| 669 | - 0x39, |
|
| 670 | - 0x92, |
|
| 671 | - 0x35, |
|
| 672 | - 0xDA, |
|
| 673 | - 0x22, |
|
| 674 | - 0x1A, |
|
| 675 | - 0x37, |
|
| 676 | - 0xC3, |
|
| 677 | - 0x23, |
|
| 678 | - 0x00, |
|
| 679 | - _ARCOM2, |
|
| 680 | - 0xC0, |
|
| 681 | - 0x06, |
|
| 682 | - 0x88, |
|
| 683 | - 0x07, |
|
| 684 | - 0xC0, |
|
| 685 | - _COM4, |
|
| 686 | - 0x87, |
|
| 687 | - 0x0E, |
|
| 688 | - 0x41, |
|
| 689 | - 0x4C, |
|
| 690 | - 0x00, |
|
| 691 | - _BANK_SEL, |
|
| 692 | - _BANK_DSP, |
|
| 693 | - _RESET, |
|
| 694 | - _RESET_DVP, |
|
| 695 | - # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 696 | - _HSIZE8, |
|
| 697 | - 0x32, |
|
| 698 | - _VSIZE8, |
|
| 699 | - 0x25, |
|
| 700 | - _SIZEL, |
|
| 701 | - 0x00, |
|
| 702 | - # Set the image window size >= output size |
|
| 703 | - _HSIZE, |
|
| 704 | - 0x64, |
|
| 705 | - _VSIZE, |
|
| 706 | - 0x4A, |
|
| 707 | - _XOFFL, |
|
| 708 | - 0x00, |
|
| 709 | - _YOFFL, |
|
| 710 | - 0x00, |
|
| 711 | - _VHYX, |
|
| 712 | - 0x00, |
|
| 713 | - _TEST, |
|
| 714 | - 0x00, |
|
| 715 | - _CTRL2, |
|
| 716 | - _CTRL2_DCW_EN | 0x1D, |
|
| 717 | - _CTRLI, |
|
| 718 | - _CTRLI_LP_DP | 0x00, |
|
| 719 | - # _R_DVP_SP, 0x08, |
|
| 720 | - ] |
|
| 721 | -) |
|
| 722 | - |
|
| 723 | -_ov2640_settings_to_svga = bytes( |
|
| 724 | - [ |
|
| 725 | - _BANK_SEL, |
|
| 726 | - _BANK_SENSOR, |
|
| 727 | - _COM7, |
|
| 728 | - _COM7_RES_SVGA, |
|
| 729 | - # Set the sensor output window |
|
| 730 | - _COM1, |
|
| 731 | - 0x0A, |
|
| 732 | - _REG32, |
|
| 733 | - _REG32_SVGA, |
|
| 734 | - _HSTART, |
|
| 735 | - 0x11, |
|
| 736 | - _HSTOP, |
|
| 737 | - 0x43, |
|
| 738 | - _VSTART, |
|
| 739 | - 0x00, |
|
| 740 | - _VSTOP, |
|
| 741 | - 0x4B, |
|
| 742 | - # _CLKRC, 0x00, |
|
| 743 | - 0x37, |
|
| 744 | - 0xC0, |
|
| 745 | - _BD50, |
|
| 746 | - 0xCA, |
|
| 747 | - _BD60, |
|
| 748 | - 0xA8, |
|
| 749 | - 0x5A, |
|
| 750 | - 0x23, |
|
| 751 | - 0x6D, |
|
| 752 | - 0x00, |
|
| 753 | - 0x3D, |
|
| 754 | - 0x38, |
|
| 755 | - 0x39, |
|
| 756 | - 0x92, |
|
| 757 | - 0x35, |
|
| 758 | - 0xDA, |
|
| 759 | - 0x22, |
|
| 760 | - 0x1A, |
|
| 761 | - 0x37, |
|
| 762 | - 0xC3, |
|
| 763 | - 0x23, |
|
| 764 | - 0x00, |
|
| 765 | - _ARCOM2, |
|
| 766 | - 0xC0, |
|
| 767 | - 0x06, |
|
| 768 | - 0x88, |
|
| 769 | - 0x07, |
|
| 770 | - 0xC0, |
|
| 771 | - _COM4, |
|
| 772 | - 0x87, |
|
| 773 | - 0x0E, |
|
| 774 | - 0x41, |
|
| 775 | - 0x42, |
|
| 776 | - 0x03, |
|
| 777 | - 0x4C, |
|
| 778 | - 0x00, |
|
| 779 | - _BANK_SEL, |
|
| 780 | - _BANK_DSP, |
|
| 781 | - _RESET, |
|
| 782 | - _RESET_DVP, |
|
| 783 | - # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 784 | - _HSIZE8, |
|
| 785 | - 0x64, |
|
| 786 | - _VSIZE8, |
|
| 787 | - 0x4B, |
|
| 788 | - _SIZEL, |
|
| 789 | - 0x00, |
|
| 790 | - # Set the image window size >= output size |
|
| 791 | - _HSIZE, |
|
| 792 | - 0xC8, |
|
| 793 | - _VSIZE, |
|
| 794 | - 0x96, |
|
| 795 | - _XOFFL, |
|
| 796 | - 0x00, |
|
| 797 | - _YOFFL, |
|
| 798 | - 0x00, |
|
| 799 | - _VHYX, |
|
| 800 | - 0x00, |
|
| 801 | - _TEST, |
|
| 802 | - 0x00, |
|
| 803 | - _CTRL2, |
|
| 804 | - _CTRL2_DCW_EN | 0x1D, |
|
| 805 | - _CTRLI, |
|
| 806 | - _CTRLI_LP_DP | 0x00, |
|
| 807 | - # _R_DVP_SP, 0x08, |
|
| 808 | - ] |
|
| 809 | -) |
|
| 810 | - |
|
| 811 | -_ov2640_settings_to_uxga = bytes( |
|
| 812 | - [ |
|
| 813 | - _BANK_SEL, |
|
| 814 | - _BANK_SENSOR, |
|
| 815 | - _COM7, |
|
| 816 | - _COM7_RES_UXGA, |
|
| 817 | - # Set the sensor output window |
|
| 818 | - _COM1, |
|
| 819 | - 0x0F, |
|
| 820 | - _REG32, |
|
| 821 | - _REG32_UXGA, |
|
| 822 | - _HSTART, |
|
| 823 | - 0x11, |
|
| 824 | - _HSTOP, |
|
| 825 | - 0x75, |
|
| 826 | - _VSTART, |
|
| 827 | - 0x01, |
|
| 828 | - _VSTOP, |
|
| 829 | - 0x97, |
|
| 830 | - # _CLKRC, 0x00, |
|
| 831 | - 0x3D, |
|
| 832 | - 0x34, |
|
| 833 | - _BD50, |
|
| 834 | - 0xBB, |
|
| 835 | - _BD60, |
|
| 836 | - 0x9C, |
|
| 837 | - 0x5A, |
|
| 838 | - 0x57, |
|
| 839 | - 0x6D, |
|
| 840 | - 0x80, |
|
| 841 | - 0x39, |
|
| 842 | - 0x82, |
|
| 843 | - 0x23, |
|
| 844 | - 0x00, |
|
| 845 | - 0x07, |
|
| 846 | - 0xC0, |
|
| 847 | - 0x4C, |
|
| 848 | - 0x00, |
|
| 849 | - 0x35, |
|
| 850 | - 0x88, |
|
| 851 | - 0x22, |
|
| 852 | - 0x0A, |
|
| 853 | - 0x37, |
|
| 854 | - 0x40, |
|
| 855 | - _ARCOM2, |
|
| 856 | - 0xA0, |
|
| 857 | - 0x06, |
|
| 858 | - 0x02, |
|
| 859 | - _COM4, |
|
| 860 | - 0xB7, |
|
| 861 | - 0x0E, |
|
| 862 | - 0x01, |
|
| 863 | - 0x42, |
|
| 864 | - 0x83, |
|
| 865 | - _BANK_SEL, |
|
| 866 | - _BANK_DSP, |
|
| 867 | - _RESET, |
|
| 868 | - _RESET_DVP, |
|
| 869 | - # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 870 | - _HSIZE8, |
|
| 871 | - 0xC8, |
|
| 872 | - _VSIZE8, |
|
| 873 | - 0x96, |
|
| 874 | - _SIZEL, |
|
| 875 | - 0x00, |
|
| 876 | - # Set the image window size >= output size |
|
| 877 | - _HSIZE, |
|
| 878 | - 0x90, |
|
| 879 | - _VSIZE, |
|
| 880 | - 0x2C, |
|
| 881 | - _XOFFL, |
|
| 882 | - 0x00, |
|
| 883 | - _YOFFL, |
|
| 884 | - 0x00, |
|
| 885 | - _VHYX, |
|
| 886 | - 0x88, |
|
| 887 | - _TEST, |
|
| 888 | - 0x00, |
|
| 889 | - _CTRL2, |
|
| 890 | - _CTRL2_DCW_EN | 0x1D, |
|
| 891 | - _CTRLI, |
|
| 892 | - 0x00, |
|
| 893 | - # _R_DVP_SP, 0x06, |
|
| 894 | - ] |
|
| 895 | -) |
|
| 896 | - |
|
| 897 | -_ov2640_color_settings = { |
|
| 898 | - OV2640_COLOR_JPEG: bytes( |
|
| 899 | - [ |
|
| 900 | - _BANK_SEL, |
|
| 901 | - _BANK_DSP, |
|
| 902 | - _RESET, |
|
| 903 | - _RESET_JPEG | _RESET_DVP, |
|
| 904 | - _IMAGE_MODE, |
|
| 905 | - _IMAGE_MODE_JPEG_EN | _IMAGE_MODE_HREF_VSYNC, |
|
| 906 | - 0xD7, |
|
| 907 | - 0x03, |
|
| 908 | - 0xE1, |
|
| 909 | - 0x77, |
|
| 910 | - 0xE5, |
|
| 911 | - 0x1F, |
|
| 912 | - 0xD9, |
|
| 913 | - 0x10, |
|
| 914 | - 0xDF, |
|
| 915 | - 0x80, |
|
| 916 | - 0x33, |
|
| 917 | - 0x80, |
|
| 918 | - 0x3C, |
|
| 919 | - 0x10, |
|
| 920 | - 0xEB, |
|
| 921 | - 0x30, |
|
| 922 | - 0xDD, |
|
| 923 | - 0x7F, |
|
| 924 | - _RESET, |
|
| 925 | - 0x00, |
|
| 926 | - ] |
|
| 927 | - ), |
|
| 928 | - OV2640_COLOR_YUV: bytes( |
|
| 929 | - [ |
|
| 930 | - _BANK_SEL, |
|
| 931 | - _BANK_DSP, |
|
| 932 | - _RESET, |
|
| 933 | - _RESET_DVP, |
|
| 934 | - _IMAGE_MODE, |
|
| 935 | - _IMAGE_MODE_YUV422, |
|
| 936 | - 0xD7, |
|
| 937 | - 0x01, |
|
| 938 | - 0xE1, |
|
| 939 | - 0x67, |
|
| 940 | - _RESET, |
|
| 941 | - 0x00, |
|
| 942 | - ] |
|
| 943 | - ), |
|
| 944 | - OV2640_COLOR_RGB: bytes( |
|
| 945 | - [ |
|
| 946 | - _BANK_SEL, |
|
| 947 | - _BANK_DSP, |
|
| 948 | - _RESET, |
|
| 949 | - _RESET_DVP, |
|
| 950 | - _IMAGE_MODE, |
|
| 951 | - _IMAGE_MODE_RGB565, |
|
| 952 | - 0xD7, |
|
| 953 | - 0x03, |
|
| 954 | - 0xE1, |
|
| 955 | - 0x77, |
|
| 956 | - _RESET, |
|
| 957 | - 0x00, |
|
| 958 | - ] |
|
| 959 | - ), |
|
| 960 | -} |
|
| 961 | - |
|
| 962 | - |
|
| 963 | -class _RegBits: |
|
| 964 | - def __init__(self, bank: int, reg: int, shift: int, mask: int) -> None: |
|
| 965 | - self.bank = bank |
|
| 966 | - self.reg = reg |
|
| 967 | - self.shift = shift |
|
| 968 | - self.mask = mask |
|
| 969 | - |
|
| 970 | - def __get__(self, obj: "_SCCBCameraBase", objtype: Optional[Type] = None) -> int: |
|
| 971 | - reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 972 | - return (reg_value >> self.shift) & self.mask |
|
| 973 | - |
|
| 974 | - def __set__(self, obj: "_SCCBCameraBase", value: Union[bool, int]) -> None: |
|
| 975 | - if value & ~self.mask: |
|
| 976 | - raise ValueError(f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}") |
|
| 977 | - reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 978 | - reg_value &= ~(self.mask << self.shift) |
|
| 979 | - reg_value |= value << self.shift |
|
| 980 | - obj._write_register(self.reg, reg_value) |
|
| 981 | - |
|
| 982 | - |
|
| 983 | -class _SCCBCameraBase: |
|
| 984 | - def __init__(self, i2c_bus: I2C, i2c_address: int) -> None: |
|
| 985 | - self._i2c_device = I2CDevice(i2c_bus, i2c_address) |
|
| 986 | - self._bank = None |
|
| 987 | - |
|
| 988 | - def _get_reg_bits(self, bank: int, reg: int, shift: int, mask: int) -> int: |
|
| 989 | - return (self._read_bank_register(bank, reg) >> shift) & mask |
|
| 990 | - |
|
| 991 | - def _set_reg_bits(self, bank: int, reg: int, shift: int, mask: int, value: int) -> None: |
|
| 992 | - reg_value = self._read_bank_register(bank, reg) |
|
| 993 | - reg_value &= ~(mask << shift) |
|
| 994 | - reg_value |= value << shift |
|
| 995 | - self._write_register(reg, reg_value) |
|
| 996 | - |
|
| 997 | - def _write_list(self, reg_list: List[int]) -> None: |
|
| 998 | - for i in range(0, len(reg_list), 2): |
|
| 999 | - self._write_register(reg_list[i], reg_list[i + 1]) |
|
| 1000 | - time.sleep(0.001) |
|
| 1001 | - |
|
| 1002 | - def _write_bank_register(self, bank: int, reg: int, value: int) -> None: |
|
| 1003 | - if self._bank != bank: |
|
| 1004 | - self._write_register(_BANK_SEL, bank) |
|
| 1005 | - self._write_register(reg, value) |
|
| 1006 | - |
|
| 1007 | - def _read_bank_register(self, bank: int, reg: int) -> int: |
|
| 1008 | - if self._bank != bank: |
|
| 1009 | - self._write_register(_BANK_SEL, bank) |
|
| 1010 | - result = self._read_register(reg) |
|
| 1011 | - return result |
|
| 1012 | - |
|
| 1013 | - def _write_register(self, reg: int, value: int) -> None: |
|
| 1014 | - if reg == _BANK_SEL: |
|
| 1015 | - if self._bank == value: |
|
| 1016 | - return |
|
| 1017 | - self._bank = value |
|
| 1018 | - # print(f"write_register {reg:02x} {value:02x}") |
|
| 1019 | - b = bytearray(2) |
|
| 1020 | - b[0] = reg |
|
| 1021 | - b[1] = value |
|
| 1022 | - with self._i2c_device as i2c: |
|
| 1023 | - i2c.write(b) |
|
| 1024 | - |
|
| 1025 | - def _read_register(self, reg: int) -> int: |
|
| 1026 | - b = bytearray(1) |
|
| 1027 | - b[0] = reg |
|
| 1028 | - with self._i2c_device as i2c: |
|
| 1029 | - i2c.write(b) |
|
| 1030 | - i2c.readinto(b) |
|
| 1031 | - return b[0] |
|
| 1032 | - |
|
| 1033 | - |
|
| 1034 | -class OV2640(_SCCBCameraBase): |
|
| 1035 | - """Library for the OV2640 digital camera""" |
|
| 1036 | - |
|
| 1037 | - test_pattern = _RegBits(_BANK_SENSOR, _COM7, 1, 1) |
|
| 1038 | - gain_ceiling = _RegBits(_BANK_SENSOR, _COM9, 5, 7) |
|
| 1039 | - bpc = _RegBits(_BANK_DSP, _CTRL3, 7, 1) |
|
| 1040 | - wpc = _RegBits(_BANK_DSP, _CTRL3, 6, 1) |
|
| 1041 | - lenc = _RegBits(_BANK_DSP, _CTRL1, 1, 1) |
|
| 1042 | - |
|
| 1043 | - def __init__( |
|
| 1044 | - self, |
|
| 1045 | - i2c_bus: I2C, |
|
| 1046 | - data_pins: Pin, |
|
| 1047 | - clock: Pin, |
|
| 1048 | - vsync: Pin, |
|
| 1049 | - href: Pin, |
|
| 1050 | - shutdown: Optional[Pin] = None, |
|
| 1051 | - reset: Optional[Pin] = None, |
|
| 1052 | - mclk: Optional[Pin] = None, |
|
| 1053 | - mclk_frequency: int = 20_000_000, |
|
| 1054 | - i2c_address: int = 0x30, |
|
| 1055 | - size: int = OV2640_SIZE_QQVGA, |
|
| 1056 | - ): |
|
| 1057 | - """ |
|
| 1058 | - Args: |
|
| 1059 | - i2c_bus (busio.I2C): The I2C bus used to configure the OV2640 |
|
| 1060 | - data_pins (List[microcontroller.Pin]): A list of 8 data pins, in order. |
|
| 1061 | - clock (microcontroller.Pin): The pixel clock from the OV2640. |
|
| 1062 | - vsync (microcontroller.Pin): The vsync signal from the OV2640. |
|
| 1063 | - href (microcontroller.Pin): The href signal from the OV2640, \ |
|
| 1064 | - sometimes inaccurately called hsync. |
|
| 1065 | - shutdown (Optional[microcontroller.Pin]): If not None, the shutdown |
|
| 1066 | - signal to the camera, also called the powerdown or enable pin. |
|
| 1067 | - reset (Optional[microcontroller.Pin]): If not None, the reset signal |
|
| 1068 | - to the camera. |
|
| 1069 | - mclk (Optional[microcontroller.Pin]): The pin on which to create a |
|
| 1070 | - master clock signal, or None if the master clock signal is |
|
| 1071 | - already being generated. |
|
| 1072 | - mclk_frequency (int): The frequency of the master clock to generate, \ |
|
| 1073 | - ignored if mclk is None, requred if it is specified |
|
| 1074 | - i2c_address (int): The I2C address of the camera. |
|
| 1075 | - """ |
|
| 1076 | - |
|
| 1077 | - # Initialize the master clock |
|
| 1078 | - if mclk: |
|
| 1079 | - self._mclk_pwm = pwmio.PWMOut(mclk, frequency=mclk_frequency) |
|
| 1080 | - self._mclk_pwm.duty_cycle = 32768 |
|
| 1081 | - else: |
|
| 1082 | - self._mclk_pwm = None |
|
| 1083 | - |
|
| 1084 | - if shutdown: |
|
| 1085 | - self._shutdown = digitalio.DigitalInOut(shutdown) |
|
| 1086 | - self._shutdown.switch_to_output(True) |
|
| 1087 | - time.sleep(0.1) |
|
| 1088 | - self._shutdown.switch_to_output(False) |
|
| 1089 | - time.sleep(0.3) |
|
| 1090 | - else: |
|
| 1091 | - self._shutdown = None |
|
| 1092 | - |
|
| 1093 | - if reset: |
|
| 1094 | - self._reset = digitalio.DigitalInOut(reset) |
|
| 1095 | - self._reset.switch_to_output(False) |
|
| 1096 | - time.sleep(0.1) |
|
| 1097 | - self._reset.switch_to_output(True) |
|
| 1098 | - time.sleep(0.1) |
|
| 1099 | - |
|
| 1100 | - super().__init__(i2c_bus, i2c_address) |
|
| 1101 | - |
|
| 1102 | - self._write_bank_register(_BANK_SENSOR, _COM7, _COM7_SRST) |
|
| 1103 | - time.sleep(0.001) |
|
| 1104 | - |
|
| 1105 | - self._write_list(_ov2640_settings_cif) |
|
| 1106 | - |
|
| 1107 | - self._colorspace = OV2640_COLOR_RGB |
|
| 1108 | - self._w = None |
|
| 1109 | - self._h = None |
|
| 1110 | - self._size = None |
|
| 1111 | - self._test_pattern = False |
|
| 1112 | - self.size = size |
|
| 1113 | - |
|
| 1114 | - self._flip_x = False |
|
| 1115 | - self._flip_y = False |
|
| 1116 | - |
|
| 1117 | - self.gain_ceiling = _COM9_AGC_GAIN_2x |
|
| 1118 | - self.bpc = False |
|
| 1119 | - self.wpc = True |
|
| 1120 | - self.lenc = True |
|
| 1121 | - |
|
| 1122 | - # self._sensor_init() |
|
| 1123 | - |
|
| 1124 | - self._imagecapture = imagecapture.ParallelImageCapture( |
|
| 1125 | - data_pins=data_pins, clock=clock, vsync=vsync, href=href |
|
| 1126 | - ) |
|
| 1127 | - |
|
| 1128 | - def capture(self, buf: WriteableBuffer) -> Optional[memoryview]: |
|
| 1129 | - """Capture an image into the buffer. |
|
| 1130 | - |
|
| 1131 | - Args: |
|
| 1132 | - buf (WriteableBuffer): A WritableBuffer to contain the \ |
|
| 1133 | - captured image. Note that this can be a ulab array or a displayio Bitmap. |
|
| 1134 | - """ |
|
| 1135 | - self._imagecapture.capture(buf) |
|
| 1136 | - if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1137 | - eoi = buf.find(b"\xff\xd9") |
|
| 1138 | - if eoi != -1: |
|
| 1139 | - # terminate the JPEG data just after the EOI marker |
|
| 1140 | - return memoryview(buf)[: eoi + 2] |
|
| 1141 | - return None |
|
| 1142 | - |
|
| 1143 | - @property |
|
| 1144 | - def capture_buffer_size(self) -> int: |
|
| 1145 | - """Return the size of capture buffer to use with current resolution & colorspace settings""" |
|
| 1146 | - if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1147 | - return self.width * self.height // 5 |
|
| 1148 | - return self.width * self.height * 2 |
|
| 1149 | - |
|
| 1150 | - @property |
|
| 1151 | - def mclk_frequency(self) -> Optional[int]: |
|
| 1152 | - """Get the actual frequency the generated mclk, or None""" |
|
| 1153 | - return self._mclk_pwm.frequency if self._mclk_pwm else None |
|
| 1154 | - |
|
| 1155 | - @property |
|
| 1156 | - def width(self) -> int: |
|
| 1157 | - """Get the image width in pixels. A buffer of 2*width*height bytes \ |
|
| 1158 | - stores a whole image.""" |
|
| 1159 | - return self._w |
|
| 1160 | - |
|
| 1161 | - @property |
|
| 1162 | - def height(self) -> int: |
|
| 1163 | - """Get the image height in pixels. A buffer of 2*width*height bytes \ |
|
| 1164 | - stores a whole image.""" |
|
| 1165 | - return self._h |
|
| 1166 | - |
|
| 1167 | - @property |
|
| 1168 | - def colorspace(self) -> bytes: |
|
| 1169 | - """Get or set the colorspace, one of the ``OV2640_COLOR_`` constants.""" |
|
| 1170 | - return self._colorspace |
|
| 1171 | - |
|
| 1172 | - @colorspace.setter |
|
| 1173 | - def colorspace(self, colorspace: bytes) -> None: |
|
| 1174 | - self._colorspace = colorspace |
|
| 1175 | - self._set_size_and_colorspace() |
|
| 1176 | - |
|
| 1177 | - def _set_colorspace(self) -> None: |
|
| 1178 | - colorspace = self._colorspace |
|
| 1179 | - settings = _ov2640_color_settings[colorspace] |
|
| 1180 | - |
|
| 1181 | - self._write_list(settings) |
|
| 1182 | - # written twice? |
|
| 1183 | - self._write_list(settings) |
|
| 1184 | - time.sleep(0.01) |
|
| 1185 | - |
|
| 1186 | - def deinit(self) -> None: |
|
| 1187 | - """Deinitialize the camera""" |
|
| 1188 | - self._imagecapture.deinit() |
|
| 1189 | - if self._mclk_pwm: |
|
| 1190 | - self._mclk_pwm.deinit() |
|
| 1191 | - if self._shutdown: |
|
| 1192 | - self._shutdown.deinit() |
|
| 1193 | - if self._reset: |
|
| 1194 | - self._reset.deinit() |
|
| 1195 | - |
|
| 1196 | - @property |
|
| 1197 | - def size(self) -> int: |
|
| 1198 | - """Get or set the captured image size, one of the ``OV2640_SIZE_`` constants.""" |
|
| 1199 | - return self._size |
|
| 1200 | - |
|
| 1201 | - def _set_size_and_colorspace(self) -> None: |
|
| 1202 | - size = self._size |
|
| 1203 | - width, height, ratio = _resolution_info[size] |
|
| 1204 | - offset_x, offset_y, max_x, max_y = _ratio_table[ratio] |
|
| 1205 | - mode = _OV2640_MODE_UXGA |
|
| 1206 | - if size <= OV2640_SIZE_CIF: |
|
| 1207 | - mode = _OV2640_MODE_CIF |
|
| 1208 | - max_x //= 4 |
|
| 1209 | - max_y //= 4 |
|
| 1210 | - offset_x //= 4 |
|
| 1211 | - offset_y //= 4 |
|
| 1212 | - max_y = min(max_y, 296) |
|
| 1213 | - |
|
| 1214 | - elif size <= OV2640_SIZE_SVGA: |
|
| 1215 | - mode = _OV2640_MODE_SVGA |
|
| 1216 | - max_x //= 2 |
|
| 1217 | - max_y //= 2 |
|
| 1218 | - offset_x //= 2 |
|
| 1219 | - offset_y //= 2 |
|
| 1220 | - |
|
| 1221 | - self._set_window(mode, offset_x, offset_y, max_x, max_y, width, height) |
|
| 1222 | - |
|
| 1223 | - @size.setter |
|
| 1224 | - def size(self, size: int) -> None: |
|
| 1225 | - self._size = size |
|
| 1226 | - self._set_size_and_colorspace() |
|
| 1227 | - |
|
| 1228 | - def _set_flip(self) -> None: |
|
| 1229 | - bits = 0 |
|
| 1230 | - if self._flip_x: |
|
| 1231 | - bits |= _REG04_HFLIP_IMG |
|
| 1232 | - if self._flip_y: |
|
| 1233 | - bits |= _REG04_VFLIP_IMG | _REG04_VREF_EN |
|
| 1234 | - self._write_bank_register(_BANK_SENSOR, _REG04, _REG04_SET(bits)) |
|
| 1235 | - |
|
| 1236 | - @property |
|
| 1237 | - def flip_x(self) -> bool: |
|
| 1238 | - """Get or set the X-flip flag""" |
|
| 1239 | - return self._flip_x |
|
| 1240 | - |
|
| 1241 | - @flip_x.setter |
|
| 1242 | - def flip_x(self, value: bool) -> None: |
|
| 1243 | - self._flip_x = bool(value) |
|
| 1244 | - self._set_flip() |
|
| 1245 | - |
|
| 1246 | - @property |
|
| 1247 | - def flip_y(self) -> bool: |
|
| 1248 | - """Get or set the Y-flip flag""" |
|
| 1249 | - return self._flip_y |
|
| 1250 | - |
|
| 1251 | - @flip_y.setter |
|
| 1252 | - def flip_y(self, value: bool) -> None: |
|
| 1253 | - self._flip_y = bool(value) |
|
| 1254 | - self._set_flip() |
|
| 1255 | - |
|
| 1256 | - @property |
|
| 1257 | - def product_id(self) -> int: |
|
| 1258 | - """Get the product id (PID) register. The expected value is 0x26.""" |
|
| 1259 | - return self._read_bank_register(_BANK_SENSOR, _REG_PID) |
|
| 1260 | - |
|
| 1261 | - @property |
|
| 1262 | - def product_version(self) -> int: |
|
| 1263 | - """Get the version (VER) register. The expected value is 0x41.""" |
|
| 1264 | - return self._read_bank_register(_BANK_SENSOR, _REG_VER) |
|
| 1265 | - |
|
| 1266 | - def _set_window( |
|
| 1267 | - self, |
|
| 1268 | - mode: int, |
|
| 1269 | - offset_x: int, |
|
| 1270 | - offset_y: int, |
|
| 1271 | - max_x: int, |
|
| 1272 | - max_y: int, |
|
| 1273 | - width: int, |
|
| 1274 | - height: int, |
|
| 1275 | - ) -> None: |
|
| 1276 | - self._w = width |
|
| 1277 | - self._h = height |
|
| 1278 | - |
|
| 1279 | - max_x //= 4 |
|
| 1280 | - max_y //= 4 |
|
| 1281 | - width //= 4 |
|
| 1282 | - height //= 4 |
|
| 1283 | - |
|
| 1284 | - win_regs = [ |
|
| 1285 | - _BANK_SEL, |
|
| 1286 | - _BANK_DSP, |
|
| 1287 | - _HSIZE, |
|
| 1288 | - max_x & 0xFF, |
|
| 1289 | - _VSIZE, |
|
| 1290 | - max_y & 0xFF, |
|
| 1291 | - _XOFFL, |
|
| 1292 | - offset_x & 0xFF, |
|
| 1293 | - _YOFFL, |
|
| 1294 | - offset_y & 0xFF, |
|
| 1295 | - _VHYX, |
|
| 1296 | - ((max_y >> 1) & 0x80) |
|
| 1297 | - | ((offset_y >> 4) & 0x70) |
|
| 1298 | - | ((max_x >> 5) & 0x08) |
|
| 1299 | - | ((offset_y >> 8) & 0x07), |
|
| 1300 | - _TEST, |
|
| 1301 | - (max_x >> 2) & 0x80, |
|
| 1302 | - _ZMOW, |
|
| 1303 | - (width) & 0xFF, |
|
| 1304 | - _ZMOH, |
|
| 1305 | - (height) & 0xFF, |
|
| 1306 | - _ZMHH, |
|
| 1307 | - ((height >> 6) & 0x04) | ((width >> 8) & 0x03), |
|
| 1308 | - ] |
|
| 1309 | - |
|
| 1310 | - pclk_auto = 0 |
|
| 1311 | - pclk_div = 8 |
|
| 1312 | - clk_2x = 0 |
|
| 1313 | - clk_div = 0 |
|
| 1314 | - |
|
| 1315 | - if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1316 | - pclk_auto = 1 |
|
| 1317 | - clk_div = 7 |
|
| 1318 | - |
|
| 1319 | - if mode == _OV2640_MODE_CIF: |
|
| 1320 | - regs = _ov2640_settings_to_cif |
|
| 1321 | - if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1322 | - clk_div = 3 |
|
| 1323 | - elif mode == _OV2640_MODE_SVGA: |
|
| 1324 | - regs = _ov2640_settings_to_svga |
|
| 1325 | - else: |
|
| 1326 | - regs = _ov2640_settings_to_uxga |
|
| 1327 | - pclk_div = 12 |
|
| 1328 | - |
|
| 1329 | - clk = clk_div | (clk_2x << 7) |
|
| 1330 | - pclk = pclk_div | (pclk_auto << 7) |
|
| 1331 | - |
|
| 1332 | - self._write_bank_register(_BANK_DSP, _R_BYPASS, _R_BYPASS_DSP_BYPAS) |
|
| 1333 | - self._write_list(regs) |
|
| 1334 | - self._write_list(win_regs) |
|
| 1335 | - self._write_bank_register(_BANK_SENSOR, _CLKRC, clk) |
|
| 1336 | - self._write_bank_register(_BANK_DSP, _R_DVP_SP, pclk) |
|
| 1337 | - self._write_register(_R_BYPASS, _R_BYPASS_DSP_EN) |
|
| 1338 | - time.sleep(0.01) |
|
| 1339 | - |
|
| 1340 | - # Reestablish colorspace |
|
| 1341 | - self._set_colorspace() |
|
| 1342 | - |
|
| 1343 | - # Reestablish test pattern |
|
| 1344 | - if self._test_pattern: |
|
| 1345 | - self.test_pattern = self._test_pattern |
|
| 1346 | - |
|
| 1347 | - @property |
|
| 1348 | - def exposure(self) -> int: |
|
| 1349 | - """The exposure level of the sensor""" |
|
| 1350 | - aec_9_2 = self._get_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF) |
|
| 1351 | - aec_15_10 = self._get_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111) |
|
| 1352 | - aec_1_0 = self._get_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11) |
|
| 1353 | - |
|
| 1354 | - return aec_1_0 | (aec_9_2 << 2) | (aec_15_10 << 10) |
|
| 1355 | - |
|
| 1356 | - @exposure.setter |
|
| 1357 | - def exposure(self, exposure: int) -> None: |
|
| 1358 | - aec_1_0 = exposure & 0x11 |
|
| 1359 | - aec_9_2 = (exposure >> 2) & 0b11111111 |
|
| 1360 | - aec_15_10 = exposure >> 10 |
|
| 1361 | - |
|
| 1362 | - self._set_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF, aec_9_2) |
|
| 1363 | - self._set_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111, aec_15_10) |
|
| 1364 | - self._set_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11, aec_1_0) |
SDK-dat/python-dat/circuitpython-dat/adafruit_ov2640/adafruit_ov2640.py
| ... | ... | @@ -0,0 +1,1364 @@ |
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | +# |
|
| 4 | +# SPDX-License-Identifier: MIT |
|
| 5 | +""" |
|
| 6 | +`adafruit_ov2640` |
|
| 7 | +================================================================================ |
|
| 8 | + |
|
| 9 | +CircuitPython driver for OV2640 Camera. |
|
| 10 | + |
|
| 11 | + |
|
| 12 | +* Author(s): Jeff Epler |
|
| 13 | + |
|
| 14 | +Implementation Notes |
|
| 15 | +-------------------- |
|
| 16 | + |
|
| 17 | +**Hardware:** |
|
| 18 | + |
|
| 19 | +* `ESP32-S2 Kaluga Dev Kit featuring ESP32-S2 WROVER <https://www.adafruit.com/product/4729>`_ |
|
| 20 | + |
|
| 21 | +**Software and Dependencies:** |
|
| 22 | + |
|
| 23 | +* Adafruit CircuitPython firmware for the supported boards: |
|
| 24 | + https://github.com/adafruit/circuitpython/releases |
|
| 25 | + |
|
| 26 | +* Adafruit's Bus Device library: https:# github.com/adafruit/Adafruit_CircuitPython_BusDevice |
|
| 27 | +""" |
|
| 28 | + |
|
| 29 | +# imports |
|
| 30 | + |
|
| 31 | +__version__ = "0.0.0+auto.0" |
|
| 32 | +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_OV7670.git" |
|
| 33 | + |
|
| 34 | +import time |
|
| 35 | + |
|
| 36 | +import digitalio |
|
| 37 | +import imagecapture |
|
| 38 | +import pwmio |
|
| 39 | +from adafruit_bus_device.i2c_device import I2CDevice |
|
| 40 | +from micropython import const |
|
| 41 | + |
|
| 42 | +try: |
|
| 43 | + from typing import List, Optional, Type, Union |
|
| 44 | + |
|
| 45 | + from busio import I2C |
|
| 46 | + from circuitpython_typing import WriteableBuffer |
|
| 47 | + from microcontroller import Pin |
|
| 48 | +except ImportError: |
|
| 49 | + pass |
|
| 50 | + |
|
| 51 | +CTRLI = const(0x50) |
|
| 52 | +_R_BYPASS = const(0x05) |
|
| 53 | +_QS = const(0x44) |
|
| 54 | +_CTRLI = const(0x50) |
|
| 55 | +_HSIZE = const(0x51) |
|
| 56 | +_VSIZE = const(0x52) |
|
| 57 | +_XOFFL = const(0x53) |
|
| 58 | +_YOFFL = const(0x54) |
|
| 59 | +_VHYX = const(0x55) |
|
| 60 | +_DPRP = const(0x56) |
|
| 61 | +_TEST = const(0x57) |
|
| 62 | +_ZMOW = const(0x5A) |
|
| 63 | +_ZMOH = const(0x5B) |
|
| 64 | +_ZMHH = const(0x5C) |
|
| 65 | +_BPADDR = const(0x7C) |
|
| 66 | +_BPDATA = const(0x7D) |
|
| 67 | +_CTRL2 = const(0x86) |
|
| 68 | +_CTRL3 = const(0x87) |
|
| 69 | +_SIZEL = const(0x8C) |
|
| 70 | +_HSIZE8 = const(0xC0) |
|
| 71 | +_VSIZE8 = const(0xC1) |
|
| 72 | +_CTRL0 = const(0xC2) |
|
| 73 | +_CTRL1 = const(0xC3) |
|
| 74 | +_R_DVP_SP = const(0xD3) |
|
| 75 | +_IMAGE_MODE = const(0xDA) |
|
| 76 | +_RESET = const(0xE0) |
|
| 77 | +_MS_SP = const(0xF0) |
|
| 78 | +_SS_ID = const(0xF7) |
|
| 79 | +_SS_CTRL = const(0xF7) |
|
| 80 | +_MC_BIST = const(0xF9) |
|
| 81 | +_MC_AL = const(0xFA) |
|
| 82 | +_MC_AH = const(0xFB) |
|
| 83 | +_MC_D = const(0xFC) |
|
| 84 | +_P_CMD = const(0xFD) |
|
| 85 | +_P_STATUS = const(0xFE) |
|
| 86 | +_BANK_SEL = const(0xFF) |
|
| 87 | + |
|
| 88 | +_CTRLI_LP_DP = const(0x80) |
|
| 89 | +_CTRLI_ROUND = const(0x40) |
|
| 90 | + |
|
| 91 | +_CTRL0_AEC_EN = const(0x80) |
|
| 92 | +_CTRL0_AEC_SEL = const(0x40) |
|
| 93 | +_CTRL0_STAT_SEL = const(0x20) |
|
| 94 | +_CTRL0_VFIRST = const(0x10) |
|
| 95 | +_CTRL0_YUV422 = const(0x08) |
|
| 96 | +_CTRL0_YUV_EN = const(0x04) |
|
| 97 | +_CTRL0_RGB_EN = const(0x02) |
|
| 98 | +_CTRL0_RAW_EN = const(0x01) |
|
| 99 | + |
|
| 100 | +_CTRL2_DCW_EN = const(0x20) |
|
| 101 | +_CTRL2_SDE_EN = const(0x10) |
|
| 102 | +_CTRL2_UV_ADJ_EN = const(0x08) |
|
| 103 | +_CTRL2_UV_AVG_EN = const(0x04) |
|
| 104 | +_CTRL2_CMX_EN = const(0x01) |
|
| 105 | + |
|
| 106 | +_CTRL3_BPC_EN = const(0x80) |
|
| 107 | +_CTRL3_WPC_EN = const(0x40) |
|
| 108 | + |
|
| 109 | +_R_DVP_SP_AUTO_MODE = const(0x80) |
|
| 110 | + |
|
| 111 | +_R_BYPASS_DSP_EN = const(0x00) |
|
| 112 | +_R_BYPASS_DSP_BYPAS = const(0x01) |
|
| 113 | + |
|
| 114 | +OV2640_COLOR_RGB = 0 |
|
| 115 | +OV2640_COLOR_YUV = 1 |
|
| 116 | +OV2640_COLOR_JPEG = 2 |
|
| 117 | + |
|
| 118 | +_IMAGE_MODE_Y8_DVP_EN = const(0x40) |
|
| 119 | +_IMAGE_MODE_JPEG_EN = const(0x10) |
|
| 120 | +_IMAGE_MODE_YUV422 = const(0x00) |
|
| 121 | +_IMAGE_MODE_RAW10 = const(0x04) |
|
| 122 | +_IMAGE_MODE_RGB565 = const(0x08) |
|
| 123 | +_IMAGE_MODE_HREF_VSYNC = const(0x02) |
|
| 124 | +_IMAGE_MODE_LBYTE_FIRST = const(0x01) |
|
| 125 | + |
|
| 126 | +_RESET_MICROC = const(0x40) |
|
| 127 | +_RESET_SCCB = const(0x20) |
|
| 128 | +_RESET_JPEG = const(0x10) |
|
| 129 | +_RESET_DVP = const(0x04) |
|
| 130 | +_RESET_IPU = const(0x02) |
|
| 131 | +_RESET_CIF = const(0x01) |
|
| 132 | + |
|
| 133 | +_MC_BIST_RESET = const(0x80) |
|
| 134 | +_MC_BIST_BOOT_ROM_SEL = const(0x40) |
|
| 135 | +_MC_BIST_12KB_SEL = const(0x20) |
|
| 136 | +_MC_BIST_12KB_MASK = const(0x30) |
|
| 137 | +_MC_BIST_512KB_SEL = const(0x08) |
|
| 138 | +_MC_BIST_512KB_MASK = const(0x0C) |
|
| 139 | +_MC_BIST_BUSY_BIT_R = const(0x02) |
|
| 140 | +_MC_BIST_MC_RES_ONE_SH_W = const(0x02) |
|
| 141 | +_MC_BIST_LAUNCH = const(0x01) |
|
| 142 | + |
|
| 143 | + |
|
| 144 | +_BANK_DSP = const(0) |
|
| 145 | +_BANK_SENSOR = const(1) |
|
| 146 | + |
|
| 147 | +# Sensor register bank FF=0x01 |
|
| 148 | +_GAIN = const(0x00) |
|
| 149 | +_COM1 = const(0x03) |
|
| 150 | +_REG04 = const(0x04) |
|
| 151 | +_REG08 = const(0x08) |
|
| 152 | +_COM2 = const(0x09) |
|
| 153 | +_REG_PID = const(0x0A) |
|
| 154 | +_REG_VER = const(0x0B) |
|
| 155 | +_COM3 = const(0x0C) |
|
| 156 | +_COM4 = const(0x0D) |
|
| 157 | +_AEC = const(0x10) |
|
| 158 | +_CLKRC = const(0x11) |
|
| 159 | +_COM7 = const(0x12) |
|
| 160 | +_COM8 = const(0x13) |
|
| 161 | +_COM9 = const(0x14) # AGC gain ceiling |
|
| 162 | +_COM10 = const(0x15) |
|
| 163 | +_HSTART = const(0x17) |
|
| 164 | +_HSTOP = const(0x18) |
|
| 165 | +_VSTART = const(0x19) |
|
| 166 | +_VSTOP = const(0x1A) |
|
| 167 | +_MIDH = const(0x1C) |
|
| 168 | +_MIDL = const(0x1D) |
|
| 169 | +_AEW = const(0x24) |
|
| 170 | +_AEB = const(0x25) |
|
| 171 | +_VV = const(0x26) |
|
| 172 | +_REG2A = const(0x2A) |
|
| 173 | +_FRARL = const(0x2B) |
|
| 174 | +_ADDVSL = const(0x2D) |
|
| 175 | +_ADDVSH = const(0x2E) |
|
| 176 | +_YAVG = const(0x2F) |
|
| 177 | +_HSDY = const(0x30) |
|
| 178 | +_HEDY = const(0x31) |
|
| 179 | +_REG32 = const(0x32) |
|
| 180 | +_ARCOM2 = const(0x34) |
|
| 181 | +_REG45 = const(0x45) |
|
| 182 | +_FLL = const(0x46) |
|
| 183 | +_FLH = const(0x47) |
|
| 184 | +_COM19 = const(0x48) |
|
| 185 | +_ZOOMS = const(0x49) |
|
| 186 | +_COM22 = const(0x4B) |
|
| 187 | +_COM25 = const(0x4E) |
|
| 188 | +_BD50 = const(0x4F) |
|
| 189 | +_BD60 = const(0x50) |
|
| 190 | +_REG5D = const(0x5D) |
|
| 191 | +_REG5E = const(0x5E) |
|
| 192 | +_REG5F = const(0x5F) |
|
| 193 | +_REG60 = const(0x60) |
|
| 194 | +_HISTO_LOW = const(0x61) |
|
| 195 | +_HISTO_HIGH = const(0x62) |
|
| 196 | + |
|
| 197 | +_REG04_DEFAULT = const(0x28) |
|
| 198 | +_REG04_HFLIP_IMG = const(0x80) |
|
| 199 | +_REG04_VFLIP_IMG = const(0x40) |
|
| 200 | +_REG04_VREF_EN = const(0x10) |
|
| 201 | +_REG04_HREF_EN = const(0x08) |
|
| 202 | +_REG04_SET = lambda x: (_REG04_DEFAULT | x) |
|
| 203 | + |
|
| 204 | +_COM2_STDBY = const(0x10) |
|
| 205 | +_COM2_OUT_DRIVE_1x = const(0x00) |
|
| 206 | +_COM2_OUT_DRIVE_2x = const(0x01) |
|
| 207 | +_COM2_OUT_DRIVE_3x = const(0x02) |
|
| 208 | +_COM2_OUT_DRIVE_4x = const(0x03) |
|
| 209 | + |
|
| 210 | +_COM3_DEFAULT = const(0x38) |
|
| 211 | +_COM3_BAND_50Hz = const(0x04) |
|
| 212 | +_COM3_BAND_60Hz = const(0x00) |
|
| 213 | +_COM3_BAND_AUTO = const(0x02) |
|
| 214 | +_COM3_BAND_SET = lambda x: (_COM3_DEFAULT | x) |
|
| 215 | + |
|
| 216 | +_COM7_SRST = const(0x80) |
|
| 217 | +_COM7_RES_UXGA = const(0x00) # UXGA |
|
| 218 | +_COM7_RES_SVGA = const(0x40) # SVGA |
|
| 219 | +_COM7_RES_CIF = const(0x20) # CIF |
|
| 220 | +_COM7_ZOOM_EN = const(0x04) # Enable Zoom |
|
| 221 | +_COM7_COLOR_BAR = const(0x02) # Enable Color Bar Test |
|
| 222 | + |
|
| 223 | +_COM8_DEFAULT = const(0xC0) |
|
| 224 | +_COM8_BNDF_EN = const(0x20) # Enable Banding filter |
|
| 225 | +_COM8_AGC_EN = const(0x04) # AGC Auto/Manual control selection |
|
| 226 | +_COM8_AEC_EN = const(0x01) # Auto/Manual Exposure control |
|
| 227 | +_COM8_SET = lambda x: (_COM8_DEFAULT | x) |
|
| 228 | + |
|
| 229 | +_COM9_DEFAULT = const(0x08) |
|
| 230 | +_COM9_AGC_GAIN_2x = const(0x00) # AGC: 2x |
|
| 231 | +_COM9_AGC_GAIN_4x = const(0x01) # AGC: 4x |
|
| 232 | +_COM9_AGC_GAIN_8x = const(0x02) # AGC: 8x |
|
| 233 | +_COM9_AGC_GAIN_16x = const(0x03) # AGC: 16x |
|
| 234 | +_COM9_AGC_GAIN_32x = const(0x04) # AGC: 32x |
|
| 235 | +_COM9_AGC_GAIN_64x = const(0x05) # AGC: 64x |
|
| 236 | +_COM9_AGC_GAIN_128x = const(0x06) # AGC: 128x |
|
| 237 | +_COM9_AGC_SET = lambda x: (_COM9_DEFAULT | (x << 5)) |
|
| 238 | + |
|
| 239 | +_COM10_HREF_EN = const(0x80) # HSYNC changes to HREF |
|
| 240 | +_COM10_HSYNC_EN = const(0x40) # HREF changes to HSYNC |
|
| 241 | +_COM10_PCLK_FREE = const(0x20) # PCLK output option: free running PCLK |
|
| 242 | +_COM10_PCLK_EDGE = const(0x10) # Data is updated at the rising edge of PCLK |
|
| 243 | +_COM10_HREF_NEG = const(0x08) # HREF negative |
|
| 244 | +_COM10_VSYNC_NEG = const(0x02) # VSYNC negative |
|
| 245 | +_COM10_HSYNC_NEG = const(0x01) # HSYNC negative |
|
| 246 | + |
|
| 247 | +_CTRL1_AWB = const(0x08) # Enable AWB |
|
| 248 | + |
|
| 249 | +_VV_AGC_TH_SET = lambda h, l: ((h << 4) | (l & 0x0F)) |
|
| 250 | + |
|
| 251 | +_REG32_UXGA = const(0x36) |
|
| 252 | +_REG32_SVGA = const(0x09) |
|
| 253 | +_REG32_CIF = const(0x89) |
|
| 254 | + |
|
| 255 | +_CLKRC_2X = const(0x80) |
|
| 256 | +_CLKRC_2X_UXGA = const(0x01 | _CLKRC_2X) |
|
| 257 | +_CLKRC_2X_SVGA = _CLKRC_2X |
|
| 258 | +_CLKRC_2X_CIF = _CLKRC_2X |
|
| 259 | + |
|
| 260 | +_OV2640_MODE_CIF = const(0) |
|
| 261 | +_OV2640_MODE_SVGA = const(1) |
|
| 262 | +_OV2640_MODE_UXGA = const(2) |
|
| 263 | + |
|
| 264 | +OV2640_SIZE_96X96 = 0 # 96x96 |
|
| 265 | +OV2640_SIZE_QQVGA = 1 # 160x120 |
|
| 266 | +OV2640_SIZE_QCIF = 2 # 176x144 |
|
| 267 | +OV2640_SIZE_HQVGA = 3 # 240x176 |
|
| 268 | +OV2640_SIZE_240X240 = 4 # 240x240 |
|
| 269 | +OV2640_SIZE_QVGA = 5 # 320x240 |
|
| 270 | +OV2640_SIZE_CIF = 6 # 400x296 |
|
| 271 | +OV2640_SIZE_HVGA = 7 # 480x320 |
|
| 272 | +OV2640_SIZE_VGA = 8 # 640x480 |
|
| 273 | +OV2640_SIZE_SVGA = 9 # 800x600 |
|
| 274 | +OV2640_SIZE_XGA = 10 # 1024x768 |
|
| 275 | +OV2640_SIZE_HD = 11 # 1280x720 |
|
| 276 | +OV2640_SIZE_SXGA = 12 # 1280x1024 |
|
| 277 | +OV2640_SIZE_UXGA = 13 # 1600x1200 |
|
| 278 | + |
|
| 279 | +_ASPECT_RATIO_4X3 = const(0) |
|
| 280 | +_ASPECT_RATIO_3X2 = const(1) |
|
| 281 | +_ASPECT_RATIO_16X10 = const(2) |
|
| 282 | +_ASPECT_RATIO_5X3 = const(3) |
|
| 283 | +_ASPECT_RATIO_16X9 = const(4) |
|
| 284 | +_ASPECT_RATIO_21X9 = const(5) |
|
| 285 | +_ASPECT_RATIO_5X4 = const(6) |
|
| 286 | +_ASPECT_RATIO_1X1 = const(7) |
|
| 287 | +_ASPECT_RATIO_9X16 = const(8) |
|
| 288 | + |
|
| 289 | +_resolution_info = [ |
|
| 290 | + [96, 96, _ASPECT_RATIO_1X1], # 96x96 |
|
| 291 | + [160, 120, _ASPECT_RATIO_4X3], # QQVGA |
|
| 292 | + [176, 144, _ASPECT_RATIO_5X4], # QCIF |
|
| 293 | + [240, 176, _ASPECT_RATIO_4X3], # HQVGA |
|
| 294 | + [240, 240, _ASPECT_RATIO_1X1], # 240x240 |
|
| 295 | + [320, 240, _ASPECT_RATIO_4X3], # QVGA |
|
| 296 | + [400, 296, _ASPECT_RATIO_4X3], # CIF |
|
| 297 | + [480, 320, _ASPECT_RATIO_3X2], # HVGA |
|
| 298 | + [640, 480, _ASPECT_RATIO_4X3], # VGA |
|
| 299 | + [800, 600, _ASPECT_RATIO_4X3], # SVGA |
|
| 300 | + [1024, 768, _ASPECT_RATIO_4X3], # XGA |
|
| 301 | + [1280, 720, _ASPECT_RATIO_16X9], # HD |
|
| 302 | + [1280, 1024, _ASPECT_RATIO_5X4], # SXGA |
|
| 303 | + [1600, 1200, _ASPECT_RATIO_4X3], # UXGA |
|
| 304 | +] |
|
| 305 | + |
|
| 306 | +_ratio_table = [ |
|
| 307 | + # ox, oy, mx, my |
|
| 308 | + [0, 0, 1600, 1200], # 4x3 |
|
| 309 | + [8, 72, 1584, 1056], # 3x2 |
|
| 310 | + [0, 100, 1600, 1000], # 16x10 |
|
| 311 | + [0, 120, 1600, 960], # 5x3 |
|
| 312 | + [0, 150, 1600, 900], # 16x9 |
|
| 313 | + [2, 258, 1596, 684], # 21x9 |
|
| 314 | + [50, 0, 1500, 1200], # 5x4 |
|
| 315 | + [200, 0, 1200, 1200], # 1x1 |
|
| 316 | + [462, 0, 676, 1200], # 9x16 |
|
| 317 | +] |
|
| 318 | + |
|
| 319 | +# 30fps@24MHz |
|
| 320 | +_ov2640_settings_cif = bytes( |
|
| 321 | + [ |
|
| 322 | + _BANK_SEL, |
|
| 323 | + _BANK_DSP, |
|
| 324 | + 0x2C, |
|
| 325 | + 0xFF, |
|
| 326 | + 0x2E, |
|
| 327 | + 0xDF, |
|
| 328 | + _BANK_SEL, |
|
| 329 | + _BANK_SENSOR, |
|
| 330 | + 0x3C, |
|
| 331 | + 0x32, |
|
| 332 | + _CLKRC, |
|
| 333 | + 0x01, |
|
| 334 | + _COM2, |
|
| 335 | + _COM2_OUT_DRIVE_3x, |
|
| 336 | + _REG04, |
|
| 337 | + _REG04_DEFAULT, |
|
| 338 | + _COM8, |
|
| 339 | + _COM8_DEFAULT | _COM8_BNDF_EN | _COM8_AGC_EN | _COM8_AEC_EN, |
|
| 340 | + _COM9, |
|
| 341 | + _COM9_AGC_SET(_COM9_AGC_GAIN_8x), |
|
| 342 | + 0x2C, |
|
| 343 | + 0x0C, |
|
| 344 | + 0x33, |
|
| 345 | + 0x78, |
|
| 346 | + 0x3A, |
|
| 347 | + 0x33, |
|
| 348 | + 0x3B, |
|
| 349 | + 0xFB, |
|
| 350 | + 0x3E, |
|
| 351 | + 0x00, |
|
| 352 | + 0x43, |
|
| 353 | + 0x11, |
|
| 354 | + 0x16, |
|
| 355 | + 0x10, |
|
| 356 | + 0x39, |
|
| 357 | + 0x92, |
|
| 358 | + 0x35, |
|
| 359 | + 0xDA, |
|
| 360 | + 0x22, |
|
| 361 | + 0x1A, |
|
| 362 | + 0x37, |
|
| 363 | + 0xC3, |
|
| 364 | + 0x23, |
|
| 365 | + 0x00, |
|
| 366 | + _ARCOM2, |
|
| 367 | + 0xC0, |
|
| 368 | + 0x06, |
|
| 369 | + 0x88, |
|
| 370 | + 0x07, |
|
| 371 | + 0xC0, |
|
| 372 | + _COM4, |
|
| 373 | + 0x87, |
|
| 374 | + 0x0E, |
|
| 375 | + 0x41, |
|
| 376 | + 0x4C, |
|
| 377 | + 0x00, |
|
| 378 | + 0x4A, |
|
| 379 | + 0x81, |
|
| 380 | + 0x21, |
|
| 381 | + 0x99, |
|
| 382 | + _AEW, |
|
| 383 | + 0x40, |
|
| 384 | + _AEB, |
|
| 385 | + 0x38, |
|
| 386 | + _VV, |
|
| 387 | + _VV_AGC_TH_SET(8, 2), |
|
| 388 | + 0x5C, |
|
| 389 | + 0x00, |
|
| 390 | + 0x63, |
|
| 391 | + 0x00, |
|
| 392 | + _HISTO_LOW, |
|
| 393 | + 0x70, |
|
| 394 | + _HISTO_HIGH, |
|
| 395 | + 0x80, |
|
| 396 | + 0x7C, |
|
| 397 | + 0x05, |
|
| 398 | + 0x20, |
|
| 399 | + 0x80, |
|
| 400 | + 0x28, |
|
| 401 | + 0x30, |
|
| 402 | + 0x6C, |
|
| 403 | + 0x00, |
|
| 404 | + 0x6D, |
|
| 405 | + 0x80, |
|
| 406 | + 0x6E, |
|
| 407 | + 0x00, |
|
| 408 | + 0x70, |
|
| 409 | + 0x02, |
|
| 410 | + 0x71, |
|
| 411 | + 0x94, |
|
| 412 | + 0x73, |
|
| 413 | + 0xC1, |
|
| 414 | + 0x3D, |
|
| 415 | + 0x34, |
|
| 416 | + 0x5A, |
|
| 417 | + 0x57, |
|
| 418 | + _BD50, |
|
| 419 | + 0xBB, |
|
| 420 | + _BD60, |
|
| 421 | + 0x9C, |
|
| 422 | + _COM7, |
|
| 423 | + _COM7_RES_CIF, |
|
| 424 | + _HSTART, |
|
| 425 | + 0x11, |
|
| 426 | + _HSTOP, |
|
| 427 | + 0x43, |
|
| 428 | + _VSTART, |
|
| 429 | + 0x00, |
|
| 430 | + _VSTOP, |
|
| 431 | + 0x25, |
|
| 432 | + _REG32, |
|
| 433 | + 0x89, |
|
| 434 | + 0x37, |
|
| 435 | + 0xC0, |
|
| 436 | + _BD50, |
|
| 437 | + 0xCA, |
|
| 438 | + _BD60, |
|
| 439 | + 0xA8, |
|
| 440 | + 0x6D, |
|
| 441 | + 0x00, |
|
| 442 | + 0x3D, |
|
| 443 | + 0x38, |
|
| 444 | + _BANK_SEL, |
|
| 445 | + _BANK_DSP, |
|
| 446 | + 0xE5, |
|
| 447 | + 0x7F, |
|
| 448 | + _MC_BIST, |
|
| 449 | + _MC_BIST_RESET | _MC_BIST_BOOT_ROM_SEL, |
|
| 450 | + 0x41, |
|
| 451 | + 0x24, |
|
| 452 | + _RESET, |
|
| 453 | + _RESET_JPEG | _RESET_DVP, |
|
| 454 | + 0x76, |
|
| 455 | + 0xFF, |
|
| 456 | + 0x33, |
|
| 457 | + 0xA0, |
|
| 458 | + 0x42, |
|
| 459 | + 0x20, |
|
| 460 | + 0x43, |
|
| 461 | + 0x18, |
|
| 462 | + 0x4C, |
|
| 463 | + 0x00, |
|
| 464 | + _CTRL3, |
|
| 465 | + _CTRL3_WPC_EN | 0x10, |
|
| 466 | + 0x88, |
|
| 467 | + 0x3F, |
|
| 468 | + 0xD7, |
|
| 469 | + 0x03, |
|
| 470 | + 0xD9, |
|
| 471 | + 0x10, |
|
| 472 | + _R_DVP_SP, |
|
| 473 | + _R_DVP_SP_AUTO_MODE | 0x02, |
|
| 474 | + 0xC8, |
|
| 475 | + 0x08, |
|
| 476 | + 0xC9, |
|
| 477 | + 0x80, |
|
| 478 | + _BPADDR, |
|
| 479 | + 0x00, |
|
| 480 | + _BPDATA, |
|
| 481 | + 0x00, |
|
| 482 | + _BPADDR, |
|
| 483 | + 0x03, |
|
| 484 | + _BPDATA, |
|
| 485 | + 0x48, |
|
| 486 | + _BPDATA, |
|
| 487 | + 0x48, |
|
| 488 | + _BPADDR, |
|
| 489 | + 0x08, |
|
| 490 | + _BPDATA, |
|
| 491 | + 0x20, |
|
| 492 | + _BPDATA, |
|
| 493 | + 0x10, |
|
| 494 | + _BPDATA, |
|
| 495 | + 0x0E, |
|
| 496 | + 0x90, |
|
| 497 | + 0x00, |
|
| 498 | + 0x91, |
|
| 499 | + 0x0E, |
|
| 500 | + 0x91, |
|
| 501 | + 0x1A, |
|
| 502 | + 0x91, |
|
| 503 | + 0x31, |
|
| 504 | + 0x91, |
|
| 505 | + 0x5A, |
|
| 506 | + 0x91, |
|
| 507 | + 0x69, |
|
| 508 | + 0x91, |
|
| 509 | + 0x75, |
|
| 510 | + 0x91, |
|
| 511 | + 0x7E, |
|
| 512 | + 0x91, |
|
| 513 | + 0x88, |
|
| 514 | + 0x91, |
|
| 515 | + 0x8F, |
|
| 516 | + 0x91, |
|
| 517 | + 0x96, |
|
| 518 | + 0x91, |
|
| 519 | + 0xA3, |
|
| 520 | + 0x91, |
|
| 521 | + 0xAF, |
|
| 522 | + 0x91, |
|
| 523 | + 0xC4, |
|
| 524 | + 0x91, |
|
| 525 | + 0xD7, |
|
| 526 | + 0x91, |
|
| 527 | + 0xE8, |
|
| 528 | + 0x91, |
|
| 529 | + 0x20, |
|
| 530 | + 0x92, |
|
| 531 | + 0x00, |
|
| 532 | + 0x93, |
|
| 533 | + 0x06, |
|
| 534 | + 0x93, |
|
| 535 | + 0xE3, |
|
| 536 | + 0x93, |
|
| 537 | + 0x05, |
|
| 538 | + 0x93, |
|
| 539 | + 0x05, |
|
| 540 | + 0x93, |
|
| 541 | + 0x00, |
|
| 542 | + 0x93, |
|
| 543 | + 0x04, |
|
| 544 | + 0x93, |
|
| 545 | + 0x00, |
|
| 546 | + 0x93, |
|
| 547 | + 0x00, |
|
| 548 | + 0x93, |
|
| 549 | + 0x00, |
|
| 550 | + 0x93, |
|
| 551 | + 0x00, |
|
| 552 | + 0x93, |
|
| 553 | + 0x00, |
|
| 554 | + 0x93, |
|
| 555 | + 0x00, |
|
| 556 | + 0x93, |
|
| 557 | + 0x00, |
|
| 558 | + 0x96, |
|
| 559 | + 0x00, |
|
| 560 | + 0x97, |
|
| 561 | + 0x08, |
|
| 562 | + 0x97, |
|
| 563 | + 0x19, |
|
| 564 | + 0x97, |
|
| 565 | + 0x02, |
|
| 566 | + 0x97, |
|
| 567 | + 0x0C, |
|
| 568 | + 0x97, |
|
| 569 | + 0x24, |
|
| 570 | + 0x97, |
|
| 571 | + 0x30, |
|
| 572 | + 0x97, |
|
| 573 | + 0x28, |
|
| 574 | + 0x97, |
|
| 575 | + 0x26, |
|
| 576 | + 0x97, |
|
| 577 | + 0x02, |
|
| 578 | + 0x97, |
|
| 579 | + 0x98, |
|
| 580 | + 0x97, |
|
| 581 | + 0x80, |
|
| 582 | + 0x97, |
|
| 583 | + 0x00, |
|
| 584 | + 0x97, |
|
| 585 | + 0x00, |
|
| 586 | + 0xA4, |
|
| 587 | + 0x00, |
|
| 588 | + 0xA8, |
|
| 589 | + 0x00, |
|
| 590 | + 0xC5, |
|
| 591 | + 0x11, |
|
| 592 | + 0xC6, |
|
| 593 | + 0x51, |
|
| 594 | + 0xBF, |
|
| 595 | + 0x80, |
|
| 596 | + 0xC7, |
|
| 597 | + 0x10, |
|
| 598 | + 0xB6, |
|
| 599 | + 0x66, |
|
| 600 | + 0xB8, |
|
| 601 | + 0xA5, |
|
| 602 | + 0xB7, |
|
| 603 | + 0x64, |
|
| 604 | + 0xB9, |
|
| 605 | + 0x7C, |
|
| 606 | + 0xB3, |
|
| 607 | + 0xAF, |
|
| 608 | + 0xB4, |
|
| 609 | + 0x97, |
|
| 610 | + 0xB5, |
|
| 611 | + 0xFF, |
|
| 612 | + 0xB0, |
|
| 613 | + 0xC5, |
|
| 614 | + 0xB1, |
|
| 615 | + 0x94, |
|
| 616 | + 0xB2, |
|
| 617 | + 0x0F, |
|
| 618 | + 0xC4, |
|
| 619 | + 0x5C, |
|
| 620 | + _CTRL1, |
|
| 621 | + 0xFD, |
|
| 622 | + 0x7F, |
|
| 623 | + 0x00, |
|
| 624 | + 0xE5, |
|
| 625 | + 0x1F, |
|
| 626 | + 0xE1, |
|
| 627 | + 0x67, |
|
| 628 | + 0xDD, |
|
| 629 | + 0x7F, |
|
| 630 | + _IMAGE_MODE, |
|
| 631 | + 0x00, |
|
| 632 | + _RESET, |
|
| 633 | + 0x00, |
|
| 634 | + _R_BYPASS, |
|
| 635 | + _R_BYPASS_DSP_EN, |
|
| 636 | + ] |
|
| 637 | +) |
|
| 638 | + |
|
| 639 | +_ov2640_settings_to_cif = bytes( |
|
| 640 | + [ |
|
| 641 | + _BANK_SEL, |
|
| 642 | + _BANK_SENSOR, |
|
| 643 | + _COM7, |
|
| 644 | + _COM7_RES_CIF, |
|
| 645 | + # Set the sensor output window |
|
| 646 | + _COM1, |
|
| 647 | + 0x0A, |
|
| 648 | + _REG32, |
|
| 649 | + _REG32_CIF, |
|
| 650 | + _HSTART, |
|
| 651 | + 0x11, |
|
| 652 | + _HSTOP, |
|
| 653 | + 0x43, |
|
| 654 | + _VSTART, |
|
| 655 | + 0x00, |
|
| 656 | + _VSTOP, |
|
| 657 | + 0x25, |
|
| 658 | + # _CLKRC, 0x00, |
|
| 659 | + _BD50, |
|
| 660 | + 0xCA, |
|
| 661 | + _BD60, |
|
| 662 | + 0xA8, |
|
| 663 | + 0x5A, |
|
| 664 | + 0x23, |
|
| 665 | + 0x6D, |
|
| 666 | + 0x00, |
|
| 667 | + 0x3D, |
|
| 668 | + 0x38, |
|
| 669 | + 0x39, |
|
| 670 | + 0x92, |
|
| 671 | + 0x35, |
|
| 672 | + 0xDA, |
|
| 673 | + 0x22, |
|
| 674 | + 0x1A, |
|
| 675 | + 0x37, |
|
| 676 | + 0xC3, |
|
| 677 | + 0x23, |
|
| 678 | + 0x00, |
|
| 679 | + _ARCOM2, |
|
| 680 | + 0xC0, |
|
| 681 | + 0x06, |
|
| 682 | + 0x88, |
|
| 683 | + 0x07, |
|
| 684 | + 0xC0, |
|
| 685 | + _COM4, |
|
| 686 | + 0x87, |
|
| 687 | + 0x0E, |
|
| 688 | + 0x41, |
|
| 689 | + 0x4C, |
|
| 690 | + 0x00, |
|
| 691 | + _BANK_SEL, |
|
| 692 | + _BANK_DSP, |
|
| 693 | + _RESET, |
|
| 694 | + _RESET_DVP, |
|
| 695 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 696 | + _HSIZE8, |
|
| 697 | + 0x32, |
|
| 698 | + _VSIZE8, |
|
| 699 | + 0x25, |
|
| 700 | + _SIZEL, |
|
| 701 | + 0x00, |
|
| 702 | + # Set the image window size >= output size |
|
| 703 | + _HSIZE, |
|
| 704 | + 0x64, |
|
| 705 | + _VSIZE, |
|
| 706 | + 0x4A, |
|
| 707 | + _XOFFL, |
|
| 708 | + 0x00, |
|
| 709 | + _YOFFL, |
|
| 710 | + 0x00, |
|
| 711 | + _VHYX, |
|
| 712 | + 0x00, |
|
| 713 | + _TEST, |
|
| 714 | + 0x00, |
|
| 715 | + _CTRL2, |
|
| 716 | + _CTRL2_DCW_EN | 0x1D, |
|
| 717 | + _CTRLI, |
|
| 718 | + _CTRLI_LP_DP | 0x00, |
|
| 719 | + # _R_DVP_SP, 0x08, |
|
| 720 | + ] |
|
| 721 | +) |
|
| 722 | + |
|
| 723 | +_ov2640_settings_to_svga = bytes( |
|
| 724 | + [ |
|
| 725 | + _BANK_SEL, |
|
| 726 | + _BANK_SENSOR, |
|
| 727 | + _COM7, |
|
| 728 | + _COM7_RES_SVGA, |
|
| 729 | + # Set the sensor output window |
|
| 730 | + _COM1, |
|
| 731 | + 0x0A, |
|
| 732 | + _REG32, |
|
| 733 | + _REG32_SVGA, |
|
| 734 | + _HSTART, |
|
| 735 | + 0x11, |
|
| 736 | + _HSTOP, |
|
| 737 | + 0x43, |
|
| 738 | + _VSTART, |
|
| 739 | + 0x00, |
|
| 740 | + _VSTOP, |
|
| 741 | + 0x4B, |
|
| 742 | + # _CLKRC, 0x00, |
|
| 743 | + 0x37, |
|
| 744 | + 0xC0, |
|
| 745 | + _BD50, |
|
| 746 | + 0xCA, |
|
| 747 | + _BD60, |
|
| 748 | + 0xA8, |
|
| 749 | + 0x5A, |
|
| 750 | + 0x23, |
|
| 751 | + 0x6D, |
|
| 752 | + 0x00, |
|
| 753 | + 0x3D, |
|
| 754 | + 0x38, |
|
| 755 | + 0x39, |
|
| 756 | + 0x92, |
|
| 757 | + 0x35, |
|
| 758 | + 0xDA, |
|
| 759 | + 0x22, |
|
| 760 | + 0x1A, |
|
| 761 | + 0x37, |
|
| 762 | + 0xC3, |
|
| 763 | + 0x23, |
|
| 764 | + 0x00, |
|
| 765 | + _ARCOM2, |
|
| 766 | + 0xC0, |
|
| 767 | + 0x06, |
|
| 768 | + 0x88, |
|
| 769 | + 0x07, |
|
| 770 | + 0xC0, |
|
| 771 | + _COM4, |
|
| 772 | + 0x87, |
|
| 773 | + 0x0E, |
|
| 774 | + 0x41, |
|
| 775 | + 0x42, |
|
| 776 | + 0x03, |
|
| 777 | + 0x4C, |
|
| 778 | + 0x00, |
|
| 779 | + _BANK_SEL, |
|
| 780 | + _BANK_DSP, |
|
| 781 | + _RESET, |
|
| 782 | + _RESET_DVP, |
|
| 783 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 784 | + _HSIZE8, |
|
| 785 | + 0x64, |
|
| 786 | + _VSIZE8, |
|
| 787 | + 0x4B, |
|
| 788 | + _SIZEL, |
|
| 789 | + 0x00, |
|
| 790 | + # Set the image window size >= output size |
|
| 791 | + _HSIZE, |
|
| 792 | + 0xC8, |
|
| 793 | + _VSIZE, |
|
| 794 | + 0x96, |
|
| 795 | + _XOFFL, |
|
| 796 | + 0x00, |
|
| 797 | + _YOFFL, |
|
| 798 | + 0x00, |
|
| 799 | + _VHYX, |
|
| 800 | + 0x00, |
|
| 801 | + _TEST, |
|
| 802 | + 0x00, |
|
| 803 | + _CTRL2, |
|
| 804 | + _CTRL2_DCW_EN | 0x1D, |
|
| 805 | + _CTRLI, |
|
| 806 | + _CTRLI_LP_DP | 0x00, |
|
| 807 | + # _R_DVP_SP, 0x08, |
|
| 808 | + ] |
|
| 809 | +) |
|
| 810 | + |
|
| 811 | +_ov2640_settings_to_uxga = bytes( |
|
| 812 | + [ |
|
| 813 | + _BANK_SEL, |
|
| 814 | + _BANK_SENSOR, |
|
| 815 | + _COM7, |
|
| 816 | + _COM7_RES_UXGA, |
|
| 817 | + # Set the sensor output window |
|
| 818 | + _COM1, |
|
| 819 | + 0x0F, |
|
| 820 | + _REG32, |
|
| 821 | + _REG32_UXGA, |
|
| 822 | + _HSTART, |
|
| 823 | + 0x11, |
|
| 824 | + _HSTOP, |
|
| 825 | + 0x75, |
|
| 826 | + _VSTART, |
|
| 827 | + 0x01, |
|
| 828 | + _VSTOP, |
|
| 829 | + 0x97, |
|
| 830 | + # _CLKRC, 0x00, |
|
| 831 | + 0x3D, |
|
| 832 | + 0x34, |
|
| 833 | + _BD50, |
|
| 834 | + 0xBB, |
|
| 835 | + _BD60, |
|
| 836 | + 0x9C, |
|
| 837 | + 0x5A, |
|
| 838 | + 0x57, |
|
| 839 | + 0x6D, |
|
| 840 | + 0x80, |
|
| 841 | + 0x39, |
|
| 842 | + 0x82, |
|
| 843 | + 0x23, |
|
| 844 | + 0x00, |
|
| 845 | + 0x07, |
|
| 846 | + 0xC0, |
|
| 847 | + 0x4C, |
|
| 848 | + 0x00, |
|
| 849 | + 0x35, |
|
| 850 | + 0x88, |
|
| 851 | + 0x22, |
|
| 852 | + 0x0A, |
|
| 853 | + 0x37, |
|
| 854 | + 0x40, |
|
| 855 | + _ARCOM2, |
|
| 856 | + 0xA0, |
|
| 857 | + 0x06, |
|
| 858 | + 0x02, |
|
| 859 | + _COM4, |
|
| 860 | + 0xB7, |
|
| 861 | + 0x0E, |
|
| 862 | + 0x01, |
|
| 863 | + 0x42, |
|
| 864 | + 0x83, |
|
| 865 | + _BANK_SEL, |
|
| 866 | + _BANK_DSP, |
|
| 867 | + _RESET, |
|
| 868 | + _RESET_DVP, |
|
| 869 | + # Set the sensor resolution (UXGA, SVGA, CIF) |
|
| 870 | + _HSIZE8, |
|
| 871 | + 0xC8, |
|
| 872 | + _VSIZE8, |
|
| 873 | + 0x96, |
|
| 874 | + _SIZEL, |
|
| 875 | + 0x00, |
|
| 876 | + # Set the image window size >= output size |
|
| 877 | + _HSIZE, |
|
| 878 | + 0x90, |
|
| 879 | + _VSIZE, |
|
| 880 | + 0x2C, |
|
| 881 | + _XOFFL, |
|
| 882 | + 0x00, |
|
| 883 | + _YOFFL, |
|
| 884 | + 0x00, |
|
| 885 | + _VHYX, |
|
| 886 | + 0x88, |
|
| 887 | + _TEST, |
|
| 888 | + 0x00, |
|
| 889 | + _CTRL2, |
|
| 890 | + _CTRL2_DCW_EN | 0x1D, |
|
| 891 | + _CTRLI, |
|
| 892 | + 0x00, |
|
| 893 | + # _R_DVP_SP, 0x06, |
|
| 894 | + ] |
|
| 895 | +) |
|
| 896 | + |
|
| 897 | +_ov2640_color_settings = { |
|
| 898 | + OV2640_COLOR_JPEG: bytes( |
|
| 899 | + [ |
|
| 900 | + _BANK_SEL, |
|
| 901 | + _BANK_DSP, |
|
| 902 | + _RESET, |
|
| 903 | + _RESET_JPEG | _RESET_DVP, |
|
| 904 | + _IMAGE_MODE, |
|
| 905 | + _IMAGE_MODE_JPEG_EN | _IMAGE_MODE_HREF_VSYNC, |
|
| 906 | + 0xD7, |
|
| 907 | + 0x03, |
|
| 908 | + 0xE1, |
|
| 909 | + 0x77, |
|
| 910 | + 0xE5, |
|
| 911 | + 0x1F, |
|
| 912 | + 0xD9, |
|
| 913 | + 0x10, |
|
| 914 | + 0xDF, |
|
| 915 | + 0x80, |
|
| 916 | + 0x33, |
|
| 917 | + 0x80, |
|
| 918 | + 0x3C, |
|
| 919 | + 0x10, |
|
| 920 | + 0xEB, |
|
| 921 | + 0x30, |
|
| 922 | + 0xDD, |
|
| 923 | + 0x7F, |
|
| 924 | + _RESET, |
|
| 925 | + 0x00, |
|
| 926 | + ] |
|
| 927 | + ), |
|
| 928 | + OV2640_COLOR_YUV: bytes( |
|
| 929 | + [ |
|
| 930 | + _BANK_SEL, |
|
| 931 | + _BANK_DSP, |
|
| 932 | + _RESET, |
|
| 933 | + _RESET_DVP, |
|
| 934 | + _IMAGE_MODE, |
|
| 935 | + _IMAGE_MODE_YUV422, |
|
| 936 | + 0xD7, |
|
| 937 | + 0x01, |
|
| 938 | + 0xE1, |
|
| 939 | + 0x67, |
|
| 940 | + _RESET, |
|
| 941 | + 0x00, |
|
| 942 | + ] |
|
| 943 | + ), |
|
| 944 | + OV2640_COLOR_RGB: bytes( |
|
| 945 | + [ |
|
| 946 | + _BANK_SEL, |
|
| 947 | + _BANK_DSP, |
|
| 948 | + _RESET, |
|
| 949 | + _RESET_DVP, |
|
| 950 | + _IMAGE_MODE, |
|
| 951 | + _IMAGE_MODE_RGB565, |
|
| 952 | + 0xD7, |
|
| 953 | + 0x03, |
|
| 954 | + 0xE1, |
|
| 955 | + 0x77, |
|
| 956 | + _RESET, |
|
| 957 | + 0x00, |
|
| 958 | + ] |
|
| 959 | + ), |
|
| 960 | +} |
|
| 961 | + |
|
| 962 | + |
|
| 963 | +class _RegBits: |
|
| 964 | + def __init__(self, bank: int, reg: int, shift: int, mask: int) -> None: |
|
| 965 | + self.bank = bank |
|
| 966 | + self.reg = reg |
|
| 967 | + self.shift = shift |
|
| 968 | + self.mask = mask |
|
| 969 | + |
|
| 970 | + def __get__(self, obj: "_SCCBCameraBase", objtype: Optional[Type] = None) -> int: |
|
| 971 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 972 | + return (reg_value >> self.shift) & self.mask |
|
| 973 | + |
|
| 974 | + def __set__(self, obj: "_SCCBCameraBase", value: Union[bool, int]) -> None: |
|
| 975 | + if value & ~self.mask: |
|
| 976 | + raise ValueError(f"Value 0x{value:02x} does not fit in mask 0x{self.mask:02x}") |
|
| 977 | + reg_value = obj._read_bank_register(self.bank, self.reg) |
|
| 978 | + reg_value &= ~(self.mask << self.shift) |
|
| 979 | + reg_value |= value << self.shift |
|
| 980 | + obj._write_register(self.reg, reg_value) |
|
| 981 | + |
|
| 982 | + |
|
| 983 | +class _SCCBCameraBase: |
|
| 984 | + def __init__(self, i2c_bus: I2C, i2c_address: int) -> None: |
|
| 985 | + self._i2c_device = I2CDevice(i2c_bus, i2c_address) |
|
| 986 | + self._bank = None |
|
| 987 | + |
|
| 988 | + def _get_reg_bits(self, bank: int, reg: int, shift: int, mask: int) -> int: |
|
| 989 | + return (self._read_bank_register(bank, reg) >> shift) & mask |
|
| 990 | + |
|
| 991 | + def _set_reg_bits(self, bank: int, reg: int, shift: int, mask: int, value: int) -> None: |
|
| 992 | + reg_value = self._read_bank_register(bank, reg) |
|
| 993 | + reg_value &= ~(mask << shift) |
|
| 994 | + reg_value |= value << shift |
|
| 995 | + self._write_register(reg, reg_value) |
|
| 996 | + |
|
| 997 | + def _write_list(self, reg_list: List[int]) -> None: |
|
| 998 | + for i in range(0, len(reg_list), 2): |
|
| 999 | + self._write_register(reg_list[i], reg_list[i + 1]) |
|
| 1000 | + time.sleep(0.001) |
|
| 1001 | + |
|
| 1002 | + def _write_bank_register(self, bank: int, reg: int, value: int) -> None: |
|
| 1003 | + if self._bank != bank: |
|
| 1004 | + self._write_register(_BANK_SEL, bank) |
|
| 1005 | + self._write_register(reg, value) |
|
| 1006 | + |
|
| 1007 | + def _read_bank_register(self, bank: int, reg: int) -> int: |
|
| 1008 | + if self._bank != bank: |
|
| 1009 | + self._write_register(_BANK_SEL, bank) |
|
| 1010 | + result = self._read_register(reg) |
|
| 1011 | + return result |
|
| 1012 | + |
|
| 1013 | + def _write_register(self, reg: int, value: int) -> None: |
|
| 1014 | + if reg == _BANK_SEL: |
|
| 1015 | + if self._bank == value: |
|
| 1016 | + return |
|
| 1017 | + self._bank = value |
|
| 1018 | + # print(f"write_register {reg:02x} {value:02x}") |
|
| 1019 | + b = bytearray(2) |
|
| 1020 | + b[0] = reg |
|
| 1021 | + b[1] = value |
|
| 1022 | + with self._i2c_device as i2c: |
|
| 1023 | + i2c.write(b) |
|
| 1024 | + |
|
| 1025 | + def _read_register(self, reg: int) -> int: |
|
| 1026 | + b = bytearray(1) |
|
| 1027 | + b[0] = reg |
|
| 1028 | + with self._i2c_device as i2c: |
|
| 1029 | + i2c.write(b) |
|
| 1030 | + i2c.readinto(b) |
|
| 1031 | + return b[0] |
|
| 1032 | + |
|
| 1033 | + |
|
| 1034 | +class OV2640(_SCCBCameraBase): |
|
| 1035 | + """Library for the OV2640 digital camera""" |
|
| 1036 | + |
|
| 1037 | + test_pattern = _RegBits(_BANK_SENSOR, _COM7, 1, 1) |
|
| 1038 | + gain_ceiling = _RegBits(_BANK_SENSOR, _COM9, 5, 7) |
|
| 1039 | + bpc = _RegBits(_BANK_DSP, _CTRL3, 7, 1) |
|
| 1040 | + wpc = _RegBits(_BANK_DSP, _CTRL3, 6, 1) |
|
| 1041 | + lenc = _RegBits(_BANK_DSP, _CTRL1, 1, 1) |
|
| 1042 | + |
|
| 1043 | + def __init__( |
|
| 1044 | + self, |
|
| 1045 | + i2c_bus: I2C, |
|
| 1046 | + data_pins: Pin, |
|
| 1047 | + clock: Pin, |
|
| 1048 | + vsync: Pin, |
|
| 1049 | + href: Pin, |
|
| 1050 | + shutdown: Optional[Pin] = None, |
|
| 1051 | + reset: Optional[Pin] = None, |
|
| 1052 | + mclk: Optional[Pin] = None, |
|
| 1053 | + mclk_frequency: int = 20_000_000, |
|
| 1054 | + i2c_address: int = 0x30, |
|
| 1055 | + size: int = OV2640_SIZE_QQVGA, |
|
| 1056 | + ): |
|
| 1057 | + """ |
|
| 1058 | + Args: |
|
| 1059 | + i2c_bus (busio.I2C): The I2C bus used to configure the OV2640 |
|
| 1060 | + data_pins (List[microcontroller.Pin]): A list of 8 data pins, in order. |
|
| 1061 | + clock (microcontroller.Pin): The pixel clock from the OV2640. |
|
| 1062 | + vsync (microcontroller.Pin): The vsync signal from the OV2640. |
|
| 1063 | + href (microcontroller.Pin): The href signal from the OV2640, \ |
|
| 1064 | + sometimes inaccurately called hsync. |
|
| 1065 | + shutdown (Optional[microcontroller.Pin]): If not None, the shutdown |
|
| 1066 | + signal to the camera, also called the powerdown or enable pin. |
|
| 1067 | + reset (Optional[microcontroller.Pin]): If not None, the reset signal |
|
| 1068 | + to the camera. |
|
| 1069 | + mclk (Optional[microcontroller.Pin]): The pin on which to create a |
|
| 1070 | + master clock signal, or None if the master clock signal is |
|
| 1071 | + already being generated. |
|
| 1072 | + mclk_frequency (int): The frequency of the master clock to generate, \ |
|
| 1073 | + ignored if mclk is None, requred if it is specified |
|
| 1074 | + i2c_address (int): The I2C address of the camera. |
|
| 1075 | + """ |
|
| 1076 | + |
|
| 1077 | + # Initialize the master clock |
|
| 1078 | + if mclk: |
|
| 1079 | + self._mclk_pwm = pwmio.PWMOut(mclk, frequency=mclk_frequency) |
|
| 1080 | + self._mclk_pwm.duty_cycle = 32768 |
|
| 1081 | + else: |
|
| 1082 | + self._mclk_pwm = None |
|
| 1083 | + |
|
| 1084 | + if shutdown: |
|
| 1085 | + self._shutdown = digitalio.DigitalInOut(shutdown) |
|
| 1086 | + self._shutdown.switch_to_output(True) |
|
| 1087 | + time.sleep(0.1) |
|
| 1088 | + self._shutdown.switch_to_output(False) |
|
| 1089 | + time.sleep(0.3) |
|
| 1090 | + else: |
|
| 1091 | + self._shutdown = None |
|
| 1092 | + |
|
| 1093 | + if reset: |
|
| 1094 | + self._reset = digitalio.DigitalInOut(reset) |
|
| 1095 | + self._reset.switch_to_output(False) |
|
| 1096 | + time.sleep(0.1) |
|
| 1097 | + self._reset.switch_to_output(True) |
|
| 1098 | + time.sleep(0.1) |
|
| 1099 | + |
|
| 1100 | + super().__init__(i2c_bus, i2c_address) |
|
| 1101 | + |
|
| 1102 | + self._write_bank_register(_BANK_SENSOR, _COM7, _COM7_SRST) |
|
| 1103 | + time.sleep(0.001) |
|
| 1104 | + |
|
| 1105 | + self._write_list(_ov2640_settings_cif) |
|
| 1106 | + |
|
| 1107 | + self._colorspace = OV2640_COLOR_RGB |
|
| 1108 | + self._w = None |
|
| 1109 | + self._h = None |
|
| 1110 | + self._size = None |
|
| 1111 | + self._test_pattern = False |
|
| 1112 | + self.size = size |
|
| 1113 | + |
|
| 1114 | + self._flip_x = False |
|
| 1115 | + self._flip_y = False |
|
| 1116 | + |
|
| 1117 | + self.gain_ceiling = _COM9_AGC_GAIN_2x |
|
| 1118 | + self.bpc = False |
|
| 1119 | + self.wpc = True |
|
| 1120 | + self.lenc = True |
|
| 1121 | + |
|
| 1122 | + # self._sensor_init() |
|
| 1123 | + |
|
| 1124 | + self._imagecapture = imagecapture.ParallelImageCapture( |
|
| 1125 | + data_pins=data_pins, clock=clock, vsync=vsync, href=href |
|
| 1126 | + ) |
|
| 1127 | + |
|
| 1128 | + def capture(self, buf: WriteableBuffer) -> Optional[memoryview]: |
|
| 1129 | + """Capture an image into the buffer. |
|
| 1130 | + |
|
| 1131 | + Args: |
|
| 1132 | + buf (WriteableBuffer): A WritableBuffer to contain the \ |
|
| 1133 | + captured image. Note that this can be a ulab array or a displayio Bitmap. |
|
| 1134 | + """ |
|
| 1135 | + self._imagecapture.capture(buf) |
|
| 1136 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1137 | + eoi = buf.find(b"\xff\xd9") |
|
| 1138 | + if eoi != -1: |
|
| 1139 | + # terminate the JPEG data just after the EOI marker |
|
| 1140 | + return memoryview(buf)[: eoi + 2] |
|
| 1141 | + return None |
|
| 1142 | + |
|
| 1143 | + @property |
|
| 1144 | + def capture_buffer_size(self) -> int: |
|
| 1145 | + """Return the size of capture buffer to use with current resolution & colorspace settings""" |
|
| 1146 | + if self.colorspace == OV2640_COLOR_JPEG: |
|
| 1147 | + return self.width * self.height // 5 |
|
| 1148 | + return self.width * self.height * 2 |
|
| 1149 | + |
|
| 1150 | + @property |
|
| 1151 | + def mclk_frequency(self) -> Optional[int]: |
|
| 1152 | + """Get the actual frequency the generated mclk, or None""" |
|
| 1153 | + return self._mclk_pwm.frequency if self._mclk_pwm else None |
|
| 1154 | + |
|
| 1155 | + @property |
|
| 1156 | + def width(self) -> int: |
|
| 1157 | + """Get the image width in pixels. A buffer of 2*width*height bytes \ |
|
| 1158 | + stores a whole image.""" |
|
| 1159 | + return self._w |
|
| 1160 | + |
|
| 1161 | + @property |
|
| 1162 | + def height(self) -> int: |
|
| 1163 | + """Get the image height in pixels. A buffer of 2*width*height bytes \ |
|
| 1164 | + stores a whole image.""" |
|
| 1165 | + return self._h |
|
| 1166 | + |
|
| 1167 | + @property |
|
| 1168 | + def colorspace(self) -> bytes: |
|
| 1169 | + """Get or set the colorspace, one of the ``OV2640_COLOR_`` constants.""" |
|
| 1170 | + return self._colorspace |
|
| 1171 | + |
|
| 1172 | + @colorspace.setter |
|
| 1173 | + def colorspace(self, colorspace: bytes) -> None: |
|
| 1174 | + self._colorspace = colorspace |
|
| 1175 | + self._set_size_and_colorspace() |
|
| 1176 | + |
|
| 1177 | + def _set_colorspace(self) -> None: |
|
| 1178 | + colorspace = self._colorspace |
|
| 1179 | + settings = _ov2640_color_settings[colorspace] |
|
| 1180 | + |
|
| 1181 | + self._write_list(settings) |
|
| 1182 | + # written twice? |
|
| 1183 | + self._write_list(settings) |
|
| 1184 | + time.sleep(0.01) |
|
| 1185 | + |
|
| 1186 | + def deinit(self) -> None: |
|
| 1187 | + """Deinitialize the camera""" |
|
| 1188 | + self._imagecapture.deinit() |
|
| 1189 | + if self._mclk_pwm: |
|
| 1190 | + self._mclk_pwm.deinit() |
|
| 1191 | + if self._shutdown: |
|
| 1192 | + self._shutdown.deinit() |
|
| 1193 | + if self._reset: |
|
| 1194 | + self._reset.deinit() |
|
| 1195 | + |
|
| 1196 | + @property |
|
| 1197 | + def size(self) -> int: |
|
| 1198 | + """Get or set the captured image size, one of the ``OV2640_SIZE_`` constants.""" |
|
| 1199 | + return self._size |
|
| 1200 | + |
|
| 1201 | + def _set_size_and_colorspace(self) -> None: |
|
| 1202 | + size = self._size |
|
| 1203 | + width, height, ratio = _resolution_info[size] |
|
| 1204 | + offset_x, offset_y, max_x, max_y = _ratio_table[ratio] |
|
| 1205 | + mode = _OV2640_MODE_UXGA |
|
| 1206 | + if size <= OV2640_SIZE_CIF: |
|
| 1207 | + mode = _OV2640_MODE_CIF |
|
| 1208 | + max_x //= 4 |
|
| 1209 | + max_y //= 4 |
|
| 1210 | + offset_x //= 4 |
|
| 1211 | + offset_y //= 4 |
|
| 1212 | + max_y = min(max_y, 296) |
|
| 1213 | + |
|
| 1214 | + elif size <= OV2640_SIZE_SVGA: |
|
| 1215 | + mode = _OV2640_MODE_SVGA |
|
| 1216 | + max_x //= 2 |
|
| 1217 | + max_y //= 2 |
|
| 1218 | + offset_x //= 2 |
|
| 1219 | + offset_y //= 2 |
|
| 1220 | + |
|
| 1221 | + self._set_window(mode, offset_x, offset_y, max_x, max_y, width, height) |
|
| 1222 | + |
|
| 1223 | + @size.setter |
|
| 1224 | + def size(self, size: int) -> None: |
|
| 1225 | + self._size = size |
|
| 1226 | + self._set_size_and_colorspace() |
|
| 1227 | + |
|
| 1228 | + def _set_flip(self) -> None: |
|
| 1229 | + bits = 0 |
|
| 1230 | + if self._flip_x: |
|
| 1231 | + bits |= _REG04_HFLIP_IMG |
|
| 1232 | + if self._flip_y: |
|
| 1233 | + bits |= _REG04_VFLIP_IMG | _REG04_VREF_EN |
|
| 1234 | + self._write_bank_register(_BANK_SENSOR, _REG04, _REG04_SET(bits)) |
|
| 1235 | + |
|
| 1236 | + @property |
|
| 1237 | + def flip_x(self) -> bool: |
|
| 1238 | + """Get or set the X-flip flag""" |
|
| 1239 | + return self._flip_x |
|
| 1240 | + |
|
| 1241 | + @flip_x.setter |
|
| 1242 | + def flip_x(self, value: bool) -> None: |
|
| 1243 | + self._flip_x = bool(value) |
|
| 1244 | + self._set_flip() |
|
| 1245 | + |
|
| 1246 | + @property |
|
| 1247 | + def flip_y(self) -> bool: |
|
| 1248 | + """Get or set the Y-flip flag""" |
|
| 1249 | + return self._flip_y |
|
| 1250 | + |
|
| 1251 | + @flip_y.setter |
|
| 1252 | + def flip_y(self, value: bool) -> None: |
|
| 1253 | + self._flip_y = bool(value) |
|
| 1254 | + self._set_flip() |
|
| 1255 | + |
|
| 1256 | + @property |
|
| 1257 | + def product_id(self) -> int: |
|
| 1258 | + """Get the product id (PID) register. The expected value is 0x26.""" |
|
| 1259 | + return self._read_bank_register(_BANK_SENSOR, _REG_PID) |
|
| 1260 | + |
|
| 1261 | + @property |
|
| 1262 | + def product_version(self) -> int: |
|
| 1263 | + """Get the version (VER) register. The expected value is 0x41.""" |
|
| 1264 | + return self._read_bank_register(_BANK_SENSOR, _REG_VER) |
|
| 1265 | + |
|
| 1266 | + def _set_window( |
|
| 1267 | + self, |
|
| 1268 | + mode: int, |
|
| 1269 | + offset_x: int, |
|
| 1270 | + offset_y: int, |
|
| 1271 | + max_x: int, |
|
| 1272 | + max_y: int, |
|
| 1273 | + width: int, |
|
| 1274 | + height: int, |
|
| 1275 | + ) -> None: |
|
| 1276 | + self._w = width |
|
| 1277 | + self._h = height |
|
| 1278 | + |
|
| 1279 | + max_x //= 4 |
|
| 1280 | + max_y //= 4 |
|
| 1281 | + width //= 4 |
|
| 1282 | + height //= 4 |
|
| 1283 | + |
|
| 1284 | + win_regs = [ |
|
| 1285 | + _BANK_SEL, |
|
| 1286 | + _BANK_DSP, |
|
| 1287 | + _HSIZE, |
|
| 1288 | + max_x & 0xFF, |
|
| 1289 | + _VSIZE, |
|
| 1290 | + max_y & 0xFF, |
|
| 1291 | + _XOFFL, |
|
| 1292 | + offset_x & 0xFF, |
|
| 1293 | + _YOFFL, |
|
| 1294 | + offset_y & 0xFF, |
|
| 1295 | + _VHYX, |
|
| 1296 | + ((max_y >> 1) & 0x80) |
|
| 1297 | + | ((offset_y >> 4) & 0x70) |
|
| 1298 | + | ((max_x >> 5) & 0x08) |
|
| 1299 | + | ((offset_y >> 8) & 0x07), |
|
| 1300 | + _TEST, |
|
| 1301 | + (max_x >> 2) & 0x80, |
|
| 1302 | + _ZMOW, |
|
| 1303 | + (width) & 0xFF, |
|
| 1304 | + _ZMOH, |
|
| 1305 | + (height) & 0xFF, |
|
| 1306 | + _ZMHH, |
|
| 1307 | + ((height >> 6) & 0x04) | ((width >> 8) & 0x03), |
|
| 1308 | + ] |
|
| 1309 | + |
|
| 1310 | + pclk_auto = 0 |
|
| 1311 | + pclk_div = 8 |
|
| 1312 | + clk_2x = 0 |
|
| 1313 | + clk_div = 0 |
|
| 1314 | + |
|
| 1315 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1316 | + pclk_auto = 1 |
|
| 1317 | + clk_div = 7 |
|
| 1318 | + |
|
| 1319 | + if mode == _OV2640_MODE_CIF: |
|
| 1320 | + regs = _ov2640_settings_to_cif |
|
| 1321 | + if self._colorspace != OV2640_COLOR_JPEG: |
|
| 1322 | + clk_div = 3 |
|
| 1323 | + elif mode == _OV2640_MODE_SVGA: |
|
| 1324 | + regs = _ov2640_settings_to_svga |
|
| 1325 | + else: |
|
| 1326 | + regs = _ov2640_settings_to_uxga |
|
| 1327 | + pclk_div = 12 |
|
| 1328 | + |
|
| 1329 | + clk = clk_div | (clk_2x << 7) |
|
| 1330 | + pclk = pclk_div | (pclk_auto << 7) |
|
| 1331 | + |
|
| 1332 | + self._write_bank_register(_BANK_DSP, _R_BYPASS, _R_BYPASS_DSP_BYPAS) |
|
| 1333 | + self._write_list(regs) |
|
| 1334 | + self._write_list(win_regs) |
|
| 1335 | + self._write_bank_register(_BANK_SENSOR, _CLKRC, clk) |
|
| 1336 | + self._write_bank_register(_BANK_DSP, _R_DVP_SP, pclk) |
|
| 1337 | + self._write_register(_R_BYPASS, _R_BYPASS_DSP_EN) |
|
| 1338 | + time.sleep(0.01) |
|
| 1339 | + |
|
| 1340 | + # Reestablish colorspace |
|
| 1341 | + self._set_colorspace() |
|
| 1342 | + |
|
| 1343 | + # Reestablish test pattern |
|
| 1344 | + if self._test_pattern: |
|
| 1345 | + self.test_pattern = self._test_pattern |
|
| 1346 | + |
|
| 1347 | + @property |
|
| 1348 | + def exposure(self) -> int: |
|
| 1349 | + """The exposure level of the sensor""" |
|
| 1350 | + aec_9_2 = self._get_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF) |
|
| 1351 | + aec_15_10 = self._get_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111) |
|
| 1352 | + aec_1_0 = self._get_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11) |
|
| 1353 | + |
|
| 1354 | + return aec_1_0 | (aec_9_2 << 2) | (aec_15_10 << 10) |
|
| 1355 | + |
|
| 1356 | + @exposure.setter |
|
| 1357 | + def exposure(self, exposure: int) -> None: |
|
| 1358 | + aec_1_0 = exposure & 0x11 |
|
| 1359 | + aec_9_2 = (exposure >> 2) & 0b11111111 |
|
| 1360 | + aec_15_10 = exposure >> 10 |
|
| 1361 | + |
|
| 1362 | + self._set_reg_bits(_BANK_SENSOR, _AEC, 0, 0xFF, aec_9_2) |
|
| 1363 | + self._set_reg_bits(_BANK_SENSOR, _REG45, 0, 0b111111, aec_15_10) |
|
| 1364 | + self._set_reg_bits(_BANK_SENSOR, _REG04, 0, 0b11, aec_1_0) |
SDK-dat/python-dat/circuitpython-dat/adafruit_ov2640/ov2640_micropython_test.py
| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | +# mpremote connect COM6 fs cp ov2640_micropython_test.py : |
|
| 2 | +# mpremote connect COM6 run ov2640_micropython_test.py |
|
| 3 | + |
|
| 4 | +import camera # type: ignore |
|
| 5 | +import time |
|
| 6 | +import sys |
|
| 7 | + |
|
| 8 | +# Initialize camera with ESP1000 pin definitions |
|
| 9 | +try: |
|
| 10 | + camera.init(0, |
|
| 11 | + d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35, |
|
| 12 | + format=camera.JPEG, |
|
| 13 | + framesize=camera.FRAME_QQVGA, # 160x120 |
|
| 14 | + xclk_freq=camera.XCLK_20MHz, |
|
| 15 | + href=23, vsync=25, reset=-1, pwdn=32, |
|
| 16 | + sioc=27, siod=26, xclk=0, pclk=22 |
|
| 17 | + ) |
|
| 18 | + print("Camera initialized successfully") |
|
| 19 | +except Exception as e: |
|
| 20 | + print("Camera init failed:", e) |
|
| 21 | + sys.exit() |
|
| 22 | + |
|
| 23 | +# Simple test - capture and save images |
|
| 24 | +count = 0 |
|
| 25 | +while True: |
|
| 26 | + try: |
|
| 27 | + print("Capturing image", count) |
|
| 28 | + buf = camera.capture() |
|
| 29 | + print("Image size:", len(buf), "bytes") |
|
| 30 | + |
|
| 31 | + # Save image |
|
| 32 | + filename = f"test_{count:03d}.jpg" |
|
| 33 | + with open(filename, 'wb') as f: |
|
| 34 | + f.write(buf) |
|
| 35 | + print("Saved:", filename) |
|
| 36 | + |
|
| 37 | + count += 1 |
|
| 38 | + time.sleep(2) |
|
| 39 | + |
|
| 40 | + # Stop after 5 images for testing |
|
| 41 | + if count >= 5: |
|
| 42 | + break |
|
| 43 | + |
|
| 44 | + except Exception as e: |
|
| 45 | + print("Capture error:", e) |
|
| 46 | + break |
|
| 47 | + |
|
| 48 | +print("Test completed") |
|
| 49 | +camera.deinit() |
SDK-dat/python-dat/circuitpython-dat/adafruit_ov2640/ov2640_simpletest.py
| ... | ... | @@ -0,0 +1,74 @@ |
| 1 | +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | +# |
|
| 4 | +# SPDX-License-Identifier: Unlicense |
|
| 5 | + |
|
| 6 | +"""Capture an image from the camera and display it as ASCII art. |
|
| 7 | + |
|
| 8 | +This demo is designed to run on the Kaluga, but you can adapt it |
|
| 9 | +to other boards by changing the constructors for `bus` and `cam` |
|
| 10 | +appropriately. |
|
| 11 | + |
|
| 12 | +The camera is placed in YUV mode, so the top 8 bits of each color |
|
| 13 | +value can be treated as "greyscale". |
|
| 14 | + |
|
| 15 | +It's important that you use a terminal program that can interpret |
|
| 16 | +"ANSI" escape sequences. The demo uses them to "paint" each frame |
|
| 17 | +on top of the prevous one, rather than scrolling. |
|
| 18 | + |
|
| 19 | +Remember to take the lens cap off, or un-comment the line setting |
|
| 20 | +the test pattern! |
|
| 21 | +""" |
|
| 22 | + |
|
| 23 | +import sys |
|
| 24 | +import time |
|
| 25 | + |
|
| 26 | +import board |
|
| 27 | +import busio |
|
| 28 | + |
|
| 29 | +import adafruit_ov2640 |
|
| 30 | + |
|
| 31 | +# mpremote connect COM6 fs put adafruit_ov2640.py : |
|
| 32 | +# mpremote connect COM6 fs put ov2640_simpletest.py : |
|
| 33 | +# mpremote connect COM6 fs run ov2640_simpletest.py |
|
| 34 | + |
|
| 35 | + |
|
| 36 | +# Pin definitions adapted from ESP1000-2-dat.py |
|
| 37 | +# d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35 |
|
| 38 | +# href=23, vsync=25, sioc=27, siod=26, xclk=0, pclk=22 |
|
| 39 | +data_pins = [board.GP5, board.GP18, board.GP19, board.GP21, board.GP36, board.GP39, board.GP34, board.GP35] |
|
| 40 | + |
|
| 41 | +bus = busio.I2C(scl=board.GP27, sda=board.GP26) # sioc=27, siod=26 |
|
| 42 | + |
|
| 43 | +cam = adafruit_ov2640.OV2640( |
|
| 44 | + bus, |
|
| 45 | + data_pins=data_pins, |
|
| 46 | + clock=board.GP22, # pclk=22 |
|
| 47 | + vsync=board.GP25, # vsync=25 |
|
| 48 | + href=board.GP23, # href=23 |
|
| 49 | + mclk=board.GP0, # xclk=0 |
|
| 50 | + mclk_frequency=20_000_000, |
|
| 51 | + size=adafruit_ov2640.OV2640_SIZE_QQVGA, |
|
| 52 | +) |
|
| 53 | +cam.colorspace = adafruit_ov2640.OV2640_COLOR_YUV |
|
| 54 | +cam.flip_y = True |
|
| 55 | +# cam.test_pattern = True |
|
| 56 | + |
|
| 57 | +buf = bytearray(2 * cam.width * cam.height) |
|
| 58 | +chars = b" .:-=+*#%@" |
|
| 59 | +remap = [chars[i * (len(chars) - 1) // 255] for i in range(256)] |
|
| 60 | + |
|
| 61 | +width = cam.width |
|
| 62 | +row = bytearray(2 * width) |
|
| 63 | + |
|
| 64 | +sys.stdout.write("\033[2J") |
|
| 65 | +while True: |
|
| 66 | + cam.capture(buf) |
|
| 67 | + for j in range(cam.height // 2): |
|
| 68 | + sys.stdout.write(f"\033[{j}H") |
|
| 69 | + for i in range(cam.width // 2): |
|
| 70 | + row[i * 2] = row[i * 2 + 1] = remap[buf[4 * (width * j + i)]] |
|
| 71 | + sys.stdout.write(row) |
|
| 72 | + sys.stdout.write("\033[K") |
|
| 73 | + sys.stdout.write("\033[J") |
|
| 74 | + time.sleep(0.05) |
|
| ... | ... | \ No newline at end of file |
SDK-dat/python-dat/circuitpython-dat/adafruit_pycamera1/cam1.py
| ... | ... | @@ -0,0 +1,298 @@ |
| 1 | + |
|
| 2 | +# SPDX-FileCopyrightText: 2023 Jeff Epler for Adafruit Industries |
|
| 3 | +# SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries |
|
| 4 | +# |
|
| 5 | +# SPDX-License-Identifier: Unlicense |
|
| 6 | +import os |
|
| 7 | +import ssl |
|
| 8 | +import time |
|
| 9 | + |
|
| 10 | +import adafruit_ntp |
|
| 11 | +import adafruit_requests |
|
| 12 | +import bitmaptools |
|
| 13 | +import displayio |
|
| 14 | +import gifio |
|
| 15 | +import rtc |
|
| 16 | +import socketpool |
|
| 17 | +import ulab.numpy as np |
|
| 18 | +import wifi |
|
| 19 | + |
|
| 20 | +import adafruit_pycamera |
|
| 21 | + |
|
| 22 | +# Wifi details are in settings.toml file, also, |
|
| 23 | +# timezone info should be included to allow local time and DST adjustments |
|
| 24 | +# # UTC_OFFSET, if present, will override TZ and DST and no API query will be done |
|
| 25 | +# UTC_OFFSET=-25200 |
|
| 26 | +# # TZ="America/Phoenix" |
|
| 27 | + |
|
| 28 | +UTC_OFFSET = os.getenv("UTC_OFFSET") |
|
| 29 | +TZ = os.getenv("TZ") |
|
| 30 | + |
|
| 31 | +print(f"Connecting to {os.getenv('CIRCUITPY_WIFI_SSID')}") |
|
| 32 | +SSID = os.getenv("CIRCUITPY_WIFI_SSID") |
|
| 33 | +PASSWORD = os.getenv("CIRCUITPY_WIFI_PASSWORD") |
|
| 34 | + |
|
| 35 | +if SSID and PASSWORD: |
|
| 36 | + wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD")) |
|
| 37 | + if wifi.radio.connected: |
|
| 38 | + print(f"Connected to {os.getenv('CIRCUITPY_WIFI_SSID')}!") |
|
| 39 | + print("My IP address is", wifi.radio.ipv4_address) |
|
| 40 | + pool = socketpool.SocketPool(wifi.radio) |
|
| 41 | + |
|
| 42 | + if UTC_OFFSET is None: |
|
| 43 | + requests = adafruit_requests.Session(pool, ssl.create_default_context()) |
|
| 44 | + response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ) |
|
| 45 | + response_as_json = response.json() |
|
| 46 | + UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"] |
|
| 47 | + print(f"UTC_OFFSET: {UTC_OFFSET}") |
|
| 48 | + |
|
| 49 | + ntp = adafruit_ntp.NTP(pool, server="pool.ntp.org", tz_offset=UTC_OFFSET // 3600) |
|
| 50 | + |
|
| 51 | + print(f"ntp time: {ntp.datetime}") |
|
| 52 | + rtc.RTC().datetime = ntp.datetime |
|
| 53 | + else: |
|
| 54 | + print("Wifi failed to connect. Time not set.") |
|
| 55 | +else: |
|
| 56 | + print("Wifi config not found in settintgs.toml. Time not set.") |
|
| 57 | + |
|
| 58 | +pycam = adafruit_pycamera.PyCamera() |
|
| 59 | +# pycam.live_preview_mode() |
|
| 60 | + |
|
| 61 | +settings = ( |
|
| 62 | + None, |
|
| 63 | + "resolution", |
|
| 64 | + "effect", |
|
| 65 | + "mode", |
|
| 66 | + "led_level", |
|
| 67 | + "led_color", |
|
| 68 | + "timelapse_rate", |
|
| 69 | +) |
|
| 70 | +curr_setting = 0 |
|
| 71 | + |
|
| 72 | +print("Starting!") |
|
| 73 | +# pycam.tone(200, 0.1) |
|
| 74 | +last_frame = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535) |
|
| 75 | +onionskin = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535) |
|
| 76 | +timelapse_remaining = None |
|
| 77 | +timelapse_timestamp = None |
|
| 78 | + |
|
| 79 | +while True: |
|
| 80 | + if pycam.mode_text == "STOP" and pycam.stop_motion_frame != 0: |
|
| 81 | + # alpha blend |
|
| 82 | + new_frame = pycam.continuous_capture() |
|
| 83 | + bitmaptools.alphablend( |
|
| 84 | + onionskin, last_frame, new_frame, displayio.Colorspace.RGB565_SWAPPED |
|
| 85 | + ) |
|
| 86 | + pycam.blit(onionskin) |
|
| 87 | + elif pycam.mode_text == "GBOY": |
|
| 88 | + bitmaptools.dither( |
|
| 89 | + last_frame, pycam.continuous_capture(), displayio.Colorspace.RGB565_SWAPPED |
|
| 90 | + ) |
|
| 91 | + pycam.blit(last_frame) |
|
| 92 | + elif pycam.mode_text == "LAPS": |
|
| 93 | + if timelapse_remaining is None: |
|
| 94 | + pycam.timelapsestatus_label.text = "STOP" |
|
| 95 | + else: |
|
| 96 | + timelapse_remaining = timelapse_timestamp - time.time() |
|
| 97 | + pycam.timelapsestatus_label.text = f"{timelapse_remaining}s / " |
|
| 98 | + # Manually updating the label text a second time ensures that the label |
|
| 99 | + # is re-painted over the blitted preview. |
|
| 100 | + pycam.timelapse_rate_label.text = pycam.timelapse_rate_label.text |
|
| 101 | + pycam.timelapse_submode_label.text = pycam.timelapse_submode_label.text |
|
| 102 | + |
|
| 103 | + # only in high power mode do we continuously preview |
|
| 104 | + if (timelapse_remaining is None) or (pycam.timelapse_submode_label.text == "HiPwr"): |
|
| 105 | + pycam.blit(pycam.continuous_capture()) |
|
| 106 | + if pycam.timelapse_submode_label.text == "LowPwr" and (timelapse_remaining is not None): |
|
| 107 | + pycam.display.brightness = 0.05 |
|
| 108 | + else: |
|
| 109 | + pycam.display.brightness = 1 |
|
| 110 | + pycam.display.refresh() |
|
| 111 | + |
|
| 112 | + if timelapse_remaining is not None and timelapse_remaining <= 0: |
|
| 113 | + # no matter what, show what was just on the camera |
|
| 114 | + pycam.blit(pycam.continuous_capture()) |
|
| 115 | + # pycam.tone(200, 0.1) # uncomment to add a beep when a photo is taken |
|
| 116 | + try: |
|
| 117 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 118 | + pycam.capture_jpeg() |
|
| 119 | + except TypeError: |
|
| 120 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 121 | + time.sleep(0.5) |
|
| 122 | + except RuntimeError: |
|
| 123 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 124 | + time.sleep(0.5) |
|
| 125 | + pycam.live_preview_mode() |
|
| 126 | + pycam.display.refresh() |
|
| 127 | + pycam.blit(pycam.continuous_capture()) |
|
| 128 | + timelapse_timestamp = time.time() + pycam.timelapse_rates[pycam.timelapse_rate] + 1 |
|
| 129 | + else: |
|
| 130 | + pycam.blit(pycam.continuous_capture()) |
|
| 131 | + # print("\t\t", capture_time, blit_time) |
|
| 132 | + |
|
| 133 | + pycam.keys_debounce() |
|
| 134 | + # test shutter button |
|
| 135 | + if pycam.shutter.long_press: |
|
| 136 | + print("FOCUS") |
|
| 137 | + print(pycam.autofocus_status) |
|
| 138 | + pycam.autofocus() |
|
| 139 | + print(pycam.autofocus_status) |
|
| 140 | + if pycam.shutter.short_count: |
|
| 141 | + print("Shutter released") |
|
| 142 | + if pycam.mode_text == "STOP": |
|
| 143 | + pycam.capture_into_bitmap(last_frame) |
|
| 144 | + pycam.stop_motion_frame += 1 |
|
| 145 | + try: |
|
| 146 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 147 | + pycam.capture_jpeg() |
|
| 148 | + except TypeError: |
|
| 149 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 150 | + time.sleep(0.5) |
|
| 151 | + except RuntimeError: |
|
| 152 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 153 | + time.sleep(0.5) |
|
| 154 | + pycam.live_preview_mode() |
|
| 155 | + |
|
| 156 | + if pycam.mode_text == "GBOY": |
|
| 157 | + try: |
|
| 158 | + f = pycam.open_next_image("gif") |
|
| 159 | + except RuntimeError: |
|
| 160 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 161 | + time.sleep(0.5) |
|
| 162 | + continue |
|
| 163 | + |
|
| 164 | + with gifio.GifWriter( |
|
| 165 | + f, |
|
| 166 | + pycam.camera.width, |
|
| 167 | + pycam.camera.height, |
|
| 168 | + displayio.Colorspace.RGB565_SWAPPED, |
|
| 169 | + dither=True, |
|
| 170 | + ) as g: |
|
| 171 | + g.add_frame(last_frame, 1) |
|
| 172 | + |
|
| 173 | + if pycam.mode_text == "GIF": |
|
| 174 | + try: |
|
| 175 | + f = pycam.open_next_image("gif") |
|
| 176 | + except RuntimeError: |
|
| 177 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 178 | + time.sleep(0.5) |
|
| 179 | + continue |
|
| 180 | + i = 0 |
|
| 181 | + ft = [] |
|
| 182 | + pycam._mode_label.text = "RECORDING" |
|
| 183 | + |
|
| 184 | + pycam.display.refresh() |
|
| 185 | + with gifio.GifWriter( |
|
| 186 | + f, |
|
| 187 | + pycam.camera.width, |
|
| 188 | + pycam.camera.height, |
|
| 189 | + displayio.Colorspace.RGB565_SWAPPED, |
|
| 190 | + dither=True, |
|
| 191 | + ) as g: |
|
| 192 | + t00 = t0 = time.monotonic() |
|
| 193 | + while (i < 15) or not pycam.shutter_button.value: |
|
| 194 | + i += 1 |
|
| 195 | + _gifframe = pycam.continuous_capture() |
|
| 196 | + g.add_frame(_gifframe, 0.12) |
|
| 197 | + pycam.blit(_gifframe) |
|
| 198 | + t1 = time.monotonic() |
|
| 199 | + ft.append(1 / (t1 - t0)) |
|
| 200 | + print(end=".") |
|
| 201 | + t0 = t1 |
|
| 202 | + pycam._mode_label.text = "GIF" |
|
| 203 | + print(f"\nfinal size {f.tell()} for {i} frames") |
|
| 204 | + print(f"average framerate {i / (t1 - t00)}fps") |
|
| 205 | + print(f"best {max(ft)} worst {min(ft)} std. deviation {np.std(ft)}") |
|
| 206 | + f.close() |
|
| 207 | + pycam.display.refresh() |
|
| 208 | + |
|
| 209 | + if pycam.mode_text == "JPEG": |
|
| 210 | + pycam.tone(200, 0.1) |
|
| 211 | + try: |
|
| 212 | + pycam.display_message("Snap!", color=0x0000FF) |
|
| 213 | + pycam.capture_jpeg() |
|
| 214 | + pycam.live_preview_mode() |
|
| 215 | + except TypeError: |
|
| 216 | + pycam.display_message("Failed", color=0xFF0000) |
|
| 217 | + time.sleep(0.5) |
|
| 218 | + pycam.live_preview_mode() |
|
| 219 | + except RuntimeError: |
|
| 220 | + pycam.display_message("Error\nNo SD Card", color=0xFF0000) |
|
| 221 | + time.sleep(0.5) |
|
| 222 | + |
|
| 223 | + if pycam.card_detect.fell: |
|
| 224 | + print("SD card removed") |
|
| 225 | + pycam.unmount_sd_card() |
|
| 226 | + pycam.display.refresh() |
|
| 227 | + if pycam.card_detect.rose: |
|
| 228 | + print("SD card inserted") |
|
| 229 | + pycam.display_message("Mounting\nSD Card", color=0xFFFFFF) |
|
| 230 | + for _ in range(3): |
|
| 231 | + try: |
|
| 232 | + print("Mounting card") |
|
| 233 | + pycam.mount_sd_card() |
|
| 234 | + print("Success!") |
|
| 235 | + break |
|
| 236 | + except OSError as e: |
|
| 237 | + print("Retrying!", e) |
|
| 238 | + time.sleep(0.5) |
|
| 239 | + else: |
|
| 240 | + pycam.display_message("SD Card\nFailed!", color=0xFF0000) |
|
| 241 | + time.sleep(0.5) |
|
| 242 | + pycam.display.refresh() |
|
| 243 | + |
|
| 244 | + if pycam.up.fell: |
|
| 245 | + print("UP") |
|
| 246 | + key = settings[curr_setting] |
|
| 247 | + if key: |
|
| 248 | + print("getting", key, getattr(pycam, key)) |
|
| 249 | + setattr(pycam, key, getattr(pycam, key) + 1) |
|
| 250 | + if pycam.down.fell: |
|
| 251 | + print("DN") |
|
| 252 | + key = settings[curr_setting] |
|
| 253 | + if key: |
|
| 254 | + setattr(pycam, key, getattr(pycam, key) - 1) |
|
| 255 | + if pycam.right.fell: |
|
| 256 | + print("RT") |
|
| 257 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 258 | + if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelapse_rate": |
|
| 259 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 260 | + print(settings[curr_setting]) |
|
| 261 | + # new_res = min(len(pycam.resolutions)-1, pycam.get_resolution()+1) |
|
| 262 | + # pycam.set_resolution(pycam.resolutions[new_res]) |
|
| 263 | + pycam.select_setting(settings[curr_setting]) |
|
| 264 | + if pycam.left.fell: |
|
| 265 | + print("LF") |
|
| 266 | + curr_setting = (curr_setting - 1 + len(settings)) % len(settings) |
|
| 267 | + if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelaps_rate": |
|
| 268 | + curr_setting = (curr_setting + 1) % len(settings) |
|
| 269 | + print(settings[curr_setting]) |
|
| 270 | + pycam.select_setting(settings[curr_setting]) |
|
| 271 | + # new_res = max(1, pycam.get_resolution()-1) |
|
| 272 | + # pycam.set_resolution(pycam.resolutions[new_res]) |
|
| 273 | + if pycam.select.fell: |
|
| 274 | + print("SEL") |
|
| 275 | + if pycam.mode_text == "LAPS": |
|
| 276 | + pycam.timelapse_submode += 1 |
|
| 277 | + pycam.display.refresh() |
|
| 278 | + if pycam.ok.fell: |
|
| 279 | + print("OK") |
|
| 280 | + if pycam.mode_text == "LAPS": |
|
| 281 | + if timelapse_remaining is None: # stopped |
|
| 282 | + print("Starting timelapse") |
|
| 283 | + timelapse_remaining = pycam.timelapse_rates[pycam.timelapse_rate] |
|
| 284 | + timelapse_timestamp = time.time() + timelapse_remaining + 1 |
|
| 285 | + # dont let the camera take over auto-settings |
|
| 286 | + saved_settings = pycam.get_camera_autosettings() |
|
| 287 | + # print(f"Current exposure {saved_settings=}") |
|
| 288 | + pycam.set_camera_exposure(saved_settings["exposure"]) |
|
| 289 | + pycam.set_camera_gain(saved_settings["gain"]) |
|
| 290 | + pycam.set_camera_wb(saved_settings["wb"]) |
|
| 291 | + else: # is running, turn off |
|
| 292 | + print("Stopping timelapse") |
|
| 293 | + |
|
| 294 | + timelapse_remaining = None |
|
| 295 | + pycam.camera.exposure_ctrl = True |
|
| 296 | + pycam.set_camera_gain(None) # go back to autogain |
|
| 297 | + pycam.set_camera_wb(None) # go back to autobalance |
|
| 298 | + pycam.set_camera_exposure(None) # go back to auto shutter |
|
| ... | ... | \ No newline at end of file |
SDK-dat/python-dat/circuitpython-dat/circuitpython-dat.md
| ... | ... | @@ -3,6 +3,8 @@ |
| 3 | 3 | |
| 4 | 4 | - [[circuitpython-esp32-s3-dat]] |
| 5 | 5 | |
| 6 | +- [[settings.toml]] setup and print wifi info [[w.py]] |
|
| 7 | + |
|
| 6 | 8 | circuitpython |
| 7 | 9 | - board |
| 8 | 10 | - digitalio |
| ... | ... | @@ -12,7 +14,12 @@ circuitpython |
| 12 | 14 | https://github.com/adafruit/circuitpython |
| 13 | 15 | |
| 14 | 16 | |
| 15 | -Start the UF2 Bootloader |
|
| 17 | + |
|
| 18 | + |
|
| 19 | +## UF2 bootloader |
|
| 20 | + |
|
| 21 | + |
|
| 22 | +### Start the UF2 Bootloader |
|
| 16 | 23 | |
| 17 | 24 | Nearly all CircuitPython boards ship with a bootloader called UF2 (USB Flashing Format) that makes installing and updating CircuitPython a quick and easy process. The bootloader is the mode your board needs to be in for the CircuitPython .uf2 file you downloaded to work. If the file you downloaded that matches the board name ends in uf2 then you want to continue with this section. However, if the file ends in .bin, you have to do a more complex installation - go to this page for details. |
| 18 | 25 | |
| ... | ... | @@ -82,14 +89,33 @@ mpremote connect COM6 fs cp settings.toml : |
| 82 | 89 | My IP address is 192.168.79.226 |
| 83 | 90 | |
| 84 | 91 | |
| 92 | +## driver and libs |
|
| 93 | + |
|
| 94 | +https://docs.circuitpython.org/projects/bundle/en/latest/drivers.html |
|
| 95 | + |
|
| 96 | +Warning |
|
| 97 | + |
|
| 98 | +This module requires the CircuitPython imagecapture module which is only in the unreleased development version ("Absolute Newest") of CircuitPython and is only supported on specific boards. |
|
| 85 | 99 | |
| 86 | -## OV2640 |
|
| 100 | +The CircuitPython build for your board must support the ``imagecapture`` module. |
|
| 101 | + |
|
| 102 | +### OV2640 |
|
| 103 | + |
|
| 104 | +- [[adafruit_ov2640.py]] - [[ov2640_micropython_test.py]] - [[ov2640_simpletest.py]] |
|
| 87 | 105 | |
| 88 | 106 | - https://github.com/adafruit/Adafruit_CircuitPython_OV2640 |
| 89 | 107 | |
| 90 | 108 | - https://docs.circuitpython.org/projects/ov2640/en/latest/ |
| 91 | 109 | |
| 92 | 110 | |
| 111 | +### pycamera |
|
| 112 | + |
|
| 113 | +- https://github.com/adafruit/Adafruit_PyCamera |
|
| 114 | + |
|
| 115 | + |
|
| 116 | + |
|
| 117 | + |
|
| 118 | + |
|
| 93 | 119 | |
| 94 | 120 | ## reference code |
| 95 | 121 |
SDK-dat/python-dat/circuitpython-dat/ov2640_micropython_test.py
| ... | ... | @@ -1,49 +0,0 @@ |
| 1 | -# mpremote connect COM6 fs cp ov2640_micropython_test.py : |
|
| 2 | -# mpremote connect COM6 run ov2640_micropython_test.py |
|
| 3 | - |
|
| 4 | -import camera # type: ignore |
|
| 5 | -import time |
|
| 6 | -import sys |
|
| 7 | - |
|
| 8 | -# Initialize camera with ESP1000 pin definitions |
|
| 9 | -try: |
|
| 10 | - camera.init(0, |
|
| 11 | - d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35, |
|
| 12 | - format=camera.JPEG, |
|
| 13 | - framesize=camera.FRAME_QQVGA, # 160x120 |
|
| 14 | - xclk_freq=camera.XCLK_20MHz, |
|
| 15 | - href=23, vsync=25, reset=-1, pwdn=32, |
|
| 16 | - sioc=27, siod=26, xclk=0, pclk=22 |
|
| 17 | - ) |
|
| 18 | - print("Camera initialized successfully") |
|
| 19 | -except Exception as e: |
|
| 20 | - print("Camera init failed:", e) |
|
| 21 | - sys.exit() |
|
| 22 | - |
|
| 23 | -# Simple test - capture and save images |
|
| 24 | -count = 0 |
|
| 25 | -while True: |
|
| 26 | - try: |
|
| 27 | - print("Capturing image", count) |
|
| 28 | - buf = camera.capture() |
|
| 29 | - print("Image size:", len(buf), "bytes") |
|
| 30 | - |
|
| 31 | - # Save image |
|
| 32 | - filename = f"test_{count:03d}.jpg" |
|
| 33 | - with open(filename, 'wb') as f: |
|
| 34 | - f.write(buf) |
|
| 35 | - print("Saved:", filename) |
|
| 36 | - |
|
| 37 | - count += 1 |
|
| 38 | - time.sleep(2) |
|
| 39 | - |
|
| 40 | - # Stop after 5 images for testing |
|
| 41 | - if count >= 5: |
|
| 42 | - break |
|
| 43 | - |
|
| 44 | - except Exception as e: |
|
| 45 | - print("Capture error:", e) |
|
| 46 | - break |
|
| 47 | - |
|
| 48 | -print("Test completed") |
|
| 49 | -camera.deinit() |
SDK-dat/python-dat/circuitpython-dat/ov2640_simpletest.py
| ... | ... | @@ -1,74 +0,0 @@ |
| 1 | -# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries |
|
| 2 | -# SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries |
|
| 3 | -# |
|
| 4 | -# SPDX-License-Identifier: Unlicense |
|
| 5 | - |
|
| 6 | -"""Capture an image from the camera and display it as ASCII art. |
|
| 7 | - |
|
| 8 | -This demo is designed to run on the Kaluga, but you can adapt it |
|
| 9 | -to other boards by changing the constructors for `bus` and `cam` |
|
| 10 | -appropriately. |
|
| 11 | - |
|
| 12 | -The camera is placed in YUV mode, so the top 8 bits of each color |
|
| 13 | -value can be treated as "greyscale". |
|
| 14 | - |
|
| 15 | -It's important that you use a terminal program that can interpret |
|
| 16 | -"ANSI" escape sequences. The demo uses them to "paint" each frame |
|
| 17 | -on top of the prevous one, rather than scrolling. |
|
| 18 | - |
|
| 19 | -Remember to take the lens cap off, or un-comment the line setting |
|
| 20 | -the test pattern! |
|
| 21 | -""" |
|
| 22 | - |
|
| 23 | -import sys |
|
| 24 | -import time |
|
| 25 | - |
|
| 26 | -import board |
|
| 27 | -import busio |
|
| 28 | - |
|
| 29 | -import adafruit_ov2640 |
|
| 30 | - |
|
| 31 | -# mpremote connect COM6 fs put adafruit_ov2640.py : |
|
| 32 | -# mpremote connect COM6 fs put ov2640_simpletest.py : |
|
| 33 | -# mpremote connect COM6 fs run ov2640_simpletest.py |
|
| 34 | - |
|
| 35 | - |
|
| 36 | -# Pin definitions adapted from ESP1000-2-dat.py |
|
| 37 | -# d0=5, d1=18, d2=19, d3=21, d4=36, d5=39, d6=34, d7=35 |
|
| 38 | -# href=23, vsync=25, sioc=27, siod=26, xclk=0, pclk=22 |
|
| 39 | -data_pins = [board.GP5, board.GP18, board.GP19, board.GP21, board.GP36, board.GP39, board.GP34, board.GP35] |
|
| 40 | - |
|
| 41 | -bus = busio.I2C(scl=board.GP27, sda=board.GP26) # sioc=27, siod=26 |
|
| 42 | - |
|
| 43 | -cam = adafruit_ov2640.OV2640( |
|
| 44 | - bus, |
|
| 45 | - data_pins=data_pins, |
|
| 46 | - clock=board.GP22, # pclk=22 |
|
| 47 | - vsync=board.GP25, # vsync=25 |
|
| 48 | - href=board.GP23, # href=23 |
|
| 49 | - mclk=board.GP0, # xclk=0 |
|
| 50 | - mclk_frequency=20_000_000, |
|
| 51 | - size=adafruit_ov2640.OV2640_SIZE_QQVGA, |
|
| 52 | -) |
|
| 53 | -cam.colorspace = adafruit_ov2640.OV2640_COLOR_YUV |
|
| 54 | -cam.flip_y = True |
|
| 55 | -# cam.test_pattern = True |
|
| 56 | - |
|
| 57 | -buf = bytearray(2 * cam.width * cam.height) |
|
| 58 | -chars = b" .:-=+*#%@" |
|
| 59 | -remap = [chars[i * (len(chars) - 1) // 255] for i in range(256)] |
|
| 60 | - |
|
| 61 | -width = cam.width |
|
| 62 | -row = bytearray(2 * width) |
|
| 63 | - |
|
| 64 | -sys.stdout.write("\033[2J") |
|
| 65 | -while True: |
|
| 66 | - cam.capture(buf) |
|
| 67 | - for j in range(cam.height // 2): |
|
| 68 | - sys.stdout.write(f"\033[{j}H") |
|
| 69 | - for i in range(cam.width // 2): |
|
| 70 | - row[i * 2] = row[i * 2 + 1] = remap[buf[4 * (width * j + i)]] |
|
| 71 | - sys.stdout.write(row) |
|
| 72 | - sys.stdout.write("\033[K") |
|
| 73 | - sys.stdout.write("\033[J") |
|
| 74 | - time.sleep(0.05) |
|
| ... | ... | \ No newline at end of file |