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

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;
+}