This is an digital video camera program using NKK\'s oLED swtich and 4D Systems\' uCam serial camera. It takes image from the uCam and displays on the IS-C15 switch. Some image processing demos are included. This program uses FatFileSytem, SDFileSystem, and TextLCD library. See http://www.youtube.com/watch?v=fqHTaCRHyQs for how it works. CQ出版社の「mbed/ARM活用事例」第10章シリアル接続カメラと有機ELディスプレイ内蔵スイッチで作るmbedディジタル・カメラの作例です。動作の様子は http://www.youtube.com/watch?v=fqHTaCRHyQs で見れます。

Dependencies:   TextLCD mbed SDFileSystem

ucam.cpp

Committer:
non
Date:
2011-10-13
Revision:
2:0621feb3adf2
Parent:
0:07d02a20d1cc

File content as of revision 2:0621feb3adf2:

/* 4D Systems uCam serial RAW/JPEG camera library
 * Copyright (c) 2011, Noriaki Mitsunaga
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "mbed.h"
#include "ucam.h"

// uCam-TTL commands:
const unsigned char ACK[] = {0xaa, 0x0e, 0x0d, 0, 0, 0};
const unsigned char ACK1[] = {0xaa, 0x0e, 0x0d, 0, 1, 0};
const unsigned char ACK_F0F0_[] = {0xaa, 0x0e, 0, 0, 0xf0, 0xf0};
const unsigned char GETPICTURE_SNAPSHOT[] = {0xaa, 0x04, 0x01, 0, 0, 0};
// const unsigned char GETPICTURE_RAWPREVIEW[] = {0xaa, 0x04, 0x02, 0, 0, 0};
const unsigned char RESET[] = {0xaa, 0x08, 0x01, 0x0, 0x0, 0xff};
const unsigned char SNAPSHOT_JPEG[] = {0xaa, 0x05, 0x00, 1, 0, 0};
const unsigned char SNAPSHOT_RAW[] = {0xaa, 0x05, 0x01, 1, 0, 0};
const unsigned char SYNC[] = {0xaa, 0x0d, 0, 0, 0, 0};

// Send special ACK
void uCam::ACK_F0F0() {
    write(ACK_F0F0_, sizeof(ACK_F0F0_));
}

// Check if buf is valid ACK.
int uCam::checkACK(const unsigned char *buf) {
    if (buf[0] == ACK[0] && buf[1] == ACK[1] && buf[2] == ACK[2]
            && buf[4] == 0 && buf[5] == 0)
        return 1;

    return 0;
}

// Compare buf to SYNC
int uCam::checkSYNC(const unsigned char *buf) {
    if (memcmp(buf, SYNC, sizeof(SYNC)) == 0)
        return 1;

    return 0;
}

// Send a command to uCam via the serial
int uCam::Command(const unsigned char *cmd) {
    // Send the command
    write(cmd, 6);

    // Wait for response
    unsigned char buf[6];
    read(buf, 6);

    // Check ACK
    if (buf[0] == 0xaa && buf[1] == 0x0e
            && buf[2] == cmd[1]
            /* ignore fourth byte */
            && buf[4] == 0 && buf[5] == 0)
        return 1;

    return 0;
}

// Initialize communcation to uCam
int uCam::Init() {
    int i;
    unsigned char buf[12];

    for (i=0; i<60; i ++) {
        // Send SYNC and check the answer
        write(SYNC, sizeof(SYNC));
        if (readT(buf, sizeof(buf)) == 12 && checkACK(buf)) {
            break;
        }
    }
    if (i == 60)      // Too many retries
        return 0;

    // Check SYNC
    if (!checkSYNC(buf+6)) {
        return 0;
    }
    write(ACK, sizeof(ACK));
    return 1;
}

// Set light frequencey (50Hz or 60Hz) to reduce flicker.
int uCam::LightFreq(int f) {
    unsigned char LIGHT[] = {0xaa, 0x13, 0, 0, 0, 0};

    if (f == 50)
        LIGHT[2] = 0x0;
    else if (f == 60)
        LIGHT[2] = 0x1;
    else
        return 0;

    return Command(LIGHT);
}

// Recive data from serial. It blocks until it recieves len bytes.
// buf: recieving buffer
// len: length to recieve
void uCam::read(unsigned char *p, int len) {
    for (; len>0; len--, p++) {
        *p = s->getc();
    }
}

// Recive data from serial with timeout
// buf: recieving buffer
// len: length of the buffer
int uCam::readT(unsigned char *buf, int len) {
    int c = 0;
    unsigned char *q = buf;

    for (int j=0; j<2000; j ++) {
        if (s->readable()) {
            *q = s->getc();
            if (c < len) {
                q ++;
                c ++;
            }
        }
        wait_us(50);
    }

    return c;
}

