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
Diff: ucam.cpp
- Revision:
- 0:07d02a20d1cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ucam.cpp Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,280 @@ +/* 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); + } +}