CameraC328

Dependents:   CameraC328_TestProgram CameraC328_Thresholding Camera_TestProgram_2015 Camera_TestProgram_2015 ... more

Files at this revision

API Documentation at this revision

Comitter:
shintamainjp
Date:
Wed Oct 13 10:45:29 2010 +0000
Parent:
14:640f564075af
Commit message:

Changed in this revision

CameraC328.cpp Show annotated file Show diff for this revision Revisions of this file
CameraC328.h Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.cpp Show annotated file Show diff for this revision Revisions of this file
SerialBuffered.h Show annotated file Show diff for this revision Revisions of this file
extlib/FATFileSystem.lib Show diff for this revision Revisions of this file
extlib/SDFileSystem.lib Show diff for this revision Revisions of this file
main.cpp Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
diff -r 640f564075af -r 49cfda6c547f CameraC328.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CameraC328.cpp	Wed Oct 13 10:45:29 2010 +0000
@@ -0,0 +1,720 @@
+/**
+ * C328-7640 device driver class (Version 0.0.6)
+ * Reference documents: C328-7640 User Manual v3.0 2004.8.19
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#include "CameraC328.h"
+
+#define WAITIDLE    waitIdle
+#define SENDFUNC    sendBytes
+#define RECVFUNC    recvBytes
+#define WAITFUNC    waitRecv
+
+/**
+ * Constructor.
+ *
+ * @param tx A pin for transmit.
+ * @param rx A pin for receive.
+ * @param baud Baud rate. (Default is Baud19200.)
+ */
+CameraC328::CameraC328(PinName tx, PinName rx, Baud baud) : serial(tx, rx) {
+    serial.baud((int)baud);
+}
+
+/**
+ * Destructor.
+ */
+CameraC328::~CameraC328() {
+}
+
+/**
+ * Make a sync. for baud rate.
+ */
+CameraC328::ErrorNumber CameraC328::sync() {
+    WAITIDLE();
+
+    for (int i = 0; i < SYNCMAX; i++) {
+        if (NoError == sendSync()) {
+            if (NoError == recvAckOrNck()) {
+                if (NoError == recvSync()) {
+                    if (NoError == sendAck(0x0D, 0x00)) {
+                        /*
+                         * After synchronization, the camera needs a little time for AEC and AGC to be stable.
+                         * Users should wait for 1-2 seconds before capturing the first picture.
+                         */
+                        wait(2);
+                        return NoError;
+                    }
+                }
+            }
+        }
+        wait_ms(50);
+    }
+    return UnexpectedReply;
+}
+
+/**
+ * Initialize.
+ *
+ * @param ct Color type.
+ * @param rr Raw resolution.
+ * @param jr JPEG resolution.
+ */
+CameraC328::ErrorNumber CameraC328::init(ColorType ct, RawResolution rr, JpegResolution jr) {
+    WAITIDLE();
+    ErrorNumber en;
+
+    en = sendInitial(ct, rr, jr);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    static bool alreadySetupPackageSize = false;
+    if (!alreadySetupPackageSize) {
+        en = sendSetPackageSize(packageSize);
+        if (NoError != en) {
+            return en;
+        }
+        WAITFUNC();
+        en = recvAckOrNck();
+        if (NoError != en) {
+            return en;
+        }
+        alreadySetupPackageSize = true;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Get uncompressed snapshot picture.
+ *
+ * @param func A pointer to a callback function.
+ *             Please do NOT block this callback function.
+ *             Because the camera module transmit image datas continuously.
+ * @return Status of the error.
+ */
+CameraC328::ErrorNumber CameraC328::getUncompressedSnapshotPicture(void(*func)(size_t done, size_t total, char c)) {
+    WAITIDLE();
+    ErrorNumber en;
+
+    en = sendSnapshot(UncompressedPicture, 0);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    en = sendGetPicture(SnapshotPicture);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    /*
+     * image data
+     */
+    DataType dt;
+    uint32_t length = 0;
+    WAITFUNC();
+    en = recvData(&dt, &length);
+    if (NoError != en) {
+        return en;
+    }
+    size_t imgcnt = 0;
+    for (int i = 0; i < (int)length; i++) {
+        char c;
+        WAITFUNC();
+        if (!RECVFUNC(&c, 1)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        imgcnt++;
+
+        /*
+         * Call a call back function.
+         * Please do not block this function.
+         */
+        func(imgcnt, length, c);
+    }
+
+    /*
+     * ACK
+     */
+    en = sendAck(0x0A, 0x00);
+    if (NoError != en) {
+        return en;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Get uncompressed preview picture.
+ *
+ * @param func A pointer to a callback function.
+ *             Please do NOT block this callback function.
+ *             Because the camera module transmit image datas continuously.
+ * @return Status of the error.
+ */
+CameraC328::ErrorNumber CameraC328::getUncompressedPreviewPicture(void(*func)(size_t done, size_t total, char c)) {
+    WAITIDLE();
+    ErrorNumber en;
+
+    en = sendGetPicture(PreviewPicture);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    /*
+     * image data
+     */
+    DataType dt;
+    uint32_t length = 0;
+    WAITFUNC();
+    en = recvData(&dt, &length);
+    if (NoError != en) {
+        return en;
+    }
+    size_t imgcnt = 0;
+    for (int i = 0; i < (int)length; i++) {
+        char c;
+        WAITFUNC();
+        if (!RECVFUNC(&c, 1)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        imgcnt++;
+
+        /*
+         * Call a call back function.
+         * Please do not block this function.
+         */
+        func(imgcnt, length, c);
+    }
+
+    /*
+     * ACK
+     */
+    en = sendAck(0x0A, 0x00);
+    if (NoError != en) {
+        return en;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Get JPEG snapshot picture.
+ *
+ * @param func A pointer to a callback function.
+ *             You can block this function until saving the image datas.
+ * @return Status of the error.
+ */
+CameraC328::ErrorNumber CameraC328::getJpegSnapshotPicture(void(*func)(char *buf, size_t siz)) {
+    WAITIDLE();
+    ErrorNumber en;
+
+    en = sendSnapshot(CompressedPicture, 1);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    en = sendGetPicture(SnapshotPicture);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    /*
+     * Data : snapshot picture
+     */
+    DataType dt;
+    uint32_t length = 0;
+    WAITFUNC();
+    en = recvData(&dt, &length);
+    if (NoError != en) {
+        return en;
+    }
+    en = sendAck(0x00, 0);
+    if (NoError != en) {
+        return en;
+    }
+
+    char databuf[packageSize - 6];
+    uint16_t pkg_total = length / (packageSize - 6);
+    for (int i = 0; i <= (int)pkg_total; i++) {
+        uint16_t checksum = 0;
+        // ID.
+        char idbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(idbuf, sizeof(idbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        checksum += idbuf[0];
+        checksum += idbuf[1];
+        uint16_t id = (idbuf[1] << 8) | (idbuf[0] << 0);
+        if (id != i) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        // Size of the data.
+        char dsbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(dsbuf, sizeof(dsbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        // Received the data.
+        checksum += dsbuf[0];
+        checksum += dsbuf[1];
+        uint16_t ds = (dsbuf[1] << 8) | (dsbuf[0] << 0);
+        WAITFUNC();
+        if (!RECVFUNC(&databuf[0], ds)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        for (int j = 0; j < ds; j++) {
+            checksum += databuf[j];
+        }
+
+        // Verify code.
+        char vcbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(vcbuf, sizeof(vcbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        uint16_t vc = (vcbuf[1] << 8) | (vcbuf[0] << 0);
+        if (vc != (checksum & 0xff)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        /*
+         * Call a call back function.
+         * You can block this function while working.
+         */
+        func(databuf, ds);
+
+        /*
+         * We should wait for camera working before reply a ACK.
+         */
+        wait_ms(100);
+        en = sendAck(0x00, 1 + i);
+        if (NoError != en) {
+            return en;
+        }
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Get JPEG preview picture.
+ *
+ * @param func A pointer to a callback function.
+ *             You can block this function until saving the image datas.
+ * @return Status of the error.
+ */
+CameraC328::ErrorNumber CameraC328::getJpegPreviewPicture(void(*func)(char *buf, size_t siz)) {
+    WAITIDLE();
+    ErrorNumber en;
+
+    en = sendGetPicture(JpegPreviewPicture);
+    if (NoError != en) {
+        return en;
+    }
+    WAITFUNC();
+    en = recvAckOrNck();
+    if (NoError != en) {
+        return en;
+    }
+
+    /*
+     * Data : JPEG preview picture
+     */
+    DataType dt;
+    uint32_t length = 0;
+    WAITFUNC();
+    en = recvData(&dt, &length);
+    if (NoError != en) {
+        return en;
+    }
+    en = sendAck(0x00, 0);
+    if (NoError != en) {
+        return en;
+    }
+
+    char databuf[packageSize - 6];
+    uint16_t pkg_total = length / (packageSize - 6);
+    for (int i = 0; i <= (int)pkg_total; i++) {
+        uint16_t checksum = 0;
+        // ID.
+        char idbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(idbuf, sizeof(idbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        checksum += idbuf[0];
+        checksum += idbuf[1];
+        uint16_t id = (idbuf[1] << 8) | (idbuf[0] << 0);
+        if (id != i) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        // Size of the data.
+        char dsbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(dsbuf, sizeof(dsbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        // Received the data.
+        checksum += dsbuf[0];
+        checksum += dsbuf[1];
+        uint16_t ds = (dsbuf[1] << 8) | (dsbuf[0] << 0);
+        WAITFUNC();
+        if (!RECVFUNC(&databuf[0], ds)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        for (int j = 0; j < ds; j++) {
+            checksum += databuf[j];
+        }
+
+        // Verify code.
+        char vcbuf[2];
+        WAITFUNC();
+        if (!RECVFUNC(vcbuf, sizeof(vcbuf))) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+        uint16_t vc = (vcbuf[1] << 8) | (vcbuf[0] << 0);
+        if (vc != (checksum & 0xff)) {
+            return (ErrorNumber)UnexpectedReply;
+        }
+
+        /*
+         * Call a call back function.
+         * You can block this function while working.
+         */
+        func(databuf, ds);
+
+        /*
+         * We should wait for camera working before reply a ACK.
+         */
+        wait_ms(100);
+        en = sendAck(0x00, 1 + i);
+        if (NoError != en) {
+            return en;
+        }
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendInitial(ColorType ct, RawResolution rr, JpegResolution jr) {
+    char send[COMMAND_LENGTH];
+
+    send[0] = 0xAA;
+    send[1] = 0x01;
+    send[2] = 0x00;
+    send[3] = (char)ct;
+    send[4] = (char)rr;
+    send[5] = (char)jr;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendGetPicture(PictureType pt) {
+    char send[COMMAND_LENGTH];
+
+    send[0] = 0xAA;
+    send[1] = 0x04;
+    send[2] = (char)pt;
+    send[3] = 0x00;
+    send[4] = 0x00;
+    send[5] = 0x00;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendSnapshot(SnapshotType st, uint16_t skipFrames) {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x05;
+    send[2] = (char)st;
+    send[3] = (skipFrames >> 0) & 0xff;
+    send[4] = (skipFrames >> 8) & 0xff;
+    send[5] = 0x00;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendSetPackageSize(uint16_t packageSize) {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x06;
+    send[2] = 0x08;
+    send[3] = (packageSize >> 0) & 0xff;
+    send[4] = (packageSize >> 8) & 0xff;
+    send[5] = 0x00;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendSetBaudrate(Baud baud) {
+    char send[COMMAND_LENGTH];
+
+    static struct baud_list {
+        Baud baud;
+        uint8_t div1st;
+        uint8_t div2nd;
+    } baudtable [] = {
+        { Baud7200, 0xff, 0x01 },
+        { Baud9600, 0xbf, 0x01 },
+        { Baud14400, 0x7f, 0x01 },
+        { Baud19200, 0x5f, 0x01 },
+        { Baud28800, 0x3f, 0x01 },
+        { Baud38400, 0x2f, 0x01 },
+        { Baud57600, 0x1f, 0x01 },
+        { Baud115200, 0x0f, 0x01 }
+    };
+
+    uint8_t div1st = 0x00, div2nd = 0x00;
+    struct baud_list *p = &baudtable[0];
+    for (int i = 0; i < sizeof(baudtable) / sizeof(baudtable[0]); i++) {
+        if (p->baud == baud) {
+            div1st = p->div1st;
+            div2nd = p->div2nd;
+        }
+        p++;
+    }
+
+    send[0] = 0xAA;
+    send[1] = 0x07;
+    send[2] = div1st;
+    send[3] = div2nd;
+    send[4] = 0x00;
+    send[5] = 0x00;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendReset(ResetType rt, bool specialReset) {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x08;
+    send[2] = (int)rt;
+    send[3] = 0x00;
+    send[4] = 0x00;
+    send[5] = specialReset ? 0xff : 0x00;
+    /*
+     * Special reset : If the parameter is 0xFF, the command is a special Reset command and the firmware responds to it immediately.
+     */
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendPowerOff() {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x09;
+    send[2] = 0x00;
+    send[3] = 0x00;
+    send[4] = 0x00;
+    send[5] = 0x00;
+
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::recvData(DataType *dt, uint32_t *length) {
+    char recv[COMMAND_LENGTH];
+    if (!RECVFUNC(recv, sizeof(recv))) {
+        return (ErrorNumber)UnexpectedReply;
+    }
+    if ((0xAA != recv[0]) || (0x0A != recv[1])) {
+        return (ErrorNumber)UnexpectedReply;
+    }
+    *dt = (DataType)recv[2];
+    *length = (recv[5] << 16) | (recv[4] << 8) | (recv[3] << 0);
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::sendSync() {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x0D;
+    send[2] = 0x00;
+    send[3] = 0x00;
+    send[4] = 0x00;
+    send[5] = 0x00;
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+CameraC328::ErrorNumber CameraC328::recvSync() {
+    char recv[COMMAND_LENGTH];
+    if (!RECVFUNC(recv, sizeof(recv))) {
+        return (ErrorNumber)UnexpectedReply;
+    }
+    if ((0xAA != recv[0]) || (0x0D != recv[1])) {
+        return (ErrorNumber)UnexpectedReply;
+    }
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Send ACK.
+ *
+ * @param commandId The command with that ID is acknowledged by this command.
+ * @param packageId For acknowledging Data command, these two bytes represent the requested package ID. While for acknowledging other commands, these two bytes are set to 00h.
+ */
+CameraC328::ErrorNumber CameraC328::sendAck(uint8_t commandId, uint16_t packageId) {
+    char send[COMMAND_LENGTH];
+    send[0] = 0xAA;
+    send[1] = 0x0E;
+    send[2] = commandId;
+    send[3] = 0x00;    // ACK counter is not used.
+    send[4] = (packageId >> 0) & 0xff;
+    send[5] = (packageId >> 8) & 0xff;
+    if (!SENDFUNC(send, sizeof(send))) {
+        return (ErrorNumber)SendRegisterTimeout;
+    }
+    return (ErrorNumber)NoError;
+}
+
+/**
+ * Receive ACK or NCK.
+ *
+ * @return Error number.
+ */
+CameraC328::ErrorNumber CameraC328::recvAckOrNck() {
+    char recv[COMMAND_LENGTH];
+    if (!RECVFUNC(recv, sizeof(recv))) {
+        return (ErrorNumber)UnexpectedReply;
+    }
+    if ((0xAA == recv[0]) && (0x0E == recv[1])) {
+        return (ErrorNumber)NoError;
+    }
+    if ((0xAA == recv[0]) && (0x0F == recv[1])) {
+        return (ErrorNumber)recv[4];
+    }
+    return (ErrorNumber)UnexpectedReply;
+}
+
+/**
+ * Send bytes to camera module.
+ *
+ * @param buf Pointer to the data buffer.
+ * @param len Length of the data buffer.
+ *
+ * @return True if the data sended.
+ */
+bool CameraC328::sendBytes(char *buf, size_t len, int timeout_us) {
+    for (uint32_t i = 0; i < (uint32_t)len; i++) {
+        int cnt = 0;
+        while (!serial.writeable()) {
+            wait_us(1);
+            cnt++;
+            if (timeout_us < cnt) {
+                return false;
+            }
+        }
+        serial.putc(buf[i]);
+    }
+    return true;
+}
+
+/**
+ * Receive bytes from camera module.
+ *
+ * @param buf Pointer to the data buffer.
+ * @param len Length of the data buffer.
+ *
+ * @return True if the data received.
+ */
+bool CameraC328::recvBytes(char *buf, size_t len, int timeout_us) {
+    for (uint32_t i = 0; i < (uint32_t)len; i++) {
+        int cnt = 0;
+        while (!serial.readable()) {
+            wait_us(1);
+            cnt++;
+            if (timeout_us < cnt) {
+                return false;
+            }
+        }
+        buf[i] = serial.getc();
+    }
+    return true;
+}
+
+/**
+ * Wait received.
+ *
+ * @return True if the data received.
+ */
+bool CameraC328::waitRecv() {
+    while (!serial.readable()) {
+    }
+    return true;
+}
+
+/**
+ * Wait idle state.
+ */
+bool CameraC328::waitIdle() {
+    while (serial.readable()) {
+        serial.getc();
+    }
+    return true;
+}
diff -r 640f564075af -r 49cfda6c547f CameraC328.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CameraC328.h	Wed Oct 13 10:45:29 2010 +0000
@@ -0,0 +1,217 @@
+/**
+ * C328-7640 device driver class (Version 0.0.6)
+ * Reference documents: C328-7640 User Manual v3.0 2004.8.19
+ *
+ * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ */
+
+#include "mbed.h"
+#include "SerialBuffered.h"
+
+#ifndef _CAMERA_C328_H_
+#define _CAMERA_C328_H_
+
+/*
+ * Class: CameraC328
+ */
+class CameraC328 {
+public:
+
+    /**
+     * Color type.
+     */
+    enum ColorType {
+        GrayScale2bit = 0x01,   // 2bit for Y only
+        GrayScale4bit = 0x02,   // 4bit for Y only
+        GrayScale8bit = 0x03,   // 8bit for Y only
+        Color12bit = 0x05,      // 444 (RGB)
+        Color16bit = 0x06,      // 565 (RGB)
+        Jpeg = 0x07
+    };
+
+    /**
+     * Raw resolution.
+     */
+    enum RawResolution {
+        RawResolution80x60 = 0x01,
+        RawResolution160x120 = 0x03
+    };
+
+    /**
+     * JPEG resolution.
+     */
+    enum JpegResolution {
+        JpegResolution80x64 = 0x01,
+        JpegResolution160x128 = 0x03,
+        JpegResolution320x240 = 0x05,
+        JpegResolution640x480 = 0x07
+    };
+
+    /**
+     * Error number.
+     */
+    enum ErrorNumber {
+        NoError = 0x00,
+        PictureTypeError = 0x01,
+        PictureUpScale = 0x02,
+        PictureScaleError = 0x03,
+        UnexpectedReply = 0x04,
+        SendPictureTimeout = 0x05,
+        UnexpectedCommand = 0x06,
+        SramJpegTypeError = 0x07,
+        SramJpegSizeError = 0x08,
+        PictureFormatError = 0x09,
+        PictureSizeError = 0x0a,
+        ParameterError = 0x0b,
+        SendRegisterTimeout = 0x0c,
+        CommandIdError = 0x0d,
+        PictureNotReady = 0x0f,
+        TransferPackageNumberError = 0x10,
+        SetTransferPackageSizeWrong = 0x11,
+        CommandHeaderError = 0xf0,
+        CommandLengthError = 0xf1,
+        SendPictureError = 0xf5,
+        SendCommandError = 0xff
+    };
+
+    /**
+     * Picture type.
+     */
+    enum PictureType {
+        SnapshotPicture = 0x01,
+        PreviewPicture = 0x02,
+        JpegPreviewPicture = 0x05
+    };
+
+    /**
+     * Snapshot type.
+     */
+    enum SnapshotType {
+        CompressedPicture = 0x00,
+        UncompressedPicture = 0x01
+    };
+
+    /**
+     * Baud rate.
+     */
+    enum Baud {
+        Baud7200 = 7200,
+        Baud9600 = 9600,
+        Baud14400 = 14400,
+        Baud19200 = 19200,  // Default.
+        Baud28800 = 28800,
+        Baud38400 = 38400,
+        Baud57600 = 57600,
+        Baud115200 = 115200
+    };
+
+    /**
+     * Reset type.
+     */
+    enum ResetType {
+        ResetWholeSystem = 0x00,
+        ResetStateMachines = 0x01
+    };
+
+    /**
+     * Data type.
+     */
+    enum DataType {
+        DataTypeSnapshotPicture = 0x01,
+        DataTypePreviewPicture = 0x02,
+        DataTypeJpegPreviewPicture = 0x05
+    };
+
+    /**
+     * Constructor.
+     *
+     * @param tx A pin for transmit.
+     * @param rx A pin for receive.
+     * @param baud Baud rate. (Default is Baud19200.)
+     */
+    CameraC328(PinName tx, PinName rx, Baud baud = Baud19200);
+
+    /**
+     * Destructor.
+     */
+    ~CameraC328();
+
+    /**
+     * Make a sync. for baud rate.
+     */
+    ErrorNumber sync();
+
+    /**
+     * Initialize.
+     *
+     * @param ct Color type.
+     * @param rr Raw resolution.
+     * @param jr JPEG resolution.
+     */
+    ErrorNumber init(ColorType ct, RawResolution rr, JpegResolution jr);
+
+    /**
+     * Get uncompressed snapshot picture.
+     *
+     * @param func A pointer to a callback function.
+     *             Please do NOT block this callback function.
+     *             Because the camera module transmit image datas continuously.
+     * @return Status of the error.
+     */
+    ErrorNumber getUncompressedSnapshotPicture(void(*func)(size_t done, size_t total, char c));
+
+    /**
+     * Get uncompressed preview picture.
+     *
+     * @param func A pointer to a callback function.
+     *             Please do NOT block this callback function.
+     *             Because the camera module transmit image datas continuously.
+     * @return Status of the error.
+     */
+    ErrorNumber getUncompressedPreviewPicture(void(*func)(size_t done, size_t total, char c));
+
+    /**
+     * Get JPEG snapshot picture.
+     *
+     * @param func A pointer to a callback function.
+     *             You can block this function until saving the image datas.
+     * @return Status of the error.
+     */
+    ErrorNumber getJpegSnapshotPicture(void(*func)(char *buf, size_t siz));
+
+    /**
+     * Get JPEG preview picture.
+     *
+     * @param func A pointer to a callback function.
+     *             You can block this function until saving the image datas.
+     * @return Status of the error.
+     */
+    ErrorNumber getJpegPreviewPicture(void(*func)(char *buf, size_t siz));
+
+private:
+    SerialBuffered serial;
+    static const int COMMAND_LENGTH = 6;
+    static const int SYNCMAX = 60;
+    static const int packageSize = 512;
+
+    ErrorNumber sendInitial(ColorType ct, RawResolution rr, JpegResolution jr);
+    ErrorNumber sendGetPicture(PictureType pt);
+    ErrorNumber sendSnapshot(SnapshotType st, uint16_t skipFrames);
+    ErrorNumber sendSetPackageSize(uint16_t packageSize);
+    ErrorNumber sendSetBaudrate(Baud baud);
+    ErrorNumber sendReset(ResetType rt, bool specialReset);
+    ErrorNumber sendPowerOff();
+    ErrorNumber recvData(DataType *dt, uint32_t *length);
+    ErrorNumber sendSync();
+    ErrorNumber recvSync();
+    ErrorNumber sendAck(uint8_t commandId, uint16_t packageId);
+    ErrorNumber recvAckOrNck();
+
+    bool sendBytes(char *buf, size_t len, int timeout_us = 20000);
+    bool recvBytes(char *buf, size_t len, int timeout_us = 20000);
+    bool waitRecv();
+    bool waitIdle();
+};
+
+#endif
diff -r 640f564075af -r 49cfda6c547f SerialBuffered.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.cpp	Wed Oct 13 10:45:29 2010 +0000
@@ -0,0 +1,99 @@
+#include "mbed.h"
+#include "SerialBuffered.h"
+
+/**
+ * Create a buffered serial class.
+ *
+ * @param tx A pin for transmit.
+ * @param rx A pin for receive.
+ */
+SerialBuffered::SerialBuffered(PinName tx, PinName rx) : Serial(tx, rx) {
+    indexContentStart = 0;
+    indexContentEnd = 0;
+    timeout = 1;
+    attach(this, &SerialBuffered::handleInterrupt);
+}
+
+/**
+ * Destroy.
+ */
+SerialBuffered::~SerialBuffered() {
+}
+
+/**
+ * Set timeout for getc().
+ *
+ * @param ms milliseconds. (-1:Disable timeout)
+ */
+void SerialBuffered::setTimeout(int ms) {
+    timeout = ms;
+}
+
+/**
+ * Read requested bytes.
+ *
+ * @param bytes A pointer to a buffer.
+ * @param requested Length.
+ *
+ * @return Readed byte length.
+ */
+size_t SerialBuffered::readBytes(uint8_t *bytes, size_t requested) {
+    int i = 0;
+    while (i < requested) {
+        int c = getc();
+        if (c < 0) {
+            break;
+        }
+        bytes[i] = c;
+        i++;
+    }
+    return i;
+}
+
+/**
+ * Get a character.
+ *
+ * @return A character. (-1:timeout)
+ */
+int SerialBuffered::getc() {
+    timer.reset();
+    timer.start();
+    while (indexContentStart == indexContentEnd) {
+        wait_ms(1);
+        if ((timeout > 0) && (timer.read_ms() > timeout)) {
+            /*
+             * Timeout occured.
+             */
+            // printf("Timeout occured.\n");
+            return EOF;
+        }
+    }
+    timer.stop();
+
+    uint8_t result = buffer[indexContentStart++];
+    indexContentStart =  indexContentStart % BUFFERSIZE;
+
+    return result;
+}
+
+/**
+ * Returns 1 if there is a character available to read, 0 otherwise.
+ */
+int SerialBuffered::readable() {
+    return indexContentStart != indexContentEnd;
+}
+
+void SerialBuffered::handleInterrupt() {
+    while (Serial::readable()) {
+        if (indexContentStart == ((indexContentEnd + 1) % BUFFERSIZE)) {
+            /*
+             * Buffer overrun occured.
+             */
+            // printf("Buffer overrun occured.\n");
+            Serial::getc();
+        } else {
+            buffer[indexContentEnd++] = Serial::getc();
+            indexContentEnd = indexContentEnd % BUFFERSIZE;
+        }
+    }
+}
diff -r 640f564075af -r 49cfda6c547f SerialBuffered.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialBuffered.h	Wed Oct 13 10:45:29 2010 +0000
@@ -0,0 +1,61 @@
+#ifndef _SERIAL_BUFFERED_H_
+#define _SERIAL_BUFFERED_H_
+
+/**
+ * Buffered serial class.
+ */
+class SerialBuffered : public Serial {
+public:
+    /**
+     * Create a buffered serial class.
+     *
+     * @param tx A pin for transmit.
+     * @param rx A pin for receive.
+     */
+    SerialBuffered(PinName tx, PinName rx);
+
+    /**
+     * Destroy.
+     */
+    virtual ~SerialBuffered();
+
+    /**
+     * Get a character.
+     *
+     * @return A character. (-1:timeout)
+     */
+    int getc();
+
+    /**
+     * Returns 1 if there is a character available to read, 0 otherwise.
+     */
+    int readable();
+
+    /**
+     * Set timeout for getc().
+     *
+     * @param ms milliseconds. (-1:Disable timeout)
+     */
+    void setTimeout(int ms);
+
+    /**
+     * Read requested bytes.
+     *
+     * @param bytes A pointer to a buffer.
+     * @param requested Length.
+     *
+     * @return Readed byte length.
+     */
+    size_t readBytes(uint8_t *bytes, size_t requested);
+
+private:
+    void handleInterrupt();
+    static const int BUFFERSIZE = 4096;
+    uint8_t buffer[BUFFERSIZE];            // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
+    uint16_t indexContentStart;   // index of first bytes of content
+    uint16_t indexContentEnd;     // index of bytes after last byte of content
+    int timeout;
+    Timer timer;
+};
+
+#endif
diff -r 640f564075af -r 49cfda6c547f extlib/FATFileSystem.lib
--- a/extlib/FATFileSystem.lib	Wed Oct 13 10:42:48 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
diff -r 640f564075af -r 49cfda6c547f extlib/SDFileSystem.lib
--- a/extlib/SDFileSystem.lib	Wed Oct 13 10:42:48 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/simon/code/SDFileSystem/#b1ddfc9a9b25
diff -r 640f564075af -r 49cfda6c547f main.cpp
--- a/main.cpp	Wed Oct 13 10:42:48 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/**
- * Test program.
- *
- * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
- * http://shinta.main.jp/
- */
-
-/*
- * Include files.
- */
-
-#include "mbed.h"
-#include "CameraC328.h"
-#include "SDFileSystem.h"
-
-/*
- * Definitions.
- */
-#define USE_JPEG_HIGH_RESOLUTION  1
-#define USE_SD_CARD 0
-
-/*
- * Variables.
- */
-static const int CAPTURE_FRAMES = 5;
-static const int RAWIMG_X = 80;
-static const int RAWIMG_Y = 60;
-static char buf[RAWIMG_X * RAWIMG_Y * 2];
-static FILE *fp_jpeg;
-
-/*
- * Modules.
- */
-#if USE_SD_CARD
-SDFileSystem sd(p5, p6, p7, p8, "fs");
-#else
-LocalFileSystem fs("fs");
-#endif
-CameraC328 camera(p9, p10, CameraC328::Baud19200);
-
-/**
- * A callback function for uncompressed images.
- * Please do NOT block this callback function.
- * Because the camera module transmit image datas continuously.
- *
- * @param done a done number of packets.
- * @param total a total number of packets.
- * @param c received data.
- */
-void uncompressed_callback(size_t done, size_t total, char c) {
-    buf[done - 1] = c;
-}
-
-/**
- * A callback function for jpeg images.
- * You can block this function until saving the image datas.
- *
- * @param buf A pointer to the image buffer.
- * @param siz A size of the image buffer.
- */
-void jpeg_callback(char *buf, size_t siz) {
-    for (int i = 0; i < (int)siz; i++) {
-        fprintf(fp_jpeg, "%c", buf[i]);
-    }
-}
-
-/**
- * Synchronizing.
- */
-void sync(void) {
-    CameraC328::ErrorNumber err = CameraC328::NoError;
-
-    err = camera.sync();
-    if (CameraC328::NoError == err) {
-        printf("[ OK ] : CameraC328::sync\n");
-    } else {
-        printf("[FAIL] : CameraC328::sync (Error=%02X)\n", (int)err);
-    }
-}
-
-/**
- * A test function for uncompressed snapshot picture.
- */
-void test_uncompressed_snapshot_picture(void) {
-    CameraC328::ErrorNumber err = CameraC328::NoError;
-
-    err = camera.init(CameraC328::Color16bit, CameraC328::RawResolution80x60, CameraC328::JpegResolution160x128);
-    if (CameraC328::NoError == err) {
-        printf("[ OK ] : CameraC328::init\n");
-    } else {
-        printf("[FAIL] : CameraC328::init (Error=%02X)\n", (int)err);
-    }
-
-    for (int i = 0; i < CAPTURE_FRAMES; i++) {
-        err = camera.getUncompressedSnapshotPicture(uncompressed_callback);
-        if (CameraC328::NoError == err) {
-            printf("[ OK ] : CameraC328::getUncompressedSnapshotPicture\n");
-        } else {
-            printf("[FAIL] : CameraC328::getUncompressedSnapshotPicture (Error=%02X)\n", (int)err);
-        }
-
-        char fname[64];
-        snprintf(fname, sizeof(fname), "/fs/ucss%04d.ppm", i);
-        FILE *fp = fopen(fname, "w");
-        fprintf(fp, "P3\n");
-        fprintf(fp, "%d %d\n", RAWIMG_X, RAWIMG_Y);
-        fprintf(fp, "%d\n", 255);
-        for (int y = 0; y < RAWIMG_Y; y++) {
-            for (int x = 0; x < RAWIMG_X; x++) {
-                int adrofs = y * (RAWIMG_X * 2) + (x * 2);
-                uint16_t dat = (buf[adrofs + 0] << 8) | (buf[adrofs + 1] << 0);
-                uint8_t r = ((dat >> 11) & 0x1f) << 3;
-                uint8_t g = ((dat >> 5) & 0x3f) << 2;
-                uint8_t b = ((dat >> 0) & 0x1f) << 3;
-                fprintf(fp,"%d %d %d\n", r, g, b);
-            }
-        }
-        fclose(fp);
-    }
-}
-
-/**
- * A test function for uncompressed preview picture.
- */
-void test_uncompressed_preview_picture(void) {
-    CameraC328::ErrorNumber err = CameraC328::NoError;
-
-    err = camera.init(CameraC328::Color16bit, CameraC328::RawResolution80x60, CameraC328::JpegResolution160x128);
-    if (CameraC328::NoError == err) {
-        printf("[ OK ] : CameraC328::init\n");
-    } else {
-        printf("[FAIL] : CameraC328::init (Error=%02X)\n", (int)err);
-    }
-
-    for (int i = 0; i < CAPTURE_FRAMES; i++) {
-        err = camera.getUncompressedPreviewPicture(uncompressed_callback);
-        if (CameraC328::NoError == err) {
-            printf("[ OK ] : CameraC328::getUncompressedPreviewPicture\n");
-        } else {
-            printf("[FAIL] : CameraC328::getUncompressedPreviewPicture (Error=%02X)\n", (int)err);
-        }
-
-        char fname[64];
-        snprintf(fname, sizeof(fname), "/fs/ucpv%04d.ppm", i);
-        FILE *fp = fopen(fname, "w");
-        fprintf(fp, "P3\n");
-        fprintf(fp, "%d %d\n", RAWIMG_X, RAWIMG_Y);
-        fprintf(fp, "%d\n", 255);
-        for (int y = 0; y < RAWIMG_Y; y++) {
-            for (int x = 0; x < RAWIMG_X; x++) {
-                int adrofs = y * (RAWIMG_X * 2) + (x * 2);
-                uint16_t dat = (buf[adrofs + 0] << 8) | (buf[adrofs + 1] << 0);
-                uint8_t r = ((dat >> 11) & 0x1f) << 3;
-                uint8_t g = ((dat >> 5) & 0x3f) << 2;
-                uint8_t b = ((dat >> 0) & 0x1f) << 3;
-                fprintf(fp,"%d %d %d\n", r, g, b);
-            }
-        }
-        fclose(fp);
-    }
-}
-
-/**
- * A test function for jpeg snapshot picture.
- */
-void test_jpeg_snapshot_picture(void) {
-    CameraC328::ErrorNumber err = CameraC328::NoError;
-
-#if USE_JPEG_HIGH_RESOLUTION
-    err = camera.init(CameraC328::Jpeg, CameraC328::RawResolution80x60, CameraC328::JpegResolution640x480);
-#else
-    err = camera.init(CameraC328::Jpeg, CameraC328::RawResolution80x60, CameraC328::JpegResolution320x240);
-#endif
-    if (CameraC328::NoError == err) {
-        printf("[ OK ] : CameraC328::init\n");
-    } else {
-        printf("[FAIL] : CameraC328::init (Error=%02X)\n", (int)err);
-    }
-
-    for (int i = 0; i < CAPTURE_FRAMES; i++) {
-        char fname[64];
-        snprintf(fname, sizeof(fname), "/fs/jpss%04d.jpg", i);
-        fp_jpeg = fopen(fname, "w");
-
-        err = camera.getJpegSnapshotPicture(jpeg_callback);
-        if (CameraC328::NoError == err) {
-            printf("[ OK ] : CameraC328::getJpegSnapshotPicture\n");
-        } else {
-            printf("[FAIL] : CameraC328::getJpegSnapshotPicture (Error=%02X)\n", (int)err);
-        }
-
-        fclose(fp_jpeg);
-    }
-}
-
-/**
- * A test function for jpeg preview picture.
- */
-void test_jpeg_preview_picture(void) {
-    CameraC328::ErrorNumber err = CameraC328::NoError;
-
-#if USE_JPEG_HIGH_RESOLUTION
-    err = camera.init(CameraC328::Jpeg, CameraC328::RawResolution80x60, CameraC328::JpegResolution640x480);
-#else
-    err = camera.init(CameraC328::Jpeg, CameraC328::RawResolution80x60, CameraC328::JpegResolution320x240);
-#endif
-    if (CameraC328::NoError == err) {
-        printf("[ OK ] : CameraC328::init\n");
-    } else {
-        printf("[FAIL] : CameraC328::init (Error=%02X)\n", (int)err);
-    }
-
-    for (int i = 0; i < CAPTURE_FRAMES; i++) {
-        char fname[64];
-        snprintf(fname, sizeof(fname), "/fs/jppv%04d.jpg", i);
-        fp_jpeg = fopen(fname, "w");
-
-        err = camera.getJpegPreviewPicture(jpeg_callback);
-        if (CameraC328::NoError == err) {
-            printf("[ OK ] : CameraC328::getJpegPreviewPicture\n");
-        } else {
-            printf("[FAIL] : CameraC328::getJpegPreviewPicture (Error=%02X)\n", (int)err);
-        }
-
-        fclose(fp_jpeg);
-    }
-}
-
-/**
- * A entry point.
- */
-int main() {
-    printf("\n");
-    printf("==========\n");
-    printf("CameraC328\n");
-    printf("==========\n");
-
-    sync();
-    test_uncompressed_snapshot_picture();
-    test_uncompressed_preview_picture();
-    test_jpeg_preview_picture();
-    test_jpeg_snapshot_picture();
-
-    return 0;
-}
diff -r 640f564075af -r 49cfda6c547f mbed.bld
--- a/mbed.bld	Wed Oct 13 10:42:48 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e