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.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
Generated on Wed Jul 13 2022 15:58:45 by 1.7.2