Oliver Hicks / Mbed 2 deprecated mbed_camera

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
ollyhicks
Date:
Fri May 23 20:48:07 2014 +0000
Commit message:
Sort of working (terrible image)

Changed in this revision

camera.cpp Show annotated file Show diff for this revision Revisions of this file
camera.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camera.cpp	Fri May 23 20:48:07 2014 +0000
@@ -0,0 +1,181 @@
+#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) {};
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camera.h	Fri May 23 20:48:07 2014 +0000
@@ -0,0 +1,52 @@
+#include "mbed.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
+ */
+
+#define CAMERA_W 176
+#define CAMERA_H 144
+#define CAMERA_BPX 2 // bits per pixel
+#define CAMERA_CLK_PERIOD 1e-6
+
+#define CAMERA_I2C_FREQ 40000
+#define CAMERA_I2C_READ_ADDR 0x43
+#define CAMERA_I2C_WRITE_ADDR 0x42
+#define CAMERA_I2C_NOACK 0
+#define CAMERA_I2C_REGMAX 201
+
+
+#define CAMERA_I2C_REG_COM3 0x0C
+#define CAMERA_I2C_REG_COM4 0x0D
+#define CAMERA_I2C_REG_COM5 0x0E
+#define CAMERA_I2C_REG_COM6 0x0F
+#define CAMERA_I2C_REG_AECH 0x10
+#define CAMERA_I2C_REG_CLKRC 0x11
+#define CAMERA_I2C_REG_COM7 0x12
+#define CAMERA_I2C_REG_COM8 0x13
+#define CAMERA_I2C_REG_COM9 0x14
+#define CAMERA_I2C_REG_COM10 0x15
+#define CAMERA_I2C_REG_COM11 0x3B
+#define CAMERA_I2C_REG_COM12 0x3C
+#define CAMERA_I2C_REG_COM13 0x3D
+#define CAMERA_I2C_REG_COM14 0x3E
+
+#define CAMERA_I2C_OF_CIF 32
+#define CAMERA_I2C_OF_QVGA 16
+#define CAMERA_I2C_OF_QCIF 8 // 176 x 144
+#define CAMERA_I2C_OF_RGB 4
+#define CAMERA_I2C_OF_YUV 0
+
+void camera_setup();
+int camera_i2c_read(int addr);
+void camera_i2c_write(int addr, int val);
+void camera_set_freq_scaler(int prescaler);
+void camera_set_output_format(int output_format);
+void camera_grab(FILE *fp);
+
+
+void wait_posedge(DigitalIn pin);
+void wait_negedge(DigitalIn pin);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri May 23 20:48:07 2014 +0000
@@ -0,0 +1,24 @@
+#include "mbed.h"
+#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
+ */
+
+LocalFileSystem local("local");
+
+int main() {
+    printf("\r\n\n\nSetup camera\r\n");
+    camera_setup();
+    printf("   Done!\r\n");
+    
+    
+    printf("Take photo\r\n");
+    FILE *fp = fopen("/local/img", "w");
+    camera_grab(fp);
+    fclose(fp);
+    printf("   Done!\r\n");
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri May 23 20:48:07 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/0b3ab51c8877
\ No newline at end of file