Implement Himax motion detection with ioctls.

This commit is contained in:
iabdalkader 2021-02-21 22:19:47 +02:00
parent 935b58d0ae
commit d36cfb2313
4 changed files with 128 additions and 4 deletions

View File

@ -126,7 +126,11 @@ typedef enum {
IOCTL_LEPTON_SET_MEASUREMENT_MODE,
IOCTL_LEPTON_GET_MEASUREMENT_MODE,
IOCTL_LEPTON_SET_MEASUREMENT_RANGE,
IOCTL_LEPTON_GET_MEASUREMENT_RANGE
IOCTL_LEPTON_GET_MEASUREMENT_RANGE,
IOCTL_HIMAX_MD_ENABLE,
IOCTL_HIMAX_MD_CLEAR,
IOCTL_HIMAX_MD_WINDOW,
IOCTL_HIMAX_MD_THRESHOLD,
} ioctl_t;
#define SENSOR_HW_FLAGS_VSYNC (0) // vertical sync polarity.

View File

@ -759,6 +759,63 @@ static mp_obj_t py_sensor_ioctl(uint n_args, const mp_obj_t *args)
break;
}
#if (OMV_ENABLE_HM01B0 == 1)
case IOCTL_HIMAX_MD_ENABLE: {
if (n_args < 2 || sensor_ioctl(request, mp_obj_get_int(args[1])) != 0) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Sensor control failed!"));
}
break;
}
case IOCTL_HIMAX_MD_WINDOW: {
if (n_args < 2) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Sensor control failed!"));
}
int x, y, w, h;
mp_obj_t *array;
mp_uint_t array_len;
mp_obj_get_array(args[1], &array_len, &array);
if (array_len == 4) {
x = mp_obj_get_int(array[0]);
y = mp_obj_get_int(array[1]);
w = mp_obj_get_int(array[2]);
h = mp_obj_get_int(array[3]);
} else if (array_len == 2) {
w = mp_obj_get_int(array[0]);
h = mp_obj_get_int(array[1]);
x = 0;
y = 0;
} else {
mp_raise_msg(&mp_type_ValueError,
MP_ERROR_TEXT("The tuple/list must either be (x, y, w, h) or (w, h)"));
}
if (sensor_ioctl(request, x, y, w, h) != 0) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Sensor control failed!"));
}
break;
}
case IOCTL_HIMAX_MD_THRESHOLD: {
if (n_args < 2 || sensor_ioctl(request, mp_obj_get_int(args[1])) != 0) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Sensor control failed!"));
}
break;
}
case IOCTL_HIMAX_MD_CLEAR: {
if (sensor_ioctl(request) != 0) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Sensor control failed!"));
}
break;
}
#endif // (OMV_ENABLE_HM01B0 == 1)
default: {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Operation not supported!"));
break;
@ -945,7 +1002,12 @@ STATIC const mp_map_elem_t globals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_LEPTON_GET_MEASUREMENT_MODE), MP_OBJ_NEW_SMALL_INT(IOCTL_LEPTON_GET_MEASUREMENT_MODE)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_LEPTON_SET_MEASUREMENT_RANGE), MP_OBJ_NEW_SMALL_INT(IOCTL_LEPTON_SET_MEASUREMENT_RANGE)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_LEPTON_GET_MEASUREMENT_RANGE), MP_OBJ_NEW_SMALL_INT(IOCTL_LEPTON_GET_MEASUREMENT_RANGE)},
#if (OMV_ENABLE_HM01B0 == 1)
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_HIMAX_MD_ENABLE), MP_OBJ_NEW_SMALL_INT(IOCTL_HIMAX_MD_ENABLE)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_HIMAX_MD_WINDOW), MP_OBJ_NEW_SMALL_INT(IOCTL_HIMAX_MD_WINDOW)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_HIMAX_MD_THRESHOLD), MP_OBJ_NEW_SMALL_INT(IOCTL_HIMAX_MD_THRESHOLD)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_IOCTL_HIMAX_MD_CLEAR), MP_OBJ_NEW_SMALL_INT(IOCTL_HIMAX_MD_CLEAR)},
#endif
// Sensor functions
{ MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&py_sensor__init__obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&py_sensor_reset_obj },

