porkling 2 éve
szülő
commit
504432519b

+ 22 - 26
std/camera/camera.c

@@ -8,37 +8,33 @@ static const char *TAG = "camera";
 camera_fb_t *pic;
 
 static camera_config_t camera_config = {
-	.pin_pwdn = -1,
-	.pin_reset = CONFIG_CAM_RST_GPIO,
-	.pin_xclk = CONFIG_CAM_XCLK_GPIO,
-	.pin_sscb_sda = CONFIG_CAM_SDA_GPIO,
-	.pin_sscb_scl = CONFIG_CAM_SCL_GPIO,
-
-	.pin_d7 = CONFIG_CAM_D7_GPIO,
-	.pin_d6 = CONFIG_CAM_D6_GPIO,
-	.pin_d5 = CONFIG_CAM_D5_GPIO,
-	.pin_d4 = CONFIG_CAM_D4_GPIO,
-	.pin_d3 = CONFIG_CAM_D3_GPIO,
-	.pin_d2 = CONFIG_CAM_D2_GPIO,
-	.pin_d1 = CONFIG_CAM_D1_GPIO,
-	.pin_d0 = CONFIG_CAM_D0_GPIO,
-	.pin_vsync = CONFIG_CAM_VSYNC_GPIO,
-	.pin_href = CONFIG_CAM_HREF_GPIO,
-	.pin_pclk = CONFIG_CAM_PCLK_GPIO,
+	.pin_pwdn 		= -1,
+	.pin_reset 		= CAM_RST_PIN,
+	.pin_xclk 		= CAM_XCLK_PIN,
+	.pin_sscb_sda = CAM_SDA_PIN,
+	.pin_sscb_scl = CAM_SCL_PIN,
+
+	.pin_d7 			= CAM_D7_PIN,
+	.pin_d6 			= CAM_D6_PIN,
+	.pin_d5 			= CAM_D5_PIN,
+	.pin_d4 			= CAM_D4_PIN,
+	.pin_d3 			= CAM_D3_PIN,
+	.pin_d2 			= CAM_D2_PIN,
+	.pin_d1 			= CAM_D1_PIN,
+	.pin_d0 			= CAM_D0_PIN,
+	.pin_vsync 		= CAM_VSYNC_PIN,
+	.pin_href 		= CAM_HREF_PIN,
+	.pin_pclk 		= CAM_PCLK_PIN,
 
 	//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
 	.xclk_freq_hz = CONFIG_CAM_XCLK_FREQ,
-#if CONFIG_CAM_XCLK_GPIO > 0
-    // .ledc_timer = LEDC_TIMER(CONFIG_CAM_XCLK_LEDC_TIMER),
-    // .ledc_channel = LEDC_CHANNEL(CONFIG_CAM_XCLK_LEDC_CHANNEL),
-#endif
 
-	.pixel_format = PIXFORMAT_JPEG,    //YUV422,GRAYSCALE,RGB565,JPEG
-	.frame_size = FRAMESIZE_SVGA,      //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
+	.pixel_format = PIXFORMAT_JPEG,    		//YUV422,GRAYSCALE,RGB565,JPEG
+	.frame_size 	= FRAMESIZE_SVGA,      	//QQVGA-UXGA Do not use sizes above QVGA when not JPEG
 
-	.jpeg_quality = 12, //0-63 lower number means higher quality
-	.fb_count = 1,       //if more than one, i2s runs in continuous mode. Use only with JPEG
-	.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
+	.jpeg_quality = JPG_QUALITY, 					//0-63 lower number means higher quality
+	.fb_count 		= 1,       							//if more than one, i2s runs in continuous mode. Use only with JPEG
+	.grab_mode 		= CAMERA_GRAB_WHEN_EMPTY,
 };
 
 static void camera_task(void)

+ 3 - 3
std/camera/driver/private_include/xclk.h

@@ -1,9 +1,9 @@
 #pragma once
 
-#include "esp_system.h"
+#include "define.h"
 
-esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz);
+int xclk_timer_conf(int ledc_timer, int xclk_freq_hz);
 
-esp_err_t camera_enable_out_clock();
+int camera_enable_out_clock();
 
 void camera_disable_out_clock();

+ 895 - 603
std/camera/sensors/ov2640.c

