TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers camera_app.cpp Source File

camera_app.cpp

00001 //*****************************************************************************
00002 // camera_app.c
00003 //
00004 // camera application macro & APIs
00005 //
00006 // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ 
00007 // 
00008 // 
00009 //  Redistribution and use in source and binary forms, with or without 
00010 //  modification, are permitted provided that the following conditions 
00011 //  are met:
00012 //
00013 //    Redistributions of source code must retain the above copyright 
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 //    Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the 
00018 //    documentation and/or other materials provided with the   
00019 //    distribution.
00020 //
00021 //    Neither the name of Texas Instruments Incorporated nor the names of
00022 //    its contributors may be used to endorse or promote products derived
00023 //    from this software without specific prior written permission.
00024 //
00025 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00026 //  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00027 //  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00028 //  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00029 //  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00030 //  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00031 //  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00032 //  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00033 //  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00034 //  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00035 //  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 //*****************************************************************************
00038 //*****************************************************************************
00039 //
00040 //! \addtogroup camera_app
00041 //! @{
00042 //
00043 //*****************************************************************************
00044 #include "mbed.h"
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 
00049 // SimpleLink include
00050 #include "cc3100_simplelink.h"
00051 
00052 #include "oslib/osi.h"
00053 #include "camera_app.h"
00054 #include "ArduCAM.h"
00055 #include "ov5642_regs.h"
00056 //#include "i2cconfig.h"
00057 //#include "camera.h"
00058 
00059 #include "app_config.h"
00060 #include "cli_uart.h"
00061 #include "Led_config.h"
00062 #include "HttpDebug.h"
00063 
00064 using namespace mbed_cc3100;
00065 
00066 
00067 ArduCAM myCAM(OV5642, p14, SPI(p11, p12, p13), I2C(p28, p27));
00068 
00069 //*****************************************************************************
00070 // Macros
00071 //*****************************************************************************
00072 #define USER_FILE_NAME          "www/images/cc3200_camera_capture.jpg"
00073 #define TOTAL_DMA_ELEMENTS      64
00074 #define AP_SSID_LEN_MAX         (33)
00075 #define ROLE_INVALID            (-5)
00076 //*****************************************************************************
00077 //                      GLOBAL VARIABLES
00078 //*****************************************************************************
00079 
00080 unsigned int g_frame_size_in_bytes;
00081 unsigned int g_uiDeviceModeConfig = ROLE_AP; //default is AP mode 
00082 extern volatile unsigned char g_CaptureImage;
00083 extern int g_uiIpObtained = 0;
00084 extern int g_uiSimplelinkRole = ROLE_INVALID;
00085 uint32_t picLoop = 0;
00086 unsigned int g_uiIpAddress = 0;
00087 volatile static unsigned char g_frame_end;
00088 
00089 #ifdef ENABLE_JPEG 
00090     int PIXELS_IN_X_AXIS = 320; 
00091     int PIXELS_IN_Y_AXIS = 240;
00092     int FRAME_SIZE_IN_BYTES = (320 * 240 * 2);
00093 #else
00094     int PIXELS_IN_X_AXIS = 240;
00095     int PIXELS_IN_Y_AXIS = 256;
00096     int FRAME_SIZE_IN_BYTES = (240 * 256 * 2);
00097 #endif    
00098 
00099 struct ImageBuffer
00100 {
00101 #ifdef ENABLE_JPEG
00102     char g_header[SMTP_BUF_LEN] /*= {'\0'}*/;
00103 #endif
00104     uint8_t g_image_buffer[IMAGE_BUF_SIZE];//12Kb
00105 };
00106 
00107 ImageBuffer g_image;
00108 
00109 typedef enum pictureRequest{
00110     NO_PICTURE = 0x00,
00111     SINGLE_HIGH_RESOLUTION = 0x01,
00112     STREAM_LOW_RESOLUTION = 0x02
00113       
00114 }e_pictureRequest;
00115 
00116 typedef enum pictureFormat{
00117     RAW_10BIT = 0,
00118     ITU_R_BT601,
00119     YCbCr_4_2_2,
00120     YCbCr_4_2_0,
00121     RGB_565,
00122     RGB_555,
00123     RGB_444
00124 
00125 }e_pictureFormat;
00126 
00127 typedef enum pictureResolution{
00128     QVGA = 0,
00129     VGA,
00130     SVGA,
00131     XGA,
00132     uXGA
00133 
00134 }e_pictureResolution;
00135 
00136 
00137 #ifdef ENABLE_JPEG
00138 #define FORMAT_YCBCR422   0
00139 #define FORMAT_YCBCR420   1
00140 #define FORMAT_MONOCHROME 2
00141 
00142 unsigned char JPEG_StdQuantTblY[64] =
00143 {
00144     16,  11,  10,  16,  24,  40,  51,  61,
00145     12,  12,  14,  19,  26,  58,  60,  55,
00146     14,  13,  16,  24,  40,  57,  69,  56,
00147     14,  17,  22,  29,  51,  87,  80,  62,
00148     18,  22,  37,  56,  68,  109, 103, 77,
00149     24,  35,  55,  64,  81,  104, 113, 92,
00150     49,  64,  78,  87, 103,  121, 120, 101,
00151     72,  92,  95,  98, 112,  100, 103,  99
00152 };
00153 
00154 unsigned char JPEG_StdQuantTblC[64] =
00155 {
00156     17,  18,  24,  47,  99,  99,  99,  99,
00157     18,  21,  26,  66,  99,  99,  99,  99,
00158     24,  26,  56,  99,  99,  99,  99,  99,
00159     47,  66,  99,  99,  99,  99,  99,  99,
00160     99,  99,  99,  99,  99,  99,  99,  99,
00161     99,  99,  99,  99,  99,  99,  99,  99,
00162     99,  99,  99,  99,  99,  99,  99,  99,
00163     99,  99,  99,  99,  99,  99,  99,  99
00164 };
00165 //
00166 // This table is used for regular-position to zigzagged-position lookup
00167 //  This is Figure A.6 from the ISO/IEC 10918-1 1993 specification 
00168 //
00169 static unsigned char zigzag[64] =
00170 {
00171     0, 1, 5, 6,14,15,27,28,
00172     2, 4, 7,13,16,26,29,42,
00173     3, 8,12,17,25,30,41,43,
00174     9,11,18,24,31,40,44,53,
00175     10,19,23,32,39,45,52,54,
00176     20,22,33,38,46,51,55,60,
00177     21,34,37,47,50,56,59,61,
00178     35,36,48,49,57,58,62,63
00179 };
00180 
00181 unsigned int JPEG_StdHuffmanTbl[384] =
00182 {
00183     0x100, 0x101, 0x204, 0x30b, 0x41a, 0x678, 0x7f8, 0x9f6,
00184     0xf82, 0xf83, 0x30c, 0x41b, 0x679, 0x8f6, 0xaf6, 0xf84,
00185     0xf85, 0xf86, 0xf87, 0xf88, 0x41c, 0x7f9, 0x9f7, 0xbf4,
00186     0xf89, 0xf8a, 0xf8b, 0xf8c, 0xf8d, 0xf8e, 0x53a, 0x8f7,
00187     0xbf5, 0xf8f, 0xf90, 0xf91, 0xf92, 0xf93, 0xf94, 0xf95,
00188     0x53b, 0x9f8, 0xf96, 0xf97, 0xf98, 0xf99, 0xf9a, 0xf9b,
00189     0xf9c, 0xf9d, 0x67a, 0xaf7, 0xf9e, 0xf9f, 0xfa0, 0xfa1,
00190     0xfa2, 0xfa3, 0xfa4, 0xfa5, 0x67b, 0xbf6, 0xfa6, 0xfa7,
00191     0xfa8, 0xfa9, 0xfaa, 0xfab, 0xfac, 0xfad, 0x7fa, 0xbf7,
00192     0xfae, 0xfaf, 0xfb0, 0xfb1, 0xfb2, 0xfb3, 0xfb4, 0xfb5,
00193     0x8f8, 0xec0, 0xfb6, 0xfb7, 0xfb8, 0xfb9, 0xfba, 0xfbb,
00194     0xfbc, 0xfbd, 0x8f9, 0xfbe, 0xfbf, 0xfc0, 0xfc1, 0xfc2,
00195     0xfc3, 0xfc4, 0xfc5, 0xfc6, 0x8fa, 0xfc7, 0xfc8, 0xfc9,
00196     0xfca, 0xfcb, 0xfcc, 0xfcd, 0xfce, 0xfcf, 0x9f9, 0xfd0,
00197     0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7, 0xfd8,
00198     0x9fa, 0xfd9, 0xfda, 0xfdb, 0xfdc, 0xfdd, 0xfde, 0xfdf,
00199     0xfe0, 0xfe1, 0xaf8, 0xfe2, 0xfe3, 0xfe4, 0xfe5, 0xfe6,
00200     0xfe7, 0xfe8, 0xfe9, 0xfea, 0xfeb, 0xfec, 0xfed, 0xfee,
00201     0xfef, 0xff0, 0xff1, 0xff2, 0xff3, 0xff4, 0xff5, 0xff6,
00202     0xff7, 0xff8, 0xff9, 0xffa, 0xffb, 0xffc, 0xffd, 0xffe,
00203     0x30a, 0xaf9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
00204     0xfd0, 0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7,
00205     0x101, 0x204, 0x30a, 0x418, 0x419, 0x538, 0x678, 0x8f4,
00206     0x9f6, 0xbf4, 0x30b, 0x539, 0x7f6, 0x8f5, 0xaf6, 0xbf5,
00207     0xf88, 0xf89, 0xf8a, 0xf8b, 0x41a, 0x7f7, 0x9f7, 0xbf6,
00208     0xec2, 0xf8c, 0xf8d, 0xf8e, 0xf8f, 0xf90, 0x41b, 0x7f8,
00209     0x9f8, 0xbf7, 0xf91, 0xf92, 0xf93, 0xf94, 0xf95, 0xf96,
00210     0x53a, 0x8f6, 0xf97, 0xf98, 0xf99, 0xf9a, 0xf9b, 0xf9c,
00211     0xf9d, 0xf9e, 0x53b, 0x9f9, 0xf9f, 0xfa0, 0xfa1, 0xfa2,
00212     0xfa3, 0xfa4, 0xfa5, 0xfa6, 0x679, 0xaf7, 0xfa7, 0xfa8,
00213     0xfa9, 0xfaa, 0xfab, 0xfac, 0xfad, 0xfae, 0x67a, 0xaf8,
00214     0xfaf, 0xfb0, 0xfb1, 0xfb2, 0xfb3, 0xfb4, 0xfb5, 0xfb6,
00215     0x7f9, 0xfb7, 0xfb8, 0xfb9, 0xfba, 0xfbb, 0xfbc, 0xfbd,
00216     0xfbe, 0xfbf, 0x8f7, 0xfc0, 0xfc1, 0xfc2, 0xfc3, 0xfc4,
00217     0xfc5, 0xfc6, 0xfc7, 0xfc8, 0x8f8, 0xfc9, 0xfca, 0xfcb,
00218     0xfcc, 0xfcd, 0xfce, 0xfcf, 0xfd0, 0xfd1, 0x8f9, 0xfd2,
00219     0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7, 0xfd8, 0xfd9, 0xfda,
00220     0x8fa, 0xfdb, 0xfdc, 0xfdd, 0xfde, 0xfdf, 0xfe0, 0xfe1,
00221     0xfe2, 0xfe3, 0xaf9, 0xfe4, 0xfe5, 0xfe6, 0xfe7, 0xfe8,
00222     0xfe9, 0xfea, 0xfeb, 0xfec, 0xde0, 0xfed, 0xfee, 0xfef,
00223     0xff0, 0xff1, 0xff2, 0xff3, 0xff4, 0xff5, 0xec3, 0xff6,
00224     0xff7, 0xff8, 0xff9, 0xffa, 0xffb, 0xffc, 0xffd, 0xffe,
00225     0x100, 0x9fa, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
00226     0xfd0, 0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7,
00227     0x100, 0x202, 0x203, 0x204, 0x205, 0x206, 0x30e, 0x41e,
00228     0x53e, 0x67e, 0x7fe, 0x8fe, 0xfff, 0xfff, 0xfff, 0xfff,
00229     0x100, 0x101, 0x102, 0x206, 0x30e, 0x41e, 0x53e, 0x67e,
00230     0x7fe, 0x8fe, 0x9fe, 0xafe, 0xfff, 0xfff, 0xfff, 0xfff
00231 };
00232 #endif 
00233 
00234 //*****************************************************************************
00235 //
00236 //!     Start Camera 
00237 //!     1. Establishes connection w/ AP//
00238 //!     2. Initializes the camera sub-components//! GPIO Enable & Configuration
00239 //!     3. Listens and processes the image capture requests from user-applications
00240 //!    
00241 //! \param[out]                      WriteBuffer - Pointer to the Frame Buffer  
00242 //!     \return                     None                         
00243 //
00244 //*****************************************************************************
00245 
00246 unsigned short StartCamera(char **WriteBuffer)
00247 {
00248     unsigned short Writelength;
00249     //
00250     // Waits in the below loop till Capture button is pressed
00251     //
00252     Writelength = CaptureImage(WriteBuffer);
00253 
00254     return(Writelength);
00255 
00256 }
00257 //*****************************************************************************
00258 //
00259 //!     InitCameraComponents 
00260 //!     PinMux, Camera Initialization and Configuration   
00261 //!
00262 //! \param[in] width - X-Axis
00263 //! \param[in] width - Y-Axis
00264 //! \return  None
00265 //
00266 //*****************************************************************************
00267 
00268 void InitCameraComponents(int width, int height)
00269 {    
00270     getCamId();
00271     
00272 #ifdef ENABLE_JPEG
00273     //Change to JPEG capture mode and initialize the OV5642 module    
00274     myCAM.set_format(JPEG);
00275 #endif    
00276     
00277     //
00278     // Initialize camera sensor
00279     //
00280     myCAM.InitCAM();
00281     myCAM.clear_fifo_flag();
00282     myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
00283     myCAM.write_reg(ARDUCHIP_FRAMES,0x00); //Bit[2:0]Number of frames to be captured
00284     
00285 }
00286 
00287 void getCamId(){
00288     
00289     uint8_t vid = 0;
00290     uint8_t pid = 0;
00291     
00292     //Check if the camera module type is OV5642
00293     myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
00294     myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
00295     if((vid != 0x56) || (pid != 0x42)){
00296       printf("Can't find OV5642 module! vid = 0x%x pid = 0x%x\r\n",vid, pid);
00297       while(1);
00298     }else{
00299       printf("OV5642 detected\r\n");
00300   }
00301 }   
00302 
00303 //*****************************************************************************
00304 //
00305 //!     CaptureImage 
00306 //!     Configures DMA and starts the Capture. Post Capture writes to SFLASH 
00307 //!    
00308 //! \param                      None  
00309 //!     \return                     None
00310 //!                               
00311 //
00312 //*****************************************************************************
00313 uint16_t CaptureImage(char** WriteBuffer)
00314 {
00315 
00316     //uint32_t g_header_length = 0;
00317     myCAM.flush_fifo();
00318     wait_ms(5);
00319     myCAM.clear_fifo_flag();     
00320     wait(1);
00321     //
00322     // Perform Image Capture 
00323     //
00324 #ifdef ENABLE_JPEG
00325     myCAM.start_capture();
00326 #else
00327 
00328 #endif 
00329 
00330     while (!(myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK))){
00331       wait_ms(100);
00332    }
00333    g_frame_size_in_bytes = myCAM.read_fifo_length();
00334    read_fifo_burst(); 
00335  
00336     /* Read the number of data items transferred in bytes) */
00337     if(g_frame_size_in_bytes <= 0 ){
00338         HttpDebug("\r\nFailed to capture or data over-run, check camera connections!\r\n");
00339         while(1){
00340             wait(0.5);
00341         }
00342     }   
00343        
00344     //
00345     // Create JPEG Header
00346     //
00347 #ifdef ENABLE_JPEG
00348 //    memset(g_image.g_header, '\0', sizeof(g_image.g_header));
00349 //    g_header_length = CreateJpegHeader((char *)&(g_image.g_header[0]), PIXELS_IN_X_AXIS,
00350 //                                       PIXELS_IN_Y_AXIS, 0, 0x0020, 9);
00351 //    HttpDebug("g_header_length = 0x%x \r\n",g_header_length);
00352     // This pushes the header to the start of the array so that the entire picture can be contiguous in memory
00353 //    memcpy(Image + g_header_length, Image, g_frame_size_in_bytes);
00354 //    memcpy(Image, g_image.g_header, g_header_length);
00355     // This pushes the header to the end of the array so that the entire picture can be contiguous in memory
00356 //    memcpy(Image + g_frame_size_in_bytes, g_image.g_header, g_header_length);
00357 
00358 #endif//ENABLE_JPEG
00359     picLoop++;
00360     HttpDebug("\r\nPicture Sent %d\r\n",picLoop);
00361 
00362     *WriteBuffer = (char*)g_image.g_image_buffer;
00363 
00364     return(g_frame_size_in_bytes);
00365 }
00366 
00367 uint8_t read_fifo_burst()
00368 {
00369     
00370     uint32_t bytesRead = 0;
00371     uint8_t temp = 0;
00372     uint8_t temp_last = 0;
00373     int32_t i;
00374     
00375     myCAM.cs_low(); 
00376     myCAM.set_fifo_burst();    
00377     myCAM._cam_spi.write(0x00);//Ignore first byte
00378     i = 0;
00379     while( 1 ){        
00380         temp_last = temp;    
00381         temp = (uint8_t )myCAM._cam_spi.write(0x00);
00382         g_image.g_image_buffer[i] = temp;
00383         i++;
00384         bytesRead++;
00385         if( temp == 0xD9 && temp_last == 0xFF ){           
00386            break;
00387         }
00388         if(i>= 1024 *10){
00389            HttpDebug("\r\nFile size exceeds 10K limit 0x%x\r\n",bytesRead);
00390            break;
00391         }
00392     }
00393     g_frame_size_in_bytes = bytesRead;
00394     myCAM.cs_high();
00395     
00396     return 1;
00397 }
00398 
00399 //*****************************************************************************
00400 //
00401 //!     JfifApp0Marker 
00402 //!    
00403 //! \param                      Pointer to the output buffer  
00404 //!     \return                     Length of the Marker                        
00405 //
00406 //*****************************************************************************
00407 
00408 #ifdef ENABLE_JPEG
00409 static int JfifApp0Marker(char *pbuf)
00410 {
00411     *pbuf++= 0xFF;                  // APP0 marker 
00412     *pbuf++= 0xE0;
00413     *pbuf++= 0x00;                  // length 
00414     *pbuf++= 0x10;
00415     *pbuf++= 0x4A;                  // JFIF identifier 
00416     *pbuf++= 0x46;
00417     *pbuf++= 0x49;
00418     *pbuf++= 0x46;
00419     *pbuf++= 0x00;
00420     *pbuf++= 0x01;                  // version 
00421     *pbuf++= 0x02;
00422     *pbuf++= 0x00;                  // units 
00423     *pbuf++= 0x00;                  // X density 
00424     *pbuf++= 0x01;
00425     *pbuf++= 0x00;                  // Y density 
00426     *pbuf++= 0x01;
00427     *pbuf++= 0x00;                  // X thumbnail 
00428     *pbuf++= 0x00;                  // Y thumbnail 
00429     return 18;
00430 }
00431 
00432 
00433 //*****************************************************************************
00434 //
00435 //!    FrameHeaderMarker
00436 //!    
00437 //! \param1                      pointer to the output buffer  
00438 //! \param2                      width   
00439 //! \param3                      height 
00440 //! \param4                      format
00441 //!
00442 //!     \return                       Length of the header marker                       
00443 //
00444 //*****************************************************************************
00445 static int FrameHeaderMarker(char *pbuf, int width, int height, int format)
00446 {
00447     int length;
00448     if (format == FORMAT_MONOCHROME)
00449         length = 11;
00450     else
00451         length = 17;
00452 
00453     *pbuf++= 0xFF;                      // start of frame: baseline DCT 
00454     *pbuf++= 0xC0;
00455     *pbuf++= length>>8;                 // length field 
00456     *pbuf++= length&0xFF;
00457     *pbuf++= 0x08;                      // sample precision 
00458     *pbuf++= height>>8;                 // number of lines 
00459     *pbuf++= height&0xFF;
00460     *pbuf++= width>>8;                  // number of samples per line 
00461     *pbuf++= width&0xFF;
00462 
00463     if (format == FORMAT_MONOCHROME)    // monochrome 
00464     {
00465         *pbuf++= 0x01;                  // number of image components in frame 
00466         *pbuf++= 0x00;                  // component identifier: Y 
00467         *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Y 
00468         *pbuf++= 0x00;                  // quantization table selector: Y 
00469     }
00470     else if (format == FORMAT_YCBCR422) // YCbCr422
00471     {
00472         *pbuf++= 0x03;                  // number of image components in frame 
00473         *pbuf++= 0x00;                  // component identifier: Y 
00474         *pbuf++= 0x21;                  // horizontal | vertical sampling factor: Y 
00475         *pbuf++= 0x00;                  // quantization table selector: Y 
00476         *pbuf++= 0x01;                  // component identifier: Cb 
00477         *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cb 
00478         *pbuf++= 0x01;                  // quantization table selector: Cb 
00479         *pbuf++= 0x02;                  // component identifier: Cr 
00480         *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cr 
00481         *pbuf++= 0x01;                  // quantization table selector: Cr 
00482     }
00483     else                                // YCbCr420 
00484     {
00485         *pbuf++= 0x03;                  // number of image components in frame 
00486         *pbuf++= 0x00;                  // component identifier: Y 
00487         *pbuf++= 0x22;                  // horizontal | vertical sampling factor: Y 
00488         *pbuf++= 0x00;                  // quantization table selector: Y 
00489         *pbuf++= 0x01;                  // component identifier: Cb 
00490         *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cb 
00491         *pbuf++= 0x01;                  // quantization table selector: Cb 
00492         *pbuf++= 0x02;                  // component identifier: Cr 
00493         *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cr 
00494         *pbuf++= 0x01;                  // quantization table selector: Cr 
00495     }
00496 
00497     return (length+2);
00498 }
00499 
00500 
00501 //*****************************************************************************
00502 //
00503 //!     ScanHeaderMarker
00504 //!
00505 //! \param1                     pointer to output buffer  
00506 //! \param2                     Format 
00507 //!
00508 //!     \return                     Length                             
00509 //
00510 //*****************************************************************************
00511 static int ScanHeaderMarker(char *pbuf, int format)
00512 {
00513     int length;
00514     if (format == FORMAT_MONOCHROME)
00515         length = 8;
00516     else
00517         length = 12;
00518 
00519     *pbuf++= 0xFF;                  // start of scan 
00520     *pbuf++= 0xDA;
00521     *pbuf++= length>>8;             // length field 
00522     *pbuf++= length&0xFF;
00523     if (format == FORMAT_MONOCHROME)// monochrome 
00524     {
00525         *pbuf++= 0x01;              // number of image components in scan 
00526         *pbuf++= 0x00;              // scan component selector: Y 
00527         *pbuf++= 0x00;              // DC | AC huffman table selector: Y 
00528     }
00529     else                            // YCbCr
00530     {
00531         *pbuf++= 0x03;              // number of image components in scan 
00532         *pbuf++= 0x00;              // scan component selector: Y 
00533         *pbuf++= 0x00;              // DC | AC huffman table selector: Y 
00534         *pbuf++= 0x01;              // scan component selector: Cb 
00535         *pbuf++= 0x11;              // DC | AC huffman table selector: Cb 
00536         *pbuf++= 0x02;              // scan component selector: Cr 
00537         *pbuf++= 0x11;              // DC | AC huffman table selector: Cr 
00538     }
00539 
00540     *pbuf++= 0x00;                  // Ss: start of predictor selector 
00541     *pbuf++= 0x3F;                  // Se: end of spectral selector 
00542     *pbuf++= 0x00;                  // Ah | Al: successive approximation bit position 
00543 
00544     return (length+2);
00545 }
00546 
00547 
00548 //*****************************************************************************
00549 //
00550 //!     DefineQuantizationTableMarker 
00551 //!      Calculate and write the quantisation tables
00552 //!      qscale is the customised scaling factor - see MT9D131 developer guide page 78 
00553 //!    
00554 //! \param1                      pointer to the output buffer  
00555 //! \param2                      Quantization Scale  
00556 //! \param3                      Format 
00557 //!
00558 //!     \return                      Length of the Marker                       
00559 //
00560 //*****************************************************************************
00561 static int DefineQuantizationTableMarker (unsigned char *pbuf, int qscale, int format)
00562 {
00563     int i, length, temp;
00564     unsigned char newtbl[64];           // temporary array to store scaled zigzagged quant entries 
00565 
00566     if (format == FORMAT_MONOCHROME)    // monochrome 
00567         length  =  67;
00568     else
00569         length  =  132;
00570 
00571     *pbuf++  =  0xFF;                   // define quantization table marker 
00572     *pbuf++  =  0xDB;
00573     *pbuf++  =  length>>8;              // length field 
00574     *pbuf++  =  length&0xFF;
00575     *pbuf++  =  0;                      // quantization table precision | identifier for luminance 
00576 
00577     // calculate scaled zigzagged luminance quantisation table entries 
00578     for (i=0; i<64; i++) {
00579         temp = (JPEG_StdQuantTblY[i] * qscale + 16) / 32;
00580         // limit the values to the valid range 
00581         if (temp <= 0)
00582             temp = 1;
00583         if (temp > 255)
00584             temp = 255;
00585         newtbl[zigzag[i]] = (unsigned char) temp;
00586     }
00587 
00588     // write the resulting luminance quant table to the output buffer 
00589     for (i=0; i<64; i++)
00590         *pbuf++ = newtbl[i];
00591 
00592     // if format is monochrome we're finished, otherwise continue on, to do chrominance quant table 
00593     if (format == FORMAT_MONOCHROME)
00594         return (length+2);
00595 
00596     *pbuf++ = 1;                        // quantization table precision | identifier for chrominance 
00597 
00598     // calculate scaled zigzagged chrominance quantisation table entries 
00599     for (i=0; i<64; i++) {
00600         temp = (JPEG_StdQuantTblC[i] * qscale + 16) / 32;
00601         // limit the values to the valid range 
00602         if (temp <= 0)
00603             temp = 1;
00604         if (temp > 255)
00605             temp = 255;
00606         newtbl[zigzag[i]] = (unsigned char) temp;
00607     }
00608 
00609     // write the resulting chrominance quant table to the output buffer 
00610     for (i=0; i<64; i++)
00611         *pbuf++ = newtbl[i];
00612 
00613     return (length+2);
00614 }
00615 
00616 
00617 //*****************************************************************************
00618 //
00619 //!     DefineHuffmanTableMarkerDC 
00620 //!    
00621 //! \param1                      pointer to Marker buffer  
00622 //! \param2                      Huffman table  
00623 //! \param3                      Class Identifier 
00624 //!  
00625 //!     \return                      Length of the marker                            
00626 //
00627 //*****************************************************************************
00628 static int DefineHuffmanTableMarkerDC(char *pbuf, unsigned int *htable, int class_id)
00629 {
00630     int i, l, count;
00631     int length;
00632     char *plength;
00633 
00634     *pbuf++= 0xFF;                  // define huffman table marker 
00635     *pbuf++= 0xC4;
00636     plength = pbuf;                 // place holder for length field 
00637     *pbuf++;
00638     *pbuf++;
00639     *pbuf++= class_id;              // huffman table class | identifier 
00640 
00641     for (l = 0; l < 16; l++)
00642     {
00643         count = 0;
00644         for (i = 0; i < 12; i++)
00645         {
00646             if ((htable[i] >> 8) == l)
00647                 count++;
00648         }
00649         *pbuf++= count;             // number of huffman codes of length l+1 
00650     }
00651 
00652     length = 19;
00653     for (l = 0; l < 16; l++)
00654     {
00655         for (i = 0; i < 12; i++)
00656         {
00657             if ((htable[i] >> 8) == l)
00658             {
00659                 *pbuf++= i;         // HUFFVAL with huffman codes of length l+1 
00660                 length++;
00661             }
00662         }
00663     }
00664 
00665     *plength++= length>>8;          // length field 
00666     *plength = length&0xFF;
00667 
00668     return (length + 2);
00669 }
00670 
00671 
00672 //*****************************************************************************
00673 //
00674 //!     DefineHuffmanTableMarkerAC 
00675 //!     1. Establishes connection w/ AP//
00676 //!     2. Initializes the camera sub-components//! GPIO Enable & Configuration
00677 //!     3. Listens and processes the image capture requests from user-applications
00678 //!    
00679 //! \param1                      pointer to Marker buffer  
00680 //! \param2                      Huffman table  
00681 //! \param3                      Class Identifier 
00682 //!
00683 //!     \return                      Length of the Marker
00684 //!                               
00685 //
00686 //*****************************************************************************
00687 static int DefineHuffmanTableMarkerAC(char *pbuf, unsigned int *htable, int class_id)
00688 {
00689     int i, l, a, b, count;
00690     char *plength;
00691     int length;
00692 
00693     *pbuf++= 0xFF;                      // define huffman table marker 
00694     *pbuf++= 0xC4;
00695     plength = pbuf;                     // place holder for length field 
00696     *pbuf++;
00697     *pbuf++;
00698     *pbuf++= class_id;                  // huffman table class | identifier 
00699 
00700     for (l = 0; l < 16; l++)
00701     {
00702         count = 0;
00703         for (i = 0; i < 162; i++)
00704         {
00705             if ((htable[i] >> 8) == l)
00706                 count++;
00707         }
00708 
00709         *pbuf++= count;                 // number of huffman codes of length l+1 
00710     }
00711 
00712     length = 19;
00713     for (l = 0; l < 16; l++)
00714     {
00715         // check EOB: 0|0 
00716         if ((htable[160] >> 8) == l)
00717         {
00718             *pbuf++= 0;                 // HUFFVAL with huffman codes of length l+1 
00719             length++;
00720         }
00721 
00722         // check HUFFVAL: 0|1 to E|A 
00723         for (i = 0; i < 150; i++)
00724         {
00725             if ((htable[i] >> 8) == l)
00726             {
00727                 a = i/10;
00728                 b = i%10;
00729                 *pbuf++= (a<<4)|(b+1);  // HUFFVAL with huffman codes of length l+1 
00730                 length++;
00731             }
00732         }
00733 
00734         // check ZRL: F|0 
00735         if ((htable[161] >> 8) == l)
00736         {
00737             *pbuf++= 0xF0;              // HUFFVAL with huffman codes of length l+1 
00738             length++;
00739         }
00740 
00741         // check HUFFVAL: F|1 to F|A 
00742         for (i = 150; i < 160; i++)
00743         {
00744             if ((htable[i] >> 8) == l)
00745             {
00746                 a = i/10;
00747                 b = i%10;
00748                 *pbuf++= (a<<4)|(b+1);  // HUFFVAL with huffman codes of length l+1 
00749                 length++;
00750             }
00751         }
00752     }
00753 
00754     *plength++= length>>8;              // length field 
00755     *plength = length&0xFF;
00756     return (length + 2);
00757 }
00758 
00759 
00760 //*****************************************************************************
00761 //
00762 //!     DefineRestartIntervalMarker
00763 //!    
00764 //! \param1                      pointer to Marker buffer  
00765 //! \param2                      return interval
00766 //!
00767 //!     \return                      Length                                
00768 //
00769 //*****************************************************************************
00770 static int DefineRestartIntervalMarker(char *pbuf, int ri)
00771 {
00772     *pbuf++= 0xFF;                  // define restart interval marker 
00773     *pbuf++= 0xDD;
00774     *pbuf++= 0x00;                  // length 
00775     *pbuf++= 0x04;
00776     *pbuf++= ri >> 8;               // restart interval 
00777     *pbuf++= ri & 0xFF;
00778     return 6;
00779 }
00780 //*****************************************************************************
00781 //
00782 //!     CreateJpegHeader
00783 //!     Create JPEG Header in JFIF format
00784 //!    
00785 //! \param1                     header - pointer to JPEG header buffer  
00786 //! \param2                     width - image width 
00787 //! \param3                     height - image height  
00788 //! \param4                     format - color format (0 = YCbCr422, 1 = YCbCr420, 2 = monochrome)  
00789 //! \param5                     restart_int - restart marker interval  
00790 //! \param6                     qscale - quantization table scaling factor
00791 //!
00792 //!     \return                     length of JPEG header (bytes)                             
00793 //
00794 //*****************************************************************************
00795 
00796 static int CreateJpegHeader(char *header, int width, int height,
00797                             int format, int restart_int, int qscale)
00798 {
00799     char *pbuf = header;
00800     int length;
00801 
00802     // SOI 
00803     *pbuf++= 0xFF;
00804     *pbuf++= 0xD8;
00805     length = 2;
00806 
00807     // JFIF APP0 
00808     length += JfifApp0Marker(pbuf);
00809 
00810     // Quantization Tables 
00811     pbuf = header + length;
00812     length += DefineQuantizationTableMarker((unsigned char *)pbuf, qscale, format);
00813 
00814     // Frame Header 
00815     pbuf = header + length;
00816     length += FrameHeaderMarker(pbuf, width, height, format);
00817 
00818     // Huffman Table DC 0 for Luma 
00819     pbuf = header + length;
00820     length += DefineHuffmanTableMarkerDC(pbuf, &JPEG_StdHuffmanTbl[352], 0x00);
00821 
00822     // Huffman Table AC 0 for Luma 
00823     pbuf = header + length;
00824     length += DefineHuffmanTableMarkerAC(pbuf, &JPEG_StdHuffmanTbl[0], 0x10);
00825 
00826     if (format != FORMAT_MONOCHROME)// YCbCr
00827     {
00828         // Huffman Table DC 1 for Chroma 
00829         pbuf = header + length;
00830         length += DefineHuffmanTableMarkerDC(pbuf, &JPEG_StdHuffmanTbl[368], 0x01);
00831 
00832         // Huffman Table AC 1 for Chroma 
00833         pbuf = header + length;
00834         length += DefineHuffmanTableMarkerAC(pbuf, &JPEG_StdHuffmanTbl[176], 0x11);
00835     }
00836 
00837     // Restart Interval 
00838     if (restart_int > 0)
00839     {
00840         pbuf = header + length;
00841         length += DefineRestartIntervalMarker(pbuf, restart_int);
00842     }
00843 
00844     // Scan Header 
00845     pbuf = header + length;
00846     length += ScanHeaderMarker(pbuf, format);
00847 
00848     return length;
00849 }
00850 #endif// jpeg defined 
00851 
00852 
00853 
00854 //*****************************************************************************
00855 //
00856 // Close the Doxygen group.
00857 //! @}
00858 //
00859 //*****************************************************************************
00860