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

Revision:
0:400d8e75a8d0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camera_app/camera_app.cpp	Sun Sep 06 15:19:36 2015 +0000
@@ -0,0 +1,860 @@
+//*****************************************************************************
+// camera_app.c
+//
+// camera application macro & APIs
+//
+// Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ 
+// 
+// 
+//  Redistribution and use in source and binary forms, with or without 
+//  modification, are permitted provided that the following conditions 
+//  are met:
+//
+//    Redistributions of source code must retain the above copyright 
+//    notice, this list of conditions and the following disclaimer.
+//
+//    Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the 
+//    documentation and/or other materials provided with the   
+//    distribution.
+//
+//    Neither the name of Texas Instruments Incorporated nor the names of
+//    its contributors may be used to endorse or promote products derived
+//    from this software without specific prior written permission.
+//
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+//*****************************************************************************
+//
+//! \addtogroup camera_app
+//! @{
+//
+//*****************************************************************************
+#include "mbed.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+// SimpleLink include
+#include "cc3100_simplelink.h"
+
+#include "oslib/osi.h"
+#include "camera_app.h"
+#include "ArduCAM.h"
+#include "ov5642_regs.h"
+//#include "i2cconfig.h"
+//#include "camera.h"
+
+#include "app_config.h"
+#include "cli_uart.h"
+#include "Led_config.h"
+#include "HttpDebug.h"
+
+using namespace mbed_cc3100;
+
+
+ArduCAM myCAM(OV5642, p14, SPI(p11, p12, p13), I2C(p28, p27));
+
+//*****************************************************************************
+// Macros
+//*****************************************************************************
+#define USER_FILE_NAME          "www/images/cc3200_camera_capture.jpg"
+#define TOTAL_DMA_ELEMENTS      64
+#define AP_SSID_LEN_MAX         (33)
+#define ROLE_INVALID            (-5)
+//*****************************************************************************
+//                      GLOBAL VARIABLES
+//*****************************************************************************
+
+unsigned int g_frame_size_in_bytes;
+unsigned int g_uiDeviceModeConfig = ROLE_AP; //default is AP mode 
+extern volatile unsigned char g_CaptureImage;
+extern int g_uiIpObtained = 0;
+extern int g_uiSimplelinkRole = ROLE_INVALID;
+uint32_t picLoop = 0;
+unsigned int g_uiIpAddress = 0;
+volatile static unsigned char g_frame_end;
+
+#ifdef ENABLE_JPEG 
+    int PIXELS_IN_X_AXIS = 320; 
+    int PIXELS_IN_Y_AXIS = 240;
+    int FRAME_SIZE_IN_BYTES = (320 * 240 * 2);
+#else
+    int PIXELS_IN_X_AXIS = 240;
+    int PIXELS_IN_Y_AXIS = 256;
+    int FRAME_SIZE_IN_BYTES = (240 * 256 * 2);
+#endif    
+
+struct ImageBuffer
+{
+#ifdef ENABLE_JPEG
+	char g_header[SMTP_BUF_LEN] /*= {'\0'}*/;
+#endif
+	uint8_t g_image_buffer[IMAGE_BUF_SIZE];//12Kb
+};
+
+ImageBuffer g_image;
+
+typedef enum pictureRequest{
+    NO_PICTURE = 0x00,
+    SINGLE_HIGH_RESOLUTION = 0x01,
+    STREAM_LOW_RESOLUTION = 0x02
+      
+}e_pictureRequest;
+
+typedef enum pictureFormat{
+    RAW_10BIT = 0,
+    ITU_R_BT601,
+    YCbCr_4_2_2,
+    YCbCr_4_2_0,
+    RGB_565,
+    RGB_555,
+    RGB_444
+
+}e_pictureFormat;
+
+typedef enum pictureResolution{
+    QVGA = 0,
+    VGA,
+    SVGA,
+    XGA,
+    uXGA
+
+}e_pictureResolution;
+
+
+#ifdef ENABLE_JPEG
+#define FORMAT_YCBCR422   0
+#define FORMAT_YCBCR420   1
+#define FORMAT_MONOCHROME 2
+
+unsigned char JPEG_StdQuantTblY[64] =
+{
+    16,  11,  10,  16,  24,  40,  51,  61,
+    12,  12,  14,  19,  26,  58,  60,  55,
+    14,  13,  16,  24,  40,  57,  69,  56,
+    14,  17,  22,  29,  51,  87,  80,  62,
+    18,  22,  37,  56,  68,  109, 103, 77,
+    24,  35,  55,  64,  81,  104, 113, 92,
+    49,  64,  78,  87, 103,  121, 120, 101,
+    72,  92,  95,  98, 112,  100, 103,  99
+};
+
+unsigned char JPEG_StdQuantTblC[64] =
+{
+    17,  18,  24,  47,  99,  99,  99,  99,
+    18,  21,  26,  66,  99,  99,  99,  99,
+    24,  26,  56,  99,  99,  99,  99,  99,
+    47,  66,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99
+};
+//
+// This table is used for regular-position to zigzagged-position lookup
+//  This is Figure A.6 from the ISO/IEC 10918-1 1993 specification 
+//
+static unsigned char zigzag[64] =
+{
+    0, 1, 5, 6,14,15,27,28,
+    2, 4, 7,13,16,26,29,42,
+    3, 8,12,17,25,30,41,43,
+    9,11,18,24,31,40,44,53,
+    10,19,23,32,39,45,52,54,
+    20,22,33,38,46,51,55,60,
+    21,34,37,47,50,56,59,61,
+    35,36,48,49,57,58,62,63
+};
+
+unsigned int JPEG_StdHuffmanTbl[384] =
+{
+    0x100, 0x101, 0x204, 0x30b, 0x41a, 0x678, 0x7f8, 0x9f6,
+    0xf82, 0xf83, 0x30c, 0x41b, 0x679, 0x8f6, 0xaf6, 0xf84,
+    0xf85, 0xf86, 0xf87, 0xf88, 0x41c, 0x7f9, 0x9f7, 0xbf4,
+    0xf89, 0xf8a, 0xf8b, 0xf8c, 0xf8d, 0xf8e, 0x53a, 0x8f7,
+    0xbf5, 0xf8f, 0xf90, 0xf91, 0xf92, 0xf93, 0xf94, 0xf95,
+    0x53b, 0x9f8, 0xf96, 0xf97, 0xf98, 0xf99, 0xf9a, 0xf9b,
+    0xf9c, 0xf9d, 0x67a, 0xaf7, 0xf9e, 0xf9f, 0xfa0, 0xfa1,
+    0xfa2, 0xfa3, 0xfa4, 0xfa5, 0x67b, 0xbf6, 0xfa6, 0xfa7,
+    0xfa8, 0xfa9, 0xfaa, 0xfab, 0xfac, 0xfad, 0x7fa, 0xbf7,
+    0xfae, 0xfaf, 0xfb0, 0xfb1, 0xfb2, 0xfb3, 0xfb4, 0xfb5,
+    0x8f8, 0xec0, 0xfb6, 0xfb7, 0xfb8, 0xfb9, 0xfba, 0xfbb,
+    0xfbc, 0xfbd, 0x8f9, 0xfbe, 0xfbf, 0xfc0, 0xfc1, 0xfc2,
+    0xfc3, 0xfc4, 0xfc5, 0xfc6, 0x8fa, 0xfc7, 0xfc8, 0xfc9,
+    0xfca, 0xfcb, 0xfcc, 0xfcd, 0xfce, 0xfcf, 0x9f9, 0xfd0,
+    0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7, 0xfd8,
+    0x9fa, 0xfd9, 0xfda, 0xfdb, 0xfdc, 0xfdd, 0xfde, 0xfdf,
+    0xfe0, 0xfe1, 0xaf8, 0xfe2, 0xfe3, 0xfe4, 0xfe5, 0xfe6,
+    0xfe7, 0xfe8, 0xfe9, 0xfea, 0xfeb, 0xfec, 0xfed, 0xfee,
+    0xfef, 0xff0, 0xff1, 0xff2, 0xff3, 0xff4, 0xff5, 0xff6,
+    0xff7, 0xff8, 0xff9, 0xffa, 0xffb, 0xffc, 0xffd, 0xffe,
+    0x30a, 0xaf9, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+    0xfd0, 0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7,
+    0x101, 0x204, 0x30a, 0x418, 0x419, 0x538, 0x678, 0x8f4,
+    0x9f6, 0xbf4, 0x30b, 0x539, 0x7f6, 0x8f5, 0xaf6, 0xbf5,
+    0xf88, 0xf89, 0xf8a, 0xf8b, 0x41a, 0x7f7, 0x9f7, 0xbf6,
+    0xec2, 0xf8c, 0xf8d, 0xf8e, 0xf8f, 0xf90, 0x41b, 0x7f8,
+    0x9f8, 0xbf7, 0xf91, 0xf92, 0xf93, 0xf94, 0xf95, 0xf96,
+    0x53a, 0x8f6, 0xf97, 0xf98, 0xf99, 0xf9a, 0xf9b, 0xf9c,
+    0xf9d, 0xf9e, 0x53b, 0x9f9, 0xf9f, 0xfa0, 0xfa1, 0xfa2,
+    0xfa3, 0xfa4, 0xfa5, 0xfa6, 0x679, 0xaf7, 0xfa7, 0xfa8,
+    0xfa9, 0xfaa, 0xfab, 0xfac, 0xfad, 0xfae, 0x67a, 0xaf8,
+    0xfaf, 0xfb0, 0xfb1, 0xfb2, 0xfb3, 0xfb4, 0xfb5, 0xfb6,
+    0x7f9, 0xfb7, 0xfb8, 0xfb9, 0xfba, 0xfbb, 0xfbc, 0xfbd,
+    0xfbe, 0xfbf, 0x8f7, 0xfc0, 0xfc1, 0xfc2, 0xfc3, 0xfc4,
+    0xfc5, 0xfc6, 0xfc7, 0xfc8, 0x8f8, 0xfc9, 0xfca, 0xfcb,
+    0xfcc, 0xfcd, 0xfce, 0xfcf, 0xfd0, 0xfd1, 0x8f9, 0xfd2,
+    0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7, 0xfd8, 0xfd9, 0xfda,
+    0x8fa, 0xfdb, 0xfdc, 0xfdd, 0xfde, 0xfdf, 0xfe0, 0xfe1,
+    0xfe2, 0xfe3, 0xaf9, 0xfe4, 0xfe5, 0xfe6, 0xfe7, 0xfe8,
+    0xfe9, 0xfea, 0xfeb, 0xfec, 0xde0, 0xfed, 0xfee, 0xfef,
+    0xff0, 0xff1, 0xff2, 0xff3, 0xff4, 0xff5, 0xec3, 0xff6,
+    0xff7, 0xff8, 0xff9, 0xffa, 0xffb, 0xffc, 0xffd, 0xffe,
+    0x100, 0x9fa, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
+    0xfd0, 0xfd1, 0xfd2, 0xfd3, 0xfd4, 0xfd5, 0xfd6, 0xfd7,
+    0x100, 0x202, 0x203, 0x204, 0x205, 0x206, 0x30e, 0x41e,
+    0x53e, 0x67e, 0x7fe, 0x8fe, 0xfff, 0xfff, 0xfff, 0xfff,
+    0x100, 0x101, 0x102, 0x206, 0x30e, 0x41e, 0x53e, 0x67e,
+    0x7fe, 0x8fe, 0x9fe, 0xafe, 0xfff, 0xfff, 0xfff, 0xfff
+};
+#endif 
+
+//*****************************************************************************
+//
+//!     Start Camera 
+//!     1. Establishes connection w/ AP//
+//!     2. Initializes the camera sub-components//! GPIO Enable & Configuration
+//!     3. Listens and processes the image capture requests from user-applications
+//!    
+//!	\param[out]                      WriteBuffer - Pointer to the Frame Buffer  
+//!     \return                     None                         
+//
+//*****************************************************************************
+
+unsigned short StartCamera(char **WriteBuffer)
+{
+	unsigned short Writelength;
+    //
+    // Waits in the below loop till Capture button is pressed
+    //
+    Writelength = CaptureImage(WriteBuffer);
+
+    return(Writelength);
+
+}
+//*****************************************************************************
+//
+//!     InitCameraComponents 
+//!     PinMux, Camera Initialization and Configuration   
+//!
+//!	\param[in] width - X-Axis
+//!	\param[in] width - Y-Axis
+//! \return  None
+//
+//*****************************************************************************
+
+void InitCameraComponents(int width, int height)
+{    
+    getCamId();
+    
+#ifdef ENABLE_JPEG
+    //Change to JPEG capture mode and initialize the OV5642 module    
+    myCAM.set_format(JPEG);
+#endif    
+    
+    //
+    // Initialize camera sensor
+    //
+    myCAM.InitCAM();
+    myCAM.clear_fifo_flag();
+    myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);
+    myCAM.write_reg(ARDUCHIP_FRAMES,0x00); //Bit[2:0]Number of frames to be captured
+    
+}
+
+void getCamId(){
+	
+	uint8_t vid = 0;
+	uint8_t pid = 0;
+	
+	//Check if the camera module type is OV5642
+    myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
+    myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
+    if((vid != 0x56) || (pid != 0x42)){
+      printf("Can't find OV5642 module! vid = 0x%x pid = 0x%x\r\n",vid, pid);
+      while(1);
+    }else{
+      printf("OV5642 detected\r\n");
+  }
+}	
+
+//*****************************************************************************
+//
+//!     CaptureImage 
+//!     Configures DMA and starts the Capture. Post Capture writes to SFLASH 
+//!    
+//!	\param                      None  
+//!     \return                     None
+//!                               
+//
+//*****************************************************************************
+uint16_t CaptureImage(char** WriteBuffer)
+{
+
+    //uint32_t g_header_length = 0;
+    myCAM.flush_fifo();
+    wait_ms(5);
+    myCAM.clear_fifo_flag();     
+    wait(1);
+    //
+    // Perform Image Capture 
+    //
+#ifdef ENABLE_JPEG
+    myCAM.start_capture();
+#else
+
+#endif 
+
+    while (!(myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK))){
+      wait_ms(100);
+   }
+   g_frame_size_in_bytes = myCAM.read_fifo_length();
+   read_fifo_burst(); 
+ 
+    /* Read the number of data items transferred in bytes) */
+    if(g_frame_size_in_bytes <= 0 ){
+    	HttpDebug("\r\nFailed to capture or data over-run, check camera connections!\r\n");
+    	while(1){
+    		wait(0.5);
+    	}
+    }	
+       
+    //
+    // Create JPEG Header
+    //
+#ifdef ENABLE_JPEG
+//    memset(g_image.g_header, '\0', sizeof(g_image.g_header));
+//    g_header_length = CreateJpegHeader((char *)&(g_image.g_header[0]), PIXELS_IN_X_AXIS,
+//                                       PIXELS_IN_Y_AXIS, 0, 0x0020, 9);
+//    HttpDebug("g_header_length = 0x%x \r\n",g_header_length);
+    // This pushes the header to the start of the array so that the entire picture can be contiguous in memory
+//    memcpy(Image + g_header_length, Image, g_frame_size_in_bytes);
+//    memcpy(Image, g_image.g_header, g_header_length);
+    // This pushes the header to the end of the array so that the entire picture can be contiguous in memory
+//    memcpy(Image + g_frame_size_in_bytes, g_image.g_header, g_header_length);
+
+#endif//ENABLE_JPEG
+    picLoop++;
+    HttpDebug("\r\nPicture Sent %d\r\n",picLoop);
+
+    *WriteBuffer = (char*)g_image.g_image_buffer;
+
+	return(g_frame_size_in_bytes);
+}
+
+uint8_t read_fifo_burst()
+{
+    
+    uint32_t bytesRead = 0;
+    uint8_t temp = 0;
+    uint8_t temp_last = 0;
+    int32_t i;
+    
+    myCAM.cs_low(); 
+    myCAM.set_fifo_burst();    
+    myCAM._cam_spi.write(0x00);//Ignore first byte
+    i = 0;
+    while( 1 ){        
+        temp_last = temp;    
+        temp = (uint8_t )myCAM._cam_spi.write(0x00);
+        g_image.g_image_buffer[i] = temp;
+        i++;
+        bytesRead++;
+        if( temp == 0xD9 && temp_last == 0xFF ){           
+           break;
+        }
+        if(i>= 1024 *10){
+           HttpDebug("\r\nFile size exceeds 10K limit 0x%x\r\n",bytesRead);
+           break;
+        }
+    }
+    g_frame_size_in_bytes = bytesRead;
+    myCAM.cs_high();
+    
+    return 1;
+}
+
+//*****************************************************************************
+//
+//!     JfifApp0Marker 
+//!    
+//!	\param                      Pointer to the output buffer  
+//!     \return                     Length of the Marker                        
+//
+//*****************************************************************************
+
+#ifdef ENABLE_JPEG
+static int JfifApp0Marker(char *pbuf)
+{
+    *pbuf++= 0xFF;                  // APP0 marker 
+    *pbuf++= 0xE0;
+    *pbuf++= 0x00;                  // length 
+    *pbuf++= 0x10;
+    *pbuf++= 0x4A;                  // JFIF identifier 
+    *pbuf++= 0x46;
+    *pbuf++= 0x49;
+    *pbuf++= 0x46;
+    *pbuf++= 0x00;
+    *pbuf++= 0x01;                  // version 
+    *pbuf++= 0x02;
+    *pbuf++= 0x00;                  // units 
+    *pbuf++= 0x00;                  // X density 
+    *pbuf++= 0x01;
+    *pbuf++= 0x00;                  // Y density 
+    *pbuf++= 0x01;
+    *pbuf++= 0x00;                  // X thumbnail 
+    *pbuf++= 0x00;                  // Y thumbnail 
+    return 18;
+}
+
+
+//*****************************************************************************
+//
+//!    FrameHeaderMarker
+//!    
+//!	\param1                      pointer to the output buffer  
+//!	\param2                      width   
+//!	\param3                      height 
+//!	\param4                      format
+//!
+//!     \return                       Length of the header marker                       
+//
+//*****************************************************************************
+static int FrameHeaderMarker(char *pbuf, int width, int height, int format)
+{
+    int length;
+    if (format == FORMAT_MONOCHROME)
+        length = 11;
+    else
+        length = 17;
+
+    *pbuf++= 0xFF;                      // start of frame: baseline DCT 
+    *pbuf++= 0xC0;
+    *pbuf++= length>>8;                 // length field 
+    *pbuf++= length&0xFF;
+    *pbuf++= 0x08;                      // sample precision 
+    *pbuf++= height>>8;                 // number of lines 
+    *pbuf++= height&0xFF;
+    *pbuf++= width>>8;                  // number of samples per line 
+    *pbuf++= width&0xFF;
+
+    if (format == FORMAT_MONOCHROME)    // monochrome 
+    {
+        *pbuf++= 0x01;                  // number of image components in frame 
+        *pbuf++= 0x00;                  // component identifier: Y 
+        *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Y 
+        *pbuf++= 0x00;                  // quantization table selector: Y 
+    }
+    else if (format == FORMAT_YCBCR422) // YCbCr422
+    {
+        *pbuf++= 0x03;                  // number of image components in frame 
+        *pbuf++= 0x00;                  // component identifier: Y 
+        *pbuf++= 0x21;                  // horizontal | vertical sampling factor: Y 
+        *pbuf++= 0x00;                  // quantization table selector: Y 
+        *pbuf++= 0x01;                  // component identifier: Cb 
+        *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cb 
+        *pbuf++= 0x01;                  // quantization table selector: Cb 
+        *pbuf++= 0x02;                  // component identifier: Cr 
+        *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cr 
+        *pbuf++= 0x01;                  // quantization table selector: Cr 
+    }
+    else                                // YCbCr420 
+    {
+        *pbuf++= 0x03;                  // number of image components in frame 
+        *pbuf++= 0x00;                  // component identifier: Y 
+        *pbuf++= 0x22;                  // horizontal | vertical sampling factor: Y 
+        *pbuf++= 0x00;                  // quantization table selector: Y 
+        *pbuf++= 0x01;                  // component identifier: Cb 
+        *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cb 
+        *pbuf++= 0x01;                  // quantization table selector: Cb 
+        *pbuf++= 0x02;                  // component identifier: Cr 
+        *pbuf++= 0x11;                  // horizontal | vertical sampling factor: Cr 
+        *pbuf++= 0x01;                  // quantization table selector: Cr 
+    }
+
+    return (length+2);
+}
+
+
+//*****************************************************************************
+//
+//!     ScanHeaderMarker
+//!
+//!	\param1                     pointer to output buffer  
+//!	\param2                     Format 
+//!
+//!     \return                     Length                             
+//
+//*****************************************************************************
+static int ScanHeaderMarker(char *pbuf, int format)
+{
+    int length;
+    if (format == FORMAT_MONOCHROME)
+        length = 8;
+    else
+        length = 12;
+
+    *pbuf++= 0xFF;                  // start of scan 
+    *pbuf++= 0xDA;
+    *pbuf++= length>>8;             // length field 
+    *pbuf++= length&0xFF;
+    if (format == FORMAT_MONOCHROME)// monochrome 
+    {
+        *pbuf++= 0x01;              // number of image components in scan 
+        *pbuf++= 0x00;              // scan component selector: Y 
+        *pbuf++= 0x00;              // DC | AC huffman table selector: Y 
+    }
+    else                            // YCbCr
+    {
+        *pbuf++= 0x03;              // number of image components in scan 
+        *pbuf++= 0x00;              // scan component selector: Y 
+        *pbuf++= 0x00;              // DC | AC huffman table selector: Y 
+        *pbuf++= 0x01;              // scan component selector: Cb 
+        *pbuf++= 0x11;              // DC | AC huffman table selector: Cb 
+        *pbuf++= 0x02;              // scan component selector: Cr 
+        *pbuf++= 0x11;              // DC | AC huffman table selector: Cr 
+    }
+
+    *pbuf++= 0x00;                  // Ss: start of predictor selector 
+    *pbuf++= 0x3F;                  // Se: end of spectral selector 
+    *pbuf++= 0x00;                  // Ah | Al: successive approximation bit position 
+
+    return (length+2);
+}
+
+
+//*****************************************************************************
+//
+//!     DefineQuantizationTableMarker 
+//!      Calculate and write the quantisation tables
+//!      qscale is the customised scaling factor - see MT9D131 developer guide page 78 
+//!    
+//!	\param1                      pointer to the output buffer  
+//!	\param2                      Quantization Scale  
+//!	\param3                      Format 
+//!
+//!     \return                      Length of the Marker                       
+//
+//*****************************************************************************
+static int DefineQuantizationTableMarker (unsigned char *pbuf, int qscale, int format)
+{
+    int i, length, temp;
+    unsigned char newtbl[64];           // temporary array to store scaled zigzagged quant entries 
+
+    if (format == FORMAT_MONOCHROME)    // monochrome 
+        length  =  67;
+    else
+        length  =  132;
+
+    *pbuf++  =  0xFF;                   // define quantization table marker 
+    *pbuf++  =  0xDB;
+    *pbuf++  =  length>>8;              // length field 
+    *pbuf++  =  length&0xFF;
+    *pbuf++  =  0;                      // quantization table precision | identifier for luminance 
+
+    // calculate scaled zigzagged luminance quantisation table entries 
+    for (i=0; i<64; i++) {
+        temp = (JPEG_StdQuantTblY[i] * qscale + 16) / 32;
+        // limit the values to the valid range 
+        if (temp <= 0)
+            temp = 1;
+        if (temp > 255)
+            temp = 255;
+        newtbl[zigzag[i]] = (unsigned char) temp;
+    }
+
+    // write the resulting luminance quant table to the output buffer 
+    for (i=0; i<64; i++)
+        *pbuf++ = newtbl[i];
+
+    // if format is monochrome we're finished, otherwise continue on, to do chrominance quant table 
+    if (format == FORMAT_MONOCHROME)
+        return (length+2);
+
+    *pbuf++ = 1;                        // quantization table precision | identifier for chrominance 
+
+    // calculate scaled zigzagged chrominance quantisation table entries 
+    for (i=0; i<64; i++) {
+        temp = (JPEG_StdQuantTblC[i] * qscale + 16) / 32;
+        // limit the values to the valid range 
+        if (temp <= 0)
+            temp = 1;
+        if (temp > 255)
+            temp = 255;
+        newtbl[zigzag[i]] = (unsigned char) temp;
+    }
+
+    // write the resulting chrominance quant table to the output buffer 
+    for (i=0; i<64; i++)
+        *pbuf++ = newtbl[i];
+
+    return (length+2);
+}
+
+
+//*****************************************************************************
+//
+//!     DefineHuffmanTableMarkerDC 
+//!    
+//!	\param1                      pointer to Marker buffer  
+//!	\param2                      Huffman table  
+//!	\param3                      Class Identifier 
+//!  
+//!     \return                      Length of the marker                            
+//
+//*****************************************************************************
+static int DefineHuffmanTableMarkerDC(char *pbuf, unsigned int *htable, int class_id)
+{
+    int i, l, count;
+    int length;
+    char *plength;
+
+    *pbuf++= 0xFF;                  // define huffman table marker 
+    *pbuf++= 0xC4;
+    plength = pbuf;                 // place holder for length field 
+    *pbuf++;
+    *pbuf++;
+    *pbuf++= class_id;              // huffman table class | identifier 
+
+    for (l = 0; l < 16; l++)
+    {
+        count = 0;
+        for (i = 0; i < 12; i++)
+        {
+            if ((htable[i] >> 8) == l)
+                count++;
+        }
+        *pbuf++= count;             // number of huffman codes of length l+1 
+    }
+
+    length = 19;
+    for (l = 0; l < 16; l++)
+    {
+        for (i = 0; i < 12; i++)
+        {
+            if ((htable[i] >> 8) == l)
+            {
+                *pbuf++= i;         // HUFFVAL with huffman codes of length l+1 
+                length++;
+            }
+        }
+    }
+
+    *plength++= length>>8;          // length field 
+    *plength = length&0xFF;
+
+    return (length + 2);
+}
+
+
+//*****************************************************************************
+//
+//!     DefineHuffmanTableMarkerAC 
+//!     1. Establishes connection w/ AP//
+//!     2. Initializes the camera sub-components//! GPIO Enable & Configuration
+//!     3. Listens and processes the image capture requests from user-applications
+//!    
+//!	\param1                      pointer to Marker buffer  
+//!	\param2                      Huffman table  
+//!	\param3                      Class Identifier 
+//!
+//!     \return                      Length of the Marker
+//!                               
+//
+//*****************************************************************************
+static int DefineHuffmanTableMarkerAC(char *pbuf, unsigned int *htable, int class_id)
+{
+    int i, l, a, b, count;
+    char *plength;
+    int length;
+
+    *pbuf++= 0xFF;                      // define huffman table marker 
+    *pbuf++= 0xC4;
+    plength = pbuf;                     // place holder for length field 
+    *pbuf++;
+    *pbuf++;
+    *pbuf++= class_id;                  // huffman table class | identifier 
+
+    for (l = 0; l < 16; l++)
+    {
+        count = 0;
+        for (i = 0; i < 162; i++)
+        {
+            if ((htable[i] >> 8) == l)
+                count++;
+        }
+
+        *pbuf++= count;                 // number of huffman codes of length l+1 
+    }
+
+    length = 19;
+    for (l = 0; l < 16; l++)
+    {
+        // check EOB: 0|0 
+        if ((htable[160] >> 8) == l)
+        {
+            *pbuf++= 0;                 // HUFFVAL with huffman codes of length l+1 
+            length++;
+        }
+
+        // check HUFFVAL: 0|1 to E|A 
+        for (i = 0; i < 150; i++)
+        {
+            if ((htable[i] >> 8) == l)
+            {
+                a = i/10;
+                b = i%10;
+                *pbuf++= (a<<4)|(b+1);  // HUFFVAL with huffman codes of length l+1 
+                length++;
+            }
+        }
+
+        // check ZRL: F|0 
+        if ((htable[161] >> 8) == l)
+        {
+            *pbuf++= 0xF0;              // HUFFVAL with huffman codes of length l+1 
+            length++;
+        }
+
+        // check HUFFVAL: F|1 to F|A 
+        for (i = 150; i < 160; i++)
+        {
+            if ((htable[i] >> 8) == l)
+            {
+                a = i/10;
+                b = i%10;
+                *pbuf++= (a<<4)|(b+1);  // HUFFVAL with huffman codes of length l+1 
+                length++;
+            }
+        }
+    }
+
+    *plength++= length>>8;              // length field 
+    *plength = length&0xFF;
+    return (length + 2);
+}
+
+
+//*****************************************************************************
+//
+//!     DefineRestartIntervalMarker
+//!    
+//!	\param1                      pointer to Marker buffer  
+//!	\param2                      return interval
+//!
+//!     \return                      Length                                
+//
+//*****************************************************************************
+static int DefineRestartIntervalMarker(char *pbuf, int ri)
+{
+    *pbuf++= 0xFF;                  // define restart interval marker 
+    *pbuf++= 0xDD;
+    *pbuf++= 0x00;                  // length 
+    *pbuf++= 0x04;
+    *pbuf++= ri >> 8;               // restart interval 
+    *pbuf++= ri & 0xFF;
+    return 6;
+}
+//*****************************************************************************
+//
+//!     CreateJpegHeader
+//!     Create JPEG Header in JFIF format
+//!    
+//!	\param1                     header - pointer to JPEG header buffer  
+//!	\param2                     width - image width 
+//!	\param3                     height - image height  
+//!	\param4                     format - color format (0 = YCbCr422, 1 = YCbCr420, 2 = monochrome)  
+//!	\param5                     restart_int - restart marker interval  
+//!	\param6                     qscale - quantization table scaling factor
+//!
+//!     \return                     length of JPEG header (bytes)                             
+//
+//*****************************************************************************
+
+static int CreateJpegHeader(char *header, int width, int height,
+                            int format, int restart_int, int qscale)
+{
+    char *pbuf = header;
+    int length;
+
+    // SOI 
+    *pbuf++= 0xFF;
+    *pbuf++= 0xD8;
+    length = 2;
+
+    // JFIF APP0 
+    length += JfifApp0Marker(pbuf);
+
+    // Quantization Tables 
+    pbuf = header + length;
+    length += DefineQuantizationTableMarker((unsigned char *)pbuf, qscale, format);
+
+    // Frame Header 
+    pbuf = header + length;
+    length += FrameHeaderMarker(pbuf, width, height, format);
+
+    // Huffman Table DC 0 for Luma 
+    pbuf = header + length;
+    length += DefineHuffmanTableMarkerDC(pbuf, &JPEG_StdHuffmanTbl[352], 0x00);
+
+    // Huffman Table AC 0 for Luma 
+    pbuf = header + length;
+    length += DefineHuffmanTableMarkerAC(pbuf, &JPEG_StdHuffmanTbl[0], 0x10);
+
+    if (format != FORMAT_MONOCHROME)// YCbCr
+    {
+        // Huffman Table DC 1 for Chroma 
+        pbuf = header + length;
+        length += DefineHuffmanTableMarkerDC(pbuf, &JPEG_StdHuffmanTbl[368], 0x01);
+
+        // Huffman Table AC 1 for Chroma 
+        pbuf = header + length;
+        length += DefineHuffmanTableMarkerAC(pbuf, &JPEG_StdHuffmanTbl[176], 0x11);
+    }
+
+    // Restart Interval 
+    if (restart_int > 0)
+    {
+        pbuf = header + length;
+        length += DefineRestartIntervalMarker(pbuf, restart_int);
+    }
+
+    // Scan Header 
+    pbuf = header + length;
+    length += ScanHeaderMarker(pbuf, format);
+
+    return length;
+}
+#endif// jpeg defined 
+
+
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
+