@@ -1,612 +1,904 @@
+/* Includes ------------------------------------------------------------------*/
+#include "ov2640.h"
+#include "nrf_drv_gpiote.h"
+#include "app_scheduler.h"
+#include "user_twim.h"
+#include "app_timer.h"
+
+static custome_event ov2640_event;
+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);
+
+/** @addtogroup 
+  * @{
+  */
+
+/** @addtogroup DCMI_Camera
+  * @{
+  */ 
+
+/* Exported types ------------------------------------------------------------*/
+/* Camera devices enumeration */
+
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+const unsigned char OV2640_JPEG_INIT[][2]=
+{
+  0xff, 0x00,
+  0x2c, 0xff,
+  0x2e, 0xdf,
+  0xff, 0x01,
+  0x3c, 0x32,
+  0x11, 0x00,
+  0x09, 0x02,
+  0x04, 0x28,
+  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,
+  0x61, 0x70,
+  0x62, 0x80,
+  0x7c, 0x05,
+  0x20, 0x80,
+  0x28, 0x30,
+  0x6c, 0x00,
+  0x6d, 0x80,
+  0x6e, 0x00,
+  0x70, 0x02,
+  0x71, 0x94,
+  0x73, 0xc1,
+  0x12, 0x40,//0x40
+  0x17, 0x11,
+  0x18, 0x43,
+  0x19, 0x00,
+  0x1a, 0x4b,
+  0x32, 0x09,
+  0x37, 0xc0,
+  0x4f, 0x60,
+  0x50, 0xa8,
+  0x6d, 0x00,
+  0x3d, 0x38,
+  0x46, 0x3f,
+  0x4f, 0x60,
+  0x0c, 0x3c,
+  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, 0x7f,
+  0xc3, 0xed,
+  0x7f, 0x00,
+  0xda, 0x00,
+  0xe5, 0x1f,
+  0xe1, 0x67,
+  0xe0, 0x00,
+  0xdd, 0x7f,
+  0x05, 0x00,
+
+  0x12, 0x40,//0x40
+  0xd3, 0x7f,
+  0xc0, 0x16,
+  0xC1, 0x12,
+  0x8c, 0x00,
+  0x86, 0x3d,
+  0x50, 0x00,
+  0x51, 0x2C,
+  0x52, 0x24,
+  0x53, 0x00,
+  0x54, 0x00,
+  0x55, 0x00,
+  0x5A, 0x2c,
+  0x5b, 0x24,
+  0x5c, 0x00,
+};
+
+const unsigned char OV2640_YUV422[][2]= 
+{
+  0xFF, 0x00,
+  0x05, 0x00,
+  0xDA, 0x10,
+  0xD7, 0x03,
+  0xDF, 0x00,
+  0x33, 0x80,
+  0x3C, 0x40,
+  0xe1, 0x77,
+  0x00, 0x00,
+};
+
+const unsigned char OV2640_JPEG[][2]=
+{
+  0xe0, 0x14,
+  0xe1, 0x77,
+  0xe5, 0x1f,
+  0xd7, 0x03,
+  0xda, 0x10,
+  0xe0, 0x00,
+  0xFF, 0x01,
+  0x04, 0x08,
+};
+
+/* JPG 320x240 */
+const unsigned char OV2640_800x600_JPEG[][2]=
+{
+	{0xff, 0x01},
+  {0x11, 0x01},
+  {0x12, 0x00}, // Bit[6:4]: Resolution selection//0x02为彩条
+  {0x17, 0x11}, // HREFST[10:3]
+  {0x18, 0x75}, // HREFEND[10:3]
+  {0x32, 0x36}, // Bit[5:3]: HREFEND[2:0]; Bit[2:0]: HREFST[2:0]
+  {0x19, 0x01}, // VSTRT[9:2]
+  {0x1a, 0x97}, // VEND[9:2]
+  {0x03, 0x0f}, // Bit[3:2]: VEND[1:0]; Bit[1:0]: VSTRT[1:0]
+  {0x37, 0x40},
+  {0x4f, 0xbb},
+  {0x50, 0x9c},
+  {0x5a, 0x57},
+  {0x6d, 0x80},
+  {0x3d, 0x34},
+  {0x39, 0x02},
+  {0x35, 0x88},
+  {0x22, 0x0a},
+  {0x37, 0x40},
+  {0x34, 0xa0},
+  {0x06, 0x02},
+  {0x0d, 0xb7},
+  {0x0e, 0x01},
+  
+  ////////////////
+  /*
+  //176*144
+   0xff,      0x00,
+      0xc0,      0xC8,
+      0xc1,      0x96,
+      0x8c,      0x00,
+      0x86,      0x3D,
+      0x50,      0x9B,
+      0x51,      0x90,
+      0x52,      0x2C,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x5a,      0x2C,
+      0x5b,      0x24,
+      0x5c,      0x00,
+      0xd3,      0x7F,
+	  ////////////
+	  */
+	  
+		/*
+	 ////////////////
+	 //320*240
+	  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,      0x7F,
+      0xe0,      0x00,
+	  ///////////////////
+	  */
+  /*
+0xff,      0x00,
+      0xe0,      0x04,
+      0xc0,      0xc8,
+      0xc1,      0x96,
+      0x86,      0x35,
+      0x50,      0x92,
+      0x51,      0x90,
+      0x52,      0x2c,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x57,      0x00,
+      0x5a,      0x58,
+      0x5b,      0x48,
+      0x5c,      0x00,
+      0xd3,      0x08,
+      0xe0,      0x00
+*/
 /*
- * This file is part of the OpenMV project.
- * Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
- * This work is licensed under the MIT license, see the file LICENSE for details.
- *
- * OV2640 driver.
+//640*480	  
+ 	  0xff,      0x00,
+      0xe0,      0x04,
+      0xc0,      0xc8,
+      0xc1,      0x96,
+      0x86,      0x3d,
+      0x50,      0x89,
+      0x51,      0x90,
+      0x52,      0x2c,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x57,      0x00,
+      0x5a,      0xa0,
+      0x5b,      0x78,
+      0x5c,      0x00,
+      0xd3,      0x04,
+      0xe0,      0x00
+	  */
+	  /////////////////////
+	  
+	  //800*600
+	  0xff,      0x00,
+      0xe0,      0x04,
+      0xc0,      0xc8,
+      0xc1,      0x96,
+      0x86,      0x35,
+      0x50,      0x89,
+      0x51,      0x90,
+      0x52,      0x2c,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x57,      0x00,
+      0x5a,      0xc8,
+      0x5b,      0x96,
+      0x5c,      0x00,
+      0xd3,      0x02,
+      0xe0,      0x00
+	  
+	  /*
+	  //1280*1024
+	  
+	  0xff,      0x00,
+      0xe0,      0x04,
+      0xc0,      0xc8,
+      0xc1,      0x96,
+      0x86,      0x3d,
+      0x50,      0x00,
+      0x51,      0x90,
+      0x52,      0x2c,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x57,      0x00,
+      0x5a,      0x40,
+      0x5b,      0xf0,
+      0x5c,      0x01,
+      0xd3,      0x02,
+      0xe0,      0x00
+	  */
+	  /*
+	  /////////////////////
+	  //1600*1200
+	  
+	  0xff,      0x00,
+      0xe0,      0x04,
+      0xc0,      0xc8,
+      0xc1,      0x96,
+      0x86,      0x3d,
+      0x50,      0x00,
+      0x51,      0x90,
+      0x52,      0x2c,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x57,      0x00,
+      0x5a,      0x90,
+      0x5b,      0x2C,
+      0x5c,      0x05,//bit2->1;bit[1:0]->1
+      0xd3,      0x02,
+      0xe0,      0x00
+	  /////////////////////
+	  */
+	  /*
+	  //1024*768
+	   0xff,      0x00,
+      0xc0,      0xC8,
+      0xc1,      0x96,
+      0x8c,      0x00,
+      0x86,      0x3D,
+      0x50,      0x00,
+      0x51,      0x90,
+      0x52,      0x2C,
+      0x53,      0x00,
+      0x54,      0x00,
+      0x55,      0x88,
+      0x5a,      0x00,
+      0x5b,      0xC0,
+      0x5c,      0x01,
+      0xd3,      0x02
+	  */
+};
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+//启动毫秒计时应用定时器。启动后,即开始产生毫秒计时,也就是提供了一个以毫秒为单位的计时基准
+static void ov2640_timers_stop(void)
+{
+	if(ov2640_timer_stat==true)
+	{
+		ret_code_t err_code = app_timer_stop(ov2640_timer_id);
+		APP_ERROR_CHECK(err_code);
+		ov2640_timer_stat=false;
+	}
+}
+
+//启动毫秒计时应用定时器。启动后,即开始产生毫秒计时,也就是提供了一个以毫秒为单位的计时基准
+static void ov2640_timers_start(uint32_t ms)
+{
+	ret_code_t err_code = app_timer_start(ov2640_timer_id, APP_TIMER_TICKS(ms), NULL);
+	APP_ERROR_CHECK(err_code);
+	ov2640_timer_stat=true;
+}
+
+static void ov2640_timers_work(uint32_t ms)
+{
+	ov2640_timers_stop();
+	if(ov2640_timer_stat==false)
+	{
+		if(ms>APP_TIMER_SAFE_WINDOW_MS)
+		{
+			ov2640_timers_start(APP_TIMER_SAFE_WINDOW_MS);
+			ov2640_timer_end=false;
+			ov2640_timer_tick=ms-APP_TIMER_SAFE_WINDOW_MS;
+		}
+		else{
+			ov2640_timers_start(ms);
+			ov2640_timer_end=true;
+			ov2640_timer_tick=0;
+		}		
+	}
+}
+
+//ov2640定时器回调
+static void ov2640_timers_handler(void * p_context)
+{
+	UNUSED_PARAMETER(p_context);
+	ov2640_timer_stat=false;
+	if(ov2640_timer_end==true)
+	{
+		Set_Ov2640_Queue(OV2640_QUEUE_TIME);
+	}
+	else{
+		ov2640_timers_work(ov2640_timer_tick);
+	}
+}
+
+/**@brief Function for the Timer initialization.
  *
+ * @details Initializes the timer module.
  */
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include "sccb.h"
-#include "xclk.h"
-#include "ov2640.h"
-#include "ov2640_regs.h"
-#include "ov2640_settings.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-
-#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
-#include "esp32-hal-log.h"
-#else
-#include "esp_log.h"
-static const char* TAG = "ov2640";
-#endif
-
-static volatile ov2640_bank_t reg_bank = BANK_MAX;
-static int set_bank(sensor_t *sensor, ov2640_bank_t bank)
-{
-    int res = 0;
-    if (bank != reg_bank) {
-        reg_bank = bank;
-        res = SCCB_Write(sensor->slv_addr, BANK_SEL, bank);
-    }
-    return res;
-}
-
-static int write_regs(sensor_t *sensor, const uint8_t (*regs)[2])
-{
-    int i=0, res = 0;
-    while (regs[i][0]) {
-        if (regs[i][0] == BANK_SEL) {
-            res = set_bank(sensor, regs[i][1]);
-        } else {
-            res = SCCB_Write(sensor->slv_addr, regs[i][0], regs[i][1]);
-        }
-        if (res) {
-            return res;
-        }
-        i++;
-    }
-    return res;
-}
-
-static int write_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg, uint8_t value)
-{
-    int ret = set_bank(sensor, bank);
-    if(!ret) {
-        ret = SCCB_Write(sensor->slv_addr, reg, value);
-    }
-    return ret;
-}
-
-static int set_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value)
-{
-    int ret = 0;
-    uint8_t c_value, new_value;
-
-    ret = set_bank(sensor, bank);
-    if(ret) {
-        return ret;
-    }
-    c_value = SCCB_Read(sensor->slv_addr, reg);
-    new_value = (c_value & ~(mask << offset)) | ((value & mask) << offset);
-    ret = SCCB_Write(sensor->slv_addr, reg, new_value);
-    return ret;
-}
-
-static int read_reg(sensor_t *sensor, ov2640_bank_t bank, uint8_t reg)
-{
-    if(set_bank(sensor, bank)){
-        return 0;
-    }
-    return SCCB_Read(sensor->slv_addr, reg);
-}
-
-static uint8_t get_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t offset, uint8_t mask)
-{
-    return (read_reg(sensor, bank, reg) >> offset) & mask;
-}
-
-static int write_reg_bits(sensor_t *sensor, uint8_t bank, uint8_t reg, uint8_t mask, int enable)
-{
-    return set_reg_bits(sensor, bank, reg, 0, mask, enable?mask:0);
-}
-
-#define WRITE_REGS_OR_RETURN(regs) ret = write_regs(sensor, regs); if(ret){return ret;}
-#define WRITE_REG_OR_RETURN(bank, reg, val) ret = write_reg(sensor, bank, reg, val); if(ret){return ret;}
-#define SET_REG_BITS_OR_RETURN(bank, reg, offset, mask, val) ret = set_reg_bits(sensor, bank, reg, offset, mask, val); if(ret){return ret;}
-
-static int reset(sensor_t *sensor)
-{
-    int ret = 0;
-    WRITE_REG_OR_RETURN(BANK_SENSOR, COM7, COM7_SRST);
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-    WRITE_REGS_OR_RETURN(ov2640_settings_cif);
-    return ret;
-}
-
-static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
-{
-    int ret = 0;
-    sensor->pixformat = pixformat;
-    switch (pixformat) {
-    case PIXFORMAT_RGB565:
-    case PIXFORMAT_RGB888:
-        WRITE_REGS_OR_RETURN(ov2640_settings_rgb565);
-        break;
-    case PIXFORMAT_YUV422:
-    case PIXFORMAT_GRAYSCALE:
-        WRITE_REGS_OR_RETURN(ov2640_settings_yuv422);
-        break;
-    case PIXFORMAT_JPEG:
-        WRITE_REGS_OR_RETURN(ov2640_settings_jpeg3);
-        break;
-    default:
-        ret = -1;
-        break;
-    }
-    if(!ret) {
-        vTaskDelay(10 / portTICK_PERIOD_MS);
-    }
-
-    return ret;
-}
-
-static int set_window(sensor_t *sensor, ov2640_sensor_mode_t mode, int offset_x, int offset_y, int max_x, int max_y, int w, int h){
-    int ret = 0;
-    const uint8_t (*regs)[2];
-    ov2640_clk_t c;
-    c.reserved = 0;
-
-    max_x /= 4;
-    max_y /= 4;
-    w /= 4;
-    h /= 4;
-    uint8_t win_regs[][2] = {
-        {BANK_SEL, BANK_DSP},
-        {HSIZE, max_x & 0xFF},
-        {VSIZE, max_y & 0xFF},
-        {XOFFL, offset_x & 0xFF},
-        {YOFFL, offset_y & 0xFF},
-        {VHYX, ((max_y >> 1) & 0X80) | ((offset_y >> 4) & 0X70) | ((max_x >> 5) & 0X08) | ((offset_x >> 8) & 0X07)},
-        {TEST, (max_x >> 2) & 0X80},
-        {ZMOW, (w)&0xFF},
-        {ZMOH, (h)&0xFF},
-        {ZMHH, ((h>>6)&0x04)|((w>>8)&0x03)},
-        {0, 0}
-    };
-
-    if (sensor->pixformat == PIXFORMAT_JPEG) {
-        c.clk_2x = 0;
-        c.clk_div = 0;
-        c.pclk_auto = 0;
-        c.pclk_div = 8;
-        if(mode == OV2640_MODE_UXGA) {
-            c.pclk_div = 12;
-        }
-        // if (sensor->xclk_freq_hz == 16000000) {
-        //     c.pclk_div = c.pclk_div / 2;
-        // }
-    } else {
-#if CONFIG_IDF_TARGET_ESP32
-        c.clk_2x = 0;
-#else
-        c.clk_2x = 1;
-#endif
-        c.clk_div = 7;
-        c.pclk_auto = 1;
-        c.pclk_div = 8;
-        if (mode == OV2640_MODE_CIF) {
-            c.clk_div = 3;
-        } else if(mode == OV2640_MODE_UXGA) {
-            c.pclk_div = 12;
-        }
-    }
-    ESP_LOGI(TAG, "Set PLL: clk_2x: %u, clk_div: %u, pclk_auto: %u, pclk_div: %u", c.clk_2x, c.clk_div, c.pclk_auto, c.pclk_div);
-
-    if (mode == OV2640_MODE_CIF) {
-        regs = ov2640_settings_to_cif;
-    } else if (mode == OV2640_MODE_SVGA) {
-        regs = ov2640_settings_to_svga;
-    } else {
-        regs = ov2640_settings_to_uxga;
-    }
-
-    WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_BYPAS);
-    WRITE_REGS_OR_RETURN(regs);
-    WRITE_REGS_OR_RETURN(win_regs);
-    WRITE_REG_OR_RETURN(BANK_SENSOR, CLKRC, c.clk);
-    WRITE_REG_OR_RETURN(BANK_DSP, R_DVP_SP, c.pclk);
-    WRITE_REG_OR_RETURN(BANK_DSP, R_BYPASS, R_BYPASS_DSP_EN);
-
-    vTaskDelay(10 / portTICK_PERIOD_MS);
-    //required when changing resolution
-    set_pixformat(sensor, sensor->pixformat);
-
-    return ret;
-}
-
-static int set_framesize(sensor_t *sensor, framesize_t framesize)
-{
-    int ret = 0;
-    uint16_t w = resolution[framesize].width;
-    uint16_t h = resolution[framesize].height;
-    aspect_ratio_t ratio = resolution[framesize].aspect_ratio;
-    uint16_t max_x = ratio_table[ratio].max_x;
-    uint16_t max_y = ratio_table[ratio].max_y;
-    uint16_t offset_x = ratio_table[ratio].offset_x;
-    uint16_t offset_y = ratio_table[ratio].offset_y;
-    ov2640_sensor_mode_t mode = OV2640_MODE_UXGA;
-
-    sensor->status.framesize = framesize;
-
-
-
-    if (framesize <= FRAMESIZE_CIF) {
-        mode = OV2640_MODE_CIF;
-        max_x /= 4;
-        max_y /= 4;
-        offset_x /= 4;
-        offset_y /= 4;
-        if(max_y > 296){
-            max_y = 296;
-        }
-    } else if (framesize <= FRAMESIZE_SVGA) {
-        mode = OV2640_MODE_SVGA;
-        max_x /= 2;
-        max_y /= 2;
-        offset_x /= 2;
-        offset_y /= 2;
-    }
-
-    ret = set_window(sensor, mode, offset_x, offset_y, max_x, max_y, w, h);
-    return ret;
-}
-
-static int set_contrast(sensor_t *sensor, int level)
-{
-    int ret=0;
-    level += 3;
-    if (level <= 0 || level > NUM_CONTRAST_LEVELS) {
-        return -1;
-    }
-    sensor->status.contrast = level-3;
-    for (int i=0; i<7; i++) {
-        WRITE_REG_OR_RETURN(BANK_DSP, contrast_regs[0][i], contrast_regs[level][i]);
-    }
-    return ret;
-}
-
-static int set_brightness(sensor_t *sensor, int level)
-{
-    int ret=0;
-    level += 3;
-    if (level <= 0 || level > NUM_BRIGHTNESS_LEVELS) {
-        return -1;
-    }
-    sensor->status.brightness = level-3;
-    for (int i=0; i<5; i++) {
-        WRITE_REG_OR_RETURN(BANK_DSP, brightness_regs[0][i], brightness_regs[level][i]);
-    }
-    return ret;
-}
-
-static int set_saturation(sensor_t *sensor, int level)
-{
-    int ret=0;
-    level += 3;
-    if (level <= 0 || level > NUM_SATURATION_LEVELS) {
-        return -1;
-    }
-    sensor->status.saturation = level-3;
-    for (int i=0; i<5; i++) {
-        WRITE_REG_OR_RETURN(BANK_DSP, saturation_regs[0][i], saturation_regs[level][i]);
-    }
-    return ret;
-}
-
-static int set_special_effect(sensor_t *sensor, int effect)
-{
-    int ret=0;
-    effect++;
-    if (effect <= 0 || effect > NUM_SPECIAL_EFFECTS) {
-        return -1;
-    }
-    sensor->status.special_effect = effect-1;
-    for (int i=0; i<5; i++) {
-        WRITE_REG_OR_RETURN(BANK_DSP, special_effects_regs[0][i], special_effects_regs[effect][i]);
-    }
-    return ret;
-}
-
-static int set_wb_mode(sensor_t *sensor, int mode)
-{
-    int ret=0;
-    if (mode < 0 || mode > NUM_WB_MODES) {
-        return -1;
-    }
-    sensor->status.wb_mode = mode;
-    SET_REG_BITS_OR_RETURN(BANK_DSP, 0XC7, 6, 1, mode?1:0);
-    if(mode) {
-        for (int i=0; i<3; i++) {
-            WRITE_REG_OR_RETURN(BANK_DSP, wb_modes_regs[0][i], wb_modes_regs[mode][i]);
-        }
-    }
-    return ret;
-}
-
-static int set_ae_level(sensor_t *sensor, int level)
-{
-    int ret=0;
-    level += 3;
-    if (level <= 0 || level > NUM_AE_LEVELS) {
-        return -1;
-    }
-    sensor->status.ae_level = level-3;
-    for (int i=0; i<3; i++) {
-        WRITE_REG_OR_RETURN(BANK_SENSOR, ae_levels_regs[0][i], ae_levels_regs[level][i]);
-    }
-    return ret;
-}
-
-static int set_quality(sensor_t *sensor, int quality)
-{
-    if(quality < 0) {
-        quality = 0;
-    } else if(quality > 63) {
-        quality = 63;
-    }
-    sensor->status.quality = quality;
-    return write_reg(sensor, BANK_DSP, QS, quality);
-}
-
-static int set_agc_gain(sensor_t *sensor, int gain)
-{
-    if(gain < 0) {
-        gain = 0;
-    } else if(gain > 30) {
-        gain = 30;
-    }
-    sensor->status.agc_gain = gain;
-    return write_reg(sensor, BANK_SENSOR, GAIN, agc_gain_tbl[gain]);
-}
-
-static int set_gainceiling_sensor(sensor_t *sensor, gainceiling_t gainceiling)
-{
-    sensor->status.gainceiling = gainceiling;
-    //return write_reg(sensor, BANK_SENSOR, COM9, COM9_AGC_SET(gainceiling));
-    return set_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7, gainceiling);
-}
-
-static int set_aec_value(sensor_t *sensor, int value)
-{
-    if(value < 0) {
-        value = 0;
-    } else if(value > 1200) {
-        value = 1200;
-    }
-    sensor->status.aec_value = value;
-    return set_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3, value & 0x3)
-           || write_reg(sensor, BANK_SENSOR, AEC, (value >> 2) & 0xFF)
-           || set_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F, value >> 10);
-}
-
-static int set_aec2(sensor_t *sensor, int enable)
-{
-    sensor->status.aec2 = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1, enable?0:1);
-}
 
