12
12
#include <zephyr/drivers/video-controls.h>
13
13
#include <zephyr/logging/log.h>
14
14
15
+ #include "video_common.h"
15
16
#include "video_ctrls.h"
16
17
#include "video_device.h"
17
18
18
19
LOG_MODULE_REGISTER (video_ov7670 , CONFIG_VIDEO_LOG_LEVEL );
19
20
20
- /* Initialization register structure */
21
- struct ov7670_reg {
22
- uint8_t reg ;
23
- uint8_t cmd ;
24
- };
25
-
26
21
struct ov7670_config {
27
22
struct i2c_dt_spec bus ;
28
23
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
@@ -43,63 +38,7 @@ struct ov7670_data {
43
38
struct video_format fmt ;
44
39
};
45
40
46
- struct ov7670_resolution_cfg {
47
- uint8_t com7 ;
48
- uint8_t com3 ;
49
- uint8_t com14 ;
50
- uint8_t scaling_xsc ;
51
- uint8_t scaling_ysc ;
52
- uint8_t dcwctr ;
53
- uint8_t pclk_div ;
54
- uint8_t pclk_delay ;
55
- };
56
-
57
- /* Resolution settings for camera, based on those present in MCUX SDK */
58
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_QCIF = {
59
- .com7 = 0x2c ,
60
- .com3 = 0x00 ,
61
- .com14 = 0x11 ,
62
- .scaling_xsc = 0x3a ,
63
- .scaling_ysc = 0x35 ,
64
- .dcwctr = 0x11 ,
65
- .pclk_div = 0xf1 ,
66
- .pclk_delay = 0x52
67
- };
68
-
69
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_QVGA = {
70
- .com7 = 0x14 ,
71
- .com3 = 0x04 ,
72
- .com14 = 0x19 ,
73
- .scaling_xsc = 0x3a ,
74
- .scaling_ysc = 0x35 ,
75
- .dcwctr = 0x11 ,
76
- .pclk_div = 0xf1 ,
77
- .pclk_delay = 0x02
78
- };
79
-
80
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_CIF = {
81
- .com7 = 0x24 ,
82
- .com3 = 0x08 ,
83
- .com14 = 0x11 ,
84
- .scaling_xsc = 0x3a ,
85
- .scaling_ysc = 0x35 ,
86
- .dcwctr = 0x11 ,
87
- .pclk_div = 0xf1 ,
88
- .pclk_delay = 0x02
89
- };
90
-
91
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
92
- .com7 = 0x04 ,
93
- .com3 = 0x00 ,
94
- .com14 = 0x00 ,
95
- .scaling_xsc = 0x3a ,
96
- .scaling_ysc = 0x35 ,
97
- .dcwctr = 0x11 ,
98
- .pclk_div = 0xf0 ,
99
- .pclk_delay = 0x02
100
- };
101
-
102
-
41
+ #define OV7670_REG8 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA8)
103
42
/* OV7670 registers */
104
43
#define OV7670_PID 0x0A
105
44
#define OV7670_COM7 0x12
@@ -209,13 +148,14 @@ static const struct video_format_cap fmts[] = {
209
148
OV7670_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
210
149
OV7670_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_YUYV ), /* CIF */
211
150
OV7670_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
212
- {0 }};
151
+ {0 }
152
+ };
213
153
214
154
/*
215
155
* This initialization table is based on the MCUX SDK driver for the OV7670.
216
156
* Note that this table assumes the camera is fed a 6MHz XCLK signal
217
157
*/
218
- static const struct ov7670_reg ov7670_init_regtbl [] = {
158
+ static const struct video_reg8 ov7670_init_regtbl [] = {
219
159
{OV7670_MVFP , 0x00 }, /* MVFP: Mirror/VFlip,Normal image */
220
160
221
161
/* configure the output timing */
@@ -369,6 +309,51 @@ static const struct ov7670_reg ov7670_init_regtbl[] = {
369
309
{0xb8 , 0x0a },
370
310
};
371
311
312
+ /* Resolution settings for camera, based on those present in MCUX SDK */
313
+ static const struct video_reg8 ov7670_regs_qcif [] = {
314
+ {OV7670_COM7 , 0x2c },
315
+ {OV7670_COM3 , 0x00 },
316
+ {OV7670_COM14 , 0x11 },
317
+ {OV7670_SCALING_XSC , 0x3a },
318
+ {OV7670_SCALING_YSC , 0x35 },
319
+ {OV7670_SCALING_DCWCTR , 0x11 },
320
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
321
+ {OV7670_SCALING_PCLK_DELAY , 0x52 },
322
+ };
323
+
324
+ static const struct video_reg8 ov7670_regs_qvga [] = {
325
+ {OV7670_COM7 , 0x14 },
326
+ {OV7670_COM3 , 0x04 },
327
+ {OV7670_COM14 , 0x19 },
328
+ {OV7670_SCALING_XSC , 0x3a },
329
+ {OV7670_SCALING_YSC , 0x35 },
330
+ {OV7670_SCALING_DCWCTR , 0x11 },
331
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
332
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
333
+ };
334
+
335
+ static const struct video_reg8 ov7670_regs_cif [] = {
336
+ {OV7670_COM7 , 0x24 },
337
+ {OV7670_COM3 , 0x08 },
338
+ {OV7670_COM14 , 0x11 },
339
+ {OV7670_SCALING_XSC , 0x3a },
340
+ {OV7670_SCALING_YSC , 0x35 },
341
+ {OV7670_SCALING_DCWCTR , 0x11 },
342
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
343
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
344
+ };
345
+
346
+ static const struct video_reg8 ov7670_regs_vga [] = {
347
+ {OV7670_COM7 , 0x04 },
348
+ {OV7670_COM3 , 0x00 },
349
+ {OV7670_COM14 , 0x00 },
350
+ {OV7670_SCALING_XSC , 0x3a },
351
+ {OV7670_SCALING_YSC , 0x35 },
352
+ {OV7670_SCALING_DCWCTR , 0x11 },
353
+ {OV7670_SCALING_PCLK_DIV , 0xf0 },
354
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
355
+ };
356
+
372
357
static int ov7670_get_caps (const struct device * dev , struct video_caps * caps )
373
358
{
374
359
caps -> format_caps = fmts ;
@@ -379,7 +364,6 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
379
364
{
380
365
const struct ov7670_config * config = dev -> config ;
381
366
struct ov7670_data * data = dev -> data ;
382
- const struct ov7670_resolution_cfg * resolution ;
383
367
int ret ;
384
368
uint8_t i = 0U ;
385
369
@@ -396,68 +380,49 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
396
380
memcpy (& data -> fmt , fmt , sizeof (data -> fmt ));
397
381
398
382
/* Set output resolution */
383
+ ret = - ENOTSUP ;
384
+ i = 0 ;
399
385
while (fmts [i ].pixelformat ) {
400
- if (fmts [i ].width_min == fmt -> width && fmts [i ].height_min == fmt -> height &&
401
- fmts [i ].pixelformat == fmt -> pixelformat ) {
386
+ if (fmts [i ].width_min == fmt -> width &&
387
+ fmts [i ].height_min == fmt -> height &&
388
+ fmts [i ].pixelformat == fmt -> pixelformat ){
402
389
/* Set output format */
403
390
switch (fmts [i ].width_min ) {
404
391
case 176 : /* QCIF */
405
- resolution = & OV7670_RESOLUTION_QCIF ;
392
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qcif ,
393
+ ARRAY_SIZE (ov7670_regs_qcif ));
394
+ break ;
395
+ case 352 : /* QCIF */
396
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_cif ,
397
+ ARRAY_SIZE (ov7670_regs_cif ));
406
398
break ;
407
399
case 320 : /* QVGA */
408
- resolution = & OV7670_RESOLUTION_QVGA ;
400
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
401
+ ARRAY_SIZE (ov7670_regs_qvga ));
409
402
break ;
410
- case 352 : /* CIF */
411
- resolution = & OV7670_RESOLUTION_CIF ;
403
+ case 640 : /* VGA */
404
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_vga ,
405
+ ARRAY_SIZE (ov7670_regs_vga ));
412
406
break ;
413
- default : /* VGA */
414
- resolution = & OV7670_RESOLUTION_VGA ;
407
+ default : /* QVGA */
408
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
409
+ ARRAY_SIZE (ov7670_regs_vga ));
415
410
break ;
416
411
}
417
- /* Program resolution bytes settings */
418
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 ,
419
- resolution -> com7 );
420
- if (ret < 0 ) {
421
- return ret ;
422
- }
423
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM3 ,
424
- resolution -> com3 );
425
- if (ret < 0 ) {
426
- return ret ;
427
- }
428
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM14 ,
429
- resolution -> com14 );
430
- if (ret < 0 ) {
431
- return ret ;
432
- }
433
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_XSC ,
434
- resolution -> scaling_xsc );
435
- if (ret < 0 ) {
436
- return ret ;
437
- }
438
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_YSC ,
439
- resolution -> scaling_ysc );
440
412
if (ret < 0 ) {
413
+ LOG_ERR ("Resolution not set!" );
441
414
return ret ;
442
415
}
443
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_DCWCTR ,
444
- resolution -> dcwctr );
445
- if (ret < 0 ) {
446
- return ret ;
447
- }
448
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_PCLK_DIV ,
449
- resolution -> pclk_div );
450
- if (ret < 0 ) {
451
- return ret ;
452
- }
453
- return i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_PCLK_DELAY ,
454
- resolution -> pclk_delay );
455
416
}
456
417
i ++ ;
457
418
}
458
419
459
- LOG_ERR ("Unsupported format" );
460
- return - ENOTSUP ;
420
+ if (ret < 0 ) {
421
+ LOG_ERR ("Resolution supported!" );
422
+ return ret ;
423
+ }
424
+
425
+ return 0 ;
461
426
}
462
427
463
428
static int ov7670_get_fmt (const struct device * dev , struct video_format * fmt )
@@ -487,14 +452,13 @@ static int ov7670_init_controls(const struct device *dev)
487
452
static int ov7670_init (const struct device * dev )
488
453
{
489
454
const struct ov7670_config * config = dev -> config ;
490
- int ret , i ;
455
+ int ret ;
491
456
uint8_t pid ;
492
457
struct video_format fmt = {
493
458
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
494
459
.width = 320 ,
495
460
.height = 240 ,
496
461
};
497
- const struct ov7670_reg * reg ;
498
462
499
463
if (!i2c_is_ready_dt (& config -> bus )) {
500
464
/* I2C device is not ready, return */
@@ -559,7 +523,7 @@ static int ov7670_init(const struct device *dev)
559
523
}
560
524
561
525
/* Reset camera registers */
562
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 , 0x80 );
526
+ ret = video_write_cci_reg (& config -> bus , OV7670_REG8 ( OV7670_COM7 ) , 0x80 );
563
527
if (ret < 0 ) {
564
528
LOG_ERR ("Could not reset camera: %d" , ret );
565
529
return ret ;
@@ -573,12 +537,10 @@ static int ov7670_init(const struct device *dev)
573
537
}
574
538
575
539
/* Write initialization values to OV7670 */
576
- for (i = 0 ; i < ARRAY_SIZE (ov7670_init_regtbl ); i ++ ) {
577
- reg = & ov7670_init_regtbl [i ];
578
- ret = i2c_reg_write_byte_dt (& config -> bus , reg -> reg , reg -> cmd );
579
- if (ret < 0 ) {
580
- return ret ;
581
- }
540
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_init_regtbl ,
541
+ ARRAY_SIZE (ov7670_init_regtbl ));
542
+ if (ret < 0 ) {
543
+ return ret ;
582
544
}
583
545
584
546
/* Initialize controls */
@@ -628,15 +590,22 @@ static DEVICE_API(video, ov7670_api) = {
628
590
#define OV7670_PWDN_GPIO (inst )
629
591
#endif
630
592
631
- #define OV7670_INIT (inst ) \
632
- const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \
633
- OV7670_RESET_GPIO(inst) \
634
- OV7670_PWDN_GPIO(inst)}; \
635
- struct ov7670_data ov7670_data_##inst; \
636
- \
637
- DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \
638
- POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); \
639
- \
593
+ #define OV7670_INIT (inst ) \
594
+ const struct ov7670_config ov7670_config_##inst = { \
595
+ .bus = I2C_DT_SPEC_INST_GET(inst), \
596
+ OV7670_RESET_GPIO(inst) \
597
+ OV7670_PWDN_GPIO(inst)}; \
598
+ \
599
+ static struct ov7670_data ov7670_data_##inst; \
600
+ \
601
+ DEVICE_DT_INST_DEFINE(inst, \
602
+ ov7670_init, \
603
+ NULL, \
604
+ &ov7670_data_##inst, \
605
+ &ov7670_config_##inst, \
606
+ POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
607
+ &ov7670_api); \
608
+ \
640
609
VIDEO_DEVICE_DEFINE(ov7670_##inst, DEVICE_DT_INST_GET(inst), NULL);
641
610
642
611
DT_INST_FOREACH_STATUS_OKAY (OV7670_INIT )
0 commit comments