A Simple library to capture pictures from the uCam by 4D Systems

Files at this revision

API Documentation at this revision

Comitter:
ms523
Date:
Tue May 29 08:01:20 2012 +0000
Commit message:
Working with external FeRAM. Will require hacking to save the data to other formats of memory

Changed in this revision

uCam.cpp Show annotated file Show diff for this revision Revisions of this file
uCam.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uCam.cpp	Tue May 29 08:01:20 2012 +0000
@@ -0,0 +1,391 @@
+#include "uCam.h"
+#include "mbed.h"
+
+#define DEBUG
+
+// Set up some memory to hold the commands
+const unsigned char SYNC[] = {0xAA, 0x0D, 0x00, 0x00, 0x00, 0x00};
+const unsigned char ACK[] = {0xAA, 0x0E, 0x0D, 0x00, 0x00, 0x00};
+const unsigned char BAUD_115200[] = {0xAA, 0x07, 0x01, 0x0F, 0x00, 0x00};
+const unsigned char BAUD_737280[] = {0xAA, 0x07, 0x00, 0x04, 0x00, 0x00};
+const unsigned char BAUD_921600[] = {0xAA, 0x07, 0x01, 0x01, 0x00, 0x00};
+const unsigned char BAUD_1228800[] = {0xAA, 0x07, 0x02, 0x00, 0x00, 0x00};
+const unsigned char GET_PICTURE[] = {0xAA, 0x04, 0x02, 0x00, 0x00, 0x00};   // take snapshot picture
+
+int picture_size;       // To track the current picture size
+DigitalOut led1(LED1),led2(LED2),led3(LED3),led4(LED4);
+
+uCam::uCam(PinName tx, PinName rx, int buffer)
+        : _uCam(tx,rx,buffer)  {
+
+    // Set the initial baud rate
+    _uCam.baud(115200);
+}
+
+// Waits for an response from the uCam module and checks that a valid ACK was received
+int uCam::Get_Response(unsigned char type, unsigned char command) {
+    // First wait for the uCam module to send the reply or timeout
+    // This waits for the module to become readable or timesout after 50 ms
+    char times = 0;         // Variable to check for timeouts
+    do {
+        wait(0.001);        // Wait 1 ms
+        times++;            // Inc variable
+        if (_uCam.readable())
+            break;
+    } while (times < 100 );
+    // Check if it timed out
+    if (times > 99) {
+        printf("\n\r Response Timeout");
+        return(0);
+    }
+    // Get the reply from the uCam module (will be 6 bytes
+    unsigned char reply[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    for (int i=0; i<6; i++) {
+        reply[i] = _uCam.getc();
+    }
+    // Check reply was valid, A valid ACK should be 0xAA, 0x0E, Command ID, X, 0x00, 0x00
+    if (reply[0] == 0xAA && reply[1] == type && reply[2] == command && reply[4] == 0x00 && reply[5] == 0x00)
+        // It was an ACK so return true
+        return(1);
+    else {
+        // Reply was invalid so print the reply and return false
+        return(0);
+    }
+}
+
+int uCam::Sync() {
+    // This will give 60 attempts to sync with the uCam module
+    for (int i=0; i<=10; i ++) {
+        // Send out the sync command
+        for (int i=0; i<6; i++) {
+            _uCam.putc(SYNC[i]);
+        }
+        // Check if the response was an ACK
+        if (Get_Response(_ACK,SYNC[1])) {
+            // It was an ACK so now get the next response - it should be a sync
+            if (Get_Response(_SYNC,0x00)) {
+                // We need a small delay (1ms) from receiving the SYNC response and sending an ACK in return
+                wait(0.001);
+                for (int i=0; i<6; i++) {
+                    _uCam.putc(ACK[i]);
+                }
+                // Everything is now complete so return true
+                return(1);
+            }
+        }
+        // Wait a while and try again
+        wait(0.01);
+        printf("\n\r Sync failed - trying again");
+    }
+    // Something went wrong so return false
+    return(0);
+}
+
+int uCam::SetBaud(int baud) {
+    // Send out the set baud command
+    for (int i=0; i<6; i++) {
+        // Select the correct data for the desired baud
+        if (baud == 115200)
+            _uCam.putc(BAUD_115200[i]);
+        else if (baud == 737280)
+            _uCam.putc(BAUD_737280[i]);
+        else if (baud == 921600)
+            _uCam.putc(BAUD_921600[i]);
+        else if (baud == 1228800)
+            _uCam.putc(BAUD_1228800[i]);
+    }
+
+    // Check if the response was an ACK
+    if (Get_Response(_ACK,0x07)) {
+        // An ACk was received so we can now set the mbed to the new baud rate
+        _uCam.baud(baud);
+        // New baud rate confirmed - return true
+        return(1);
+    } else
+        // Something went wrong - return false
+        return(0);
+}
+
+int uCam::Initial(unsigned char COLOUR, unsigned char RES) {
+    // Set up a buffer to hold the uCam response
+    unsigned char buf[6] = {0xAA, 0x01, 0x00, COLOUR, 0x00, 0x00};
+
+    //Amend the initial command for the type of image
+    if (buf[3]==0x07) {
+        buf[5] = RES;           // The image is a JPEG so set byte 5
+    } else {
+        buf[4] = RES;           // The image is RAW so set byte 4
+    }
+
+    // Get the number of bytes to be transferred
+    // Start by finding out how many bytes per pixel
+    if (COLOUR == GREY_8BIT || COLOUR == COLOUR_8BIT) {
+        picture_size = 1;
+    } else if (COLOUR == COLOUR_16BIT) {
+        picture_size = 2;
+    }
+    // Then multiply this by the number of pixels
+    if (RES == RAW_80x60)
+        picture_size = picture_size*80*60;
+    else if (RES == RAW_160x120)
+        picture_size = picture_size*160*120;
+    else if (RES == RAW_320x240)
+        picture_size = picture_size*320*240;
+    else if (RES == RAW_640x480)
+        picture_size = picture_size*640*480;
+    else if (RES == RAW_128x128)
+        picture_size = picture_size*128*128;
+    else if (RES == RAW_128x96)
+        picture_size = picture_size*128*96;
+
+    // Send out the initial command
+    for (int i=0; i<6; i++) {
+        _uCam.putc(buf[i]);
+    }
+
+    // Check for ACK
+    if (Get_Response(_ACK,0x01)) {
+        // An ACk was received - return true
+        return(1);
+    } else {
+        // Something went wrong - return false
+        return(0);
+    }
+}
+
+int uCam::Get_Picture(unsigned char *data) {
+
+    // Send out the get picture command
+    for (int i=0; i<6; i++) {
+        _uCam.putc(GET_PICTURE[i]);
+    }
+
+    if (!Get_Response(_ACK,0x04))
+        // Something went wrong
+        return(0);
+
+    // Get response from uCam
+    for (int i=0; i<picture_size; i++) {
+        if (_uCam.readable())
+            data[i] = _uCam.getc();
+        else {
+            i--;
+        }
+    }
+
+    // We need a small delay (1ms) from receiving the SYNC response and sending an ACK in return
+    wait(0.001);
+    for (int i=0; i<6; i++) {
+        _uCam.putc(ACK[i]);
+    }
+    // Everything is now complete so return true
+    return(1);
+}
+
+int uCam::Save_Picture_To_Memory(FeRAM &flash, int address) {
+    // Variables
+    unsigned char buf[6];       // Buffer to save data from uCam before its written to flash
+    int length;                 // The length of the incoing data (sent in data packet from uCam)
+    char binned = 0;            // Escape variable to break out of function if some data isn't sent from uCam
+    Timer bin;                  // Timer to see if uCam has hung
+
+    Timer t;
+    t.start();
+
+    // Send out the get picture command
+    for (int i=0; i<6; i++) {
+        _uCam.putc(GET_PICTURE[i]);
+    }
+
+    if (!Get_Response(_ACK,0x04))
+        // Something went wrong
+        return(0);
+#ifdef DEBUG
+    printf("\n Getting picture");
+#endif
+    // Get the first 6 bytes
+    // Format 0xAA 0x0A (Data command), Data type, 3 bytes to show length
+    for (int i=0; i<6; i++) {
+        while (!_uCam.readable()) {
+            wait_us(1);
+        }
+        buf[i] = _uCam.getc();      // Get a byte of data
+    }
+    length = (buf[5] << 16) + (buf[4] << 8) + buf[3];
+
+    // Get response from uCam and save to flash
+    bin.start();
+    for (int i=0; i<length; i++) {
+#ifdef DEBUG
+        // See where we are...
+        if (i>length/4)
+            led1 = 1;
+        if (i>length/2)
+            led2 = 1;
+        if (i>length*3/4)
+            led3 = 1;
+#endif
+        // reset the timer
+        bin.reset();
+
+        while (!_uCam.readable()) {
+#ifdef DEBUG
+            led4 = 1;   // Turn LED on to show we're waiting
+#endif
+            // Check to see if we have been waiting for more than 10 ms
+            if (bin.read() > 0.01) {
+                printf("\n binned at %d",i);
+                binned = 1;
+                break;
+            }
+        }
+#ifdef DEBUG
+        led4 = 0;                           // Turn LED off again
+#endif
+
+        // If this if statement runs than it means the uCam module has hung
+        if (binned) {
+            for (; i<length; i++) {
+                flash.write_byte(i + address, 0x00);       // Fill the remaining bytes with 0x00
+            }
+            break;                          // This breaks out of the loop and writes an ACk back to uCam
+        }
+
+        // uCam has a byte of data ready to read - so go get it!
+        flash.write_byte(i + address, _uCam.getc());
+
+    }
+    // All data has been received so send an ACK back to the uCam module
+    _uCam.putc(0xAA);
+    _uCam.putc(0x0E);
+    _uCam.putc(0x0A);
+    _uCam.putc(0x00);
+    _uCam.putc(0x01);
+    _uCam.putc(0x00);
+
+#ifdef DEBUG
+    t.stop();
+    //printf("\n Finished in %.3f Secs",t.read());
+
+    // Turn all the LEDs off
+    led1 = led2 = led3 = led4 = 0;
+#endif
+
+    // Everything is now complete so return true
+    return(1);
+}
+
+int uCam::Save_Zoom_Picture_To_Memory(FeRAM &flash, int address){
+    // Variables
+    unsigned char buf[6];       // Buffer to save data from uCam before its written to flash
+    unsigned char dummy;        // Byte to read in unwanted info
+    int length;                 // The length of the incoing data (sent in data packet from uCam)
+    int pos = 0;
+    char binned = 0;            // Escape variable to break out of function if some data isn't sent from uCam
+    Timer bin;                  // Timer to see if uCam has hung
+
+    Timer t;
+    t.start();
+
+    // Send out the get picture command
+#ifdef DEBUG
+    printf("\n\n\n\n\n\n\n\n\n\n");
+#endif
+    for (int i=0; i<6; i++) {
+        _uCam.putc(GET_PICTURE[i]);
+        #ifdef DEBUG
+            printf("[%X],",GET_PICTURE[i]);
+        #endif
+    }
+
+    if (!Get_Response(_ACK,0x04))
+        // Something went wrong
+        return(0);
+#ifdef DEBUG
+    printf("\n Getting picture \n");
+#endif
+    // Get the first 6 bytes
+    // Format 0xAA 0x0A (Data command), Data type, 3 bytes to show length
+    for (int i=0; i<6; i++) {
+        while (!_uCam.readable()) {
+            wait_us(1);
+        }
+        buf[i] = _uCam.getc();      // Get a byte of data
+        printf("[%2X],",buf[i]);
+    }
+    length = (buf[5] << 16) + (buf[4] << 8) + buf[3];
+#ifdef DEBUG
+    printf("\n Length is: %d \n[%d] [%d] [%d]",length, buf[5], buf[4], buf[3]);
+#endif
+
+    // Get response from uCam and save to flash
+    bin.start();
+    for (int i=0; i<length; i++) {
+#ifdef DEBUG
+        // See where we are...
+        if (i>length/4)
+            led1 = 1;
+        if (i>length/2)
+            led2 = 1;
+        if (i>length*3/4)
+            led3 = 1;
+#endif
+        // reset the timer
+        bin.reset();
+
+        while (!_uCam.readable()) {
+#ifdef DEBUG
+            led4 = 1;   // Turn LED on to show we're waiting
+#endif
+            // Check to see if we have been waiting for more than 10 ms
+            if (bin.read() > 0.01) {
+                printf("\n binned at %d",i);
+                binned = 1;
+                break;
+            }
+        }
+#ifdef DEBUG
+        led4 = 0;                           // Turn LED off again
+#endif
+
+        // If this if statement runs than it means the uCam module has hung
+        if (binned) {
+            for (; i<length; i++) {
+                flash.write_byte(i + address, 0x00);       // Fill the remaining bytes with 0x00
+            }
+            break;                          // This breaks out of the loop and writes an ACk back to uCam
+        }
+
+        // uCam has a byte of data ready to read - so go get it!
+        // Need to check here if I actually want it!
+        if (i < 320 * 60 * 2 || i > 320 * 180 * 2)      // Pixel is too high or low
+            dummy = _uCam.getc();
+        else if (i % 640 < 160)                         // Pixel is too left
+            dummy = _uCam.getc();
+        else if (i % 640 < 160 + 320){                  // Pixel is in the centre - go get it!
+            flash.write_byte(pos + address, _uCam.getc());
+            pos++;
+        } else                                          // Pixel is too right
+            dummy = _uCam.getc();
+         
+
+    }
+    // All data has been received so send an ACK back to the uCam module
+    _uCam.putc(0xAA);
+    _uCam.putc(0x0E);
+    _uCam.putc(0x0A);
+    _uCam.putc(0x00);
+    _uCam.putc(0x01);
+    _uCam.putc(0x00);
+
+#ifdef DEBUG
+    t.stop();
+    //printf("\n Finished in %.3f Secs",t.read());
+
+    // Turn all the LEDs off
+    led1 = led2 = led3 = led4 = 0;
+#endif
+
+    // Everything is now complete so return true
+    return(1);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uCam.h	Tue May 29 08:01:20 2012 +0000
@@ -0,0 +1,61 @@
+#ifndef __UCAM_H__
+#define __UCAM_H__
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+#include "FeRAM.h"
+
+// Define colours
+#define GREY_2BIT 0x01
+#define GREY_4BIT 0x02
+#define GREY_8BIT 0x03
+#define COLOUR_8BIT 0x04
+#define COLOUR_12BIT 0x05
+#define COLOUR_16BIT 0x06
+#define JPEG 0x07
+// Define RAW formats
+#define RAW_80x60 0x01
+#define RAW_160x120 0x03
+#define RAW_320x240 0x05
+#define RAW_640x480 0x07
+#define RAW_128x128 0x09
+#define RAW_128x96 0x0B
+// Define JPEG formats
+#define JPEG_60x64 0x01
+#define JPEG_160x128 0x03
+#define JPEG_320x240 0x05
+#define JPEG_640x480 0x07
+// Define uCam responses
+#define _ACK 0x0E
+#define _SYNC 0x0D
+
+// mode codes for 23K256
+#define BYTE_MODE       0x00
+#define SEQUENTIAL_MODE 0x40
+
+// command codes for 23K256
+#define READ            0x03
+#define WRITE           0x02
+#define READ_STATUS     0x05 // called RDSR in datasheet
+#define WRITE_STATUS    0x01 // called WRSR in datasheet
+
+class uCam {
+public:
+    // define which pins are used
+    uCam(PinName tx, PinName rx, int buffer);
+
+    // Methods
+    int Sync();
+    int SetBaud(int baud);
+    int Initial(unsigned char COLOUR, unsigned char RES);
+    int Get_Picture(unsigned char *data);
+    int Get_Response(unsigned char type, unsigned char command);
+    int Save_Picture_To_Memory(FeRAM &flash, int address);
+    int Save_Zoom_Picture_To_Memory(FeRAM &flash, int address);
+    
+private:
+    MODSERIAL _uCam;    // uCam TX and RX
+    
+};
+
+#endif
\ No newline at end of file