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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* This software is an digital video camera program using NKK's oLED swtich
00002  * and 4D Systems' uCam serial camera. It takes image from the uCam and 
00003  * displays on the IS-C15 switch. Some image processing demos are included.
00004  *
00005  * This program uses FatFileSytem, SDFileSystem, and TextLCD library. 
00006  *   
00007  * Copyright (c) 2011, Noriaki Mitsunaga
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining a copy
00010  * of this software and associated documentation files (the "Software"), to deal
00011  * in the Software without restriction, including without limitation the rights
00012  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00013  * copies of the Software, and to permit persons to whom the Software is
00014  * furnished to do so, subject to the following conditions:
00015  *
00016  * The above copyright notice and this permission notice shall be included in
00017  * all copies or substantial portions of the Software.
00018  *
00019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00020  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00022  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00024  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00025  * THE SOFTWARE.
00026  */
00027 #include "mbed.h"
00028 // #define USE_LCD              // Need this if you want to use text LCD
00029 #ifdef USE_LCD
00030 #include "TextLCD.h"
00031 #endif
00032 // #include "SDFileSystem.h" // Need this if you want to save to SD-Card
00033 
00034 #include "isc15.h"
00035 #include "ucam.h"
00036 
00037 // SDFileSystem sd(p5, p6, p7, p8, "sd"); // Need this if you want to save to SD-Card
00038 LocalFileSystem local("local"); // Need this if you want to save to local flash
00039 SPI spi(p11, p12, p13); // mosi(SDO), miso(SDI), sclk(SCLK)
00040 
00041 ISC15 ISC15(p16, p15, p14, p18);   // NKK IS-C15 oLED swtich
00042 DigitalOut led1(LED1), led2(LED2); // On board LEDs
00043 DigitalIn sw1(p17);                // Shutter switch (IS-C15)
00044 uCam ucam(p9, p10);                // uCam-TTL (p9=TX, p10=RX)
00045 
00046 Ticker timer;
00047 bool sw1pressed = false;
00048 bool sw1pressing = false;
00049 
00050 #ifdef USE_LCD
00051 TextLCD lcd(p24, p26, p27, p28, p29, p30); // rs, e, d0-d3
00052 #define LCDPRINTF(...) lcd.printf(__VA_ARGS__)
00053 #else
00054 #define LCDPRINTF(...)
00055 #endif /* USE_LCD */
00056 
00057 /* Function prototypes */
00058 void checkSW();
00059 int  SaveJPEG(const char *fname);
00060 
00061 /* main fuction */
00062 int main() {
00063     unsigned char cam[80*60*2];
00064     unsigned char oled[64*48*2];
00065     int n = 0;
00066 
00067     sw1.mode(PullUp);
00068     led1 = led2 = 1;
00069     // Setup the spi for 8 bit data, high steady state clock,
00070     // second edge capture, with a 4MHz clock rate
00071     spi.format(8, 3);
00072     spi.frequency(4000000);
00073     // Initialize IS Color 15's oLED
00074     ISC15.Init(ISC15_DEVICE_ISC15, &spi);
00075     // Clear oLED display
00076     ISC15.Cls();
00077 
00078     // Initialize uCam-TTL
00079     LCDPRINTF("Init Camera..\n");
00080     if (!ucam.Init()) {
00081         LCDPRINTF("Init failed.\n");
00082         goto ERROR;
00083     }
00084     // Set AC frequency (60 for Kansai-area, 50 for Kanto-area)
00085     if (!ucam.LightFreq(60))
00086         goto ERROR;
00087     // Attach tick timer to checkSW function
00088     timer.attach_us(checkSW, 20000);
00089 
00090     LCDPRINTF("Starting.\n");
00091     led1 = led2 = 0;
00092 
00093     for (;;) {
00094         // Flush LED
00095         led1 = 1;
00096         wait(0.1);
00097         led1 = 0;
00098 
00099 #if 1   /* D1: Set 1 to test RGB565 mode */
00100         if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_RGB565, UCAM_RAW_RESOLUTION_80X60, cam))
00101             goto ERROR;
00102 
00103         for (int y=0; y<48; y++) {
00104             unsigned char *rg = cam + (80-64)/2 + ((60-48)/2+y)*80*2;
00105             unsigned char *gb = rg + 1;
00106             unsigned char *p = oled + y*64*2;
00107             for (int x=0; x<64; x++, rg+=2, gb+=2) {
00108                 *p ++ = (*gb <<3)    | (*rg & 0x7);
00109                 *p ++ = (*gb & 0xe0) | (*rg >> 3);
00110             }
00111         }
00112         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00113 #endif
00114 
00115 #if 0   /* D2: Set 1 to test 4bit gray mode */
00116         if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_4BITG, UCAM_RAW_RESOLUTION_80X60, cam))
00117             goto ERROR;
00118 
00119         for (int y=0; y<48; y++) {
00120             unsigned char *v = cam + ((80-64)/2 + ((60-48)/2+y)*80)/2;
00121             unsigned char *p = oled + y*64*2;
00122             for (int x=0; x<64; x++, v++) {
00123                 int V = (*v & 0xf0) >> 4;
00124                 *p ++ = (V << 4)    | (V >> 1);
00125                 *p ++ = ((V << 2) & 0xe0) | (V << 1);
00126                 x ++;
00127 
00128                 V = *v & 0xf;
00129                 *p ++ = (V << 4)    | (V >> 1);
00130                 *p ++ = ((V << 2) & 0xe0) | (V << 1);
00131             }
00132         }
00133         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00134 #endif
00135 
00136 #if 0   /* D3: Set 1 to test 8bit gray mode */
00137         if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_8BITG, UCAM_RAW_RESOLUTION_80X60, cam))
00138             goto ERROR;
00139 
00140         for (int y=0; y<48; y++) {
00141             unsigned char *v = cam + (80-64)/2 + ((60-48)/2+y)*80;
00142             unsigned char *p = oled + y*64*2;
00143             for (int x=0; x<64; x++, v++) {
00144                 *p ++ = (*v & 0xf8) | (*v >> 5);
00145                 *p ++ = ((*v << 3) & 0xe0) | (*v >> 3);
00146             }
00147         }
00148         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00149 #endif
00150 
00151 #if 0   /* D4: Set 1 to test RGB332 mode */
00152         if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_RGB332, UCAM_RAW_RESOLUTION_80X60, cam))
00153             goto ERROR;
00154 
00155         for (int y=0; y<48; y++) {
00156             unsigned char *v = cam + ((80-64)/2 + ((60-48)/2+y)*80);
00157             unsigned char *p = oled + y*64*2;
00158             for (int x=0; x<64; x++, v++) {
00159                 int B = (*v & 0xe0) >> 5; /* 3bits */
00160                 int G = (*v & 0x1c) >> 3; /* 3bits */
00161                 int R = (*v & 0x3);       /* 2bits */
00162                 *p ++ = (B << 6) | G;
00163                 *p ++ =  R << 2;
00164             }
00165         }
00166         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00167 #endif
00168 
00169 #if 0   /* D5: Set 1 to test cropping (digital zoom) */
00170         if (!ucam.SnapshotRawCrop(UCAM_COLOR_TYPE_RGB565,
00171                                   UCAM_RAW_RESOLUTION_160X120, 48, 36, 64, 48, cam))
00172             goto ERROR;
00173 
00174         unsigned char *rg = cam;
00175         unsigned char *gb = rg + 1;
00176         unsigned char *p = oled;
00177         for (int i=64*48; i>0; i--, rg+=2, gb+=2) {
00178             *p ++ = (*gb <<3)    | (*rg & 0x7);
00179             *p ++ = (*gb & 0xe0) | (*rg >> 3);
00180         }
00181         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00182 #endif
00183 
00184 #if 0   /* D6: Set 1 to test 8bit gray differential image */
00185         unsigned char cam2[80*60];
00186         static unsigned char *camp = cam, *cam2p = cam2;
00187 
00188         if (!ucam.SnapshotRaw(UCAM_COLOR_TYPE_8BITG, UCAM_RAW_RESOLUTION_80X60, camp))
00189             goto ERROR;
00190 
00191         for (int y=0; y<48; y++) {
00192             unsigned char *v = camp + (80-64)/2 + ((60-48)/2+y)*80;
00193             unsigned char *b = cam2p + (80-64)/2 + ((60-48)/2+y)*80;
00194             unsigned char *p = oled + y*64*2;
00195 
00196             for (int x=0; x<64; x++, v++, b++) {
00197                 if (abs(*v-*b)>10) {
00198                     *p ++ = (*v & 0xf8) | (*v >> 5);
00199                     *p ++ = ((*v << 3) & 0xe0) | (*v >> 3);
00200                 } else {
00201                     *p ++ = 0;
00202                     *p ++ = 0;
00203                 }
00204             }
00205         }
00206         if (camp == cam) {
00207             camp = cam2;
00208             cam2p = cam;
00209         } else {
00210             camp = cam;
00211             cam2p = cam2;
00212         }
00213         ISC15.Disp(ISC15_DSPMODE_64K, oled);
00214 #endif
00215 
00216 #if 0   /* D7: Set 1 to show RGB565 image when images' differential is large */
00217         unsigned char cam2[80*60*2];
00218         static unsigned char *camp = cam, *cam2p = cam2;
00219 
00220         if (!ucam.SnapshotRawCrop(UCAM_COLOR_TYPE_RGB565,
00221                                   UCAM_RAW_RESOLUTION_80X60, 8, 6, 64, 48, camp))
00222             goto ERROR;
00223 
00224         unsigned char *rg = camp;
00225         unsigned char *gb = rg + 1;
00226         unsigned char *rg0 = cam2p;
00227         unsigned char *gb0 = rg0 + 1;
00228         unsigned int diff = 0;
00229 
00230         for (int i=64*48; i>0; i--, rg+=2, gb+=2, rg0+=2, gb0+=2)
00231             diff += abs(((*rg & 0x7)<<3 | (*gb >> 5))-((*rg0 & 0x7)<<3 | (*gb0>> 5)));
00232         LCDPRINTF("d: %d.\n", diff);
00233 
00234         if (diff > 3000) {
00235             rg = camp;
00236             gb = rg + 1;
00237             unsigned char *p = oled;
00238             for (int i=64*48; i>0; i--, rg+=2, gb+=2) {
00239                 *p ++ = (*gb <<3)    | (*rg & 0x7);
00240                 *p ++ = (*gb & 0xe0) | (*rg >> 3);
00241             }
00242             ISC15.Disp(ISC15_DSPMODE_64K, oled);
00243         } else {
00244             ISC15.Cls();
00245         }
00246         if (camp == cam) {
00247             camp = cam2;
00248             cam2p = cam;
00249         } else {
00250             camp = cam;
00251             cam2p = cam2;
00252         }
00253 #endif
00254 
00255         if (sw1pressed) {
00256             char fname[20];
00257 //            sprintf(fname, "/sd/%05d.jpg", n); // Save to SD-Card
00258             sprintf(fname, "/local/%05d.jpg", n); // Save to local flash memory
00259             LCDPRINTF("Saving image\n");
00260             SaveJPEG(fname);
00261             LCDPRINTF("DONE        \n");
00262             n ++;
00263             sw1pressed = false;
00264             led2 = 0;
00265         }
00266     }
00267 
00268 ERROR:
00269     LCDPRINTF("ERROR\n");
00270     while (1) {
00271         led1 = 1;
00272         wait(0.1);
00273         led1 = 0;
00274         wait(0.1);
00275     }
00276 }
00277 
00278 /* ------------------------------------------ */
00279 /*   Check current status of the switch       */
00280 /*   The fuction is called by 20ms timer      */
00281 /* ------------------------------------------ */
00282 void checkSW() {
00283     if (sw1 == 0) {
00284         /* Swtich is pressed */
00285         sw1pressed = true;
00286         sw1pressing = true;
00287         led2 = 1;
00288     } else {
00289         /* Switch is open */
00290         sw1pressing = false;
00291         led2 = 0;
00292     }
00293 }
00294 
00295 /* ------------------------------------------ */
00296 /* Save a JPEG image read from uCam to a file */
00297 /* ------------------------------------------ */
00298 int SaveJPEG(const char *fname) {
00299     /* Open file */
00300     FILE *fp = fopen(fname, "wb");
00301     if (fp == NULL) {
00302         LCDPRINTF("XXX %s\n", fname);
00303         return 0;
00304     }
00305 
00306     /* Prepare to recieve JPEG image */    
00307     int sz = ucam.SnapshotJPEGi(UCAM_JPEG_RESOLUTION_320X240, 512);
00308     if (sz == 0)
00309         return 0;
00310 
00311     /* Recieve packets */
00312     int pno = 0;
00313     unsigned char cam[512];
00314     while (sz > 0) {
00315         int pksz = 512;
00316         led2 = ~led2;
00317 
00318         if (sz < (512 - 6))
00319             pksz = sz + 6;
00320         LCDPRINTF("%d %d\n", pno, pksz);
00321         /* Recieve a packet */
00322         if (!ucam.SnapshotJPEGd(pno, cam, pksz)) {
00323             if (fp != NULL)
00324                 fclose(fp);
00325             return 0;
00326         }
00327         /* Write the packet */
00328         if (fp != NULL)
00329             fwrite(cam + 4, 1, pksz - 6, fp);
00330         sz -= (pksz - 6);
00331         pno ++;
00332         /* Check end of the image */
00333         if (sz == 0) {
00334             if (pksz == 512) {
00335                 // Send reset command as manual says
00336                 wait_ms(3);
00337                 ucam.Reset();
00338                 ucam.Init();
00339             } else {
00340                 ucam.ACK_F0F0();
00341             }
00342         }
00343     }
00344     fclose(fp);
00345 
00346     return 1;
00347 }