ov7670 library
Dependents: Project_test Capture_bw_portin Capture_bw_v3 Project_190659132
ov7670.cpp@1:d82dbad9c06b, 2013-03-16 (annotated)
- Committer:
- edodm85
- Date:
- Sat Mar 16 13:40:36 2013 +0000
- Revision:
- 1:d82dbad9c06b
- Parent:
- 0:810d59d0b843
- Child:
- 2:354a00023f79
Add QVGA and VGA reg
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
edodm85 | 0:810d59d0b843 | 1 | #include "ov7670.h" |
edodm85 | 0:810d59d0b843 | 2 | |
edodm85 | 0:810d59d0b843 | 3 | |
edodm85 | 0:810d59d0b843 | 4 | OV7670::OV7670(PinName sda, PinName scl, PinName vs, PinName hr, PinName we, PortName port, int mask, PinName rt, PinName o, PinName rc) : _i2c(sda,scl),vsync(vs),href(hr),wen(we),data(port,mask),rrst(rt),oe(o),rclk(rc) |
edodm85 | 0:810d59d0b843 | 5 | { |
edodm85 | 0:810d59d0b843 | 6 | _i2c.stop(); |
edodm85 | 0:810d59d0b843 | 7 | _i2c.frequency(OV7670_I2CFREQ); |
edodm85 | 0:810d59d0b843 | 8 | vsync.fall(this,&OV7670::VsyncHandler); // interrupt fall edge |
edodm85 | 0:810d59d0b843 | 9 | href.rise(this,&OV7670::HrefHandler); // interrupt rise edge |
edodm85 | 0:810d59d0b843 | 10 | CaptureReq = false; |
edodm85 | 0:810d59d0b843 | 11 | Busy = false; |
edodm85 | 0:810d59d0b843 | 12 | Done = false; |
edodm85 | 0:810d59d0b843 | 13 | LineCounter = 0; |
edodm85 | 0:810d59d0b843 | 14 | rrst = 1; |
edodm85 | 0:810d59d0b843 | 15 | oe = 1; |
edodm85 | 0:810d59d0b843 | 16 | rclk = 1; |
edodm85 | 0:810d59d0b843 | 17 | wen = 0; |
edodm85 | 0:810d59d0b843 | 18 | } |
edodm85 | 0:810d59d0b843 | 19 | |
edodm85 | 0:810d59d0b843 | 20 | OV7670::~OV7670() |
edodm85 | 0:810d59d0b843 | 21 | { |
edodm85 | 0:810d59d0b843 | 22 | |
edodm85 | 0:810d59d0b843 | 23 | } |
edodm85 | 0:810d59d0b843 | 24 | |
edodm85 | 0:810d59d0b843 | 25 | // capture request |
edodm85 | 0:810d59d0b843 | 26 | void OV7670::CaptureNext(void) |
edodm85 | 0:810d59d0b843 | 27 | { |
edodm85 | 0:810d59d0b843 | 28 | CaptureReq = true ; |
edodm85 | 0:810d59d0b843 | 29 | Busy = true ; |
edodm85 | 0:810d59d0b843 | 30 | } |
edodm85 | 0:810d59d0b843 | 31 | |
edodm85 | 0:810d59d0b843 | 32 | // capture done? (with clear) |
edodm85 | 0:810d59d0b843 | 33 | bool OV7670::CaptureDone(void) |
edodm85 | 0:810d59d0b843 | 34 | { |
edodm85 | 0:810d59d0b843 | 35 | bool result ; |
edodm85 | 0:810d59d0b843 | 36 | if (Busy) { |
edodm85 | 0:810d59d0b843 | 37 | result = false ; |
edodm85 | 0:810d59d0b843 | 38 | } else { |
edodm85 | 0:810d59d0b843 | 39 | result = Done ; |
edodm85 | 0:810d59d0b843 | 40 | Done = false ; |
edodm85 | 0:810d59d0b843 | 41 | } |
edodm85 | 0:810d59d0b843 | 42 | return result ; |
edodm85 | 0:810d59d0b843 | 43 | } |
edodm85 | 0:810d59d0b843 | 44 | |
edodm85 | 0:810d59d0b843 | 45 | // write to camera |
edodm85 | 0:810d59d0b843 | 46 | void OV7670::WriteReg(int addr,int data) |
edodm85 | 0:810d59d0b843 | 47 | { |
edodm85 | 0:810d59d0b843 | 48 | _i2c.start() ; |
edodm85 | 0:810d59d0b843 | 49 | _i2c.write(OV7670_WRITE) ; |
edodm85 | 0:810d59d0b843 | 50 | wait_us(OV7670_WRITEWAIT); |
edodm85 | 0:810d59d0b843 | 51 | _i2c.write(addr) ; |
edodm85 | 0:810d59d0b843 | 52 | wait_us(OV7670_WRITEWAIT); |
edodm85 | 0:810d59d0b843 | 53 | _i2c.write(data) ; |
edodm85 | 0:810d59d0b843 | 54 | _i2c.stop() ; |
edodm85 | 0:810d59d0b843 | 55 | } |
edodm85 | 0:810d59d0b843 | 56 | |
edodm85 | 0:810d59d0b843 | 57 | // read from camera |
edodm85 | 0:810d59d0b843 | 58 | int OV7670::ReadReg(int addr) |
edodm85 | 0:810d59d0b843 | 59 | { |
edodm85 | 0:810d59d0b843 | 60 | int data ; |
edodm85 | 0:810d59d0b843 | 61 | |
edodm85 | 0:810d59d0b843 | 62 | _i2c.start() ; |
edodm85 | 0:810d59d0b843 | 63 | _i2c.write(OV7670_WRITE) ; |
edodm85 | 0:810d59d0b843 | 64 | wait_us(OV7670_WRITEWAIT); |
edodm85 | 0:810d59d0b843 | 65 | _i2c.write(addr) ; |
edodm85 | 0:810d59d0b843 | 66 | _i2c.stop() ; |
edodm85 | 0:810d59d0b843 | 67 | wait_us(OV7670_WRITEWAIT); |
edodm85 | 0:810d59d0b843 | 68 | |
edodm85 | 0:810d59d0b843 | 69 | _i2c.start() ; |
edodm85 | 0:810d59d0b843 | 70 | _i2c.write(OV7670_READ) ; |
edodm85 | 0:810d59d0b843 | 71 | wait_us(OV7670_WRITEWAIT); |
edodm85 | 0:810d59d0b843 | 72 | data = _i2c.read(OV7670_NOACK) ; |
edodm85 | 0:810d59d0b843 | 73 | _i2c.stop() ; |
edodm85 | 0:810d59d0b843 | 74 | |
edodm85 | 0:810d59d0b843 | 75 | return data ; |
edodm85 | 0:810d59d0b843 | 76 | } |
edodm85 | 0:810d59d0b843 | 77 | |
edodm85 | 0:810d59d0b843 | 78 | void OV7670::Reset(void) { |
edodm85 | 0:810d59d0b843 | 79 | WriteReg(0x12,0x80) ; // RESET CAMERA |
edodm85 | 0:810d59d0b843 | 80 | wait_ms(200) ; |
edodm85 | 0:810d59d0b843 | 81 | } |
edodm85 | 0:810d59d0b843 | 82 | |
edodm85 | 1:d82dbad9c06b | 83 | int OV7670::Init(char c, int n) |
edodm85 | 0:810d59d0b843 | 84 | { |
edodm85 | 0:810d59d0b843 | 85 | |
edodm85 | 0:810d59d0b843 | 86 | if (ReadReg(REG_PID) != 0x76) // check id camera |
edodm85 | 0:810d59d0b843 | 87 | { |
edodm85 | 0:810d59d0b843 | 88 | return 0; |
edodm85 | 0:810d59d0b843 | 89 | } |
edodm85 | 0:810d59d0b843 | 90 | |
edodm85 | 1:d82dbad9c06b | 91 | Reset(); // Resets all registers to default values |
edodm85 | 1:d82dbad9c06b | 92 | Reset(); // Resets all registers to default values |
edodm85 | 1:d82dbad9c06b | 93 | |
edodm85 | 1:d82dbad9c06b | 94 | WriteReg(REG_RGB444, 0x00); // Disable RGB444 |
edodm85 | 1:d82dbad9c06b | 95 | WriteReg(REG_COM10,0x02); // 0x02 VSYNC negative (http://nasulica.homelinux.org/?p=959) |
edodm85 | 1:d82dbad9c06b | 96 | WriteReg(REG_MVFP,0x27); // mirror image |
edodm85 | 1:d82dbad9c06b | 97 | |
edodm85 | 1:d82dbad9c06b | 98 | WriteReg(REG_CLKRC,0x80); // prescaler x1 |
edodm85 | 1:d82dbad9c06b | 99 | WriteReg(DBLV,0x0a); // bypass PLL |
edodm85 | 1:d82dbad9c06b | 100 | |
edodm85 | 0:810d59d0b843 | 101 | WriteReg(REG_COM11,0x0A) ; |
edodm85 | 1:d82dbad9c06b | 102 | WriteReg(REG_TSLB,0x04); // 0D = UYVY 04 = YUYV |
edodm85 | 1:d82dbad9c06b | 103 | WriteReg(REG_COM13,0x88); // connect to REG_TSLB |
edodm85 | 0:810d59d0b843 | 104 | |
edodm85 | 1:d82dbad9c06b | 105 | |
edodm85 | 1:d82dbad9c06b | 106 | if(c == 'b' || c == 'y') // YUV |
edodm85 | 1:d82dbad9c06b | 107 | { |
edodm85 | 1:d82dbad9c06b | 108 | WriteReg(REG_COM7, 0x00); // YUV |
edodm85 | 1:d82dbad9c06b | 109 | WriteReg(REG_COM17, 0x00); // color bar disable |
edodm85 | 1:d82dbad9c06b | 110 | WriteReg(REG_COM3, 0x04); |
edodm85 | 1:d82dbad9c06b | 111 | WriteReg(REG_COM15, 0xC0); // Set normal rgb with Full range |
edodm85 | 1:d82dbad9c06b | 112 | |
edodm85 | 1:d82dbad9c06b | 113 | }else |
edodm85 | 1:d82dbad9c06b | 114 | if(c == 'r') // RGB565 |
edodm85 | 1:d82dbad9c06b | 115 | { |
edodm85 | 1:d82dbad9c06b | 116 | WriteReg(REG_COM7, 0x04); // RGB + color bar disable |
edodm85 | 1:d82dbad9c06b | 117 | WriteReg(REG_RGB444, 0x00); // Disable RGB444 |
edodm85 | 1:d82dbad9c06b | 118 | WriteReg(REG_COM15, 0x10); // Set rgb565 with Full range 0xD0 |
edodm85 | 1:d82dbad9c06b | 119 | WriteReg(REG_COM3, 0x04); |
edodm85 | 1:d82dbad9c06b | 120 | WriteReg(REG_CLKRC,0x80); // prescaler x1 |
edodm85 | 1:d82dbad9c06b | 121 | } |
edodm85 | 1:d82dbad9c06b | 122 | |
edodm85 | 1:d82dbad9c06b | 123 | WriteReg(0x70, 0x3A); // Scaling Xsc |
edodm85 | 1:d82dbad9c06b | 124 | WriteReg(0x71, 0x35); // Scaling Ysc |
edodm85 | 1:d82dbad9c06b | 125 | WriteReg(0xA2, 0x02); // pixel clock delay |
edodm85 | 1:d82dbad9c06b | 126 | |
edodm85 | 1:d82dbad9c06b | 127 | if(n == 19200) // 160*120 |
edodm85 | 1:d82dbad9c06b | 128 | { |
edodm85 | 1:d82dbad9c06b | 129 | WriteReg(REG_COM14, 0x1a); // divide by 4 |
edodm85 | 1:d82dbad9c06b | 130 | WriteReg(0x72, 0x22); // downsample by 4 |
edodm85 | 1:d82dbad9c06b | 131 | WriteReg(0x73, 0xf2); // divide by 4 |
edodm85 | 1:d82dbad9c06b | 132 | WriteReg(REG_HSTART,0x16); |
edodm85 | 1:d82dbad9c06b | 133 | WriteReg(REG_HSTOP,0x04); |
edodm85 | 1:d82dbad9c06b | 134 | WriteReg(REG_HREF,0xa4); |
edodm85 | 1:d82dbad9c06b | 135 | WriteReg(REG_VSTART,0x02); |
edodm85 | 1:d82dbad9c06b | 136 | WriteReg(REG_VSTOP,0x7a); |
edodm85 | 1:d82dbad9c06b | 137 | WriteReg(REG_VREF,0x0a); |
edodm85 | 1:d82dbad9c06b | 138 | } |
edodm85 | 1:d82dbad9c06b | 139 | if(n == 76800) // 320*240 |
edodm85 | 1:d82dbad9c06b | 140 | { |
edodm85 | 1:d82dbad9c06b | 141 | WriteReg(REG_COM14, 0x19); |
edodm85 | 1:d82dbad9c06b | 142 | WriteReg(0x72, 0x11); |
edodm85 | 1:d82dbad9c06b | 143 | WriteReg(0x73, 0xf1); |
edodm85 | 1:d82dbad9c06b | 144 | WriteReg(REG_HSTART,0x16); |
edodm85 | 1:d82dbad9c06b | 145 | WriteReg(REG_HSTOP,0x04); |
edodm85 | 1:d82dbad9c06b | 146 | WriteReg(REG_HREF,0x24); |
edodm85 | 1:d82dbad9c06b | 147 | WriteReg(REG_VSTART,0x02); |
edodm85 | 1:d82dbad9c06b | 148 | WriteReg(REG_VSTOP,0x7a); |
edodm85 | 1:d82dbad9c06b | 149 | WriteReg(REG_VREF,0x0a); |
edodm85 | 1:d82dbad9c06b | 150 | } |
edodm85 | 1:d82dbad9c06b | 151 | if(n == 307200) // 640*480 |
edodm85 | 1:d82dbad9c06b | 152 | { |
edodm85 | 1:d82dbad9c06b | 153 | WriteReg(REG_COM3,0x00); // REG_COM3 |
edodm85 | 1:d82dbad9c06b | 154 | WriteReg(0x3e,0x00); // REG_COM14 |
edodm85 | 1:d82dbad9c06b | 155 | WriteReg(0x72,0x11); // |
edodm85 | 1:d82dbad9c06b | 156 | WriteReg(0x73,0xf0); // |
edodm85 | 1:d82dbad9c06b | 157 | |
edodm85 | 1:d82dbad9c06b | 158 | WriteReg(0x32,0xb6); // HREF |
edodm85 | 1:d82dbad9c06b | 159 | WriteReg(0x17,0x13); // HSTART |
edodm85 | 1:d82dbad9c06b | 160 | WriteReg(0x18,0x01); // HSTOP |
edodm85 | 1:d82dbad9c06b | 161 | WriteReg(0x19,0x02); // VSTART |
edodm85 | 1:d82dbad9c06b | 162 | WriteReg(0x1a,0x7a); // VSTOP |
edodm85 | 1:d82dbad9c06b | 163 | WriteReg(0x03,0x0a); // VREF |
edodm85 | 1:d82dbad9c06b | 164 | WriteReg(0x70, 0x3a); // Scaling Xsc |
edodm85 | 1:d82dbad9c06b | 165 | WriteReg(0x71, 0x35); // Scaling Ysc |
edodm85 | 1:d82dbad9c06b | 166 | WriteReg(0xA2, 0x02); // pixel clock delay |
edodm85 | 1:d82dbad9c06b | 167 | |
edodm85 | 1:d82dbad9c06b | 168 | WriteReg(REG_COM1, 0x00); |
edodm85 | 1:d82dbad9c06b | 169 | } |
edodm85 | 1:d82dbad9c06b | 170 | |
edodm85 | 1:d82dbad9c06b | 171 | |
edodm85 | 0:810d59d0b843 | 172 | // COLOR SETTING |
edodm85 | 1:d82dbad9c06b | 173 | |
edodm85 | 0:810d59d0b843 | 174 | WriteReg(REG_COM8,0x8F); // AGC AWB AEC Enab |
edodm85 | 1:d82dbad9c06b | 175 | WriteReg(0xAA,0x14); // Average-based AEC algorithm |
edodm85 | 0:810d59d0b843 | 176 | WriteReg(REG_BRIGHT,0x00); // 0x00(Brightness 0) - 0x18(Brightness +1) - 0x98(Brightness -1) |
edodm85 | 0:810d59d0b843 | 177 | WriteReg(REG_CONTRAS,0x40); // 0x40(Contrast 0) - 0x50(Contrast +1) - 0x38(Contrast -1) |
edodm85 | 1:d82dbad9c06b | 178 | WriteReg(0xB1,0xB1); // Automatic Black level Calibration |
edodm85 | 1:d82dbad9c06b | 179 | |
edodm85 | 1:d82dbad9c06b | 180 | WriteReg(MTX1,0x80); |
edodm85 | 1:d82dbad9c06b | 181 | WriteReg(MTX2,0x80); |
edodm85 | 1:d82dbad9c06b | 182 | WriteReg(MTX3,0x00); |
edodm85 | 1:d82dbad9c06b | 183 | WriteReg(MTX4,0x22); |
edodm85 | 1:d82dbad9c06b | 184 | WriteReg(MTX5,0x5e); |
edodm85 | 1:d82dbad9c06b | 185 | WriteReg(MTX6,0x80); |
edodm85 | 1:d82dbad9c06b | 186 | WriteReg(MTXS,0x9e); |
edodm85 | 0:810d59d0b843 | 187 | WriteReg(AWBC7,0x88); |
edodm85 | 0:810d59d0b843 | 188 | WriteReg(AWBC8,0x88); |
edodm85 | 0:810d59d0b843 | 189 | WriteReg(AWBC9,0x44); |
edodm85 | 0:810d59d0b843 | 190 | WriteReg(AWBC10,0x67); |
edodm85 | 0:810d59d0b843 | 191 | WriteReg(AWBC11,0x49); |
edodm85 | 0:810d59d0b843 | 192 | WriteReg(AWBC12,0x0e); |
edodm85 | 0:810d59d0b843 | 193 | WriteReg(REG_GFIX,0x00); |
edodm85 | 0:810d59d0b843 | 194 | WriteReg(GGAIN,0x40); |
edodm85 | 0:810d59d0b843 | 195 | WriteReg(AWBCTR3,0x0a); |
edodm85 | 0:810d59d0b843 | 196 | WriteReg(AWBCTR2,0x55); |
edodm85 | 0:810d59d0b843 | 197 | WriteReg(AWBCTR1,0x11); |
edodm85 | 0:810d59d0b843 | 198 | WriteReg(AWBCTR0,0x9f); |
edodm85 | 0:810d59d0b843 | 199 | |
edodm85 | 0:810d59d0b843 | 200 | WriteReg(0xb0,0x84); |
edodm85 | 1:d82dbad9c06b | 201 | |
edodm85 | 0:810d59d0b843 | 202 | return 1; |
edodm85 | 0:810d59d0b843 | 203 | } |
edodm85 | 0:810d59d0b843 | 204 | |
edodm85 | 0:810d59d0b843 | 205 | // vsync handler |
edodm85 | 0:810d59d0b843 | 206 | void OV7670::VsyncHandler(void) |
edodm85 | 0:810d59d0b843 | 207 | { |
edodm85 | 0:810d59d0b843 | 208 | |
edodm85 | 0:810d59d0b843 | 209 | // Capture Enable |
edodm85 | 0:810d59d0b843 | 210 | if (CaptureReq) { |
edodm85 | 0:810d59d0b843 | 211 | wen = 1 ; |
edodm85 | 0:810d59d0b843 | 212 | Done = false ; |
edodm85 | 0:810d59d0b843 | 213 | CaptureReq = false ; |
edodm85 | 0:810d59d0b843 | 214 | } else { |
edodm85 | 0:810d59d0b843 | 215 | wen = 0 ; |
edodm85 | 0:810d59d0b843 | 216 | if (Busy) { |
edodm85 | 0:810d59d0b843 | 217 | Busy = false ; |
edodm85 | 0:810d59d0b843 | 218 | Done = true ; |
edodm85 | 0:810d59d0b843 | 219 | } |
edodm85 | 0:810d59d0b843 | 220 | } |
edodm85 | 0:810d59d0b843 | 221 | |
edodm85 | 0:810d59d0b843 | 222 | // Hline Counter |
edodm85 | 0:810d59d0b843 | 223 | LastLines = LineCounter ; |
edodm85 | 0:810d59d0b843 | 224 | LineCounter = 0 ; |
edodm85 | 0:810d59d0b843 | 225 | } |
edodm85 | 0:810d59d0b843 | 226 | |
edodm85 | 0:810d59d0b843 | 227 | // href handler |
edodm85 | 0:810d59d0b843 | 228 | void OV7670::HrefHandler(void) |
edodm85 | 0:810d59d0b843 | 229 | { |
edodm85 | 0:810d59d0b843 | 230 | LineCounter++ ; |
edodm85 | 0:810d59d0b843 | 231 | } |
edodm85 | 0:810d59d0b843 | 232 | |
edodm85 | 0:810d59d0b843 | 233 | // Data Read |
edodm85 | 0:810d59d0b843 | 234 | int OV7670::ReadOnebyte(void) |
edodm85 | 0:810d59d0b843 | 235 | { |
edodm85 | 0:810d59d0b843 | 236 | int B1; |
edodm85 | 0:810d59d0b843 | 237 | rclk = 1; |
edodm85 | 0:810d59d0b843 | 238 | B1 = (((data&0x07800000)>>19)|((data&0x078000)>>15)); |
edodm85 | 0:810d59d0b843 | 239 | rclk = 0; |
edodm85 | 0:810d59d0b843 | 240 | return B1; |
edodm85 | 0:810d59d0b843 | 241 | } |
edodm85 | 0:810d59d0b843 | 242 | |
edodm85 | 0:810d59d0b843 | 243 | // Data Start read from FIFO |
edodm85 | 0:810d59d0b843 | 244 | void OV7670::ReadStart(void) |
edodm85 | 0:810d59d0b843 | 245 | { |
edodm85 | 0:810d59d0b843 | 246 | rrst = 0 ; |
edodm85 | 0:810d59d0b843 | 247 | oe = 0 ; |
edodm85 | 0:810d59d0b843 | 248 | wait_us(1) ; |
edodm85 | 0:810d59d0b843 | 249 | rclk = 0 ; |
edodm85 | 0:810d59d0b843 | 250 | wait_us(1) ; |
edodm85 | 0:810d59d0b843 | 251 | rclk = 1 ; |
edodm85 | 0:810d59d0b843 | 252 | wait_us(1) ; |
edodm85 | 0:810d59d0b843 | 253 | rrst = 1 ; |
edodm85 | 0:810d59d0b843 | 254 | } |
edodm85 | 0:810d59d0b843 | 255 | |
edodm85 | 0:810d59d0b843 | 256 | // Data Stop read from FIFO |
edodm85 | 0:810d59d0b843 | 257 | void OV7670::ReadStop(void) |
edodm85 | 0:810d59d0b843 | 258 | { |
edodm85 | 0:810d59d0b843 | 259 | oe = 1 ; |
edodm85 | 0:810d59d0b843 | 260 | ReadOnebyte() ; |
edodm85 | 0:810d59d0b843 | 261 | rclk = 1 ; |
edodm85 | 0:810d59d0b843 | 262 | } |