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, committed 2011-10-06
- Comitter:
- non
- Date:
- Thu Oct 06 00:54:08 2011 +0000
- Child:
- 1:e848ee65abc9
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_unsupported/code/fatfilesystem/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/simon/code/SDFileSystem/#b1ddfc9a9b25
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.cpp Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,159 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford + * + * 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 "TextLCD.h" +#include "mbed.h" + +TextLCD::TextLCD(PinName rs, PinName e, PinName d0, PinName d1, + PinName d2, PinName d3, LCDType type) : _rs(rs), + _e(e), _d(d0, d1, d2, d3), + _type(type) { + + _e = 1; + _rs = 0; // command mode + + wait(0.015); // Wait 15ms to ensure powered up + + // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) + for (int i=0; i<3; i++) { + writeByte(0x3); + wait(0.00164); // this command takes 1.64ms, so wait for it + } + writeByte(0x2); // 4-bit mode + wait(0.000040f); // most instructions take 40us + + writeCommand(0x28); // Function set 001 BW N F - - + writeCommand(0x0C); + writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes + cls(); +} + +void TextLCD::character(int column, int row, int c) { + int a = address(column, row); + writeCommand(a); + writeData(c); +} + +void TextLCD::cls() { + writeCommand(0x01); // cls, and set cursor to 0 + wait(0.00164f); // This command takes 1.64 ms + locate(0, 0); +} + +void TextLCD::locate(int column, int row) { + _column = column; + _row = row; +} + +int TextLCD::_putc(int value) { + if (value == '\n') { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } else { + character(_column, _row, value); + _column++; + if (_column >= columns()) { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } + } + return value; +} + +int TextLCD::_getc() { + return -1; +} + +void TextLCD::writeByte(int value) { + _d = value >> 4; + wait(0.000040f); // most instructions take 40us + _e = 0; + wait(0.000040f); + _e = 1; + _d = value >> 0; + wait(0.000040f); + _e = 0; + wait(0.000040f); // most instructions take 40us + _e = 1; +} + +void TextLCD::writeCommand(int command) { + _rs = 0; + writeByte(command); +} + +void TextLCD::writeData(int data) { + _rs = 1; + writeByte(data); +} + +int TextLCD::address(int column, int row) { + switch (_type) { + case LCD20x4: + switch (row) { + case 0: + return 0x80 + column; + case 1: + return 0xc0 + column; + case 2: + return 0x94 + column; + case 3: + return 0xd4 + column; + } + case LCD16x2B: + return 0x80 + (row * 40) + column; + case LCD16x2: + case LCD20x2: + default: + return 0x80 + (row * 0x40) + column; + } +} + +int TextLCD::columns() { + switch (_type) { + case LCD20x4: + case LCD20x2: + return 20; + case LCD16x2: + case LCD16x2B: + default: + return 16; + } +} + +int TextLCD::rows() { + switch (_type) { + case LCD20x4: + return 4; + case LCD16x2: + case LCD16x2B: + case LCD20x2: + default: + return 2; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.h Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,111 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford + * + * 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. + */ + +#ifndef MBED_TEXTLCD_H +#define MBED_TEXTLCD_H + +#include "mbed.h" + +/** A TextLCD interface for driving 4-bit HD44780-based LCDs + * + * Currently supports 16x2, 20x2 and 20x4 panels + * + * @code + * #include "mbed.h" + * #include "TextLCD.h" + * + * TextLCD lcd(p10, p12, p15, p16, p29, p30); // rs, e, d0-d3 + * + * int main() { + * lcd.printf("Hello World!\n"); + * } + * @endcode + */ +class TextLCD : public Stream { +public: + + /** LCD panel format */ + enum LCDType { + LCD16x2 /**< 16x2 LCD panel (default) */ + , LCD16x2B /**< 16x2 LCD panel alternate addressing */ + , LCD20x2 /**< 20x2 LCD panel */ + , LCD20x4 /**< 20x4 LCD panel */ + }; + + /** Create a TextLCD interface + * + * @param rs Instruction/data control line + * @param e Enable line (clock) + * @param d0-d3 Data lines + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ + TextLCD(PinName rs, PinName e, PinName d0, PinName d1, PinName d2, PinName d3, LCDType type = LCD16x2); + +#if DOXYGEN_ONLY + /** Write a character to the LCD + * + * @param c The character to write to the display + */ + int putc(int c); + + /** Write a formated string to the LCD + * + * @param format A printf-style format string, followed by the + * variables to use in formating the string. + */ + int printf(const char* format, ...); +#endif + + /** Locate to a screen column and row + * + * @param column The horizontal position from the left, indexed from 0 + * @param row The vertical position from the top, indexed from 0 + */ + void locate(int column, int row); + + /** Clear the screen and locate to 0,0 */ + void cls(); + + int rows(); + int columns(); + +protected: + + // Stream implementation functions + virtual int _putc(int value); + virtual int _getc(); + + int address(int column, int row); + void character(int column, int row, int c); + void writeByte(int value); + void writeCommand(int command); + void writeData(int data); + + DigitalOut _rs, _e; + BusOut _d; + LCDType _type; + + int _column; + int _row; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/isc15.cpp Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,227 @@ +/* mbed NKK IS-C15/C01 oLED switch 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 "isc15.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// Some constants +//////////////////////////////////////////////////////////////////////////////////////// +const int DAT = 1; +const int CMD = 0; + +//////////////////////////////////////////////////////////////////////////////////////// +// OLED's initial setup commands (IS15) +//////////////////////////////////////////////////////////////////////////////////////// +const unsigned char SetupColumnAddress[] = { 0x03, 0x15, 0x10, 0x4f }; +const unsigned char SetupRowaddress[] = { 0x03, 0x75, 0x00, 0x2f }; +const unsigned char SetContrastColorA[] = { 0x02, 0x81, 0x19 }; +const unsigned char SetContrastColorB[] = { 0x02, 0x82, 0x14 }; +const unsigned char SetContrastColorC[] = { 0x02, 0x83, 0x24 }; +const unsigned char MasterCurrentControl[] = { 0x02, 0x87, 0x0f }; +const unsigned char RemapColorDepth[] = { 0x02, 0xa0, 0x70 }; +const unsigned char SetDisplayStartLine[] = { 0x02, 0xa1, 0x00 }; +const unsigned char SetDisplayOffset[] = { 0x02, 0xa2, 0x10 }; +const unsigned char SetDisplayMode[] = { 0x01, 0xa4 }; +const unsigned char SetMultiplexRatio[] = { 0x02, 0xa8, 0x2f }; +const unsigned char DimModeSetting[] = { 0x05, 0xab, 0x12, 0x0c, 0x14, 0x12 }; +const unsigned char SetDisplayDim[] = { 0x01, 0xac }; +const unsigned char SetDisplayOff[] = { 0x01, 0xae }; +const unsigned char SetDisplayNormal[] = { 0x01, 0xaf }; +const unsigned char SetMasterConfiguration[] = { 0x02, 0xad, 0x8e }; +const unsigned char PhasePeriodAdjustment[] = { 0x02, 0xb1, 0x44 }; +const unsigned char DisplayClockDivider[] = { 0x02, 0xb3, 0xa0 }; +const unsigned char EnableLinearGrayScale[] = { 0x01, 0xb9 }; +const unsigned char SetPrechargeLevel[] = { 0x02, 0xbb, 0x12 }; +const unsigned char SetVcomh[] = { 0x03, 0xbe, 0x28 }; + +const unsigned char ColorDepth64k[] = { 0x02, 0xa0, 0x70 }; +const unsigned char ColorDepth256[] = { 0x02, 0xa0, 0x30 }; + +// OLED's initial setup commands (for display only type (IS01) ) +const unsigned char SetupColumnAddress_d[] = { 0x03, 0x15, 0x16, 0x49 }; //display +const unsigned char SetupRowaddress_d[] = { 0x03, 0x75, 0x00, 0x23 }; //display +const unsigned char SetContrastColorA_d[] = { 0x02, 0x81, 0x0f }; //display +const unsigned char SetContrastColorB_d[] = { 0x02, 0x82, 0x0e }; //display +const unsigned char SetContrastColorC_d[] = { 0x02, 0x83, 0x1b }; //display +const unsigned char SetDisplayOffset_d[] = { 0x02, 0xa2, 0x1c }; //display +const unsigned char SetMultiplexRatio_d[] = { 0x02, 0xa8, 0x23 }; //display +const unsigned char DimModeSetting_d[] = { 0x05, 0xab, 0x0b, 0x08, 0x0f, 0x12 }; //display +const unsigned char DisplayClockDivider_d[] = { 0x02, 0xb3, 0x30 }; //display +const unsigned char SetVcomh_d[] = { 0x03, 0xbe, 0x21 }; //display + +// +// Change OLED's address setting +// +void ISC15::AdrInit( int DevType ) { + if (spi == NULL) + return; + + if (DevType == ISC15_DEVICE_ISC15) { + SendCommand( SetupColumnAddress ); + SendCommand( SetupRowaddress ); + } else { + SendCommand( SetupColumnAddress_d ); + SendCommand( SetupRowaddress_d ); + } +} + + +// +// Display data on OLED +// +void ISC15::Disp( int Mode, const unsigned char *dat ) { + if (spi == NULL) + return; + + AdrInit(DevType); + DspMode(Mode); + if (Mode == ISC15_DSPMODE_64K) + SendData(dat, ISC15_WIDTH*ISC15_HEIGHT*2); + else + SendData(dat, ISC15_WIDTH*ISC15_HEIGHT); +} + +// +// Change OLED's color depth setting (64K or 256 colors) +// +void ISC15::DspMode( int DspMode ) { + if (spi == NULL) + return; + + if ( DspMode == ISC15_DSPMODE_64K ) { + SendCommand( ColorDepth64k ); + } else { + SendCommand( ColorDepth256 ); + } +} + +// +// Fill out display +// +void ISC15::Fill(unsigned char c) { + if (spi == NULL) + return; + + AdrInit(DevType); + DspMode(0); + + is_dc = DAT; + for (int i = ISC15_WIDTH*ISC15_HEIGHT; i>0; i --) { + is_cs = 0; + spi->write(c); + is_cs = 1; + } +} + +// +// initial settings of OLED +// +void ISC15::Init( int DeviceType, SPI *s ) { + volatile unsigned char delay = 0x20; + + DevType = DeviceType; + spi = s; + + // reset OLED + is_vcc = 0; + is_reset = 0; + wait_us(3); + is_reset = 1; + is_vcc = 1; + + // initial settings + AdrInit(DevType); + + if (DevType == ISC15_DEVICE_ISC15) { + SendCommand( SetContrastColorA ); + SendCommand( SetContrastColorB ); + SendCommand( SetContrastColorC ); + SendCommand( MasterCurrentControl ); + SendCommand( SetDisplayStartLine ); + SendCommand( SetDisplayOffset ); + SendCommand( SetDisplayMode ); + SendCommand( SetMultiplexRatio ); + SendCommand( DimModeSetting ); + SendCommand( SetMasterConfiguration ); + SendCommand( PhasePeriodAdjustment ); + SendCommand( DisplayClockDivider ); + SendCommand( EnableLinearGrayScale ); + SendCommand( SetPrechargeLevel ); + SendCommand( SetVcomh ); + } else { + SendCommand( SetContrastColorA_d ); + SendCommand( SetContrastColorB_d ); + SendCommand( SetContrastColorC_d ); + SendCommand( MasterCurrentControl ); + SendCommand( SetDisplayStartLine ); + SendCommand( SetDisplayOffset_d ); + SendCommand( SetDisplayMode ); + SendCommand( SetMultiplexRatio_d ); + SendCommand( DimModeSetting_d ); + SendCommand( SetMasterConfiguration ); + SendCommand( PhasePeriodAdjustment ); + SendCommand( DisplayClockDivider_d ); + SendCommand( EnableLinearGrayScale ); + SendCommand( SetPrechargeLevel ); + SendCommand( SetVcomh_d ); + } + + // display mode settings + DspMode( ISC15_DSPMODE_64K); + + SendCommand( SetDisplayNormal ); +} + +// +// Send a command / data to OLED via SPI +// +void ISC15::Send( const unsigned char *p, int len ) { + if (spi == NULL) + return; + + for (; len>0; len --, p ++) { + is_cs = 0; + spi->write(*p); + is_cs = 1; + } +} + +// +// Send a command to OLED +// +void ISC15::SendCommand( const unsigned char *com ) { + if (spi == NULL) + return; + + is_dc = CMD; + Send(com+1, *com); +} + +// +// Send data to OLED +// +void ISC15::SendData( const unsigned char *dat, int len ) { + if (spi == NULL) + return; + + is_dc = DAT; + Send(dat, len); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/isc15.h Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,61 @@ +/* mbed NKK IS-C15/C01 oLED switch 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. + */ +#ifndef __ISC15_H__ +#define __ISC15_H__ + +#include "mbed.h" + +#define ISC15_DEVICE_ISC01 0 +#define ISC15_DEVICE_ISC15 1 + +#define ISC15_DSPMODE_256 0 +#define ISC15_DSPMODE_64K 1 + +#define ISC15_WIDTH 64 +#define ISC15_HEIGHT 48 + +class ISC15 { +public: + ISC15( PinName cs, PinName reset, PinName dc, PinName vcc ) + : is_cs(cs), is_reset(reset), is_dc(dc), is_vcc(vcc) { + DevType = 1; + spi = NULL; + } + void Cls() { + Fill(0); + }; + void Disp( int Mode, const unsigned char *dat ); + void Fill( unsigned char c ); + void Init( int DeviceType, SPI *s ); + +private: + DigitalOut is_cs, is_reset, is_dc, is_vcc; + int DevType; // 0:ISC01, 1:ISC15 + SPI *spi; + + void AdrInit( int DevType ); + void DspMode( int DspMode_ ); + void Send( const unsigned char *p, int len ); + void SendCommand( const unsigned char *com ); + void SendData( const unsigned char *dat, int len ); +}; +#endif
--- /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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ucam.h Thu Oct 06 00:54:08 2011 +0000 @@ -0,0 +1,82 @@ +/* 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. + */ +#ifndef __UCAM_H__ +#define __UCAM_H__ + +#include "mbed.h" + +#define UCAM_COLOR_TYPE_2BITG 0x1 +#define UCAM_COLOR_TYPE_4BITG 0x2 +#define UCAM_COLOR_TYPE_8BITG 0x3 +#define UCAM_COLOR_TYPE_RGB332 0x4 +#define UCAM_COLOR_TYPE_RGB444 0x5 +#define UCAM_COLOR_TYPE_RGB565 0x6 +#define UCAM_COLOR_TYPE_JPEG 0x7 + +#define UCAM_RAW_RESOLUTION_80X60 0x1 +#define UCAM_RAW_RESOLUTION_160X120 0x3 +#define UCAM_RAW_RESOLUTION_320X240 0x5 +#define UCAM_RAW_RESOLUTION_640X480 0x7 +#define UCAM_RAW_RESOLUTION_128x128 0x9 +#define UCAM_RAW_RESOLUTION_128x96 0xB + +const int ucam_raw_resolution_w[] = {80, 160, 320, 640, 128, 128}; +const int ucam_raw_resolution_h[] = {60, 120, 240, 480, 128, 96}; + +#define UCAM_JPEG_RESOLUTION_80X64 0x1 +#define UCAM_JPEG_RESOLUTION_160X128 0x3 +#define UCAM_JPEG_RESOLUTION_320X240 0x5 +#define UCAM_JPEG_RESOLUTION_640X480 0x7 + +class uCam { +public: + uCam(PinName tx, PinName rx) { + s = new Serial(tx, rx); + s->baud(57600); + } + ~uCam() { + delete s; + } + + int Command(const unsigned char *cmd); + void ACK_F0F0(); + int Init(); + int LightFreq(int f); + void Reset(); + int SnapshotRaw(int Color, int Res, unsigned char *buf); + int SnapshotRawCrop(int Color, int Res, + int x0, int y0, int w, int h, + unsigned char *buf); + int SnapshotJPEGi(int Res, int pksz); + int SnapshotJPEGd(int no, unsigned char *buf, int pksz); + +private: + Serial *s; + + int checkACK(const unsigned char *buf); + int checkSYNC(const unsigned char *buf); + void read(unsigned char *p, int len); + int readT(unsigned char *buf, int len); + void write(const unsigned char *p, int len); +}; + +#endif