diff --git a/bsp/stm32/stm32h743-atk-apollo/board/Kconfig b/bsp/stm32/stm32h743-atk-apollo/board/Kconfig index e2d7618062..a2065dc17e 100644 --- a/bsp/stm32/stm32h743-atk-apollo/board/Kconfig +++ b/bsp/stm32/stm32h743-atk-apollo/board/Kconfig @@ -41,6 +41,13 @@ menu "Onboard Peripheral Drivers" select RT_USING_DFS_ELMFAT default n + config BSP_USING_OV2640 + bool "Enable camera (ov2640)" + select BSP_USING_DCMI + select BSP_USING_I2C + select BSP_USING_I2C2 + default n + endmenu menu "On-chip Peripheral Drivers" @@ -98,28 +105,55 @@ menu "On-chip Peripheral Drivers" select RT_USING_SPI default n - menuconfig BSP_USING_I2C1 - bool "Enable I2C1 BUS (software simulation)" - default n - select RT_USING_I2C - select RT_USING_I2C_BITOPS - select RT_USING_PIN - if BSP_USING_I2C1 - comment "Notice: PH4 --> 116; PH5 --> 117" - config BSP_I2C1_SCL_PIN - int "i2c1 scl pin number" - range 1 176 - default 116 - config BSP_I2C1_SDA_PIN - int "I2C1 sda pin number" - range 1 176 - default 117 - endif + menuconfig BSP_USING_I2C + bool "Enable I2C BUS (software simulation)" + select RT_USING_I2C + select RT_USING_I2C_BITOPS + select RT_USING_PIN + default n + if BSP_USING_I2C + menuconfig BSP_USING_I2C1 + bool "Enable I2C1 BUS (software simulation)" + default n + if BSP_USING_I2C1 + comment "Notice: PH4 --> 116; PH5 --> 117" + config BSP_I2C1_SCL_PIN + int "i2c1 scl pin number" + range 1 176 + default 116 + config BSP_I2C1_SDA_PIN + int "I2C1 sda pin number" + range 1 176 + default 117 + menuconfig BSP_USING_I2C2 + bool "Enable I2C2 BUS (software simulation)" + default n + endif + + menuconfig BSP_USING_I2C2 + bool "Enable I2C2 BUS (software simulation)" + default n + if BSP_USING_I2C2 + comment "Notice: PH13 --> 125; PH15 --> 127" + config BSP_I2C2_SCL_PIN + int "i2c2 scl pin number" + range 1 176 + default 127 + config BSP_I2C2_SDA_PIN + int "I2C2 sda pin number" + range 1 176 + default 125 + endif + endif config BSP_USING_ON_CHIP_FLASH bool "Enable on-chip FLASH" default n + config BSP_USING_DCMI + bool "Enable DCMI" + default n + menuconfig BSP_USING_ONCHIP_RTC bool "Enable RTC" select RT_USING_RTC diff --git a/bsp/stm32/stm32h743-atk-apollo/board/SConscript b/bsp/stm32/stm32h743-atk-apollo/board/SConscript index 8ed2e269df..07cbe41b4f 100644 --- a/bsp/stm32/stm32h743-atk-apollo/board/SConscript +++ b/bsp/stm32/stm32h743-atk-apollo/board/SConscript @@ -17,6 +17,10 @@ if GetDepend(['BSP_USING_QSPI_FLASH']): src += Glob('ports/drv_qspi_flash.c') if GetDepend(['BSP_USING_SDMMC']): src += Glob('ports/drv_sdio.c') +if GetDepend(['BSP_USING_DCMI']): + src += Glob('ports/drv_dcmi.c') +if GetDepend(['BSP_USING_OV2640']): + src += Glob('ports/drv_ov2640.c') path = [cwd] path += [cwd + '/CubeMX_Config/Inc'] diff --git a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.c b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.c new file mode 100644 index 0000000000..8a57c37e01 --- /dev/null +++ b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-27 thread-liu the first version + */ + +#include "board.h" + +#if defined(BSP_USING_DCMI) + +#include + +#define DRV_DEBUG +#define LOG_TAG "drv.dcmi" +#include + +struct stm32_dcmi +{ + DCMI_HandleTypeDef DCMI_Handle; + struct rt_dcmi_device dev; +}; +static struct stm32_dcmi rt_dcmi = {0}; + +DMA_HandleTypeDef hdma_dcmi; + +static void rt_hw_dcmi_dma_init(void) +{ + __HAL_RCC_DMA2_CLK_ENABLE(); + + hdma_dcmi.Instance = DMA2_Stream1; + hdma_dcmi.Init.Request = DMA_REQUEST_DCMI; + hdma_dcmi.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_dcmi.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_dcmi.Init.MemInc = DMA_MINC_ENABLE; + hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_dcmi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_dcmi.Init.Mode = DMA_CIRCULAR; + hdma_dcmi.Init.Priority = DMA_PRIORITY_HIGH; + hdma_dcmi.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_dcmi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_dcmi.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_dcmi.Init.PeriphBurst = DMA_PBURST_SINGLE; + + HAL_DMA_DeInit(&hdma_dcmi); + HAL_DMA_Init(&hdma_dcmi); + + __HAL_LINKDMA(&rt_dcmi.DCMI_Handle, DMA_Handle, hdma_dcmi); + + HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0x00, 0x00); + HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);; +} + +void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint32_t len) +{ + __HAL_UNLOCK(&hdma_dcmi); + + HAL_DMAEx_MultiBufferStart(&hdma_dcmi, (rt_uint32_t)&DCMI->DR, dst_addr1, dst_addr2, len); + + __HAL_DMA_ENABLE_IT(&hdma_dcmi, DMA_IT_TC); +} + +static rt_err_t rt_hw_dcmi_init(DCMI_HandleTypeDef *device) +{ + RT_ASSERT(device != RT_NULL); + + device->Instance = DCMI; + device->Init.SynchroMode = DCMI_SYNCHRO_HARDWARE; + device->Init.PCKPolarity = DCMI_PCKPOLARITY_RISING; + device->Init.VSPolarity = DCMI_VSPOLARITY_LOW; + device->Init.HSPolarity = DCMI_HSPOLARITY_LOW; + device->Init.CaptureRate = DCMI_CR_ALL_FRAME; + device->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B; + device->Init.JPEGMode = DCMI_JPEG_ENABLE; + device->Init.ByteSelectMode = DCMI_BSM_ALL; + device->Init.ByteSelectStart = DCMI_OEBS_ODD; + device->Init.LineSelectMode = DCMI_LSM_ALL; + device->Init.LineSelectStart = DCMI_OELS_ODD; + + if (HAL_DCMI_Init(device) != HAL_OK) + { + LOG_E("dcmi init error!"); + return RT_ERROR; + } + + DCMI->IER = 0x0; + + __HAL_DCMI_ENABLE_IT(device, DCMI_IT_FRAME); + __HAL_DCMI_ENABLE(device); + + return RT_EOK; +} + +void DCMI_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DCMI_IRQHandler(&rt_dcmi.DCMI_Handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void DCMI_Start(void) +{ + __HAL_DMA_ENABLE(&hdma_dcmi); + DCMI->CR |= DCMI_CR_CAPTURE; +} + +void DCMI_Stop(void) +{ + DCMI->CR &= ~(DCMI_CR_CAPTURE); + while (DCMI->CR & 0x01); + __HAL_DMA_DISABLE(&hdma_dcmi); +} + +/* Capture a frame of the image */ +void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) +{ + extern void camera_frame_data_process(void); + /* enter interrupt */ + rt_interrupt_enter(); + /* move frame data to buffer */ + camera_frame_data_process(); + + __HAL_DCMI_ENABLE_IT(&rt_dcmi.DCMI_Handle, DCMI_IT_FRAME); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +void DMA2_Stream1_IRQHandler(void) +{ + extern void camera_dma_data_process(void); + /* enter interrupt */ + rt_interrupt_enter(); + + if (__HAL_DMA_GET_FLAG(&hdma_dcmi, DMA_FLAG_TCIF1_5) != RESET) + { + __HAL_DMA_CLEAR_FLAG(&hdma_dcmi, DMA_FLAG_TCIF1_5); + /* move dma data to buffer */ + camera_dma_data_process(); + } + + /* leave interrupt */ + rt_interrupt_leave(); +} + +static rt_err_t rt_dcmi_init(rt_device_t dev) +{ + RT_ASSERT(dev != RT_NULL); + rt_err_t result = RT_EOK; + + result = rt_hw_dcmi_init(&rt_dcmi.DCMI_Handle); + if (result != RT_EOK) + { + return result; + } + + rt_hw_dcmi_dma_init(); + + return result; +} + +static rt_err_t rt_dcmi_open(rt_device_t dev, rt_uint16_t oflag) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_err_t rt_dcmi_close(rt_device_t dev) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_err_t rt_dcmi_control(rt_device_t dev, int cmd, void *args) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_size_t rt_dcmi_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +static rt_size_t rt_dcmi_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + RT_ASSERT(dev != RT_NULL); + + return RT_EOK; +} + +int dcmi_init(void) +{ + rt_dcmi.dev.parent.type = RT_Device_Class_Miscellaneous; + rt_dcmi.dev.parent.init = rt_dcmi_init; + rt_dcmi.dev.parent.open = rt_dcmi_open; + rt_dcmi.dev.parent.close = rt_dcmi_close; + rt_dcmi.dev.parent.read = rt_dcmi_read; + rt_dcmi.dev.parent.write = rt_dcmi_write; + rt_dcmi.dev.parent.control = rt_dcmi_control; + rt_dcmi.dev.parent.user_data = RT_NULL; + + rt_device_register(&rt_dcmi.dev.parent, "dcmi", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE); + + LOG_I("dcmi init success!"); + + return RT_EOK; +} +INIT_BOARD_EXPORT(dcmi_init); + +#endif diff --git a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.h b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.h new file mode 100644 index 0000000000..af519987dd --- /dev/null +++ b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_dcmi.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-27 thread-liu the first version + */ + +#ifndef __DRV_DCMI_H__ +#define __DRV_DCMI_H__ + +#include "board.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct rt_dcmi_device +{ + struct rt_device parent; +}; + +extern DMA_HandleTypeDef hdma_dcmi; +extern void rt_hw_dcmi_dma_config(rt_uint32_t dst_addr1, rt_uint32_t dst_addr2, rt_uint32_t len); +extern void DCMI_Start(void); +extern void DCMI_Stop(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c new file mode 100644 index 0000000000..0ed9345156 --- /dev/null +++ b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.c @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-08-03 thread-liu the first version + */ + +#include "board.h" + +#if defined(BSP_USING_OV2640) + +#include +#include +#include +#include "pcf8574.h" + +#define DRV_DEBUG +//#define CAMERA_DUMP +#define LOG_TAG "drv.ov2640" +#include + +#define DEV_ADDRESS 0x30 /* OV2640 address */ +#define I2C_NAME "i2c2" + +#define RESET_PIN GET_PIN(A, 15) /* camera reset pin */ + +/* camera PWDN pin */ +#define DCMI_PWDN_IO 2 /* pcf8574 (0-7) */ + +volatile rt_uint32_t jpeg_data_len = 0; +volatile rt_uint8_t jpeg_data_ok = 0; +struct rt_i2c_bus_device *i2c_bus = RT_NULL; + +#define JPEG_BUF_SIZE 32 * 1024 +#define JPEG_LINE_SIZE 1 * 1024 + +static pcf8574_device_t pcf_dev = RT_NULL; + +static rt_uint32_t *jpeg_data_buf = RT_NULL; +static rt_uint32_t JPEG_LINE0_BUF[JPEG_LINE_SIZE]; +static rt_uint32_t JPEG_LINE1_BUF[JPEG_LINE_SIZE]; + +#if defined(CAMERA_DUMP) +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen) +{ + unsigned char *buf = (unsigned char *)ptr; + int i, j; + + for (i = 0; i < buflen; i += 16) + { + rt_kprintf("%08x:", i); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + rt_kprintf("%02x", buf[i + j]); + } + else + { + rt_kprintf(" "); + } + } + rt_kprintf(" "); + + for (j = 0; j < 16; j++) + { + if (i + j < buflen) + { + rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.'); + } + } + rt_kprintf("\n"); + } +} +#endif + +static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t len, rt_uint8_t *buf) +{ + struct rt_i2c_msg msg[2]; + + RT_ASSERT(bus != RT_NULL); + + msg[0].addr = DEV_ADDRESS; + msg[0].flags = RT_I2C_WR; + msg[0].buf = ® + msg[0].len = 2; + + msg[1].addr = DEV_ADDRESS; + msg[1].flags = RT_I2C_RD; + msg[1].len = len; + msg[1].buf = buf; + + if (rt_i2c_transfer(bus, msg, 2) == 2) + { + return RT_EOK; + } + + return RT_ERROR; +} + +/* i2c write reg */ +static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data) +{ + rt_uint8_t buf[2]; + struct rt_i2c_msg msgs; + + RT_ASSERT(bus != RT_NULL); + + buf[0] = reg ; + buf[1] = data; + + msgs.addr = DEV_ADDRESS; + msgs.flags = RT_I2C_WR; + msgs.buf = buf; + msgs.len = 2; + + if (rt_i2c_transfer(bus, &msgs, 1) == 1) + { + return RT_EOK; + } + + return RT_ERROR; +} + +static rt_err_t ov2640_read_id(struct rt_i2c_bus_device *bus) +{ + rt_uint8_t read_value[2]; + rt_uint16_t id = 0; + read_reg(bus, OV2640_SENSOR_MIDH, 1, &read_value[0]); + read_reg(bus, OV2640_SENSOR_MIDL, 1, &read_value[1]); + id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00); + id |= ((rt_uint16_t)(read_value[1]) & 0x00FF); + + if (id != OV2640_MID) + { + LOG_E("ov2640 init error, mid: 0x%04x", id); + return RT_ERROR; + } + + LOG_I("ov2640 read mid success, mid: 0x%04x", id); + + read_reg(bus, OV2640_SENSOR_PIDH, 1, &read_value[0]); + read_reg(bus, OV2640_SENSOR_PIDL, 1, &read_value[1]); + id = ((rt_uint16_t)(read_value[0] << 8) & 0xFF00); + id |= ((rt_uint16_t)(read_value[1]) & 0x00FF); + + if (id != OV2640_PID) + { + LOG_E("ov2640 init error, pid: 0x%04x", id); + return RT_ERROR; + } + + LOG_I("ov2640 read hid success, pid: 0x%04x", id); + + return RT_EOK; +} + +/* change ov2640 to jpeg mode */ +void ov2640_jpeg_mode(void) +{ + rt_uint16_t i=0; + /* set yun422 mode */ + for (i = 0; i < (sizeof(ov2640_yuv422_reg_tbl) / 2); i++) + { + write_reg(i2c_bus, ov2640_yuv422_reg_tbl[i][0],ov2640_yuv422_reg_tbl[i][1]); + } + + /* set jpeg mode */ + for(i=0;i<(sizeof(ov2640_jpeg_reg_tbl)/2);i++) + { + write_reg(i2c_bus, ov2640_jpeg_reg_tbl[i][0],ov2640_jpeg_reg_tbl[i][1]); + } +} + +/* change ov2640 to rgb565 mode */ +void ov2640_rgb565_mode(void) +{ + rt_uint16_t i=0; + for (i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++) + { + write_reg(i2c_bus, ov2640_rgb565_reg_tbl[i][0],ov2640_rgb565_reg_tbl[i][1]); + } +} + +/* set auto exposure */ +void ov2640_set_auto_exposure(rt_uint8_t level) +{ + rt_uint8_t i = 0; + rt_uint8_t *p = (rt_uint8_t*)OV2640_AUTOEXPOSURE_LEVEL[level]; + for (i = 0; i < 4; i++) + { + write_reg(i2c_bus, p[i*2],p[i*2+1]); + } +} + +/* set light mode + * 0: auto + * 1: sunny + * 2: cloudy + * 3: office + * 4: home + * */ +void ov2640_set_light_mode(rt_uint8_t mode) +{ + rt_uint8_t regccval, regcdval, regceval; + + switch(mode) + { + case 0: + write_reg(i2c_bus, 0xFF, 0x00); + write_reg(i2c_bus, 0xC7, 0x10); + return; + + case 2: + regccval = 0x65; + regcdval = 0x41; + regceval = 0x4F; + break; + + case 3: + regccval = 0x52; + regcdval = 0x41; + regceval = 0x66; + break; + + case 4: + regccval = 0x42; + regcdval = 0x3F; + regceval = 0x71; + break; + + default: + regccval = 0x5E; + regcdval = 0x41; + regceval = 0x54; + break; + } + + write_reg(i2c_bus, 0xFF, 0x00); + write_reg(i2c_bus, 0xC7, 0x40); + write_reg(i2c_bus, 0xCC, regccval); + write_reg(i2c_bus, 0xCD, regcdval); + write_reg(i2c_bus, 0xCE, regceval); +} + +/* set color saturation + * 0: -2 + * 1: -1 + * 2: 0 + * 3: +1 + * 4: +2 + * */ +void ov2640_set_color_saturation(rt_uint8_t sat) +{ + rt_uint8_t reg7dval = ((sat+2)<<4) | 0x08; + write_reg(i2c_bus, 0xFF, 0X00); + write_reg(i2c_bus, 0x7C, 0X00); + write_reg(i2c_bus, 0x7D, 0X02); + write_reg(i2c_bus, 0x7C, 0X03); + write_reg(i2c_bus, 0x7D, reg7dval); + write_reg(i2c_bus, 0x7D, reg7dval); +} + +/* set brightness + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_brightness(rt_uint8_t bright) +{ + write_reg(i2c_bus, 0xff, 0x00); + write_reg(i2c_bus, 0x7c, 0x00); + write_reg(i2c_bus, 0x7d, 0x04); + write_reg(i2c_bus, 0x7c, 0x09); + write_reg(i2c_bus, 0x7d, bright << 4); + write_reg(i2c_bus, 0x7d, 0x00); +} + +/* set contrast + * 0: -2 + * 1: -1 + * 2: 0 + * 3: 1 + * 4: 2 + * */ +void ov2640_set_contrast(rt_uint8_t contrast) +{ + rt_uint8_t reg7d0val, reg7d1val; + + switch(contrast) + { + case 0: + reg7d0val = 0x18; + reg7d1val = 0x34; + break; + + case 1: + reg7d0val = 0x1C; + reg7d1val = 0x2A; + break; + + case 3: + reg7d0val = 0x24; + reg7d1val = 0x16; + break; + + case 4: + reg7d0val = 0x28; + reg7d1val = 0x0C; + break; + + default: + reg7d0val = 0x20; + reg7d1val = 0x20; + break; + } + write_reg(i2c_bus, 0xff, 0x00); + write_reg(i2c_bus, 0x7c, 0x00); + write_reg(i2c_bus, 0x7d, 0x04); + write_reg(i2c_bus, 0x7c, 0x07); + write_reg(i2c_bus, 0x7d, 0x20); + write_reg(i2c_bus, 0x7d, reg7d0val); + write_reg(i2c_bus, 0x7d, reg7d1val); + write_reg(i2c_bus, 0x7d, 0x06); +} + +/* set special effects + * 0: noraml + * 1: negative film + * 2: black-and-white + * 3: the red + * 4: the green + * 5: the blue + * 6: Retro +*/ +void ov2640_set_special_effects(rt_uint8_t eft) +{ + rt_uint8_t reg7d0val, reg7d1val, reg7d2val; + + switch(eft) + { + case 1: + reg7d0val = 0x40; + break; + case 2: + reg7d0val = 0x18; + break; + case 3: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xC0; + break; + case 4: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0x40; + break; + case 5: + reg7d0val = 0x18; + reg7d1val = 0xA0; + reg7d2val = 0x40; + break; + case 6: + reg7d0val = 0x18; + reg7d1val = 0x40; + reg7d2val = 0xA6; + break; + default: + reg7d0val = 0x00; + reg7d1val = 0x80; + reg7d2val = 0x80; + break; + } + write_reg(i2c_bus, 0xff, 0x00); + write_reg(i2c_bus, 0x7c, 0x00); + write_reg(i2c_bus, 0x7d, reg7d0val); + write_reg(i2c_bus, 0x7c, 0x05); + write_reg(i2c_bus, 0x7d, reg7d1val); + write_reg(i2c_bus, 0x7d, reg7d2val); +} + +/* set the image output window */ +void ov2640_set_window_size(rt_uint16_t sx,rt_uint16_t sy,rt_uint16_t width,rt_uint16_t height) +{ + rt_uint16_t endx; + rt_uint16_t endy; + rt_uint8_t temp; + endx = sx + width / 2; + endy = sy + height / 2; + + write_reg(i2c_bus, 0xFF, 0x01); + read_reg(i2c_bus, 0x03, 1, &temp); + temp &= 0xF0; + temp |= ((endy & 0x03) << 2) | (sy & 0x03); + write_reg(i2c_bus, 0x03, temp); + write_reg(i2c_bus, 0x19, sy>>2); + write_reg(i2c_bus, 0x1A, endy>>2); + + read_reg(i2c_bus, 0x32, 1, &temp); + temp &= 0xC0; + temp |= ((endx & 0x07) << 3) | (sx & 0x07); + write_reg(i2c_bus, 0x32, temp); + write_reg(i2c_bus, 0x17, sx>>3); + write_reg(i2c_bus, 0x18, endx>>3); +} + +/* set the image output size */ +rt_uint8_t ov2640_set_image_out_size(rt_uint16_t width,rt_uint16_t height) +{ + rt_uint16_t outh, outw; + rt_uint8_t temp; + + if(width%4)return 1; + if(height%4)return 2; + outw = width / 4; + outh = height / 4; + write_reg(i2c_bus, 0xFF, 0x00); + write_reg(i2c_bus, 0xE0, 0x04); + write_reg(i2c_bus, 0x5A, outw & 0XFF); + write_reg(i2c_bus, 0x5B, outh & 0XFF); + temp = (outw >> 8) & 0x03; + temp |= (outh >> 6) & 0x04; + write_reg(i2c_bus, 0x5C, temp); + write_reg(i2c_bus, 0xE0, 0X00); + + return RT_EOK; +} + +/* set the image window size */ +rt_uint8_t ov2640_set_image_window_size(rt_uint16_t offx, rt_uint16_t offy, rt_uint16_t width, rt_uint16_t height) +{ + rt_uint16_t hsize, vsize; + rt_uint8_t temp; + if ((width % 4) || (height%4)) + { + return RT_ERROR; + } + hsize = width / 4; + vsize = height / 4; + write_reg(i2c_bus, 0XFF,0X00); + write_reg(i2c_bus, 0XE0,0X04); + write_reg(i2c_bus, 0X51,hsize&0XFF); + write_reg(i2c_bus, 0X52,vsize&0XFF); + write_reg(i2c_bus, 0X53,offx&0XFF); + write_reg(i2c_bus, 0X54,offy&0XFF); + temp=(vsize>>1)&0X80; + temp|=(offy>>4)&0X70; + temp|=(hsize>>5)&0X08; + temp|=(offx>>8)&0X07; + write_reg(i2c_bus, 0X55,temp); + write_reg(i2c_bus, 0X57,(hsize>>2)&0X80); + write_reg(i2c_bus, 0XE0,0X00); + return 0; +} + +/* set output resolution */ +rt_uint8_t ov2640_set_image_size(rt_uint16_t width ,rt_uint16_t height) +{ + rt_uint8_t temp; + write_reg(i2c_bus, 0xFF, 0x00); + write_reg(i2c_bus, 0xE0, 0x04); + write_reg(i2c_bus, 0xC0, (width >>3) & 0xFF); + write_reg(i2c_bus, 0xC1, (height >> 3) & 0xFF); + temp = (width & 0x07) << 3; + temp |= height & 0x07; + temp |= (width >> 4) & 0x80; + write_reg(i2c_bus, 0x8C, temp); + write_reg(i2c_bus, 0xE0, 0x00); + + return RT_EOK; +} + +void camera_dma_data_process(void) +{ + rt_uint16_t i; + rt_uint32_t *pbuf; + pbuf = jpeg_data_buf + jpeg_data_len; + + if (DMA2_Stream1->CR & (1<<19)) + { + for (i = 0; i < JPEG_LINE_SIZE; i++) + { + pbuf[i] = JPEG_LINE0_BUF[i]; + } + jpeg_data_len += JPEG_LINE_SIZE; + } + else + { + for (i = 0; i < JPEG_LINE_SIZE; i++) + { + pbuf[i] = JPEG_LINE1_BUF[i]; + } + jpeg_data_len += JPEG_LINE_SIZE; + } + SCB_CleanInvalidateDCache(); +} + +/* After a frame of picture data has been collected. */ +void camera_frame_data_process(void) +{ + rt_uint16_t i, rlen; + rt_uint32_t *pbuf = RT_NULL; + + if (jpeg_data_ok == 0) + { + DMA2_Stream1->CR &= ~(1<<0); + while(DMA2_Stream1->CR & 0x01); + + rlen = JPEG_LINE_SIZE - DMA2_Stream1->NDTR; + pbuf = jpeg_data_buf + jpeg_data_len; + + if (DMA2_Stream1->CR & (1<<19)) + { + for (i = 0; i < rlen; i++) + { + pbuf[i] = JPEG_LINE1_BUF[i]; + } + } + else + { + for (i = 0; i < rlen; i++) + { + pbuf[i] = JPEG_LINE0_BUF[i]; + } + } + jpeg_data_len += rlen; + jpeg_data_ok = 1; + } + if (jpeg_data_ok==2) + { + DMA2_Stream1->NDTR = JPEG_LINE_SIZE; + DMA2_Stream1->CR |= 1<<0; + jpeg_data_ok = 0; + jpeg_data_len = 0; + } +} + +int ov2640_pwdn_set(rt_uint8_t sta) +{ + if (pcf_dev == RT_NULL) + { + LOG_E("can't find pcf8574 device!"); + return -1; + } + pcf8574_pin_write(pcf_dev, DCMI_PWDN_IO, sta); + + return 0; +} + +void sw_ov2640_mode(void) +{ + GPIO_InitTypeDef GPIO_Initure = {0}; + + ov2640_pwdn_set(0); + + GPIO_Initure.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11; + GPIO_Initure.Mode = GPIO_MODE_AF_PP; + GPIO_Initure.Pull = GPIO_PULLUP; + GPIO_Initure.Speed = GPIO_SPEED_HIGH; + GPIO_Initure.Alternate = GPIO_AF13_DCMI; + HAL_GPIO_Init(GPIOC,&GPIO_Initure); +} + +void sw_sdcard_mode(void) +{ + GPIO_InitTypeDef GPIO_Initure = {0}; + + ov2640_pwdn_set(1); /* OV2640 Power Down */ + + GPIO_Initure.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11; + GPIO_Initure.Mode = GPIO_MODE_AF_PP; + GPIO_Initure.Pull = GPIO_PULLUP; + GPIO_Initure.Speed = GPIO_SPEED_HIGH; + GPIO_Initure.Alternate = GPIO_AF12_SDMMC1; + HAL_GPIO_Init(GPIOC, &GPIO_Initure); +} + +int rt_ov2640_init(void) +{ + rt_uint16_t i = 0; + rt_err_t result = RT_EOK; + rt_device_t dcmi_dev = RT_NULL; + + sw_ov2640_mode(); + pcf_dev = pcf8574_init("i2c1", RT_NULL); + if (pcf_dev == RT_NULL) + { + LOG_E("can't find pcf8574, please check it"); + return -RT_ERROR; + } + + ov2640_pwdn_set(0); + rt_thread_delay(20); + + /* ov2640 hard reset */ + rt_pin_mode(RESET_PIN, PIN_MODE_OUTPUT); + rt_pin_write(RESET_PIN, PIN_LOW); + rt_thread_delay(20); + rt_pin_write(RESET_PIN, PIN_HIGH); + rt_thread_delay(20); + + i2c_bus = rt_i2c_bus_device_find(I2C_NAME); + if (i2c_bus == RT_NULL) + { + LOG_E("can't find %s deivce", I2C_NAME); + return RT_ERROR; + } + /* Prepare the camera to be configured */ + result = write_reg(i2c_bus, OV2640_DSP_RA_DLMT, 0x01); + if (result != RT_EOK ) + { + LOG_E("ov2640 write reg error!"); + return RT_ERROR; + } + rt_thread_delay(10); + result = write_reg(i2c_bus, OV2640_SENSOR_COM7, 0x80); + if (result != RT_EOK) + { + LOG_E("ov2640 soft reset error!"); + return RT_ERROR; + } + rt_thread_delay(20); + + result = ov2640_read_id(i2c_bus); + if (result != RT_EOK ) + { + LOG_E("ov2640 read id error!"); + return RT_ERROR; + } + + for (i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++) + { + write_reg(i2c_bus, ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1]); + } + + ov2640_rgb565_mode(); + ov2640_set_light_mode(0); + ov2640_set_color_saturation(3); + ov2640_set_brightness(4); + ov2640_set_contrast(3); + ov2640_jpeg_mode(); + ov2640_set_image_window_size(0, 0, 320, 240); + ov2640_set_image_out_size(320, 240); + + dcmi_dev = rt_device_find("dcmi"); + if (dcmi_dev == RT_NULL) + { + LOG_E("can't find dcmi device!"); + return RT_ERROR; + } + rt_device_open(dcmi_dev, RT_DEVICE_FLAG_RDWR); + + jpeg_data_buf = rt_malloc(JPEG_BUF_SIZE); + if (RT_NULL == jpeg_data_buf) + { + rt_kprintf("jpeg data buf malloc error!\n"); + return RT_ERROR; + } + + /* start dcmi capture */ + rt_hw_dcmi_dma_config((rt_uint32_t)JPEG_LINE0_BUF, (rt_uint32_t)JPEG_LINE1_BUF, JPEG_LINE_SIZE); + + rt_kprintf("camera init success!\n"); + + return RT_EOK; +} +INIT_APP_EXPORT(rt_ov2640_init); + +int camera_sample(int argc, char **argv) +{ + rt_err_t result = RT_EOK; + int fd = -1; + rt_uint32_t i, jpg_start, jpg_len; + rt_uint8_t jpg_head = 0; + rt_uint8_t *p = RT_NULL; + + if (argc != 2) + { + rt_kprintf("Usage:\n"); + rt_kprintf("camera_sample file.jpg\n"); + return -1; + } + + sw_ov2640_mode(); + DCMI_Start(); + + while (1) + { + while (jpeg_data_ok != 1); + jpeg_data_ok = 2; + while (jpeg_data_ok != 1); + DCMI_Stop(); + + p = (rt_uint8_t *)jpeg_data_buf; + jpg_len = 0; + jpg_head = 0; + for (i = 0; i < jpeg_data_len * 4; i++) + { + /* jpg head */ + if ((p[i] == 0xFF) && (p[i + 1] == 0xD8)) + { + jpg_start = i; + jpg_head = 1; + } + /* jpg end */ + if ((p[i] == 0xFF) && (p[i + 1] == 0xD9) && jpg_head) + { + jpg_len = i - jpg_start + 2; /* a picture len */ + break; + } + } + if (jpg_len) + { + p += jpg_start; + sw_sdcard_mode(); + fd = open(argv[1], O_WRONLY | O_CREAT); + if (fd < 0) + { + rt_kprintf("open file for recording failed!\n"); + result = -RT_ERROR; + goto _exit; + } + else + { + write(fd, p, jpg_len); + close(fd); + rt_kprintf("%s picture capture complate!\n", argv[1]); + break; + } + } + else + { + rt_kprintf("jpg_len error!\n"); + result = -RT_ERROR; + goto _exit; + } + } + +_exit: + return result;; +} +MSH_CMD_EXPORT(camera_sample, record picture to a jpg file); + +#endif diff --git a/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.h b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.h new file mode 100644 index 0000000000..4ff948b0c6 --- /dev/null +++ b/bsp/stm32/stm32h743-atk-apollo/board/ports/drv_ov2640.h @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2020-07-27 thread-liu first version + */ + +#ifndef __DRV_OV2640_H__ +#define __DRV_OV2640_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define OV2640_MID 0X7FA2 +#define OV2640_PID 0X2642 + + +//褰撻�夋嫨DSP鍦板潃(0XFF=0X00)鏃�,OV2640鐨凞SP瀵勫瓨鍣ㄥ湴鍧�鏄犲皠琛� +#define OV2640_DSP_R_BYPASS 0x05 +#define OV2640_DSP_Qs 0x44 +#define OV2640_DSP_CTRL 0x50 +#define OV2640_DSP_HSIZE1 0x51 +#define OV2640_DSP_VSIZE1 0x52 +#define OV2640_DSP_XOFFL 0x53 +#define OV2640_DSP_YOFFL 0x54 +#define OV2640_DSP_VHYX 0x55 +#define OV2640_DSP_DPRP 0x56 +#define OV2640_DSP_TEST 0x57 +#define OV2640_DSP_ZMOW 0x5A +#define OV2640_DSP_ZMOH 0x5B +#define OV2640_DSP_ZMHH 0x5C +#define OV2640_DSP_BPADDR 0x7C +#define OV2640_DSP_BPDATA 0x7D +#define OV2640_DSP_CTRL2 0x86 +#define OV2640_DSP_CTRL3 0x87 +#define OV2640_DSP_SIZEL 0x8C +#define OV2640_DSP_HSIZE2 0xC0 +#define OV2640_DSP_VSIZE2 0xC1 +#define OV2640_DSP_CTRL0 0xC2 +#define OV2640_DSP_CTRL1 0xC3 +#define OV2640_DSP_R_DVP_SP 0xD3 +#define OV2640_DSP_IMAGE_MODE 0xDA +#define OV2640_DSP_RESET 0xE0 +#define OV2640_DSP_MS_SP 0xF0 +#define OV2640_DSP_SS_ID 0x7F +#define OV2640_DSP_SS_CTRL 0xF8 +#define OV2640_DSP_MC_BIST 0xF9 +#define OV2640_DSP_MC_AL 0xFA +#define OV2640_DSP_MC_AH 0xFB +#define OV2640_DSP_MC_D 0xFC +#define OV2640_DSP_P_STATUS 0xFE +#define OV2640_DSP_RA_DLMT 0xFF + +//褰撻�夋嫨浼犳劅鍣ㄥ湴鍧�(0XFF=0X01)鏃�,OV2640鐨凞SP瀵勫瓨鍣ㄥ湴鍧�鏄犲皠琛� +#define OV2640_SENSOR_GAIN 0x00 +#define OV2640_SENSOR_COM1 0x03 +#define OV2640_SENSOR_REG04 0x04 +#define OV2640_SENSOR_REG08 0x08 +#define OV2640_SENSOR_COM2 0x09 +#define OV2640_SENSOR_PIDH 0x0A +#define OV2640_SENSOR_PIDL 0x0B +#define OV2640_SENSOR_COM3 0x0C +#define OV2640_SENSOR_COM4 0x0D +#define OV2640_SENSOR_AEC 0x10 +#define OV2640_SENSOR_CLKRC 0x11 +#define OV2640_SENSOR_COM7 0x12 +#define OV2640_SENSOR_COM8 0x13 +#define OV2640_SENSOR_COM9 0x14 +#define OV2640_SENSOR_COM10 0x15 +#define OV2640_SENSOR_HREFST 0x17 +#define OV2640_SENSOR_HREFEND 0x18 +#define OV2640_SENSOR_VSTART 0x19 +#define OV2640_SENSOR_VEND 0x1A +#define OV2640_SENSOR_MIDH 0x1C +#define OV2640_SENSOR_MIDL 0x1D +#define OV2640_SENSOR_AEW 0x24 +#define OV2640_SENSOR_AEB 0x25 +#define OV2640_SENSOR_W 0x26 +#define OV2640_SENSOR_REG2A 0x2A +#define OV2640_SENSOR_FRARL 0x2B +#define OV2640_SENSOR_ADDVSL 0x2D +#define OV2640_SENSOR_ADDVHS 0x2E +#define OV2640_SENSOR_YAVG 0x2F +#define OV2640_SENSOR_REG32 0x32 +#define OV2640_SENSOR_ARCOM2 0x34 +#define OV2640_SENSOR_REG45 0x45 +#define OV2640_SENSOR_FLL 0x46 +#define OV2640_SENSOR_FLH 0x47 +#define OV2640_SENSOR_COM19 0x48 +#define OV2640_SENSOR_ZOOMS 0x49 +#define OV2640_SENSOR_COM22 0x4B +#define OV2640_SENSOR_COM25 0x4E +#define OV2640_SENSOR_BD50 0x4F +#define OV2640_SENSOR_BD60 0x50 +#define OV2640_SENSOR_REG5D 0x5D +#define OV2640_SENSOR_REG5E 0x5E +#define OV2640_SENSOR_REG5F 0x5F +#define OV2640_SENSOR_REG60 0x60 +#define OV2640_SENSOR_HISTO_LOW 0x61 +#define OV2640_SENSOR_HISTO_HIGH 0x62 + +/* Automatic exposure setting parameters table, support 5 levels */ +const rt_uint8_t OV2640_AUTOEXPOSURE_LEVEL[5][8]= +{ + { + 0xFF,0x01, + 0x24,0x20, + 0x25,0x18, + 0x26,0x60, + }, + { + 0xFF,0x01, + 0x24,0x34, + 0x25,0x1c, + 0x26,0x00, + }, + { + 0xFF,0x01, + 0x24,0x3e, + 0x25,0x38, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x48, + 0x25,0x40, + 0x26,0x81, + }, + { + 0xFF,0x01, + 0x24,0x58, + 0x25,0x50, + 0x26,0x92, + }, +}; + +const rt_uint8_t ov2640_sxga_init_reg_tbl[][2]= +{ + {0xff, 0x00}, + {0x2c, 0xff}, + {0x2e, 0xdf}, + {0xff, 0x01}, + {0x3c, 0x32}, + {0x11, 0x00}, + {0x09, 0x02}, + {0x04, 0xD8}, + {0x13, 0xe5}, + {0x14, 0x48}, + {0x2c, 0x0c}, + {0x33, 0x78}, + {0x3a, 0x33}, + {0x3b, 0xfB}, + {0x3e, 0x00}, + {0x43, 0x11}, + {0x16, 0x10}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {0x34, 0xc0}, + {0x36, 0x1a}, + {0x06, 0x88}, + {0x07, 0xc0}, + {0x0d, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {0x48, 0x00}, + {0x5B, 0x00}, + {0x42, 0x03}, + {0x4a, 0x81}, + {0x21, 0x99}, + {0x24, 0x40}, + {0x25, 0x38}, + {0x26, 0x82}, + {0x5c, 0x00}, + {0x63, 0x00}, + {0x46, 0x00}, + {0x0c, 0x3c}, + {0x61, 0x70}, + {0x62, 0x80}, + {0x7c, 0x05}, + {0x20, 0x80}, + {0x28, 0x30}, + {0x6c, 0x00}, + {0x6d, 0x80}, + {0x6e, 0x00}, + {0x70, 0x02}, + {0x71, 0x94}, + {0x73, 0xc1}, + {0x3d, 0x34}, + {0x5a, 0x57}, + {0x12, 0x00}, + {0x17, 0x11}, + {0x18, 0x75}, + {0x19, 0x01}, + {0x1a, 0x97}, + {0x32, 0x36}, + {0x03, 0x0f}, + {0x37, 0x40}, + {0x4f, 0xca}, + {0x50, 0xa8}, + {0x5a, 0x23}, + {0x6d, 0x00}, + {0x6d, 0x38}, + {0xff, 0x00}, + {0xe5, 0x7f}, + {0xf9, 0xc0}, + {0x41, 0x24}, + {0xe0, 0x14}, + {0x76, 0xff}, + {0x33, 0xa0}, + {0x42, 0x20}, + {0x43, 0x18}, + {0x4c, 0x00}, + {0x87, 0xd5}, + {0x88, 0x3f}, + {0xd7, 0x03}, + {0xd9, 0x10}, + {0xd3, 0x82}, + {0xc8, 0x08}, + {0xc9, 0x80}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7c, 0x03}, + {0x7d, 0x48}, + {0x7d, 0x48}, + {0x7c, 0x08}, + {0x7d, 0x20}, + {0x7d, 0x10}, + {0x7d, 0x0e}, + {0x90, 0x00}, + {0x91, 0x0e}, + {0x91, 0x1a}, + {0x91, 0x31}, + {0x91, 0x5a}, + {0x91, 0x69}, + {0x91, 0x75}, + {0x91, 0x7e}, + {0x91, 0x88}, + {0x91, 0x8f}, + {0x91, 0x96}, + {0x91, 0xa3}, + {0x91, 0xaf}, + {0x91, 0xc4}, + {0x91, 0xd7}, + {0x91, 0xe8}, + {0x91, 0x20}, + {0x92, 0x00}, + {0x93, 0x06}, + {0x93, 0xe3}, + {0x93, 0x05}, + {0x93, 0x05}, + {0x93, 0x00}, + {0x93, 0x04}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x96, 0x00}, + {0x97, 0x08}, + {0x97, 0x19}, + {0x97, 0x02}, + {0x97, 0x0c}, + {0x97, 0x24}, + {0x97, 0x30}, + {0x97, 0x28}, + {0x97, 0x26}, + {0x97, 0x02}, + {0x97, 0x98}, + {0x97, 0x80}, + {0x97, 0x00}, + {0x97, 0x00}, + {0xc3, 0xef}, + {0xa4, 0x00}, + {0xa8, 0x00}, + {0xc5, 0x11}, + {0xc6, 0x51}, + {0xbf, 0x80}, + {0xc7, 0x10}, + {0xb6, 0x66}, + {0xb8, 0xA5}, + {0xb7, 0x64}, + {0xb9, 0x7C}, + {0xb3, 0xaf}, + {0xb4, 0x97}, + {0xb5, 0xFF}, + {0xb0, 0xC5}, + {0xb1, 0x94}, + {0xb2, 0x0f}, + {0xc4, 0x5c}, + {0xc0, 0xc8}, + {0xc1, 0x96}, + {0x8c, 0x00}, + {0x86, 0x3d}, + {0x50, 0x00}, + {0x51, 0x90}, + {0x52, 0x2c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x88}, + {0x5a, 0x90}, + {0x5b, 0x2C}, + {0x5c, 0x05}, + {0xd3, 0x02}, + {0xc3, 0xed}, + {0x7f, 0x00}, + {0xda, 0x09}, + {0xe5, 0x1f}, + {0xe1, 0x67}, + {0xe0, 0x00}, + {0xdd, 0x7f}, + {0x05, 0x00}, +}; + +/* SVGA 800*600 */ +const rt_uint8_t ov2640_svga_init_reg_tbl[][2]= +{ + {0xff, 0x00}, + {0x2c, 0xff}, + {0x2e, 0xdf}, + {0xff, 0x01}, + {0x3c, 0x32}, + {0x11, 0x00}, + {0x09, 0x02}, + {0x04, 0xD8}, + {0x13, 0xe5}, + {0x14, 0x48}, + {0x2c, 0x0c}, + {0x33, 0x78}, + {0x3a, 0x33}, + {0x3b, 0xfB}, + {0x3e, 0x00}, + {0x43, 0x11}, + {0x16, 0x10}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {0x34, 0xc0}, + {0x36, 0x1a}, + {0x06, 0x88}, + {0x07, 0xc0}, + {0x0d, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {0x48, 0x00}, + {0x5B, 0x00}, + {0x42, 0x03}, + {0x4a, 0x81}, + {0x21, 0x99}, + {0x24, 0x40}, + {0x25, 0x38}, + {0x26, 0x82}, + {0x5c, 0x00}, + {0x63, 0x00}, + {0x46, 0x22}, + {0x0c, 0x3c}, + {0x61, 0x70}, + {0x62, 0x80}, + {0x7c, 0x05}, + {0x20, 0x80}, + {0x28, 0x30}, + {0x6c, 0x00}, + {0x6d, 0x80}, + {0x6e, 0x00}, + {0x70, 0x02}, + {0x71, 0x94}, + {0x73, 0xc1}, + {0x3d, 0x34}, + {0x5a, 0x57}, + {0x12, 0x40}, + {0x17, 0x11}, + {0x18, 0x43}, + {0x19, 0x00}, + {0x1a, 0x4b}, + {0x32, 0x09}, + {0x37, 0xc0}, + {0x4f, 0xca}, + {0x50, 0xa8}, + {0x5a, 0x23}, + {0x6d, 0x00}, + {0x3d, 0x38}, + {0xff, 0x00}, + {0xe5, 0x7f}, + {0xf9, 0xc0}, + {0x41, 0x24}, + {0xe0, 0x14}, + {0x76, 0xff}, + {0x33, 0xa0}, + {0x42, 0x20}, + {0x43, 0x18}, + {0x4c, 0x00}, + {0x87, 0xd5}, + {0x88, 0x3f}, + {0xd7, 0x03}, + {0xd9, 0x10}, + {0xd3, 0x82}, + {0xc8, 0x08}, + {0xc9, 0x80}, + {0x7c, 0x00}, + {0x7d, 0x00}, + {0x7c, 0x03}, + {0x7d, 0x48}, + {0x7d, 0x48}, + {0x7c, 0x08}, + {0x7d, 0x20}, + {0x7d, 0x10}, + {0x7d, 0x0e}, + {0x90, 0x00}, + {0x91, 0x0e}, + {0x91, 0x1a}, + {0x91, 0x31}, + {0x91, 0x5a}, + {0x91, 0x69}, + {0x91, 0x75}, + {0x91, 0x7e}, + {0x91, 0x88}, + {0x91, 0x8f}, + {0x91, 0x96}, + {0x91, 0xa3}, + {0x91, 0xaf}, + {0x91, 0xc4}, + {0x91, 0xd7}, + {0x91, 0xe8}, + {0x91, 0x20}, + {0x92, 0x00}, + {0x93, 0x06}, + {0x93, 0xe3}, + {0x93, 0x05}, + {0x93, 0x05}, + {0x93, 0x00}, + {0x93, 0x04}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x96, 0x00}, + {0x97, 0x08}, + {0x97, 0x19}, + {0x97, 0x02}, + {0x97, 0x0c}, + {0x97, 0x24}, + {0x97, 0x30}, + {0x97, 0x28}, + {0x97, 0x26}, + {0x97, 0x02}, + {0x97, 0x98}, + {0x97, 0x80}, + {0x97, 0x00}, + {0x97, 0x00}, + {0xc3, 0xed}, + {0xa4, 0x00}, + {0xa8, 0x00}, + {0xc5, 0x11}, + {0xc6, 0x51}, + {0xbf, 0x80}, + {0xc7, 0x10}, + {0xb6, 0x66}, + {0xb8, 0xA5}, + {0xb7, 0x64}, + {0xb9, 0x7C}, + {0xb3, 0xaf}, + {0xb4, 0x97}, + {0xb5, 0xFF}, + {0xb0, 0xC5}, + {0xb1, 0x94}, + {0xb2, 0x0f}, + {0xc4, 0x5c}, + {0xc0, 0x64}, + {0xc1, 0x4B}, + {0x8c, 0x00}, + {0x86, 0x3D}, + {0x50, 0x00}, + {0x51, 0xC8}, + {0x52, 0x96}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x00}, + {0x5a, 0xC8}, + {0x5b, 0x96}, + {0x5c, 0x00}, + {0xd3, 0x02}, + {0xc3, 0xed}, + {0x7f, 0x00}, + {0xda, 0x09}, + {0xe5, 0x1f}, + {0xe1, 0x67}, + {0xe0, 0x00}, + {0xdd, 0x7f}, + {0x05, 0x00}, +}; + +/* Initialization sequence for QVGA resolution (320x240) */ +const unsigned char OV2640_QVGA[][2]= +{ + {0xff, 0x00}, + {0x2c, 0xff}, + {0x2e, 0xdf}, + {0xff, 0x01}, + {0x3c, 0x32}, + {0x11, 0x00}, + {0x09, 0x02}, + {0x04, 0xA8}, + {0x13, 0xe5}, + {0x14, 0x48}, + {0x2c, 0x0c}, + {0x33, 0x78}, + {0x3a, 0x33}, + {0x3b, 0xfB}, + {0x3e, 0x00}, + {0x43, 0x11}, + {0x16, 0x10}, + {0x4a, 0x81}, + {0x21, 0x99}, + {0x24, 0x40}, + {0x25, 0x38}, + {0x26, 0x82}, + {0x5c, 0x00}, + {0x63, 0x00}, + {0x46, 0x3f}, + {0x0c, 0x3c}, + {0x61, 0x70}, + {0x62, 0x80}, + {0x7c, 0x05}, + {0x20, 0x80}, + {0x28, 0x30}, + {0x6c, 0x00}, + {0x6d, 0x80}, + {0x6e, 0x00}, + {0x70, 0x02}, + {0x71, 0x94}, + {0x73, 0xc1}, + {0x3d, 0x34}, + {0x5a, 0x57}, + {0x12, 0x00}, + {0x11, 0x00}, + {0x17, 0x11}, + {0x18, 0x75}, + {0x19, 0x01}, + {0x1a, 0x97}, + {0x32, 0x36}, + {0x03, 0x0f}, + {0x37, 0x40}, + {0x4f, 0xbb}, + {0x50, 0x9c}, + {0x5a, 0x57}, + {0x6d, 0x80}, + {0x6d, 0x38}, + {0x39, 0x02}, + {0x35, 0x88}, + {0x22, 0x0a}, + {0x37, 0x40}, + {0x23, 0x00}, + {0x34, 0xa0}, + {0x36, 0x1a}, + {0x06, 0x02}, + {0x07, 0xc0}, + {0x0d, 0xb7}, + {0x0e, 0x01}, + {0x4c, 0x00}, + {0xff, 0x00}, + {0xe5, 0x7f}, + {0xf9, 0xc0}, + {0x41, 0x24}, + {0xe0, 0x14}, + {0x76, 0xff}, + {0x33, 0xa0}, + {0x42, 0x20}, + {0x43, 0x18}, + {0x4c, 0x00}, + {0x87, 0xd0}, + {0x88, 0x3f}, + {0xd7, 0x03}, + {0xd9, 0x10}, + {0xd3, 0x82}, + {0xc8, 0x08}, + {0xc9, 0x80}, + {0x7d, 0x00}, + {0x7c, 0x03}, + {0x7d, 0x48}, + {0x7c, 0x08}, + {0x7d, 0x20}, + {0x7d, 0x10}, + {0x7d, 0x0e}, + {0x90, 0x00}, + {0x91, 0x0e}, + {0x91, 0x1a}, + {0x91, 0x31}, + {0x91, 0x5a}, + {0x91, 0x69}, + {0x91, 0x75}, + {0x91, 0x7e}, + {0x91, 0x88}, + {0x91, 0x8f}, + {0x91, 0x96}, + {0x91, 0xa3}, + {0x91, 0xaf}, + {0x91, 0xc4}, + {0x91, 0xd7}, + {0x91, 0xe8}, + {0x91, 0x20}, + {0x92, 0x00}, + {0x93, 0x06}, + {0x93, 0xe3}, + {0x93, 0x02}, + {0x93, 0x02}, + {0x93, 0x00}, + {0x93, 0x04}, + {0x93, 0x00}, + {0x93, 0x03}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x93, 0x00}, + {0x96, 0x00}, + {0x97, 0x08}, + {0x97, 0x19}, + {0x97, 0x02}, + {0x97, 0x0c}, + {0x97, 0x24}, + {0x97, 0x30}, + {0x97, 0x28}, + {0x97, 0x26}, + {0x97, 0x02}, + {0x97, 0x98}, + {0x97, 0x80}, + {0x97, 0x00}, + {0x97, 0x00}, + {0xc3, 0xef}, + {0xff, 0x00}, + {0xba, 0xdc}, + {0xbb, 0x08}, + {0xb6, 0x24}, + {0xb8, 0x33}, + {0xb7, 0x20}, + {0xb9, 0x30}, + {0xb3, 0xb4}, + {0xb4, 0xca}, + {0xb5, 0x43}, + {0xb0, 0x5c}, + {0xb1, 0x4f}, + {0xb2, 0x06}, + {0xc7, 0x00}, + {0xc6, 0x51}, + {0xc5, 0x11}, + {0xc4, 0x9c}, + {0xbf, 0x00}, + {0xbc, 0x64}, + {0xa6, 0x00}, + {0xa7, 0x1e}, + {0xa7, 0x6b}, + {0xa7, 0x47}, + {0xa7, 0x33}, + {0xa7, 0x00}, + {0xa7, 0x23}, + {0xa7, 0x2e}, + {0xa7, 0x85}, + {0xa7, 0x42}, + {0xa7, 0x33}, + {0xa7, 0x00}, + {0xa7, 0x23}, + {0xa7, 0x1b}, + {0xa7, 0x74}, + {0xa7, 0x42}, + {0xa7, 0x33}, + {0xa7, 0x00}, + {0xa7, 0x23}, + {0xc0, 0xc8}, + {0xc1, 0x96}, + {0x8c, 0x00}, + {0x86, 0x3d}, + {0x50, 0x92}, + {0x51, 0x90}, + {0x52, 0x2c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x88}, + {0x5a, 0x50}, + {0x5b, 0x3c}, + {0x5c, 0x00}, + {0xd3, 0x04}, + {0x7f, 0x00}, + {0xda, 0x00}, + {0xe5, 0x1f}, + {0xe1, 0x67}, + {0xe0, 0x00}, + {0xdd, 0x7f}, + {0x05, 0x00}, + {0xff, 0x00}, + {0xe0, 0x04}, + {0xc0, 0xc8}, + {0xc1, 0x96}, + {0x86, 0x3d}, + {0x50, 0x92}, + {0x51, 0x90}, + {0x52, 0x2c}, + {0x53, 0x00}, + {0x54, 0x00}, + {0x55, 0x88}, + {0x57, 0x00}, + {0x5a, 0x50}, + {0x5b, 0x3C}, + {0x5c, 0x00}, + {0xd3, 0x08}, + {0xe0, 0x00}, + {0xFF, 0x00}, + {0x05, 0x00}, + {0xDA, 0x08}, + {0xda, 0x09}, + {0x98, 0x00}, + {0x99, 0x00}, + {0x00, 0x00}, +}; + +const rt_uint8_t ov2640_jpeg_reg_tbl[][2]= +{ + {0xff, 0x01}, + {0xe0, 0x14}, + {0xe1, 0x77}, + {0xe5, 0x1f}, + {0xd7, 0x03}, + {0xda, 0x10}, + {0xe0, 0x00}, +}; + +const rt_uint8_t ov2640_rgb565_reg_tbl[][2]= +{ + {0xFF, 0x00}, + {0xDA, 0x09}, + {0xD7, 0x03}, + {0xDF, 0x02}, + {0x33, 0xa0}, + {0x3C, 0x00}, + {0xe1, 0x67}, + + {0xff, 0x01}, + {0xe0, 0x00}, + {0xe1, 0x00}, + {0xe5, 0x00}, + {0xd7, 0x00}, + {0xda, 0x00}, + {0xe0, 0x00}, +}; +const rt_uint8_t ov2640_yuv422_reg_tbl[][2] = +{ + {0xFF, 0x00}, + {0xDA, 0x10}, + {0xD7, 0x03}, + {0xDF, 0x00}, + {0x33, 0x80}, + {0x3C, 0x40}, + {0xe1, 0x77}, + {0x00, 0x00}, +}; + + +#ifdef __cplusplus +} +#endif + +#endif