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

uCam.cpp

Committer:
ms523
Date:
2012-05-29
Revision:
0:68395cd065e4

File content as of revision 0:68395cd065e4:

#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);
}