Test_OV9650.c
上传用户:jankzhpno
上传日期:2022-08-03
资源大小:4763k
文件大小:11k
源码类别:

Windows CE

开发平台:

Visual C++

  1. #include "def.h"
  2. #include "2440addr.h"
  3. #include "2440lib.h"
  4. #include "Test_OV9650.h"
  5. /************************************************/
  6. //some macros and inline function to support porting
  7. //from linux driver,
  8. #define CLKCON rCLKCON
  9. #define CLKCON_CAMIF (1<<19)
  10. #define UPLLCON rUPLLCON
  11. #define CLKDIVN rCLKDIVN
  12. #define DIVN_UPLL_EN (1<<3)
  13. #define CAMDIVN rCAMDIVN
  14. #define CAMCLK_SET_DIV (1<<4)
  15. #define CAM_CTRL rCIGCTRL //??
  16. #define GPIO_E14 14
  17. #define GPIO_E15 15
  18. #define GPIO_PULLUP_EN (0<<30)
  19. #define GPIO_PULLUP_DIS (1<<30)
  20. #define GPIO_MODE_IN (0<<31)
  21. #define GPIO_MODE_OUT (1UL<<31)
  22. #define read_gpio_bit(x) ((rGPEDAT & (1<<(x))) ? 1 : 0)
  23. #define write_gpio_bit_set(x) (rGPEDAT |= 1<<(x))
  24. #define write_gpio_bit_clear(x) (rGPEDAT &= ~(1<<(x)))
  25. //only support GPE, in and out
  26. static __inline void set_gpio_ctrl(unsigned int gpio)
  27. {
  28. rGPECON &= ~(3<<((gpio&0xf)*2));
  29. if(gpio&GPIO_MODE_OUT)
  30. rGPECON |= 1<<((gpio&0xf)*2);
  31. if(gpio&GPIO_PULLUP_DIS)
  32. rGPEUP |= 1<<(gpio&0xf);
  33. else
  34. rGPEUP &= ~(1<<(gpio&0xf));
  35. }
  36. #define ENODEV 2
  37. #define udelay(x) Delay(x/50)
  38. #define mdelay(x) Delay((x)*8)
  39. #define printk Uart_Printf
  40. static U8 sccb_id = 0x60; //OV9650
  41. //---
  42. static void CamModuleReset(void)
  43. {
  44. //bit 30 is external reset
  45. rCIGCTRL |= (1<<30); //external camera reset high
  46. Delay(30);
  47. rCIGCTRL &= ~(1<<30); //external camera reset low
  48. Delay(30);
  49. // rCIGCTRL |= (1<<19); //external camera reset high
  50. // Delay(30);
  51. // rCIGCTRL &= ~(1<<19); //external camera reset low
  52. // Delay(30);
  53. }
  54. //---
  55. typedef unsigned long dma_addr_t;
  56. #define panic prink
  57. /*********** start of OV7620 ********************/
  58. /* refer to 25p of OV7620 datasheet */
  59. #  define OV7620_SCCB_ID sccb_id//0x42  /* CS[2:0] = 000 */ //use variable
  60. #  define OV7620_MAX_CLK 24000000 // 24MHz
  61. #  define OV7620_PRODUCT_ID 0x7FA2
  62. #  define OV7620_SCCB_DELAY    100 
  63. #  define OV7620_SCCB_DELAY2   100
  64. #  define SIO_C          (GPIO_E14)
  65. #  define SIO_D          (GPIO_E15)
  66. #  define MAKE_HIGH(_x)  write_gpio_bit_set(_x)
  67. #  define MAKE_LOW(_x)   write_gpio_bit_clear(_x)
  68. #  define BIT_READ(_x)   read_gpio_bit(_x)
  69. #  define CFG_READ(_x)   set_gpio_ctrl(_x | GPIO_PULLUP_DIS | GPIO_MODE_IN)
  70. #  define CFG_WRITE(_x)  set_gpio_ctrl(_x | GPIO_PULLUP_DIS | GPIO_MODE_OUT)
  71. #if OV7620_SCCB_DELAY > 0
  72. #  define WAIT_CYL udelay(OV7620_SCCB_DELAY)
  73. #else
  74. #  define WAIT_CYL (void)(0)
  75. #endif
  76. #if OV7620_SCCB_DELAY2 > 0
  77. #  define WAIT_STAB udelay(OV7620_SCCB_DELAY2)
  78. #else
  79. #  define WAIT_STAB (void)(0)
  80. #endif
  81. static unsigned int get_camera_clk(void)
  82. {
  83. return 24000000;//OV7620_MAX_CLK;
  84. }
  85. /* 2-wire SCCB */
  86. void __inline ov7620_sccb_start(void)
  87. {
  88. MAKE_HIGH(SIO_C);
  89. MAKE_HIGH(SIO_D);
  90. WAIT_STAB;
  91. MAKE_LOW(SIO_D);
  92. WAIT_STAB;
  93. MAKE_LOW(SIO_C);
  94. WAIT_STAB;
  95. }
  96. /* 2-wire SCCB */
  97. void __inline ov7620_sccb_end(void)
  98. {
  99. MAKE_LOW(SIO_D);
  100. WAIT_STAB;
  101. MAKE_HIGH(SIO_C);
  102. WAIT_STAB;
  103. MAKE_HIGH(SIO_D);
  104. WAIT_STAB;
  105. }
  106. void __inline ov7620_sccb_write_bit(unsigned char bit)
  107. {
  108. if (bit)
  109. MAKE_HIGH(SIO_D);
  110. else
  111. MAKE_LOW(SIO_D);
  112. WAIT_STAB;
  113. MAKE_HIGH(SIO_C);
  114. WAIT_CYL;
  115. MAKE_LOW(SIO_C);
  116. WAIT_STAB;
  117. }
  118. int __inline ov7620_sccb_read_bit(void)
  119. {
  120. int tmp = 0;
  121. MAKE_HIGH(SIO_C);
  122. WAIT_CYL;
  123. tmp = BIT_READ(SIO_D);
  124. MAKE_LOW(SIO_C);
  125. WAIT_STAB;
  126. return tmp;
  127. }
  128. void __inline ov7620_sccb_writechar(unsigned char data)
  129. {
  130. int i = 0;
  131. /* data */
  132. for (i = 0; i < 8; i++ ) {
  133. ov7620_sccb_write_bit(data & 0x80);
  134. data <<= 1;
  135. }
  136. /* 9th bit - Don't care */
  137. ov7620_sccb_write_bit(1);
  138. }
  139. void __inline ov7620_sccb_readchar(unsigned char *val)
  140. {
  141. int i;
  142. int tmp = 0;
  143. CFG_READ(SIO_D);
  144. for (i = 7; i >= 0; i--)
  145. tmp |= ov7620_sccb_read_bit() << i;
  146. CFG_WRITE(SIO_D);
  147. /* 9th bit - N.A. */
  148. ov7620_sccb_write_bit(1);
  149. *val = tmp & 0xff;
  150. }
  151. /* 3-phase write */
  152. static void ov7620_sccb_sendbyte(unsigned char subaddr, unsigned char data)
  153. {
  154. // down(&dev.bus_lock);
  155. ov7620_sccb_start();
  156. ov7620_sccb_writechar(OV7620_SCCB_ID);
  157. ov7620_sccb_writechar(subaddr);
  158. ov7620_sccb_writechar(data);
  159. ov7620_sccb_end();
  160. mdelay(7);
  161. // up(&dev.bus_lock);
  162. }
  163. /* 2-phase read */
  164. static unsigned char ov7620_sccb_receivebyte(unsigned char subaddr)
  165. {
  166. unsigned char value;
  167. // down(&dev.bus_lock);
  168. /* 2-phase write */
  169. ov7620_sccb_start();
  170. ov7620_sccb_writechar(OV7620_SCCB_ID);
  171. ov7620_sccb_writechar(subaddr);
  172. ov7620_sccb_end();
  173. /* 2-phase read */
  174. ov7620_sccb_start();
  175. ov7620_sccb_writechar(OV7620_SCCB_ID | 0x01);
  176. ov7620_sccb_readchar(&value);
  177. ov7620_sccb_end();
  178. mdelay(7);
  179. // up(&dev.bus_lock);
  180. return value;
  181. }
  182. void __inline ov7620_init(void)
  183. {
  184. CFG_WRITE(SIO_C);
  185. CFG_WRITE(SIO_D);
  186. mdelay(10);
  187. }
  188. void __inline ov7620_deinit(void)
  189. {
  190. CFG_READ(SIO_C);
  191. CFG_READ(SIO_D);
  192. }
  193. void __inline ov7620_config(void)
  194. {
  195. int i;
  196. /* for (i = 0; i < OV7620_REGS; i++) {
  197. if (ov7620_reg[i].subaddr == CHIP_DELAY)
  198. mdelay(ov7620_reg[i].value);
  199. else
  200. ov7620_sccb_sendbyte(ov7620_reg[i].subaddr & 0xff
  201. , ov7620_reg[i].value & 0xff);
  202. }*/
  203. for (i = 0; i < OV9650_REGS; i++) {
  204. if (ov9650_reg[i].subaddr == CHIP_DELAY)
  205. Delay(ov9650_reg[i].value);
  206. //mdelay(ov9650_reg[i].value);
  207. else
  208. ov7620_sccb_sendbyte(ov9650_reg[i].subaddr & 0xff
  209. , ov9650_reg[i].value & 0xff);
  210. }
  211. }
  212. int __inline check_ov7620(void)
  213. {
  214. int ret = 0;
  215. int ov7620_mid = 0;
  216. int try_count =0; //2 times
  217. try_again:
  218. //printk("OV9650_SCCB_ID is %dn", OV7620_SCCB_ID);
  219. ov7620_mid = (ov7620_sccb_receivebyte(0x1c) << 8);
  220. ov7620_mid |= ov7620_sccb_receivebyte(0x1d);
  221. // ov7620_sccb_sendbyte(0xec, 0);
  222. // ov7620_mid = ov7620_sccb_receivebyte(0xb0);
  223. // printk("read ID is 0x%xn", ov7620_mid);
  224. if (ov7620_mid != OV7620_PRODUCT_ID) {
  225. if (!try_count++) goto try_again;
  226. // 
  227. //OV7620_SCCB_ID++;
  228. //if(OV7620_SCCB_ID) goto try_again;
  229. printk("Invalid manufacture ID (0x%04X). there is no OV7620(0x%04X)n",
  230. ov7620_mid, OV7620_PRODUCT_ID);
  231. ret = -ENODEV;
  232. } else {
  233. //printk("OV7620(0x%04X) detected.n", ov7620_mid);
  234. }
  235. //for ov9650
  236. ov7620_mid = (ov7620_sccb_receivebyte(0x0a) << 8);
  237. ov7620_mid |= ov7620_sccb_receivebyte(0x0b);
  238. //printk("Product ID is 0x%04xn", ov7620_mid);
  239. //---
  240. return ret;
  241. }
  242. /********* end of OV7620 ********************/
  243. /********** start of S/W YUV2RGB ************/
  244. #define XLATTABSIZE      256
  245. #define MulDiv(x, y, z) ((long)((int) x * (int) y) / (int) z)
  246. //#define CLIP(x) min_t(int, 255, max_t(int, 0, (x)))
  247. #define CLIP(x) {if(x<0) x=0;if(x>255) x=255;}
  248. #define RED_REGION      0xf800
  249. #define GREEN_REGION    0x07e0
  250. #define BLUE_REGION     0x001f
  251. int XlatY[XLATTABSIZE] = { 0 };
  252. int XlatV_B[XLATTABSIZE] = { 0 };
  253. int XlatV_G[XLATTABSIZE] = { 0 };
  254. int XlatU_G[XLATTABSIZE] = { 0 };
  255. int XlatU_R[XLATTABSIZE] = { 0 };
  256. #define ORIG_XLAT 1
  257. void init_yuvtable (void)
  258. {
  259. int i, j;
  260. for (i = 0; i < XLATTABSIZE; i++) {
  261. #if ORIG_XLAT
  262. j = min(253, max(16, i));
  263. #else
  264. j = (255 * i + 110) / 220; // scale up
  265. j = min(255, max(j, 16));
  266. #endif
  267. // orig: XlatY[i] = (int ) j;
  268. XlatY[i] = j-16;
  269. }
  270. for (i = 0; i < XLATTABSIZE; i++) {
  271. #if ORIG_XLAT
  272. j = min(240, max(16, i));
  273. j -= 128;
  274. #else
  275. j = i - 128; // make signed
  276. if (j < 0)
  277. j++; // noise reduction
  278. j = (127 * j + 56) / 112; // scale up
  279. j = min(127, max(-128, j));
  280. #endif
  281. XlatV_B[i] = MulDiv (j, 1000, 564); /* j*219/126 */
  282. XlatV_G[i] = MulDiv (j, 1100, 3328);
  283. XlatU_G[i] = MulDiv (j, 3100, 4207);
  284. XlatU_R[i] = MulDiv (j, 1000, 713);
  285. }
  286. }
  287. #define MORE_QUALITY 1
  288. void __inline yuv_convert_rgb16(unsigned char *rawY, unsigned char *rawU,
  289.    unsigned char *rawV, unsigned char *rgb, int size)
  290. {
  291. unsigned short  buf1, buf3;
  292. int   red;
  293. int   blue;
  294. int   green;
  295. unsigned long   cnt;
  296. int    Y, U, V;
  297. unsigned short  data;
  298. unsigned short  data2;
  299. for ( cnt = 0 ; cnt < size; cnt +=2){
  300. buf1 = *(rawY+cnt) & 0xff;  // Y data
  301. buf3 = *(rawY+cnt+1) & 0xff;  // Y data
  302. U = *(rawV+cnt/2) & 0xff;
  303. V = *(rawU+cnt/2) & 0xff;
  304. #if MORE_QUALITY
  305. Y = buf1;
  306. #else
  307. Y = ((buf1+buf3)/2);
  308. #endif
  309. red = XlatY[Y] + XlatU_R[U];
  310. CLIP(red);
  311. green = XlatY[Y] - XlatV_G[V] - XlatU_G[U];
  312. CLIP(green);
  313. blue = XlatY[Y] + XlatV_B[V];
  314. CLIP(blue);
  315. data = ((red << 8) & RED_REGION)
  316. | ((green << 3) & GREEN_REGION)
  317. | (blue >> 3);
  318. #if MORE_QUALITY
  319. Y = buf3;
  320. red = XlatY[Y] + XlatU_R[U];
  321. CLIP(red);
  322. green = XlatY[Y] - XlatV_G[V] - XlatU_G[U];
  323. CLIP(green);
  324. blue = XlatY[Y] + XlatV_B[V];
  325. CLIP(blue);
  326. data2 = ((red << 8) & RED_REGION)
  327. | ((green << 3) & GREEN_REGION)
  328. | (blue >> 3);
  329. #else
  330. data2 = data;
  331. #endif
  332. *(unsigned short *)(rgb + 2 * cnt) = data;
  333. *(unsigned short *)(rgb + 2 * (cnt + 1))= data2;
  334. }
  335. }
  336. /********** end of S/W YUV2RGB ******************/
  337. static void s3c2440_cam_gpio_init(void)
  338. {
  339. //--- changed
  340. rGPJCON = 0x2aaaaaa;
  341. rGPJDAT = 0;
  342.     rGPJUP  = 0; //pull-up enable
  343. }
  344. /* 
  345.  * $> SW.LEE
  346.  * 
  347.  * OV7620_CLK is 12Mhz or 24Mhz
  348.  *
  349.  * CAMCLK = OV7620_CLK;
  350.  * CAMCLK_DIV =  UPLL / ( CAMCLK * 2)  - 1 ; 
  351.  */ 
  352. void __inline s3c2440_camif_init(void)
  353. {
  354. unsigned int upll, uclk, camclk,camclk_div;
  355. camclk = get_camera_clk();
  356. CLKCON |= CLKCON_CAMIF;
  357. /* Supposed that you must set UPLL at first */
  358. /* UPLLCON = FInsrt(0x38, fPLL_MDIV) | FInsrt(0x02, fPLL_PDIV)
  359.                                 | FInsrt(0x02, fPLL_SDIV);
  360. upll = s3c2440_get_bus_clk(GET_UPLL);
  361. */
  362. //--- change above to this
  363. //UPLLCON = (0x38<<12)|(2<<4)|(1); //is this 96M ???
  364. ChangeUPllValue(56, 2, 1); //0x38==56
  365. CLKDIVN |= DIVN_UPLL_EN; //UCLK=UPLL/2
  366. upll = 96000000;
  367. //---
  368. uclk = (CLKDIVN & DIVN_UPLL_EN) ? upll/2 : upll;
  369. printk("CAMERA : UPLL %08d  UCLK %08d CAMCLK %08d n",upll, uclk, camclk);
  370. camclk_div = upll /( camclk * 2) -1 ;
  371. CAMDIVN = CAMCLK_SET_DIV | (camclk_div & 0xf ) ;
  372. }
  373. void __inline s3c2440_camif_deinit(void)
  374. {
  375. CLKCON &= ~CLKCON_CAMIF;
  376. CAM_CTRL = 0;
  377. mdelay(5);
  378. }
  379. /***************************************************/
  380. int Test_OV9650(void)
  381. {
  382. int ret;
  383. init_yuvtable();
  384. s3c2440_cam_gpio_init();
  385. s3c2440_camif_init();
  386. // while(1)
  387. CamModuleReset();
  388. ov7620_init();
  389. /* rGPECON &= ~(0xfUL<<28);
  390. rGPECON |= 5<<28;
  391. rGPEUP  &= ~(3<<14);
  392. while(1) {
  393. rGPEDAT &= ~(3<<14);
  394. rGPEDAT |= 3<<14;
  395. }
  396. */
  397. //GPE14,15 are open-drain output without inner pull-up,
  398. //so must install external pull up registers!!!
  399. /* while(!Uart_GetKey()) {
  400. MAKE_HIGH(SIO_D);
  401. MAKE_HIGH(SIO_C);
  402. Delay(10);
  403. MAKE_LOW(SIO_D);
  404. MAKE_LOW(SIO_C);
  405. Delay(10);
  406. }
  407. */
  408. /* CFG_READ(SIO_D);
  409. printk("%dn", BIT_READ(SIO_D));
  410. CFG_WRITE(SIO_D);
  411. */
  412. printk("Check camera IDn");
  413. ret = check_ov7620() ;
  414. if (ret) {
  415. printk("Can't find camera!n");
  416. return ret;
  417. }
  418. printk("Initial Camera now, Please wait several minutes...n");
  419. ov7620_config();
  420. return 0;
  421. }