-static int set_colorbar(sensor_t *sensor, int enable)
+void ov2640_timers_init(void)
 {
-    sensor->status.colorbar = enable;
-    return write_reg_bits(sensor, BANK_SENSOR, COM7, COM7_COLOR_BAR, enable?1:0);
+	// Initialize timer module, making it use the scheduler
+//	ret_code_t err_code = app_timer_init();
+//	APP_ERROR_CHECK(err_code);
+	
+	//创建一个应用定时器,产生秒计时。模式:周期性应用定时器,注册应用定时器事件句柄
+	ret_code_t err_code = app_timer_create(&ov2640_timer_id,
+                                APP_TIMER_MODE_SINGLE_SHOT,
+                                ov2640_timers_handler);
+	APP_ERROR_CHECK(err_code);
 }
 
-static int set_agc_sensor(sensor_t *sensor, int enable)
+/**
+  * @brief  Initializes the hardware resources (I2C and GPIO) used to configure 
+  *         the OV2640 camera.
+  * @param  None
+  * @retval None
+  */
+void OV2640_Gpio_Init(void)
 {
-    sensor->status.agc = enable;
-    return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AGC_EN, enable?1:0);
-}
-
-static int set_aec_sensor(sensor_t *sensor, int enable)
-{
-    sensor->status.aec = enable;
-    return write_reg_bits(sensor, BANK_SENSOR, COM8, COM8_AEC_EN, enable?1:0);
-}
-
-static int set_hmirror_sensor(sensor_t *sensor, int enable)
-{
-    sensor->status.hmirror = enable;
-    return write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_HFLIP_IMG, enable?1:0);
-}
-
-static int set_vflip_sensor(sensor_t *sensor, int enable)
-{
-    int ret = 0;
-    sensor->status.vflip = enable;
-    ret = write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VREF_EN, enable?1:0);
-    return ret & write_reg_bits(sensor, BANK_SENSOR, REG04, REG04_VFLIP_IMG, enable?1:0);
-}
-
-static int set_raw_gma_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.raw_gma = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1, enable?1:0);
-}
-
-static int set_awb_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.awb = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1, enable?1:0);
-}
-
-static int set_awb_gain_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.awb_gain = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1, enable?1:0);
-}
-
-static int set_lenc_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.lenc = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1, enable?1:0);
-}
-
-static int set_dcw_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.dcw = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1, enable?1:0);
-}
-
-static int set_bpc_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.bpc = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1, enable?1:0);
-}
-
-static int set_wpc_dsp(sensor_t *sensor, int enable)
-{
-    sensor->status.wpc = enable;
-    return set_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1, enable?1:0);
-}
-
-//unsupported
-static int set_sharpness(sensor_t *sensor, int level)
-{
-   return -1;
-}
-
-static int set_denoise(sensor_t *sensor, int level)
-{
-   return -1;
-}
-
-static int get_reg(sensor_t *sensor, int reg, int mask)
-{
-    int ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF);
-    if(ret > 0){
-        ret &= mask;
-    }
-    return ret;
-}
-
-static int set_reg(sensor_t *sensor, int reg, int mask, int value)
-{
-    int ret = 0;
-    ret = read_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF);
-    if(ret < 0){
-        return ret;
-    }
-    value = (ret & ~mask) | (value & mask);
-    ret = write_reg(sensor, (reg >> 8) & 0x01, reg & 0xFF, value);
-    return ret;
-}
-
-static int set_res_raw(sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning)
-{
-    return set_window(sensor, (ov2640_sensor_mode_t)startX, offsetX, offsetY, totalX, totalY, outputX, outputY);
-}
-
-static int _set_pll(sensor_t *sensor, int bypass, int multiplier, int sys_div, int root_2x, int pre_div, int seld5, int pclk_manual, int pclk_div)
-{
-    return -1;
-}
-
-static int set_xclk(sensor_t *sensor, int timer, int xclk)
-{
-    int ret = 0;
-    sensor->xclk_freq_hz = xclk * 1000000U;
-    ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
-    return ret;
-}
-
-static int init_status(sensor_t *sensor){
-    sensor->status.brightness = 0;
-    sensor->status.contrast = 0;
-    sensor->status.saturation = 0;
-    sensor->status.ae_level = 0;
-    sensor->status.special_effect = 0;
-    sensor->status.wb_mode = 0;
-
-    sensor->status.agc_gain = 30;
-    int agc_gain = read_reg(sensor, BANK_SENSOR, GAIN);
-    for (int i=0; i<30; i++){
-        if(agc_gain >= agc_gain_tbl[i] && agc_gain < agc_gain_tbl[i+1]){
-            sensor->status.agc_gain = i;
-            break;
-        }
-    }
-
-    sensor->status.aec_value = ((uint16_t)get_reg_bits(sensor, BANK_SENSOR, REG45, 0, 0x3F) << 10)
-                             | ((uint16_t)read_reg(sensor, BANK_SENSOR, AEC) << 2)
-                             | get_reg_bits(sensor, BANK_SENSOR, REG04, 0, 3);//0 - 1200
-    sensor->status.quality = read_reg(sensor, BANK_DSP, QS);
-    sensor->status.gainceiling = get_reg_bits(sensor, BANK_SENSOR, COM9, 5, 7);
-
-    sensor->status.awb = get_reg_bits(sensor, BANK_DSP, CTRL1, 3, 1);
-    sensor->status.awb_gain = get_reg_bits(sensor, BANK_DSP, CTRL1, 2, 1);
-    sensor->status.aec = get_reg_bits(sensor, BANK_SENSOR, COM8, 0, 1);
-    sensor->status.aec2 = get_reg_bits(sensor, BANK_DSP, CTRL0, 6, 1);
-    sensor->status.agc = get_reg_bits(sensor, BANK_SENSOR, COM8, 2, 1);
-    sensor->status.bpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 7, 1);
-    sensor->status.wpc = get_reg_bits(sensor, BANK_DSP, CTRL3, 6, 1);
-    sensor->status.raw_gma = get_reg_bits(sensor, BANK_DSP, CTRL1, 5, 1);
-    sensor->status.lenc = get_reg_bits(sensor, BANK_DSP, CTRL1, 1, 1);
-    sensor->status.hmirror = get_reg_bits(sensor, BANK_SENSOR, REG04, 7, 1);
-    sensor->status.vflip = get_reg_bits(sensor, BANK_SENSOR, REG04, 6, 1);
-    sensor->status.dcw = get_reg_bits(sensor, BANK_DSP, CTRL2, 5, 1);
-    sensor->status.colorbar = get_reg_bits(sensor, BANK_SENSOR, COM7, 1, 1);
-
-    sensor->status.sharpness = 0;//not supported
-    sensor->status.denoise = 0;
-    return 0;
-}
-
-int ov2640_detect(int slv_addr, sensor_id_t *id)
-{
-    if (OV2640_SCCB_ADDR == slv_addr) {
-        SCCB_Write(slv_addr, 0xFF, 0x01);//bank sensor
-        uint16_t PID = SCCB_Read(slv_addr, 0x0A);
-        if (OV2640_PID == PID) {
-            id->PID = PID;
-            id->VER = SCCB_Read(slv_addr, REG_VER);
-            id->MIDL = SCCB_Read(slv_addr, REG_MIDL);
-            id->MIDH = SCCB_Read(slv_addr, REG_MIDH);
-            return PID;
-        } else {
-            ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
-        }
-    }
-    return 0;
-}
-
-int ov2640_init(sensor_t *sensor)
-{
-    sensor->reset = reset;
-    sensor->init_status = init_status;
-    sensor->set_pixformat = set_pixformat;
-    sensor->set_framesize = set_framesize;
-    sensor->set_contrast  = set_contrast;
-    sensor->set_brightness= set_brightness;
-    sensor->set_saturation= set_saturation;
-
-    sensor->set_quality = set_quality;
-    sensor->set_colorbar = set_colorbar;
-
-    sensor->set_gainceiling = set_gainceiling_sensor;
-    sensor->set_gain_ctrl = set_agc_sensor;
-    sensor->set_exposure_ctrl = set_aec_sensor;
-    sensor->set_hmirror = set_hmirror_sensor;
-    sensor->set_vflip = set_vflip_sensor;
-
-    sensor->set_whitebal = set_awb_dsp;
-    sensor->set_aec2 = set_aec2;
-    sensor->set_aec_value = set_aec_value;
-    sensor->set_special_effect = set_special_effect;
-    sensor->set_wb_mode = set_wb_mode;
-    sensor->set_ae_level = set_ae_level;
-
-    sensor->set_dcw = set_dcw_dsp;
-    sensor->set_bpc = set_bpc_dsp;
-    sensor->set_wpc = set_wpc_dsp;
-    sensor->set_awb_gain = set_awb_gain_dsp;
-    sensor->set_agc_gain = set_agc_gain;
-
-    sensor->set_raw_gma = set_raw_gma_dsp;
-    sensor->set_lenc = set_lenc_dsp;
-
-    //not supported
-    sensor->set_sharpness = set_sharpness;
-    sensor->set_denoise = set_denoise;
-
-    sensor->get_reg = get_reg;
-    sensor->set_reg = set_reg;
-    sensor->set_res_raw = set_res_raw;
-    sensor->set_pll = _set_pll;
-    sensor->set_xclk = set_xclk;
-    ESP_LOGD(TAG, "OV2640 Attached");
-    return 0;
+	nrf_gpio_cfg_input(CAM_D0_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D1_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D2_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D3_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D4_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D5_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D6_PIN,NRF_GPIO_PIN_NOPULL);
+	nrf_gpio_cfg_input(CAM_D7_PIN,NRF_GPIO_PIN_NOPULL);
 }
