First release

Dependencies:   EthernetInterface HTTPServer TextLCD mbed-rpc mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2014, Sumio Morioka
00003  * All rights reserved.
00004  *
00005  * This source code was originally written by Dr.Sumio Morioka for use in the Oct 2014 issue of 
00006  * "the Interface magazine", published by CQ publishing Co.Ltd in Japan (http://www.cqpub.co.jp).
00007  * The author has no responsibility on any results caused by using this code.
00008  *
00009  * - Distribution date of this code: Aug 26, 2014
00010  * - Author: Dr.Sumio Morioka (http://www002.upp.so-net.ne.jp/morioka)
00011  *
00012  *
00013  * IMPORTANT NOTICE:
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *   * Redistributions of source code must retain the above copyright
00017  *     notice, this list of conditions and the following disclaimer.
00018  *   * Redistributions in binary form must reproduce the above copyright
00019  *     notice, this list of conditions and the following disclaimer in the
00020  *     documentation and/or other materials provided with the distribution.
00021  *   * Neither the name of the copyright holder nor the
00022  *     names of its contributors may be used to endorse or promote products
00023  *     derived from this software without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00026  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00027  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00029  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00030  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00032  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  */
00036  
00037 #include "mbed.h"
00038 #include "mbed_rpc.h"
00039 
00040 #include "TextLCD.h"
00041 #include "LocalFileSystem.h"
00042 
00043 #include "EthernetInterface.h"
00044 #include "HTTPServer.h"
00045 #include "FsHandler.h"
00046 #include "RpcHandler.h"
00047 
00048 #include "ov7670.h"
00049 
00050 TextLCD lcd(p24, p26, p27, p28, p29, p30);
00051 
00052 
00053 //#define USE_RPCOUT
00054 #undef USE_RPCOUT
00055 
00056 #ifndef USE_RPCOUT
00057 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
00058 PwmOut sv0(p21), sv1(p22), sv2(p23);
00059 #else
00060 RpcDigitalOut led1(LED1, "led1");
00061 RpcDigitalOut led2(LED2, "led2");
00062 RpcDigitalOut led3(LED3, "led3");
00063 RpcDigitalOut led4(LED4, "led4");
00064 
00065 RpcPwmOut sv0(p21, "sv0");
00066 RpcPwmOut sv1(p22, "sv1");
00067 RpcPwmOut sv2(p23, "sv2");
00068 #endif
00069 
00070 
00071 LocalFileSystem local("webfs");
00072 
00073 OV7670 camera(
00074     p9,p10,         // SDA,SCL(I2C / SCCB)
00075     p5,p6,p7,       // VSYNC,HREF,WEN(FIFO)
00076     p20,p19,p18,p17,p16,p15,p14,p13,    // D7-D0
00077     p8,p11,p12);    // RRST,OE,RCLK
00078 
00079 //Timer tmr;
00080 
00081 #define QQVGA
00082 //#define QVGA
00083 //#define VGA34
00084 
00085 #ifdef QQVGA
00086 #define SIZEX 160
00087 #define SIZEY 120
00088 #endif
00089 
00090 #ifdef QVGA
00091 #define SIZEX 320
00092 #define SIZEY 240
00093 #endif
00094 
00095 #ifdef VGA34
00096 #define SIZEX 480
00097 #define SIZEY 360
00098 #endif
00099 
00100 
00101 //void cam_cap(void);
00102 void cam_cap(Arguments* input, Reply* output);
00103 RPCFunction rpcFunc(&cam_cap, "cam_cap");
00104 
00105 #ifndef USE_RPCOUT
00106 float   sv0_rpc;
00107 float   sv1_rpc;
00108 float   sv2_rpc;
00109 
00110 RPCVariable<float> rpc_sv0_val(&sv0_rpc, "sv0");
00111 RPCVariable<float> rpc_sv1_val(&sv1_rpc, "sv1");
00112 RPCVariable<float> rpc_sv2_val(&sv2_rpc, "sv2");
00113 #endif
00114 
00115 int     cap_flag;
00116 RPCVariable<int> rpc_cap_flag(&cap_flag, "cap_flag");
00117 
00118 
00119 int memfree(void)
00120 {
00121     int ret = 1;
00122     while (1) {
00123         char    *p  = (char *)malloc(ret);
00124         if (p == NULL)
00125             break;
00126         free(p);
00127         ret++;
00128     }
00129     return (ret);
00130 }
00131 
00132 
00133 float deg_to_pulsewidth(float deg)
00134 {
00135     // limit range
00136     if (deg < -90.0f)
00137         deg = -90.0f;
00138     else if (deg > 90.0f)
00139         deg = 90.0f;
00140 
00141     // return result
00142     return (0.00145f + 0.001f * (deg / 90.0f));
00143 }
00144 
00145 int main() 
00146 {
00147     float   sv0_val, sv1_val, sv2_val;
00148     
00149 #ifndef USE_RPCOUT
00150     led1 = 0;
00151     led2 = 0;
00152     led3 = 0;
00153     led4 = 0;
00154 #else
00155     led1.write(0);
00156     led2.write(0);
00157     led3.write(0);
00158     led4.write(0);
00159 #endif
00160 
00161 #ifdef USE_RPCOUT
00162     sv0_val = 0.00045f;         // unit: sec
00163     sv1_val = 0.00145f;         // unit: sec
00164     sv2_val = 0.00245f;         // unit: sec
00165 
00166     sv0.period(0.02f);          // unit: sec
00167     sv0.pulsewidth(sv0_val);
00168 
00169     sv1.period(0.02f);          // unit: sec
00170     sv1.pulsewidth(sv1_val);
00171 
00172     sv2.period(0.02f);          // unit: sec
00173     sv2.pulsewidth(sv2_val);
00174 
00175 #else
00176     sv0_val = 0.0f;             // unit: deg
00177     sv1_val = 0.0f;             // unit: deg
00178     sv2_val = 0.0f;             // unit: deg
00179     
00180     sv0.period(0.02f);          // unit: sec
00181     sv0.pulsewidth(deg_to_pulsewidth(sv0_val));
00182 
00183     sv1.period(0.02f);          // unit: sec
00184     sv1.pulsewidth(deg_to_pulsewidth(sv1_val));
00185 
00186     sv2.period(0.02f);          // unit: sec
00187     sv2.pulsewidth(deg_to_pulsewidth(sv2_val));
00188 
00189     sv0_rpc = sv0_val;
00190     sv1_rpc = sv1_val;
00191     sv2_rpc = sv2_val;
00192 #endif
00193     
00194     cap_flag    = 0;
00195 
00196     ////////////////////////////////////////////////////////////////////////////
00197     camera.WriteReg(0x12, 0x80);            // com7; reset
00198     wait_ms(200);
00199 
00200     camera.InitDefaultReg();
00201 
00202     // negate vsync
00203     camera.WriteReg(0x15, 0x02);            // com10; negative vsync
00204 
00205 #ifdef QQVGA
00206     camera.InitQQVGA();
00207 #endif
00208 #ifdef QVGA
00209     camera.InitQVGA();
00210 #endif
00211 #ifdef VGA34
00212     camera.InitVGA_3_4();
00213 #endif
00214 
00215     // data format
00216     camera.WriteReg(0x12, 0x04 + 0);    // com7 RGB (bit1...test pattern)
00217     camera.WriteReg(0x40, 0xD0);    // com15 RGB565
00218     camera.WriteReg(0x8c, 0x00);    // RGB444
00219 
00220     wait_ms(300);
00221 
00222 //{
00223 //FILE *f = fopen("/webfs/REG.TXT", "wt");
00224 //for (int i = 0; i < 256; i++) {
00225 //    int val = camera.ReadReg(i);
00226 //  fprintf(f, "%02X ", val);
00227 //  if ((i % 16) == 15)
00228 //      fprintf(f, "\n");
00229 //}
00230 //fclose(f);
00231 //}
00232 
00233     //////////////////////////////////////////////////
00234 
00235     // network
00236     EthernetInterface   eth;    // locate here
00237 
00238 //  //Static IP
00239 //  char *ip        = "192.168.0.20";
00240 //  char *mask      = "255.255.255.0";
00241 //  char *gateway   = "192.168.0.1";
00242 //  eth.init(ip, mask, gateway);
00243     //DHCP
00244     eth.init();
00245 
00246     eth.connect();
00247 
00248     lcd.locate(0, 0);
00249     lcd.printf("IP %s", eth.getIPAddress());
00250 
00251     // rcp
00252 #ifdef USE_RPCOUT
00253 //    RPC::add_rpc_class<RpcDigitalIn>();       // read
00254     RPC::add_rpc_class<RpcDigitalOut>();        // read,write
00255 //    RPC::add_rpc_class<RpcDigitalInOut>();    // read,write,input,output
00256     RPC::add_rpc_class<RpcPwmOut>();            // read,write,period,period_ms,pulsewidth,pulsewidth_ms
00257 //    RPC::add_rpc_class<RpcAnalogIn>();        // read,read_u16
00258 //    RPC::add_rpc_class<RpcAnalogOut>();       // read,write,write_u16
00259 //    RPC::add_rpc_class<RpcSPI>();             // format,frequency,write
00260 //    RPC::add_rpc_class<RpcSerial>();          // baud,readable,writeable(SPELL?),putc,getc,puts
00261 //    RPC::add_rpc_class<RpcTimer>();           // start,stop,reset,read,read_ms,read_us
00262 #endif
00263 
00264     // http
00265     HTTPServer svr;         // locate here
00266     HTTPFsRequestHandler::mount("/webfs/", "/");
00267     svr.addHandler<HTTPFsRequestHandler>("/");
00268     svr.addHandler<HTTPRpcRequestHandler>("/rpc");
00269 
00270     svr.start(80, &eth);
00271 
00272 //    lcd.locate(0, 1);
00273 //    lcd.printf("mem %d", memfree());
00274         
00275 #ifndef USE_RPCOUT
00276     led1 = 1;
00277 #else
00278     led1.write(1);
00279 #endif
00280 
00281     while (1) {
00282         svr.poll();
00283 
00284 #ifndef USE_RPCOUT
00285         if (sv0_val != sv0_rpc) {
00286             sv0_val = sv0_rpc;
00287             // limit
00288             if (sv0_val < -90.0f)
00289                 sv0_val = -90.0f;
00290             else if (sv0_val > 90.0f)
00291                 sv0_val = 90.0f;
00292 
00293             sv0_rpc = sv0_val;
00294             sv0.pulsewidth(deg_to_pulsewidth(sv0_val));
00295 
00296             lcd.locate(0, 1);
00297             lcd.printf("0:%f ", sv0_val);
00298         }
00299 
00300         if (sv1_val != sv1_rpc) {
00301             sv1_val = sv1_rpc;
00302             // limit
00303             if (sv1_val < -90.0f)
00304                 sv1_val = -90.0f;
00305             else if (sv1_val > 90.0f)
00306                 sv1_val = 90.0f;
00307 
00308             sv1_rpc = sv1_val;
00309             sv1.pulsewidth(deg_to_pulsewidth(sv1_val));
00310 
00311             lcd.locate(0, 1);
00312             lcd.printf("1:%f ", sv1_val);
00313         }
00314 
00315         if (sv2_val != sv2_rpc) {
00316             sv2_val = sv2_rpc;
00317             // limit
00318             if (sv2_val < -90.0f)
00319                 sv2_val = -90.0f;
00320             else if (sv2_val > 90.0f)
00321                 sv2_val = 90.0f;
00322 
00323             sv2_rpc = sv2_val;
00324             sv2.pulsewidth(deg_to_pulsewidth(sv2_val));
00325 
00326             lcd.locate(0, 1);
00327             lcd.printf("2:%f ", sv2_val);
00328         }
00329 #endif
00330 
00331         wait_ms(10);
00332    }
00333 }
00334 
00335 
00336 //void cam_capture(char *input, char *output)       // compile error
00337 void cam_cap(Arguments* input, Reply* output)
00338 //void cam_cap(void)
00339 {
00340     FILE *fp_bmp;
00341     unsigned int d1, d2;
00342     unsigned char sort[3];
00343 
00344 #ifndef USE_RPCOUT
00345     led2 = 1;
00346 #else
00347     led2.write(1);
00348 #endif
00349 
00350     cap_flag    = 0;
00351 
00352     fp_bmp  = fopen("/webfs/cam.bmp", "wb");
00353 
00354     /////////////////////////
00355     // file header
00356     /////////////////////////
00357     fprintf(fp_bmp, "BM");
00358     int val = 14 + 40 + SIZEX * SIZEY * 3;   // file size
00359     fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
00360     fprintf(fp_bmp, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0x36, 0, 0, 0);
00361 
00362     /////////////////////////
00363     // information header
00364     /////////////////////////
00365     fprintf(fp_bmp, "%c%c%c%c", 0x28, 0, 0, 0);  // header size
00366     fprintf(fp_bmp, "%c%c%c%c", SIZEX % 0x100, SIZEX / 0x100, SIZEX / 0x10000, SIZEX / 0x1000000);
00367     fprintf(fp_bmp, "%c%c%c%c", SIZEY % 0x100, SIZEY / 0x100, SIZEY / 0x10000, SIZEY / 0x1000000);
00368     fprintf(fp_bmp, "%c%c", 1, 0);               // # of plane
00369     fprintf(fp_bmp, "%c%c", 24, 0);              // bit count
00370     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);     // compression
00371     val = SIZEX * SIZEY * 3;         // data size
00372     fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
00373     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00374     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00375     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00376     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00377 
00378     camera.CaptureNext();   // sample start!
00379 
00380     while(camera.CaptureDone() == false)
00381         ;
00382 
00383     camera.ReadStart();     // reset pointer
00384 
00385 #ifndef USE_RPCOUT
00386     led3 = 1;
00387 #else
00388     led3.write(1);
00389 #endif
00390 
00391     for (int y = 0;y < SIZEY;y++) {    
00392         for (int x = 0;x < SIZEX;x++) {
00393             d1 = camera.ReadOneByte() ; // upper nibble is XXX , lower nibble is B
00394             d2 = camera.ReadOneByte() ; // upper nibble is G   , lower nibble is R
00395 
00396             // RGB565
00397             sort[0] = ((d1 & 0xF8) >> 3) << 3;      // R
00398             sort[1] = ( ((d1 & 0x07) << 3) + ((d2 & 0xE0) >> 5) ) << 2;     // G
00399             sort[2] = (d2 & 0x1F) << 3;             // B
00400 
00401             fprintf(fp_bmp, "%c%c%c", sort[2], sort[1], sort[0]);       // B,G,R
00402         }
00403     }
00404 
00405     camera.ReadStop();
00406     fclose(fp_bmp);
00407 
00408 #ifndef USE_RPCOUT
00409     led2 = 0;
00410     led3 = 0;
00411     led4 = 0;
00412 #else
00413     led2.write(0);
00414     led3.write(0);
00415     led4.write(0);
00416 #endif
00417 
00418     cap_flag    = 1;
00419 }
00420 
00421 // end of file