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

main.cpp

Committer:
non
Date:
2011-10-13
Revision:
2:0621feb3adf2
Parent:
0:07d02a20d1cc

File content as of revision 2:0621feb3adf2:

/* 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;
}