+
+void OV2640_CaptureGpioInit(nrf_drv_gpiote_in_config_t *config,nrfx_gpiote_evt_handler_t evt_handler)
+{
+	ret_code_t err_code;
+	
+	//配置引脚为GPIOTE输入
+	config->pull=NRF_GPIO_PIN_PULLUP;
+  err_code = nrf_drv_gpiote_in_init(CAM_PCLK_PIN, config, evt_handler);
+  APP_ERROR_CHECK(err_code);
+	
+	err_code = nrf_drv_gpiote_in_init(CAM_VSYNC_PIN, config, evt_handler);
+  APP_ERROR_CHECK(err_code);
+	
+	err_code = nrf_drv_gpiote_in_init(CAM_HREF_PIN, config, evt_handler);
+  APP_ERROR_CHECK(err_code);
+	
+	//使能事件模式
+	nrf_drv_gpiote_in_event_enable(CAM_PCLK_PIN,true);
+	nrf_drv_gpiote_in_event_enable(CAM_VSYNC_PIN,true);
+	nrf_drv_gpiote_in_event_enable(CAM_HREF_PIN,true);	
+}
+
+static void ov2640_i2s_done(void)
+{
+	
+}
+
+static void ov2640_i2s_timeout(void)
+{
+	
+}
+
+void OV2640_i2s_Init(void)
+{
+ 	twim0_init(ov2640_i2s_done, ov2640_i2s_timeout);
+}
+
+/**
+  * @brief  Resets the OV2640 camera.
+  * @param  None
+  * @retval None
+  */
+void OV2640_Reset(void)
+{
+  OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01);
+  OV2640_WriteReg(OV2640_SENSOR_COM7, 0x80);
+}
+
+/**
+  * @brief  Reads the OV2640 Manufacturer identifier.
+  * @param  OV2640ID: Pointer to the OV2640 Manufacturer identifier
+  * @retval None
+  */
+void OV2640_ReadID(OV2640_IDTypeDef *OV2640ID)
+{
+  OV2640_WriteReg(OV2640_DSP_RA_DLMT, 0x01);
+  OV2640ID->Manufacturer_ID1 = OV2640_ReadReg(OV2640_SENSOR_MIDH);
+  OV2640ID->Manufacturer_ID2 = OV2640_ReadReg(OV2640_SENSOR_MIDL);
+  OV2640ID->PIDH = OV2640_ReadReg(OV2640_SENSOR_PIDH);
+  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)
+{
+  uint32_t i;
+
+  OV2640_Reset();
+  Delay_nMS(200);
+
+  /* Initialize OV2640 */
+  for(i=0; i<(sizeof(OV2640_JPEG_INIT)/2); i++)
+  {
+    OV2640_WriteReg(OV2640_JPEG_INIT[i][0], OV2640_JPEG_INIT[i][1]);
+		Delay_nMS(1);
+  }
+
+  /* Set to output YUV422 */
+  for(i=0; i<(sizeof(OV2640_YUV422)/2); i++)
+  {
+    OV2640_WriteReg(OV2640_YUV422[i][0], OV2640_YUV422[i][1]);
+		Delay_nMS(1);
+  }
+
+  OV2640_WriteReg(0xff, 0x01);
+  OV2640_WriteReg(0x15, 0x00);
+
+  /* Set to output JPEG */
+  for(i=0; i<(sizeof(OV2640_JPEG)/2); i++)
+  {
+    OV2640_WriteReg(OV2640_JPEG[i][0], OV2640_JPEG[i][1]);
+	Delay_nMS(1);
+  }
+
+  Delay_nMS(100);
+	
+	for(i=0; i<(sizeof(OV2640_800x600_JPEG)/2); i++)
+	{
+		OV2640_WriteReg(OV2640_800x600_JPEG[i][0], OV2640_800x600_JPEG[i][1]);
+		Delay_nMS(1);
+	}
+  
+  
+}
+
+/**
+  * @brief  Configures the OV2640 camera brightness.
+  * @param  Brightness: Brightness value, where Brightness can be: 
+  *         0x40 for Brightness +2,
+  *         0x30 for Brightness +1,
+  *         0x20 for Brightness 0,
+  *         0x10 for Brightness -1,
+  *         0x00 for Brightness -2,
+  * @retval None
+  */
+void OV2640_BrightnessConfig(uint8_t Brightness)
+{
+  OV2640_WriteReg(0xff, 0x00);
+  OV2640_WriteReg(0x7c, 0x00);
+  OV2640_WriteReg(0x7d, 0x04);
+  OV2640_WriteReg(0x7c, 0x09);
+  OV2640_WriteReg(0x7d, Brightness);
+  OV2640_WriteReg(0x7d, 0x00);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const static uint8_t OV2640_AUTOEXPOSURE_LEVEL0[]=
+{
+	0xFF,	0x01,	0xff,
+	0x24,	0x20,	0xff,
+	0x25,	0x18,	0xff,
+	0x26,	0x60,	0xff,
+	0x00,	0x00,	0x00
+};
+
+const static uint8_t OV2640_AUTOEXPOSURE_LEVEL1[]=
+{
+	0xFF,	0x01,	0xff,
+	0x24,	0x34,	0xff,
+	0x25,	0x1c,	0xff,
+	0x26,	0x70,	0xff,
+	0x00,	0x00,	0x00
+};
+const static uint8_t OV2640_AUTOEXPOSURE_LEVEL2[]=
+{
+	0xFF,	0x01,	0xff,
+	0x24,	0x3e,	0xff,
+	0x25,	0x38,	0xff,
+	0x26,	0x81,	0xff,
+	0x00,	0x00,	0x00
+};
+const static uint8_t OV2640_AUTOEXPOSURE_LEVEL3[]=
+{
+	0xFF,	0x01,	0xff,
+	0x24,	0x48,	0xff,
+	0x25,	0x40,	0xff,
+	0x26,	0x81,	0xff,
+	0x00,	0x00,	0x00
+};
+const static uint8_t OV2640_AUTOEXPOSURE_LEVEL4[]=
+{
+	0xFF,	0x01,	0xff,
+	0x24,	0x58,	0xff,
+	0x25,	0x50,	0xff,
+	0x26,	0x92,	0xff,
+	0x00,	0x00,	0x00
+};
+
+void SCCB_WriteRegs(const uint8_t* pbuf)
+{
+	while(1)
+	{
+		if((*pbuf == 0) && (*(pbuf + 1) == 0))
+		{
+			break;
+		}
+		else
+		{
+			OV2640_WriteReg(*pbuf++, *pbuf++);
+		}
+	}
+}
+void OV2640_AutoExposure(uint8_t level)
+{
+	switch(level)
+	{
+		case 0:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL0);
+			break;
+		case 1:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL1);
+			break;
+		case 2:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL2);
+			break;
+		case 3:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL3);
+			break;
+		case 4:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL4);
+			break;
+		default:
+			SCCB_WriteRegs(OV2640_AUTOEXPOSURE_LEVEL0);
+			break;
+	}
+	
+}
+/**
+  * @brief  Configures the OV2640 camera Black and white mode.
+  * @param  BlackWhite: BlackWhite value, where BlackWhite can be: 
+  *         0x18 for B&W,
+  *         0x40 for Negative,
+  *         0x58 for B&W negative,
+  *         0x00 for Normal,
+  * @retval None
+  */
+void OV2640_BandWConfig(uint8_t BlackWhite)
+{
+  OV2640_WriteReg(0xff, 0x00);
+  OV2640_WriteReg(0x7c, 0x00);
+  OV2640_WriteReg(0x7d, BlackWhite);
+  OV2640_WriteReg(0x7c, 0x05);
+  OV2640_WriteReg(0x7d, 0x80);
+  OV2640_WriteReg(0x7d, 0x80);
+}
+
+/**
+  * @brief  Configures the OV2640 camera color effects.
+  * @param  value1: Color effects value1
+  * @param  value2: Color effects value2
+  *         where value1 and value2 can be: 
+  *         value1 = 0x40, value2 = 0xa6 for Antique,
+  *         value1 = 0xa0, value2 = 0x40 for Bluish,
+  *         value1 = 0x40, value2 = 0x40 for Greenish,
+  *         value1 = 0x40, value2 = 0xc0 for Reddish,
+  * @retval None
+  */
+void OV2640_ColorEffectsConfig(uint8_t value1, uint8_t value2)
+{
+  OV2640_WriteReg(0xff, 0x00);
+  OV2640_WriteReg(0x7c, 0x00);
+  OV2640_WriteReg(0x7d, 0x18);
+  OV2640_WriteReg(0x7c, 0x05);
+  OV2640_WriteReg(0x7d, value1);
+  OV2640_WriteReg(0x7d, value2);
+}
+
+/**
+  * @brief  Configures the OV2640 camera contrast.
+  * @param  value1: Contrast value1
+  * @param  value2: Contrast value2
+  *         where value1 and value2 can be: 
+  *         value1 = 0x28, value2 = 0x0c for Contrast +2,
+  *         value1 = 0x24, value2 = 0x16 for Contrast +1,
+  *         value1 = 0x20, value2 = 0x20 for Contrast 0,
+  *         value1 = 0x1c, value2 = 0x2a for Contrast -1,
+  *         value1 = 0x18, value2 = 0x34 for Contrast -2,
+  * @retval None
+  */
+void OV2640_ContrastConfig(uint8_t value1, uint8_t value2)
+{
+  OV2640_WriteReg(0xff, 0x00);
+  OV2640_WriteReg(0x7c, 0x00);
+  OV2640_WriteReg(0x7d, 0x04);
+  OV2640_WriteReg(0x7c, 0x07);
+  OV2640_WriteReg(0x7d, 0x20);
+  OV2640_WriteReg(0x7d, value1);
+  OV2640_WriteReg(0x7d, value2);
+  OV2640_WriteReg(0x7d, 0x06);
+}
+
+/**
+  * @brief  Writes a byte at a specific Camera register
+  * @param  Addr: OV2640 register address.
+  * @param  Data: Data to be written to the specific register 
+  * @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)
+{
+	uint8_t sdata[3] = {0};
+	
+	memcpy(sdata, &Addr, 2);
+	sdata[2] = Data;
+	
+  nrf_drv_twim0_tx(OV2640_DEVICE_WRITE_ADDRESS, sdata, 3, true);
+  
+  /* If operation is OK, return 0 */
+  return 0;
+}
+
+/**
+  * @brief  Reads a byte from a specific Camera register
+  * @param  Addr: OV2640 register address.
+  * @retval data read from the specific register or 0xFF if timeout condition
+  *         occured. 
+  */
+uint8_t OV2640_ReadReg(uint16_t Addr)
+{
+	uint8_t recv_data = 0;
+	nrf_drv_twim0_rx(OV2640_DEVICE_WRITE_ADDRESS, recv_data, 1);
+  /* return the read data */
+  return Data;
+}
+
+static uint8_t get_ov2640_data(void)
+{
+	uint8_t data = 0;
+	
+	uint8_t temp = nrf_gpio_pin_read(CAM_D0_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D1_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D2_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D3_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D4_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D5_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D6_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	temp = nrf_gpio_pin_read(CAM_D7_PIN);
+	data <<= 1;
+	data |= temp;
+	
+	return data;
+}
+
+void ov2640_init(void)
+{
+	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);
+}
+
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

