OV7670 Library

Dependents:   OV7670_make

ov7670.cpp

Committer:
edodm85
Date:
2013-03-16
Revision:
1:d82dbad9c06b
Parent:
0:810d59d0b843
Child:
2:354a00023f79

File content as of revision 1:d82dbad9c06b:

#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, int n) 
{
    
    if (ReadReg(REG_PID) != 0x76)       // check id camera
    {
        return 0;
    }
    
    Reset();                                // Resets all registers to default values
    Reset();                                // Resets all registers to default values
    
    WriteReg(REG_RGB444, 0x00);             // Disable RGB444
    WriteReg(REG_COM10,0x02);               // 0x02   VSYNC negative (http://nasulica.homelinux.org/?p=959)
    WriteReg(REG_MVFP,0x27);                // mirror image 

    WriteReg(REG_CLKRC,0x80);               // prescaler x1     
    WriteReg(DBLV,0x0a);                    // bypass PLL 
        
    WriteReg(REG_COM11,0x0A) ;
    WriteReg(REG_TSLB,0x04);                // 0D = UYVY  04 = YUYV     
    WriteReg(REG_COM13,0x88);               // connect to REG_TSLB
    
        
    if(c == 'b' || c == 'y')     // YUV
    {
        WriteReg(REG_COM7, 0x00);           // YUV
        WriteReg(REG_COM17, 0x00);          // color bar disable
        WriteReg(REG_COM3, 0x04);
        WriteReg(REG_COM15, 0xC0);          // Set normal rgb with Full range

    }else
    if(c == 'r')                // RGB565
    {                                       
        WriteReg(REG_COM7, 0x04);           // RGB + color bar disable 
        WriteReg(REG_RGB444, 0x00);         // Disable RGB444
        WriteReg(REG_COM15, 0x10);          // Set rgb565 with Full range    0xD0
        WriteReg(REG_COM3, 0x04);
        WriteReg(REG_CLKRC,0x80);           // prescaler x1 
    }
      
    WriteReg(0x70, 0x3A);                   // Scaling Xsc
    WriteReg(0x71, 0x35);                   // Scaling Ysc
    WriteReg(0xA2, 0x02);                   // pixel clock delay

    if(n == 19200)              // 160*120
    {
        WriteReg(REG_COM14, 0x1a);          // divide by 4
        WriteReg(0x72, 0x22);               // downsample by 4
        WriteReg(0x73, 0xf2);               // divide by 4
        WriteReg(REG_HSTART,0x16);
        WriteReg(REG_HSTOP,0x04);
        WriteReg(REG_HREF,0xa4);           
        WriteReg(REG_VSTART,0x02);
        WriteReg(REG_VSTOP,0x7a);
        WriteReg(REG_VREF,0x0a);         
    }    
    if(n == 76800)              // 320*240
    {
        WriteReg(REG_COM14, 0x19);         
        WriteReg(0x72, 0x11);
        WriteReg(0x73, 0xf1);
        WriteReg(REG_HSTART,0x16);
        WriteReg(REG_HSTOP,0x04);
        WriteReg(REG_HREF,0x24);            
        WriteReg(REG_VSTART,0x02);
        WriteReg(REG_VSTOP,0x7a);
        WriteReg(REG_VREF,0x0a);
    }
    if(n == 307200)             // 640*480    
    { 
        WriteReg(REG_COM3,0x00);    // REG_COM3 
        WriteReg(0x3e,0x00);        //  REG_COM14
        WriteReg(0x72,0x11);        //
        WriteReg(0x73,0xf0);        //
          
        WriteReg(0x32,0xb6);        // HREF   
        WriteReg(0x17,0x13);        // HSTART
        WriteReg(0x18,0x01);        // HSTOP
        WriteReg(0x19,0x02);        // VSTART
        WriteReg(0x1a,0x7a);        // VSTOP
        WriteReg(0x03,0x0a);        // VREF
        WriteReg(0x70, 0x3a);       // Scaling Xsc
        WriteReg(0x71, 0x35);       // Scaling Ysc
        WriteReg(0xA2, 0x02);       // pixel clock delay

        WriteReg(REG_COM1, 0x00);                 
    }
      
    
    // COLOR SETTING
          
    WriteReg(REG_COM8,0x8F);        // AGC AWB AEC Enab
    WriteReg(0xAA,0x14);            // Average-based AEC algorithm
    WriteReg(REG_BRIGHT,0x00);      // 0x00(Brightness 0) - 0x18(Brightness +1) - 0x98(Brightness -1)
    WriteReg(REG_CONTRAS,0x40);     // 0x40(Contrast 0) - 0x50(Contrast +1) - 0x38(Contrast -1)
    WriteReg(0xB1,0xB1);            // Automatic Black level Calibration
    
    WriteReg(MTX1,0x80);        
    WriteReg(MTX2,0x80);      
    WriteReg(MTX3,0x00);        
    WriteReg(MTX4,0x22);        
    WriteReg(MTX5,0x5e);        
    WriteReg(MTX6,0x80);        
    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(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));
        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 ;
}