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

Revision:
0:68395cd065e4
--- /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