+ 65 - 48
std/camera/target/xclk.c

@@ -1,64 +1,81 @@
-#include "driver/gpio.h"
-#include "driver/ledc.h"
-#include "esp_err.h"
-#include "esp_log.h"
-#include "esp_system.h"
+#include <stdio.h>
+#include <string.h>
+#include "nrf_drv_pwm.h"
+#include "app_util_platform.h"
+#include "app_timer.h"
+#include "nrf_drv_clock.h"
+#include "app_error.h"
+#include "nrf_log.h"
+#include "nrf_log_ctrl.h"
+#include "nrf_log_default_backends.h"
 #include "xclk.h"
-#include "esp_camera.h"
+#include "nrf_camera.h"
 
-#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
-#include "esp32-hal-log.h"
-#else
-#include "esp_log.h"
-static const char* TAG = "camera_xclk";
-#endif
+static nrf_drv_pwm_t pwm_instance = NRF_DRV_PWM_INSTANCE(0);
 
-static ledc_channel_t g_ledc_channel = 0;
+static void xclk_init(camera_config_t* config)
+{
+	nrfx_pwm_config_t const pwm_cfg = {
+		.output_pins = {
+			config->pin_xclk | NRF_DRV_PWM_PIN_INVERTED,				//将pwm0的通道0映射到引脚17
+			NRF_DRV_PWM_PIN_NOT_USED,
+			NRF_DRV_PWM_PIN_NOT_USED,					
+			NRF_DRV_PWM_PIN_NOT_USED,														//其他通道不使用
+		},
+		.irq_priority = APP_IRQ_PRIORITY_LOWEST,							//设置优先级
+		.base_clock = NRF_PWM_CLK_16MHz,											//设置时钟频率1M
+		.count_mode = NRF_PWM_MODE_UP,												//设置向上计数模式
+		.top_value = 16,																			//设置top值
+		.load_mode = NRF_PWM_LOAD_COMMON,											//设置装载模式common
+		.step_mode = NRF_PWM_STEP_AUTO												//序列周期自动推进
+	};
+
+	return nrfx_pwm_init(&pwm_instance, &pwm_cfg, pwm_handler);
+}
+
+/**
+ * 开启pwm函数
+ */
+static void xclk_play(void)
+{	
+	static nrf_pwm_values_common_t seq0_values = 8;
+	//设置pwm播放设置
+	nrf_pwm_sequence_t const seq0 = {
+		.values.p_individual = &seq0_values,			//指向pwm占空比序列
+		.length = NRF_PWM_VALUES_LENGTH(seq0_values),	//计算pwm包含周期数200
+		.repeats = 0,									//序列中周期重复数为0
+		.end_delay = 0									//序列后不插入延时
+	};
+	//自动触发pwm重新播放
+	(void)nrfx_pwm_simple_playback(&pwm_instance,&seq0,1,NRFX_PWM_FLAG_LOOP);
+}
 
