OV7670 without FIFO, SCCB protocol rewritten.
Embed:
(wiki syntax)
Show/hide line numbers
ov7670s.cpp
00001 #include "mbed.h" 00002 #include "global.h" 00003 #include "math.h" 00004 #include "ov7670sreg.h" 00005 #include "ov7670s.h" 00006 #include "FastPWM.h" 00007 #include "SPI_TFT_ILI9341.h" 00008 00009 OV7670::OV7670( 00010 PinName siod, // Camera I2C port data 00011 PinName sioc, // Camera I2C port clock 00012 PinName xclk, // Pixelclock 00013 00014 PortName port, 00015 int mask, 00016 /* 00017 XCLK 00018 VSYNC 00019 HREF 00020 PinName d7, // D7 00021 PinName d6, // D6 00022 PinName d5, // D5 00023 PinName d4, // D4 00024 PinName d3, // D3 00025 PinName d2, // D2 00026 PinName d1, // D1 00027 PinName d0, // D0 00028 */ 00029 PinName rst // /RESET 00030 ):_siod(siod),_sioc(sioc),_xclk(xclk),data(port,mask),_rst(rst) 00031 { 00032 } 00033 00034 //DigitalOut str(PB_3); // internal strobe for debug 00035 //DigitalOut str1(PC_8); // internal strobe for debug 00036 00037 void OV7670::Start() 00038 { 00039 _sioc=1; 00040 _siod.output(); 00041 _siod=1; 00042 wait_us(OV7670_I2CFREQ); 00043 _siod=0; 00044 wait_us(OV7670_I2CFREQ); 00045 _sioc=0; 00046 wait_us(OV7670_I2CFREQ); 00047 00048 } 00049 void OV7670::End() 00050 { 00051 _sioc=0; 00052 _siod.output(); 00053 _siod=0; 00054 wait_us(OV7670_I2CFREQ); 00055 _sioc=1; 00056 wait_us(OV7670_I2CFREQ); 00057 _siod=1; 00058 wait_us(OV7670_I2CFREQ); 00059 _siod.input(); 00060 wait_us(OV7670_I2CFREQ); 00061 } 00062 00063 void OV7670::Reset() 00064 { 00065 _sioc=1; 00066 //str=0; 00067 //str1=0; 00068 _siod.input(); 00069 _xclk.period_us(CAMERA_CLK_PERIOD); 00070 _xclk.write(0.5); 00071 _rst=1; 00072 wait_us(1000); 00073 _rst=0; 00074 wait_us(1000); 00075 _rst=1; 00076 wait_us(1000); 00077 WriteReg(0x12,0x80) ; // RESET CAMERA 00078 wait_ms(300) ; 00079 WriteReg(0x12,0x00); 00080 wait_ms(300) ; 00081 } 00082 void OV7670::WriteBy(int addr) 00083 { 00084 int tempo=0; 00085 _siod.output(); 00086 wait_us(1); 00087 _sioc=0; 00088 _siod=1; 00089 for (int i=0; i<8; i++) { 00090 tempo=addr>>7-i; 00091 tempo=tempo&0x01; 00092 _sioc=0; 00093 _siod=tempo;; 00094 wait_us(OV7670_I2CFREQ); 00095 _sioc=1; 00096 wait_us(OV7670_I2CFREQ); 00097 } 00098 _sioc=0; 00099 _siod=1; 00100 _siod.input(); 00101 wait_us(OV7670_I2CFREQ); 00102 _sioc=1; 00103 wait_us(OV7670_I2CFREQ); 00104 _sioc=0; 00105 } 00106 00107 int OV7670::ReadBy() 00108 { 00109 unsigned char data[8]; 00110 int tt=0; 00111 _siod.input(); 00112 _sioc=0; 00113 for (int i=0; i<8; i++) { 00114 _sioc=0; 00115 wait_us(OV7670_I2CFREQ); 00116 _sioc=1; 00117 data[7-i]=_siod; 00118 wait_us(OV7670_I2CFREQ); 00119 } 00120 _sioc=0; 00121 for (int i=0; i<8; i++) { 00122 tt=tt|data[7-i]; 00123 if (i<7) { 00124 tt=tt<<1; 00125 } 00126 } 00127 _siod.output(); 00128 _siod=1; 00129 wait_us(OV7670_I2CFREQ); 00130 _sioc=1; 00131 wait_us(OV7670_I2CFREQ); 00132 _sioc=0; 00133 return tt; 00134 } 00135 00136 void OV7670::WriteReg2(int data) 00137 { 00138 Start(); 00139 WriteBy(OV7670_WRITE); 00140 WriteBy(data); 00141 End(); 00142 } 00143 void OV7670::WriteReg(int subad,int data) 00144 { 00145 Start(); 00146 WriteBy(OV7670_WRITE); 00147 WriteBy(subad); 00148 WriteBy(data); 00149 End(); 00150 } 00151 void OV7670::capture(void) 00152 { 00153 pc.printf("capture requested \r\n"); 00154 fp = fopen(desfile, "w"); 00155 for (int i=0; i<38400; i++) { 00156 fputc(bank[i], fp); 00157 } 00158 pc.printf("captured done \r\n"); 00159 TFT.foreground(Green); 00160 TFT.locate(0,0); 00161 printf(" capture done"); 00162 fclose(fp); 00163 captur=false; 00164 } 00165 00166 int OV7670::ReadReg(int subad) 00167 { 00168 int dr=0; 00169 WriteReg2(subad); 00170 Start(); 00171 WriteBy(OV7670_READ); 00172 dr = ReadBy(); 00173 End(); 00174 return dr; 00175 } 00176 00177 void OV7670::exrgbf(int j) 00178 { 00179 00180 int ncl = nc*2; 00181 int jn,jn1,d1,d2,d3; 00182 jn =j*ncl/2; 00183 jn1=(j/2)*ncl*nl/2; 00184 00185 00186 00187 for(int k=0; k <nl/2; k++) { 00188 00189 for (int i = jn; i< (j+1)*ncl/2; i=i+2) { 00190 d1=2*(i-jn)+ncl*2*k; 00191 d2=i+ncl*k+jn1; 00192 d3=(2*(i-jn))+ ncl*(2*k+1); 00193 bankf[d1]=bank[d2]; 00194 bankf[d1+2]=bank[d2]; 00195 bankf[d1+1]=bank[d2+1]; 00196 bankf[d1+3]=bank[d2+1]; 00197 00198 bankf[d3]=bank[d2]; 00199 bankf[d3+2]=bank[d2]; 00200 bankf[d3+1]=bank[d2+1]; 00201 bankf[d3+3]=bank[d2+1]; 00202 00203 } 00204 00205 } 00206 } 00207 00208 00209 // capture request 00210 void OV7670::CaptureNext(void) 00211 { 00212 __disable_irq(); // Disable Interrupts 00213 00214 bool cc=true; 00215 bool h,c,v; 00216 bool cpr=false; 00217 int w; 00218 w=data.read(); 00219 v=w>>12; 00220 // waitnegedge(v); 00221 while(!v) { 00222 w=data.read(); 00223 v=w>>12; 00224 }; 00225 while(v) { 00226 w=data.read(); 00227 v=w>>12; 00228 }; 00229 if (captur) { 00230 cpr=true; 00231 captur=false; 00232 } 00233 //waitposedge(v); 00234 while(v) { 00235 w=data.read(); 00236 v=w>>12; 00237 }; 00238 while(!v) { 00239 w=data.read(); 00240 v=w>>12; 00241 }; 00242 PixelCounter=0; 00243 //Time.start(); 00244 while (v) { 00245 w=data.read(); 00246 v=w>>12; 00247 h=w>>11&0x01; 00248 c=w>>10&0x01; 00249 00250 if (!c && h ) { 00251 cc=true; 00252 } 00253 if (cc && c && h) { 00254 bank[PixelCounter]=w>>2; 00255 PixelCounter++; 00256 cc=false; 00257 00258 } 00259 } 00260 00261 __enable_irq(); // Enable Interrupts 00262 if (cpr) { 00263 capture(); 00264 cpr=false; 00265 } 00266 } 00267 00268 unsigned char OV7670::reverse(unsigned char b) 00269 { 00270 b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; 00271 b = (b & 0xCC) >> 2 | (b & 0x33) << 2; 00272 b = (b & 0xAA) >> 1 | (b & 0x55) << 1; 00273 return b; 00274 } 00275 00276 00277 00278 00279 int OV7670::Init(char *format, int n) 00280 { 00281 00282 if (ReadReg(REG_PID) != 0x76) { // check id camera 00283 return 0; 00284 } 00285 00286 Reset(); // Resets all registers to default values 00287 Reset(); // Resets all registers to default values 00288 00289 WriteReg(REG_RGB444, 0x00); // Disable RGB444 00290 WriteReg(REG_COM10, 0x22); // 0x02 VSYNC negative (http://nasulica.homelinux.org/?p=959) 00291 WriteReg(REG_MVFP, 0x27); // mirror image 00292 00293 WriteReg(REG_CLKRC, 0x80); // prescaler x1 00294 WriteReg(DBLV, 0x0a); // bypass PLL 00295 00296 WriteReg(REG_COM11, 0x0A) ; 00297 WriteReg(REG_TSLB, 0x0D); // 0D = UYVY 04 = YUYV 00298 WriteReg(REG_COM13, 0x88); // connect to REG_TSLB 00299 00300 00301 if((strcmp("BAW", format) == 0) || (strcmp("YUV", format) == 0)|| (strcmp("RAW", format) == 0)) { // YUV 00302 WriteReg(REG_COM7, 0x00); // YUV 00303 WriteReg(REG_COM17, 0x00); // color bar disable 00304 WriteReg(REG_COM3, 0x04); 00305 WriteReg(REG_COM15, 0xC0); // Set normal rgb with Full range 00306 00307 } else if((strcmp("RGB", format) == 0)) { // RGB565 00308 WriteReg(REG_COM7, 0x04); // RGB + color bar disable 00309 WriteReg(REG_RGB444, 0x00); // Disable RGB444 00310 WriteReg(REG_COM15, 0x10); // Set rgb565 with Full range 0xD0 00311 WriteReg(REG_COM3, 0x04);//0x44 00312 //WriteReg(REG_COM1, 0x40); 00313 WriteReg(REG_CLKRC, 0x80); // prescaler x1 00314 } 00315 00316 WriteReg(0x70, 0x3A); // Scaling Xsc 00317 WriteReg(0x71, 0x35); // Scaling Ysc 00318 WriteReg(0xA2, 0x02); // pixel clock delay 00319 00320 if(n == 19200) { // 160*120 00321 WriteReg(REG_COM14, 0x1a); // divide by 4 00322 WriteReg(0x72, 0x22); // downsample by 4 00323 WriteReg(0x73, 0xf2); // divide by 4 00324 WriteReg(REG_HREF, 0x24);//a4 00325 WriteReg(REG_HSTART, 0x16); 00326 WriteReg(REG_HSTOP, 0x04); 00327 WriteReg(REG_VREF, 0x0a);//0a 00328 WriteReg(REG_VSTART, 0x02); 00329 WriteReg(REG_VSTOP, 0x7a); 00330 00331 00332 WriteReg(0x7a, 0x20); 00333 WriteReg(0x7b, 0x1c); 00334 WriteReg(0x7c, 0x28); 00335 WriteReg(0x7d, 0x3c); 00336 WriteReg(0x7e, 0x5a); 00337 WriteReg(0x7f, 0x68); 00338 WriteReg(0x80, 0x76); 00339 WriteReg(0x81, 0x80); 00340 WriteReg(0x82, 0x88); 00341 WriteReg(0x83, 0x8f); 00342 WriteReg(0x84, 0x96); 00343 WriteReg(0x85, 0xa3); 00344 WriteReg(0x86, 0xaf); 00345 WriteReg(0x87, 0xc4); 00346 WriteReg(0x88, 0xd7); 00347 WriteReg(0x89, 0xe8); 00348 00349 WriteReg(0x13, 0xe0); 00350 WriteReg(0x00, 0x00); 00351 WriteReg(0x10, 0x00); 00352 WriteReg(0x0d, 0x40); 00353 WriteReg(0x14, 0x18); 00354 WriteReg(0xa5, 0x05); 00355 WriteReg(0xab, 0x07); 00356 WriteReg(0x24, 0x95); 00357 WriteReg(0x25, 0x33); 00358 WriteReg(0x26, 0xe3); 00359 WriteReg(0x9f, 0x78); 00360 WriteReg(0xa0, 0x68); 00361 WriteReg(0xa1, 0x03); 00362 WriteReg(0xa6, 0xd8); 00363 WriteReg(0xa7, 0xd8); 00364 WriteReg(0xa8, 0xf0); 00365 WriteReg(0xa9, 0x90); 00366 WriteReg(0xaa, 0x94); 00367 WriteReg(0x13, 0xe5); 00368 00369 WriteReg(0x0e, 0x61); 00370 WriteReg(0x0f, 0x4b); 00371 WriteReg(0x16, 0x02); 00372 00373 WriteReg(0x21, 0x02); 00374 WriteReg(0x22, 0x91); 00375 WriteReg(0x29, 0x07); 00376 WriteReg(0x33, 0x0b); 00377 WriteReg(0x35, 0x0b); 00378 WriteReg(0x37, 0x1d); 00379 WriteReg(0x38, 0x71); 00380 WriteReg(0x39, 0x2a); 00381 WriteReg(0x3c, 0x78); 00382 WriteReg(0x4d, 0x40); 00383 WriteReg(0x4e, 0x20); 00384 WriteReg(0x69, 0x00); 00385 00386 WriteReg(0x74, 0x10); 00387 WriteReg(0x8d, 0x4f); 00388 WriteReg(0x8e, 0x00); 00389 WriteReg(0x8f, 0x00); 00390 WriteReg(0x90, 0x00); 00391 WriteReg(0x91, 0x00); 00392 WriteReg(0x92, 0x00); 00393 00394 WriteReg(0x96, 0x00); 00395 WriteReg(0x9a, 0x80); 00396 WriteReg(0xb0, 0x84); 00397 WriteReg(0xb1, 0x0c); 00398 WriteReg(0xb2, 0x0e); 00399 WriteReg(0xb3, 0x82); 00400 WriteReg(0xb8, 0x0a); 00401 00402 WriteReg(0x43, 0x0a); 00403 WriteReg(0x44, 0xf0); 00404 WriteReg(0x45, 0x34); 00405 WriteReg(0x46, 0x58); 00406 WriteReg(0x47, 0x28); 00407 WriteReg(0x48, 0x3a); 00408 WriteReg(0x59, 0x88); 00409 WriteReg(0x5a, 0x88); 00410 WriteReg(0x5b, 0x44); 00411 WriteReg(0x5c, 0x67); 00412 WriteReg(0x5d, 0x49); 00413 WriteReg(0x5e, 0x0e); 00414 WriteReg(0x64, 0x04); 00415 WriteReg(0x65, 0x20); 00416 WriteReg(0x66, 0x05); 00417 WriteReg(0x94, 0x04); 00418 WriteReg(0x95, 0x08); 00419 00420 WriteReg(0x6c, 0x0a); 00421 WriteReg(0x6d, 0x55); 00422 WriteReg(0x6e, 0x11); 00423 WriteReg(0x6f, 0x9f); 00424 WriteReg(0x6a, 0x40); 00425 WriteReg(0x01, 0x40); 00426 WriteReg(0x02, 0x40); 00427 WriteReg(0x13, 0xe7); 00428 WriteReg(0x15, 0x02); 00429 00430 WriteReg(0x4f, 0x80); 00431 WriteReg(0x50, 0x80); 00432 WriteReg(0x51, 0x00); 00433 WriteReg(0x52, 0x22); 00434 WriteReg(0x53, 0x5e); 00435 WriteReg(0x54, 0x80); 00436 WriteReg(0x58, 0x9e); 00437 00438 WriteReg(0x41, 0x08); 00439 WriteReg(0x3f, 0x00); 00440 WriteReg(0x75, 0x05); 00441 WriteReg(0x76, 0xe1); 00442 WriteReg(0x4c, 0x00); 00443 WriteReg(0x77, 0x01); 00444 WriteReg(0x3d, 0xc1); 00445 WriteReg(0x4b, 0x09); 00446 WriteReg(0xc9, 0x60); 00447 WriteReg(0x41, 0x38); 00448 WriteReg(0x56, 0x40); 00449 00450 WriteReg(0x34, 0x11); 00451 WriteReg(0x3b, 0x02); 00452 WriteReg(0xa4, 0x88); 00453 WriteReg(0x96, 0x00); 00454 WriteReg(0x97, 0x30); 00455 WriteReg(0x98, 0x20); 00456 WriteReg(0x99, 0x30); 00457 WriteReg(0x9a, 0x84); 00458 WriteReg(0x9b, 0x29); 00459 WriteReg(0x9c, 0x03); 00460 WriteReg(0x9d, 0x4c); 00461 WriteReg(0x9e, 0x3f); 00462 WriteReg(0x78, 0x04); 00463 00464 WriteReg(0x79, 0x01); 00465 WriteReg(0xc8, 0xf0); 00466 WriteReg(0x79, 0x0f); 00467 WriteReg(0xc8, 0x00); 00468 WriteReg(0x79, 0x10); 00469 WriteReg(0xc8, 0x7e); 00470 WriteReg(0x79, 0x0a); 00471 WriteReg(0xc8, 0x80); 00472 WriteReg(0x79, 0x0b); 00473 WriteReg(0xc8, 0x01); 00474 WriteReg(0x79, 0x0c); 00475 WriteReg(0xc8, 0x0f); 00476 WriteReg(0x79, 0x0d); 00477 WriteReg(0xc8, 0x20); 00478 WriteReg(0x79, 0x09); 00479 WriteReg(0xc8, 0x80); 00480 WriteReg(0x79, 0x02); 00481 WriteReg(0xc8, 0xc0); 00482 WriteReg(0x79, 0x03); 00483 WriteReg(0xc8, 0x40); 00484 WriteReg(0x79, 0x05); 00485 WriteReg(0xc8, 0x30); 00486 WriteReg(0x79, 0x26); 00487 WriteReg(0x09, 0x03); 00488 WriteReg(0x3b, 0x42); 00489 00490 WriteReg(0xff, 0xff); /* END MARKER */ 00491 WriteReg(DBLV, 0x4a); // clock multiplication by 4 4a 00492 //WriteReg(REG_CLKRC, 0x80); // prescaler x1 00493 WriteReg(REG_CLKRC, 0x03); // prescaler x2 00494 } 00495 if(n == 76800) { // 320*240 00496 00497 00498 } 00499 if(n == 307200) { // 640*480 00500 00501 } 00502 00503 return 1; 00504 }
Generated on Tue Jul 19 2022 21:47:14 by 1.7.2