Skip to content

Commit

Permalink
Merge branch 'dev_xel' into 'dev'
Browse files Browse the repository at this point in the history
Add support for sensor autodetect.

See merge request maix_sw/k230_canmv!261
  • Loading branch information
kendryte747 committed Jun 24, 2024
2 parents 4a171c3 + 4e9c18f commit 45af351
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 88 deletions.
8 changes: 5 additions & 3 deletions k230_sdk_overlay/src/big/mpp/include/comm/k_vicap_comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,11 @@ typedef struct
} k_vicap_mcm_chn_vf_info;

typedef struct {
k_u32 adapt_id[16];
k_u32 adapt_len;
}k_vicap_adapt_id;
k_u32 csi_num;
k_u32 width;
k_u32 height;
k_u32 fps;
} k_vicap_probe_config;

#define K_ERR_VICAP_INVALID_DEVID K_DEF_ERR(K_ID_VICAP, K_ERR_LEVEL_ERROR, K_ERR_INVALID_DEVID)
#define K_ERR_VICAP_INVALID_CHNID K_DEF_ERR(K_ID_VICAP, K_ERR_LEVEL_ERROR, K_ERR_INVALID_CHNID)
Expand Down
3 changes: 1 addition & 2 deletions k230_sdk_overlay/src/big/mpp/userapps/api/mpi_sensor_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,8 +454,7 @@ k_s32 kd_mpi_sensor_otpdata_set(k_s32 fd, void *ota_data);

k_s32 kd_mpi_sensor_mirror_set(k_s32 fd, k_vicap_mirror_mode mirror);


k_s32 kd_mpi_sensor_adapt_get(k_vicap_adapt_id *csi0_adapt_id, k_vicap_adapt_id *csi1_adapt_id, k_vicap_adapt_id *csi2_adapt_id);
k_s32 kd_mpi_sensor_adapt_get(k_vicap_probe_config *config, k_vicap_sensor_info *info);

/** @} */ /** <!-- ==== SENSOR End ==== */

Expand Down
156 changes: 114 additions & 42 deletions k230_sdk_overlay/src/big/mpp/userapps/src/sensor/mpi_sensor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1435,81 +1435,153 @@ k_s32 kd_mpi_sensor_mirror_set(k_s32 fd, k_vicap_mirror_mode mirror)
return ret;
}

/*
Sensor Name: Sensor1, FPS: 60, Width: 1920, Height: 1080
Sensor Name: Sensor2, FPS: 60, Width: 1280, Height: 720
Sensor Name: Sensor3, FPS: 30, Width: 1920, Height: 1080
Sensor Name: Sensor4, FPS: 30, Width: 1280, Height: 720
*/
static int compare_sensor_info(const void *a, const void *b) {
k_vicap_sensor_info *sensorA = (k_vicap_sensor_info *)a;
k_vicap_sensor_info *sensorB = (k_vicap_sensor_info *)b;

// Compare fps
if (sensorA->fps != sensorB->fps) {
return sensorB->fps - sensorA->fps;
}
// If fps is the same, compare width
if (sensorA->width != sensorB->width) {
return sensorB->width - sensorA->width;
}
// If width is the same, compare height
return sensorB->height - sensorA->height;
}

