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
![](2025-07-30-16-50-00.png)
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
![](2025-07-30-16-50-54.png)
... ...
@@ -26,64 +77,64 @@
26 77
load:0x403b6000,len:0x8c8
27 78
load:0x403ba000,len:0x2c04
28 79
entry 0x403b61c4
29
- I (24) boot: ESP-IDF v4.4-dev-2594-ga20df743f1-dirty 2nd stage bootloader
30
- I (25) boot: compile time 16:57:21
31
- I (25) boot: chip revision: 0
32
- I (28) boot.esp32s3: SPI Speed : 80MHz
33
- I (33) boot.esp32s3: SPI Mode : DIO
34
- I (38) boot.esp32s3: SPI Flash Size : 2MB
35
- I (43) boot: Enabling RNG early entropy source...
36
- W (48) bootloader_random: RNG for ESP32-S3 not currently supported
37
- I (55) boot: Partition Table:
38
- I (59) boot: ## Label Usage Type ST Offset Length
39
- I (66) boot: 0 nvs WiFi data 01 02 00009000 00006000
40
- I (73) boot: 1 phy_init RF data 01 01 0000f000 00001000
41
- I (81) boot: 2 factory factory app 00 00 00010000 00100000
42
- I (88) boot: End of partition table
43
- I (92) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=090e0h ( 37088) map
44
- I (108) esp_image: segment 1: paddr=00019108 vaddr=3fc90dd0 size=0253ch ( 9532) load
45
- I (111) esp_image: segment 2: paddr=0001b64c vaddr=40374000 size=049cch ( 18892) load
46
- I (122) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1b660h (112224) map
47
- I (147) esp_image: segment 4: paddr=0003b688 vaddr=403789cc size=08404h ( 33796) load
48
- I (154) esp_image: segment 5: paddr=00043a94 vaddr=50000000 size=00010h ( 16) load
49
- I (160) boot: Loaded app from partition at offset 0x10000
50
- I (160) boot: Disabling RNG early entropy source...
51
- W (164) bootloader_random: RNG for ESP32-S3 not currently supported
52
- I (182) cpu_start: Pro cpu up.
53
- I (182) cpu_start: Starting app cpu, entry point is 0x40375104
54
- I (0) cpu_start: App cpu up.
55
- I (196) cpu_start: Pro cpu start user code
56
- I (196) cpu_start: cpu freq: 160000000
57
- I (196) cpu_start: Application information:
58
- I (199) cpu_start: Project name: led_strip
59
- I (204) cpu_start: App version: 1
60
- I (209) cpu_start: Compile time: Aug 17 2021 17:09:47
61
- I (215) cpu_start: ELF file SHA256: bda59acbde3f7a0e...
62
- I (221) cpu_start: ESP-IDF: v4.4-dev-2594-ga20df743f1-dirty
63
- I (228) heap_init: Initializing. RAM available for dynamic allocation:
64
- I (235) heap_init: At 3FC94220 len 0004BDE0 (303 KiB): D/IRAM
65
- I (241) heap_init: At 3FCE0000 len 0000EE34 (59 KiB): STACK/DRAM
66
- I (248) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
67
- I (255) spi_flash: detected chip: generic
68
- I (259) spi_flash: flash io: dio
69
- W (263) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
70
- I (277) cpu_start: Starting scheduler on PRO CPU.
71
- I (0) cpu_start: Starting scheduler on APP CPU.
72
- I (308) example: LED Rainbow Chase Start
73
- I (308) example: USB initialization
74
- I (308) tusb_desc:
80
+ I (24boot: ESP-IDF v4.4-dev-2594-ga20df743f1-dirty 2nd stage bootloader
81
+ I (25boot: compile time 16:57:21
82
+ I (25boot: chip revision: 0
83
+ I (28boot.esp32s3: SPI Speed : 80MHz
84
+ I (33boot.esp32s3: SPI Mode : DIO
85
+ I (38boot.esp32s3: SPI Flash Size : 2MB
86
+ I (43boot: Enabling RNG early entropy source...
87
+ W (48bootloader_random: RNG for ESP32-S3 not currently supported
88
+ I (55boot: Partition Table:
89
+ I (59boot: ## Label Usage Type ST Offset Length
90
+ I (66boot: 0 nvs WiFi data 01 02 00009000 00006000
91
+ I (73boot: 1 phy_init RF data 01 01 0000f000 00001000
92
+ I (81boot: 2 factory factory app 00 00 00010000 00100000
93
+ I (88boot: End of partition table
94
+ I (92esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=090e0h ( 37088map
95
+ I (108esp_image: segment 1: paddr=00019108 vaddr=3fc90dd0 size=0253ch ( 9532load
96
+ I (111esp_image: segment 2: paddr=0001b64c vaddr=40374000 size=049cch ( 18892load
97
+ I (122esp_image: segment 3: paddr=00020020 vaddr=42000020 size=1b660h (112224map
98
+ I (147esp_image: segment 4: paddr=0003b688 vaddr=403789cc size=08404h ( 33796load
99
+ I (154esp_image: segment 5: paddr=00043a94 vaddr=50000000 size=00010h ( 16load
100
+ I (160boot: Loaded app from partition at offset 0x10000
101
+ I (160boot: Disabling RNG early entropy source...
102
+ W (164bootloader_random: RNG for ESP32-S3 not currently supported
103
+ I (182cpu_start: Pro cpu up.
104
+ I (182cpu_start: Starting app cpu, entry point is 0x40375104
105
+ I (0cpu_start: App cpu up.
106
+ I (196cpu_start: Pro cpu start user code
107
+ I (196cpu_start: cpu freq: 160000000
108
+ I (196cpu_start: Application information:
109
+ I (199cpu_start: Project name: led_strip
110
+ I (204cpu_start: App version: 1
111
+ I (209cpu_start: Compile time: Aug 17 2021 17:09:47
112
+ I (215cpu_start: ELF file SHA256: bda59acbde3f7a0e...
113
+ I (221cpu_start: ESP-IDF: v4.4-dev-2594-ga20df743f1-dirty
114
+ I (228heap_init: Initializing. RAM available for dynamic allocation:
115
+ I (235heap_init: At 3FC94220 len 0004BDE0 (303 KiB): D/IRAM
116
+ I (241heap_init: At 3FCE0000 len 0000EE34 (59 KiB): STACK/DRAM
117
+ I (248heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
118
+ I (255spi_flash: detected chip: generic
119
+ I (259spi_flash: flash io: dio
120
+ W (263spi_flash: Detected size(16384klarger than the size in the binary image header(2048k). Using the size in the binary image header.
121
+ I (277cpu_start: Starting scheduler on PRO CPU.
122
+ I (0cpu_start: Starting scheduler on APP CPU.
123
+ I (308example: LED Rainbow Chase Start
124
+ I (308example: USB initialization
125
+ I (308tusb_desc:
75 126
76 127
...
77 128
78
- I (478) TinyUSB: TinyUSB Driver installed
79
- I (488) example: USB initialization DONE
80
- I (1388) example: log -> UART
129
+ I (478TinyUSB: TinyUSB Driver installed
130
+ I (488example: USB initialization DONE
131
+ I (1388example: log -> UART
81 132
example: print -> stdout
82 133
example: print -> stderr
83
- I (2888) example: log -> UART
134
+ I (2888example: log -> UART
84 135
example: print -> stdout
85 136
example: print -> stderr
86
- I (4388) example: log -> UART
137
+ I (4388example: log -> UART
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
+![](2025-07-31-13-03-47.png)
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
+![](2025-07-31-13-09-24.png)
6
+
7
+
8
+Downloading adafruit-circuitpython-yd_esp32_s3_n16r8-en_US-9.2.8.uf2...
9
+
10
+![](2025-07-31-13-10-33.png)
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