Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
camera_app/camera_app.cpp
- Committer:
- dflet
- Date:
- 2015-09-15
- Revision:
- 21:38c6b11aa348
- Parent:
- 18:3f1b52616d00
- Child:
- 22:f9b5e0b80bf2
File content as of revision 21:38c6b11aa348:
//***************************************************************************** // 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 "app_config.h" #include "camera_app.h" #include "mt9d111.h" #ifdef OV5642_CAM #include "ov5642.h" #endif #ifdef OV2640_CAM #include "ov2640.h" #include "ov5642.h" #endif #include "i2cconfig.h" #include "cli_uart.h" #include "Led_config.h" #include "HttpDebug.h" using namespace mbed_cc3100; //***************************************************************************** // Macros //***************************************************************************** #define USER_FILE_NAME "www/images/cc3200_camera_capture.jpg" #define AP_SSID_LEN_MAX (33) #define ROLE_INVALID (-5) //***************************************************************************** // GLOBAL VARIABLES //***************************************************************************** unsigned int g_frame_size_in_bytes; extern volatile unsigned char g_CaptureImage; extern int g_uiIpObtained = 0; extern int g_uiSimplelinkRole = ROLE_INVALID; unsigned int g_uiIpAddress = 0; uint32_t picLoop = 0; volatile static unsigned char g_frame_end; volatile static uint16_t g_lines; DCMI_HandleTypeDef phdcmi; DMA_HandleTypeDef phdma_dcmi; #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 = 176; int PIXELS_IN_Y_AXIS = 144; int FRAME_SIZE_IN_BYTES = (176 * 144 * 2); #endif struct ImageBuffer { #ifdef ENABLE_JPEG char g_header[SMTP_BUF_LEN] /*= {'\0'}*/; #endif uint32_t g_image_buffer[((IMAGE_BUF_SIZE)/(sizeof(unsigned int)))];//25Kb uint8_t sec_image_buffer[26 * 1024]; }; 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 // //***************************************************************************** uint32_t StartCamera(char **WriteBuffer) { uint32_t 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) { Uart_Write((uint8_t*)"InitCameraComponents \n\r"); // // Initialize I2C Interface // I2CInit(); #ifdef MT9D111_CAM cam_power_on(); getCamId(); // // Initialize camera sensor // CameraSensorInit(); #ifdef ENABLE_JPEG // // Configure Sensor in Capture Mode // PIXELS_IN_X_AXIS = width; PIXELS_IN_Y_AXIS = height; FRAME_SIZE_IN_BYTES = PIXELS_IN_X_AXIS * PIXELS_IN_Y_AXIS * BYTES_PER_PIXEL; StartSensorInJpegMode(width, height); #endif//ENABLE_JPEG #endif//MT9D111_CAM #ifdef OV5642_CAM check_camId(); init_cam(); #endif//OV5642_CAM #ifdef OV2640_CAM camId(); initCam(); #endif//OV2640_CAM } //***************************************************************************** // //! Set resolution of camera //! //! \param[in] width - X Axis //! \param[in] height - Y Axis //! \return 0 on success else -ve // //***************************************************************************** int SetCameraResolution(int width, int height) { Uart_Write((uint8_t*)"SetCameraResolution \n\r"); int lRetVal = 0; PIXELS_IN_X_AXIS = width; PIXELS_IN_Y_AXIS = height; FRAME_SIZE_IN_BYTES = PIXELS_IN_X_AXIS * PIXELS_IN_Y_AXIS * BYTES_PER_PIXEL; lRetVal = CameraSensorResolution(width, height); return lRetVal; } //***************************************************************************** // //! CaptureImage //! Configures DMA and starts the Capture. Post Capture writes to SFLASH //! //! \param None //! \return None //! // //***************************************************************************** uint32_t CaptureImage(char** WriteBuffer) { uint32_t g_header_length = 0; uint32_t image_size = 0; uint32_t *pbuffer = &(g_image.g_image_buffer[0]); uint8_t *sec_pbuffer = &(g_image.sec_image_buffer[0]); // int32_t lRetVal= -1; int32_t err = 0; #ifdef MT9D111_CAM uint8_t jpeg_end[] = {0xFF, 0xD9}; #endif picLoop++; DMAConfig(); // wait(1); #ifdef MT9D111_CAM /* Send cam capture request, value in frames */ Start_still_capture(1);// Switch to context b wait(1); #endif // // DCMI Perform Image Capture // #ifdef ENABLE_JPEG HAL_DCMI_Start_DMA(&phdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)pbuffer, NUM_OF_4B_CHUNKS); #else HAL_DCMI_Start_DMA(&phdcmi, DCMI_MODE_CONTINUOUS, (uint32_t)pbuffer, NUM_OF_4B_CHUNKS); #endif while(g_frame_end == 0);//Set in the Frame complete callback function #ifdef MT9D111_CAM Stop_still_capture();// Switch to context a #endif /* Read the number of data items transferred in bytes ((4x) uint = bytes) */ g_frame_size_in_bytes = 4*(NUM_OF_4B_CHUNKS - phdma_dcmi.Instance->NDTR);//NDTR counts down! if(g_frame_size_in_bytes <= 0 || g_frame_size_in_bytes > (NUM_OF_4B_CHUNKS *4)) { err = HAL_DMA_GetState(&phdma_dcmi); HttpDebug("\r\nDMA error! 0x%x\r\n",err); HttpDebug("\r\nDMA error! 0x%x\r\n",phdma_dcmi.ErrorCode); HttpDebug("g_frame_size_in_bytes = 0x%x\r\n",g_frame_size_in_bytes); HttpDebug("\r\nFailed to capture data, check camera connections!\r\n"); HAL_DMA_Abort(&phdma_dcmi); #ifdef MT9D111_CAM cam_power_off(); #endif HAL_DCMI_MspDeInit(&phdcmi); HttpDebug("Image Capture failed\n\r"); while(1) { wait(0.5); } } uint8_t* Image = reinterpret_cast<uint8_t*>(pbuffer); #ifdef MT9D111_CAM memcpy(Image + g_frame_size_in_bytes, jpeg_end, 2); g_frame_size_in_bytes += 2; #endif // // Create JPEG Header // #ifdef MT9D111_CAM #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, 8); // This pushes the header to the start of the array so that the entire picture can be contiguous in memory memcpy(sec_pbuffer + g_header_length, Image, g_frame_size_in_bytes); memcpy(sec_pbuffer, g_image.g_header, g_header_length); image_size = g_header_length + g_frame_size_in_bytes; HttpDebug("\r\nCapture Image %d size 0x%x\r\n",picLoop, image_size); #endif//ENABLE_JPEG *WriteBuffer = (char*)g_image.sec_image_buffer; return(g_header_length += g_frame_size_in_bytes); #endif//MT9D111_CAM HttpDebug("\r\nCapture Image %d size 0x%x\r\n",picLoop, image_size); *WriteBuffer = (char*)g_image.sec_image_buffer; return(g_frame_size_in_bytes); } //***************************************************************************** // //! DMA Config //! Initialize the DMA\DCMI and Setup the DMA transfer //! //! \param None //! \return None // //***************************************************************************** void DMAConfig() { phdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE; #ifdef OV5642_CAM phdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;//Data clocked out on rising edge phdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH;//Active high phdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;//Active low #endif #ifdef OV2640_CAM phdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;//Data clocked out on rising edge phdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;//Active low phdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;//Active low #endif #ifdef MT9D111_CAM phdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;//Data clocked out on rising edge // phdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_FALLING;//Data clocked out on falling edge phdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;//Active high phdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;//Active high #endif phdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME; phdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;//8 bit data #ifdef ENABLE_JPEG phdcmi.Init.JPEGMode = DCMI_JPEG_ENABLE; #else phdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE; #endif phdcmi.Instance = DCMI; DCMI_MspInit(&phdcmi); HAL_DCMI_Init(&phdcmi); } void DCMI_MspInit(DCMI_HandleTypeDef* hdcmi) { /* Peripheral DCMI init*/ GPIO_InitTypeDef GPIO_InitStruct; if(hdcmi->Instance==DCMI) { __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); __GPIOC_CLK_ENABLE(); __GPIOE_CLK_ENABLE(); /* Peripheral clock enable */ __DCMI_CLK_ENABLE(); /* DMA controller clock enable */ __DMA2_CLK_ENABLE(); /**MCO1 GPIO Configuration PA8 ------> RCC_MCO_1 */ /**DCMI GPIO Configuration PA9 ------> DCMI_D0 PA10 ------> DCMI_D1 PC8 ------> DCMI_D2 PC9 ------> DCMI_D3 PE4 ------> DCMI_D4 PB6 ------> DCMI_D5 PE5 ------> DCMI_D6 PE6 ------> DCMI_D7 PA6 ------> DCMI_PIXCK PA4 ------> DCMI_HSYNC PB7 ------> DCMI_VSYNC */ /* D4 D6 D7 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); /* HSYNC PIXCLK D0 D1 */ GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* D2 D3 */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* D5 VSYNC */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); phdma_dcmi.Instance = DMA2_Stream1; phdma_dcmi.Init.Channel = DMA_CHANNEL_1; phdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY; phdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE; phdma_dcmi.Init.MemInc = DMA_MINC_ENABLE; phdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;//Cam is 1 byte wide data (8 bits) should this be word????? phdma_dcmi.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;//Memory has been defined as uint (1 word) phdma_dcmi.Init.Mode = DMA_NORMAL; phdma_dcmi.Init.Priority = DMA_PRIORITY_HIGH; phdma_dcmi.Init.FIFOMode = DMA_FIFOMODE_DISABLE; phdma_dcmi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; phdma_dcmi.Init.MemBurst = DMA_MBURST_SINGLE; phdma_dcmi.Init.PeriphBurst = DMA_PBURST_SINGLE; __HAL_LINKDMA(hdcmi, DMA_Handle, phdma_dcmi); /*** Configure the NVIC for DCMI and DMA ***/ /* NVIC configuration for DCMI transfer complete interrupt */ HAL_NVIC_SetPriority(DCMI_IRQn, 3, 0); HAL_NVIC_EnableIRQ(DCMI_IRQn); /* NVIC configuration for DMA2 transfer complete interrupt */ HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 3, 0); HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); HAL_DMA_Init(&phdma_dcmi); } g_frame_size_in_bytes = 0; g_frame_end = 0; } /******************************************************************************/ /* STM32F4xx Peripheral Interrupt Handlers */ /* Add here the Interrupt Handlers for the used peripherals. */ /* For the available peripheral interrupt handler names, */ /* please refer to the startup file (startup_stm32f4xx.s). */ /******************************************************************************/ void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi) { int32_t dcmi_state; int32_t dcmi_error; HAL_DMA_Abort(&phdma_dcmi); HttpDebug("\r\nDCMI_ErrorCallback!\r\n"); dcmi_state = HAL_DCMI_GetState(&phdcmi); if(0 == dcmi_state){ HttpDebug("\r\nDCMI not yet initialized or disabled\r\n"); }else if(1 == dcmi_state){ HttpDebug("\r\nDCMI initialized and ready for use\r\n"); }else if(2 == dcmi_state){ HttpDebug("\r\nDCMI internal processing is ongoing\r\n"); }else if(3 == dcmi_state){ HttpDebug("\r\nDCMI timeout state\r\n"); }else if(4 == dcmi_state){ HttpDebug("\r\nDCMI error state\r\n"); dcmi_error = HAL_DCMI_GetError(&phdcmi); if(1 == dcmi_error){ HttpDebug("\r\nDCMI Synchronisation error\r\n"); }else if(2 == dcmi_error){ HttpDebug("\r\nDCMI Overrun\r\n"); } } HttpDebug("\r\nExtra info! \r\n"); g_frame_size_in_bytes = 4*(NUM_OF_4B_CHUNKS - phdma_dcmi.Instance->NDTR);//NDTR counts down! if(g_frame_size_in_bytes >= 0xC800){ HttpDebug("Bytes captured equals or exceeds buffer size! \r\n"); HttpDebug("Bytes captured 0x%x\r\n",g_frame_size_in_bytes); }else{ HttpDebug("Bytes captured 0x%x\r\n",g_frame_size_in_bytes); } HAL_DMA_Abort(&phdma_dcmi); #ifdef MT9D111_CAM cam_power_off(); #endif HAL_DCMI_MspDeInit(&phdcmi); } void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi) { //g_lines++; //HttpDebug("\r\nDCMI_LineEventCallback! 0x%x\r\n",hdcmi->ErrorCode); } void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi) { //g_lines = 0; // printf("\r\nVsyncEventCallback\r\n"); } void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) { HAL_DMA_Abort(&phdma_dcmi); g_frame_end = 1; //HttpDebug("\r\nDCMI Frame Capture complete! \r\n"); } void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi) { if(hdcmi->Instance==DCMI) { /* Peripheral clock disable */ __DCMI_CLK_DISABLE(); /**DCMI GPIO Configuration PE4 ------> DCMI_D4 PE5 ------> DCMI_D6 PE6 ------> DCMI_D7 PA4 ------> DCMI_HSYNC PA6 ------> DCMI_PIXCK PC8 ------> DCMI_D2 PC9 ------> DCMI_D3 PA9 ------> DCMI_D0 PA10 ------> DCMI_D1 PB6 ------> DCMI_D5 PB7 ------> DCMI_VSYNC PA8 ------> MCO1 */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10); HAL_GPIO_DeInit(GPIOC, GPIO_PIN_9|GPIO_PIN_8); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7); /* Peripheral DMA DeInit*/ HAL_DMA_DeInit(hdcmi->DMA_Handle); /* Peripheral interrupt DeInit*/ HAL_NVIC_DisableIRQ(DCMI_IRQn); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8); HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8 | GPIO_PIN_9); } } //***************************************************************************** // //! JfifApp0Marker //! //! \param Pointer to the output buffer //! \return Length of the Marker // //***************************************************************************** #ifdef ENABLE_JPEG static int JfifApp0Marker(char *pbuf) { // Uart_Write((uint8_t*)"JfifApp0Marker \n\r"); *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) { // Uart_Write((uint8_t*)"FrameHeaderMarker \n\r"); 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) { // Uart_Write((uint8_t*)"DefineQuantizationTableMarker \n\r"); 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) { // Uart_Write((uint8_t*)"DefineHuffmanTableMarkerDC \n\r"); 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) { // Uart_Write((uint8_t*)"DefineHuffmanTableMarkerAC \n\r"); 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) { // Uart_Write((uint8_t*)"DefineRestartIntervalMarker \n\r"); *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) { // Uart_Write((uint8_t*)"CreateJpegHeader \n\r"); 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. //! @} // //*****************************************************************************