Merge pull request #1386 from openmv/sensor_errors

Add sensor error codes.
This commit is contained in:
Ibrahim Abd Elkader 2021-07-01 20:52:08 +02:00 committed by GitHub
commit 6b821aeac9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 366 additions and 175 deletions

View File

@ -149,15 +149,39 @@ typedef enum {
IOCTL_HIMAX_OSC_ENABLE, IOCTL_HIMAX_OSC_ENABLE,
} ioctl_t; } ioctl_t;
#define SENSOR_HW_FLAGS_VSYNC (0) // vertical sync polarity. typedef enum {
#define SENSOR_HW_FLAGS_HSYNC (1) // horizontal sync polarity. SENSOR_ERROR_NO_ERROR = 0,
#define SENSOR_HW_FLAGS_PIXCK (2) // pixel clock edge. SENSOR_ERROR_CTL_FAILED = -1,
#define SENSOR_HW_FLAGS_FSYNC (3) // hardware frame sync. SENSOR_ERROR_CTL_UNSUPPORTED = -2,
#define SENSOR_HW_FLAGS_JPEGE (4) // hardware JPEG encoder. SENSOR_ERROR_ISC_UNDETECTED = -3,
#define SENSOR_HW_FLAGS_RGB565_REV (5) // byte reverse rgb565. SENSOR_ERROR_ISC_UNSUPPORTED = -4,
#define SENSOR_HW_FLAGS_GET(s, x) ((s)->hw_flags & (1<<x)) SENSOR_ERROR_ISC_INIT_FAILED = -5,
#define SENSOR_HW_FLAGS_SET(s, x, v) ((s)->hw_flags |= (v<<x)) SENSOR_ERROR_TIM_INIT_FAILED = -6,
#define SENSOR_HW_FLAGS_CLR(s, x) ((s)->hw_flags &= ~(1<<x)) SENSOR_ERROR_DMA_INIT_FAILED = -7,
SENSOR_ERROR_DCMI_INIT_FAILED = -8,
SENSOR_ERROR_IO_ERROR = -9,
SENSOR_ERROR_CAPTURE_FAILED = -10,
SENSOR_ERROR_CAPTURE_TIMEOUT = -11,
SENSOR_ERROR_INVALID_FRAMESIZE = -12,
SENSOR_ERROR_INVALID_PIXFORMAT = -13,
SENSOR_ERROR_INVALID_WINDOW = -14,
SENSOR_ERROR_INVALID_FRAMERATE = -15,
SENSOR_ERROR_INVALID_ARGUMENT = -16,
SENSOR_ERROR_PIXFORMAT_UNSUPPORTED = -17,
SENSOR_ERROR_FRAMEBUFFER_ERROR = -18,
SENSOR_ERROR_FRAMEBUFFER_OVERFLOW = -19,
SENSOR_ERROR_JPEG_OVERFLOW = -20,
} sensor_error_t;
#define SENSOR_HW_FLAGS_VSYNC (0) // vertical sync polarity.
#define SENSOR_HW_FLAGS_HSYNC (1) // horizontal sync polarity.
#define SENSOR_HW_FLAGS_PIXCK (2) // pixel clock edge.
#define SENSOR_HW_FLAGS_FSYNC (3) // hardware frame sync.
#define SENSOR_HW_FLAGS_JPEGE (4) // hardware JPEG encoder.
#define SENSOR_HW_FLAGS_RGB565_REV (5) // byte reverse rgb565.
#define SENSOR_HW_FLAGS_GET(s, x) ((s)->hw_flags & (1<<x))
#define SENSOR_HW_FLAGS_SET(s, x, v) ((s)->hw_flags |= (v<<x))
#define SENSOR_HW_FLAGS_CLR(s, x) ((s)->hw_flags &= ~(1<<x))
typedef void (*vsync_cb_t)(uint32_t vsync); typedef void (*vsync_cb_t)(uint32_t vsync);
typedef void (*frame_cb_t)(); typedef void (*frame_cb_t)();
@ -385,4 +409,6 @@ int sensor_auto_crop_framebuffer();
// Default snapshot function. // Default snapshot function.
int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags); int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags);
// Convert sensor error codes to strings.
const char *sensor_strerror(int error);
#endif /* __SENSOR_H__ */ #endif /* __SENSOR_H__ */

View File

