OV7670 Library

Dependents:   OV7670_make

ov7670.cpp

Committer:
edodm85
Date:
2013-03-10
Revision:
0:810d59d0b843
Child:
1:d82dbad9c06b

File content as of revision 0:810d59d0b843:

#include "ov7670.h"   

    
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)
{
        _i2c.stop();
        _i2c.frequency(OV7670_I2CFREQ);
        vsync.fall(this,&OV7670::VsyncHandler);     // interrupt fall edge
        href.rise(this,&OV7670::HrefHandler);       // interrupt rise edge
        CaptureReq = false;
        Busy = false;
        Done = false;
        LineCounter = 0;
        rrst = 1;
        oe = 1;
        rclk = 1;
        wen = 0;
}

OV7670::~OV7670()
{

}

// capture request
void OV7670::CaptureNext(void)
{
    CaptureReq = true ;
    Busy = true ;
}

// capture done? (with clear)
bool OV7670::CaptureDone(void)
{
    bool result ;
    if (Busy) {
        result = false ;
    } else {
        result = Done ;
        Done = false ;
    }
    return result ;
}

// write to camera
void OV7670::WriteReg(int addr,int data)
{
    _i2c.start() ;
    _i2c.write(OV7670_WRITE) ;
    wait_us(OV7670_WRITEWAIT);
    _i2c.write(addr) ;
    wait_us(OV7670_WRITEWAIT);
    _i2c.write(data) ;
    _i2c.stop() ;
}

// read from camera
int OV7670::ReadReg(int addr)
{
    int data ;
    
    _i2c.start() ;
    _i2c.write(OV7670_WRITE) ;
    wait_us(OV7670_WRITEWAIT);
    _i2c.write(addr) ;
    _i2c.stop() ;
    wait_us(OV7670_WRITEWAIT);    

    _i2c.start() ;
    _i2c.write(OV7670_READ) ;
    wait_us(OV7670_WRITEWAIT);
    data = _i2c.read(OV7670_NOACK) ;
    _i2c.stop() ;

    return data ;
}

void OV7670::Reset(void) {    
    WriteReg(0x12,0x80) ;       // RESET CAMERA
    wait_ms(200) ;
}

int OV7670::Init(char c) 
{
    
    if (ReadReg(REG_PID) != 0x76)       // check id camera
    {
        return 0;
    }
    
    Reset();                        // Resets all registers to default values
 
    WriteReg(REG_CLKRC,0x80);
    WriteReg(REG_COM11,0x0A) ;
    WriteReg(REG_TSLB,0x04);        // 0D = UYVY  04 = YUYV     
    WriteReg(REG_COM13,0x88);       // connect to REG_TSLB
    
    //WriteReg(REG_COM7,0x01) ;     // output format: raw
    WriteReg(REG_RGB444, 0x00);     // Disable RGB444    
    WriteReg(REG_HSTART,0x16) ;
    WriteReg(REG_HSTOP,0x04) ;
    WriteReg(REG_HREF,0x24) ;
    WriteReg(REG_VSTART,0x02) ;
    WriteReg(REG_VSTOP,0x7a) ;
    WriteReg(REG_VREF,0x0a) ;
    WriteReg(REG_COM10,0x02) ;          // 0x02   VSYNC negative (http://nasulica.homelinux.org/?p=959)
    WriteReg(REG_MVFP,0x27) ;
  
        if(c == 'y')
        {
            WriteReg(REG_COM7,0x00);            // YUV
            WriteReg(REG_COM17,0x00);           // color bar disable
            WriteReg(REG_COM3, 0x04);
            WriteReg(REG_COM14, 0x1a);          // by 4
            WriteReg(REG_COM15, 0xC0);          // Set normal rgb
            WriteReg(0x70, 0x3A);
            WriteReg(0x71, 0x35);
            WriteReg(0x72, 0x22);
            WriteReg(0x73, 0xf2);
            WriteReg(0xA2, 0x02);
        }else{                                  // RGB565
            WriteReg(REG_COM7,0x04);            // RGB + color bar disable 
            WriteReg(REG_RGB444, 0x00);         // Disable RGB444
            WriteReg(REG_COM15, 0xD0);          // Set rgb565 0xD0 or rgb555 0xD8 
            WriteReg(REG_COM3, 0x04);
            WriteReg(REG_COM14, 0x1a);          // by 4
            WriteReg(0x70, 0x3A);
            WriteReg(0x71, 0x35);
            WriteReg(0x72, 0x22);
            WriteReg(0x73, 0xf2);
            WriteReg(0xA2, 0x02);
        }
         
    // COLOR SETTING
    
    WriteReg(REG_COM8,0x8F);        // AGC AWB AEC Enab
    WriteReg(REG_BRIGHT,0x00);      // 0x00(Brightness 0) - 0x18(Brightness +1) - 0x98(Brightness -1)

    WriteReg(MTX1,0x80);
    WriteReg(MTX2,0x80);
    WriteReg(MTX3,0x00);
    WriteReg(MTX4,0x22);
    WriteReg(MTX5,0x5e);
    WriteReg(MTX6,0x80);
    WriteReg(REG_CONTRAS,0x40);     // 0x40(Contrast 0) - 0x50(Contrast +1) - 0x38(Contrast -1)
    WriteReg(MTXS,0x9e);
    WriteReg(AWBC7,0x88);
    WriteReg(AWBC8,0x88);
    WriteReg(AWBC9,0x44);
    WriteReg(AWBC10,0x67);
    WriteReg(AWBC11,0x49);
    WriteReg(AWBC12,0x0e);
    WriteReg(REG_GFIX,0x00);
    WriteReg(GGAIN,0x40);
    WriteReg(DBLV,0x0a);
    WriteReg(AWBCTR3,0x0a);
    WriteReg(AWBCTR2,0x55);
    WriteReg(AWBCTR1,0x11);
    WriteReg(AWBCTR0,0x9f);

    WriteReg(0xb0,0x84);
    
    return 1;
}    

// vsync handler
void OV7670::VsyncHandler(void)
{
    
    // Capture Enable
    if (CaptureReq) {
        wen = 1 ;
        Done = false ;
        CaptureReq = false ;
    } else {
        wen = 0 ;
        if (Busy) {
            Busy = false ;
            Done = true ;
        }
    }
    
    // Hline Counter
    LastLines = LineCounter ;
    LineCounter = 0 ;
}

// href handler
void OV7670::HrefHandler(void)
{
    LineCounter++ ;
}

// Data Read
int OV7670::ReadOnebyte(void)
{
        int B1;
        rclk = 1;
        B1 = (((data&0x07800000)>>19)|((data&0x078000)>>15));
        //B1 = data;                  // BusIn data(d0,d1,d2,d3,d4,d5,d6,d7)
        rclk = 0;
        return B1; 
}

// Data Start read from FIFO
void OV7670::ReadStart(void)
{        
    rrst = 0 ;
    oe = 0 ;
    wait_us(1) ;
    rclk = 0 ;
    wait_us(1) ;
    rclk = 1 ;
    wait_us(1) ;        
    rrst = 1 ;
}

// Data Stop read from FIFO
void OV7670::ReadStop(void)
{
    oe = 1 ;
    ReadOnebyte() ;
    rclk = 1 ;
}