-esp_err_t xclk_timer_conf(int ledc_timer, int xclk_freq_hz)
+static void xclk_stop(void)
 {
-    ledc_timer_config_t timer_conf;
-    timer_conf.duty_resolution = LEDC_TIMER_1_BIT;
-    timer_conf.freq_hz = xclk_freq_hz;
-    timer_conf.speed_mode = LEDC_LOW_SPEED_MODE;
+	nrfx_pwm_stop(&pwm_instance, true);
+}
 
-#if ESP_IDF_VERSION_MAJOR >= 4
-    timer_conf.clk_cfg = LEDC_AUTO_CLK;
-#endif
-    timer_conf.timer_num = (ledc_timer_t)ledc_timer;
-    esp_err_t err = ledc_timer_config(&timer_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(TAG, "ledc_timer_config failed for freq %d, rc=%x", xclk_freq_hz, err);
-    }
-    return err;
+static void xclk_uninit(void)
+{
+	nrfx_pwm_uninit(&pwm_instance);
 }
 
-esp_err_t camera_enable_out_clock(camera_config_t* config)
+ret_code_t xclk_timer_conf(camera_config_t* config)
 {
-    esp_err_t err = xclk_timer_conf(config->ledc_timer, config->xclk_freq_hz);
-    if (err != ESP_OK) {
-        ESP_LOGE(TAG, "ledc_timer_config failed, rc=%x", err);
-        return err;
-    }
+	ret_code_t err = xclk_init(&timer_conf);
+	if (err != NRF_SUCCESS) {
+			NRF_LOG_INFO("xclk pwm failed for rc=%x", err);
+	}
+	return err;
+}
 