View File

@ -60,7 +60,7 @@ static const uint16_t default_regs[][2] = {
{SINGLE_THR_HOT, 0x90}, // single hot pixel th
{SINGLE_THR_COLD, 0x40}, // single cold pixel th
{0x1012, 0x00}, // Sync. shift disable
{0x2000, 0x07},
{STATISTIC_CTRL, 0x07}, // AE stat en | MD LROI stat en | magic
{0x2003, 0x00},
{0x2004, 0x1C},
{0x2007, 0x00},
@ -99,7 +99,7 @@ static const uint16_t default_regs[][2] = {
{FS_50HZ_H, 0x00},
{FS_50HZ_L, 0x32},
{MD_CTRL, 0x30},
{MD_CTRL, 0x00},
{FRAME_LEN_LINES_H, HIMAX_FRAME_LENGTH_QVGA>>8},
{FRAME_LEN_LINES_L, HIMAX_FRAME_LENGTH_QVGA&0xFF},
{LINE_LEN_PCK_H, HIMAX_LINE_LEN_PCK_QVGA>>8},
@ -394,6 +394,53 @@ static int set_vflip(sensor_t *sensor, int enable)
return ret;
}
static int ioctl(sensor_t *sensor, int request, va_list ap)
{
int ret = 0;
switch (request) {
case IOCTL_HIMAX_MD_ENABLE: {
uint32_t enable = va_arg(ap, uint32_t);
ret = cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_CTRL, enable ? 1:0);
break;
}
case IOCTL_HIMAX_MD_WINDOW: {
uint32_t x1 = va_arg(ap, uint32_t);
uint32_t y1 = va_arg(ap, uint32_t);
uint32_t x2 = va_arg(ap, uint32_t) + x1;
uint32_t y2 = va_arg(ap, uint32_t) + y1;
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_X_START_H, (x1>>8));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_X_START_L, (x1&0xff));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_Y_START_H, (y1>>8));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_Y_START_L, (y1&0xff));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_X_END_H, (x2>>8));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_X_END_L, (x2&0xff));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_Y_END_H, (y2>>8));
ret |= cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_LROI_Y_END_L, (y2&0xff));
break;
}
case IOCTL_HIMAX_MD_THRESHOLD: {
uint32_t threshold = va_arg(ap, uint32_t);
ret = cambus_writeb2(&sensor->bus, sensor->slv_addr, MD_THL, threshold);
break;
}
case IOCTL_HIMAX_MD_CLEAR: {
ret = cambus_writeb2(&sensor->bus, sensor->slv_addr, I2C_CLEAR, 1);
break;
}
default: {
ret = -1;
break;
}
}
return ret;
}
int hm01b0_init(sensor_t *sensor)
{
// Initialize sensor structure.
@ -419,6 +466,7 @@ int hm01b0_init(sensor_t *sensor)
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;
sensor->ioctl = ioctl;
// Set sensor flags
SENSOR_HW_FLAGS_SET(sensor, SENSOR_HW_FLAGS_VSYNC, 0);

View File

@ -80,6 +80,16 @@
#define MD_THM1 0x2159
#define MD_THM2 0x215A
#define MD_THL 0x215B
#define STATISTIC_CTRL 0x2000
#define MD_LROI_X_START_H 0x2011
#define MD_LROI_X_START_L 0x2012
#define MD_LROI_Y_START_H 0x2013
#define MD_LROI_Y_START_L 0x2014
#define MD_LROI_X_END_H 0x2015
#define MD_LROI_X_END_L 0x2016
#define MD_LROI_Y_END_H 0x2017
#define MD_LROI_Y_END_L 0x2018
#define MD_INTERRUPT 0x2160
// Sensor timing control
#define QVGA_WIN_EN 0x3010
#define SIX_BIT_MODE_EN 0x3011