TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.
Diff: camera_app/camera_app.cpp
- 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. +//! @} +// +//***************************************************************************** +