drv_ov2640.c 17 KB

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