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/mt9d111/mt9d111.cpp
- Committer:
- dflet
- Date:
- 2015-09-15
- Revision:
- 22:f9b5e0b80bf2
- Parent:
- 21:38c6b11aa348
File content as of revision 22:f9b5e0b80bf2:
//***************************************************************************** // MT9D111.c // // Micron MT9D111 camera sensor driver // // 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 mt9d111 //! @{ // //***************************************************************************** #include <stdio.h> #include <stdbool.h> #include <stdint.h> #include "mbed.h" #include "cc3100_sl_common.h" #include "mt9d111.h" #include "i2cconfig.h" #include "cli_uart.h" #include "HttpDebug.h" #include "app_config.h" #define RET_OK 0 #define RET_ERROR -1 #define SENSOR_PAGE_REG 0xF0 #define CAM_I2C_SLAVE_WRITE 0xBA//Write #define CAM_I2C_SLAVE_READ 0xBB//Read #ifdef MT9D111_CAM DigitalOut standby(PA_3); #endif extern DCMI_HandleTypeDef phdcmi; /* Soft Reset Sequence */ static const s_RegList soft_reset_cmd_list[]= { {0, 0x65, 0xA000 }, // Bypass the PLL {1, 0xC3, 0x0501 }, // Perform MCU reset {0, 0x0D, 0x0021 }, // Enable soft reset {100, 0x00, 0x0032 }, // Delay = 50ms {0, 0x0D, 0x0000 }, // Disable soft reset {100, 0x00, 0x01f4 }, // Delay = 500ms }; #ifndef ENABLE_JPEG static const s_RegList preview_on_cmd_list[]= { {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0001 }, // SEQ_CMD, Do Preview {1, 0xC6, 0xA104 }, // SEQ_CMD {111, 0xC8, 0x0003 }, // SEQ_CMD, Do Preview {1, 0xC6, 0xA103 }, // SEQ_CMD-refresh {1, 0xC8, 0x0005 }, // SEQ_CMD-refresh {1, 0xC6, 0xA103 }, // SEQ_CMD-refresh {1, 0xC8, 0x0006 }, // SEQ_CMD-refresh {1, 0xC6, 0xA104 }, // SEQ_CMD {111, 0xC8, 0x0003 }, // SEQ_CMD, Do Preview {100, 0x00, 0x01f4 }, // Delay = 500ms }; static const s_RegList freq_setup_cmd_List[]= { {1, 0xC6, 0x276D }, // MODE_FIFO_CONF1_A {1, 0xC8, 0xE4E2 }, // MODE_FIFO_CONF1_A =(58594) {1, 0xC6, 0xA76F }, // MODE_FIFO_CONF2_A {1, 0xC8, 0x00E8 }, // MODE_FIFO_CONF2_A =(232) (1, 0xC6, 0x2774 ), // MODE_FIFO_CONF1_B ** (1, 0xC8, 0xE4E2 ), // MODE_FIFO_CONF1_B ** =(58594) (1, 0xC6, 0xA776 ), // MODE_FIFO_CONF2_B ** (1, 0xC8, 0x00E8 ), // MODE_FIFO_CONF2_B ** =(232) {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0005 }, // SEQ_CMD (Refresh) // Set maximum integration time to get a minimum of 15 fps at 45MHz {1, 0xC6, 0xA20E }, // AE_MAX_INDEX {1, 0xC8, 0x0004 }, // AE_MAX_INDEX {1, 0xC6, 0xA102 }, // SEQ_MODE {1, 0xC8, 0x0001 }, // SEQ_MODE {1, 0xC6, 0xA102 }, // SEQ_MODE {1, 0xC8, 0x0005 }, // SEQ_MODE // Set minimum integration time to get a maximum of 15 fps at 45MHz {1, 0xC6, 0xA20D }, // AE_MAX_INDEX {1, 0xC8, 0x0004 }, // AE_MAX_INDEX {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0005 }, // SEQ_CMD (Refresh) {100, 0x00, 0x01f4 }, // Delay = 500ms }; static const s_RegList image_size_240_320_preview_cmds_list[]= { {0, 0x07, 0x00FE }, // HORZ_BLANK_A {0, 0x08, 0x02A0 }, // VERT_BLANK_A {0, 0x20, 0x0303 }, // READ_MODE_B (Image flip settings) {0, 0x21, 0x8400 }, // READ_MODE_A (1ADC) {1, 0xC6, 0x2703 }, // MODE_OUTPUT_WIDTH_A {1, 0xC8, 0x00F0 }, // MODE_OUTPUT_WIDTH_A = 0xF0 (240) {1, 0xC6, 0x2705 }, // MODE_OUTPUT_HEIGHT_A {1, 0xC8, 0x0140 }, // MODE_OUTPUT_HEIGHT_A = 0x0140 (320) {1, 0xC6, 0x2727 }, // MODE_CROP_X0_A {1, 0xC8, 0x0000 }, // MODE_CROP_X0_A = 0x00 {1, 0xC6, 0x2729 }, // MODE_CROP_X1_A {1, 0xC8, 0x00F0 }, // MODE_CROP_X1_A = 0xF0 {1, 0xC6, 0x272B }, // MODE_CROP_Y0_A {1, 0xC8, 0x0000 }, // MODE_CROP_Y0_A = 0xF0 {1, 0xC6, 0x272D }, // MODE_CROP_Y1_A {1, 0xC8, 0x0140 }, // MODE_CROP_Y1_A = 0x0140 {1, 0xC6, 0x270F }, // MODE_SENSOR_ROW_START_A {1, 0xC8, 0x001C }, // MODE_SENSOR_ROW_START_A = 0x001C (28) {1, 0xC6, 0x2711 }, // MODE_SENSOR_COL_START_A {1, 0xC8, 0x003C }, // MODE_SENSOR_COL_START_A = 0x003C (60) {1, 0xC6, 0x2713 }, // MODE_SENSOR_ROW_HEIGHT_A {1, 0xC8, 0x0280 }, // MODE_SENSOR_ROW_HEIGHT_A = 0x0280 (640) {1, 0xC6, 0x2715 }, // MODE_SENSOR_COL_WIDTH_A {1, 0xC8, 0x03C0 }, // MODE_SENSOR_COL_WIDTH_A = 0x03C0 (960) {1, 0xC6, 0x2717 }, // MODE_SENSOR_X_DELAY_A {1, 0xC8, 0x0088 }, // MODE_SENSOR_X_DELAY_A = 0x0088 {1, 0xC6, 0x2719 }, // MODE_SENSOR_ROW_SPEED_A {1, 0xC8, 0x0011 }, // MODE_SENSOR_ROW_SPEED_A = 0x0011 {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0005 }, // SEQ_CMD = 0x0005 {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0006 }, // SEQ_CMD = 0x0006 {100, 0x00, 0x01f4 }, // Delay = 500ms }; static const s_RegList preview_cmds_list[]= { {1, 0xC6, 0xA77D }, // MODE_OUTPUT_FORMAT_A {1, 0xC8, 0x0020 }, // MODE_OUTPUT_FORMAT_A; RGB565 = 0x0020 {1, 0xC6, 0x270B }, // MODE_CONFIG {1, 0xC8, 0x0030 }, // MODE_CONFIG, JPEG disabled for A and B = 0x0030 {1, 0xC6, 0xA103 }, // SEQ_CMD {1, 0xC8, 0x0005 }, // SEQ_CMD, refresh = 0x0005 {100, 0x00, 0x01f4 }, // Delay = 500ms }; #else static const s_RegList pll_cmds_list[]= { {0, 0x65, 0xA000 }, // Disable PLL // {100, 0x00, 0x0064 }, // Delay =100ms {0, 0x65, 0xE000 }, // Power DOWN PLL {100, 0x00, 0x01F4 }, // Delay =500ms {0, 0x66, 0x3003 }, // M = 48 N = 3 PLL fIN = 8MHz fOUT = 24MHz // {0, 0x66, 0x7801 }, // M = 120 N = 1 PLL fIN = 8MHz fOUT = 60MHz {0, 0x67, 0x0501 }, // P = 1 {0, 0x65, 0xA000 }, // Disable PLL {100, 0x00, 0x01F4 }, // Delay =500ms {0, 0x65, 0x2000 }, // Enable PLL {100, 0x00, 0x01F4 }, // Delay =500ms }; static const s_RegList capture_cmds_list[]= { {0, 0x20, 0x0000 }, // READ_MODE_B (Image flip settings) {100, 0x00, 0x00FA }, // Delay =250ms {1, 0xC6, 0xA102 }, // SEQ_MODE {1, 0xC8, 0x0001 }, // SEQ_MODE {1, 0xC6, 0xA102 }, // SEQ_MODE {1, 0xC8, 0x0005 }, // SEQ_MODE {1, 0xC6, 0xA120 }, // Enable Capture video {1, 0xC8, 0x0002 }, {1, 0xC6, 0x270B }, // Mode config, disable JPEG bypass {1, 0xC8, 0x0000 }, {1, 0xC6, 0x2702 }, // FIFO_config0b, no spoof, adaptive clock {1, 0xC8, 0x001E }, {1, 0xC6, 0xA907 }, // JPEG mode config, video {1, 0xC8, 0x0035 }, {1, 0xC6, 0xA906 }, // Format YCbCr422 {1, 0xC8, 0x0000 }, {1, 0xC6, 0xA90A }, // Set the qscale1 {1, 0xC8, 0x0088 }, {1, 0xC6, 0x2908 }, // Set the restartInt {1, 0xC8, 0x0020 }, {100, 0x00, 0x00FA }, // Delay =250ms {1, 0xC6, 0x2707 }, // MODE_OUTPUT_WIDTH_B #ifdef XGA_FRAME {1, 0xC8, 1024 }, #endif #ifdef VGA_FRAME {1, 0xC8, 640 }, #endif #ifdef QVGA_FRAME {1, 0xC8, 320 }, #endif {1, 0xC6, 0x2709 }, // MODE_OUTPUT_HEIGHT_B #ifdef XGA_FRAME {1, 0xC8, 768 }, #endif #ifdef VGA_FRAME {1, 0xC8, 480 }, #endif #ifdef QVGA_FRAME {1, 0xC8, 240 }, #endif {1, 0xC6, 0x2735 }, // MODE_CROP_X0_B {1, 0xC8, 640 }, {1, 0xC6, 0x2737 }, // MODE_CROP_X1_B {1, 0xC8, 1600 }, {1, 0xC6, 0x2739 }, // MODE_CROP_Y0_B {1, 0xC8, 480 }, {1, 0xC6, 0x273B }, // MODE_CROP_Y1_B {1, 0xC8, 1200 }, {1, 0xC6, 0xA103 }, //SEQ_CMD {1, 0xC8, 0x0005 }, //SEQ_CMD, refresh {100, 0x00, 0x00FA }, // Delay = 250ms // {111, 0xC8,0x0002 }, //Wait for sequencer change }; static const s_RegList bypass_pll_list[]= { {0, 0x65, 0xA000 }, // Disable PLL {100, 0x00, 0x01F4 }, // Delay =500ms }; static const s_RegList enable_pll_list[]= { {0, 0x65, 0x2000 }, // Enable PLL {100, 0x00, 0x01F4 }, // Delay =500ms }; static const s_RegList context_a_list[]= { {1, 0xC6, 0xA103 }, //SEQ_CMD {1, 0xC8, 0x0001 }, //SEQ_CMD, Do Preview }; static const s_RegList enter_standby_list[]= { {1, 0xC6, 0xA103 }, //SEQ_CMD {1, 0xC8, 0x0003 }, //SEQ_CMD, standby }; static const s_RegList context_b_list[]= { {1, 0xC6, 0xA103 }, // SEQ_CMD, Do capture {1, 0xC8, 0x0002 }, // Start capture }; static const s_RegList start_capture_cmd_list[]= { {1, 0xC6, 0xA103 }, // SEQ_CMD, Do capture {1, 0xC8, 0x0002 }, // Start capture }; static const s_RegList stop_capture_cmd_list[]= { {1, 0xC6, 0xA103 }, // SEQ_CMD, Do capture {1, 0xC8, 0x0001 }, // Stop capture }; #define INDEX_CROP_X0 1 #define INDEX_CROP_X1 3 #define INDEX_CROP_Y0 5 #define INDEX_CROP_Y1 7 #define INDEX_SIZE_WIDTH 12//9 #define INDEX_SIZE_HEIGHT 14//11 static s_RegList resolution_cmds_list[]= { // {100, 0x00, 0x01F4 }, // Delay =500ms {1, 0xC6, 0x2735 }, //MODE_CROP_X0_A {1, 0xC8, 0x0000 }, //MODE_CROP_X0_A {1, 0xC6, 0x2737 }, //MODE_CROP_X1_A {1, 0xC8, 1600 }, //MODE_CROP_X1_A {1, 0xC6, 0x2739 }, //MODE_CROP_Y0_A {1, 0xC8, 0x0000 }, //MODE_CROP_Y0_A {1, 0xC6, 0x273B }, //MODE_CROP_Y1_A {1, 0xC8, 1200 }, //MODE_CROP_Y1_A {1, 0xC6, 0xA103 }, // SEQ_CMD, Do capture {1, 0xC8, 0x0005 }, {1, 0xC6, 0x2707 }, //MODE_OUTPUT_WIDTH_B {1, 0xC8, 640 }, //MODE_OUTPUT_WIDTH_B {1, 0xC6, 0x2709 }, //MODE_OUTPUT_HEIGHT_B {1, 0xC8, 480 }, //MODE_OUTPUT_HEIGHT_B {100, 0x00, 0x01f4 }, // Delay = 500ms }; #endif static const s_RegList init_cmds_list[]= { {0, 0x33, 0x0343 }, // RESERVED_CORE_33 {1, 0xC6, 0xA115 }, //SEQ_LLMODE {1, 0xC8, 0x0020 }, //SEQ_LLMODE {0, 0x38, 0x0866 }, // RESERVED_CORE_38 {100, 0x00, 0x0064 }, // Delay =100ms {2, 0x80, 0x0168 }, // LENS_CORRECTION_CONTROL {2, 0x81, 0x6432 }, // ZONE_BOUNDS_X1_X2 {2, 0x82, 0x3296 }, // ZONE_BOUNDS_X0_X3 {2, 0x83, 0x9664 }, // ZONE_BOUNDS_X4_X5 {2, 0x84, 0x5028 }, // ZONE_BOUNDS_Y1_Y2 {2, 0x85, 0x2878 }, // ZONE_BOUNDS_Y0_Y3 {2, 0x86, 0x7850 }, // ZONE_BOUNDS_Y4_Y5 {2, 0x87, 0x0000 }, // CENTER_OFFSET {2, 0x88, 0x0152 }, // FX_RED {2, 0x89, 0x015C }, // FX_GREEN {2, 0x8A, 0x00F4 }, // FX_BLUE {2, 0x8B, 0x0108 }, // FY_RED {2, 0x8C, 0x00FA }, // FY_GREEN {2, 0x8D, 0x00CF }, // FY_BLUE {2, 0x8E, 0x09AD }, // DF_DX_RED {2, 0x8F, 0x091E }, // DF_DX_GREEN {2, 0x90, 0x0B3F }, // DF_DX_BLUE {2, 0x91, 0x0C85 }, // DF_DY_RED {2, 0x92, 0x0CFF }, // DF_DY_GREEN {2, 0x93, 0x0D86 }, // DF_DY_BLUE {2, 0x94, 0x163A }, // SECOND_DERIV_ZONE_0_RED {2, 0x95, 0x0E47 }, // SECOND_DERIV_ZONE_0_GREEN {2, 0x96, 0x103C }, // SECOND_DERIV_ZONE_0_BLUE {2, 0x97, 0x1D35 }, // SECOND_DERIV_ZONE_1_RED {2, 0x98, 0x173E }, // SECOND_DERIV_ZONE_1_GREEN {2, 0x99, 0x1119 }, // SECOND_DERIV_ZONE_1_BLUE {2, 0x9A, 0x1663 }, // SECOND_DERIV_ZONE_2_RED {2, 0x9B, 0x1569 }, // SECOND_DERIV_ZONE_2_GREEN {2, 0x9C, 0x104C }, // SECOND_DERIV_ZONE_2_BLUE {2, 0x9D, 0x1015 }, // SECOND_DERIV_ZONE_3_RED {2, 0x9E, 0x1010 }, // SECOND_DERIV_ZONE_3_GREEN {2, 0x9F, 0x0B0A }, // SECOND_DERIV_ZONE_3_BLUE {2, 0xA0, 0x0D53 }, // SECOND_DERIV_ZONE_4_RED {2, 0xA1, 0x0D51 }, // SECOND_DERIV_ZONE_4_GREEN {2, 0xA2, 0x0A44 }, // SECOND_DERIV_ZONE_4_BLUE {2, 0xA3, 0x1545 }, // SECOND_DERIV_ZONE_5_RED {2, 0xA4, 0x1643 }, // SECOND_DERIV_ZONE_5_GREEN {2, 0xA5, 0x1231 }, // SECOND_DERIV_ZONE_5_BLUE {2, 0xA6, 0x0047 }, // SECOND_DERIV_ZONE_6_RED {2, 0xA7, 0x035C }, // SECOND_DERIV_ZONE_6_GREEN {2, 0xA8, 0xFE30 }, // SECOND_DERIV_ZONE_6_BLUE {2, 0xA9, 0x4625 }, // SECOND_DERIV_ZONE_7_RED {2, 0xAA, 0x47F3 }, // SECOND_DERIV_ZONE_7_GREEN {2, 0xAB, 0x5859 }, // SECOND_DERIV_ZONE_7_BLUE {2, 0xAC, 0x0000 }, // X2_FACTORS {2, 0xAD, 0x0000 }, // GLOBAL_OFFSET_FXY_FUNCTION {2, 0xAE, 0x0000 }, // K_FACTOR_IN_K_FX_FY {1, 0x08, 0x01FC }, // COLOR_PIPELINE_CONTROL {100, 0x00, 0x00C8 }, // Delay =200ms {1, 0xBE, 0x0004 }, // YUV_YCBCR_CONTROL {0, 0x65, 0xA000 }, // PLL CLOCK_ENABLING {100, 0x00, 0x00C8 }, // Delay =200ms {1, 0xC6, 0x2003 }, //MON_ARG1 {1, 0xC8, 0x0748 }, //MON_ARG1 {1, 0xC6, 0xA002 }, //MON_CMD {1, 0xC8, 0x0001 }, //MON_CMD {100, 0x00, 0x01F4 }, //Delay = 500ms {1, 0xC6, 0xA361 }, //AWB_TG_MIN0 {1, 0xC8, 0x00E2 }, //AWB_TG_MIN0 {1, 0x1F, 0x0018 }, // RESERVED_SOC1_1F {1, 0x51, 0x7F40 }, // RESERVED_SOC1_51 {100, 0x00, 0x01F4 }, //Delay = 500ms {0, 0x33, 0x0343 }, // RESERVED_CORE_33 {0, 0x38, 0x0868 }, // RESERVED_CORE_38 {1, 0xC6, 0xA10F }, //SEQ_RESET_LEVEL_TH {1, 0xC8, 0x0042 }, //SEQ_RESET_LEVEL_TH {1, 0x1F, 0x0020 }, // RESERVED_SOC1_1F {1, 0xC6, 0xAB04 }, //HG_MAX_DLEVEL {1, 0xC8, 0x0008 }, //HG_MAX_DLEVEL {1, 0xC6, 0xA120 }, //SEQ_CAP_MODE {1, 0xC8, 0x0002 }, //SEQ_CAP_MODE {1, 0xC6, 0xA103 }, //SEQ_CMD {1, 0xC8, 0x0001 }, //SEQ_CMD {100, 0x00, 0x01F4 }, // Delay =1000ms {1, 0xC6, 0xA102 }, //SEQ_MODE {1, 0xC8, 0x001F }, //SEQ_MODE {1, 0x08, 0x01FC }, // COLOR_PIPELINE_CONTROL {1, 0x08, 0x01EC }, // COLOR_PIPELINE_CONTROL {1, 0x08, 0x01FC }, // COLOR_PIPELINE_CONTROL {1, 0x36, 0x0F08 }, // APERTURE_PARAMETERS {1, 0xC6, 0x270B }, //MODE_CONFIG {1, 0xC8, 0x0030 }, //MODE_CONFIG, JPEG disabled for A and B {1, 0xC6, 0xA121 }, //SEQ_CAP_MODE {1, 0xC8, 0x007f }, //SEQ_CAP_MODE (127 frames before switching to Preview) {0, 0x05, 0x011E }, // HORZ_BLANK_B {0, 0x06, 0x006F }, // VERT_BLANK_B {0, 0x07, 0xFE }, // HORZ_BLANK_A {0, 0x08, 19 }, // VERT_BLANK_A {0, 0x20, 0x0303 }, // READ_MODE_B (Image flip settings) {0, 0x21, 0x8400 }, // READ_MODE_A (1ADC) {1, 0xC6, 0x2717 }, //MODE_SENSOR_X_DELAY_A {1, 0xC8, 792 }, //MODE_SENSOR_X_DELAY_A {1, 0xC6, 0x270F }, //MODE_SENSOR_ROW_START_A {1, 0xC8, 0x001C }, //MODE_SENSOR_ROW_START_A {1, 0xC6, 0x2711 }, //MODE_SENSOR_COL_START_A {1, 0xC8, 0x003C }, //MODE_SENSOR_COL_START_A {1, 0xC6, 0x2713 }, //MODE_SENSOR_ROW_HEIGHT_A {1, 0xC8, 0x04B0 }, //MODE_SENSOR_ROW_HEIGHT_A {1, 0xC6, 0x2715 }, //MODE_SENSOR_COL_WIDTH_A {1, 0xC8, 0x0640 }, //MODE_SENSOR_COL_WIDTH_A {1, 0xC6, 0x2719 }, //MODE_SENSOR_ROW_SPEED_A {1, 0xC8, 0x0011 }, //MODE_SENSOR_ROW_SPEED_A {1, 0xC6, 0x2707 }, //MODE_OUTPUT_WIDTH_B {1, 0xC8, 0x0640 }, //MODE_OUTPUT_WIDTH_B {1, 0xC6, 0x2709 }, //MODE_OUTPUT_HEIGHT_B {1, 0xC8, 0x04B0 }, //MODE_OUTPUT_HEIGHT_B {1, 0xC6, 0x271B }, //MODE_SENSOR_ROW_START_B {1, 0xC8, 0x001C }, //MODE_SENSOR_ROW_START_B {1, 0xC6, 0x271D }, //MODE_SENSOR_COL_START_B {1, 0xC8, 0x003C }, //MODE_SENSOR_COL_START_B {1, 0xC6, 0x271F }, //MODE_SENSOR_ROW_HEIGHT_B {1, 0xC8, 0x04B0 }, //MODE_SENSOR_ROW_HEIGHT_B {1, 0xC6, 0x2721 }, //MODE_SENSOR_COL_WIDTH_B {1, 0xC8, 0x0640 }, //MODE_SENSOR_COL_WIDTH_B {1, 0xC6, 0x2723 }, //MODE_SENSOR_X_DELAY_B {1, 0xC8, 0x0716 }, //MODE_SENSOR_X_DELAY_B {1, 0xC6, 0x2725 }, //MODE_SENSOR_ROW_SPEED_B {1, 0xC8, 0x0011 }, //MODE_SENSOR_ROW_SPEED_B //Maximum Slew-Rate on IO-Pads (for Mode A) {1, 0xC6, 0x276B }, //MODE_FIFO_CONF0_A {1, 0xC8, 0x0027 }, //MODE_FIFO_CONF0_A {1, 0xC6, 0x276D }, //MODE_FIFO_CONF1_A {1, 0xC8, 0xE1E1 }, //MODE_FIFO_CONF1_A {1, 0xC6, 0xA76F }, //MODE_FIFO_CONF2_A {1, 0xC8, 0x00E1 }, //MODE_FIFO_CONF2_A //Maximum Slew-Rate on IO-Pads (for Mode B) {1, 0xC6, 0x2772 }, //MODE_FIFO_CONF0_B {1, 0xC8, 0x0027 }, //MODE_FIFO_CONF0_B {1, 0xC6, 0x2774 }, //MODE_FIFO_CONF1_B {1, 0xC8, 0xE1E1 }, //MODE_FIFO_CONF1_B {1, 0xC6, 0xA776 }, //MODE_FIFO_CONF2_B {1, 0xC8, 0x00E1 }, //MODE_FIFO_CONF2_B //Set maximum integration time to get a minimum of 15 fps at 45MHz {1, 0xC6, 0xA20E }, //AE_MAX_INDEX {1, 0xC8, 0x0004 }, //AE_MAX_INDEX //Set minimum integration time to get a maximum of 15 fps at 45MHz {1, 0xC6, 0xA20D }, //AE_MAX_INDEX {1, 0xC8, 0x0004 }, //AE_MAX_INDEX // Configue all GPIO for output and set low to save power {1, 0xC6, 0x9078 }, {1, 0xC8, 0x0000 }, {1, 0xC6, 0x9079 }, {1, 0xC8, 0x0000 }, {1, 0xC6, 0x9070 }, {1, 0xC8, 0x0000 }, {1, 0xC6, 0x9071 }, {1, 0xC8, 0x0000 }, // gamma and contrast {1, 0xC6, 0xA743 }, // MODE_GAM_CONT_A {1, 0xC8, 0x0003 }, // MODE_GAM_CONT_A {1, 0xC6, 0xA744 }, // MODE_GAM_CONT_B {1, 0xC8, 0x0003 }, // MODE_GAM_CONT_B {100, 0x00, 0x01f4 }, // Delay =500ms }; void getCamId() { uint16_t Id = 0; uint8_t ucBuffer[20]; ucBuffer[0] = 0x00; ucBuffer[1] = 0x00; int lRetVal = -1; lRetVal = RegLstWrite((s_RegList *)soft_reset_cmd_list, sizeof(soft_reset_cmd_list)/sizeof(s_RegList)); wait_ms(1); I2CBufferWrite(CAM_I2C_SLAVE_WRITE,ucBuffer,1,I2C_SEND_STOP); I2CBufferRead(CAM_I2C_SLAVE_READ,ucBuffer,2,I2C_SEND_STOP); Id = (uint16_t)ucBuffer[0] << 8 | (uint16_t)ucBuffer[1]; HttpDebug("\r\nCamera ID = 0x%x\r\n",Id); if(Id != 0x1519) { HttpDebug("MT9D111 Camera not found! I2C read/write failed. \n\r"); HAL_DCMI_MspDeInit(&phdcmi); while(1); } } //***************************************************************************** // //! This function initilizes the camera sensor //! //! \param None //! //! \return 0 - Success //! -1 - Error // //***************************************************************************** int CameraSensorInit() { HttpDebug("CameraSensorInit \n\r"); int lRetVal = -1; lRetVal = RegLstWrite((s_RegList *)init_cmds_list, \ sizeof(init_cmds_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); lRetVal = RegLstWrite((s_RegList *)pll_cmds_list, \ sizeof(pll_cmds_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); #ifndef ENABLE_JPEG lRetVal = RegLstWrite((s_RegList *)preview_cmds_list, sizeof(preview_cmds_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); lRetVal = RegLstWrite((s_RegList *)image_size_240_320_preview_cmds_list, \ sizeof(image_size_240_320_preview_cmds_list)/ \ sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); lRetVal = RegLstWrite((s_RegList *)freq_setup_cmd_List, sizeof(freq_setup_cmd_List)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); lRetVal = RegLstWrite((s_RegList *)preview_on_cmd_list, sizeof(preview_on_cmd_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); #endif return 0; } //***************************************************************************** // //! This function configures the sensor in JPEG mode //! //! \param[in] width - X-Axis //! \param[in] height - Y-Axis //! //! \return 0 - Success //! -1 - Error // //***************************************************************************** int StartSensorInJpegMode(int width, int height) { #ifdef ENABLE_JPEG int lRetVal = -1; HttpDebug("\n\rStartSensorInJpegMode \n\r"); lRetVal = RegLstWrite((s_RegList *)capture_cmds_list, sizeof(capture_cmds_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); #endif return 0; } int StartCaptureCmd() { int32_t lRetVal= -1; #ifdef ENABLE_JPEG lRetVal = RegLstWrite((s_RegList *)start_capture_cmd_list, sizeof(start_capture_cmd_list)/sizeof(s_RegList)); #endif return 0; } int StopCaptureCmd() { int32_t lRetVal= -1; #ifdef ENABLE_JPEG lRetVal = RegLstWrite((s_RegList *)stop_capture_cmd_list, sizeof(stop_capture_cmd_list)/sizeof(s_RegList)); #endif return 0; } //***************************************************************************** // //! This function configures the sensor ouput resolution //! //! \param[in] width - X-Axis //! \param[in] height - Y-Axis //! //! \return 0 - Success //! -1 - Error // //***************************************************************************** int CameraSensorResolution(int width, int height) { HttpDebug("CameraSensorResolution \n\r"); #ifdef ENABLE_JPEG int lRetVal = -1; lRetVal = RegLstWrite((s_RegList *)stop_capture_cmd_list, sizeof(stop_capture_cmd_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); resolution_cmds_list[INDEX_SIZE_WIDTH].usValue = width; resolution_cmds_list[INDEX_SIZE_HEIGHT].usValue = height; lRetVal = RegLstWrite((s_RegList *)resolution_cmds_list, sizeof(resolution_cmds_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); lRetVal = RegLstWrite((s_RegList *)start_capture_cmd_list, sizeof(start_capture_cmd_list)/sizeof(s_RegList)); ASSERT_ON_ERROR(lRetVal); #else if(width != 240 || height != 256) return -1; #endif return 0; } //***************************************************************************** // //! This function implements the Register Write in MT9D111 sensor //! //! \param1 Register List //! \param2 No. Of Items //! //! \return 0 - Success //! -1 - Error // //***************************************************************************** static int RegLstWrite(s_RegList *pRegLst, unsigned int ulNofItems) { unsigned int ulNdx; unsigned short usTemp; unsigned char i; uint8_t ucBuffer[20]; unsigned int ulSize; int lRetVal = -1; int l = 0; if(pRegLst == NULL) { return RET_ERROR; } for(ulNdx = 0; ulNdx < ulNofItems; ulNdx++) { if(pRegLst->ucPageAddr == 100) { // PageAddr == 100, insret a delay equal to reg value wait_ms(pRegLst->usValue); } else { // Set the page ucBuffer[0] = SENSOR_PAGE_REG;//0xF0 ucBuffer[1] = 0x00; ucBuffer[2] = pRegLst->ucPageAddr; if(0 != I2CBufferWrite(CAM_I2C_SLAVE_WRITE, ucBuffer, 3, I2C_SEND_STOP)) { HttpDebug("\n\rError writing SENSOR_PAGE_REG \n\r"); return RET_ERROR; } ucBuffer[0] = SENSOR_PAGE_REG; lRetVal = I2CBufferWrite(CAM_I2C_SLAVE_WRITE, ucBuffer, 1, 0); ASSERT_ON_ERROR(lRetVal); lRetVal = I2CBufferRead(CAM_I2C_SLAVE_READ, ucBuffer, 2, I2C_SEND_STOP); ASSERT_ON_ERROR(lRetVal); ucBuffer[0] = pRegLst->ucRegAddr; if(pRegLst->ucPageAddr == 0x1 && pRegLst->ucRegAddr == 0xC8) { usTemp = 0xC8; i=1; while(pRegLst->ucRegAddr == usTemp) { ucBuffer[i] = (unsigned char)(pRegLst->usValue >> 8); ucBuffer[i+1] = (unsigned char)(pRegLst->usValue & 0xFF); i += 2; usTemp++; pRegLst++; ulNdx++; } ulSize = (i-2)*2 + 1; ulNdx--; pRegLst--; } else { ulSize = 3; ucBuffer[1] = (unsigned char)(pRegLst->usValue >> 8); ucBuffer[2] = (unsigned char)(pRegLst->usValue & 0xFF); } if(0 != I2CBufferWrite(CAM_I2C_SLAVE_WRITE,ucBuffer, ulSize,I2C_SEND_STOP)) { HttpDebug("\n\rError i2c write \n\r"); return RET_ERROR; } } pRegLst++; wait_ms(10); } return RET_OK; } static int wait_for_seq_state(int state) { int i, new_state; for (i = 0; i < 1000; i++) { new_state = read_firmware_var(SEQ_DRV_ID, SEQ_STATE_OFFSET, 1); // HttpDebug("seq state %d\r\n", new_state); if (new_state == state){ return 0; } wait_ms(2); } HttpDebug("Timeout waiting for seq_state %d\r\n", state); return 1; } /* * Read a 8/16-bit value from a firmware driver given the driver ID and the * var offset. It assumes logic address. * The value is returned if successful, or 1 otherwise. */ static uint16_t read_firmware_var(int id, int offset, int byte) { uint16_t val; uint8_t ucBuffer[20]; /* always use logical address */ val = VAR_ADDRESS_TYPE_LOGIC << VAR_ADDRESS_TYPE_SHIFT; val |= (byte << VAR_LENGTH_SHIFT); val |= (id << VAR_DRV_ID_SHIFT); val |= (offset << VAR_ADDRESS_SHIFT); ucBuffer[0] = REG_PAGE;//0xF0 ucBuffer[1] = 0x00; ucBuffer[2] = PAGE_IFP1;//1 /* setup page pointer */ if (I2CBufferWrite(CAM_I2C_SLAVE_WRITE, (uint8_t*)ucBuffer, 3, I2C_SEND_STOP)){ return 1; } ucBuffer[0] = REG_VAR_ADDR;//0xC6 ucBuffer[1] = val >> 8; ucBuffer[2] = val & 0x00FF; /* setup var pointer */ if (I2CBufferWrite(CAM_I2C_SLAVE_WRITE, (uint8_t*)ucBuffer, 3, I2C_SEND_STOP)){ return 1; } ucBuffer[0] = REG_VAR_DATA;//0xC8 if (I2CBufferWrite(CAM_I2C_SLAVE_WRITE, (uint8_t*)ucBuffer, 1, I2C_SEND_STOP)){ return 1; } /* read the var */ if (I2CBufferRead(CAM_I2C_SLAVE_READ, ucBuffer, 2, I2C_SEND_STOP)){ return 1; } val = ucBuffer[0] << 8; val |= ucBuffer[1]; return val; } int Start_still_capture(int frames) { int err = 1; // HttpDebug("Context B comamnd sequence ..."); err = RegLstWrite((s_RegList *)context_b_list, sizeof(context_b_list)/sizeof(s_RegList)); if (err){ return err; } /* wait until the seq driver state change */ err = wait_for_seq_state(SEQ_STATE_CAPTURE); if (err == 1){ return err; } /* need a few frames delay to stablize the output */ // wait_ms(500); return 0; } int Stop_still_capture(){ int err = 1; // HttpDebug("Context A comamnd sequence ..."); err = RegLstWrite((s_RegList *)context_a_list, sizeof(context_a_list)/sizeof(s_RegList)); if (err){ return err; } /* wait until the seq driver state change */ err = wait_for_seq_state(SEQ_STATE_PREVIEW); if (err == 1){ return err; } return 0; } int cam_power_on(void) { int err; HttpDebug("cam_power_on \r\n"); /* the caller already enabled our XCLK, wait to make sure it is stable */ wait_us(100); /* release STANDBY line */ cam_exit_standby(); /* wait 1ms before enable PLL per Micron Tech. Note */ wait_ms(1); err = RegLstWrite((s_RegList *)pll_cmds_list, sizeof(pll_cmds_list)/sizeof(s_RegList)); if (err){ return err; } err = RegLstWrite((s_RegList *)context_a_list, sizeof(context_a_list)/sizeof(s_RegList)); if (err){ return err; } err = wait_for_seq_state(SEQ_STATE_PREVIEW); return err; } int cam_power_off(void) { int err; /* have to check sequencer is in preview mode */ if (read_firmware_var(SEQ_DRV_ID, SEQ_STATE_OFFSET, 1) != SEQ_STATE_PREVIEW) { // printf("Calling power_off while not in preview state!\r\n"); /* Put sequencer in preview mode */ err = RegLstWrite((s_RegList *)context_a_list, sizeof(context_a_list)/sizeof(s_RegList)); if (err){ HttpDebug("Error writing context_a_list!\r\n"); return err; } err = wait_for_seq_state(SEQ_STATE_PREVIEW); if (err){ HttpDebug("Cannot place cam in preview state!\r\n"); return err; } } /* Issue standby command to sequencer */ err = RegLstWrite((s_RegList *)enter_standby_list, sizeof(enter_standby_list)/sizeof(s_RegList)); if (err){ return err; } /* Poll the sequencer until it enters standby state */ err = wait_for_seq_state(SEQ_STATE_STANDBY); if (err){ return err; } /* bypass PLL */ err = RegLstWrite((s_RegList *)bypass_pll_list, sizeof(bypass_pll_list)/sizeof(s_RegList)); if (err){ return err; } /* assert STANDBY line */ cam_enter_standby(); /* the caller can cut off XCLK now */ return 0; } void cam_exit_standby(void) { #ifdef MT9D111_CAM HttpDebug("cam_exit_standby \r\n"); standby = 0; #endif } void cam_enter_standby(void) { #ifdef MT9D111_CAM HttpDebug("cam_enter_standby \r\n"); standby = 1; wait(1); #endif } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************