drivers/sensors: Add different event buffer sizes for genx320.

This commit is contained in:
Kwabena W. Agyeman 2025-07-03 18:39:17 -07:00
parent 3908807509
commit c231f66555
11 changed files with 165 additions and 24 deletions

View File

@ -88,7 +88,7 @@ typedef struct genx_state {
static genx_state_t genx = {};
static int set_active_mode(omv_csi_t *csi, genx_mode_t mode);
static int set_active_mode(omv_csi_t *csi, genx_mode_t mode, int framesize);
static int reset(omv_csi_t *csi) {
genx_state_t *genx = csi->priv;
@ -99,7 +99,7 @@ static int reset(omv_csi_t *csi) {
genx->event_time_us = 0;
// Set histogram mode by default.
if (set_active_mode(csi, OMV_CSI_GENX320_MODE_HISTO)) {
if (set_active_mode(csi, OMV_CSI_GENX320_MODE_HISTO, OMV_CSI_FRAMESIZE_320X320)) {
return OMV_CSI_ERROR_CSI_INIT_FAILED;
}
@ -153,7 +153,7 @@ static int set_framesize(omv_csi_t *csi, omv_csi_framesize_t framesize) {
if (genx->mode == OMV_CSI_GENX320_MODE_HISTO) {
return (framesize == OMV_CSI_FRAMESIZE_320X320) ? 0 : -1;
} else {
return (framesize == OMV_CSI_FRAMESIZE_128X64) ? 0 : -1;
return (framesize == OMV_CSI_FRAMESIZE_CUSTOM) ? 0 : -1;
}
}
@ -420,7 +420,7 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) {
int mode = va_arg(ap, int);
if (mode == OMV_CSI_GENX320_MODE_HISTO) {
if ((ret = set_active_mode(csi, OMV_CSI_GENX320_MODE_HISTO))) {
if ((ret = set_active_mode(csi, OMV_CSI_GENX320_MODE_HISTO, OMV_CSI_FRAMESIZE_320X320))) {
break;
}
@ -432,17 +432,25 @@ static int ioctl(omv_csi_t *csi, int request, va_list ap) {
break;
}
} else if (mode == OMV_CSI_GENX320_MODE_EVENT) {
if ((ret = set_active_mode(csi, OMV_CSI_GENX320_MODE_EVENT))) {
size_t ndarray_size = va_arg(ap, size_t);
if (ndarray_size < 1024 || ndarray_size > 65536 || (ndarray_size & (ndarray_size - 1))) {
ret = -1;
break;
}
resolution[OMV_CSI_FRAMESIZE_CUSTOM][0] = 1024;
resolution[OMV_CSI_FRAMESIZE_CUSTOM][1] = ndarray_size >> 8;
if ((ret = set_active_mode(csi, OMV_CSI_GENX320_MODE_EVENT, OMV_CSI_FRAMESIZE_CUSTOM))) {
break;
}
// 1 byte per pixel.
if ((ret = omv_csi_set_pixformat(csi, PIXFORMAT_GRAYSCALE))) {
break;
}
// 128*64 bytes / 4 bytes per event = 2048 events.
if ((ret = omv_csi_set_framesize(csi, OMV_CSI_FRAMESIZE_128X64))) {
if ((ret = omv_csi_set_framesize(csi, OMV_CSI_FRAMESIZE_CUSTOM))) {
break;
}
} else {
@ -607,7 +615,7 @@ static int post_process_event(omv_csi_t *csi, image_t *image, uint32_t flags) {
return valid_count;
}
static int set_active_mode(omv_csi_t *csi, genx_mode_t mode) {
static int set_active_mode(omv_csi_t *csi, genx_mode_t mode, int framesize) {
genx_state_t *genx = csi->priv;
if (genx->issd) {
@ -638,8 +646,8 @@ static int set_active_mode(omv_csi_t *csi, genx_mode_t mode) {
}
// Configure Packet and Frame sizes
uint32_t packet_width = (mode == OMV_CSI_GENX320_MODE_EVENT) ? 128 : ACTIVE_SENSOR_WIDTH;
uint32_t packet_height = (mode == OMV_CSI_GENX320_MODE_EVENT) ? 64 : ACTIVE_SENSOR_HEIGHT;
uint32_t packet_width = resolution[framesize][0];
uint32_t packet_height = resolution[framesize][1];
uint32_t packet_hsync = (mode == OMV_CSI_GENX320_MODE_EVENT) ?
EVENT_HSYNC_CLOCK_CYCLES : HISTO_HSYNC_CLOCK_CYCLES;

View File

@ -1196,6 +1196,8 @@ static mp_obj_t py_csi_ioctl(size_t n_args, const mp_obj_t *args) {
case OMV_CSI_IOCTL_GENX320_SET_MODE: {
if (n_args == 1) {
error = omv_csi_ioctl(self->csi, request, mp_obj_get_int(args[0]));
} else if (n_args == 2) {
error = omv_csi_ioctl(self->csi, request, mp_obj_get_int(args[0]), mp_obj_get_int(args[1]));
}
break;
}
@ -1207,11 +1209,15 @@ static mp_obj_t py_csi_ioctl(size_t n_args, const mp_obj_t *args) {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Expected a ndarray with dtype uint16"));
}
uint32_t expected_len = resolution[self->csi->framesize][0] *
(resolution[self->csi->framesize][1] / sizeof(uint32_t));
if (!(ndarray_is_dense(array) && (array->ndim == 2) &&
(array->shape[ULAB_MAX_DIMS - 2] == 2048) &&
(array->shape[ULAB_MAX_DIMS - 2] == expected_len) &&
(array->shape[ULAB_MAX_DIMS - 1] == EC_EVENT_SIZE))) {
mp_raise_msg_varg(&mp_type_ValueError,
MP_ERROR_TEXT("Expected a dense ndarray with shape (2048, %d)"), EC_EVENT_SIZE);
MP_ERROR_TEXT("Expected a dense ndarray with shape (%d, %d)"),
expected_len, EC_EVENT_SIZE);
}
error = omv_csi_ioctl(self->csi, request, array->array);

View File

@ -16,6 +16,7 @@ img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -28,7 +29,7 @@ events = np.zeros((2048, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()

View File

@ -20,6 +20,7 @@ img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -32,7 +33,7 @@ events = np.zeros((2048, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()

View File

@ -0,0 +1,56 @@
# This work is licensed under the MIT license.
# Copyright (c) 2013-2025 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# This example shows off using the genx320 event camera from Prophesee
# using event streaming mode with a very deep event buffer for capturing events.
import csi
import image
import time
# https://micropython-ulab.readthedocs.io/en/latest/index.html
from ulab import numpy as np
# Surface to draw the histogram image on.
img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
# [2] Milliseconds timestamp
# [3] Microseconds timestamp
# [4] X coordinate 0 to 319 for GENX320
# [5] Y coordinate 0 to 319 for GENX320
events = np.zeros((32768, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
while True:
clock.tick()
# Reads up to 32768 events from the camera.
# Returns the number of valid events (0-32768) or a negative error code.
# Note that old events in the buffer are not cleared to save CPU time.
event_count = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
# Render events into a histogram image.
# If clear=True, the image is reset to "brightness" before drawing.
# For each PIX_ON_EVENT, add "contrast" to the bin value;
# for each PIX_OFF_EVENT, subtract it and clamp to [0, 255].
# If clear=False, histogram accumulates over multiple calls.
img.draw_event_histogram(events[:event_count], clear=True, brightness=128, contrast=16)
# Push the image to the jpeg buffer for the IDE to pull and display.
# The IDE pulls frames off the camera at a much lower rate than the
# onboard camera frame rate printed below.
img.flush()
print(event_count, clock.fps())

View File

@ -0,0 +1,64 @@
# This work is licensed under the MIT license.
# Copyright (c) 2013-2025 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# This example shows off using the genx320 event camera from Prophesee
# using event streaming mode with a very deep event buffer for capturing events.
#
# Adds filtering of events based on the event type (PIX_ON_EVENT or PIX_OFF_EVENT).
import csi
import image
import time
# https://micropython-ulab.readthedocs.io/en/latest/index.html
from ulab import numpy as np
TARGET_EVENT_TYPE = csi.PIX_ON_EVENT # Change to PIX_OFF_EVENT to filter low events.
# Surface to draw the histogram image on.
img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
# [2] Milliseconds timestamp
# [3] Microseconds timestamp
# [4] X coordinate 0 to 319 for GENX320
# [5] Y coordinate 0 to 319 for GENX320
events = np.zeros((32768, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
while True:
clock.tick()
# Reads up to 32768 events from the camera.
# Returns the number of valid events (0-32768) or a negative error code.
# Note that old events in the buffer are not cleared to save CPU time.
event_count = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
events_slice = events[:event_count]
indices = np.nonzero(events_slice[:, 0] == TARGET_EVENT_TYPE)[0]
if len(indices):
target_events = np.take(events_slice, indices, axis=0)
# Render events into a histogram image.
# If clear=True, the image is reset to "brightness" before drawing.
# For each PIX_ON_EVENT, add "contrast" to the bin value;
# for each PIX_OFF_EVENT, subtract it and clamp to [0, 255].
# If clear=False, histogram accumulates over multiple calls.
img.draw_event_histogram(target_events, clear=True, brightness=128, contrast=16)
# Push the image to the jpeg buffer for the IDE to pull and display.
# The IDE pulls frames off the camera at a much lower rate than the
# onboard camera frame rate printed below.
img.flush()
print(len(target_events), clock.fps())

View File

@ -20,6 +20,7 @@ img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -32,7 +33,7 @@ events = np.zeros((2048, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()

View File

@ -14,6 +14,7 @@ from ulab import numpy as np
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -26,7 +27,7 @@ events = np.zeros((2048, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
t = time.ticks_us()

View File

@ -18,6 +18,7 @@ TARGET_EVENT_TYPE = csi.PIX_ON_EVENT # Change to PIX_OFF_EVENT to filter low ev
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -30,7 +31,7 @@ events = np.zeros((2048, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
t = time.ticks_us()

View File

@ -11,13 +11,14 @@ import time
# https://micropython-ulab.readthedocs.io/en/latest/index.html
from ulab import numpy as np
EXPOSURE_FRAMES = 10
EXPOSURE_FRAMES = 30
# Surface to draw the histogram image on.
img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -25,12 +26,12 @@ img = image.Image(320, 320, image.GRAYSCALE)
# [3] Microseconds timestamp
# [4] X coordinate 0 to 319 for GENX320
# [5] Y coordinate 0 to 319 for GENX320
events = np.zeros((2048, 6), dtype=np.uint16)
events = np.zeros((32768, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
i = 0

View File

@ -15,13 +15,14 @@ from ulab import numpy as np
TARGET_EVENT_TYPE = csi.PIX_ON_EVENT # Change to PIX_OFF_EVENT to filter low events.
EXPOSURE_FRAMES = 10
EXPOSURE_FRAMES = 30
# Surface to draw the histogram image on.
img = image.Image(320, 320, image.GRAYSCALE)
# Stores camera events
# Shape: (EVT_res, 6) where EVT_res is the event resolution
# EVT_res: must be a power of two between 1024 and 65536.
# Columns:
# [0] Event type
# [1] Seconds timestamp
@ -34,7 +35,7 @@ events = np.zeros((32768, 6), dtype=np.uint16)
# Initialize the sensor.
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT)
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
i = 0
@ -59,7 +60,7 @@ while True:
# For each PIX_ON_EVENT, add "contrast" to the bin value;
# for each PIX_OFF_EVENT, subtract it and clamp to [0, 255].
# If clear=False, histogram accumulates over multiple calls.
img.draw_event_histogram(target_events, clear=c, brightness=128, contrast=64)
img.draw_event_histogram(target_events, clear=c, brightness=128, contrast=16)
# Push the image to the jpeg buffer for the IDE to pull and display.
# The IDE pulls frames off the camera at a much lower rate than the