|
@@ -6,14 +6,21 @@
|
|
|
#include "app_timer.h"
|
|
|
|
|
|
static custome_event ov2640_event;
|
|
|
-APP_TIMER_DEF(ov2640_timer_id);
|
|
|
+static void Set_Ov2640_Queue(OV2640_QUEUE_TYPE type);
|
|
|
+static ov2640_work_e ov2640_work = OV2640_WORK_RST;
|
|
|
|
|
|
+APP_TIMER_DEF(ov2640_timer_id);
|
|
|
static uint32_t ov2640_timer_tick = 0;
|
|
|
static bool ov2640_timer_end = true;
|
|
|
static bool ov2640_timer_stat = false;
|
|
|
|
|
|
-void Set_Ov2640_Queue(OV2640_QUEUE_TYPE type);
|
|
|
+//TWI传输完成标志
|
|
|
+static volatile bool m_xfer_done = false;
|
|
|
+//TWI传输超时标志
|
|
|
+static volatile bool m_xfer_timeout = false;
|
|
|
|
|
|
+static uint8_t OV2640_ReadReg(uint16_t Addr);
|
|
|
+static ret_code_t OV2640_WriteReg(uint16_t Addr, uint8_t Data);
|
|
|
/** @addtogroup
|
|
|
* @{
|
|
|
*/
|
|
@@ -557,25 +564,30 @@ void OV2640_CaptureGpioInit(nrf_drv_gpiote_in_config_t *config,nrfx_gpiote_evt_h
|
|
|
|
|
|
static void ov2640_i2s_done(void)
|
|
|
{
|
|
|
-
|
|
|
+ m_xfer_done = true;
|
|
|
}
|
|
|
|
|
|
static void ov2640_i2s_timeout(void)
|
|
|
{
|
|
|
-
|
|
|
+ m_xfer_timeout = true;
|
|
|
}
|
|
|
|
|
|
-void OV2640_i2s_Init(void)
|
|
|
+void OV2640_i2s_init(void)
|
|
|
{
|
|
|
twim0_init(ov2640_i2s_done, ov2640_i2s_timeout);
|
|
|
}
|
|
|
|
|
|
+void OV2640_i2s_uninit(void)
|
|
|
+{
|
|
|
+ twim0_uinit();
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief Resets the OV2640 camera.
|
|
|
* @param None
|
|
|
* @retval None
|
|
|
*/
|
|
|
-void OV2640_Reset(void)
|
|
|
+static void OV2640_Reset(void)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01);
|
|
|
OV2640_WriteReg(OV2640_SENSOR_COM7, 0x80);
|
|
@@ -586,7 +598,7 @@ void OV2640_Reset(void)
|
|
|
* @param OV2640ID: Pointer to the OV2640 Manufacturer identifier
|
|
|
* @retval None
|
|
|
*/
|
|
|
-void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID)
|
|
|
+static void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01);
|
|
|
OV2640ID->Manufacturer_ID1 = OV2640_ReadReg(OV2640_SENSOR_MIDH);
|
|
@@ -595,51 +607,51 @@ void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID)
|
|
|
OV2640ID->PIDL = OV2640_ReadReg(OV2640_SENSOR_PIDL);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @brief Configures the OV2640 camera in JPEG mode.
|
|
|
- * @param JPEGImageSize: JPEG image size
|
|
|
- * @retval None
|
|
|
- */
|
|
|
-void OV2640_JPEGConfig(void)
|
|
|
+static void ov2640_cmd_jpeg_init(void)
|
|
|
{
|
|
|
- uint32_t i;
|
|
|
-
|
|
|
- OV2640_Reset();
|
|
|
- Delay_nMS(200);
|
|
|
-
|
|
|
- /* Initialize OV2640 */
|
|
|
- for(i=0; i<(sizeof(OV2640_JPEG_INIT)/2); i++)
|
|
|
+ /* Initialize OV2640 */
|
|
|
+ for(int i=0; i<(sizeof(OV2640_JPEG_INIT)/2); i++)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_JPEG_INIT[i][0], OV2640_JPEG_INIT[i][1]);
|
|
|
- Delay_nMS(1);
|
|
|
+ nrf_delay_us(100);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /* Set to output YUV422 */
|
|
|
- for(i=0; i<(sizeof(OV2640_YUV422)/2); i++)
|
|
|
+static void ov2640_cmd_yuv422(void)
|
|
|
+{
|
|
|
+ /* Set to output YUV422 */
|
|
|
+ for(int i=0; i<(sizeof(OV2640_YUV422)/2); i++)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_YUV422[i][0], OV2640_YUV422[i][1]);
|
|
|
- Delay_nMS(1);
|
|
|
+ nrf_delay_us(100);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- OV2640_WriteReg(0xff, 0x01);
|
|
|
+static void ov2640_cmd_jpeg(void)
|
|
|
+{
|
|
|
+ OV2640_WriteReg(0xff, 0x01);
|
|
|
OV2640_WriteReg(0x15, 0x00);
|
|
|
-
|
|
|
- /* Set to output JPEG */
|
|
|
- for(i=0; i<(sizeof(OV2640_JPEG)/2); i++)
|
|
|
+
|
|
|
+ /* Set to output JPEG */
|
|
|
+ for(int i=0; i<(sizeof(OV2640_JPEG)/2); i++)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_JPEG[i][0], OV2640_JPEG[i][1]);
|
|
|
- Delay_nMS(1);
|
|
|
+ nrf_delay_us(100);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- Delay_nMS(100);
|
|
|
-
|
|
|
- for(i=0; i<(sizeof(OV2640_800x600_JPEG)/2); i++)
|
|
|
+/**
|
|
|
+ * @brief Configures the OV2640 camera in JPEG mode.
|
|
|
+ * @param JPEGImageSize: JPEG image size
|
|
|
+ * @retval None
|
|
|
+ */
|
|
|
+void OV2640_JPEGConfig(void)
|
|
|
+{
|
|
|
+ for(int i=0; i<(sizeof(OV2640_800x600_JPEG)/2); i++)
|
|
|
{
|
|
|
OV2640_WriteReg(OV2640_800x600_JPEG[i][0], OV2640_800x600_JPEG[i][1]);
|
|
|
- Delay_nMS(1);
|
|
|
+ nrf_delay_us(100);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -715,7 +727,8 @@ void SCCB_WriteRegs(const uint8_t* pbuf)
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- OV2640_WriteReg(*pbuf++, *pbuf++);
|
|
|
+ OV2640_WriteReg(*pbuf, *(pbuf+1));
|
|
|
+ pbuf += 2;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -815,17 +828,27 @@ void OV2640_ContrastConfig(uint8_t value1, uint8_t value2)
|
|
|
* @retval 0x00 if write operation is OK.
|
|
|
* 0xFF if timeout condition occured (device not connected or bus error).
|
|
|
*/
|
|
|
-uint8_t OV2640_WriteReg(uint16_t Addr, uint8_t Data)
|
|
|
+static ret_code_t OV2640_WriteReg(uint16_t Addr, uint8_t Data)
|
|
|
{
|
|
|
uint8_t sdata[3] = {0};
|
|
|
|
|
|
memcpy(sdata, &Addr, 2);
|
|
|
sdata[2] = Data;
|
|
|
|
|
|
- nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 3, true);
|
|
|
-
|
|
|
+ m_xfer_done = false;
|
|
|
+ nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 3, false);
|
|
|
+ while((m_xfer_done == false) && (m_xfer_timeout == false))
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m_xfer_done == false)
|
|
|
+ {
|
|
|
+ return NRF_ERROR_TIMEOUT;
|
|
|
+ }
|
|
|
+
|
|
|
/* If operation is OK, return 0 */
|
|
|
- return 0;
|
|
|
+ return NRF_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -834,12 +857,36 @@ uint8_t OV2640_WriteReg(uint16_t Addr, uint8_t Data)
|
|
|
* @retval data read from the specific register or 0xFF if timeout condition
|
|
|
* occured.
|
|
|
*/
|
|
|
-uint8_t OV2640_ReadReg(uint16_t Addr)
|
|
|
+static uint8_t OV2640_ReadReg(uint16_t Addr)
|
|
|
{
|
|
|
uint8_t recv_data = 0;
|
|
|
- nrf_drv_twim0_rx(OV2640_DEVICE_WRITE_ADDRESS, recv_data, 1);
|
|
|
+ uint8_t sdata[2] = {0};
|
|
|
+
|
|
|
+ memcpy(sdata, &Addr, 2);
|
|
|
+ m_xfer_done = false;
|
|
|
+ nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 2, true);
|
|
|
+ while((m_xfer_done == false) && (m_xfer_timeout == false))
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m_xfer_done == false)
|
|
|
+ {
|
|
|
+ return NRF_ERROR_TIMEOUT;
|
|
|
+ }
|
|
|
+
|
|
|
+ nrf_drv_twim0_rx(OV2640_DEVICE_WRITE_ADDRESS, &recv_data, 1);
|
|
|
+ while((m_xfer_done == false) && (m_xfer_timeout == false))
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if(m_xfer_done == false)
|
|
|
+ {
|
|
|
+ return NRF_ERROR_TIMEOUT;
|
|
|
+ }
|
|
|
/* return the read data */
|
|
|
- return Data;
|
|
|
+ return recv_data;
|
|
|
}
|
|
|
|
|
|
static uint8_t get_ov2640_data(void)
|
|
@@ -881,16 +928,96 @@ static uint8_t get_ov2640_data(void)
|
|
|
return data;
|
|
|
}
|
|
|
|
|
|
-void ov2640_init(void)
|
|
|
+//void ov2640_init(void)
|
|
|
+//{
|
|
|
+
|
|
|
+// OV2640_ReadID(&OV2640_Camera_ID); //读取OV2640ID,测试硬件,依次为:0x7F,0xA2,0x26,0x42
|
|
|
+// OV2640_JPEGConfig(JPEG_320x240); //配置OV2640输出320*240像素的JPG图片
|
|
|
+//
|
|
|
+// OV2640_BrightnessConfig(0x20);
|
|
|
+// OV2640_AutoExposure(2);
|
|
|
+//}
|
|
|
+
|
|
|
+static void ov2640_pro(void)
|
|
|
+{
|
|
|
+ switch(ov2640_work)
|
|
|
+ {
|
|
|
+ case OV2640_WORK_I2C_INIT:{
|
|
|
+ OV2640_i2s_init();
|
|
|
+ ov2640_work = OV2640_WORK_RST;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_RST:{
|
|
|
+ OV2640_Reset();
|
|
|
+ ov2640_work = OV2640_WORK_JPEG_INIT;
|
|
|
+ ov2640_timers_work(100);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_JPEG_INIT:{
|
|
|
+ ov2640_cmd_jpeg_init();
|
|
|
+ ov2640_work = OV2640_WORK_YUV422;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_YUV422:{
|
|
|
+ ov2640_cmd_yuv422();
|
|
|
+ ov2640_work = OV2640_WORK_JPEG;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_JPEG:{
|
|
|
+ ov2640_cmd_jpeg();
|
|
|
+ ov2640_work = OV2640_WORK_JPEGCONFIG;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_JPEGCONFIG:{
|
|
|
+ OV2640_JPEGConfig();
|
|
|
+ ov2640_work = OV2640_WORK_BNCONFIG;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_BNCONFIG:{
|
|
|
+ OV2640_BrightnessConfig(0x20);
|
|
|
+ ov2640_work = OV2640_WORK_AUTOEXP;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_AUTOEXP:{
|
|
|
+ OV2640_AutoExposure(2);
|
|
|
+ ov2640_work = OV2640_WORK_I2C_UNINIT;
|
|
|
+ ov2640_timers_work(1);
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_VSYNC:{
|
|
|
+
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_PCLK:{
|
|
|
+
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_HREF:{
|
|
|
+
|
|
|
+ }break;
|
|
|
+ case OV2640_WORK_I2C_UNINIT:{
|
|
|
+ OV2640_i2s_uninit();
|
|
|
+ ov2640_work = OV2640_WORK_I2C_INIT;
|
|
|
+ }break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void ov2640_queue(void *p_event_data, uint16_t event_size)
|
|
|
{
|
|
|
- OV2640_HW_Init(); //IIC初始化
|
|
|
- OV2640_ReadID(&OV2640_Camera_ID); //读取OV2640ID,测试硬件,依次为:0x7F,0xA2,0x26,0x42
|
|
|
- OV2640_JPEGConfig(JPEG_320x240); //配置OV2640输出320*240像素的JPG图片
|
|
|
- //设置自动曝光和白平衡
|
|
|
- OV2640_BrightnessConfig(0x20);
|
|
|
- OV2640_AutoExposure(2);
|
|
|
+ custome_event *evt = (custome_event*)p_event_data;
|
|
|
+ if((ov2640_event.flag & (1 << OV2640_QUEUE_INT)) != 0)
|
|
|
+ {
|
|
|
+ ov2640_pro();
|
|
|
+ ov2640_event.flag &= (~(1 << OV2640_QUEUE_INT));
|
|
|
+ }
|
|
|
+ if((ov2640_event.flag & (1 << OV2640_QUEUE_TIME)) != 0)
|
|
|
+ {
|
|
|
+ ov2640_pro();
|
|
|
+ ov2640_event.flag &= (~(1 << OV2640_QUEUE_TIME));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+static void Set_Ov2640_Queue(OV2640_QUEUE_TYPE type)
|
|
|
+{
|
|
|
+ ov2640_event.flag |= (1<<type);
|
|
|
+ ret_code_t err_code = app_sched_event_put(&ov2640_event, sizeof(ov2640_event), ov2640_queue);
|
|
|
+}
|
|
|
|
|
|
|
|
|
/**
|