k_s32 kd_mpi_sensor_adapt_get(k_vicap_adapt_id *csi0_adapt_id, k_vicap_adapt_id *csi1_adapt_id, k_vicap_adapt_id *csi2_adapt_id)
k_s32 kd_mpi_sensor_adapt_get(k_vicap_probe_config *config, k_vicap_sensor_info *info)
{
k_s32 i = 0, j = 0;
#define MAX_SENSOR_COUNT (16)

k_s32 ret = 0;
k_s32 sensor_fd = -1;
k_u32 chip_id;
k_vicap_sensor_info sensor_info;
k_sensor_mode mode;

csi0_adapt_id->adapt_len = 0;
csi1_adapt_id->adapt_len = 0;
csi2_adapt_id->adapt_len = 0;
k_u32 sensor_info_count = 0;
k_vicap_sensor_info sensor_info, *p_sensor_info = NULL;
k_vicap_sensor_info sensor_info_list[MAX_SENSOR_COUNT];

for (i = 0; i != SENSOR_TYPE_MAX; i++)
if (((void *)0 == config) || ((void *)0 == info))
{
memset(&sensor_info, 0, sizeof(k_vicap_sensor_info));
memset(&mode, 0, sizeof(k_sensor_mode));
return 2;
}
sensor_info_count = 0;
memset(info, 0, sizeof(k_vicap_sensor_info));
memset(&sensor_info_list[0], 0, sizeof(sensor_info_list));

for (int sensor_idx = 0; sensor_idx != SENSOR_TYPE_MAX; sensor_idx++)
{
if (sensor_info_count >= MAX_SENSOR_COUNT)
{
printf("kd_mpi_sensor_adapt_get, too may ids\n");
break;
}

memset(&mode, 0, sizeof(k_sensor_mode));
memset(&sensor_info, 0, sizeof(k_vicap_sensor_info));

ret = kd_mpi_vicap_get_sensor_info((k_vicap_sensor_type)sensor_idx, &sensor_info);
if (ret)
{
printf("kd_mpi_vicap_adapt_config, the sensor type not supported! index is %d \n", sensor_idx);
continue;
}

ret = kd_mpi_vicap_get_sensor_info((k_vicap_sensor_type)i , &sensor_info);
if (ret) {
printf("kd_mpi_vicap_adapt_config, the sensor type not supported! i is %d \n", i);
if (config->csi_num != sensor_info.csi_num)
{
continue;
}
}

// open sensor
// open sensor
sensor_fd = kd_mpi_sensor_open(sensor_info.sensor_name);
if (sensor_fd < 0) {
pr_err("%s, sensor open failed.\n", __func__);
if (sensor_fd < 0)
{
printf("%s, sensor open failed.\n", __func__);
continue;
}

mode.sensor_type = sensor_info.sensor_type;
ret = kd_mpi_sensor_mode_get(sensor_fd, &mode);
if (ret) {
pr_err("%s, sensor mode get failed. i is %d \n", __func__, i);
if (ret)
{
printf("%s, sensor mode get failed. i is %d \n", __func__, sensor_idx);
continue;
}

// check sensor need mclk
for(k_s32 idx = 0; idx < SENSOR_MCLK_MAX - 1; idx++)
for (k_s32 idx = 0; idx < SENSOR_MCLK_MAX - 1; idx++)
{
if(mode.mclk_setting[idx].mclk_setting_en)
if (mode.mclk_setting[idx].mclk_setting_en)
{
ret = kd_mpi_vicap_sensor_set_mclk(mode.mclk_setting[idx].setting);
}
}

// ret = kd_mpi_sensor_power_set(sensor_fd, K_TRUE);
ret = kd_mpi_sensor_id_get(sensor_fd, &chip_id);
if(ret == 0)
if (ret == 0)
{
// chip ok
switch(sensor_info.csi_num)
{
case VICAP_CSI0 :
csi0_adapt_id->adapt_id[csi0_adapt_id->adapt_len] = i;
csi0_adapt_id->adapt_len = csi0_adapt_id->adapt_len + 1;
break;
case VICAP_CSI1 :
csi1_adapt_id->adapt_id[csi1_adapt_id->adapt_len] = i;
csi1_adapt_id->adapt_len = csi1_adapt_id->adapt_len + 1;
break;
case VICAP_CSI2 :
csi2_adapt_id->adapt_id[csi2_adapt_id->adapt_len] = i;
csi2_adapt_id->adapt_len = csi2_adapt_id->adapt_len + 1;
break;
default :
printf("csi num err \n");
break;
}
memcpy(&sensor_info_list[sensor_info_count], &sensor_info, sizeof(k_vicap_sensor_info));
sensor_info_count++;
}

kd_mpi_sensor_close(sensor_fd);
}

return 0;
}
if (sensor_info_count)
{
qsort(&sensor_info_list[0], sensor_info_count, sizeof(k_vicap_sensor_info), compare_sensor_info);

/* first find wanted fps */
if(0x00 != config->fps)
{
for (int i = 0; i < sensor_info_count; i++)
{
p_sensor_info = &sensor_info_list[i];

if ((config->width == p_sensor_info->width) && (config->height == p_sensor_info->height) && (config->fps == p_sensor_info->fps))
{
memcpy(info, p_sensor_info, sizeof(k_vicap_sensor_info));
return 0;
}
}
}

/* find same resolution */
for (int i = 0; i < sensor_info_count; i++)
{
p_sensor_info = &sensor_info_list[i];

if ((config->width == p_sensor_info->width) && (config->height == p_sensor_info->height) /* && (config->fps == p_sensor_info->fps) */)
{
memcpy(info, p_sensor_info, sizeof(k_vicap_sensor_info));
return 0;
}
}

/* find a bigger resolution */
for (int i = 0; i < sensor_info_count; i++)
{
p_sensor_info = &sensor_info_list[i];

if ((config->width <= p_sensor_info->width) && (config->height <= p_sensor_info->height) /* && (config->fps == p_sensor_info->fps) */)
{
memcpy(info, p_sensor_info, sizeof(k_vicap_sensor_info));
return 0;
}
}
}

return 1;

#undef MAX_SENSOR_COUNT
}
54 changes: 17 additions & 37 deletions micropython/port/builtin_py/media/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
# Don't edit it arbitrarily!!!

class Sensor:
OV5647 = const(200)

RGB565 = PIXEL_FORMAT_RGB_565
RGB888 = PIXEL_FORMAT_RGB_888
RGBP888 = PIXEL_FORMAT_RGB_888_PLANAR
Expand Down Expand Up @@ -134,35 +132,6 @@ def _run_mcm_device(cls):

sensor._is_started = True

@staticmethod
def _get_the_senrsor_type(brd, _type, id):
if brd == "k230_canmv":
if _type == Sensor.OV5647:
if id == CAM_DEV_ID_0:
return OV_OV5647_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR, 0
elif id == CAM_DEV_ID_1:
return OV_OV5647_MIPI_CSI1_1920X1080_30FPS_10BIT_LINEAR, 0
else:
return OV_OV5647_MIPI_CSI2_1920X1080_30FPS_10BIT_LINEAR, 0
else:
raise NotImplementedError(f"Unsupport Sensor type {_type}")
elif brd == "k230_canmv_01studio":
if _type == Sensor.OV5647:
if id == CAM_DEV_ID_0:
return OV_OV5647_MIPI_CSI0_1920X1080_30FPS_10BIT_LINEAR, 3
elif id == CAM_DEV_ID_1:
return OV_OV5647_MIPI_CSI1_1920X1080_30FPS_10BIT_LINEAR, 3
else:
return OV_OV5647_MIPI_CSI2_1920X1080_30FPS_10BIT_LINEAR, 3
else:
raise NotImplementedError(f"Unsupport Sensor type {_type}")
elif brd == "k230d_canmv":
raise NotImplementedError("TODO")
elif brd == "k230_evb":
raise NotImplementedError("TODO")
else:
raise AssertionError(f"invaild board type, please ask for support.")

# id
# type
# force
Expand All @@ -171,7 +140,6 @@ def __init__(self, **kwargs):
self._dft_output_buff_num = 6

dft_sensor_id = CAM_DEV_ID_0
dft_sensor_type = Sensor.OV5647

brd = os.uname()[-1]
if brd == "k230d_canmv":
Expand All @@ -188,11 +156,23 @@ def __init__(self, **kwargs):
if not force and Sensor._devs[self._dev_id] is not None:
raise OSError(f"sensor({self._dev_id}) is already inited.")

mirror = 0
self._type = kwargs.get('type', dft_sensor_type)
arg_type = kwargs.get('type', None)
if arg_type is not None:
self._type = arg_type
else:
info = k_vicap_sensor_info()
cfg = k_vicap_probe_config()
cfg.csi = self._dev_id + 1 # convert to csi num
cfg.fps = kwargs.get('fps', 30)
cfg.width = kwargs.get('width', 1920)
cfg.height = kwargs.get('height', 1080)

ret = kd_mpi_sensor_adapt_get(cfg, info)
if 0 != ret:
raise RuntimeError(f"Can not found sensor on {self._dev_id}")

if self._type >= Sensor.OV5647:
self._type, mirror = Sensor._get_the_senrsor_type(brd, self._type, self._dev_id)
self._type = info.type
print(f"use sensor {info.type}, output {info.width}x{info.height}@{info.fps}")

if (self._type > SENSOR_TYPE_MAX - 1):
raise AssertionError(f"invaild sensor type {self._type}, should < {SENSOR_TYPE_MAX - 1}")
Expand All @@ -206,7 +186,7 @@ def __init__(self, **kwargs):
self._dev_attr.mode = VICAP_WORK_ONLINE_MODE
# self._dev_attr.mode = VICAP_WORK_OFFLINE_MODE
self._dev_attr.input_type = VICAP_INPUT_TYPE_SENSOR
self._dev_attr.mirror = mirror
self._dev_attr.mirror = 0

self._is_started = False

Expand Down
23 changes: 19 additions & 4 deletions micropython/port/builtin_py/mpp/vicap_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def k_vicap_isp_pipe_ctrl_parse(s, kwargs):
s.data = kwargs.get("data", 0)

k_vicap_sensor_info_desc = {
"sensor_name": 0 | uctypes.UINT64,
"name": 0 | uctypes.UINT64,
"width": 8 | uctypes.UINT16,
"height": 10 | uctypes.UINT16,
"csi_num": 12 | uctypes.UINT32,
Expand All @@ -110,11 +110,12 @@ def k_vicap_isp_pipe_ctrl_parse(s, kwargs):
"flash_mode": 40 | uctypes.UINT32,
"first_frame": 44 | uctypes.UINT32,
"glitch_filter": 48 | uctypes.UINT16,
"sensor_type": 52 | uctypes.UINT32,
"fps": 50 | uctypes.UINT16,
"type": 52 | uctypes.UINT32,
}

def k_vicap_sensor_info_parse(s, kwargs):
s.sensor_name = kwargs.get("sensor_name", 0)
s.name = kwargs.get("name", 0)
s.width = kwargs.get("width", 0)
s.height = kwargs.get("height", 0)
s.csi_num = kwargs.get("csi_num", 0)
Expand All @@ -127,7 +128,8 @@ def k_vicap_sensor_info_parse(s, kwargs):
s.flash_mode = kwargs.get("flash_mode", 0)
s.first_frame = kwargs.get("first_frame", 0)
s.glitch_filter = kwargs.get("glitch_filter", 0)
s.sensor_type = kwargs.get("sensor_type", 0)
s.fps = kwargs.get("fps", 0)
s.type = kwargs.get("type", 0)

k_vicap_chn_attr_desc = {
"out_win": (0, k_vicap_window_desc),
Expand Down Expand Up @@ -324,3 +326,16 @@ def k_vicap_chn_set_info_parse(s, kwargs):
s.pixel_format = kwargs.get("pixel_format", 0)
s.buf_size = kwargs.get("buf_size", 0)
s.alignment = kwargs.get("alignment", 0)

k_vicap_probe_config_desc = {
"csi": 0 | uctypes.UINT32,
"width": 4 | uctypes.UINT32,
"height": 8 | uctypes.UINT32,
"fps": 12 | uctypes.UINT32,
}

def k_vicap_probe_config_parse(s, kwargs):
s.csi = kwargs.get("csi", 0)
s.width = kwargs.get("width", 0)
s.height = kwargs.get("height", 0)
s.fps = kwargs.get("fps", 0)
7 changes: 7 additions & 0 deletions micropython/port/builtin_py/mpp/vicap_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,10 @@ def k_vicap_chn_set_info(**kwargs):
s = uctypes.struct(uctypes.addressof(buf), vicap_def.k_vicap_chn_set_info_desc, layout)
vicap_def.k_vicap_chn_set_info_parse(s, kwargs)
return s

def k_vicap_probe_config(**kwargs):
layout = uctypes.NATIVE
buf = bytearray(uctypes.sizeof(vicap_def.k_vicap_probe_config_desc, layout))
s = uctypes.struct(uctypes.addressof(buf), vicap_def.k_vicap_probe_config_desc, layout)
vicap_def.k_vicap_probe_config_parse(s, kwargs)
return s
2 changes: 2 additions & 0 deletions micropython/port/builtin_py/mpp_binding/vicap_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
#include <errno.h>
#include "py/runtime.h"
#include "py/obj.h"
#include "k_vicap_comm.h"
#include "mpi_vicap_api.h"
#include "mpi_sensor_api.h"

#define DEF_FUNC_ADD(x) { MP_ROM_QSTR(MP_QSTR_##x), MP_ROM_PTR(&x##_obj) },

Expand Down
1 change: 1 addition & 0 deletions micropython/port/builtin_py/mpp_binding/vicap_func_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ DEF_INT_FUNC_INT_STRUCTPTR_INT(kd_mpi_vicap_set_vi_drop_frame, k_vicap_drop_fram
DEF_INT_FUNC_INT_INT(kd_mpi_vicap_set_database_parse_mode)
DEF_INT_FUNC_INT(kd_mpi_vicap_tpg_enable)
DEF_INT_FUNC_INT_ARRAY_INT(kd_mpi_vicap_load_image, void)
DEF_INT_FUNC_STRUCTPTR_STRUCTPTR(kd_mpi_sensor_adapt_get, k_vicap_probe_config, k_vicap_sensor_info)

0 comments on commit 45af351

Please sign in to comment.