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: main.cpp
- Revision:
- 0:07d02a20d1cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,347 @@ +/* This software 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. + * + * 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" +// #define USE_LCD // Need this if you want to use text LCD +#ifdef USE_LCD +#include "TextLCD.h" +#endif +// #include "SDFileSystem.h" // Need this if you want to save to SD-Card + +#include "isc15.h" +#include "ucam.h" + +// SDFileSystem sd(p5, p6, p7, p8, "sd"); // Need this if you want to save to SD-Card +LocalFileSystem local("local"); // Need this if you want to save to local flash +SPI spi(p11, p12, p13); // mosi(SDO), miso(SDI), sclk(SCLK) + +ISC15 ISC15(p16, p15, p14, p18); // NKK IS-C15 oLED swtich +DigitalOut led1(LED1), led2(LED2); // On board LEDs +DigitalIn sw1(p17); // Shutter switch (IS-C15) +uCam ucam(p9, p10); // uCam-TTL (p9=TX, p10=RX) + +Ticker timer; +bool sw1pressed = false; +bool sw1pressing = false; + +#ifdef USE_LCD +TextLCD lcd(p24, p26, p27, p28, p29, p30); // rs, e, d0-d3 +#define LCDPRINTF(...) lcd.printf(__VA_ARGS__) +#else +#define LCDPRINTF(...) +#endif /* USE_LCD */ + +/* Function prototypes */ +void checkSW(); +int SaveJPEG(const char *fname); + +/* main fuction */ +int main() { + unsigned char cam[80*60*2]; + unsigned char oled[64*48*2]; + int n = 0; + + sw1.mode(PullUp); + led1 = led2 = 1; + // Setup the spi for 8 bit data, high steady state clock, + // second edge capture, with a 4MHz clock rate + spi.format(8, 3); + spi.frequency(4000000); + // Initialize IS Color 15's oLED + ISC15.Init(ISC15_DEVICE_ISC15, &spi); + // Clear oLED display + ISC15.Cls(); + + // Initialize uCam-TTL + LCDPRINTF("Init Camera..\n"); + if (!ucam.Init()) { + LCDPRINTF("Init failed.\n"); + goto ERROR; + } + // Set AC frequency (60 for Kansai-area, 50 for Kanto-area) + if (!ucam.LightFreq(60)) + goto ERROR; + // Attach tick timer to checkSW function + timer.attach_us(checkSW, 20000); + + LCDPRINTF("Starting.\n"); + led1 = led2 = 0; + + for (;;) { + // Flush LED + led1 = 1; + wait(0.1); + led1 = 0; + +#if 1 /* D1: Set 1 to test RGB565 mode */ + if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_RGB565, UCAM_RAW_RESOLUTION_80X60, cam)) + goto ERROR; + + for (int y=0; y<48; y++) { + unsigned char *rg = cam + (80-64)/2 + ((60-48)/2+y)*80*2; + unsigned char *gb = rg + 1; + unsigned char *p = oled + y*64*2; + for (int x=0; x<64; x++, rg+=2, gb+=2) { + *p ++ = (*gb <<3) | (*rg & 0x7); + *p ++ = (*gb & 0xe0) | (*rg >> 3); + } + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D2: Set 1 to test 4bit gray mode */ + if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_4BITG, UCAM_RAW_RESOLUTION_80X60, cam)) + goto ERROR; + + for (int y=0; y<48; y++) { + unsigned char *v = cam + ((80-64)/2 + ((60-48)/2+y)*80)/2; + unsigned char *p = oled + y*64*2; + for (int x=0; x<64; x++, v++) { + int V = (*v & 0xf0) >> 4; + *p ++ = (V << 4) | (V >> 1); + *p ++ = ((V << 2) & 0xe0) | (V << 1); + x ++; + + V = *v & 0xf; + *p ++ = (V << 4) | (V >> 1); + *p ++ = ((V << 2) & 0xe0) | (V << 1); + } + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D3: Set 1 to test 8bit gray mode */ + if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_8BITG, UCAM_RAW_RESOLUTION_80X60, cam)) + goto ERROR; + + for (int y=0; y<48; y++) { + unsigned char *v = cam + (80-64)/2 + ((60-48)/2+y)*80; + unsigned char *p = oled + y*64*2; + for (int x=0; x<64; x++, v++) { + *p ++ = (*v & 0xf8) | (*v >> 5); + *p ++ = ((*v << 3) & 0xe0) | (*v >> 3); + } + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D4: Set 1 to test RGB332 mode */ + if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_RGB332, UCAM_RAW_RESOLUTION_80X60, cam)) + goto ERROR; + + for (int y=0; y<48; y++) { + unsigned char *v = cam + ((80-64)/2 + ((60-48)/2+y)*80); + unsigned char *p = oled + y*64*2; + for (int x=0; x<64; x++, v++) { + int B = (*v & 0xe0) >> 5; /* 3bits */ + int G = (*v & 0x1c) >> 3; /* 3bits */ + int R = (*v & 0x3); /* 2bits */ + *p ++ = (B << 6) | G; + *p ++ = R << 2; + } + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D5: Set 1 to test cropping (digital zoom) */ + if (!ucam.SnapshotRawCrop(UCAM_COLOR_TYPE_RGB565, + UCAM_RAW_RESOLUTION_160X120, 48, 36, 64, 48, cam)) + goto ERROR; + + unsigned char *rg = cam; + unsigned char *gb = rg + 1; + unsigned char *p = oled; + for (int i=64*48; i>0; i--, rg+=2, gb+=2) { + *p ++ = (*gb <<3) | (*rg & 0x7); + *p ++ = (*gb & 0xe0) | (*rg >> 3); + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D6: Set 1 to test 8bit gray differential image */ + unsigned char cam2[80*60]; + static unsigned char *camp = cam, *cam2p = cam2; + + if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_8BITG, UCAM_RAW_RESOLUTION_80X60, camp)) + goto ERROR; + + for (int y=0; y<48; y++) { + unsigned char *v = camp + (80-64)/2 + ((60-48)/2+y)*80; + unsigned char *b = cam2p + (80-64)/2 + ((60-48)/2+y)*80; + unsigned char *p = oled + y*64*2; + + for (int x=0; x<64; x++, v++, b++) { + if (abs(*v-*b)>10) { + *p ++ = (*v & 0xf8) | (*v >> 5); + *p ++ = ((*v << 3) & 0xe0) | (*v >> 3); + } else { + *p ++ = 0; + *p ++ = 0; + } + } + } + if (camp == cam) { + camp = cam2; + cam2p = cam; + } else { + camp = cam; + cam2p = cam2; + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); +#endif + +#if 0 /* D7: Set 1 to show RGB565 image when images' differential is large */ + unsigned char cam2[80*60*2]; + static unsigned char *camp = cam, *cam2p = cam2; + + if (!ucam.SnapshotRawCrop(UCAM_COLOR_TYPE_RGB565, + UCAM_RAW_RESOLUTION_80X60, 8, 6, 64, 48, camp)) + goto ERROR; + + unsigned char *rg = camp; + unsigned char *gb = rg + 1; + unsigned char *rg0 = cam2p; + unsigned char *gb0 = rg0 + 1; + unsigned int diff = 0; + + for (int i=64*48; i>0; i--, rg+=2, gb+=2, rg0+=2, gb0+=2) + diff += abs(((*rg & 0x7)<<3 | (*gb >> 5))-((*rg0 & 0x7)<<3 | (*gb0>> 5))); + LCDPRINTF("d: %d.\n", diff); + + if (diff > 3000) { + rg = camp; + gb = rg + 1; + unsigned char *p = oled; + for (int i=64*48; i>0; i--, rg+=2, gb+=2) { + *p ++ = (*gb <<3) | (*rg & 0x7); + *p ++ = (*gb & 0xe0) | (*rg >> 3); + } + ISC15.Disp(ISC15_DSPMODE_64K, oled); + } else { + ISC15.Cls(); + } + if (camp == cam) { + camp = cam2; + cam2p = cam; + } else { + camp = cam; + cam2p = cam2; + } +#endif + + if (sw1pressed) { + char fname[20]; +// sprintf(fname, "/sd/%05d.jpg", n); // Save to SD-Card + sprintf(fname, "/local/%05d.jpg", n); // Save to local flash memory + LCDPRINTF("Saving image\n"); + SaveJPEG(fname); + LCDPRINTF("DONE \n"); + n ++; + sw1pressed = false; + led2 = 0; + } + } + +ERROR: + LCDPRINTF("ERROR\n"); + while (1) { + led1 = 1; + wait(0.1); + led1 = 0; + wait(0.1); + } +} + +/* ------------------------------------------ */ +/* Check current status of the switch */ +/* The fuction is called by 20ms timer */ +/* ------------------------------------------ */ +void checkSW() { + if (sw1 == 0) { + /* Swtich is pressed */ + sw1pressed = true; + sw1pressing = true; + led2 = 1; + } else { + /* Switch is open */ + sw1pressing = false; + led2 = 0; + } +} + +/* ------------------------------------------ */ +/* Save a JPEG image read from uCam to a file */ +/* ------------------------------------------ */ +int SaveJPEG(const char *fname) { + /* Open file */ + FILE *fp = fopen(fname, "wb"); + if (fp == NULL) { + LCDPRINTF("XXX %s\n", fname); + return 0; + } + + /* Prepare to recieve JPEG image */ + int sz = ucam.SnapshotJPEGi(UCAM_JPEG_RESOLUTION_320X240, 512); + if (sz == 0) + return 0; + + /* Recieve packets */ + int pno = 0; + unsigned char cam[512]; + while (sz > 0) { + int pksz = 512; + led2 = ~led2; + + if (sz < (512 - 6)) + pksz = sz + 6; + LCDPRINTF("%d %d\n", pno, pksz); + /* Recieve a packet */ + if (!ucam.SnapshotJPEGd(pno, cam, pksz)) { + if (fp != NULL) + fclose(fp); + return 0; + } + /* Write the packet */ + if (fp != NULL) + fwrite(cam + 4, 1, pksz - 6, fp); + sz -= (pksz - 6); + pno ++; + /* Check end of the image */ + if (sz == 0) { + if (pksz == 512) { + // Send reset command as manual says + wait_ms(3); + ucam.Reset(); + ucam.Init(); + } else { + ucam.ACK_F0F0(); + } + } + } + fclose(fp); + + return 1; +}