-    g_ledc_channel = config->ledc_channel;
-    ledc_channel_config_t ch_conf;
-    ch_conf.gpio_num = config->pin_xclk;
-    ch_conf.speed_mode = LEDC_LOW_SPEED_MODE;
-    ch_conf.channel = config->ledc_channel;
-    ch_conf.intr_type = LEDC_INTR_DISABLE;
-    ch_conf.timer_sel = config->ledc_timer;
-    ch_conf.duty = 1;
-    ch_conf.hpoint = 0;
-    err = ledc_channel_config(&ch_conf);
-    if (err != ESP_OK) {
-        ESP_LOGE(TAG, "ledc_channel_config failed, rc=%x", err);
-        return err;
-    }
+ret_code_t camera_enable_out_clock(camera_config_t* config)
+{
+    xclk_play();
     return ESP_OK;
 }
 
 void camera_disable_out_clock()
 {
-    ledc_stop(LEDC_LOW_SPEED_MODE, g_ledc_channel, 0);
+	xclk_stop();
 }

+ 3 - 3
std/inc/user_twim.h

@@ -12,12 +12,12 @@ extern "C" {
 #endif                          
 
 typedef void (*twim_xfer_func)(void);
-	
+
 typedef struct{
 	twim_xfer_func twim_xfer_done;				//TWI传输完成标志
 	twim_xfer_func twim_xfer_timeout;			//TWI超时标志
 }user_twim_s;
-	
+
 #if NRF_MODULE_ENABLED(NRFX_TWIM_0)
 void twim0_init(twim_xfer_func done,twim_xfer_func timeout);
 void twim0_uinit(void);
@@ -31,7 +31,7 @@ void twim1_uinit(void);
 ret_code_t nrf_drv_twim1_tx(uint8_t address,uint8_t const * p_data,uint8_t length,bool no_stop);
 ret_code_t nrf_drv_twim1_rx(uint8_t address,uint8_t * p_data,uint8_t length);
 #endif
-	
+
 #ifdef __cplusplus
 }
 #endif

