OV7670 + 23LC1024 + Bluetooth

Dependencies:   FastPWM MODSERIAL mbed

Files at this revision

API Documentation at this revision

Comitter:
sampullman
Date:
Tue Jul 23 06:33:27 2013 +0000
Parent:
0:f309a2b2f27b
Child:
2:a7f5fa80a385
Commit message:
Implemented image streaming client protocol. Single image works, but fails to send subsequent frames.

Changed in this revision

Constants.h Show annotated file Show diff for this revision Revisions of this file
MODSERIAL.lib Show annotated file Show diff for this revision Revisions of this file
OC7670.cpp Show annotated file Show diff for this revision Revisions of this file
OV7670.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
spi_ram/spi_ram.cpp Show annotated file Show diff for this revision Revisions of this file
spi_ram/spi_ram.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Constants.h	Tue Jul 23 06:33:27 2013 +0000
@@ -0,0 +1,15 @@
+#define TAPCAM_ID 0xA7
+
+/* Bluetooth camera API commands */
+#define REQUEST_PROFILE     5
+#define CLIENT_PROFILE      6
+#define TAKE_PICTURE        7
+#define IMAGE_READ          8
+#define FRAME_READ          9
+#define FEED_REQUEST        10
+#define FEED_CANCEL         11
+#define FEED_START          12
+#define FEED_START_ACK      13
+#define FEED_STOP           14
+
+#define ORIENTATION         "0\n"   // Camera orientation (0 = not rotated)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Tue Jul 23 06:33:27 2013 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/AjK/code/MODSERIAL/#ae0408ebdd68
--- a/OC7670.cpp	Mon Jul 22 23:55:34 2013 +0000
+++ b/OC7670.cpp	Tue Jul 23 06:33:27 2013 +0000
@@ -11,15 +11,13 @@
     PortName port, // 8bit bus port
     int mask // 0000 0111 4000 0111 1000 0000 0000 0000 = 0x07878000
     
-    ) : camera(sda,scl), data(port, mask), inPort(Port2, 0x0000001C)
+    ) : camera(sda,scl), data(port, mask), inPort(Port2, 0x0000001C),  spi(p5, p6, p7), ram(spi, p8)
 {
     camera.stop();
     camera.frequency(OV7670_I2CFREQ);
-    CaptureReq = false;
-    Busy = false;
-    Done = false;
-    LineCounter = 0;
     xclkPin = xclk;
+    spi.frequency(16000000);
+    size = 0;
 }
 
 void OV7670::Init() {
@@ -114,6 +112,7 @@
     WriteReg(0x6f,0x9f);
 
     WriteReg(0xb0,0x84);
+    size = 160 * 120 * 2;
 }
 
 void OV7670::scopeTest(Serial *host) {
@@ -135,10 +134,12 @@
     //printf("Avg on, off = %d, %d\n\r", t1.read_us()/100, t2.read_us()/100);
 }
 
-int OV7670::captureImage(unsigned char *arr1, unsigned char* arr2) {
+int OV7670::captureImage() {
     int d, i=0;
     int byte = 0;
     Timer t1;
+    // Prepare SRAM output
+    ram.startWriteSequence();
     // Read in the first half of the image
     while(inPort & 0x00000008) {};    // Wait for VSYNC low
     while(!(inPort & 0x00000008)) {}; // Wait for VSYNC high
@@ -154,17 +155,38 @@
             d = data;
             byte  = (d & 0x07800000) >> 19; // bit26 to bit7
             byte |= (d & 0x00078000) >> 15; // bit18 to bit3
-            arr1[i] = byte;
+            //arr1[i] = byte;
+            ram.writeSequence1(byte);
             while(inPort & 0x00000010) {};        // Wait for PCLK low
             while(!(inPort & 0x00000010)) {};  // Wait for PCLK high
             d = data;
             byte  = (d & 0x07800000) >> 19; // bit26 to bit7
             byte |= (d & 0x00078000) >> 15; // bit18 to bit3
-            arr2[i++] = byte;
+            ram.writeSequence1(byte);
+            //arr2[i++] = byte;
             while(inPort & 0x00000010) {}; 
+            i++;
         }
     }
+    //t1.stop();
+    ram.stopSequence();
     //printf("Image read: %d\n\r", t1.read_us());
     return i*2;
 }
+
+
+void OV7670::sendImage(Serial *dest, int numBytes) {
+    Timer t;
+    Serial host = *dest;
+    // Write the image to the serial host
+    ram.startReadSequence();
+    t.start();
+    for (int i = 0; i < numBytes; i++) {
+        while(!(host.writeable())) {}
+        host.putc(ram.readSequence1());
+    }
+    t.stop();
+    printf("BT time: %d\n\r", t.read_us());
+    ram.stopSequence();
+}
     
\ No newline at end of file
--- a/OV7670.h	Mon Jul 22 23:55:34 2013 +0000
+++ b/OV7670.h	Tue Jul 23 06:33:27 2013 +0000
@@ -1,6 +1,7 @@
 #include "mbed.h"
 #include "OV7670reg.h"
 #include "FastPWM.h"
