mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #2725 from openmv/refactor_csi
ports/all: Refactor CSI drivers.
This commit is contained in:
commit
f3f7b0aa06
@ -598,7 +598,7 @@ __weak int omv_csi_get_id() {
|
||||
return csi.chip_id;
|
||||
}
|
||||
|
||||
__weak uint32_t omv_csi_get_xclk_frequency() {
|
||||
__weak uint32_t omv_csi_get_clk_frequency() {
|
||||
return OMV_CSI_ERROR_CTL_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +390,7 @@ int omv_csi_reset();
|
||||
int omv_csi_get_id();
|
||||
|
||||
// Returns the xclk freq in hz.
|
||||
uint32_t omv_csi_get_xclk_frequency();
|
||||
uint32_t omv_csi_get_clk_frequency();
|
||||
|
||||
// Returns the xclk freq in hz.
|
||||
int omv_csi_set_clk_frequency(uint32_t frequency);
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
#define EVENT_THRESHOLD_SIGMA 10
|
||||
|
||||
#define EVT_CLK_MULTIPLIER (2)
|
||||
#define EVT_CLK_FREQ (((omv_csi_get_xclk_frequency() * EVT_CLK_MULTIPLIER) + 500000) / 1000000)
|
||||
#define EVT_CLK_FREQ (((omv_csi_get_clk_frequency() * EVT_CLK_MULTIPLIER) + 500000) / 1000000)
|
||||
|
||||
#define AFK_50_HZ (50)
|
||||
#define AFK_60_HZ (60)
|
||||
@ -236,7 +236,7 @@ static int set_framerate(omv_csi_t *csi, int framerate) {
|
||||
}
|
||||
|
||||
int lines = ACTIVE_SENSOR_HEIGHT + VSYNC_CLOCK_CYCLES;
|
||||
int clocks_per_frame = (omv_csi_get_xclk_frequency() * EVT_CLK_MULTIPLIER) / framerate;
|
||||
int clocks_per_frame = (omv_csi_get_clk_frequency() * EVT_CLK_MULTIPLIER) / framerate;
|
||||
int hsync_clocks = (clocks_per_frame / lines) - ACTIVE_SENSOR_WIDTH;
|
||||
|
||||
if (hsync_clocks <= 0) {
|
||||
|
||||
@ -476,7 +476,7 @@ static int reset(omv_csi_t *csi) {
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, 0x301A, reg | (1 << 9));
|
||||
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, MT9M114_REG_CAM_SYSCTL_PLL_DIVIDER_M_N,
|
||||
(omv_csi_get_xclk_frequency() == OMV_MT9M114_CLK_FREQ)
|
||||
(omv_csi_get_clk_frequency() == OMV_MT9M114_CLK_FREQ)
|
||||
? 0x120 // xclk=24MHz, m=32, n=1, csi=48MHz, bus=76.8MHz
|
||||
: 0x448); // xclk=25MHz, m=72, n=4, csi=45MHz, bus=72MHz
|
||||
|
||||
@ -675,7 +675,7 @@ static int set_framesize(omv_csi_t *csi, omv_csi_framesize_t framesize) {
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, MT9M114_REG_SENSOR_CFG_Y_ADDR_END, sensor_he);
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, MT9M114_REG_SENSOR_CFG_X_ADDR_END, sensor_we);
|
||||
|
||||
int pixclk = (omv_csi_get_xclk_frequency() == OMV_MT9M114_CLK_FREQ) ? 48000000 : 45000000;
|
||||
int pixclk = (omv_csi_get_clk_frequency() == OMV_MT9M114_CLK_FREQ) ? 48000000 : 45000000;
|
||||
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, MT9M114_REG_SENSOR_CFG_PIXCLK, pixclk >> 16);
|
||||
ret |= omv_i2c_writew2(&csi->i2c_bus, csi->slv_addr, MT9M114_REG_SENSOR_CFG_PIXCLK + 2, pixclk);
|
||||
|
||||
@ -343,7 +343,7 @@ static int set_auto_exposure(omv_csi_t *csi, int enable, int exposure_us) {
|
||||
ret |= omv_i2c_readw(&csi->i2c_bus, csi->slv_addr, window_width, &row_time_0);
|
||||
ret |= omv_i2c_readw(&csi->i2c_bus, csi->slv_addr, horizontal_blanking, &row_time_1);
|
||||
|
||||
int clock = omv_csi_get_xclk_frequency();
|
||||
int clock = omv_csi_get_clk_frequency();
|
||||
|
||||
int exposure = IM_MIN(exposure_us, MICROSECOND_CLKS / 2) * (clock / MICROSECOND_CLKS);
|
||||
int row_time = row_time_0 + row_time_1;
|
||||
@ -389,7 +389,7 @@ static int get_exposure_us(omv_csi_t *csi, int *exposure_us) {
|
||||
ret |= omv_i2c_readw(&csi->i2c_bus, csi->slv_addr, fine_shutter_width_total, &int_pixels);
|
||||
}
|
||||
|
||||
int clock = omv_csi_get_xclk_frequency();
|
||||
int clock = omv_csi_get_clk_frequency();
|
||||
|
||||
if (reg & (context ? MT9V0X4_AEC_ENABLE_B : MT9V0XX_AEC_ENABLE)) {
|
||||
ret |= omv_i2c_readw(&csi->i2c_bus, csi->slv_addr, MT9V0XX_AEC_EXPOSURE_OUTPUT, &int_rows);
|
||||
|
||||
@ -1126,7 +1126,7 @@ static int calc_pclk_freq(uint8_t sc_pll_ctrl_0,
|
||||
uint8_t sc_pll_ctrl_2,
|
||||
uint8_t sc_pll_ctrl_3,
|
||||
uint8_t sys_root_div) {
|
||||
uint32_t pclk_freq = omv_csi_get_xclk_frequency();
|
||||
uint32_t pclk_freq = omv_csi_get_clk_frequency();
|
||||
pclk_freq /= ((sc_pll_ctrl_3 & 0x10) != 0x00) ? 2 : 1;
|
||||
pclk_freq /= ((sc_pll_ctrl_0 & 0x0F) == 0x0A) ? 5 : 4; //camera has two MIPI lanes
|
||||
switch (sc_pll_ctrl_3 & 0x0F) {
|
||||
|
||||
@ -95,62 +95,6 @@ void omv_csi_init0() {
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
CPI_Type *cpi = cpi_get_base_addr(&csi);
|
||||
|
||||
alif_hal_csi_init(cpi, 0);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
omv_gpio_write(OMV_CSI_RESET_PIN, 0);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the CSI external clock.
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image csi.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// csi probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
// All good!
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_config(omv_csi_config_t config) {
|
||||
if (config == OMV_CSI_CONFIG_INIT) {
|
||||
CPI_Type *cpi = cpi_get_base_addr(&csi);
|
||||
@ -452,6 +396,62 @@ int omv_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
CPI_Type *cpi = cpi_get_base_addr(&csi);
|
||||
|
||||
alif_hal_csi_init(cpi, 0);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
omv_gpio_write(OMV_CSI_POWER_PIN, 0);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
omv_gpio_write(OMV_CSI_RESET_PIN, 0);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the CSI external clock.
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image csi.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// csi probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
// All good!
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CAM_IRQHandler(void) {
|
||||
uint32_t mask = 0;
|
||||
CPI_Type *cpi = cpi_get_base_addr(&csi);
|
||||
|
||||
@ -73,62 +73,6 @@ void omv_csi_init0() {
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
mimxrt_hal_csi_init(CSI);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
omv_gpio_write(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
// Some sensors need to call snapshot from init.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
// All good!
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_config(omv_csi_config_t config) {
|
||||
if (config == OMV_CSI_CONFIG_INIT) {
|
||||
CSI_Reset(CSI);
|
||||
@ -207,7 +151,7 @@ int omv_csi_set_clk_frequency(uint32_t frequency) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t omv_csi_get_xclk_frequency() {
|
||||
uint32_t omv_csi_get_clk_frequency() {
|
||||
return 24000000 / (CLOCK_GetDiv(kCLOCK_CsiDiv) + 1);
|
||||
}
|
||||
|
||||
@ -587,3 +531,59 @@ int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
mimxrt_hal_csi_init(CSI);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
omv_gpio_write(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
omv_gpio_write(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
// Some sensors need to call snapshot from init.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
// All good!
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -61,62 +61,6 @@ static const volatile uint32_t *_pclkPort;
|
||||
|
||||
extern void __fatal_error(const char *msg);
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
nrf_gpio_cfg_output(OMV_CSI_POWER_PIN);
|
||||
nrf_gpio_pin_write(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
nrf_gpio_cfg_output(OMV_CSI_RESET_PIN);
|
||||
nrf_gpio_pin_write(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Clear fb_enabled flag
|
||||
// This is executed only once to initialize the FB enabled flag.
|
||||
//JPEG_FB()->enabled = 0;
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
csi.detected = true;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
/* All good! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_config(omv_csi_config_t config) {
|
||||
if (config == OMV_CSI_CONFIG_INIT) {
|
||||
uint32_t csi_pins[] = {
|
||||
@ -150,7 +94,7 @@ int omv_csi_config(omv_csi_config_t config) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t omv_csi_get_xclk_frequency() {
|
||||
uint32_t omv_csi_get_clk_frequency() {
|
||||
return OMV_CSI_CLK_FREQUENCY;
|
||||
}
|
||||
|
||||
@ -261,3 +205,59 @@ int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
framebuffer_init_image(fb, image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
nrf_gpio_cfg_output(OMV_CSI_POWER_PIN);
|
||||
nrf_gpio_pin_write(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
nrf_gpio_cfg_output(OMV_CSI_RESET_PIN);
|
||||
nrf_gpio_pin_write(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Configure the CSI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
// CSI config failed
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Clear fb_enabled flag
|
||||
// This is executed only once to initialize the FB enabled flag.
|
||||
//JPEG_FB()->enabled = 0;
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
csi.detected = true;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
/* All good! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -65,91 +65,6 @@ static void omv_csi_dma_config(int w, int h, int bpp, uint32_t *capture_buf, boo
|
||||
dma_irqn_set_channel_enabled(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL, true);
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
// PIXCLK
|
||||
gpio_init(OMV_CSI_PXCLK_PIN);
|
||||
gpio_set_dir(OMV_CSI_PXCLK_PIN, GPIO_IN);
|
||||
|
||||
// HSYNC
|
||||
gpio_init(OMV_CSI_HSYNC_PIN);
|
||||
gpio_set_dir(OMV_CSI_HSYNC_PIN, GPIO_IN);
|
||||
|
||||
// VSYNC
|
||||
gpio_init(OMV_CSI_VSYNC_PIN);
|
||||
gpio_set_dir(OMV_CSI_VSYNC_PIN, GPIO_IN);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
gpio_init(OMV_CSI_POWER_PIN);
|
||||
gpio_set_dir(OMV_CSI_POWER_PIN, GPIO_OUT);
|
||||
gpio_pull_down(OMV_CSI_POWER_PIN);
|
||||
gpio_put(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
gpio_init(OMV_CSI_RESET_PIN);
|
||||
gpio_set_dir(OMV_CSI_RESET_PIN, GPIO_OUT);
|
||||
gpio_pull_up(OMV_CSI_RESET_PIN);
|
||||
gpio_put(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Set new DMA IRQ handler.
|
||||
// Disable IRQs.
|
||||
irq_set_enabled(OMV_CSI_DMA_IRQ, false);
|
||||
|
||||
// Clear DMA interrupts.
|
||||
dma_irqn_acknowledge_channel(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL);
|
||||
|
||||
// Remove current handler if any
|
||||
irq_handler_t irq_handler = irq_get_exclusive_handler(OMV_CSI_DMA_IRQ);
|
||||
if (irq_handler != NULL) {
|
||||
irq_remove_handler(OMV_CSI_DMA_IRQ, irq_handler);
|
||||
}
|
||||
|
||||
// Set new exclusive IRQ handler.
|
||||
irq_set_exclusive_handler(OMV_CSI_DMA_IRQ, dma_irq_handler);
|
||||
// Or set shared IRQ handler, but this needs to be called once.
|
||||
// irq_add_shared_handler(OMV_CSI_DMA_IRQ, dma_irq_handler, PICO_DEFAULT_IRQ_PRIORITY);
|
||||
|
||||
irq_set_enabled(OMV_CSI_DMA_IRQ, true);
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
/* All good! */
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
|
||||
// Disable DMA channel
|
||||
dma_channel_abort(OMV_CSI_DMA_CHANNEL);
|
||||
@ -280,3 +195,88 @@ int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
// PIXCLK
|
||||
gpio_init(OMV_CSI_PXCLK_PIN);
|
||||
gpio_set_dir(OMV_CSI_PXCLK_PIN, GPIO_IN);
|
||||
|
||||
// HSYNC
|
||||
gpio_init(OMV_CSI_HSYNC_PIN);
|
||||
gpio_set_dir(OMV_CSI_HSYNC_PIN, GPIO_IN);
|
||||
|
||||
// VSYNC
|
||||
gpio_init(OMV_CSI_VSYNC_PIN);
|
||||
gpio_set_dir(OMV_CSI_VSYNC_PIN, GPIO_IN);
|
||||
|
||||
#if defined(OMV_CSI_POWER_PIN)
|
||||
gpio_init(OMV_CSI_POWER_PIN);
|
||||
gpio_set_dir(OMV_CSI_POWER_PIN, GPIO_OUT);
|
||||
gpio_pull_down(OMV_CSI_POWER_PIN);
|
||||
gpio_put(OMV_CSI_POWER_PIN, 1);
|
||||
#endif
|
||||
|
||||
#if defined(OMV_CSI_RESET_PIN)
|
||||
gpio_init(OMV_CSI_RESET_PIN);
|
||||
gpio_set_dir(OMV_CSI_RESET_PIN, GPIO_OUT);
|
||||
gpio_pull_up(OMV_CSI_RESET_PIN);
|
||||
gpio_put(OMV_CSI_RESET_PIN, 1);
|
||||
#endif
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
// Failed to initialize the csi clock.
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
if ((init_ret = omv_csi_probe_init(OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED)) != 0) {
|
||||
// Sensor probe/init failed.
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
// Set new DMA IRQ handler.
|
||||
// Disable IRQs.
|
||||
irq_set_enabled(OMV_CSI_DMA_IRQ, false);
|
||||
|
||||
// Clear DMA interrupts.
|
||||
dma_irqn_acknowledge_channel(OMV_CSI_DMA, OMV_CSI_DMA_CHANNEL);
|
||||
|
||||
// Remove current handler if any
|
||||
irq_handler_t irq_handler = irq_get_exclusive_handler(OMV_CSI_DMA_IRQ);
|
||||
if (irq_handler != NULL) {
|
||||
irq_remove_handler(OMV_CSI_DMA_IRQ, irq_handler);
|
||||
}
|
||||
|
||||
// Set new exclusive IRQ handler.
|
||||
irq_set_exclusive_handler(OMV_CSI_DMA_IRQ, dma_irq_handler);
|
||||
// Or set shared IRQ handler, but this needs to be called once.
|
||||
// irq_add_shared_handler(OMV_CSI_DMA_IRQ, dma_irq_handler, PICO_DEFAULT_IRQ_PRIORITY);
|
||||
|
||||
irq_set_enabled(OMV_CSI_DMA_IRQ, true);
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
/* All good! */
|
||||
csi.detected = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -95,129 +95,64 @@ void omv_csi_mdma_irq_handler(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_DMA
|
||||
static int omv_csi_dma_config() {
|
||||
// DMA Stream configuration
|
||||
csi.dma.Instance = DMA2_Stream1;
|
||||
#if defined(STM32H7)
|
||||
csi.dma.Init.Request = DMA_REQUEST_DCMI;
|
||||
#else
|
||||
csi.dma.Init.Channel = DMA_CHANNEL_1;
|
||||
#endif
|
||||
csi.dma.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
csi.dma.Init.MemInc = DMA_MINC_ENABLE;
|
||||
csi.dma.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
csi.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
||||
csi.dma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||
csi.dma.Init.Mode = DMA_NORMAL;
|
||||
csi.dma.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
csi.dma.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
csi.dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
csi.dma.Init.MemBurst = DMA_MBURST_INC4;
|
||||
csi.dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||
|
||||
// Initialize the DMA stream
|
||||
HAL_DMA_DeInit(&csi.dma);
|
||||
if (HAL_DMA_Init(&csi.dma) != HAL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set DMA IRQ handle
|
||||
dma_utils_set_irq_descr(DMA2_Stream1, &csi.dma);
|
||||
|
||||
// Configure the DMA IRQ Channel
|
||||
NVIC_SetPriority(DMA2_Stream1_IRQn, IRQ_PRI_DMA21);
|
||||
|
||||
#if USE_MDMA
|
||||
csi.mdma0.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_0);
|
||||
csi.mdma1.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void omv_csi_init0() {
|
||||
omv_csi_abort(&csi, true, false);
|
||||
|
||||
// Disable callbacks
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
|
||||
csi.disable_delays = false;
|
||||
|
||||
// Re-init i2c bus to reset the bus state after soft reset, which
|
||||
// could have interrupted the bus in the middle of a transfer.
|
||||
if (csi.i2c_bus.initialized) {
|
||||
// Reinitialize the bus using the last used id and speed.
|
||||
omv_i2c_init(&csi.i2c_bus, csi.i2c_bus.id, csi.i2c_bus.speed);
|
||||
}
|
||||
|
||||
csi.disable_delays = false;
|
||||
|
||||
// Disable VSYNC IRQ and callback
|
||||
omv_csi_set_vsync_callback(NULL);
|
||||
|
||||
// Disable Frame callback.
|
||||
omv_csi_set_frame_callback(NULL);
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
// List of I2C buses to scan.
|
||||
uint32_t buses[][2] = {
|
||||
{OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED},
|
||||
#if defined(OMV_CSI_I2C_ALT_ID)
|
||||
{OMV_CSI_I2C_ALT_ID, OMV_CSI_I2C_ALT_SPEED},
|
||||
#endif
|
||||
};
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
for (uint32_t i = 0, n_buses = OMV_ARRAY_SIZE(buses); i < n_buses; i++) {
|
||||
uint32_t id = buses[i][0], speed = buses[i][1];
|
||||
if ((init_ret = omv_csi_probe_init(id, speed)) == 0) {
|
||||
break;
|
||||
}
|
||||
omv_i2c_deinit(&csi.i2c_bus);
|
||||
// Scan the next bus or fail if this is the last one.
|
||||
if ((i + 1) == n_buses) {
|
||||
return init_ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the DCMI DMA Stream
|
||||
#if USE_DMA
|
||||
if (omv_csi_dma_config() != 0) {
|
||||
return OMV_CSI_ERROR_DMA_INIT_FAILED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Configure the DCMI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Clear fb_enabled flag.
|
||||
JPEG_FB()->enabled = 0;
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
csi.detected = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_config(omv_csi_config_t config) {
|
||||
if (config == OMV_CSI_CONFIG_INIT) {
|
||||
#if USE_DMA
|
||||
// DMA Stream configuration
|
||||
csi.dma.Instance = DMA2_Stream1;
|
||||
#if defined(STM32H7)
|
||||
csi.dma.Init.Request = DMA_REQUEST_DCMI;
|
||||
#else
|
||||
csi.dma.Init.Channel = DMA_CHANNEL_1;
|
||||
#endif
|
||||
csi.dma.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
csi.dma.Init.MemInc = DMA_MINC_ENABLE;
|
||||
csi.dma.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
csi.dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
||||
csi.dma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||
csi.dma.Init.Mode = DMA_NORMAL;
|
||||
csi.dma.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
csi.dma.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
|
||||
csi.dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
csi.dma.Init.MemBurst = DMA_MBURST_INC4;
|
||||
csi.dma.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||
|
||||
// Initialize the DMA stream
|
||||
HAL_DMA_DeInit(&csi.dma);
|
||||
if (HAL_DMA_Init(&csi.dma) != HAL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set DMA IRQ handle
|
||||
dma_utils_set_irq_descr(DMA2_Stream1, &csi.dma);
|
||||
|
||||
// Configure the DMA IRQ Channel
|
||||
NVIC_SetPriority(DMA2_Stream1_IRQn, IRQ_PRI_DMA21);
|
||||
|
||||
#if USE_MDMA
|
||||
csi.mdma0.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_0);
|
||||
csi.mdma1.Instance = MDMA_CHAN_TO_INSTANCE(OMV_MDMA_CHANNEL_DCMI_1);
|
||||
#endif
|
||||
|
||||
#endif // USE_DMA
|
||||
|
||||
// Configure DCMI/PP.
|
||||
#if USE_DCMIPP
|
||||
// Initialize the DCMIPP
|
||||
@ -352,6 +287,7 @@ int omv_csi_config(omv_csi_config_t config) {
|
||||
.ShiftBlue = 0,
|
||||
.MultiplierBlue = 128,
|
||||
};
|
||||
|
||||
if (HAL_DCMIPP_PIPE_SetISPExposureConfig(&csi.dcmi, DCMIPP_PIPE, &expcfg) != HAL_OK ||
|
||||
HAL_DCMIPP_PIPE_EnableISPExposure(&csi.dcmi, DCMIPP_PIPE) != HAL_OK) {
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
@ -432,7 +368,7 @@ int omv_csi_abort(omv_csi_t *csi, bool fifo_flush, bool in_irq) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t omv_csi_get_xclk_frequency() {
|
||||
uint32_t omv_csi_get_clk_frequency() {
|
||||
return (OMV_CSI_TIM_PCLK_FREQ() * 2) / (csi.tim.Init.Period + 1);
|
||||
}
|
||||
|
||||
@ -1148,3 +1084,56 @@ int omv_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omv_csi_init() {
|
||||
int init_ret = 0;
|
||||
|
||||
// List of I2C buses to scan.
|
||||
uint32_t buses[][2] = {
|
||||
{OMV_CSI_I2C_ID, OMV_CSI_I2C_SPEED},
|
||||
#if defined(OMV_CSI_I2C_ALT_ID)
|
||||
{OMV_CSI_I2C_ALT_ID, OMV_CSI_I2C_ALT_SPEED},
|
||||
#endif
|
||||
};
|
||||
|
||||
// Reset the csi state
|
||||
memset(&csi, 0, sizeof(omv_csi_t));
|
||||
|
||||
// Set default framebuffer
|
||||
csi.fb = framebuffer_get(0);
|
||||
|
||||
// Set default snapshot function.
|
||||
csi.snapshot = omv_csi_snapshot;
|
||||
|
||||
// Configure the csi external clock (XCLK).
|
||||
if (omv_csi_set_clk_frequency(OMV_CSI_CLK_FREQUENCY) != 0) {
|
||||
return OMV_CSI_ERROR_TIM_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Detect and initialize the image sensor.
|
||||
for (uint32_t i = 0, n_buses = OMV_ARRAY_SIZE(buses); i < n_buses; i++) {
|
||||
uint32_t id = buses[i][0], speed = buses[i][1];
|
||||
if ((init_ret = omv_csi_probe_init(id, speed)) == 0) {
|
||||
break;
|
||||
}
|
||||
omv_i2c_deinit(&csi.i2c_bus);
|
||||
// Scan the next bus or fail if this is the last one.
|
||||
if ((i + 1) == n_buses) {
|
||||
return init_ret;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the DCMI interface.
|
||||
if (omv_csi_config(OMV_CSI_CONFIG_INIT) != 0) {
|
||||
return OMV_CSI_ERROR_CSI_INIT_FAILED;
|
||||
}
|
||||
|
||||
// Clear fb_enabled flag.
|
||||
JPEG_FB()->enabled = 0;
|
||||
|
||||
// Set default color palette.
|
||||
csi.color_palette = rainbow_table;
|
||||
|
||||
csi.detected = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user