1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-08-03 thread-liu the first version
9 */
10
11 #include "board.h"
12
13 #if defined(BSP_USING_OV2640)
14
15 #include <dfs_file.h>
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <sys/stat.h>
19 #include <sys/statfs.h>
20 #include <drv_ov2640.h>
21 #include <drv_dcmi.h>
22 #include "pcf8574.h"
23
24 #define DRV_DEBUG
25 //#define CAMERA_DUMP
26 #define LOG_TAG "drv.ov2640"
27 #include <drv_log.h>
28
29 #define DEV_ADDRESS 0x30 /* OV2640 address */
30 #define I2C_NAME "i2c2"
31
32 #define RESET_PIN GET_PIN(A, 15) /* camera reset pin */
33
34 /* camera PWDN pin */
35 #define DCMI_PWDN_IO 2 /* pcf8574 (0-7) */
36
37 volatile rt_uint32_t jpeg_data_len = 0;
38 volatile rt_uint8_t jpeg_data_ok = 0;
39 struct rt_i2c_bus_device *i2c_bus = RT_NULL;
40
41 #define JPEG_BUF_SIZE 32 * 1024
42 #define JPEG_LINE_SIZE 1 * 1024
43
44 static pcf8574_device_t pcf_dev = RT_NULL;
45
46 static rt_uint32_t *jpeg_data_buf = RT_NULL;
47 static rt_uint32_t JPEG_LINE0_BUF[JPEG_LINE_SIZE];
48 static rt_uint32_t JPEG_LINE1_BUF[JPEG_LINE_SIZE];
49
50 #if defined(CAMERA_DUMP)
51 #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
dump_hex(const rt_uint8_t * ptr,rt_size_t buflen)52 static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
53 {
54 unsigned char *buf = (unsigned char *)ptr;
55 int i, j;
56
57 for (i = 0; i < buflen; i += 16)
58 {
59 rt_kprintf("%08x:", i);
60
61 for (j = 0; j < 16; j++)
62 {
63 if (i + j < buflen)
64 {
65 rt_kprintf("%02x", buf[i + j]);
66 }
67 else
68 {
69 rt_kprintf(" ");
70 }
71 }
72 rt_kprintf(" ");
73
74 for (j = 0; j < 16; j++)
75 {
76 if (i + j < buflen)
77 {
78 rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
79 }
80 }
81 rt_kprintf("\n");
82 }
83 }
84 #endif
85
read_reg(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint8_t len,rt_uint8_t * buf)86 static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf)
87 {
88 struct rt_i2c_msg msg[2];
89
90 RT_ASSERT(bus != RT_NULL);
91
92 msg[0].addr = DEV_ADDRESS;
93 msg[0].flags = RT_I2C_WR;
94 msg[0].buf = ®
95 msg[0].len = 2;
96
97 msg[1].addr = DEV_ADDRESS;
98 msg[1].flags = RT_I2C_RD;
99 msg[1].len = len;
100 msg[1].buf = buf;
101
102 if (rt_i2c_transfer(bus, msg, 2) == 2)
103 {
104 return RT_EOK;
105 }
106
107 return -RT_ERROR;
108 }
109
110 /* i2c write reg */
write_reg(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint8_t data)111 static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data)
112 {
113 rt_uint8_t buf[2];
114 struct rt_i2c_msg msgs;
115
116 RT_ASSERT(bus != RT_NULL);
117
118 buf[0] = reg ;
119 buf[1] = data;
120
121 msgs.addr = DEV_ADDRESS;
122 msgs.flags = RT_I2C_WR;
123 msgs.buf = buf;
124 msgs.len = 2;
125
126 if (rt_i2c_transfer(bus, &msgs, 1) == 1)
127 {
128 return RT_EOK;
129 }
130
131 return -RT_ERROR;
132 }
133
ov2640_read_id(struct rt_i2c_bus_device * bus)134 static rt_err_t ov2640_read_id(struct rt_i2c_bus_device *bus)
135 {
136 rt_uint8_t read_value[2];
137 rt_uint16_t id = 0;
138 read_reg(bus, OV2640_SENSOR_MIDH, 1, &read_value[0]);
139 read_reg(bus, OV2640_SENSOR_MIDL, 1, &read_value[1]);
140 id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00);
141 id |= ((rt_uint16_t)(read_value[1]) & 0x00FF);
142
143 if (id != OV2640_MID)
144 {
145 LOG_E("ov2640 init error, mid: 0x%04x", id);
146 return -RT_ERROR;
147 }
148
149 LOG_I("ov2640 read mid success, mid: 0x%04x", id);
150
151 read_reg(bus, OV2640_SENSOR_PIDH, 1, &read_value[0]);
152 read_reg(bus, OV2640_SENSOR_PIDL, 1, &read_value[1]);
153 id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00);
154 id |= ((rt_uint16_t)(read_value[1]) & 0x00FF);
155
156 if (id != OV2640_PID)
157 {
158 LOG_E("ov2640 init error, pid: 0x%04x", id);
159 return -RT_ERROR;
160 }
161
162 LOG_I("ov2640 read hid success, pid: 0x%04x", id);
163
164 return RT_EOK;
165 }
166
167 /* change ov2640 to jpeg mode */
ov2640_jpeg_mode(void)168 void ov2640_jpeg_mode(void)
169 {
170 rt_uint16_t i=0;
171 /* set yun422 mode */
172 for (i = 0; i < (sizeof(ov2640_yuv422_reg_tbl) / 2); i++)
173 {
174 write_reg(i2c_bus, ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]);
175 }
176
177 /* set jpeg mode */
178 for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++)
179 {
180 write_reg(i2c_bus, ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]);
181 }
182 }
183
184 /* change ov2640 to rgb565 mode */
ov2640_rgb565_mode(void)185 void ov2640_rgb565_mode(void)
186 {
187 rt_uint16_t i=0;
188 for (i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++)
189 {
190 write_reg(i2c_bus, ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]);
191 }
192 }
193
194 /* set auto exposure */
ov2640_set_auto_exposure(rt_uint8_t level)195 void ov2640_set_auto_exposure(rt_uint8_t level)
196 {
197 rt_uint8_t i = 0;
198 rt_uint8_t *p = (rt_uint8_t*)OV2640_AUTOEXPOSURE_LEVEL[level];
199 for (i = 0; i < 4; i++)
200 {
201 write_reg(i2c_bus, p[i*2],p[i*2+1]);
202 }
203 }
204
205 /* set light mode
206 * 0: auto
207 * 1: sunny
208 * 2: cloudy
209 * 3: office
210 * 4: home
211 * */
ov2640_set_light_mode(rt_uint8_t mode)212 void ov2640_set_light_mode(rt_uint8_t mode)
213 {
214 rt_uint8_t regccval, regcdval, regceval;
215
216 switch(mode)
217 {
218 case 0:
219 write_reg(i2c_bus, 0xFF, 0x00);
220 write_reg(i2c_bus, 0xC7, 0x10);
221 return;
222
223 case 2:
224 regccval = 0x65;
225 regcdval = 0x41;
226 regceval = 0x4F;
227 break;
228
229 case 3:
230 regccval = 0x52;
231 regcdval = 0x41;
232 regceval = 0x66;
233 break;
234
235 case 4:
236 regccval = 0x42;
237 regcdval = 0x3F;
238 regceval = 0x71;
239 break;
240
241 default:
242 regccval = 0x5E;
243 regcdval = 0x41;
244 regceval = 0x54;
245 break;
246 }
247
248 write_reg(i2c_bus, 0xFF, 0x00);
249 write_reg(i2c_bus, 0xC7, 0x40);
250 write_reg(i2c_bus, 0xCC, regccval);
251 write_reg(i2c_bus, 0xCD, regcdval);
252 write_reg(i2c_bus, 0xCE, regceval);
253 }
254
255 /* set color saturation
256 * 0: -2
257 * 1: -1
258 * 2: 0
259 * 3: +1
260 * 4: +2
261 * */
ov2640_set_color_saturation(rt_uint8_t sat)262 void ov2640_set_color_saturation(rt_uint8_t sat)
263 {
264 rt_uint8_t reg7dval = ((sat+2)<<4) | 0x08;
265 write_reg(i2c_bus, 0xFF, 0X00);
266 write_reg(i2c_bus, 0x7C, 0X00);
267 write_reg(i2c_bus, 0x7D, 0X02);
268 write_reg(i2c_bus, 0x7C, 0X03);
269 write_reg(i2c_bus, 0x7D, reg7dval);
270 write_reg(i2c_bus, 0x7D, reg7dval);
271 }
272
273 /* set brightness
274 * 0: -2
275 * 1: -1
276 * 2: 0
277 * 3: 1
278 * 4: 2
279 * */
ov2640_set_brightness(rt_uint8_t bright)280 void ov2640_set_brightness(rt_uint8_t bright)
281 {
282 write_reg(i2c_bus, 0xff, 0x00);
283 write_reg(i2c_bus, 0x7c, 0x00);
284 write_reg(i2c_bus, 0x7d, 0x04);
285 write_reg(i2c_bus, 0x7c, 0x09);
286 write_reg(i2c_bus, 0x7d, bright << 4);
287 write_reg(i2c_bus, 0x7d, 0x00);
288 }
289
290 /* set contrast
291 * 0: -2
292 * 1: -1
293 * 2: 0
294 * 3: 1
295 * 4: 2
296 * */
ov2640_set_contrast(rt_uint8_t contrast)297 void ov2640_set_contrast(rt_uint8_t contrast)
298 {
299 rt_uint8_t reg7d0val, reg7d1val;
300
301 switch(contrast)
302 {
303 case 0:
304 reg7d0val = 0x18;
305 reg7d1val = 0x34;
306 break;
307
308 case 1:
309 reg7d0val = 0x1C;
310 reg7d1val = 0x2A;
311 break;
312
313 case 3:
314 reg7d0val = 0x24;
315 reg7d1val = 0x16;
316 break;
317
318 case 4:
319 reg7d0val = 0x28;
320 reg7d1val = 0x0C;
321 break;
322
323 default:
324 reg7d0val = 0x20;
325 reg7d1val = 0x20;
326 break;
327 }
328 write_reg(i2c_bus, 0xff, 0x00);
329 write_reg(i2c_bus, 0x7c, 0x00);
330 write_reg(i2c_bus, 0x7d, 0x04);
331 write_reg(i2c_bus, 0x7c, 0x07);
332 write_reg(i2c_bus, 0x7d, 0x20);
333 write_reg(i2c_bus, 0x7d, reg7d0val);
334 write_reg(i2c_bus, 0x7d, reg7d1val);
335 write_reg(i2c_bus, 0x7d, 0x06);
336 }
337
338 /* set special effects
339 * 0: noraml
340 * 1: negative film
341 * 2: black-and-white
342 * 3: the red
343 * 4: the green
344 * 5: the blue
345 * 6: Retro
346 */
ov2640_set_special_effects(rt_uint8_t eft)347 void ov2640_set_special_effects(rt_uint8_t eft)
348 {
349 rt_uint8_t reg7d0val, reg7d1val, reg7d2val;
350
351 switch(eft)
352 {
353 case 1:
354 reg7d0val = 0x40;
355 break;
356 case 2:
357 reg7d0val = 0x18;
358 break;
359 case 3:
360 reg7d0val = 0x18;
361 reg7d1val = 0x40;
362 reg7d2val = 0xC0;
363 break;
364 case 4:
365 reg7d0val = 0x18;
366 reg7d1val = 0x40;
367 reg7d2val = 0x40;
368 break;
369 case 5:
370 reg7d0val = 0x18;
371 reg7d1val = 0xA0;
372 reg7d2val = 0x40;
373 break;
374 case 6:
375 reg7d0val = 0x18;
376 reg7d1val = 0x40;
377 reg7d2val = 0xA6;
378 break;
379 default:
380 reg7d0val = 0x00;
381 reg7d1val = 0x80;
382 reg7d2val = 0x80;
383 break;
384 }
385 write_reg(i2c_bus, 0xff, 0x00);
386 write_reg(i2c_bus, 0x7c, 0x00);
387 write_reg(i2c_bus, 0x7d, reg7d0val);
388 write_reg(i2c_bus, 0x7c, 0x05);
389 write_reg(i2c_bus, 0x7d, reg7d1val);
390 write_reg(i2c_bus, 0x7d, reg7d2val);
391 }
392
393 /* set the image output window */
ov2640_set_window_size(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height)394 void ov2640_set_window_size(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height)
395 {
396 rt_uint16_t endx;
397 rt_uint16_t endy;
398 rt_uint8_t temp;
399 endx = sx + width / 2;
400 endy = sy + height / 2;
401
402 write_reg(i2c_bus, 0xFF, 0x01);
403 read_reg(i2c_bus, 0x03, 1, &temp);
404 temp &= 0xF0;
405 temp |= ((endy & 0x03) << 2) | (sy & 0x03);
406 write_reg(i2c_bus, 0x03, temp);
407 write_reg(i2c_bus, 0x19, sy>>2);
408 write_reg(i2c_bus, 0x1A, endy>>2);
409
410 read_reg(i2c_bus, 0x32, 1, &temp);
411 temp &= 0xC0;
412 temp |= ((endx & 0x07) << 3) | (sx & 0x07);
413 write_reg(i2c_bus, 0x32, temp);
414 write_reg(i2c_bus, 0x17, sx>>3);
415 write_reg(i2c_bus, 0x18, endx>>3);
416 }
417
418 /* set the image output size */
ov2640_set_image_out_size(rt_uint16_t width,rt_uint16_t height)419 rt_uint8_t ov2640_set_image_out_size(rt_uint16_t width,rt_uint16_t height)
420 {
421 rt_uint16_t outh, outw;
422 rt_uint8_t temp;
423
424 if(width%4)return 1;
425 if(height%4)return 2;
426 outw = width / 4;
427 outh = height / 4;
428 write_reg(i2c_bus, 0xFF, 0x00);
429 write_reg(i2c_bus, 0xE0, 0x04);
430 write_reg(i2c_bus, 0x5A, outw & 0XFF);
431 write_reg(i2c_bus, 0x5B, outh & 0XFF);
432 temp = (outw >> 8) & 0x03;
433 temp |= (outh >> 6) & 0x04;
434 write_reg(i2c_bus, 0x5C, temp);
435 write_reg(i2c_bus, 0xE0, 0X00);
436
437 return RT_EOK;
438 }
439
440 /* set the image window size */
ov2640_set_image_window_size(rt_uint16_t offx,rt_uint16_t offy,rt_uint16_t width,rt_uint16_t height)441 rt_err_t ov2640_set_image_window_size(rt_uint16_t offx, rt_uint16_t offy, rt_uint16_t width, rt_uint16_t height)
442 {
443 rt_uint16_t hsize, vsize;
444 rt_uint8_t temp;
445 if ((width % 4) || (height%4))
446 {
447 return -RT_ERROR;
448 }
449 hsize = width / 4;
450 vsize = height / 4;
451 write_reg(i2c_bus, 0XFF,0X00);
452 write_reg(i2c_bus, 0XE0,0X04);
453 write_reg(i2c_bus, 0X51,hsize&0XFF);
454 write_reg(i2c_bus, 0X52,vsize&0XFF);
455 write_reg(i2c_bus, 0X53,offx&0XFF);
456 write_reg(i2c_bus, 0X54,offy&0XFF);
457 temp=(vsize>>1)&0X80;
458 temp|=(offy>>4)&0X70;
459 temp|=(hsize>>5)&0X08;
460 temp|=(offx>>8)&0X07;
461 write_reg(i2c_bus, 0X55,temp);
462 write_reg(i2c_bus, 0X57,(hsize>>2)&0X80);
463 write_reg(i2c_bus, 0XE0,0X00);
464 return RT_EOK;
465 }
466
467 /* set output resolution */
ov2640_set_image_size(rt_uint16_t width,rt_uint16_t height)468 rt_uint8_t ov2640_set_image_size(rt_uint16_t width ,rt_uint16_t height)
469 {
470 rt_uint8_t temp;
471 write_reg(i2c_bus, 0xFF, 0x00);
472 write_reg(i2c_bus, 0xE0, 0x04);
473 write_reg(i2c_bus, 0xC0, (width >>3) & 0xFF);
474 write_reg(i2c_bus, 0xC1, (height >> 3) & 0xFF);
475 temp = (width & 0x07) << 3;
476 temp |= height & 0x07;
477 temp |= (width >> 4) & 0x80;
478 write_reg(i2c_bus, 0x8C, temp);
479 write_reg(i2c_bus, 0xE0, 0x00);
480
481 return RT_EOK;
482 }
483
camera_dma_data_process(void)484 void camera_dma_data_process(void)
485 {
486 rt_uint16_t i;
487 rt_uint32_t *pbuf;
488 pbuf = jpeg_data_buf + jpeg_data_len;
489
490 if (DMA2_Stream1->CR & (1<<19))
491 {
492 for (i = 0; i < JPEG_LINE_SIZE; i++)
493 {
494 pbuf[i] = JPEG_LINE0_BUF[i];
495 }
496 jpeg_data_len += JPEG_LINE_SIZE;
497 }
498 else
499 {
500 for (i = 0; i < JPEG_LINE_SIZE; i++)
501 {
502 pbuf[i] = JPEG_LINE1_BUF[i];
503 }
504 jpeg_data_len += JPEG_LINE_SIZE;
505 }
506 SCB_CleanInvalidateDCache();
507 }
508
509 /* After a frame of picture data has been collected. */
camera_frame_data_process(void)510 void camera_frame_data_process(void)
511 {
512 rt_uint16_t i, rlen;
513 rt_uint32_t *pbuf = RT_NULL;
514
515 if (jpeg_data_ok == 0)
516 {
517 DMA2_Stream1->CR &= ~(1<<0);
518 while(DMA2_Stream1->CR & 0x01);
519
520 rlen = JPEG_LINE_SIZE - DMA2_Stream1->NDTR;
521 pbuf = jpeg_data_buf + jpeg_data_len;
522
523 if (DMA2_Stream1->CR & (1<<19))
524 {
525 for (i = 0; i < rlen; i++)
526 {
527 pbuf[i] = JPEG_LINE1_BUF[i];
528 }
529 }
530 else
531 {
532 for (i = 0; i < rlen; i++)
533 {
534 pbuf[i] = JPEG_LINE0_BUF[i];
535 }
536 }
537 jpeg_data_len += rlen;
538 jpeg_data_ok = 1;
539 }
540 if (jpeg_data_ok==2)
541 {
542 DMA2_Stream1->NDTR = JPEG_LINE_SIZE;
543 DMA2_Stream1->CR |= 1<<0;
544 jpeg_data_ok = 0;
545 jpeg_data_len = 0;
546 }
547 }
548
ov2640_pwdn_set(rt_uint8_t sta)549 int ov2640_pwdn_set(rt_uint8_t sta)
550 {
551 if (pcf_dev == RT_NULL)
552 {
553 LOG_E("can't find pcf8574 device!");
554 return -1;
555 }
556 pcf8574_pin_write(pcf_dev, DCMI_PWDN_IO, sta);
557
558 return 0;
559 }
560
sw_ov2640_mode(void)561 void sw_ov2640_mode(void)
562 {
563 GPIO_InitTypeDef GPIO_Initure = {0};
564
565 ov2640_pwdn_set(0);
566
567 GPIO_Initure.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11;
568 GPIO_Initure.Mode = GPIO_MODE_AF_PP;
569 GPIO_Initure.Pull = GPIO_PULLUP;
570 GPIO_Initure.Speed = GPIO_SPEED_HIGH;
571 GPIO_Initure.Alternate = GPIO_AF13_DCMI;
572 HAL_GPIO_Init(GPIOC,&GPIO_Initure);
573 }
574
sw_sdcard_mode(void)575 void sw_sdcard_mode(void)
576 {
577 GPIO_InitTypeDef GPIO_Initure = {0};
578
579 ov2640_pwdn_set(1); /* OV2640 Power Down */
580
581 GPIO_Initure.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11;
582 GPIO_Initure.Mode = GPIO_MODE_AF_PP;
583 GPIO_Initure.Pull = GPIO_PULLUP;
584 GPIO_Initure.Speed = GPIO_SPEED_HIGH;
585 GPIO_Initure.Alternate = GPIO_AF12_SDMMC1;
586 HAL_GPIO_Init(GPIOC, &GPIO_Initure);
587 }
588
rt_ov2640_init(void)589 int rt_ov2640_init(void)
590 {
591 rt_uint16_t i = 0;
592 rt_err_t result = RT_EOK;
593 rt_device_t dcmi_dev = RT_NULL;
594
595 sw_ov2640_mode();
596 pcf_dev = pcf8574_init("i2c1", RT_NULL);
597 if (pcf_dev == RT_NULL)
598 {
599 LOG_E("can't find pcf8574, please check it");
600 return -RT_ERROR;
601 }
602
603 ov2640_pwdn_set(0);
604 rt_thread_delay(20);
605
606 /* ov2640 hard reset */
607 rt_pin_mode(RESET_PIN, PIN_MODE_OUTPUT);
608 rt_pin_write(RESET_PIN, PIN_LOW);
609 rt_thread_delay(20);
610 rt_pin_write(RESET_PIN, PIN_HIGH);
611 rt_thread_delay(20);
612
613 i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
614 if (i2c_bus == RT_NULL)
615 {
616 LOG_E("can't find %s deivce", I2C_NAME);
617 return -RT_ERROR;
618 }
619 /* Prepare the camera to be configured */
620 result = write_reg(i2c_bus, OV2640_DSP_RA_DLMT, 0x01);
621 if (result != RT_EOK )
622 {
623 LOG_E("ov2640 write reg error!");
624 return -RT_ERROR;
625 }
626 rt_thread_delay(10);
627 result = write_reg(i2c_bus, OV2640_SENSOR_COM7, 0x80);
628 if (result != RT_EOK)
629 {
630 LOG_E("ov2640 soft reset error!");
631 return -RT_ERROR;
632 }
633 rt_thread_delay(20);
634
635 result = ov2640_read_id(i2c_bus);
636 if (result != RT_EOK )
637 {
638 LOG_E("ov2640 read id error!");
639 return -RT_ERROR;
640 }
641
642 for (i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++)
643 {
644 write_reg(i2c_bus, ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1]);
645 }
646
647 ov2640_rgb565_mode();
648 ov2640_set_light_mode(0);
649 ov2640_set_color_saturation(3);
650 ov2640_set_brightness(4);
651 ov2640_set_contrast(3);
652 ov2640_jpeg_mode();
653 ov2640_set_image_window_size(0, 0, 320, 240);
654 ov2640_set_image_out_size(320, 240);
655
656 dcmi_dev = rt_device_find("dcmi");
657 if (dcmi_dev == RT_NULL)
658 {
659 LOG_E("can't find dcmi device!");
660 return -RT_ERROR;
661 }
662 rt_device_open(dcmi_dev, RT_DEVICE_FLAG_RDWR);
663
664 jpeg_data_buf = rt_malloc(JPEG_BUF_SIZE);
665 if (RT_NULL == jpeg_data_buf)
666 {
667 rt_kprintf("jpeg data buf malloc error!\n");
668 return -RT_ERROR;
669 }
670
671 /* start dcmi capture */
672 rt_hw_dcmi_dma_config((rt_uint32_t)JPEG_LINE0_BUF, (rt_uint32_t)JPEG_LINE1_BUF, JPEG_LINE_SIZE);
673
674 rt_kprintf("camera init success!\n");
675
676 return RT_EOK;
677 }
678 INIT_APP_EXPORT(rt_ov2640_init);
679
camera_sample(int argc,char ** argv)680 int camera_sample(int argc, char **argv)
681 {
682 rt_err_t result = RT_EOK;
683 int fd = -1;
684 rt_uint32_t i, jpg_start, jpg_len;
685 rt_uint8_t jpg_head = 0;
686 rt_uint8_t *p = RT_NULL;
687
688 if (argc != 2)
689 {
690 rt_kprintf("Usage:\n");
691 rt_kprintf("camera_sample file.jpg\n");
692 return -1;
693 }
694
695 sw_ov2640_mode();
696 DCMI_Start();
697
698 while (1)
699 {
700 while (jpeg_data_ok != 1);
701 jpeg_data_ok = 2;
702 while (jpeg_data_ok != 1);
703 DCMI_Stop();
704
705 p = (rt_uint8_t *)jpeg_data_buf;
706 jpg_len = 0;
707 jpg_head = 0;
708 for (i = 0; i < jpeg_data_len * 4; i++)
709 {
710 /* jpg head */
711 if ((p[i] == 0xFF) && (p[i + 1] == 0xD8))
712 {
713 jpg_start = i;
714 jpg_head = 1;
715 }
716 /* jpg end */
717 if ((p[i] == 0xFF) && (p[i + 1] == 0xD9) && jpg_head)
718 {
719 jpg_len = i - jpg_start + 2; /* a picture len */
720 break;
721 }
722 }
723 if (jpg_len)
724 {
725 p += jpg_start;
726 sw_sdcard_mode();
727 fd = open(argv[1], O_WRONLY | O_CREAT);
728 if (fd < 0)
729 {
730 rt_kprintf("open file for recording failed!\n");
731 result = -RT_ERROR;
732 goto _exit;
733 }
734 else
735 {
736 write(fd, p, jpg_len);
737 close(fd);
738 rt_kprintf("%s picture capture complate!\n", argv[1]);
739 break;
740 }
741 }
742 else
743 {
744 rt_kprintf("jpg_len error!\n");
745 result = -RT_ERROR;
746 goto _exit;
747 }
748 }
749
750 _exit:
751 return result;;
752 }
753 MSH_CMD_EXPORT(camera_sample, record picture to a jpg file);
754
755 #endif
756