TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.
camera_app/camera_app.cpp
- Committer:
- dflet
- Date:
- 2015-09-11
- Revision:
- 1:e448e81c416f
- Parent:
- 0:400d8e75a8d0
File content as of revision 1:e448e81c416f:
//*****************************************************************************
// 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.
//! @}
//
//*****************************************************************************