source: azure_iot_hub_f767zi/trunk/asp_baseplatform/gdic/sipeed_ov2640/sipeed_ov2640.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 27.9 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2004-2012 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 * Copyright (C) 2015-2019 by TOPPERS PROJECT Educational Working Group.
11 *
12 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
20 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * の無保証規定を掲載すること.
22 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
23 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * と.
25 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
26 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
27 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * 報告すること.
29 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
30 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
32 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
33 * 免責すること.
34 *
35 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
36 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
37 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
38 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
39 * の責任を負わない.
40 *
41 * $Id$
42 */
43/*
44 * SIPEED OV2640 CAMARA制御プログラムの本体
45 */
46
47#include <kernel.h>
48#include <t_syslog.h>
49#include <target_syssvc.h>
50#include "device.h"
51
52#include "dvp.h"
53#include "ov2640_regs.h"
54#include "stdlib.h"
55#include "math.h"
56#include "sipeed_ov2640.h"
57
58
59#define IM_MAX(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
60#define IM_MIN(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
61#define IM_DIV(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _b ? (_a / _b) : 0; })
62#define IM_MOD(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _b ? (_a % _b) : 0; })
63
64#ifndef SNAPSHOT_TIMEOUT
65#define SNAPDHOT_TIMEOUT 300
66#endif
67
68
69#define SVGA_HSIZE (800)
70#define SVGA_VSIZE (600)
71
72#define UXGA_HSIZE (1600)
73#define UXGA_VSIZE (1200)
74static const uint8_t ov2640_default[][2] = { //k210
75 {0xff, 0x01},
76 {0x12, 0x80},
77 {0xff, 0x00},
78 {0x2c, 0xff},
79 {0x2e, 0xdf},
80 {0xff, 0x01},
81 {0x3c, 0x32},
82 {0x11, 0x00},
83 {0x09, 0x02},
84 {0x04, 0xa8},//v flip and h mirro
85 {0x13, 0xe5},
86 {0x14, 0x48},
87 {0x2c, 0x0c},
88 {0x33, 0x78},
89 {0x3a, 0x33},
90 {0x3b, 0xfb},
91 {0x3e, 0x00},
92 {0x43, 0x11},
93 {0x16, 0x10},
94 {0x39, 0x92},//test 92
95 {0x23, 0x00},
96 {0x36, 0x1a},
97 {0x07, 0xc0},
98 {0x4c, 0x00},
99 {0x48, 0x00},
100 {0x5b, 0x00},
101 {0x4a, 0x81},
102 {0x21, 0x99},
103 {0x24, 0x40},
104 {0x25, 0x38},
105 {0x26, 0x82},
106 {0x5c, 0x00},
107 {0x63, 0x00},
108 {0x46, 0x22},
109 {0x0c, 0x3c},
110 {0x61, 0x70},
111 {0x62, 0x80},
112 {0x7c, 0x05},
113 {0x20, 0x80},
114 {0x28, 0x30},
115 {0x6c, 0x00},
116 {0x6d, 0x80},
117 {0x6e, 0x00},
118 {0x70, 0x02},
119 {0x71, 0x94},
120 {0x73, 0xc1},
121 {0x5a, 0x57},
122 {0x37, 0xc0},
123 {0x4f, 0xca},
124 {0x50, 0xa8},
125 {0x5a, 0x23},
126 {0x6d, 0x00},
127 {0x3d, 0x38},
128 {0xff, 0x00},
129 {0xe5, 0x7f},
130 {0xf9, 0xc0},
131 {0x41, 0x24},
132 {0xe0, 0x14},
133 {0x76, 0xff},
134 {0x33, 0xa0},
135 {0x42, 0x20},
136 {0x43, 0x18},
137 {0x4c, 0x00},
138 {0x87, 0xd5},
139 {0x88, 0x3f},
140 {0xd7, 0x03},//[pixformat]:
141 {0xd9, 0x10},
142 {0xd3, 0x82},
143 {0xc8, 0x08},
144 {0xc9, 0x80},
145 {0x7c, 0x00},
146 {0x7d, 0x00},
147 {0x7c, 0x03},
148 {0x7d, 0x48},
149 {0x7d, 0x48},
150 {0x7c, 0x08},
151 {0x7d, 0x20},
152 {0x7d, 0x10},
153 {0x7d, 0x0e},
154 {0x90, 0x00},
155 {0x91, 0x0e},
156 {0x91, 0x1a},
157 {0x91, 0x31},
158 {0x91, 0x5a},
159 {0x91, 0x69},
160 {0x91, 0x75},
161 {0x91, 0x7e},
162 {0x91, 0x88},
163 {0x91, 0x8f},
164 {0x91, 0x96},
165 {0x91, 0xa3},
166 {0x91, 0xaf},
167 {0x91, 0xc4},
168 {0x91, 0xd7},
169 {0x91, 0xe8},
170 {0x91, 0x20},
171 {0x92, 0x00},
172 {0x93, 0x06},
173 {0x93, 0xe3},
174 {0x93, 0x05},
175 {0x93, 0x05},
176 {0x93, 0x00},
177 {0x93, 0x04},
178 {0x93, 0x00},
179 {0x93, 0x00},
180 {0x93, 0x00},
181 {0x93, 0x00},
182 {0x93, 0x00},
183 {0x93, 0x00},
184 {0x93, 0x00},
185 {0x96, 0x00},
186 {0x97, 0x08},
187 {0x97, 0x19},
188 {0x97, 0x02},
189 {0x97, 0x0c},
190 {0x97, 0x24},
191 {0x97, 0x30},
192 {0x97, 0x28},
193 {0x97, 0x26},
194 {0x97, 0x02},
195 {0x97, 0x98},
196 {0x97, 0x80},
197 {0x97, 0x00},
198 {0x97, 0x00},
199 {0xc3, 0xed},
200 {0xa4, 0x00},
201 {0xa8, 0x00},
202 {0xc5, 0x11},
203 {0xc6, 0x51},
204 {0xbf, 0x80},
205 {0xc7, 0x10},
206 {0xb6, 0x66},
207 {0xb8, 0xa5},
208 {0xb7, 0x64},
209 {0xb9, 0x7c},
210 {0xb3, 0xaf},
211 {0xb4, 0x97},
212 {0xb5, 0xff},
213 {0xb0, 0xc5},
214 {0xb1, 0x94},
215 {0xb2, 0x0f},
216 {0xc4, 0x5c},
217 {0x5a, 0xc8},
218 {0x5b, 0x96},
219 {0x5c, 0x00},
220 {0xc3, 0xed},
221 {0x7f, 0x00},
222 {0xda, 0x08},//pixformat
223 {0xe5, 0x1f},
224 {0xe1, 0x67},//pixformat
225 {0xe0, 0x00},
226 {0xdd, 0x7f},
227 {0x05, 0x00},
228#if 1 //color bar
229 {0xff, 0x01},
230 {0x12, 0x02},
231#endif
232 {0x00, 0x00}
233
234};
235static const uint8_t svga_config[][2] = { //k210
236 {0xff, 0x01},//bank sel
237 {0x35, 0xda},//[SVGA]:
238 {0x22, 0x1a},//[SVGA]:
239 {0x37, 0xc3},//[SVGA]:
240 {0x34, 0xc0},//[SVGA]:
241 {0x06, 0x88},//[SVGA]:
242 {0x0d, 0x87},//[SVGA]:
243 {0x0e, 0x41},//[SVGA]:
244 {0x42, 0x03},//[SVGA]:
245 {0x3d, 0x34},//[SVGA]:
246 {0x12, 0x40},//[SVGA]: COM7,COM7_RES_SVGA SVGA
247 {0x03, 0x0f},//[SVGA]: COM1,0x0F
248 {0x17, 0x11},//[SVGA]:HSTART
249 {0x18, 0x43},//[SVGA]:HSTOP
250 {0x19, 0x00},//[SVGA]:VSTART
251 {0x1a, 0x4b},//[SVGA]:VSTOP
252 {0x32, 0x09},//[SVGA]:REG32
253
254 {0xff, 0x00},//bank sel
255 {0xc0, 0x64},//[SVGA]:HSIZE8 SVGA_HSIZE>>3
256 {0xc1, 0x4b},//[SVGA]:VSIZE8 SVGA_VSIZE>>3
257 {0x8c, 0x00},//[SVGA]:SIZEL
258 {0x86, 0x3d},//[SVGA]:
259 {0x50, 0x00},//[SVGA]:CTRLI
260 {0x51, 0xc8},//[SVGA]:HSIZE
261 {0x52, 0x96},//[SVGA]:VSIZE
262 {0x53, 0x00},//[SVGA]:XOFFL
263 {0x54, 0x00},//[SVGA]:YOFFL
264 {0x55, 0x00},//[SVGA]:VHYX
265 {0xd3, 0x02},//[SVGA]:R_DVP_SP
266};
267
268static const uint8_t uxga_regs[][2] = {
269 { BANK_SEL, BANK_SEL_SENSOR },
270 /* DSP input image resoultion and window size control */
271 { COM7, COM7_RES_UXGA},
272 { COM1, 0x0F }, /* UXGA=0x0F, SVGA=0x0A, CIF=0x06 */
273 { REG32, 0x36 }, /* UXGA=0x36, SVGA/CIF=0x09 */
274
275 { HSTART, 0x11 }, /* UXGA=0x11, SVGA/CIF=0x11 */
276 { HSTOP, 0x75 }, /* UXGA=0x75, SVGA/CIF=0x43 */
277
278 { VSTART, 0x01 }, /* UXGA=0x01, SVGA/CIF=0x00 */
279 { VSTOP, 0x97 }, /* UXGA=0x97, SVGA/CIF=0x4b */
280 { 0x3d, 0x34 }, /* UXGA=0x34, SVGA/CIF=0x38 */
281
282 { 0x35, 0x88 },
283 { 0x22, 0x0a },
284 { 0x37, 0x40 },
285 { 0x34, 0xa0 },
286 { 0x06, 0x02 },
287 { 0x0d, 0xb7 },
288 { 0x0e, 0x01 },
289 { 0x42, 0x83 },
290
291 /* Set DSP input image size and offset.
292 The sensor output image can be scaled with OUTW/OUTH */
293 { BANK_SEL, BANK_SEL_DSP },
294 { R_BYPASS, R_BYPASS_DSP_BYPAS },
295
296 { RESET, RESET_DVP },
297 { HSIZE8, (UXGA_HSIZE>>3)}, /* Image Horizontal Size HSIZE[10:3] */
298 { VSIZE8, (UXGA_VSIZE>>3)}, /* Image Vertiacl Size VSIZE[10:3] */
299
300 /* {HSIZE[11], HSIZE[2:0], VSIZE[2:0]} */
301 { SIZEL, ((UXGA_HSIZE>>6)&0x40) | ((UXGA_HSIZE&0x7)<<3) | (UXGA_VSIZE&0x7)},
302
303 { XOFFL, 0x00 }, /* OFFSET_X[7:0] */
304 { YOFFL, 0x00 }, /* OFFSET_Y[7:0] */
305 { HSIZE, ((UXGA_HSIZE>>2)&0xFF) }, /* H_SIZE[7:0] real/4 */
306 { VSIZE, ((UXGA_VSIZE>>2)&0xFF) }, /* V_SIZE[7:0] real/4 */
307
308 /* V_SIZE[8]/OFFSET_Y[10:8]/H_SIZE[8]/OFFSET_X[10:8] */
309 { VHYX, ((UXGA_VSIZE>>3)&0x80) | ((UXGA_HSIZE>>7)&0x08) },
310 { TEST, (UXGA_HSIZE>>4)&0x80}, /* H_SIZE[9] */
311
312 { CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
313 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
314
315 /* H_DIVIDER/V_DIVIDER */
316 { CTRLI, CTRLI_LP_DP | 0x00},
317 /* DVP prescalar */
318 { R_DVP_SP, R_DVP_SP_AUTO_MODE | 0x04},
319
320 { R_BYPASS, R_BYPASS_DSP_EN },
321 { RESET, 0x00 },
322 {0, 0},
323};
324
325static const uint8_t yuv422_regs[][2] = {
326 { BANK_SEL, BANK_SEL_DSP },
327 { RESET, RESET_DVP},
328 { 0xD7, 0x01 },
329 { IMAGE_MODE, IMAGE_MODE_YUV422 },
330 { 0xE1, 0x67 },
331 { RESET, 0x00 },
332 {0, 0},
333};
334
335static const uint8_t rgb565_regs[][2] = {
336 { BANK_SEL, BANK_SEL_DSP },
337 { RESET, RESET_DVP},
338 { 0xD7, 0x03},
339 { IMAGE_MODE, IMAGE_MODE_RGB565 },
340 { 0xE1, 0x77 },
341 { RESET, 0x00 },
342 {0, 0},
343};
344
345static const uint8_t jpeg_regs[][2] = {
346 { BANK_SEL, BANK_SEL_DSP },
347 { RESET, RESET_DVP},
348 { IMAGE_MODE, IMAGE_MODE_JPEG_EN|IMAGE_MODE_RGB565 },
349 { 0xD7, 0x03 },
350 { 0xE1, 0x77 },
351 { QS, 0x0C },
352 { RESET, 0x00 },
353 {0, 0},
354};
355
356#define NUM_BRIGHTNESS_LEVELS (5)
357static const uint8_t brightness_regs[NUM_BRIGHTNESS_LEVELS + 1][5] = {
358 { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA },
359 { 0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */
360 { 0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */
361 { 0x00, 0x04, 0x09, 0x20, 0x00 }, /* 0 */
362 { 0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */
363 { 0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */
364};
365
366#define NUM_CONTRAST_LEVELS (5)
367static const uint8_t contrast_regs[NUM_CONTRAST_LEVELS + 1][7] = {
368 { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA, BPDATA, BPDATA },
369 { 0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */
370 { 0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */
371 { 0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /* 0 */
372 { 0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */
373 { 0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */
374};
375
376#define NUM_SATURATION_LEVELS (5)
377static const uint8_t saturation_regs[NUM_SATURATION_LEVELS + 1][5] = {
378 { BPADDR, BPDATA, BPADDR, BPDATA, BPDATA },
379 { 0x00, 0x02, 0x03, 0x28, 0x28 }, /* -2 */
380 { 0x00, 0x02, 0x03, 0x38, 0x38 }, /* -1 */
381 { 0x00, 0x02, 0x03, 0x48, 0x48 }, /* 0 */
382 { 0x00, 0x02, 0x03, 0x58, 0x58 }, /* +1 */
383 { 0x00, 0x02, 0x03, 0x58, 0x58 }, /* +2 */
384};
385
386static const int resolution[][2] = {
387 {0, 0 },
388 // C/SIF Resolutions
389 {88, 72 }, /* QQCIF */
390 {176, 144 }, /* QCIF */
391 {352, 288 }, /* CIF */
392 {88, 60 }, /* QQSIF */
393 {176, 120 }, /* QSIF */
394 {352, 240 }, /* SIF */
395 // VGA Resolutions
396 {40, 30 }, /* QQQQVGA */
397 {80, 60 }, /* QQQVGA */
398 {160, 120 }, /* QQVGA */
399 {320, 240 }, /* QVGA */
400 {640, 480 }, /* VGA */
401 {60, 40 }, /* HQQQVGA */
402 {120, 80 }, /* HQQVGA */
403 {240, 160 }, /* HQVGA */
404 // FFT Resolutions
405 {64, 32 }, /* 64x32 */
406 {64, 64 }, /* 64x64 */
407 {128, 64 }, /* 128x64 */
408 {128, 128 }, /* 128x64 */
409 // Other
410 {128, 160 }, /* LCD */
411 {128, 160 }, /* QQVGA2 */
412 {720, 480 }, /* WVGA */
413 {752, 480 }, /* WVGA2 */
414 {800, 600 }, /* SVGA */
415 {1280, 1024}, /* SXGA */
416 {1600, 1200}, /* UXGA */
417};
418
419
420#define cambus_writeb(h, a, d) dvp_sccb_send_data(((h)->hdvp), ((h)->_slaveAddr), (a), (d))
421
422int Sipeed_OV2640_cambus_scan_gc0328(OV2640_t *hcmr);
423int Sipeed_OV2640_dvpInitIrq(void);
424
425static int cambus_readb(OV2640_t *hcmr, uint8_t reg_addr, uint8_t *reg_data)
426{
427
428 int ret = 0;
429 *reg_data = dvp_sccb_receive_data(hcmr->hdvp, hcmr->_slaveAddr, reg_addr);
430 if(0xff == *reg_data)
431 ret = -1;
432 return ret;
433}
434
435static int reverse_u32pixel(uint32_t* addr, uint32_t length)
436{
437 if(NULL == addr)
438 return -1;
439
440 uint32_t data;
441 uint32_t* pend = addr+length;
442 for(;addr<pend;addr++)
443 {
444 data = *(addr);
445 *(addr) = ((data & 0x000000FF) << 24) | ((data & 0x0000FF00) << 8) |
446 ((data & 0x00FF0000) >> 8) | ((data & 0xFF000000) >> 24) ;
447 } //1.7ms
448
449
450 return 0;
451}
452
453static int cambus_read_id(OV2640_t *hcmr, uint8_t addr, uint16_t *manuf_id, uint16_t *device_id)
454{
455 dvp_sccb_send_data(hcmr->hdvp, addr, 0xFF, 0x01);
456 *manuf_id = (dvp_sccb_receive_data(hcmr->hdvp, addr, 0x1C) << 8) | dvp_sccb_receive_data(hcmr->hdvp, addr, 0x1D);
457 *device_id = (dvp_sccb_receive_data(hcmr->hdvp, addr, 0x0A) << 8) | dvp_sccb_receive_data(hcmr->hdvp, addr, 0x0B);
458 return 0;
459}
460
461static int cambus_scan(OV2640_t *hcmr)
462{
463
464 uint16_t manuf_id = 0;
465 uint16_t device_id = 0;
466 for (uint8_t addr=0x08; addr<=0x77; addr++) {
467 cambus_read_id(hcmr, addr ,&manuf_id,&device_id);
468 if(0xffff != device_id)
469 {
470 return addr ;
471 }
472 }
473 return 0;
474}
475
476
477void
478ov2640_getResolition(OV2640_t *hcmr, framesize_t frameSize)
479{
480 hcmr->_width = resolution[frameSize][0];
481 hcmr->_height = resolution[frameSize][1];
482}
483
484ER
485ov2640_sensor_ov_detect(OV2640_t *hcmr)
486{
487 DVP_Handle_t *hdvp = hcmr->hdvp;
488
489 /* Reset the sensor */
490 dvp_dcmi_reset(hdvp, true);
491 dly_tsk(10);
492
493 dvp_dcmi_reset(hdvp, false);
494 dly_tsk(10);
495
496 /* Probe the ov sensor */
497 hcmr->_slaveAddr = cambus_scan(hcmr);
498 if(hcmr->_slaveAddr == 0){
499 /* Sensor has been held in reset,
500 so the reset line is active low */
501 hcmr->_resetPoliraty = ACTIVE_LOW;
502
503 /* Pull the sensor out of the reset state,systick_sleep() */
504 dvp_dcmi_reset(hdvp, true);
505 dly_tsk(10);
506
507 /* Probe again to set the slave addr */
508 hcmr->_slaveAddr = cambus_scan(hcmr);
509 if(hcmr->_slaveAddr == 0){
510 hcmr->_pwdnPoliraty = ACTIVE_LOW;
511 dvp_dcmi_powerdown(hdvp, false);
512 dly_tsk(10);
513
514 hcmr->_slaveAddr = cambus_scan(hcmr);
515 if(hcmr->_slaveAddr == 0){
516 hcmr->_resetPoliraty = ACTIVE_HIGH;
517 dvp_dcmi_reset(hdvp, false);
518 dly_tsk(10);
519
520 hcmr->_slaveAddr = cambus_scan(hcmr);
521 if(hcmr->_slaveAddr == 0){
522 //should do something?
523 return E_SYS;
524 }
525 }
526 }
527 }
528
529 // Clear sensor chip ID.
530 hcmr->_id = 0;
531
532 if(hcmr->_slaveAddr == LEPTON_ID){
533 hcmr->_id = LEPTON_ID;
534 /*set LEPTON xclk rate*/
535 /*lepton_init*/
536 }
537 else{
538 // Read ON semi sensor ID.
539 cambus_readb(hcmr, ON_CHIP_ID, &hcmr->_id);
540 if(hcmr->_id == MT9V034_ID){
541 /*set MT9V034 xclk rate*/
542 /*mt9v034_init*/
543 }
544 else{ // Read OV sensor ID.
545 cambus_readb(hcmr, OV_CHIP_ID, &hcmr->_id);
546 // Initialize sensor struct.
547 switch(hcmr->_id){
548 case OV9650_ID:
549 /*ov9650_init*/
550 break;
551 case OV2640_ID:
552 // printf("detect ov2640, id:%x\n", _slaveAddr);
553 break;
554 case OV7725_ID:
555 /*ov7725_init*/
556 break;
557 default:
558 // Sensor is not supported.
559 return E_SYS;
560 }
561 }
562 }
563 return E_OK;
564}
565
566ER
567ov2640_sensro_gc_detect(OV2640_t *hcmr)
568{
569 DVP_Handle_t *hdvp = hcmr->hdvp;
570 uint8_t id;
571
572 dvp_dcmi_powerdown(hdvp, false);//enable gc0328 要恢? normal 工作模式,需将 PWDN pin 接入低?平即可,同?写入初始化寄存器即可
573 dvp_dcmi_reset(hdvp, false); //reset gc3028
574 dly_tsk(10);
575 dvp_dcmi_reset(hdvp, true);
576 dly_tsk(10);
577 id = ov2640_cambus_scan_gc0328(hcmr);
578 if(0 == id){
579 return E_SYS;
580 }
581 else{
582 // printf("[MAIXPY]: gc0328 id = %x\n",id);
583 hcmr->_slaveAddr = GC0328_ADDR;
584 hcmr->_id = id;
585 }
586 return E_OK;
587}
588
589
590ER
591ov2640_reset(OV2640_t *hcmr)
592{
593 int i=0;
594 const uint8_t (*regs)[2];
595
596 /* Reset all registers */
597 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
598 cambus_writeb(hcmr, COM7, COM7_SRST);
599
600 /* delay n ms */
601 dly_tsk(10);
602
603 i = 0;
604 regs = ov2640_default;
605 /* Write initial regsiters */
606 while (regs[i][0]) {
607 cambus_writeb(hcmr, regs[i][0], regs[i][1]);
608 i++;
609 }
610 i = 0;
611 regs = svga_config;
612 /* Write DSP input regsiters */
613 while (regs[i][0]) {
614 cambus_writeb(hcmr, regs[i][0], regs[i][1]);
615 i++;
616 }
617 return E_OK;
618}
619
620ER
621ov2640_set_pixformat(OV2640_t *hcmr)
622{
623 int i=0;
624 const uint8_t (*regs)[2]=NULL;
625
626 /* read pixel format reg */
627 switch(hcmr->pixFormat){
628 case PIXFORMAT_RGB565:
629 regs = rgb565_regs;
630 break;
631 case PIXFORMAT_YUV422:
632 case PIXFORMAT_GRAYSCALE:
633 regs = yuv422_regs;
634 break;
635 case PIXFORMAT_JPEG:
636 regs = jpeg_regs;
637 break;
638 default:
639 return E_PAR;
640 }
641
642 /* Write initial regsiters */
643 while(regs[i][0]){
644 cambus_writeb(hcmr, regs[i][0], regs[i][1]);
645 i++;
646 }
647 switch(hcmr->pixFormat) {
648 case PIXFORMAT_RGB565:
649 hcmr->hdvp->Init.Format = DVP_FORMAT_RGB;
650 break;
651 case PIXFORMAT_YUV422:
652 hcmr->hdvp->Init.Format = DVP_FORMAT_YUY;
653 break;
654 case PIXFORMAT_GRAYSCALE:
655 hcmr->hdvp->Init.Format = DVP_FORMAT_Y;
656 break;
657 case PIXFORMAT_JPEG:
658 hcmr->hdvp->Init.Format = DVP_FORMAT_RGB;
659 break;
660 default:
661 return E_PAR;
662 }
663 dvp_set_image_format(hcmr->hdvp);
664 /* delay n ms */
665 dly_tsk(30);
666 return E_OK;
667}
668
669ER
670ov2640_set_framesize(OV2640_t *hcmr)
671{
672 uint8_t clkrc;
673 uint16_t w = hcmr->_width;
674 uint16_t h = hcmr->_height;
675 int i=0;
676 const uint8_t (*regs)[2];
677
678 if((w <= 800) && (h <= 600)){
679 clkrc =0x80;
680 regs = svga_config;
681// regs = ov2640_config;
682 }
683 else{
684 clkrc =0x81;
685 regs = uxga_regs;
686 }
687
688 /* Disable DSP */
689 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
690 cambus_writeb(hcmr, R_BYPASS, R_BYPASS_DSP_BYPAS);
691
692 /* Set CLKRC */
693 if(clkrc == 0x81){
694 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
695 cambus_writeb(hcmr, CLKRC, clkrc);
696 }
697
698 /* Write DSP input regsiters */
699 while(regs[i][0]){
700 cambus_writeb(hcmr, regs[i][0], regs[i][1]);
701 i++;
702 }
703
704 /* Write output width */
705 cambus_writeb(hcmr,0xe0,0x04 ); /* OUTH[8]/OUTW[9:8] */
706 cambus_writeb(hcmr, ZMOW, (w>>2)&0xFF); /* OUTW[7:0] (real/4) */
707 cambus_writeb(hcmr, ZMOH, (h>>2)&0xFF); /* OUTH[7:0] (real/4) */
708 cambus_writeb(hcmr, ZMHH, ((h>>8)&0x04)|((w>>10)&0x03)); /* OUTH[8]/OUTW[9:8] */
709 cambus_writeb(hcmr,0xe0,0x00 ); /* OUTH[8]/OUTW[9:8] */
710
711 /* Enable DSP */
712 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
713 cambus_writeb(hcmr, R_BYPASS, R_BYPASS_DSP_EN);
714
715 /* delay n ms */
716 dly_tsk(30);
717 hcmr->hdvp->Init.Width = w;
718 hcmr->hdvp->Init.Height = h;
719 return dvp_set_image_size(hcmr->hdvp);
720}
721
722
723ER
724ov2640_activate(OV2640_t *hcmr, bool_t run)
725{
726 return dvp_activate(hcmr->hdvp, run);
727}
728
729int
730ov2640_id(OV2640_t *hcmr)
731{
732 return hcmr->_id;
733}
734
735ER
736ov2640_snapshot(OV2640_t *hcmr)
737{
738 DVP_Handle_t *hdvp = hcmr->hdvp;
739 int32_t timeout = SNAPDHOT_TIMEOUT;
740
741 //wait for new frame
742 hdvp->state = DVP_STATE_ACTIVATE;
743
744 while(hdvp->state != DVP_STATE_FINISH){
745 if(--timeout <= 0)
746 return E_TMOUT;
747 if(hdvp->semid != 0)
748 twai_sem(hdvp->semid, 1);
749 else
750 dly_tsk(1);
751 }
752 reverse_u32pixel((uint32_t*)hcmr->_dataBuffer, hcmr->_width * hcmr->_height/2);
753 return E_OK;
754}
755
756ER
757ov2640_cambus_scan_gc0328(OV2640_t *hcmr)
758{
759 uint8_t id;
760
761 dvp_sccb_send_data(hcmr->hdvp, GC0328_ADDR, 0xFE, 0x00);
762 id = dvp_sccb_receive_data(hcmr->hdvp, GC0328_ADDR, 0xf0);
763 if(id != 0x9d){
764 return 0;
765 }
766 return id;
767}
768
769
770ER
771ov2640_setInvert(OV2640_t *hcmr, bool_t invert)
772{
773 uint8_t reg;
774
775 cambus_readb(hcmr, BANK_SEL, &reg);
776 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
777 cambus_readb(hcmr, REG04, &reg);
778
779 if(invert){
780 reg |= REG04_HFLIP_IMG;
781 }
782 else{
783 reg &= ~REG04_HFLIP_IMG;
784 }
785 cambus_writeb(hcmr, REG04, reg);
786 return E_OK;
787}
788
789ER
790ov2640_set_contrast(OV2640_t *hcmr, int level)
791{
792 int i;
793
794 level += (NUM_CONTRAST_LEVELS / 2 + 1);
795 if(level < 0 || level > NUM_CONTRAST_LEVELS){
796 return E_PAR;
797 }
798
799 /* Switch to DSP register bank */
800 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
801
802 /* Write contrast registers */
803 for(i = 0 ; i < sizeof(contrast_regs[0])/sizeof(contrast_regs[0][0]) ; i++){
804 cambus_writeb(hcmr, contrast_regs[0][i], contrast_regs[level][i]);
805 }
806 return E_OK;
807}
808
809ER
810ov2640_set_brightness(OV2640_t *hcmr, int level)
811{
812 int i;
813
814 level += (NUM_BRIGHTNESS_LEVELS / 2 + 1);
815 if(level < 0 || level > NUM_BRIGHTNESS_LEVELS){
816 return E_PAR;
817 }
818
819 /* Switch to DSP register bank */
820 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
821
822 /* Write brightness registers */
823 for(i = 0 ; i < sizeof(brightness_regs[0])/sizeof(brightness_regs[0][0]) ; i++){
824 cambus_writeb(hcmr, brightness_regs[0][i], brightness_regs[level][i]);
825 }
826 return E_OK;
827}
828
829ER
830ov2640_set_saturation(OV2640_t *hcmr, int level)
831{
832 int i;
833
834 level += (NUM_SATURATION_LEVELS / 2 + 1);
835 if(level < 0 || level > NUM_SATURATION_LEVELS){
836 return E_PAR;
837 }
838
839 /* Switch to DSP register bank */
840 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
841
842 /* Write contrast registers */
843 for(i = 0 ; i < sizeof(saturation_regs[0])/sizeof(saturation_regs[0][0]) ; i++){
844 cambus_writeb(hcmr, saturation_regs[0][i], saturation_regs[level][i]);
845 }
846 return E_OK;
847}
848
849ER
850ov2640_set_gainceiling(OV2640_t *hcmr, gainceiling_t gainceiling)
851{
852 /* Switch to SENSOR register bank */
853 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
854
855 /* Write gain ceiling register */
856 cambus_writeb(hcmr, COM9, COM9_AGC_SET(gainceiling));
857 return E_OK;
858}
859
860ER
861ov2640_set_quality(OV2640_t *hcmr, int qs)
862{
863 /* Switch to DSP register bank */
864 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_DSP);
865
866 /* Write QS register */
867 cambus_writeb(hcmr, QS, qs);
868 return E_OK;
869}
870
871ER
872ov2640_set_colorbar(OV2640_t *hcmr, bool_t enable)
873{
874 uint8_t reg;
875
876 /* Switch to SENSOR register bank */
877 cambus_writeb(hcmr, BANK_SEL, BANK_SEL_SENSOR);
878
879 /* Update COM7 */
880 cambus_readb(hcmr, COM7, &reg);
881
882 if(enable){
883 reg |= COM7_COLOR_BAR;
884 }
885 else{
886 reg &= ~COM7_COLOR_BAR;
887 }
888 cambus_writeb(hcmr, COM7, reg);
889 return E_OK;
890}
891
892ER
893ov2640_set_auto_exposure(OV2640_t *hcmr, bool_t enable, int exposure_us)
894{
895 uint32_t freq = hcmr->hdvp->Init.Freq;
896 uint8_t reg;
897 int ret = 0;
898
899 cambus_readb(hcmr, BANK_SEL, &reg);
900 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
901 cambus_readb(hcmr, COM8, &reg);
902 cambus_writeb(hcmr, COM8, COM8_SET_AEC(reg, enable));
903
904 if((!enable) && (exposure_us >= 0)){
905 int t_line = 0;
906 int pll_mult, clk_rc, exposure;
907 int t_pclk = 0;
908 cambus_readb(hcmr, COM7, &reg);
909
910 if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
911 if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
912 if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
913
914 ret |= cambus_readb(hcmr, CLKRC, &reg);
915 pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
916 clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
917
918 ret |= cambus_readb(hcmr, BANK_SEL, &reg);
919 cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
920 ret |= cambus_readb(hcmr, IMAGE_MODE, &reg);
921
922 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
923 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
924 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
925
926 exposure = IM_MAX(IM_MIN(((exposure_us*(((freq/clk_rc)*pll_mult)/1000000))/t_pclk)/t_line,0xFFFF),0x0000);
927
928 ret |= cambus_readb(hcmr, BANK_SEL, &reg);
929 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
930
931 ret |= cambus_readb(hcmr, REG04, &reg);
932 cambus_writeb(hcmr, REG04, (reg & 0xFC) | ((exposure >> 0) & 0x3));
933
934 ret |= cambus_readb(hcmr, AEC, &reg);
935 cambus_writeb(hcmr, AEC, (reg & 0x00) | ((exposure >> 2) & 0xFF));
936
937 ret |= cambus_readb(hcmr, REG04, &reg);
938 cambus_writeb(hcmr, REG04, (reg & 0xC0) | ((exposure >> 10) & 0x3F));
939 }
940 if(ret == 0)
941 return E_OK;
942 else
943 return E_SYS;
944}
945
946ER
947ov2640_get_exposure_us(OV2640_t *hcmr, int *exposure_us)
948{
949 uint32_t freq = hcmr->hdvp->Init.Freq;
950 uint8_t reg, aec_10, aec_92, aec_1510;
951 int t_line = 0;
952 int t_pclk = 0;
953 int pll_mult, clk_rc;
954 uint16_t exposure;
955 int ret = cambus_readb(hcmr, BANK_SEL, &reg);
956
957 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
958 ret |= cambus_readb(hcmr, COM8, &reg);
959
960 // DISABLED
961 // if (reg & COM8_AEC_EN) {
962 // ret |= cambus_writeb(_slaveAddr, COM8, reg & (~COM8_AEC_EN));
963 // }
964 // DISABLED
965
966 ret |= cambus_readb(hcmr, REG04, &aec_10);
967 ret |= cambus_readb(hcmr, AEC, &aec_92);
968 ret |= cambus_readb(hcmr, REG45, &aec_1510);
969
970 // DISABLED
971 // if (reg & COM8_AEC_EN) {
972 // ret |= cambus_writeb(_slaveAddr, COM8, reg | COM8_AEC_EN);
973 // }
974 // DISABLED
975
976 ret |= cambus_readb(hcmr, COM7, &reg);
977
978 if (COM7_GET_RES(reg) == COM7_RES_UXGA) t_line = 1600 + 322;
979 if (COM7_GET_RES(reg) == COM7_RES_SVGA) t_line = 800 + 390;
980 if (COM7_GET_RES(reg) == COM7_RES_CIF) t_line = 400 + 195;
981
982 ret |= cambus_readb(hcmr, CLKRC, &reg);
983 pll_mult = (reg & CLKRC_DOUBLE) ? 2 : 1;
984 clk_rc = ((reg & CLKRC_DIVIDER_MASK) + 1) * 2;
985
986 ret |= cambus_readb(hcmr, BANK_SEL, &reg);
987 cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
988 ret |= cambus_readb(hcmr, IMAGE_MODE, &reg);
989
990 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_YUV422) t_pclk = 2;
991 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RAW10) t_pclk = 1;
992 if (IMAGE_MODE_GET_FMT(reg) == IMAGE_MODE_RGB565) t_pclk = 2;
993
994 exposure = ((aec_1510 & 0x3F) << 10) + ((aec_92 & 0xFF) << 2) + ((aec_10 & 0x3) << 0);
995 *exposure_us = (exposure*t_line*t_pclk)/(((freq/clk_rc)*pll_mult)/1000000);
996 if(ret == 0)
997 return E_OK;
998 else
999 return E_SYS;
1000}
1001
1002ER
1003ov2640_set_auto_whitebal(OV2640_t *hcmr, bool_t enable, float r_gain_db, float g_gain_db, float b_gain_db)
1004{
1005 uint8_t reg;
1006 int ret = cambus_readb(hcmr, BANK_SEL, &reg);
1007 cambus_writeb(hcmr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
1008 ret |= cambus_readb(hcmr, CTRL1, &reg);
1009 cambus_writeb(hcmr, CTRL1, (reg & (~CTRL1_AWB)) | (enable ? CTRL1_AWB : 0));
1010
1011 if((!enable) && (!isnanf(r_gain_db)) && (!isnanf(g_gain_db)) && (!isnanf(b_gain_db))
1012 && (!isinff(r_gain_db)) && (!isinff(g_gain_db)) && (!isinff(b_gain_db))) {
1013 }
1014 if(ret == 0)
1015 return E_OK;
1016 else
1017 return E_SYS;
1018}
1019
1020ER
1021ov2640_set_vflip(OV2640_t *hcmr, bool_t enable)
1022{
1023 uint8_t reg;
1024 int ret = cambus_readb(hcmr, BANK_SEL, &reg);
1025 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
1026 ret |= cambus_readb(hcmr, REG04, &reg);
1027
1028 if(enable){
1029 reg |= REG04_VFLIP_IMG;
1030 reg |= REG04_VREF_EN;
1031 }
1032 else{
1033 reg &= ~REG04_VFLIP_IMG;
1034 reg &= ~REG04_VREF_EN;
1035 }
1036 cambus_writeb(hcmr, REG04, reg);
1037 if(ret == 0)
1038 return E_OK;
1039 else
1040 return E_SYS;
1041}
1042
1043#ifdef USE_GAIN
1044ER
1045ov2640_set_auto_gain(OV2640_t *hcmr, bool_t enable, float gain_db, float gain_db_ceiling)
1046{
1047 uint8_t reg;
1048
1049 cambus_readb(hcmr, BANK_SEL, &reg);
1050 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
1051 cambus_readb(hcmr, COM8, &reg);
1052 cambus_writeb(hcmr, COM8, (reg & (~COM8_AGC_EN)) | ((enable != 0) ? COM8_AGC_EN : 0));
1053
1054 if((!enable) && (!isnanf(gain_db)) && (!isinff(gain_db))){
1055 float gain = IM_MAX(IM_MIN(expf((gain_db / 20.0) * log(10.0)), 32.0), 1.0);
1056 int gain_temp = roundf(log2(IM_MAX(gain / 2.0, 1.0)));
1057 int gain_hi = 0xF >> (4 - gain_temp);
1058 int gain_lo = IM_MIN(roundf(((gain / (1 << gain_temp)) - 1.0) * 16.0), 15);
1059
1060 cambus_writeb(hcmr, GAIN, (gain_hi << 4) | (gain_lo << 0));
1061 }
1062 else if(enable && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))){
1063 float gain_ceiling = IM_MAX(IM_MIN(expf((gain_db_ceiling / 20.0) * log(10.0)), 128.0), 2.0);
1064
1065 cambus_readb(hcmr, COM9, &reg);
1066 cambus_writeb(hcmr, COM9, (reg & 0x1F) | (((int)ceilf(log2(gain_ceiling)) - 1) << 5));
1067 }
1068 return E_OK;
1069}
1070
1071ER
1072ov2640_get_gain_db(OV2640_t *hcmr, float *gain_db)
1073{
1074 uint8_t reg, gain;
1075 int hi_gain;
1076 float lo_gain;
1077
1078 cambus_readb(hcmr, BANK_SEL, &reg);
1079 cambus_writeb(hcmr, BANK_SEL, reg | BANK_SEL_SENSOR);
1080 cambus_readb(hcmr, COM8, &reg);
1081
1082 // DISABLED
1083 // if (reg & COM8_AGC_EN) {
1084 // ret |= cambus_writeb(_slaveAddr, COM8, reg & (~COM8_AGC_EN));
1085 // }
1086 // DISABLED
1087
1088 cambus_readb(hcmr, GAIN, &gain);
1089
1090 // DISABLED
1091 // if (reg & COM8_AGC_EN) {
1092 // ret |= cambus_writeb(_slaveAddr, COM8, reg | COM8_AGC_EN);
1093 // }
1094 // DISABLED
1095
1096 hi_gain = 1 << (((gain >> 7) & 1) + ((gain >> 6) & 1) + ((gain >> 5) & 1) + ((gain >> 4) & 1));
1097 lo_gain = 1.0 + (((gain >> 0) & 0xF) / 16.0);
1098 *gain_db = 20.0 * (log(hi_gain * lo_gain) / log(10.0));
1099 return E_OK;
1100}
1101#endif /* USE_GAIN */
1102
Note: See TracBrowser for help on using the repository browser.