OV7670 + 23LC1024 + Bluetooth
Dependencies: FastPWM MODSERIAL mbed
Revision 1:6e4d2cff76e8, committed 2013-07-23
- 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
--- /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