// Reset uCam
void uCam::Reset() {
    Command(RESET);
}

// Recieve a JPEG image packet. You need to call SnapshotJPEGi() before.
// no: packet number (starts from 0)
// buf: recieving buffer
// pksz: packet size to recieve
int uCam::SnapshotJPEGd(int no, unsigned char *buf, int pksz) {
    unsigned char ACK_[] = {0xaa, 0x0e, 0x00, 0, 0, 0};

    ACK_[4] = no & 0xff;
    ACK_[5] = (no >> 8) & 0xff;

    write(ACK_, sizeof(ACK_));
    read(buf, pksz);

    return 1;
}

// Prepare to recieve a JPEG image.
// Res: resolution of the image (did not work well for 640x480 with uCam-TTL(ov528 version))
// pksz: packet size to recieve
int uCam::SnapshotJPEGi(int Res, int pksz) {
    unsigned char INITIAL[] = {0xaa, 0x01, 0x00, 0x07, 0x01, 0x00};
    unsigned char SET_PACKAGESIZE[] = {0xaa, 0x06, 0x08, 0x00, 0x00, 0x00};
    unsigned char buf[6];

    INITIAL[5] = Res;
    SET_PACKAGESIZE[3] = pksz & 0xff;
    SET_PACKAGESIZE[4] = (pksz >> 8) & 0xff;

    if (!Command(INITIAL))
        return 0;
    if (!Command(SET_PACKAGESIZE))
        return 0;
    if (!Command(SNAPSHOT_JPEG))
        return 0;
    if (!Command(GETPICTURE_SNAPSHOT))
        return 0;

    read(buf, 6);
    if (!(buf[0] == 0xaa && buf[1] == 0x0a && buf[2] == 0x01))
        return 0;

    return buf[5]<<16 | buf[4]<<8 | buf[3]; // return file size
}

// Take a raw image. 
//
// Color: color mode (supporte form 8bit gray, RGB232, or RGB565 only)
// Res: image resolution
// buf: buffer to save the image
int uCam::SnapshotRaw(int Color, int Res, unsigned char *buf) {
    unsigned char INITIAL[] = {0xaa, 0x01, 0x00, 0x00, 0x00, 0x07};

    INITIAL[3] = Color;
    INITIAL[4] = Res;

    if (!Command(INITIAL))
        return 0;
    if (!Command(SNAPSHOT_RAW))
        return 0;
    if (!Command(GETPICTURE_SNAPSHOT))
        return 0;

    read(buf, 6);
    if (!(buf[0] == 0xaa && buf[1] == 0x0a && buf[2] == 0x01))
        return 0;

    // lcd.printf("%d\n", buf[3] + buf[4]<<8 + buf[5]<<16);
    read(buf, buf[5]<<16 | buf[4]<<8 | buf[3] /* 80*60*2*/ );
    write(ACK1, sizeof(ACK1));

    return 1;
}

// Take a raw image. This function crops
// the image while it is recieving data from uCam
//
// Color: color mode (supporte form 8bit gray, RGB232, or RGB565 only)
// Res: image resolution
// x0, y0: top left corner of the cropping area
// w, h: width and height of cropping area
// buf: buffer to save the image
int uCam::SnapshotRawCrop(int Color, int Res,
                          int x0, int y0, int w, int h,
                          unsigned char *buf) {
    unsigned char INITIAL[] = {0xaa, 0x01, 0x00, 0x00, 0x00, 0x07};
    int W = ucam_raw_resolution_w[(Res-1)/2];
    int H = ucam_raw_resolution_h[(Res-1)/2];

    if (Color == UCAM_COLOR_TYPE_RGB565) {
        W *= 2;
        x0 *= 2;
        w *= 2;
    }

    INITIAL[3] = Color;
    INITIAL[4] = Res;

    if (!Command(INITIAL))
        return 0;
    if (!Command(SNAPSHOT_RAW))
        return 0;
    if (!Command(GETPICTURE_SNAPSHOT))
        return 0;

    read(buf, 6);
    if (!(buf[0] == 0xaa && buf[1] == 0x0a && buf[2] == 0x01))
        return 0;

    for (int i=y0*W; i>0; i--) /* Skip */
        s->getc();

    for (int i=h; i>0; i--) {
        for (int j=x0; j>0; j--) /* Skip */
            s->getc();
        read(buf, w);
        buf += w;
        for (int j=W-w-x0; j>0; j--) /* Skip */
            s->getc();
    }
    for (int i=(H-y0-h)*W; i>0; i--) /* Skip */
        s->getc();
    write(ACK1, sizeof(ACK1));

    return 1;
}

// Write <len> characters from p to the serial
void uCam::write(const unsigned char *p, int len) {
    for (; len>0; len--, p++) {
        s->putc(*p);
    }
}