Oliver Hicks / Mbed 2 deprecated mbed_camera

Dependencies:   mbed

camera.cpp

Committer:
ollyhicks
Date:
2014-05-23
Revision:
0:78595d38d985

File content as of revision 0:78595d38d985:

#include "camera.h"

/* 
 * Links
 * https://gist.github.com/franciscospaeth/8503747
 * http://embeddedprogrammer.blogspot.co.uk/2012/07/hacking-ov7670-camera-module-sccb-cheat.html
 * http://www.voti.nl/docs/OV7670.pdf
 */

BusIn data_p(p17,p18,p15,p16,p13,p14,p11,p12);

PwmOut xclock_p(p21);
DigitalIn pclock_p(p8);
DigitalIn href_p(p5);
DigitalIn vsync_p(p6);

DigitalOut pwdn_p(p19);
DigitalOut reset_p(p20);

I2C i2c(p9, p10);   //sda,scl

void camera_setup() {
    pwdn_p.write(0);
    reset_p.write(1); // The reset pin must be HIGH! (3v3)
    
    /*
     * Make camera xclk using PWM
     *
     * Note the this is 1Mhz, the datasheet specifies a minimum of 26Mhz.
     * Reports online state that 10Mhz works, but if you're having issues 
     * try 26Mhz as we don't understand the side affects.
     */
    xclock_p.period(CAMERA_CLK_PERIOD);
    xclock_p = 0.5;
     
    // i2c
    i2c.stop() ;
    i2c.frequency(CAMERA_I2C_FREQ); // must be slow
    wait(0.1);
    
    /*
     * Set to QCIF (176 x 144)
     * Note that CAMERA_W and CAMERA_H must also be changed so
     * that the buffers are the correct length
     */
    camera_set_output_format(CAMERA_I2C_OF_QCIF);
    
    /*
     * Set PCLK frequency slow enough for us to read and save the data (larger = slower)
     * Maximum 65 = (2^6 - 1) see datasheet for CLKRC
     */
    camera_set_freq_scaler(32);
}

void camera_set_freq_scaler(int prescaler) {
    camera_i2c_write(CAMERA_I2C_REG_CLKRC, prescaler);
}

void camera_set_output_format(int output_format) {
    camera_i2c_write(CAMERA_I2C_REG_COM3, 0x08); // enable scaling
    camera_i2c_write(CAMERA_I2C_REG_COM7, output_format);
}

/**
 * Grab a single frame from the camera and save to the file
 */
void camera_grab(FILE *fp) {    
    char href, vsync;
        
    int x = 0; // col
    int y = 0; // row
    long n = 0; //  px number
    
    // Write one row of pixels to the file at a time, so store the row in a buffer
    char row_buffer[CAMERA_W * CAMERA_BPX];
    
    // http://3.bp.blogspot.com/-cjOYTMj4C4M/UA2kV-db8GI/AAAAAAAAAPs/rtCGSIGjOHo/s1600/vga.png
    
    // Wait until the end of the previous frame
    wait_negedge(vsync_p);
    
    // Start of the frame
    while(1) {
        // Each row
        
        // Wait until the start of a row or the end of a frame
        do {
            href = href_p.read();
            vsync = vsync_p.read();
        } while(href == 0 && vsync == 0);
        
        // Vsync high, thus the end of the frame
        if(vsync == 1){
            // Print the current x, y and n
            // These indicate how many pixels where actually captured
            printf("y: %d\r\n", y);
            printf("x: %d\r\n", x);
            printf("n: %ld\r\n", n);
            return; // is the end of a frame
        }
        // else carry on (href = 1)
        
        x = 0;
        
        /*
         * Note we must sample at the rising edge of the PCLK,
         * but we must also read the href to check that the frame
         * has not ended.
         * http://2.bp.blogspot.com/-K-OIuy-inUU/UA2gp3SYgYI/AAAAAAAAAPg/Gure3RWI8G4/s1600/href.png
         */
        
        wait_posedge(pclock_p);
        
        while(href_p.read() == 1) {
            // Each column
            
            // sample at the rising edge of the PCLK signal
            
            row_buffer[x] = data_p.read();
            
            n++;
            x++;
            
            // Wait until next rising edge so that when the href read is done it has changed
            wait_posedge(pclock_p);
        }
        
        // Write row buffer to the flash
        fwrite(row_buffer, sizeof(char), sizeof(row_buffer), fp);
        
        
        y++;
    }
    
}

int camera_i2c_read(int addr) { 
    int data=0;
    
    // Address
    i2c.start();
    i2c.write(CAMERA_I2C_WRITE_ADDR);
    i2c.write(addr);
    
    // Not sure why we must stop the i2c bus?
    i2c.stop();
    
    wait_us(50);
        
    // Data
    i2c.start();
    i2c.write(CAMERA_I2C_READ_ADDR);
    data = i2c.read(CAMERA_I2C_NOACK) ;
    i2c.stop();
    
    wait_us(50);
    return data;
}

void camera_i2c_write(int addr, int val) { 
    i2c.start();
    
    i2c.write(CAMERA_I2C_WRITE_ADDR);
    i2c.write(addr);
    
    i2c.write(val);
    
    i2c.stop();
    
    wait_us(50);
}

void wait_posedge(DigitalIn pin) {
    while(pin.read() == 1) {};
    while(pin.read() == 0) {};
}

void wait_negedge(DigitalIn pin) {
    while(pin.read() == 0) {};
    while(pin.read() == 1) {};
}