+#include "spi_ram.h"
  
 #define OV7670_WRITE (0x42)
 #define OV7670_READ  (0x43)
@@ -17,11 +18,9 @@
     I2C camera;
     PinName xclkPin;
     PortIn data, inPort;
-    volatile int LineCounter;
-    volatile int LastLines;
-    volatile bool CaptureReq;
-    volatile bool Busy;
-    volatile bool Done;    
+    SPI spi;
+    SRAM ram;
+    int size;
         
     OV7670(
         PinName sda, // Camera I2C port
@@ -49,7 +48,9 @@
 
     void scopeTest(Serial *host);
 
-    // Capture image in two arrays. Returns number of bytes received
-    int captureImage(unsigned char *arr1, unsigned char* arr2);
+    // Capture image to external SRAM. Returns number of bytes received
+    int captureImage();
+    
+    void sendImage(Serial *dest, int numBytes);
  
 };
\ No newline at end of file
--- a/main.cpp	Mon Jul 22 23:55:34 2013 +0000
+++ b/main.cpp	Tue Jul 23 06:33:27 2013 +0000
@@ -1,6 +1,9 @@
 #include "mbed.h"
+#include "Constants.h"
 #include "OV7670.h"
 #include "FastPWM.h"
+#include "spi_ram.h"
+#include "MODSERIAL.h"
 
 #define SIZEX (160)
 #define SIZEY (120)
@@ -12,10 +15,9 @@
     Port0, 0x07878000); // D0-D7 -> P11-p18
     
 Serial host(USBTX, USBRX);
+MODSERIAL bt(p9, p10, 16384, 512);
 DigitalOut status(p20);
-
-unsigned char bank0[SIZE];
-unsigned char *bank1 = (unsigned char *)(0x2007C000);
+int feedMode = 0;
 
 int hexToInt(int i) {
     if(i >= '0' && i <= '9') return i - '0';
@@ -29,18 +31,21 @@
     return (hexToInt(b1) << 4) | hexToInt(b2);
 }
 