@ -97,16 +97,17 @@ __weak int sensor_init()
{ {
// Reset the sesnor state // Reset the sesnor state
memset(&sensor, 0, sizeof(sensor_t)); memset(&sensor, 0, sizeof(sensor_t));
return -1; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
__weak int sensor_abort() __weak int sensor_abort()
{ {
return -1; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
__weak int sensor_reset() __weak int sensor_reset()
{ {
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
// Reset the sensor state // Reset the sensor state
@ -146,15 +147,22 @@ __weak int sensor_reset()
mp_hal_delay_ms(10); mp_hal_delay_ms(10);
DCMI_RESET_HIGH(); DCMI_RESET_HIGH();
} }
mp_hal_delay_ms(20); mp_hal_delay_ms(20);
// Check if the control is supported.
if (sensor.reset == NULL) {
return SENSOR_ERROR_CTL_UNSUPPORTED;
}
// Call sensor-specific reset function // Call sensor-specific reset function
if (sensor.reset(&sensor) != 0) { if (sensor.reset(&sensor) != 0) {
return -1; return SENSOR_ERROR_CTL_FAILED;
} }
// Reset framebuffers // Reset framebuffers
framebuffer_reset_buffers(); framebuffer_reset_buffers();
return 0; return 0;
} }
@ -216,7 +224,7 @@ int sensor_probe_init()
sensor.slv_addr = cambus_scan(&sensor.bus); sensor.slv_addr = cambus_scan(&sensor.bus);
#ifndef OMV_ENABLE_NONI2CIS #ifndef OMV_ENABLE_NONI2CIS
if (sensor.slv_addr == 0) { if (sensor.slv_addr == 0) {
return -2; return SENSOR_ERROR_ISC_UNDETECTED;
} }
#endif #endif
} }
@ -281,12 +289,11 @@ int sensor_probe_init()
sensor.reset_pol = ACTIVE_LOW; sensor.reset_pol = ACTIVE_LOW;
break; break;
} }
// No sensors detected. return SENSOR_ERROR_ISC_UNDETECTED;
return -2;
#endif #endif
default: default:
return -3; return SENSOR_ERROR_ISC_UNSUPPORTED;
break; break;
} }
@ -294,7 +301,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_OV2640 == 1) #if (OMV_ENABLE_OV2640 == 1)
case OV2640_ID: case OV2640_ID:
if (sensor_set_xclk_frequency(OV2640_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(OV2640_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = ov2640_init(&sensor); init_ret = ov2640_init(&sensor);
break; break;
@ -303,7 +310,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_OV5640 == 1) #if (OMV_ENABLE_OV5640 == 1)
case OV5640_ID: case OV5640_ID:
if (sensor_set_xclk_frequency(OV5640_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(OV5640_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = ov5640_init(&sensor); init_ret = ov5640_init(&sensor);
break; break;
@ -312,7 +319,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_OV7670 == 1) #if (OMV_ENABLE_OV7670 == 1)
case OV7670_ID: case OV7670_ID:
if (sensor_set_xclk_frequency(OV7670_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(OV7670_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = ov7670_init(&sensor); init_ret = ov7670_init(&sensor);
break; break;
@ -321,7 +328,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_OV7690 == 1) #if (OMV_ENABLE_OV7690 == 1)
case OV7690_ID: case OV7690_ID:
if (sensor_set_xclk_frequency(OV7690_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(OV7690_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = ov7690_init(&sensor); init_ret = ov7690_init(&sensor);
break; break;
@ -342,7 +349,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_MT9V034 == 1) #if (OMV_ENABLE_MT9V034 == 1)
case MT9V034_ID: case MT9V034_ID:
if (sensor_set_xclk_frequency(MT9V034_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(MT9V034_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = mt9v034_init(&sensor); init_ret = mt9v034_init(&sensor);
break; break;
@ -351,7 +358,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_MT9M114 == 1) #if (OMV_ENABLE_MT9M114 == 1)
case MT9M114_ID: case MT9M114_ID:
if (sensor_set_xclk_frequency(MT9M114_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(MT9M114_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = mt9m114_init(&sensor); init_ret = mt9m114_init(&sensor);
break; break;
@ -360,7 +367,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_LEPTON == 1) #if (OMV_ENABLE_LEPTON == 1)
case LEPTON_ID: case LEPTON_ID:
if (sensor_set_xclk_frequency(LEPTON_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(LEPTON_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = lepton_init(&sensor); init_ret = lepton_init(&sensor);
break; break;
@ -375,7 +382,7 @@ int sensor_probe_init()
#if (OMV_ENABLE_GC2145 == 1) #if (OMV_ENABLE_GC2145 == 1)
case GC2145_ID: case GC2145_ID:
if (sensor_set_xclk_frequency(GC2145_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(GC2145_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = gc2145_init(&sensor); init_ret = gc2145_init(&sensor);
break; break;
@ -384,20 +391,20 @@ int sensor_probe_init()
#if (OMV_ENABLE_PAJ6100 == 1) #if (OMV_ENABLE_PAJ6100 == 1)
case PAJ6100_ID: case PAJ6100_ID:
if (sensor_set_xclk_frequency(PAJ6100_XCLK_FREQ) != 0) { if (sensor_set_xclk_frequency(PAJ6100_XCLK_FREQ) != 0) {
return -3; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
init_ret = paj6100_init(&sensor); init_ret = paj6100_init(&sensor);
break; break;
#endif // (OMV_ENABLE_PAJ6100 == 1) #endif // (OMV_ENABLE_PAJ6100 == 1)
default: default:
return -3; return SENSOR_ERROR_ISC_UNSUPPORTED;
break; break;
} }
if (init_ret != 0 ) { if (init_ret != 0 ) {
// Sensor init failed. // Sensor init failed.
return -4; return SENSOR_ERROR_ISC_INIT_FAILED;
} }
return 0; return 0;
@ -410,12 +417,12 @@ __weak int sensor_get_id()
__weak uint32_t sensor_get_xclk_frequency() __weak uint32_t sensor_get_xclk_frequency()
{ {
return 0; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
__weak int sensor_set_xclk_frequency(uint32_t frequency) __weak int sensor_set_xclk_frequency(uint32_t frequency)
{ {
return -1; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
__weak bool sensor_is_detected() __weak bool sensor_is_detected()
@ -425,19 +432,27 @@ __weak bool sensor_is_detected()
__weak int sensor_sleep(int enable) __weak int sensor_sleep(int enable)
{ {
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
if (sensor.sleep == NULL // Check if the control is supported.
|| sensor.sleep(&sensor, enable) != 0) { if (sensor.sleep == NULL) {
// Operation not supported return SENSOR_ERROR_CTL_UNSUPPORTED;
return -1;
} }
// Call the sensor specific function.
if (sensor.sleep(&sensor, enable) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_shutdown(int enable) __weak int sensor_shutdown(int enable)
{ {
int ret = 0; int ret = 0;
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
if (enable) { if (enable) {
@ -455,31 +470,44 @@ __weak int sensor_shutdown(int enable)
} }
mp_hal_delay_ms(10); mp_hal_delay_ms(10);
return ret; return ret;
} }
__weak int sensor_read_reg(uint16_t reg_addr) __weak int sensor_read_reg(uint16_t reg_addr)
{ {
// Check if the control is supported.
if (sensor.read_reg == NULL) { if (sensor.read_reg == NULL) {
// Operation not supported return SENSOR_ERROR_CTL_UNSUPPORTED;
return -1;
} }
return sensor.read_reg(&sensor, reg_addr);
// Call the sensor specific function.
if (sensor.read_reg(&sensor, reg_addr) == -1) {
return SENSOR_ERROR_IO_ERROR;
}
return 0;
} }
__weak int sensor_write_reg(uint16_t reg_addr, uint16_t reg_data) __weak int sensor_write_reg(uint16_t reg_addr, uint16_t reg_data)
{ {
// Check if the control is supported.
if (sensor.write_reg == NULL) { if (sensor.write_reg == NULL) {
// Operation not supported return SENSOR_ERROR_CTL_UNSUPPORTED;
return -1;
} }
return sensor.write_reg(&sensor, reg_addr, reg_data);
// Call the sensor specific function.
if (sensor.write_reg(&sensor, reg_addr, reg_data) == -1) {
return SENSOR_ERROR_IO_ERROR;
}
return 0;
} }
__weak int sensor_set_pixformat(pixformat_t pixformat) __weak int sensor_set_pixformat(pixformat_t pixformat)
{ {
// Check if the value has changed.
if (sensor.pixformat == pixformat) { if (sensor.pixformat == pixformat) {
// No change
return 0; return 0;
} }
@ -491,25 +519,29 @@ __weak int sensor_set_pixformat(pixformat_t pixformat)
&& (pixformat == PIXFORMAT_RGB565) && (pixformat == PIXFORMAT_RGB565)
&& (MAIN_FB()->u * MAIN_FB()->v * 2 > size) && (MAIN_FB()->u * MAIN_FB()->v * 2 > size)
&& (MAIN_FB()->u * MAIN_FB()->v * 1 <= size)) { && (MAIN_FB()->u * MAIN_FB()->v * 1 <= size)) {
// No change
return 0; return 0;
} }
// Cropping and transposing (and thus auto rotation) don't work in JPEG mode. // Cropping and transposing (and thus auto rotation) don't work in JPEG mode.
if ((pixformat == PIXFORMAT_JPEG) if ((pixformat == PIXFORMAT_JPEG)
&& (sensor_get_cropped() || sensor.transpose || sensor.auto_rotation)) { && (sensor_get_cropped() || sensor.transpose || sensor.auto_rotation)) {
return -1; return SENSOR_ERROR_PIXFORMAT_UNSUPPORTED;
} }
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
// Flush previous frame. // Flush previous frame.
framebuffer_update_jpeg_buffer(); framebuffer_update_jpeg_buffer();
if (sensor.set_pixformat == NULL // Check if the control is supported.
|| sensor.set_pixformat(&sensor, pixformat) != 0) { if (sensor.set_pixformat == NULL) {
// Operation not supported return SENSOR_ERROR_CTL_UNSUPPORTED;
return -1; }
// Call the sensor specific function.
if (sensor.set_pixformat(&sensor, pixformat) != 0) {
return SENSOR_ERROR_CTL_FAILED;
} }
mp_hal_delay_ms(100); // wait for the camera to settle mp_hal_delay_ms(100); // wait for the camera to settle
@ -534,16 +566,19 @@ __weak int sensor_set_framesize(framesize_t framesize)
return 0; return 0;
} }
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
// Flush previous frame. // Flush previous frame.
framebuffer_update_jpeg_buffer(); framebuffer_update_jpeg_buffer();
// Call the sensor specific function // Call the sensor specific function
if (sensor.set_framesize == NULL if (sensor.set_framesize == NULL) {
|| sensor.set_framesize(&sensor, framesize) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
// Operation not supported }
return -1;
if (sensor.set_framesize(&sensor, framesize) != 0) {
return SENSOR_ERROR_CTL_FAILED;
} }
mp_hal_delay_ms(100); // wait for the camera to settle mp_hal_delay_ms(100); // wait for the camera to settle
@ -574,15 +609,16 @@ __weak int sensor_set_framerate(int framerate)
} }
if (framerate < 0) { if (framerate < 0) {
return -1; return SENSOR_ERROR_INVALID_ARGUMENT;
} }
// Call the sensor specific function (does not fail if function is not set) // Call the sensor specific function (does not fail if function is not set)
if (sensor.set_framerate != NULL) { if (sensor.set_framerate != NULL) {
if (sensor.set_framerate(&sensor, framerate) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
// Operation not supported }
return -1;
} if (sensor.set_framerate(&sensor, framerate) != 0) {
return SENSOR_ERROR_CTL_FAILED;
} }
// Set framerate // Set framerate
@ -634,16 +670,17 @@ __weak uint32_t sensor_get_dst_bpp()
__weak int sensor_set_windowing(int x, int y, int w, int h) __weak int sensor_set_windowing(int x, int y, int w, int h)
{ {
// Check if the value has changed.
if ((MAIN_FB()->x == x) && (MAIN_FB()->y == y) && if ((MAIN_FB()->x == x) && (MAIN_FB()->y == y) &&
(MAIN_FB()->u == w) && (MAIN_FB()->v == h)) { (MAIN_FB()->u == w) && (MAIN_FB()->v == h)) {
// No change
return 0; return 0;
} }
if (sensor.pixformat == PIXFORMAT_JPEG) { if (sensor.pixformat == PIXFORMAT_JPEG) {
return -1; return SENSOR_ERROR_PIXFORMAT_UNSUPPORTED;
} }
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
// Flush previous frame. // Flush previous frame.
@ -665,151 +702,218 @@ __weak int sensor_set_windowing(int x, int y, int w, int h)
__weak int sensor_set_contrast(int level) __weak int sensor_set_contrast(int level)
{ {
if (sensor.set_contrast != NULL) { // Check if the control is supported.
return sensor.set_contrast(&sensor, level); if (sensor.set_contrast == NULL) {
return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
return -1;
// Call the sensor specific function.
if (sensor.set_contrast(&sensor, level) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0;
} }
__weak int sensor_set_brightness(int level) __weak int sensor_set_brightness(int level)
{ {
if (sensor.set_brightness != NULL) { // Check if the control is supported.
return sensor.set_brightness(&sensor, level); if (sensor.set_brightness == NULL) {
return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
return -1;
// Call the sensor specific function.
if (sensor.set_brightness(&sensor, level) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0;
} }
__weak int sensor_set_saturation(int level) __weak int sensor_set_saturation(int level)
{ {
if (sensor.set_saturation != NULL) { // Check if the control is supported.
return sensor.set_saturation(&sensor, level); if (sensor.set_saturation == NULL) {
return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
return -1;
// Call the sensor specific function.
if (sensor.set_saturation(&sensor, level) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0;
} }
__weak int sensor_set_gainceiling(gainceiling_t gainceiling) __weak int sensor_set_gainceiling(gainceiling_t gainceiling)
{ {
// Check if the value has changed.
if (sensor.gainceiling == gainceiling) { if (sensor.gainceiling == gainceiling) {
/* no change */
return 0; return 0;
} }
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_gainceiling == NULL if (sensor.set_gainceiling == NULL) {
|| sensor.set_gainceiling(&sensor, gainceiling) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_gainceiling(&sensor, gainceiling) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
// Set the new control value.
sensor.gainceiling = gainceiling; sensor.gainceiling = gainceiling;
return 0; return 0;
} }
__weak int sensor_set_quality(int qs) __weak int sensor_set_quality(int qs)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_quality == NULL if (sensor.set_quality == NULL) {
|| sensor.set_quality(&sensor, qs) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_quality(&sensor, qs) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_set_colorbar(int enable) __weak int sensor_set_colorbar(int enable)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_colorbar == NULL if (sensor.set_colorbar == NULL) {
|| sensor.set_colorbar(&sensor, enable) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_colorbar(&sensor, enable) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_set_auto_gain(int enable, float gain_db, float gain_db_ceiling) __weak int sensor_set_auto_gain(int enable, float gain_db, float gain_db_ceiling)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_auto_gain == NULL if (sensor.set_auto_gain == NULL) {
|| sensor.set_auto_gain(&sensor, enable, gain_db, gain_db_ceiling) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_auto_gain(&sensor, enable, gain_db, gain_db_ceiling) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_get_gain_db(float *gain_db) __weak int sensor_get_gain_db(float *gain_db)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.get_gain_db == NULL if (sensor.get_gain_db == NULL) {
|| sensor.get_gain_db(&sensor, gain_db) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.get_gain_db(&sensor, gain_db) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_set_auto_exposure(int enable, int exposure_us) __weak int sensor_set_auto_exposure(int enable, int exposure_us)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_auto_exposure == NULL if (sensor.set_auto_exposure == NULL) {
|| sensor.set_auto_exposure(&sensor, enable, exposure_us) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_auto_exposure(&sensor, enable, exposure_us) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_get_exposure_us(int *exposure_us) __weak int sensor_get_exposure_us(int *exposure_us)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.get_exposure_us == NULL if (sensor.get_exposure_us == NULL) {
|| sensor.get_exposure_us(&sensor, exposure_us) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.get_exposure_us(&sensor, exposure_us) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_set_auto_whitebal(int enable, float r_gain_db, float g_gain_db, float b_gain_db) __weak int sensor_set_auto_whitebal(int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_auto_whitebal == NULL if (sensor.set_auto_whitebal == NULL) {
|| sensor.set_auto_whitebal(&sensor, enable, r_gain_db, g_gain_db, b_gain_db) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_auto_whitebal(&sensor, enable, r_gain_db, g_gain_db, b_gain_db) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_get_rgb_gain_db(float *r_gain_db, float *g_gain_db, float *b_gain_db) __weak int sensor_get_rgb_gain_db(float *r_gain_db, float *g_gain_db, float *b_gain_db)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.get_rgb_gain_db == NULL if (sensor.get_rgb_gain_db == NULL) {
|| sensor.get_rgb_gain_db(&sensor, r_gain_db, g_gain_db, b_gain_db) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.get_rgb_gain_db(&sensor, r_gain_db, g_gain_db, b_gain_db) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
return 0; return 0;
} }
__weak int sensor_set_hmirror(int enable) __weak int sensor_set_hmirror(int enable)
{ {
// Check if the value has changed.
if (sensor.hmirror == ((bool) enable)) { if (sensor.hmirror == ((bool) enable)) {
/* no change */
return 0; return 0;
} }
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_hmirror == NULL if (sensor.set_hmirror == NULL) {
|| sensor.set_hmirror(&sensor, enable) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_hmirror(&sensor, enable) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
// Set the new control value.
sensor.hmirror = enable; sensor.hmirror = enable;
mp_hal_delay_ms(100); // wait for the camera to settle
// Wait for the camera to settle
mp_hal_delay_ms(100);
return 0; return 0;
} }
@ -820,21 +924,30 @@ __weak bool sensor_get_hmirror()
__weak int sensor_set_vflip(int enable) __weak int sensor_set_vflip(int enable)
{ {
// Check if the value has changed.
if (sensor.vflip == ((bool) enable)) { if (sensor.vflip == ((bool) enable)) {
/* no change */
return 0; return 0;
} }
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_vflip == NULL if (sensor.set_vflip == NULL) {
|| sensor.set_vflip(&sensor, enable) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_vflip(&sensor, enable) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
// Set the new control value.
sensor.vflip = enable; sensor.vflip = enable;
mp_hal_delay_ms(100); // wait for the camera to settle
// Wait for the camera to settle
mp_hal_delay_ms(100);
return 0; return 0;
} }
@ -845,18 +958,21 @@ __weak bool sensor_get_vflip()
__weak int sensor_set_transpose(bool enable) __weak int sensor_set_transpose(bool enable)
{ {
// Check if the value has changed.
if (sensor.transpose == enable) { if (sensor.transpose == enable) {
/* no change */
return 0; return 0;
} }
if (sensor.pixformat == PIXFORMAT_JPEG) { // Disable any ongoing frame capture.
return -1;
}
sensor_abort(); sensor_abort();
if (sensor.pixformat == PIXFORMAT_JPEG) {
return SENSOR_ERROR_PIXFORMAT_UNSUPPORTED;
}
// Set the new control value.
sensor.transpose = enable; sensor.transpose = enable;
return 0; return 0;
} }
@ -867,17 +983,20 @@ __weak bool sensor_get_transpose()
__weak int sensor_set_auto_rotation(bool enable) __weak int sensor_set_auto_rotation(bool enable)
{ {
// Check if the value has changed.
if (sensor.auto_rotation == enable) { if (sensor.auto_rotation == enable) {
/* no change */
return 0; return 0;
} }
if (sensor.pixformat == PIXFORMAT_JPEG) { // Disable any ongoing frame capture.
return -1;
}
sensor_abort(); sensor_abort();
// Operation not supported on JPEG images.
if (sensor.pixformat == PIXFORMAT_JPEG) {
return SENSOR_ERROR_PIXFORMAT_UNSUPPORTED;
}
// Set the new control value.
sensor.auto_rotation = enable; sensor.auto_rotation = enable;
return 0; return 0;
} }
@ -889,6 +1008,7 @@ __weak bool sensor_get_auto_rotation()
__weak int sensor_set_framebuffers(int count) __weak int sensor_set_framebuffers(int count)
{ {
// Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
// Flush previous frame. // Flush previous frame.
@ -899,29 +1019,37 @@ __weak int sensor_set_framebuffers(int count)
__weak int sensor_set_special_effect(sde_t sde) __weak int sensor_set_special_effect(sde_t sde)
{ {
// Check if the value has changed.
if (sensor.sde == sde) { if (sensor.sde == sde) {
/* no change */
return 0; return 0;
} }
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_special_effect == NULL if (sensor.set_special_effect == NULL) {
|| sensor.set_special_effect(&sensor, sde) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */
return -1;
} }
// Call the sensor specific function.
if (sensor.set_special_effect(&sensor, sde) != 0) {
return SENSOR_ERROR_CTL_FAILED;
}
// Set the new control value.
sensor.sde = sde; sensor.sde = sde;
return 0; return 0;
} }
__weak int sensor_set_lens_correction(int enable, int radi, int coef) __weak int sensor_set_lens_correction(int enable, int radi, int coef)
{ {
/* call the sensor specific function */ // Check if the control is supported.
if (sensor.set_lens_correction == NULL if (sensor.set_lens_correction == NULL) {
|| sensor.set_lens_correction(&sensor, enable, radi, coef) != 0) { return SENSOR_ERROR_CTL_UNSUPPORTED;
/* operation not supported */ }
return -1;
// Call the sensor specific function.
if (sensor.set_lens_correction(&sensor, enable, radi, coef) != 0) {
return SENSOR_ERROR_CTL_FAILED;
} }
return 0; return 0;
@ -929,19 +1057,21 @@ __weak int sensor_set_lens_correction(int enable, int radi, int coef)
__weak int sensor_ioctl(int request, ... /* arg */) __weak int sensor_ioctl(int request, ... /* arg */)
{ {
int ret = -1; // Disable any ongoing frame capture.
sensor_abort(); sensor_abort();
if (sensor.ioctl != NULL) { // Check if the control is supported.
va_list ap; if (sensor.ioctl == NULL) {
va_start(ap, request); return SENSOR_ERROR_CTL_UNSUPPORTED;
/* call the sensor specific function */
ret = sensor.ioctl(&sensor, request, ap);
va_end(ap);
} }
return ret; va_list ap;
va_start(ap, request);
// Call the sensor specific function.
int ret = sensor.ioctl(&sensor, request, ap);
va_end(ap);
return ((ret != 0) ? SENSOR_ERROR_CTL_FAILED : 0);
} }
__weak int sensor_set_vsync_callback(vsync_cb_t vsync_cb) __weak int sensor_set_vsync_callback(vsync_cb_t vsync_cb)
@ -1063,6 +1193,41 @@ __weak int sensor_auto_crop_framebuffer()
return 0; return 0;
} }
mp_rom_error_text_t sensor_strerror(int error)
{
static mp_rom_error_text_t sensor_errors[] = {
MP_ERROR_TEXT("No error."),
MP_ERROR_TEXT("Sensor control failed."),
MP_ERROR_TEXT("The requested operation is not supported by the image sensor."),
MP_ERROR_TEXT("Failed to detect the image sensor or image sensor is detached."),
MP_ERROR_TEXT("The detected image sensor is not supported."),
MP_ERROR_TEXT("Failed to initialize the image sensor."),
MP_ERROR_TEXT("Failed to initialize the image sensor clock."),
MP_ERROR_TEXT("Failed to initialize the image sensor DMA."),
MP_ERROR_TEXT("Failed to initialize the image sensor DCMI."),
MP_ERROR_TEXT("An low level I/O error has occurred."),
MP_ERROR_TEXT("Frame capture has failed."),
MP_ERROR_TEXT("Frame capture has timed out."),
MP_ERROR_TEXT("Frame size is not supported or is not set."),
MP_ERROR_TEXT("Pixel format is not supported or is not set."),
MP_ERROR_TEXT("Window is not supported or is not set."),
MP_ERROR_TEXT("An invalid argument is used."),
MP_ERROR_TEXT("The requested operation is not supported on the current pixel format."),
MP_ERROR_TEXT("Frame buffer error."),
MP_ERROR_TEXT("Frame buffer overflow, try reducing the frame size."),
MP_ERROR_TEXT("JPEG frame buffer overflow."),
};
// Sensor errors are negative.
error = ((error < 0) ? (error * -1) : error);
if (error > (sizeof(sensor_errors) / sizeof(sensor_errors[0]))) {
return "Unknown error.";
} else {
return sensor_errors[error];
}
}
__weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags) __weak int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
{ {
return -1; return -1;

View File

@ -69,7 +69,7 @@ int sensor_init()
// Configure the sensor external clock (XCLK). // Configure the sensor external clock (XCLK).
if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) { if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) {
// Failed to initialize the sensor clock. // Failed to initialize the sensor clock.
return -1; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
// Detect and initialize the image sensor. // Detect and initialize the image sensor.
@ -82,7 +82,7 @@ int sensor_init()
// Configure the DCMI interface. // Configure the DCMI interface.
if (sensor_dcmi_config(PIXFORMAT_INVALID) != 0){ if (sensor_dcmi_config(PIXFORMAT_INVALID) != 0){
// DCMI config failed // DCMI config failed
return -6; return SENSOR_ERROR_DCMI_INIT_FAILED;
} }
// Clear fb_enabled flag // Clear fb_enabled flag
@ -162,7 +162,7 @@ int sensor_set_xclk_frequency(uint32_t frequency)
int sensor_set_windowing(int x, int y, int w, int h) int sensor_set_windowing(int x, int y, int w, int h)
{ {
return -1; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
// This is the default snapshot function, which can be replaced in sensor_init functions. // This is the default snapshot function, which can be replaced in sensor_init functions.
@ -179,14 +179,14 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
} }
if (sensor_check_framebuffer_size() != 0) { if (sensor_check_framebuffer_size() != 0) {
return -1; return SENSOR_ERROR_FRAMEBUFFER_OVERFLOW;
} }
framebuffer_free_current_buffer(); framebuffer_free_current_buffer();
vbuffer_t *buffer = framebuffer_get_tail(FB_NO_FLAGS); vbuffer_t *buffer = framebuffer_get_tail(FB_NO_FLAGS);
if (!buffer) { if (!buffer) {
return -1; return SENSOR_ERROR_FRAMEBUFFER_ERROR;
} }
uint8_t *b = buffer->data; uint8_t *b = buffer->data;

View File

@ -95,7 +95,7 @@ int sensor_init()
// Configure the sensor external clock (XCLK). // Configure the sensor external clock (XCLK).
if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) { if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) {
// Failed to initialize the sensor clock. // Failed to initialize the sensor clock.
return -1; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
// Detect and initialize the image sensor. // Detect and initialize the image sensor.
@ -183,7 +183,7 @@ int sensor_set_xclk_frequency(uint32_t frequency)
int sensor_set_windowing(int x, int y, int w, int h) int sensor_set_windowing(int x, int y, int w, int h)
{ {
return -1; return SENSOR_ERROR_CTL_UNSUPPORTED;
} }
static void dma_irq_handler() static void dma_irq_handler()
@ -214,7 +214,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
framebuffer_update_jpeg_buffer(); framebuffer_update_jpeg_buffer();
if (sensor_check_framebuffer_size() != 0) { if (sensor_check_framebuffer_size() != 0) {
return -1; return SENSOR_ERROR_FRAMEBUFFER_OVERFLOW;
} }
// Free the current FB head. // Free the current FB head.
@ -230,7 +230,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
MAIN_FB()->bpp = 2; MAIN_FB()->bpp = 2;
break; break;
default: default:
return -1; return SENSOR_ERROR_INVALID_PIXFORMAT;
} }
vbuffer_t *buffer = framebuffer_get_head(FB_NO_FLAGS); vbuffer_t *buffer = framebuffer_get_head(FB_NO_FLAGS);
@ -240,7 +240,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
if (buffer == NULL && !dma_channel_is_busy(DCMI_DMA_CHANNEL)) { if (buffer == NULL && !dma_channel_is_busy(DCMI_DMA_CHANNEL)) {
buffer = framebuffer_get_tail(FB_PEEK); buffer = framebuffer_get_tail(FB_PEEK);
if (buffer == NULL) { if (buffer == NULL) {
return -1; return SENSOR_ERROR_FRAMEBUFFER_ERROR;
} }
// Configure the DMA on the first frame, for later frames only the write is changed. // Configure the DMA on the first frame, for later frames only the write is changed.
@ -262,7 +262,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
buffer = framebuffer_get_head(FB_NO_FLAGS); buffer = framebuffer_get_head(FB_NO_FLAGS);
if ((mp_hal_ticks_ms() - ticks) > 3000) { if ((mp_hal_ticks_ms() - ticks) > 3000) {
sensor_abort(); sensor_abort();
return -1; return SENSOR_ERROR_CAPTURE_TIMEOUT;
} }
} }

View File

@ -130,7 +130,7 @@ int sensor_init()
// Configure the sensor external clock (XCLK). // Configure the sensor external clock (XCLK).
if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) { if (sensor_set_xclk_frequency(OMV_XCLK_FREQUENCY) != 0) {
// Failed to initialize the sensor clock. // Failed to initialize the sensor clock.
return -1; return SENSOR_ERROR_TIM_INIT_FAILED;
} }
// Detect and initialize the image sensor. // Detect and initialize the image sensor.
@ -142,13 +142,13 @@ int sensor_init()
// Configure the DCMI DMA Stream // Configure the DCMI DMA Stream
if (sensor_dma_config() != 0) { if (sensor_dma_config() != 0) {
// DMA problem // DMA problem
return -5; return SENSOR_ERROR_DMA_INIT_FAILED;
} }
// Configure the DCMI interface. // Configure the DCMI interface.
if (sensor_dcmi_config(PIXFORMAT_INVALID) != 0){ if (sensor_dcmi_config(PIXFORMAT_INVALID) != 0){
// DCMI config failed // DCMI config failed
return -6; return SENSOR_ERROR_DCMI_INIT_FAILED;
} }
// Clear fb_enabled flag // Clear fb_enabled flag
@ -751,7 +751,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
// Error out if the pixformat is not set. // Error out if the pixformat is not set.
if (!bytes_per_pixel) { if (!bytes_per_pixel) {
return -1; return SENSOR_ERROR_INVALID_PIXFORMAT;
} }
uint32_t x_crop = get_dcmi_hw_crop(bytes_per_pixel); uint32_t x_crop = get_dcmi_hw_crop(bytes_per_pixel);
@ -770,14 +770,14 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
|| (dma_line_width_bytes > (OMV_LINE_BUF_SIZE / 2)) || (dma_line_width_bytes > (OMV_LINE_BUF_SIZE / 2))
|| (!length) || (!length)
|| (length % DMA_LENGTH_ALIGNMENT)) { || (length % DMA_LENGTH_ALIGNMENT)) {
return -2; return SENSOR_ERROR_INVALID_FRAMESIZE;
} }
// Get the destination buffer address. // Get the destination buffer address.
vbuffer_t *buffer = framebuffer_get_tail(FB_PEEK); vbuffer_t *buffer = framebuffer_get_tail(FB_PEEK);
if ((sensor->pixformat == PIXFORMAT_JPEG) && (sensor->chip_id == OV2640_ID) && (!buffer)) { if ((sensor->pixformat == PIXFORMAT_JPEG) && (sensor->chip_id == OV2640_ID) && (!buffer)) {
return -3; return SENSOR_ERROR_FRAMEBUFFER_ERROR;
} }
#if (OMV_ENABLE_SENSOR_MDMA == 1) #if (OMV_ENABLE_SENSOR_MDMA == 1)
@ -901,7 +901,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
} }
#endif #endif
return -4; return SENSOR_ERROR_CAPTURE_TIMEOUT;
} }
} }
@ -921,7 +921,7 @@ int sensor_snapshot(sensor_t *sensor, image_t *image, uint32_t flags)
// The JPEG in the frame buffer is actually invalid. // The JPEG in the frame buffer is actually invalid.
if (buffer->jpeg_buffer_overflow) { if (buffer->jpeg_buffer_overflow) {
return -5; return SENSOR_ERROR_JPEG_OVERFLOW;
} }
// Prepare the frame buffer w/h/bpp values given the image type. // Prepare the frame buffer w/h/bpp values given the image type.