Add HIMAX HM01B0 driver.

This commit is contained in:
iabdalkader 2020-02-08 21:25:59 +02:00
parent 85b207ce3f
commit abd977c60f
7 changed files with 380 additions and 0 deletions

View File

@ -187,6 +187,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
ov5640.o \ ov5640.o \
mt9v034.o \ mt9v034.o \
lepton.o \ lepton.o \
hm01b0.o \
sensor.o \ sensor.o \
stm32fxxx_hal_msp.o \ stm32fxxx_hal_msp.o \
soft_i2c.o \ soft_i2c.o \
@ -504,6 +505,7 @@ UVC_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/, \
ov5640.o \ ov5640.o \
mt9v034.o \ mt9v034.o \
lepton.o \ lepton.o \
hm01b0.o \
sensor.o \ sensor.o \
stm32fxxx_hal_msp.o \ stm32fxxx_hal_msp.o \
soft_i2c.o \ soft_i2c.o \

View File

@ -25,6 +25,7 @@ SRCS += $(addprefix , \
ov5640.c \ ov5640.c \
mt9v034.c \ mt9v034.c \
lepton.c \ lepton.c \
hm01b0.c \
sensor.c \ sensor.c \
stm32fxxx_hal_msp.c \ stm32fxxx_hal_msp.c \
soft_i2c.c \ soft_i2c.c \

229
src/omv/hm01b0.c Normal file
View 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, &reg) != 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, &reg_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, &reg);
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, &reg);
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
View 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
View 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__

View File

@ -19,6 +19,7 @@
#include "ov5640.h" #include "ov5640.h"
#include "mt9v034.h" #include "mt9v034.h"
#include "lepton.h" #include "lepton.h"
#include "hm01b0.h"
#include "sensor.h" #include "sensor.h"
#include "systick.h" #include "systick.h"
#include "framebuffer.h" #include "framebuffer.h"
@ -329,6 +330,13 @@ int sensor_init()
case OV5640_SLV_ADDR: case OV5640_SLV_ADDR:
cambus_readb2(sensor.slv_addr, OV5640_CHIP_ID, &sensor.chip_id); cambus_readb2(sensor.slv_addr, OV5640_CHIP_ID, &sensor.chip_id);
break; 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: default:
return -3; return -3;
break; break;
@ -363,6 +371,11 @@ int sensor_init()
case OV9650_ID: case OV9650_ID:
init_ret = ov9650_init(&sensor); init_ret = ov9650_init(&sensor);
break; break;
#if (OMV_SENSOR_HM01B0 == 1)
case HM01B0_ID:
init_ret = hm01b0_init(&sensor);
break;
#endif //(OMV_SENSOR_HM01B0 == 1)
default: default:
return -3; return -3;
break; break;

View File

@ -19,10 +19,13 @@
#define MT9V034_SLV_ADDR (0xB8) #define MT9V034_SLV_ADDR (0xB8)
#define LEPTON_SLV_ADDR (0x54) #define LEPTON_SLV_ADDR (0x54)
#define OV5640_SLV_ADDR (0x78) #define OV5640_SLV_ADDR (0x78)
#define HM01B0_SLV_ADDR (0x48)
// Chip ID registers.
#define OV_CHIP_ID (0x0A) #define OV_CHIP_ID (0x0A)
#define OV5640_CHIP_ID (0x300A) #define OV5640_CHIP_ID (0x300A)
#define ON_CHIP_ID (0x00) #define ON_CHIP_ID (0x00)
#define HIMAX_CHIP_ID (0x0001)
#define OV9650_ID (0x96) #define OV9650_ID (0x96)
#define OV2640_ID (0x26) #define OV2640_ID (0x26)
@ -30,6 +33,7 @@
#define OV5640_ID (0x56) #define OV5640_ID (0x56)
#define MT9V034_ID (0x13) #define MT9V034_ID (0x13)
#define LEPTON_ID (0x54) #define LEPTON_ID (0x54)
#define HM01B0_ID (0xAA) // TODO fix this with valid manf. ID.
typedef enum { typedef enum {
PIXFORMAT_INVALID = 0, PIXFORMAT_INVALID = 0,