1 /*
2 * Copyright (c) 2006-2022, 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 * 2022-04-13 Miaowulue fit openmv-h7plus
10 */
11
12 #include "board.h"
13
14 #ifdef BSP_USING_OV5640
15
16 #include <dfs_file.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <sys/stat.h>
20 #include <sys/statfs.h>
21 #include "drv_ov5640.h"
22
23 //#define DRV_DEBUG
24 //#define CAMERA_DUMP
25 #define LOG_TAG "drv.ov5640"
26 #include <drv_log.h>
27
28 #define CHIP_ADDRESS 0x3C /* OV5640 address */
29 #define I2C_NAME "i2c1"
30 #define RST_PIN GET_PIN(A, 10)
31 #define PWDN_PIN GET_PIN(D, 7)
32
33 #define JPEG_BUF_SIZE 8 * 1024
34 #define JPEG_LINE_SIZE 1 * 1024
35
36 static rt_int32_t JPEG_DATA_BUF[JPEG_BUF_SIZE];
37 static rt_int32_t JPEG_LINE_BUF[2][JPEG_LINE_SIZE];
38
39 volatile rt_uint32_t jpeg_data_len = 0;
40 volatile rt_uint8_t jpeg_data_ok = 0;
41 struct rt_i2c_bus_device *i2c_bus = RT_NULL;
42 extern DCMI_HandleTypeDef dcmi;
43 extern DMA_HandleTypeDef hdma_dcmi;
44
45 #if defined(CAMERA_DUMP)
46 #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
dump_hex(const rt_uint8_t * ptr,rt_size_t buflen)47 static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
48 {
49 unsigned char *buf = (unsigned char *)ptr;
50 int i, j;
51
52 for (i = 0; i < buflen; i += 16)
53 {
54 rt_kprintf("%08x:", i);
55
56 for (j = 0; j < 16; j++)
57 {
58 if (i + j < buflen)
59 {
60 rt_kprintf("%02x", buf[i + j]);
61 }
62 else
63 {
64 rt_kprintf(" ");
65 }
66 }
67 rt_kprintf(" ");
68
69 for (j = 0; j < 16; j++)
70 {
71 if (i + j < buflen)
72 {
73 rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
74 }
75 }
76 rt_kprintf("\n");
77 }
78 }
79 #endif
80
81 /* i2c read reg */
read_reg(struct rt_i2c_bus_device * bus,rt_uint16_t reg,rt_uint8_t len,rt_uint8_t * buf)82 static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint16_t reg, rt_uint8_t len, rt_uint8_t *buf)
83 {
84 struct rt_i2c_msg msg[2] = {0, 0};
85 static rt_uint8_t i2c_reg[2] = {0, 0};
86
87 RT_ASSERT(bus != RT_NULL);
88
89 i2c_reg[0] = ((uint16_t)(reg >> 8) & 0xFF);
90 i2c_reg[1] = ((uint16_t)(reg & 0xFF));
91
92 msg[0].addr = CHIP_ADDRESS;
93 msg[0].flags = RT_I2C_WR;
94 msg[0].buf = i2c_reg;
95 msg[0].len = 2;
96
97 msg[1].addr = CHIP_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_uint16_t reg,rt_uint8_t data)111 static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint16_t reg, rt_uint8_t data)
112 {
113 rt_uint8_t buf[3];
114 struct rt_i2c_msg msgs;
115
116 RT_ASSERT(bus != RT_NULL);
117
118 buf[0] = ((uint16_t)(reg >> 8) & 0xFF);
119 buf[1] = ((uint16_t)(reg)&0xFF);
120
121 buf[2] = data;
122
123 msgs.addr = CHIP_ADDRESS;
124 msgs.flags = RT_I2C_WR;
125 msgs.buf = buf;
126 msgs.len = 3;
127
128 if (rt_i2c_transfer(bus, &msgs, 1) == 1)
129 {
130 return RT_EOK;
131 }
132
133 return -RT_ERROR;
134 }
135
ov5640_read_id(struct rt_i2c_bus_device * bus,rt_uint16_t * id)136 static rt_err_t ov5640_read_id(struct rt_i2c_bus_device *bus, rt_uint16_t *id)
137 {
138 rt_uint8_t read_value[2];
139
140 read_reg(bus, 0x300A, 1, &read_value[0]);
141 read_reg(bus, 0x300B, 1, &read_value[1]);
142 *id = ((uint16_t)(read_value[0] << 8) & 0xFF00);
143 *id |= ((uint16_t)(read_value[1]) & 0x00FF);
144
145 if (*id != OV5640_ID)
146 {
147 LOG_E("ov5640 init error, id: 0x%04x", *id);
148 return -RT_ERROR;
149 }
150
151 LOG_I("ov5640 init success, id: 0x%04x", *id);
152
153 return RT_EOK;
154 }
155
ov5640_hard_reset(void)156 static rt_err_t ov5640_hard_reset(void)
157 {
158 rt_pin_mode(RST_PIN, PIN_MODE_OUTPUT);
159 rt_pin_mode(PWDN_PIN, PIN_MODE_OUTPUT);
160
161 rt_pin_write(RST_PIN, PIN_LOW);
162 rt_thread_mdelay(20);
163 rt_pin_write(PWDN_PIN, PIN_LOW);
164 rt_thread_mdelay(5);
165 rt_pin_write(RST_PIN, PIN_HIGH);
166 rt_thread_mdelay(20);
167
168 return RT_EOK;
169 }
170
OV5640_Flash_Ctrl(struct rt_i2c_bus_device * bus,rt_uint8_t sw)171 void OV5640_Flash_Ctrl(struct rt_i2c_bus_device *bus, rt_uint8_t sw)
172 {
173 write_reg(bus, 0x3016, 0X02);
174 write_reg(bus, 0x301C, 0X02);
175 if (sw)
176 {
177 write_reg(bus, 0X3019, 0X02);
178 }
179 else
180 {
181 write_reg(bus, 0X3019, 0X00);
182 }
183 }
184
ov5640_config(struct rt_i2c_bus_device * bus)185 static rt_err_t ov5640_config(struct rt_i2c_bus_device *bus)
186 {
187 rt_uint32_t i = 0;
188 rt_uint8_t value = 0;
189
190 write_reg(bus, 0x3103, 0X11); /* system clock from pad, bit[1] */
191 write_reg(bus, 0X3008, 0X82); /* soft reset */
192
193 rt_thread_delay(10);
194
195 for (i = 0; i < (sizeof(RGB565_Init) / 4); i++)
196 {
197 write_reg(bus, RGB565_Init[i][0], RGB565_Init[i][1]);
198 rt_thread_delay(10);
199 read_reg(bus, RGB565_Init[i][0], 1, &value);
200
201 if (RGB565_Init[i][1] != value)
202 {
203 LOG_D("error reg value[0x%x]:0x%02x - 0x%02x", RGB565_Init[i][0], RGB565_Init[i][1], value);
204 }
205 }
206
207 OV5640_Flash_Ctrl(bus, 1); /* open camera flash*/
208 rt_thread_delay(3);
209 OV5640_Flash_Ctrl(bus, 0); /* close camera flash*/
210
211 return RT_EOK;
212 }
213
214 /* JPEG */
ov5640_jpeg_mode(struct rt_i2c_bus_device * bus)215 void ov5640_jpeg_mode(struct rt_i2c_bus_device *bus)
216 {
217 rt_uint16_t i = 0;
218 for (i = 0; i < (sizeof(OV5640_jpeg_reg_tbl) / 4); i++)
219 {
220 write_reg(bus, OV5640_jpeg_reg_tbl[i][0], OV5640_jpeg_reg_tbl[i][1]);
221 }
222 }
223
224 /* RGB565 */
ov5640_rgb565_mode(struct rt_i2c_bus_device * bus)225 void ov5640_rgb565_mode(struct rt_i2c_bus_device *bus)
226 {
227 rt_uint16_t i = 0;
228 for (i = 0; i < (sizeof(ov5640_rgb565_reg_tbl) / 4); i++)
229 {
230 write_reg(bus, ov5640_rgb565_reg_tbl[i][0], ov5640_rgb565_reg_tbl[i][1]);
231 }
232
233 write_reg(bus, 0x3821, 0x06);
234 }
235
ov5640_focus_init(struct rt_i2c_bus_device * bus)236 rt_uint8_t ov5640_focus_init(struct rt_i2c_bus_device *bus)
237 {
238 rt_uint16_t tickstart = 0 ,i = 0;
239 rt_uint16_t addr = 0x8000;
240 rt_uint8_t state = 0x8F;
241
242 write_reg(bus, 0x3000, 0x20); //reset MCU
243 for (i = 0; i < sizeof(OV5640_AF_Config); i++)
244 {
245 write_reg(bus, addr, OV5640_AF_Config[i]);
246 addr++;
247 }
248 write_reg(bus, 0x3022, 0x00);
249 write_reg(bus, 0x3023, 0x00);
250 write_reg(bus, 0x3024, 0x00);
251 write_reg(bus, 0x3025, 0x00);
252 write_reg(bus, 0x3026, 0x00);
253 write_reg(bus, 0x3027, 0x00);
254 write_reg(bus, 0x3028, 0x00);
255 write_reg(bus, 0x3029, 0x7f);
256 write_reg(bus, 0x3000, 0x00);
257 i = 0;
258
259 tickstart = rt_tick_get();
260 do
261 {
262 read_reg(bus, 0x3029, 1, &state);
263 if (rt_tick_get() - tickstart > 1000)
264 {
265 return -RT_ERROR;
266 }
267 } while (state != 0x70);
268
269 return RT_EOK;
270 }
271
ov5640_set_light(struct rt_i2c_bus_device * bus,rt_uint8_t mode)272 void ov5640_set_light(struct rt_i2c_bus_device *bus, rt_uint8_t mode)
273 {
274 rt_uint8_t i = 0;
275 write_reg(bus, 0x3212, 0x03); //start group 3
276
277 for (i = 0; i < 7; i++)
278 {
279 write_reg(bus, 0x3400 + i, OV5640_LIGHTMODE_TBL[mode][i]);
280 }
281
282 write_reg(bus, 0x3212, 0x13); //end group 3
283 write_reg(bus, 0x3212, 0xa3); //launch group 3
284 }
285
286 /* sat:0~6 */
ov5640_color_saturation(struct rt_i2c_bus_device * bus,rt_uint8_t sat)287 void ov5640_color_saturation(struct rt_i2c_bus_device *bus, rt_uint8_t sat)
288 {
289 rt_uint8_t i = 0;
290 write_reg(bus, 0x3212, 0x03); //start group 3
291 write_reg(bus, 0x5381, 0x1c);
292 write_reg(bus, 0x5382, 0x5a);
293 write_reg(bus, 0x5383, 0x06);
294 for (i = 0; i < 6; i++)
295 {
296 write_reg(bus, 0x5384 + i, OV5640_SATURATION_TBL[sat][i]);
297 }
298 write_reg(bus, 0x538b, 0x98);
299 write_reg(bus, 0x538a, 0x01);
300 write_reg(bus, 0x3212, 0x13); //end group 3
301 write_reg(bus, 0x3212, 0xa3); //launch group 3
302 }
303
304 /* bright:0~8 */
ov5640_set_brightness(struct rt_i2c_bus_device * bus,rt_uint8_t bright)305 void ov5640_set_brightness(struct rt_i2c_bus_device *bus, rt_uint8_t bright)
306 {
307 rt_uint8_t brtval;
308 if (bright < 4)
309 {
310 brtval = 4 - bright;
311 }
312 else
313 {
314 brtval = bright - 4;
315 }
316 write_reg(bus, 0x3212, 0x03); //start group 3
317 write_reg(bus, 0x5587, brtval << 4);
318 if (bright < 4)
319 {
320 write_reg(bus, 0x5588, 0x09);
321 }
322 else
323 {
324 write_reg(bus, 0x5588, 0x01);
325 }
326 write_reg(bus, 0x3212, 0x13); //end group 3
327 write_reg(bus, 0x3212, 0xa3); //launch group 3
328 }
329
330 /* contrast:0~6 */
ov5640_contrast(struct rt_i2c_bus_device * bus,rt_uint8_t contrast)331 void ov5640_contrast(struct rt_i2c_bus_device *bus, rt_uint8_t contrast)
332 {
333 rt_uint8_t reg0val = 0x00;
334 rt_uint8_t reg1val = 0x20;
335 switch (contrast)
336 {
337 case 0:
338 reg1val = reg0val = 0X14;
339 break;
340
341 case 1:
342 reg1val = reg0val = 0X18;
343 break;
344
345 case 2:
346 reg1val = reg0val = 0X1C;
347 break;
348
349 case 4:
350 reg0val = 0X10;
351 reg1val = 0X24;
352 break;
353
354 case 5:
355 reg0val = 0X18;
356 reg1val = 0X28;
357 break;
358
359 case 6:
360 reg0val = 0X1C;
361 reg1val = 0X2C;
362
363 break;
364 }
365 write_reg(bus, 0x3212, 0x03); //start group 3
366 write_reg(bus, 0x5585, reg0val);
367 write_reg(bus, 0x5586, reg1val);
368 write_reg(bus, 0x3212, 0x13); //end group 3
369 write_reg(bus, 0x3212, 0xa3); //launch group 3
370 }
371
372 /* sharp:0~33 */
ov5640_set_sharpness(struct rt_i2c_bus_device * bus,rt_uint8_t sharp)373 void ov5640_set_sharpness(struct rt_i2c_bus_device *bus, rt_uint8_t sharp)
374 {
375 if (sharp < 33)
376 {
377 write_reg(bus, 0x5308, 0x65);
378 write_reg(bus, 0x5302, sharp);
379 }
380 else
381 {
382 write_reg(bus, 0x5308, 0x25);
383 write_reg(bus, 0x5300, 0x08);
384 write_reg(bus, 0x5301, 0x30);
385 write_reg(bus, 0x5302, 0x10);
386 write_reg(bus, 0x5303, 0x00);
387 write_reg(bus, 0x5309, 0x08);
388 write_reg(bus, 0x530a, 0x30);
389 write_reg(bus, 0x530b, 0x04);
390 write_reg(bus, 0x530c, 0x06);
391 }
392 }
393
ov5640_focus_constant(struct rt_i2c_bus_device * bus)394 rt_uint8_t ov5640_focus_constant(struct rt_i2c_bus_device *bus)
395 {
396 rt_uint8_t temp = 0;
397 rt_uint16_t tickstrat = 0;
398
399 write_reg(bus, 0x3023, 0x01);
400 write_reg(bus, 0x3022, 0x08);
401 do
402 {
403 tickstrat = rt_tick_get();
404 read_reg(bus, 0x3023, 1, &temp);
405 if (rt_tick_get() - tickstrat > 1000)
406 {
407 return -RT_ERROR;
408 }
409 } while (temp != 0x00);
410
411 write_reg(bus, 0x3023, 0x01);
412 write_reg(bus, 0x3022, 0x04);
413
414 do
415 {
416 tickstrat = rt_tick_get();
417 read_reg(bus, 0x3023, 1, &temp);
418 if (rt_tick_get() - tickstrat > 1000)
419 {
420 return -RT_ERROR;
421 }
422 } while (temp != 0x00);
423
424 return 0;
425 }
426
ov5640_set_outsize(struct rt_i2c_bus_device * bus,rt_uint16_t offx,rt_uint16_t offy,rt_uint16_t width,rt_uint16_t height)427 rt_uint8_t ov5640_set_outsize(struct rt_i2c_bus_device *bus, rt_uint16_t offx, rt_uint16_t offy, rt_uint16_t width, rt_uint16_t height)
428 {
429 write_reg(bus, 0X3212, 0X03);
430
431 write_reg(bus, 0x3808, width >> 8);
432 write_reg(bus, 0x3809, width & 0xff);
433 write_reg(bus, 0x380a, height >> 8);
434 write_reg(bus, 0x380b, height & 0xff);
435
436 write_reg(bus, 0x3810, offx >> 8);
437 write_reg(bus, 0x3811, offx & 0xff);
438
439 write_reg(bus, 0x3812, offy >> 8);
440 write_reg(bus, 0x3813, offy & 0xff);
441
442 write_reg(bus, 0X3212, 0X13);
443 write_reg(bus, 0X3212, 0Xa3);
444
445 return RT_EOK;
446 }
447
rt_hw_camera_rx_callback(void)448 void rt_hw_camera_rx_callback(void)
449 {
450 rt_uint16_t i;
451 rt_int32_t *pbuf = RT_NULL;
452 pbuf = JPEG_DATA_BUF + jpeg_data_len;
453
454 if (((DMA_Stream_TypeDef *)hdma_dcmi.Instance)->CR & (1 << 19))
455 {
456 for (i = 0; i < JPEG_LINE_SIZE; i++)
457 {
458 pbuf[i] = JPEG_LINE_BUF[0][i];
459 }
460 jpeg_data_len += JPEG_LINE_SIZE;
461
462 }
463 else
464 {
465 for (i = 0; i < JPEG_LINE_SIZE; i++)
466 {
467 pbuf[i] = JPEG_LINE_BUF[1][i];
468 }
469 jpeg_data_len += JPEG_LINE_SIZE;
470 }
471 }
472
473 /* After a frame of JPEG data has been collected. */
jpeg_data_process(void)474 void jpeg_data_process(void)
475 {
476 rt_uint16_t i, rlen;
477 int *pbuf = RT_NULL;
478
479 if (!jpeg_data_ok)
480 {
481 __HAL_DMA_DISABLE(&hdma_dcmi);
482 rlen = JPEG_LINE_SIZE - __HAL_DMA_GET_COUNTER(&hdma_dcmi);
483 pbuf = JPEG_DATA_BUF + jpeg_data_len;
484
485 if (((DMA_Stream_TypeDef *)hdma_dcmi.Instance)->CR & (1 << 19))
486 {
487 for (i = 0; i < rlen; i++)
488 {
489 pbuf[i] = JPEG_LINE_BUF[1][i];
490 }
491 }
492 else
493 {
494 for (i = 0; i < rlen; i++)
495 {
496 pbuf[i] = JPEG_LINE_BUF[0][i];
497 }
498 }
499 jpeg_data_len += rlen;
500 jpeg_data_ok = 1;
501 }
502
503 if (jpeg_data_ok == 2)
504 {
505 __HAL_DMA_SET_COUNTER(&hdma_dcmi, JPEG_LINE_SIZE);
506 __HAL_DMA_ENABLE(&hdma_dcmi);
507
508 jpeg_data_ok = 0;
509 jpeg_data_len = 0;
510 }
511 }
512
ov5640_set_xclk_frequency(uint32_t frequency)513 int ov5640_set_xclk_frequency(uint32_t frequency)
514 {
515 extern void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
516 int tclk = HAL_RCC_GetPCLK2Freq() * 2;
517 int period = (tclk / frequency) - 1;
518 int pulse = period / 2;
519
520 TIM_HandleTypeDef TIMHandle = {.Instance = TIM1};
521
522 if (TIMHandle.Init.Period && (TIMHandle.Init.Period != period)) {
523 __HAL_TIM_SET_AUTORELOAD(&TIMHandle, period);
524 __HAL_TIM_SET_COMPARE(&TIMHandle, TIM_CHANNEL_1, pulse);
525 return 0;
526 }
527
528 TIMHandle.Init.Period = period;
529 TIMHandle.Init.Prescaler = 0;
530 TIMHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
531 TIMHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
532 TIMHandle.Init.RepetitionCounter = 0;
533 TIMHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
534
535 TIM_OC_InitTypeDef TIMOCHandle;
536 TIMOCHandle.Pulse = pulse;
537 TIMOCHandle.OCMode = TIM_OCMODE_PWM1;
538 TIMOCHandle.OCPolarity = TIM_OCPOLARITY_HIGH;
539 TIMOCHandle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
540 TIMOCHandle.OCFastMode = TIM_OCFAST_DISABLE;
541 TIMOCHandle.OCIdleState = TIM_OCIDLESTATE_RESET;
542 TIMOCHandle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
543
544 HAL_TIM_MspPostInit(&TIMHandle);
545
546 if ((HAL_TIM_PWM_Init(&TIMHandle) != HAL_OK)
547 || (HAL_TIM_PWM_ConfigChannel(&TIMHandle, &TIMOCHandle, TIM_CHANNEL_1) != HAL_OK)
548 || (HAL_TIM_PWM_Start(&TIMHandle, TIM_CHANNEL_1) != HAL_OK))
549 {
550 rt_kprintf("config fail!\n");
551 return -1;
552 }
553
554 return 0;
555 }
556
rt_hw_ov5640_init(void)557 int rt_hw_ov5640_init(void)
558 {
559 ov5640_set_xclk_frequency(24000000);
560 extern void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint16_t len);
561
562 static rt_uint16_t id = 0;
563 rt_device_t dcmi_dev = RT_NULL;
564
565 i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
566 if (i2c_bus == RT_NULL)
567 {
568 LOG_E("can't find %c deivce", I2C_NAME);
569 return -RT_ERROR;
570 }
571
572 ov5640_hard_reset();
573 ov5640_read_id(i2c_bus, &id);
574 ov5640_config(i2c_bus);
575 ov5640_rgb565_mode(i2c_bus); /* rgb565 mode */
576 ov5640_focus_init(i2c_bus);
577 ov5640_jpeg_mode(i2c_bus); /* jpeg mode */
578 ov5640_set_light(i2c_bus, 0); /* auto mode */
579 ov5640_color_saturation(i2c_bus, 3);
580 ov5640_set_brightness(i2c_bus, 4); /* brigetness 0 */
581 ov5640_contrast(i2c_bus, 3);
582 ov5640_set_sharpness(i2c_bus, 33);
583 ov5640_focus_constant(i2c_bus);
584
585 /* dcmi init */
586 dcmi_dev = rt_device_find("dcmi");
587 if (dcmi_dev == RT_NULL)
588 {
589 LOG_E("can't find dcmi device!");
590 return -RT_ERROR;
591 }
592 rt_device_open(dcmi_dev, RT_DEVICE_FLAG_RDWR);
593
594 rt_hw_dcmi_dma_config((rt_uint32_t)&JPEG_LINE_BUF[0], (rt_uint32_t)&JPEG_LINE_BUF[1], JPEG_LINE_SIZE);
595 ov5640_set_outsize(i2c_bus, 4, 0, jpeg_picture_size[1][0], jpeg_picture_size[1][1]);
596
597 return RT_EOK;
598 }
599 INIT_APP_EXPORT(rt_hw_ov5640_init);
600
camera_sample(int argc,char ** argv)601 int camera_sample(int argc, char **argv)
602 {
603
604 int fd = -1;
605 rt_uint32_t i, jpg_start, jpg_len;
606 rt_uint16_t tickstart = 0;
607 rt_uint8_t jpg_head = 0;
608 rt_uint8_t *p = RT_NULL;
609
610 if (argc != 2)
611 {
612 rt_kprintf("Usage:\n");
613 rt_kprintf("camera_sample file.jpg\n");
614 return -1;
615 }
616
617 /* start dcmi capture */
618 __HAL_DMA_ENABLE(&hdma_dcmi);
619 dcmi.Instance->CR |= DCMI_CR_CAPTURE;
620
621 tickstart = rt_tick_get();
622 while (1)
623 {
624 if (rt_tick_get() - tickstart > 1000)
625 {
626 LOG_E("picture capture overtime!");
627 break;
628 }
629
630 if (jpeg_data_ok == 1)
631 {
632 dcmi.Instance->CR &= ~(DCMI_CR_CAPTURE);
633 tickstart = rt_tick_get();
634 while(dcmi.Instance->CR & 0x01)
635 {
636 if (rt_tick_get() - tickstart > 0x1000)
637 {
638 rt_kprintf("dcmi close failed!\n");
639 jpeg_data_ok = 2;
640 break;
641 }
642 }
643 __HAL_DMA_DISABLE(&hdma_dcmi);
644
645 p = (rt_uint8_t *)JPEG_DATA_BUF;
646 jpg_len = 0;
647 jpg_head = 0;
648 for (i = 0; i < jpeg_data_len * 4; i++)
649 {
650 /* jpg head */
651 if ((p[i] == 0xFF) && (p[i + 1] == 0xD8))
652 {
653 jpg_start = i;
654 jpg_head = 1;
655 }
656 /* jpg end */
657 if ((p[i] == 0xFF) && (p[i + 1] == 0xD9) && jpg_head)
658 {
659 jpg_len = i - jpg_start + 2; /* a picture len */
660 break;
661 }
662 }
663
664 if (jpg_len)
665 {
666 p += jpg_start;
667
668 fd = open(argv[1], O_WRONLY | O_CREAT);
669 if (fd < 0)
670 {
671 rt_kprintf("open file for recording failed!\n");
672 return -RT_ERROR;
673 }
674 else
675 {
676 write(fd, p, jpg_len);
677 close(fd);
678 rt_kprintf("picture capture complate!\n");
679 memset(JPEG_DATA_BUF,0,jpeg_data_len);
680 jpeg_data_len = 0;
681 jpeg_data_ok = 0;
682 break;
683 }
684 }
685
686 jpeg_data_ok = 2;
687 }
688 }
689
690 return RT_EOK;
691 }
692 MSH_CMD_EXPORT(camera_sample, record picture to a jpg file);
693
694 #endif
695