-void sendImage() {
-    // Write the image to the serial host
-    for (int i = 0; i < SIZE; i++) {
-        while(!(host.writeable())) {}
-        host.putc(bank0[i]);
-        while(!(host.writeable())) {}
-        host.putc(bank1[i]);
+void readLine(Serial *ser, char *data) {
+    int i=0;
+    char c = '0';
+    while(c != '\n') {
+        if(ser->readable()) {
+            c = ser->getc();
+            data[i++] = c;
+        }
     }
+    data[i] = '\0';
 }
 
 int main() {
     host.baud(115200);
+    bt.baud(230400);
     
     // Initialize a 12Mhz XCLK for the camera
     camera.Init();
@@ -52,28 +57,73 @@
     camera.InitQQVGA();
 
     char c;
+    char data[20];
     while(1) {
+        if(bt.readable()) {
+            c = bt.getc();
+            switch(c) {
+                case REQUEST_PROFILE:
+                    host.printf("Profile requested\n\r");
+                    bt.putc(CLIENT_PROFILE);
+                    bt.putc((TAPCAM_ID >> 4) & 0x0F);
+                    bt.putc(TAPCAM_ID & 0x0F);
+                    bt.printf("device\n");
+                    break;
+                case CLIENT_PROFILE: {
+                    host.printf("Client profile:\n\r");
+                    int id = bt.getc() << 4;
+                    id |= bt.getc();
+                    readLine(&bt, data);
+                    host.printf("ID: %d\n\r", id);
+                    host.printf("Type: %s\n\r", data);
+                    break;
+                }
+                case FEED_REQUEST:
+                    host.printf("Feed requested\n\r");
+                    bt.putc(FEED_START);
+                    break;
+                case FEED_START_ACK:
+                    host.printf("Feed start acknowledged\n\r");
+                    feedMode = 1;
+                    break;
+                case FEED_CANCEL:
+                    host.printf("Feed canceled\n\r");
+                    feedMode = 0;
+                    break;
+            }
+        }
+        if(feedMode) {
+            int bytes = camera.captureImage();
+            bt.putc(FRAME_READ);
+            bt.printf(ORIENTATION);
+            bt.printf("%d\n", bytes);
+            camera.sendImage(&bt, bytes);
+            host.printf("Sent %d\n\r", bytes);
+            wait_ms(100);
+        }
         if(host.readable()) {
             c = host.getc();
-        } else {
-            continue;
-        }
-        if(c == 'r') {
-            int reg = getHexWord(&host);
-            host.printf("%d\n\r", camera.ReadReg(reg));
-        } else if(c == 'w') {
-            int reg = getHexWord(&host);
-            int val = getHexWord(&host);
-            camera.WriteReg(reg, val);
-            host.printf("%d\n\r", camera.ReadReg(reg));
-        } else if(c == 't') {
-            camera.scopeTest(&host);
-        } else if(c == 'c') {
-            status = 1;
-            int bytes = camera.captureImage(bank0, bank1);
-            //host.printf("%d\n", bytes);
-            sendImage();
-            status = 0;
+            if(c == 'r') {
+                int reg = getHexWord(&host);
+                host.printf("%d\n\r", camera.ReadReg(reg));
+            } else if(c == 'w') {
+                int reg = getHexWord(&host);
+                int val = getHexWord(&host);
+                camera.WriteReg(reg, val);
+                host.printf("%d\n\r", camera.ReadReg(reg));
+            } else if(c == 't') {
+                camera.scopeTest(&host);
+            } else if(c == 'c') {
+                status = 1;
+                int bytes = camera.captureImage();
+                host.printf("%d\n", bytes);
+                camera.sendImage(&host, bytes);
+                status = 0;
+            } else if(c == 's') {
+                feedMode = false;
+            } else if(c == 'p') {
+                bt.putc(REQUEST_PROFILE);
+            }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spi_ram/spi_ram.cpp	Tue Jul 23 06:33:27 2013 +0000
@@ -0,0 +1,81 @@
+#include "spi_ram.h"
+
+SRAM::SRAM(SPI& spiDef, PinName csiPin) : spi(spiDef), csi(csiPin)  {
+    deselect();
+}
+
+void SRAM::select() {
+    csi = 0;
+}
+
+void SRAM::deselect() {
+    csi = 1;
+}
+
+void SRAM::writeStatus(char status) {
+    select();
+    spi.write(WRITE_STATUS);
+    spi.write(status);
+    deselect();
+}
+ 
+char SRAM::readStatus() {
+    select();
+    spi.write(READ_STATUS);
+    char result = (char)spi.write(0);
+    deselect();
+    return result;
+}
+ 
+void SRAM::prepareCommand(char command, int address) {
+    select();
+    spi.write(command);
+    spi.write(address >> 16);
+    spi.write((address >> 8) & 0xFF);
+    spi.write(address & 0xFF);
+}
+
+void SRAM::startWriteSequence() {
+    select();
+    writeStatus(SEQUENTIAL_MODE);
+    prepareCommand(WRITE, 0);
+}
+
+void SRAM::writeSequence0(char c) {
+    while (!(LPC_SSP0->SR & TNF));       // While TNF-Bit = 0, wait for FIFO
+    LPC_SSP0->DR = c;                // Write to FIFO buffer
+    while( !(LPC_SSP0->SR & RNE));
+    uint8_t v = LPC_SSP0->DR;
+}
+
+void SRAM::writeSequence1(char c) {
+    while (!(LPC_SSP1->SR & TNF));       // While TNF-Bit = 0, wait for FIFO
+    LPC_SSP1->DR = c;                // Write to FIFO buffer
+    while( !(LPC_SSP1->SR & RNE));
+    uint8_t v = LPC_SSP1->DR;
+}
+
+void SRAM::startReadSequence() {
+    select();
+    writeStatus(SEQUENTIAL_MODE);
+    prepareCommand(READ, 0);
+}
+
+char SRAM::readSequence0() {
+    while (!(LPC_SSP0->SR & TNF));       // While TNF-Bit = 0, wait for FIFO
+    LPC_SSP0->DR = 0;                // Write to FIFO buffer
+    while( !(LPC_SSP0->SR & RNE));
+    return LPC_SSP0->DR;
+}
+
+char SRAM::readSequence1() {
+    while (!(LPC_SSP1->SR & TNF));       // While TNF-Bit = 0, wait for FIFO
+    LPC_SSP1->DR = 0;                // Write to FIFO buffer
+    while( !(LPC_SSP1->SR & RNE));
+    return LPC_SSP1->DR;
+}
+
+void SRAM::stopSequence() {
+    deselect();
+    writeStatus(BYTE_MODE);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spi_ram/spi_ram.h	Tue Jul 23 06:33:27 2013 +0000
@@ -0,0 +1,44 @@
+#include "mbed.h"
+
+#ifndef  SPI_RAM_H
+#define  SPI_RAM_H
+
+// Mode codes
+#define BYTE_MODE       0x00
+#define SEQUENTIAL_MODE 0x40
+
+// Command codes
+#define READ            0x03
+#define WRITE           0x02
+#define READ_STATUS     0x05
+#define WRITE_STATUS    0x01
+
+// Underlying SPI constants
+#define TFE             0x02
+#define TNF             0x02
+#define RNE             0x04
+
+class SRAM {
+public:
+
+    SRAM(SPI& spiDef, PinName csiPin);
+
+    char readStatus();
+    void writeStatus(char status);
+    void startWriteSequence();
+    void startReadSequence();
+    void writeSequence0(char c);
+    void writeSequence1(char c);
+    char readSequence0();
+    char readSequence1();
+    void stopSequence();
+
+private:
+    SPI& spi;
+    DigitalOut csi;
+    void prepareCommand(char command, int address);
+    void select();
+    void deselect();
+};
+
+#endif
\ No newline at end of file