+ 10 - 10
std/src/user_twim.c

@@ -13,10 +13,10 @@ static const nrf_drv_twi_config_t twim0_config = {
 	.scl                = TWI_SCL_M0,  																		/**<  SCL引脚 										*/
 	.sda                = TWI_SDA_M0,  																		/**< 	定义TWI SDA引脚 						*/
 	.frequency          = NRFX_TWIM0_DEFAULT_CONFIG_FREQUENCY, 						/**< 	TWI速率 										*/
-	.interrupt_priority = NRFX_TWIM0_DEFAULT_CONFIG_IRQ_PRIORITY, 					/**< 	TWI优先级 									*/
+	.interrupt_priority = NRFX_TWIM0_DEFAULT_CONFIG_IRQ_PRIORITY, 				/**< 	TWI优先级 									*/
 	.clear_bus_init     = false																						/**< 	初始化期间不发送9个SCL时钟 	*/
 };
-	
+
 //TWI事件处理函数
 static void twim0_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
 {
@@ -80,13 +80,13 @@ void twim0_uinit(void)
 ret_code_t nrf_drv_twim0_tx(uint8_t address,uint8_t const * p_data,uint8_t length,bool no_stop)
 {
 	ret_code_t err_code = nrf_drv_twi_tx(&m_twim0, address, p_data, length, no_stop);
-	APP_ERROR_CHECK(err_code);
+	return err_code;
 }
 
 ret_code_t nrf_drv_twim0_rx(uint8_t address,uint8_t * p_data,uint8_t length)
 {
 	ret_code_t err_code = nrf_drv_twi_rx(&m_twim0, address, p_data, length);
-	APP_ERROR_CHECK(err_code);
+	return err_code;
 }
 														
 #endif
@@ -100,12 +100,12 @@ static const nrf_drv_twi_t m_twim1 = NRF_DRV_TWI_INSTANCE(1);
 
 //定义并初始化TWI配置结构体
 static const nrf_drv_twi_config_t twim1_config = {
-       .scl                = TWI_SCL_M1,  																		/**<  SCL引脚 */
-       .sda                = TWI_SDA_M1,  																		/**< 定义TWI SDA引脚 */
-       .frequency          = NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY, 							/**< TWI速率 */
-       .interrupt_priority = NRFX_TWIM_1_DEFAULT_CONFIG_IRQ_PRIORITY, 					/**< TWI优先级 */
-       .clear_bus_init     = false																						/**< 初始化期间不发送9个SCL时钟 */
-    };
+	.scl                = TWI_SCL_M1,  																		/**< SCL引脚 										*/
+	.sda                = TWI_SDA_M1,  																		/**< 定义TWI SDA引脚 						*/
+	.frequency          = NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY, 						/**< TWI速率 										*/
+	.interrupt_priority = NRFX_TWIM_1_DEFAULT_CONFIG_IRQ_PRIORITY, 				/**< TWI优先级 									*/
+	.clear_bus_init     = false																						/**< 初始化期间不发送9个SCL时钟 */
+};
 
 	
 //TWI事件处理函数