drv_ov5640.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* Copyright 2018 Canaan Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. #include "drv_ov5640.h"
  18. #include "ov5640cfg.h"
  19. #include "ov5640af.h"
  20. #include "dvp.h"
  21. static void hal_delay(uint32_t delay)
  22. {
  23. usleep(delay * 1000);
  24. }
  25. static void ov5640_wr_reg(uint16_t reg,uint8_t data)
  26. {
  27. dvp_sccb_send_data(OV5640_ADDR, reg, data);
  28. }
  29. static uint8_t ov5640_rd_reg(uint16_t reg)
  30. {
  31. return dvp_sccb_receive_data(OV5640_ADDR, reg);
  32. }
  33. uint8_t ov5640_init(void)
  34. {
  35. uint16_t i = 0;
  36. uint16_t reg = 0;
  37. reg = ov5640_rd_reg(OV5640_CHIPIDH);
  38. reg <<= 8;
  39. reg |= ov5640_rd_reg(OV5640_CHIPIDL);
  40. if(reg != OV5640_ID)
  41. {
  42. printf("ID: %d \r\n", reg);
  43. return 1;
  44. }
  45. ov5640_wr_reg(0x3103,0X11); /*system clock from pad, bit[1]*/
  46. ov5640_wr_reg(0X3008,0X82);
  47. hal_delay(10);
  48. for(i = 0; i<sizeof(ov5640_init_reg_tbl) / 4; i++)
  49. {
  50. ov5640_wr_reg(ov5640_init_reg_tbl[i][0], ov5640_init_reg_tbl[i][1]);
  51. }
  52. hal_delay(50);
  53. /* Test for flash light*/
  54. ov5640_flash_lamp(1);
  55. hal_delay(50);
  56. ov5640_flash_lamp(0);
  57. return 0x00;
  58. }
  59. void ov5640_flash_lamp(uint8_t sw)
  60. {
  61. ov5640_wr_reg(0x3016, 0X02);
  62. ov5640_wr_reg(0x301C, 0X02);
  63. if(sw)
  64. ov5640_wr_reg(0X3019, 0X02);
  65. else
  66. ov5640_wr_reg(0X3019, 0X00);
  67. }
  68. const static uint8_t OV5640_EXPOSURE_TBL[7][6]=
  69. {
  70. 0x10,0x08,0x10,0x08,0x20,0x10,//-3
  71. 0x20,0x18,0x41,0x20,0x18,0x10,//-2
  72. 0x30,0x28,0x61,0x30,0x28,0x10,//-1
  73. 0x38,0x30,0x61,0x38,0x30,0x10,//0
  74. 0x40,0x38,0x71,0x40,0x38,0x10,//+1
  75. 0x50,0x48,0x90,0x50,0x48,0x20,//+2
  76. 0x60,0x58,0xa0,0x60,0x58,0x20,//+3
  77. };
  78. //exposure: 0 - 6,
  79. void OV5640_Exposure(uint8_t exposure)
  80. {
  81. ov5640_wr_reg(0x3212,0x03); //start group 3
  82. ov5640_wr_reg(0x3a0f,OV5640_EXPOSURE_TBL[exposure][0]);
  83. ov5640_wr_reg(0x3a10,OV5640_EXPOSURE_TBL[exposure][1]);
  84. ov5640_wr_reg(0x3a1b,OV5640_EXPOSURE_TBL[exposure][2]);
  85. ov5640_wr_reg(0x3a1e,OV5640_EXPOSURE_TBL[exposure][3]);
  86. ov5640_wr_reg(0x3a11,OV5640_EXPOSURE_TBL[exposure][4]);
  87. ov5640_wr_reg(0x3a1f,OV5640_EXPOSURE_TBL[exposure][5]);
  88. ov5640_wr_reg(0x3212,0x13); //end group 3
  89. ov5640_wr_reg(0x3212,0xa3); //launch group 3
  90. }
  91. const static uint8_t OV5640_LIGHTMODE_TBL[5][7]=
  92. {
  93. 0x04,0X00,0X04,0X00,0X04,0X00,0X00,//Auto
  94. 0x06,0X1C,0X04,0X00,0X04,0XF3,0X01,//Sunny
  95. 0x05,0X48,0X04,0X00,0X07,0XCF,0X01,//Office
  96. 0x06,0X48,0X04,0X00,0X04,0XD3,0X01,//Cloudy
  97. 0x04,0X10,0X04,0X00,0X08,0X40,0X01,//Home
  98. };
  99. // light mode:
  100. // 0: auto
  101. // 1: sunny
  102. // 2: office
  103. // 3: cloudy
  104. // 4: home
  105. void OV5640_Light_Mode(uint8_t mode)
  106. {
  107. uint8_t i;
  108. ov5640_wr_reg(0x3212,0x03); //start group 3
  109. for(i=0;i<7;i++)ov5640_wr_reg(0x3400+i,OV5640_LIGHTMODE_TBL[mode][i]);
  110. ov5640_wr_reg(0x3212,0x13); //end group 3
  111. ov5640_wr_reg(0x3212,0xa3); //launch group 3
  112. }
  113. const static uint8_t OV5640_SATURATION_TBL[7][6]=
  114. {
  115. 0X0C,0x30,0X3D,0X3E,0X3D,0X01,//-3
  116. 0X10,0x3D,0X4D,0X4E,0X4D,0X01,//-2
  117. 0X15,0x52,0X66,0X68,0X66,0X02,//-1
  118. 0X1A,0x66,0X80,0X82,0X80,0X02,//+0
  119. 0X1F,0x7A,0X9A,0X9C,0X9A,0X02,//+1
  120. 0X24,0x8F,0XB3,0XB6,0XB3,0X03,//+2
  121. 0X2B,0xAB,0XD6,0XDA,0XD6,0X04,//+3
  122. };
  123. // Color Saturation:
  124. // sat: 0 - 6
  125. void OV5640_Color_Saturation(uint8_t sat)
  126. {
  127. uint8_t i;
  128. ov5640_wr_reg(0x3212,0x03); //start group 3
  129. ov5640_wr_reg(0x5381,0x1c);
  130. ov5640_wr_reg(0x5382,0x5a);
  131. ov5640_wr_reg(0x5383,0x06);
  132. for(i=0;i<6;i++) ov5640_wr_reg(0x5384+i,OV5640_SATURATION_TBL[sat][i]);
  133. ov5640_wr_reg(0x538b, 0x98);
  134. ov5640_wr_reg(0x538a, 0x01);
  135. ov5640_wr_reg(0x3212, 0x13); //end group 3
  136. ov5640_wr_reg(0x3212, 0xa3); //launch group 3
  137. }
  138. //Brightness
  139. // bright: 0 - 8
  140. void OV5640_Brightness(uint8_t bright)
  141. {
  142. uint8_t brtval;
  143. if(bright<4)brtval=4-bright;
  144. else brtval=bright-4;
  145. ov5640_wr_reg(0x3212,0x03); //start group 3
  146. ov5640_wr_reg(0x5587,brtval<<4);
  147. if(bright<4)ov5640_wr_reg(0x5588,0x09);
  148. else ov5640_wr_reg(0x5588,0x01);
  149. ov5640_wr_reg(0x3212,0x13); //end group 3
  150. ov5640_wr_reg(0x3212,0xa3); //launch group 3
  151. }
  152. //Contrast:
  153. // contrast: 0 - 6
  154. void OV5640_Contrast(uint8_t contrast)
  155. {
  156. uint8_t reg0val=0X00;
  157. uint8_t reg1val=0X20;
  158. switch(contrast)
  159. {
  160. case 0://-3
  161. reg1val=reg0val=0X14;
  162. break;
  163. case 1://-2
  164. reg1val=reg0val=0X18;
  165. break;
  166. case 2://-1
  167. reg1val=reg0val=0X1C;
  168. break;
  169. case 4://1
  170. reg0val=0X10;
  171. reg1val=0X24;
  172. break;
  173. case 5://2
  174. reg0val=0X18;
  175. reg1val=0X28;
  176. break;
  177. case 6://3
  178. reg0val=0X1C;
  179. reg1val=0X2C;
  180. break;
  181. }
  182. ov5640_wr_reg(0x3212,0x03); //start group 3
  183. ov5640_wr_reg(0x5585,reg0val);
  184. ov5640_wr_reg(0x5586,reg1val);
  185. ov5640_wr_reg(0x3212,0x13); //end group 3
  186. ov5640_wr_reg(0x3212,0xa3); //launch group 3
  187. }
  188. // Sharpness:
  189. // sharp: 0 - 33 (0: close , 33: auto , other: Sharpness)
  190. void OV5640_Sharpness(uint8_t sharp)
  191. {
  192. if(sharp<33)
  193. {
  194. ov5640_wr_reg(0x5308,0x65);
  195. ov5640_wr_reg(0x5302,sharp);
  196. }else // auto
  197. {
  198. ov5640_wr_reg(0x5308,0x25);
  199. ov5640_wr_reg(0x5300,0x08);
  200. ov5640_wr_reg(0x5301,0x30);
  201. ov5640_wr_reg(0x5302,0x10);
  202. ov5640_wr_reg(0x5303,0x00);
  203. ov5640_wr_reg(0x5309,0x08);
  204. ov5640_wr_reg(0x530a,0x30);
  205. ov5640_wr_reg(0x530b,0x04);
  206. ov5640_wr_reg(0x530c,0x06);
  207. }
  208. }
  209. const static uint8_t OV5640_EFFECTS_TBL[7][3]=
  210. {
  211. 0X06,0x40,0X10, // normal
  212. 0X1E,0xA0,0X40,
  213. 0X1E,0x80,0XC0,
  214. 0X1E,0x80,0X80,
  215. 0X1E,0x40,0XA0,
  216. 0X40,0x40,0X10,
  217. 0X1E,0x60,0X60,
  218. };
  219. void OV5640_Special_Effects(uint8_t eft)
  220. {
  221. ov5640_wr_reg(0x3212,0x03); //start group 3
  222. ov5640_wr_reg(0x5580,OV5640_EFFECTS_TBL[eft][0]);
  223. ov5640_wr_reg(0x5583,OV5640_EFFECTS_TBL[eft][1]);// sat U
  224. ov5640_wr_reg(0x5584,OV5640_EFFECTS_TBL[eft][2]);// sat V
  225. ov5640_wr_reg(0x5003,0x08);
  226. ov5640_wr_reg(0x3212,0x13); //end group 3
  227. ov5640_wr_reg(0x3212,0xa3); //launch group 3
  228. }
  229. uint8_t OV5640_Focus_Init(void)
  230. {
  231. uint16_t i;
  232. uint16_t addr=0x8000;
  233. uint8_t state=0x8F;
  234. ov5640_wr_reg(0x3000, 0x20); //reset
  235. for(i=0;i<sizeof(OV5640_AF_Config);i++)
  236. {
  237. ov5640_wr_reg(addr,OV5640_AF_Config[i]);
  238. addr++;
  239. }
  240. ov5640_wr_reg(0x3022,0x00);
  241. ov5640_wr_reg(0x3023,0x00);
  242. ov5640_wr_reg(0x3024,0x00);
  243. ov5640_wr_reg(0x3025,0x00);
  244. ov5640_wr_reg(0x3026,0x00);
  245. ov5640_wr_reg(0x3027,0x00);
  246. ov5640_wr_reg(0x3028,0x00);
  247. ov5640_wr_reg(0x3029,0x7f);
  248. ov5640_wr_reg(0x3000,0x00);
  249. i=0;
  250. do
  251. {
  252. state=ov5640_rd_reg(0x3029);
  253. hal_delay(5);
  254. i++;
  255. if(i>1000)return 1;
  256. }while(state!=0x70);
  257. return 0;
  258. }
  259. uint8_t OV5640_Auto_Focus(void)
  260. {
  261. uint8_t temp=0;
  262. uint16_t retry=0;
  263. ov5640_wr_reg(0x3023,0x01);
  264. ov5640_wr_reg(0x3022,0x08);
  265. do
  266. {
  267. temp=ov5640_rd_reg(0x3023);
  268. retry++;
  269. if(retry>1000)return 2;
  270. hal_delay(5);
  271. } while(temp!=0x00);
  272. ov5640_wr_reg(0x3023,0x01);
  273. ov5640_wr_reg(0x3022,0x04);
  274. retry=0;
  275. do
  276. {
  277. temp=ov5640_rd_reg(0x3023);
  278. retry++;
  279. if(retry>1000)return 2;
  280. hal_delay(5);
  281. }while(temp!=0x00);
  282. return 0;
  283. }