123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /*
- * Copyright (c) 2021 HPMicro
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
- #include "hpm_ov7725.h"
- static const uint8_t ov7725_default_regs[][2] = {
- {COM4, 0x41}, /* bypass PLL */
- /*
- * VGA Window Size
- */
- {HSTART, 0x22},
- {HSIZE, 0xa4},
- {VSTART, 0x07},
- {VSIZE, 0xf0},
- {HREF, 0x00},
- /*
- * Scale down to VGA Resolution
- */
- {HOUTSIZE, 0xA0},
- {VOUTSIZE, 0xF0},
- {COM12, 0x03},
- {EXHCH, 0x00},
- {TGT_B, 0x7F},
- {FIXGAIN, 0x09},
- {AWB_CTRL0, 0xE0},
- {DSP_CTRL1, 0xFF},
- {DSP_CTRL2, 0x20},
- {DSP_CTRL3, 0x00},
- {DSP_CTRL4, 0x00},
- {COM8, 0xF8},
- {COM6, 0xC5},
- {COM9, 0x11},
- {COM10, COM10_VSYNC_NEG | COM10_PCLK_MASK}, /* Invert VSYNC and MASK PCLK */
- {BDBASE, 0x7F},
- {DBSTEP, 0x03},
- {AEW, 0x70},
- {AEB, 0x43},
- {VPT, 0xA1},
- {EXHCL, 0x00},
- {AWB_CTRL3, 0xAA},
- {COM8, 0xFF},
- /*
- * Gamma
- */
- {GAM1, 0x0C},
- {GAM2, 0x16},
- {GAM3, 0x2A},
- {GAM4, 0x4E},
- {GAM5, 0x61},
- {GAM6, 0x6F},
- {GAM7, 0x7B},
- {GAM8, 0x86},
- {GAM9, 0x8E},
- {GAM10, 0x97},
- {GAM11, 0xA4},
- {GAM12, 0xAF},
- {GAM13, 0xC5},
- {GAM14, 0xD7},
- {GAM15, 0xE8},
- {SLOP, 0x20},
- {EDGE1, 0x05},
- {EDGE2, 0x03},
- {EDGE3, 0x00},
- {DNSOFF, 0x01},
- {MTX1, 0xB0},
- {MTX2, 0x9D},
- {MTX3, 0x13},
- {MTX4, 0x16},
- {MTX5, 0x7B},
- {MTX6, 0x91},
- {MTX_CTRL, 0x1E},
- {BRIGHTNESS, 0x08},
- {CONTRAST, 0x20},
- {UVADJ0, 0x81},
- {SDE, (SDE_CONT_BRIGHT_EN | SDE_SATURATION_EN)},
- /*
- * For 30 fps/60Hz
- */
- {DM_LNL, 0x00},
- {DM_LNH, 0x00},
- {BDBASE, 0x7F},
- {DBSTEP, 0x03},
- /*
- * Lens Correction, should be tuned with real camera module
- */
- {LC_RADI, 0x10},
- {LC_COEF, 0x10},
- {LC_COEFB, 0x14},
- {LC_COEFR, 0x17},
- {LC_CTR, 0x05},
- {COM5, 0x65},
- };
- static const uint8_t ov7725_default_yuv_regs[][2] = {
- {COM12, 0x03},
- {HSTART, 0x22},
- {HSIZE, 0xa4},
- {VSTART, 0x07},
- {VSIZE, 0xf0},
- {HREF, 0x00},
- {HOUTSIZE, 0xa0},
- {VOUTSIZE, 0xf0},
- {EXHCH, 0x00},
- {CLKRC, 0x01},
- {TGT_B, 0x7f},
- {FIXGAIN, 0x09},
- {AWB_CTRL0, 0xe0},
- {DSP_CTRL1, 0xff},
- {DSP_CTRL2, 0x20},
- {DSP_CTRL3, 0x00},
- {DSP_CTRL4, 0x48},
- {COM8, 0xf0},
- {COM4, 0x41}, /* 0x51/ 0x61/ 0x71 for different AEC/AGC window */
- {COM6, 0xc5},
- {COM9, 0x11},
- {BDBASE, 0x7f},
- {DBSTEP, 0x03},
- {AEW, 0x40},
- {AEB, 0x30},
- {VPT, 0xa1},
- {EXHCL, 0x00},
- {AWB_CTRL3, 0xaa},
- {COM8, 0xff},
- {EDGE1, 0x05},
- {DNSOFF, 0x01},
- {EDGE2, 0x03},
- {EDGE3, 0x00},
- {MTX1, 0xb0},
- {MTX2, 0x9d},
- {MTX3, 0x13},
- {MTX4, 0x16},
- {MTX5, 0x7b},
- {MTX6, 0x91},
- {MTX_CTRL, 0x1e},
- {BRIGHTNESS, 0x08},
- {CONTRAST, 0x20},
- {UVADJ0, 0x81},
- {SDE, 0x06},
- /* Gamma */
- {GAM1, 0x0c},
- {GAM2, 0x16},
- {GAM3, 0x2a},
- {GAM4, 0x4e},
- {GAM5, 0x61},
- {GAM6, 0x6f},
- {GAM7, 0x7b},
- {GAM8, 0x86},
- {GAM9, 0x8e},
- {GAM10, 0x97},
- {GAM11, 0xa4},
- {GAM12, 0xaf},
- {GAM13, 0xc5},
- {GAM14, 0xd7},
- {GAM15, 0xe8},
- {SLOP, 0x20},
- /* for 30 fps,0Hz */
- {DM_LNL, 0x00},
- {BDBASE, 0x7f},
- {DBSTEP, 0x03},
- /* Lens Correcon, should be tuned with real camera module */
- {LC_RADI, 0x10},
- {LC_COEF, 0x10},
- {LC_COEFB, 0x14},
- {LC_COEFR, 0x17},
- {LC_CTR, 0x05},
- {COM5, 0x65},
- };
- hpm_stat_t ov7725_read_register(camera_context_t *context, uint8_t reg, uint8_t *buf)
- {
- hpm_stat_t stat = i2c_master_write(context->ptr, context->i2c_device_addr, ®, 1);
- if (stat != status_success) {
- return stat;
- }
- return i2c_master_read(context->ptr, context->i2c_device_addr, buf, 1);
- }
- hpm_stat_t ov7725_write_register(camera_context_t *context, uint8_t reg, uint8_t val)
- {
- return i2c_master_address_write(context->ptr, context->i2c_device_addr, ®, 1, &val, 1);
- }
- hpm_stat_t ov7725_load_settings(camera_context_t *context, uint8_t *reg_values, uint32_t count)
- {
- hpm_stat_t stat = status_success;
- for (uint32_t i = 0, j = 0; i < count; i++, j += 2) {
- stat = ov7725_write_register(context, reg_values[j], reg_values[j+1]);
- if (stat != status_success) {
- break;
- }
- }
- return stat;
- }
- hpm_stat_t ov7725_software_reset(camera_context_t *context)
- {
- hpm_stat_t stat = status_success;
- stat = ov7725_write_register(context, COM7, COM7_RESET);
- if (stat != status_success) {
- return stat;
- }
- return stat;
- }
- hpm_stat_t ov7725_check_chip_id(camera_context_t *context)
- {
- hpm_stat_t stat = status_success;
- uint8_t val_h = 0;
- uint8_t val_l = 0;
- HPM_CHECK_RET(ov7725_read_register(context, OV7725_CHIP_ID_HIGH_BYTE_ADDR, &val_h));
- HPM_CHECK_RET(ov7725_read_register(context, OV7725_CHIP_ID_LOW_BYTE_ADDR, &val_l));
- if (val_h != OV7725_CHIP_ID_HIGH_BYTE_VALUE) {
- return status_fail;
- }
- if (val_l != OV7725_CHIP_ID_LOW_BYTE_VALUE) {
- return status_fail;
- }
- return stat;
- }
- static hpm_stat_t ov7725_set_framesize(camera_context_t *context, uint16_t width, uint16_t height)
- {
- hpm_stat_t stat = status_success;
- uint32_t hstart = 0x22U << 2;
- uint32_t vstart = 0x7U << 1;
- uint32_t hsize = width + 16;
- stat |= ov7725_write_register(context, HSTART, hstart >> 2);
- stat |= ov7725_write_register(context, HSIZE, hsize >> 2);
- stat |= ov7725_write_register(context, VSTART, vstart >> 1);
- stat |= ov7725_write_register(context, VSIZE, height >> 1);
- stat |= ov7725_write_register(context, HOUTSIZE, width >> 2);
- stat |= ov7725_write_register(context, VOUTSIZE, height >> 1);
- stat |= ov7725_write_register(context, HREF,
- ((vstart & 1) << 6) | ((hstart & 3) << 4) | ((height & 1) << 2) | ((hsize & 3) << 0));
- stat = ov7725_write_register(context, EXHCH, ((height & 0x1) << 2) | (width & 0x3));
- if (stat != status_success) {
- return stat;
- }
- return stat;
- }
- hpm_stat_t ov7725_set_pixel_format(camera_context_t *context, display_pixel_format_t pixel_format)
- {
- hpm_stat_t stat = status_success;
- uint8_t val = 0;
- stat |= ov7725_read_register(context, COM7, &val);
- val &= ~0x1F;
- switch (pixel_format) {
- case display_pixel_format_rgb565:
- val |= COM7_FMT_RGB565;
- break;
- case display_pixel_format_rgb444:
- val |= COM7_FMT_RGB444;
- break;
- case display_pixel_format_yuv422:
- case display_pixel_format_y8:
- val |= COM7_FMT_YUV;
- break;
- case display_pixel_format_raw8:
- stat |= ov7725_write_register(context, DSP_CTRL4, DSP_CTRL4_RAW8);
- val |= COM7_FMT_R_BAYER;
- break;
- default:
- stat = status_invalid_argument;
- break;
- }
- if (stat != status_success) {
- return stat;
- }
- stat |= ov7725_write_register(context, COM7, val);
- if (stat != status_success) {
- return stat;
- }
- return stat;
- }
- hpm_stat_t ov7725_init(camera_context_t *context, camera_config_t *ov_config)
- {
- hpm_stat_t stat = status_success;
- switch (ov_config->pixel_format) {
- case display_pixel_format_yuv422:
- case display_pixel_format_y8:
- ov7725_load_settings(context, (uint8_t *) ov7725_default_yuv_regs, ARRAY_SIZE(ov7725_default_yuv_regs));
- break;
- default:
- ov7725_load_settings(context, (uint8_t *) ov7725_default_regs, ARRAY_SIZE(ov7725_default_regs));
- stat |= ov7725_write_register(context, COM7, COM7_RES_VGA | COM7_FMT_RGB565);
- stat |= ov7725_write_register(context, COM10, 0);
- stat |= ov7725_write_register(context, COM3, 0);
- break;
- }
- stat |= ov7725_write_register(context, CLKRC, 0x2);
- stat |= ov7725_write_register(context, COM4, 0x41);
- stat |= ov7725_set_framesize(context, ov_config->width, ov_config->height);
- stat |= ov7725_set_pixel_format(context, ov_config->pixel_format);
- if (stat != status_success) {
- return stat;
- }
- return stat;
- }
- void ov7725_power_up(camera_context_t *context)
- {
- assert(context->delay_ms != NULL);
- if (context->write_rst) {
- context->write_rst(OV7725_RST_ACTIVE);
- }
- if (context->write_pwdn) {
- context->write_pwdn(OV7725_PWDN_ACTIVE);
- }
- context->delay_ms(5);
- if (context->write_pwdn) {
- context->write_pwdn(OV7725_PWDN_INACTIVE);
- }
- context->delay_ms(2);
- if (context->write_rst) {
- context->write_rst(OV7725_RST_INACTIVE);
- }
- context->delay_ms(20);
- }
|