mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Add HIMAX HM01B0 driver.
This commit is contained in:
parent
85b207ce3f
commit
abd977c60f
@ -187,6 +187,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
|
||||
ov5640.o \
|
||||
mt9v034.o \
|
||||
lepton.o \
|
||||
hm01b0.o \
|
||||
sensor.o \
|
||||
stm32fxxx_hal_msp.o \
|
||||
soft_i2c.o \
|
||||
@ -504,6 +505,7 @@ UVC_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
|
||||
ov5640.o \
|
||||
mt9v034.o \
|
||||
lepton.o \
|
||||
hm01b0.o \
|
||||
sensor.o \
|
||||
stm32fxxx_hal_msp.o \
|
||||
soft_i2c.o \
|
||||
|
||||
@ -25,6 +25,7 @@ SRCS += $(addprefix , \
|
||||
ov5640.c \
|
||||
mt9v034.c \
|
||||
lepton.c \
|
||||
hm01b0.c \
|
||||
sensor.c \
|
||||
stm32fxxx_hal_msp.c \
|
||||
soft_i2c.c \
|
||||
|
||||
229
src/omv/hm01b0.c
Normal file
229
src/omv/hm01b0.c
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* HM01B0 driver.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include STM32_HAL_H
|
||||
#include "cambus.h"
|
||||
#include "hm01b0.h"
|
||||
#include "hm01b0_regs.h"
|
||||
#include "systick.h"
|
||||
#include "omv_boardconfig.h"
|
||||
#define HIMAX_BOOT_RETRY (10)
|
||||
|
||||
#if (OMV_SENSOR_HM01B0 == 1)
|
||||
static const uint16_t default_regs[][2] = {
|
||||
{BLC_TGT, 0x08}, // BLC target :8 at 8 bit mode
|
||||
{BLC2_TGT, 0x08}, // BLI target :8 at 8 bit mode
|
||||
{0x3044, 0x0A}, // Increase CDS time for settling
|
||||
{0x3045, 0x00}, // Make symetric for cds_tg and rst_tg
|
||||
{0x3047, 0x0A}, // Increase CDS time for settling
|
||||
{0x3050, 0xC0}, // Make negative offset up to 4x
|
||||
{0x3051, 0x42},
|
||||
{0x3052, 0x50},
|
||||
{0x3053, 0x00},
|
||||
{0x3054, 0x03}, // tuning sf sig clamping as lowest
|
||||
{0x3055, 0xF7}, // tuning dsun
|
||||
{0x3056, 0xF8}, // increase adc nonoverlap clk
|
||||
{0x3057, 0x29}, // increase adc pwr for missing code
|
||||
{0x3058, 0x1F}, // turn on dsun
|
||||
{0x3059, 0x1E},
|
||||
{0x3064, 0x00},
|
||||
{0x3065, 0x04}, // pad pull 0
|
||||
|
||||
{BLC_CFG, 0x43}, // BLC_on, IIR
|
||||
|
||||
{0x1001, 0x43}, // BLC dithering en
|
||||
{0x1002, 0x43}, // blc_darkpixel_thd
|
||||
{0x0350, 0x00}, // Dgain Control
|
||||
{BLI_EN, 0x01}, // BLI enable
|
||||
{0x1003, 0x00}, // BLI Target [Def: 0x20]
|
||||
|
||||
{DPC_CTRL, 0x01}, // DPC option 0: DPC off 1 : mono 3 : bayer1 5 : bayer2
|
||||
{0x1009, 0xA0}, // cluster hot pixel th
|
||||
{0x100A, 0x60}, // cluster cold pixel th
|
||||
{SINGLE_THR_HOT, 0x90}, // single hot pixel th
|
||||
{SINGLE_THR_COLD, 0x40}, // single cold pixel th
|
||||
{0x1012, 0x00}, // Sync. shift disable
|
||||
{0x2000, 0x07},
|
||||
{0x2003, 0x00},
|
||||
{0x2004, 0x1C},
|
||||
{0x2007, 0x00},
|
||||
{0x2008, 0x58},
|
||||
{0x200B, 0x00},
|
||||
{0x200C, 0x7A},
|
||||
{0x200F, 0x00},
|
||||
{0x2010, 0xB8},
|
||||
{0x2013, 0x00},
|
||||
{0x2014, 0x58},
|
||||
{0x2017, 0x00},
|
||||
{0x2018, 0x9B},
|
||||
|
||||
{AE_CTRL, 0x01}, //Automatic Exposure
|
||||
{AE_TARGET_MEAN, 0x3C}, //AE target mean [Def: 0x3C]
|
||||
{AE_MIN_MEAN, 0x0A}, //AE min target mean [Def: 0x0A]
|
||||
|
||||
{INTEGRATION_H, 0x00}, //Integration H [Def: 0x01]
|
||||
{INTEGRATION_L, 0x60}, //Integration L [Def: 0x08]
|
||||
{ANALOG_GAIN, 0x00}, //Analog Global Gain [Def: 0x00]
|
||||
{DAMPING_FACTOR, 0x20}, //Damping Factor [Def: 0x20]
|
||||
{DIGITAL_GAIN_H, 0x01}, //Digital Gain High [Def: 0x01]
|
||||
{DIGITAL_GAIN_L, 0x00}, //Digital Gain Low [Def: 0x00]
|
||||
|
||||
{CONVERGE_IN_TH, 0x03}, //Converge in threshold [Def: 0x03]
|
||||
{CONVERGE_OUT_TH, 0x05}, //Converge out threshold [Def: 0x05]
|
||||
{MAX_INTG_H, 0x01}, //Maximum INTG High Byte [Def: 0x01]
|
||||
{MAX_INTG_L, 0x54}, //Maximum INTG Low Byte [Def: 0x54]
|
||||
{MAX_AGAIN_FULL, 0x03}, //Maximum Analog gain in full frame mode [Def: 0x03]
|
||||
{MAX_AGAIN_BIN2, 0x04}, //Maximum Analog gain in bin2 mode [Def: 0x04]
|
||||
|
||||
{0x210B, 0xC0},
|
||||
{0x210E, 0x00}, //Flicker Control
|
||||
{0x210F, 0x00},
|
||||
{0x2110, 0x3C},
|
||||
{0x2111, 0x00},
|
||||
{0x2112, 0x32},
|
||||
|
||||
{0x2150, 0x30},
|
||||
{0x0340, 0x02},
|
||||
{0x0341, 0x16},
|
||||
{0x0342, 0x01},
|
||||
{0x0343, 0x78},
|
||||
{0x3010, 0x01},
|
||||
{0x0383, 0x01},
|
||||
{0x0387, 0x01},
|
||||
{0x0390, 0x00},
|
||||
{0x3011, 0x70},
|
||||
{0x3059, 0x02},
|
||||
{0x3060, 0x01},
|
||||
{IMG_ORIENTATION, 0x01}, // change the orientation
|
||||
{0x0104, 0x01},
|
||||
|
||||
//============= End of regs marker ==================
|
||||
{0x0000, 0x00},
|
||||
};
|
||||
|
||||
static int reset(sensor_t *sensor)
|
||||
{
|
||||
// Reset sensor.
|
||||
uint8_t reg=0xff;
|
||||
for (int retry=HIMAX_BOOT_RETRY; reg != HIMAX_MODE_STANDBY; retry--) {
|
||||
if (retry == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (cambus_writeb2(sensor->slv_addr, SW_RESET, HIMAX_RESET) != 0) {
|
||||
return -1;
|
||||
}
|
||||
// Delay for 1ms.
|
||||
systick_sleep(1);
|
||||
if (cambus_readb2(sensor->slv_addr, MODE_SELECT, ®) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Write default regsiters
|
||||
int ret = 0;
|
||||
for (int i=0; default_regs[i][0] && ret == 0; i++) {
|
||||
ret |= cambus_writeb2(sensor->slv_addr, default_regs[i][0], default_regs[i][1]);
|
||||
}
|
||||
|
||||
// Set PCLK polarity.
|
||||
ret |= cambus_writeb2(sensor->slv_addr, PCLK_POLARITY, (0x20 | PCLK_FALLING_EDGE));
|
||||
|
||||
// TODO: Set mode to streaming ?
|
||||
ret |= cambus_writeb2(sensor->slv_addr, MODE_SELECT, HIMAX_MODE_STREAMING);
|
||||
|
||||
// Delay 300 ms TODO is this required ?
|
||||
systick_sleep(300);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_reg(sensor_t *sensor, uint16_t reg_addr)
|
||||
{
|
||||
uint8_t reg_data;
|
||||
if (cambus_readb2(sensor->slv_addr, reg_addr, ®_data) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return reg_data;
|
||||
}
|
||||
|
||||
static int write_reg(sensor_t *sensor, uint16_t reg_addr, uint16_t reg_data)
|
||||
{
|
||||
return cambus_writeb2(sensor->slv_addr, reg_addr, reg_data);
|
||||
}
|
||||
|
||||
static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
|
||||
{
|
||||
int ret = 0;
|
||||
switch (pixformat) {
|
||||
case PIXFORMAT_GRAYSCALE:
|
||||
// assuming the sensor is in GS mode by default.
|
||||
break;
|
||||
// Won't support any other format for now.
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_framesize(sensor_t *sensor, framesize_t framesize)
|
||||
{
|
||||
int ret=0;
|
||||
uint16_t w = resolution[framesize][0];
|
||||
uint16_t h = resolution[framesize][1];
|
||||
|
||||
if ((w != 320) || (h != 240)) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_hmirror(sensor_t *sensor, int enable)
|
||||
{
|
||||
uint8_t reg;
|
||||
int ret = cambus_readb2(sensor->slv_addr, IMG_ORIENTATION, ®);
|
||||
ret |= cambus_writeb2(sensor->slv_addr, IMG_ORIENTATION, HIMAX_SET_HMIRROR(reg, enable)) ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_vflip(sensor_t *sensor, int enable)
|
||||
{
|
||||
uint8_t reg;
|
||||
int ret = cambus_readb2(sensor->slv_addr, IMG_ORIENTATION, ®);
|
||||
ret |= cambus_writeb2(sensor->slv_addr, IMG_ORIENTATION, HIMAX_SET_VMIRROR(reg, enable)) ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hm01b0_init(sensor_t *sensor)
|
||||
{
|
||||
// Initialize sensor structure.
|
||||
sensor->gs_bpp = 1;
|
||||
sensor->reset = reset;
|
||||
sensor->read_reg = read_reg;
|
||||
sensor->write_reg = write_reg;
|
||||
sensor->set_pixformat = set_pixformat;
|
||||
sensor->set_framesize = set_framesize;
|
||||
sensor->set_hmirror = set_hmirror;
|
||||
sensor->set_vflip = set_vflip;
|
||||
|
||||
// Set sensor flags
|
||||
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_VSYNC, 1);
|
||||
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_HSYNC, 1);
|
||||
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_PIXCK, 0);
|
||||
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_FSYNC, 1);
|
||||
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_JPEGE, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif //(OMV_SENSOR_HM01B0 == 1)
|
||||
15
src/omv/hm01b0.h
Normal file
15
src/omv/hm01b0.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* HM01B0 driver.
|
||||
*/
|
||||
#ifndef __HM01B0_H__
|
||||
#define __HM01B0_H__
|
||||
#include "sensor.h"
|
||||
int hm01b0_init(sensor_t *sensor);
|
||||
#endif // __HM01B0_H__
|
||||
116
src/omv/hm01b0_regs.h
Normal file
116
src/omv/hm01b0_regs.h
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
*
|
||||
* Copyright (c) 2013-2019 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
* Copyright (c) 2013-2019 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
*
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* HM01B0 register definitions.
|
||||
*/
|
||||
#ifndef __REG_REGS_H__
|
||||
#define __REG_REGS_H__
|
||||
|
||||
// Read only registers
|
||||
#define MODEL_ID_H 0x0000
|
||||
#define MODEL_ID_L 0x0001
|
||||
#define FRAME_COUNT 0x0005
|
||||
#define PIXEL_ORDER 0x0006
|
||||
// Sensor mode control
|
||||
#define MODE_SELECT 0x0100
|
||||
#define IMG_ORIENTATION 0x0101
|
||||
#define SW_RESET 0x0103
|
||||
#define GRP_PARAM_HOLD 0x0104
|
||||
// Sensor exposure gain control
|
||||
#define INTEGRATION_H 0x0202
|
||||
#define INTEGRATION_L 0x0203
|
||||
#define ANALOG_GAIN 0x0205
|
||||
#define DIGITAL_GAIN_H 0x020E
|
||||
#define DIGITAL_GAIN_L 0x020F
|
||||
// Frame timing control
|
||||
#define FRAME_LEN_LINES_H 0x0340
|
||||
#define FRAME_LEN_LINES_L 0x0341
|
||||
#define LINE_LEN_PCK_H 0x0342
|
||||
#define LINE_LEN_PCK_L 0x0343
|
||||
// Binning mode control
|
||||
#define READOUT_X 0x0383
|
||||
#define READOUT_Y 0x0387
|
||||
#define BINNING_MODE 0x0390
|
||||
// Test pattern control
|
||||
#define TEST_PATTERN_MODE 0x0601
|
||||
// Black level control
|
||||
#define BLC_CFG 0x1000
|
||||
#define BLC_TGT 0x1003
|
||||
#define BLI_EN 0x1006
|
||||
#define BLC2_TGT 0x1007
|
||||
// Sensor reserved
|
||||
#define DPC_CTRL 0x1008
|
||||
#define SINGLE_THR_HOT 0x100B
|
||||
#define SINGLE_THR_COLD 0x100C
|
||||
// VSYNC,HSYNC and pixel shift register
|
||||
#define VSYNC_HSYNC_PIXEL_SHIFT_EN 0x1012
|
||||
// Automatic exposure gain control
|
||||
#define AE_CTRL 0x2100
|
||||
#define AE_TARGET_MEAN 0x2101
|
||||
#define AE_MIN_MEAN 0x2102
|
||||
#define CONVERGE_IN_TH 0x2103
|
||||
#define CONVERGE_OUT_TH 0x2104
|
||||
#define MAX_INTG_H 0x2105
|
||||
#define MAX_INTG_L 0x2106
|
||||
#define MIN_INTG 0x2107
|
||||
#define MAX_AGAIN_FULL 0x2108
|
||||
#define MAX_AGAIN_BIN2 0x2109
|
||||
#define MIN_AGAIN 0x210A
|
||||
#define MAX_DGAIN 0x210B
|
||||
#define MIN_DGAIN 0x210C
|
||||
#define DAMPING_FACTOR 0x210D
|
||||
#define FS_CTRL 0x210E
|
||||
#define FS_60HZ_H 0x210F
|
||||
#define FS_60HZ_L 0x2110
|
||||
#define FS_50HZ_H 0x2111
|
||||
#define FS_50HZ_L 0x2112
|
||||
#define FS_HYST_TH 0x2113
|
||||
// Motion detection control
|
||||
#define MD_CTRL 0x2150
|
||||
#define I2C_CLEAR 0x2153
|
||||
#define WMEAN_DIFF_TH_H 0x2155
|
||||
#define WMEAN_DIFF_TH_M 0x2156
|
||||
#define WMEAN_DIFF_TH_L 0x2157
|
||||
#define MD_THH 0x2158
|
||||
#define MD_THM1 0x2159
|
||||
#define MD_THM2 0x215A
|
||||
#define MD_THL 0x215B
|
||||
// Sensor timing control
|
||||
#define QVGA_WIN_EN 0x3010
|
||||
#define SIX_BIT_MODE_EN 0x3011
|
||||
#define PMU_AUTOSLEEP_FRAMECNT 0x3020
|
||||
#define ADVANCE_VSYNC 0x3022
|
||||
#define ADVANCE_HSYNC 0x3023
|
||||
#define EARLY_GAIN 0x3035
|
||||
// IO and clock control
|
||||
#define BIT_CONTROL 0x3059
|
||||
#define OSC_CLK_DIV 0x3060
|
||||
#define ANA_Register_11 0x3061
|
||||
#define IO_DRIVE_STR 0x3062
|
||||
#define IO_DRIVE_STR2 0x3063
|
||||
#define ANA_Register_14 0x3064
|
||||
#define OUTPUT_PIN_STATUS_CONTROL 0x3065
|
||||
#define ANA_Register_17 0x3067
|
||||
#define PCLK_POLARITY 0x3068
|
||||
/*
|
||||
* Useful value of Himax registers
|
||||
*/
|
||||
#define HIMAX_RESET 0x01
|
||||
#define HIMAX_MODE_STANDBY 0x00
|
||||
#define HIMAX_MODE_STREAMING 0x01 // I2C triggered streaming enable
|
||||
#define HIMAX_MODE_STREAMING_NFRAMES 0x03 // Output N frames
|
||||
#define HIMAX_MODE_STREAMING_TRIG 0x05 // Hardware Trigger
|
||||
#define HIMAX_SET_HMIRROR(r, x) ((r&0xFE)|((x&1)<<0))
|
||||
#define HIMAX_SET_VMIRROR(r, x) ((r&0xFD)|((x&1)<<1))
|
||||
|
||||
#define PCLK_RISING_EDGE 0x00
|
||||
#define PCLK_FALLING_EDGE 0x01
|
||||
#define AE_CTRL_ENABLE 0x00
|
||||
#define AE_CTRL_DISABLE 0x01
|
||||
|
||||
#endif //__REG_REGS_H__
|
||||
@ -19,6 +19,7 @@
|
||||
#include "ov5640.h"
|
||||
#include "mt9v034.h"
|
||||
#include "lepton.h"
|
||||
#include "hm01b0.h"
|
||||
#include "sensor.h"
|
||||
#include "systick.h"
|
||||
#include "framebuffer.h"
|
||||
@ -329,6 +330,13 @@ int sensor_init()
|
||||
case OV5640_SLV_ADDR:
|
||||
cambus_readb2(sensor.slv_addr, OV5640_CHIP_ID, &sensor.chip_id);
|
||||
break;
|
||||
#if (OMV_SENSOR_HM01B0 == 1)
|
||||
case HM01B0_SLV_ADDR:
|
||||
cambus_readb2(sensor.slv_addr, HIMAX_CHIP_ID, &sensor.chip_id);
|
||||
// TODO fix when manf. ID is known.
|
||||
sensor.chip_id = HM01B0_ID;
|
||||
break;
|
||||
#endif //(OMV_SENSOR_HM01B0 == 1)
|
||||
default:
|
||||
return -3;
|
||||
break;
|
||||
@ -363,6 +371,11 @@ int sensor_init()
|
||||
case OV9650_ID:
|
||||
init_ret = ov9650_init(&sensor);
|
||||
break;
|
||||
#if (OMV_SENSOR_HM01B0 == 1)
|
||||
case HM01B0_ID:
|
||||
init_ret = hm01b0_init(&sensor);
|
||||
break;
|
||||
#endif //(OMV_SENSOR_HM01B0 == 1)
|
||||
default:
|
||||
return -3;
|
||||
break;
|
||||
|
||||
@ -19,10 +19,13 @@
|
||||
#define MT9V034_SLV_ADDR (0xB8)
|
||||
#define LEPTON_SLV_ADDR (0x54)
|
||||
#define OV5640_SLV_ADDR (0x78)
|
||||
#define HM01B0_SLV_ADDR (0x48)
|
||||
|
||||
// Chip ID registers.
|
||||
#define OV_CHIP_ID (0x0A)
|
||||
#define OV5640_CHIP_ID (0x300A)
|
||||
#define ON_CHIP_ID (0x00)
|
||||
#define HIMAX_CHIP_ID (0x0001)
|
||||
|
||||
#define OV9650_ID (0x96)
|
||||
#define OV2640_ID (0x26)
|
||||
@ -30,6 +33,7 @@
|
||||
#define OV5640_ID (0x56)
|
||||
#define MT9V034_ID (0x13)
|
||||
#define LEPTON_ID (0x54)
|
||||
#define HM01B0_ID (0xAA) // TODO fix this with valid manf. ID.
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_INVALID = 0,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user