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   = &reg;
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