From 6766e3a2e674cf25b0e0f5904f4562ce85283ea2 Mon Sep 17 00:00:00 2001 From: KubaWis Date: Fri, 21 Mar 2025 19:13:42 +0100 Subject: [PATCH] WIP: something is working getting 1/6th of the jpeg frame (at least its now somekind correct) --- esp-cam-dump.log | 180 +++++++++++++ src/PicoIris.cpp | 16 +- src/ov2640/SCCB.cpp | 20 +- src/ov2640/SCCB.hpp | 1 + src/ov2640/camera.cpp | 528 +++++++++++++++++++++++++++++++------- src/ov2640/camera.hpp | 237 ++++++++++++++++- src/pio/image/image.pio.h | 14 +- 7 files changed, 885 insertions(+), 111 deletions(-) create mode 100644 esp-cam-dump.log diff --git a/esp-cam-dump.log b/esp-cam-dump.log new file mode 100644 index 0000000..2039d7b --- /dev/null +++ b/esp-cam-dump.log @@ -0,0 +1,180 @@ +.pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG +.frame_size = FRAMESIZE_240X240, //QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates. + +.jpeg_quality = 7, //0-63, for OV series camera sensors, lower number means higher quality +.fb_count = 1, + +ov2640_detect +I (379) sccb: SCCB_WRITE addr:0x30, reg:0xff, data:0x01, +I (379) sccb: SCCB_READ addr:0x30, reg:0x0a, data:0x26, +READ PID: I (389) sccb: SCCB_READ addr:0x30, reg:0x0b, data:0x42, +I (399) sccb: SCCB_READ addr:0x30, reg:0x1d, data:0xa2, +I (399) sccb: SCCB_READ addr:0x30, reg:0x1c, data:0x7f, +I (409) camera: Detected OV2640 camera +I (409) camera: Camera PID=0x26 VER=0x42 MIDL=0x7f MIDH=0xa2 +I (429) sccb: SCCB_WRITE addr:0x30, reg:0xff, data:0x01, +I (429) sccb: SCCB_WRITE addr:0x30, reg:0x12, data:0x80, +I (439) sccb: SCCB_WRITE addr:0x30, reg:0xff, data:0x00, +I (439) sccb: SCCB_WRITE addr:0x30, reg:0x2c, data:0xff, +I (439) sccb: SCCB_WRITE addr:0x30, reg:0x2e, data:0xdf, +I (449) sccb: SCCB_WRITE addr:0x30, reg:0xff, data:0x01, +I (449) sccb: SCCB_WRITE addr:0x30, reg:0x3c, data:0x32, +I (459) sccb: SCCB_WRITE addr:0x30, reg:0x11, data:0x01, +I (469) sccb: SCCB_WRITE addr:0x30, reg:0x09, data:0x02, +I (469) sccb: SCCB_WRITE addr:0x30, reg:0x04, data:0x28, +I (479) sccb: SCCB_WRITE addr:0x30, reg:0x13, data:0xe5, +I (479) sccb: SCCB_WRITE addr:0x30, reg:0x14, data:0x48, +I (489) sccb: SCCB_WRITE addr:0x30, reg:0x2c, data:0x0c, +I (499) sccb: SCCB_WRITE addr:0x30, reg:0x33, data:0x78, +I (499) sccb: SCCB_WRITE addr:0x30, reg:0x3a, data:0x33, +I (509) sccb: SCCB_WRITE addr:0x30, reg:0x3b, data:0xfb, +I (509) sccb: SCCB_WRITE addr:0x30, reg:0x3e, data:0x00, +I (519) sccb: SCCB_WRITE addr:0x30, reg:0x43, data:0x11, +I (529) sccb: SCCB_WRITE addr:0x30, reg:0x16, data:0x10, +I (529) sccb: SCCB_WRITE addr:0x30, reg:0x39, data:0x92, +I (539) sccb: SCCB_WRITE addr:0x30, reg:0x35, data:0xda, +I (539) sccb: SCCB_WRITE addr:0x30, reg:0x22, data:0x1a, +I (549) sccb: SCCB_WRITE addr:0x30, reg:0x37, data:0xc3, +I (559) sccb: SCCB_WRITE addr:0x30, reg:0x23, data:0x00, +I (559) sccb: SCCB_WRITE addr:0x30, reg:0x34, data:0xc0, +I (569) sccb: SCCB_WRITE addr:0x30, reg:0x06, data:0x88, +I (569) sccb: SCCB_WRITE addr:0x30, reg:0x07, data:0xc0, +I (579) sccb: SCCB_WRITE addr:0x30, reg:0x0d, data:0x87, +I (589) sccb: SCCB_WRITE addr:0x30, reg:0x0e, data:0x41, +I (589) sccb: SCCB_WRITE addr:0x30, reg:0x4c, data:0x00, +I (599) sccb: SCCB_WRITE addr:0x30, reg:0x4a, data:0x81, +I (599) sccb: SCCB_WRITE addr:0x30, reg:0x21, data:0x99, +I (609) sccb: SCCB_WRITE addr:0x30, reg:0x24, data:0x40, +I (619) sccb: SCCB_WRITE addr:0x30, reg:0x25, data:0x38, +I (619) sccb: SCCB_WRITE addr:0x30, reg:0x26, data:0x82, +I (629) sccb: SCCB_WRITE addr:0x30, reg:0x5c, data:0x00, +I (629) sccb: SCCB_WRITE addr:0x30, reg:0x63, data:0x00, +I (639) sccb: SCCB_WRITE addr:0x30, reg:0x61, data:0x70, +I (639) sccb: SCCB_WRITE addr:0x30, reg:0x62, data:0x80, +I (649) sccb: SCCB_WRITE addr:0x30, reg:0x7c, data:0x05, +I (659) sccb: SCCB_WRITE addr:0x30, reg:0x20, data:0x80, +I (659) sccb: SCCB_WRITE addr:0x30, reg:0x28, data:0x30, +I (669) sccb: SCCB_WRITE addr:0x30, reg:0x6c, data:0x00, +I (669) sccb: SCCB_WRITE addr:0x30, reg:0x6d, data:0x80, +I (679) sccb: SCCB_WRITE addr:0x30, reg:0x6e, data:0x00, +I (689) sccb: SCCB_WRITE addr:0x30, reg:0x70, data:0x02, +I (689) sccb: SCCB_WRITE addr:0x30, reg:0x71, data:0x94, +I (699) sccb: SCCB_WRITE addr:0x30, reg:0x73, data:0xc1, +I (699) sccb: SCCB_WRITE addr:0x30, reg:0x3d, data:0x34, +I (709) sccb: SCCB_WRITE addr:0x30, reg:0x5a, data:0x57, +I (719) sccb: SCCB_WRITE addr:0x30, reg:0x4f, data:0xbb, +I (719) sccb: SCCB_WRITE addr:0x30, reg:0x50, data:0x9c, +I (729) sccb: SCCB_WRITE addr:0x30, reg:0x12, data:0x20, +I (729) sccb: SCCB_WRITE addr:0x30, reg:0x17, data:0x11, +I (739) sccb: SCCB_WRITE addr:0x30, reg:0x18, data:0x43, +I (749) sccb: SCCB_WRITE addr:0x30, reg:0x19, data:0x00, +I (749) sccb: SCCB_WRITE addr:0x30, reg:0x1a, data:0x25, +I (759) sccb: SCCB_WRITE addr:0x30, reg:0x32, data:0x89, +I (759) sccb: SCCB_WRITE addr:0x30, reg:0x37, data:0xc0, +I (769) sccb: SCCB_WRITE addr:0x30, reg:0x4f, data:0xca, +I (779) sccb: SCCB_WRITE addr:0x30, reg:0x50, data:0xa8, +I (779) sccb: SCCB_WRITE addr:0x30, reg:0x6d, data:0x00, +I (789) sccb: SCCB_WRITE addr:0x30, reg:0x3d, data:0x38, +I (789) sccb: SCCB_WRITE addr:0x30, reg:0xff, data:0x00, +I (799) sccb: SCCB_WRITE addr:0x30, reg:0xe5, data:0x7f, +I (809) sccb: SCCB_WRITE addr:0x30, reg:0xf9, data:0xc0, +I (809) sccb: SCCB_WRITE addr:0x30, reg:0x41, data:0x24, +I (819) sccb: SCCB_WRITE addr:0x30, reg:0xe0, data:0x14, +I (819) sccb: SCCB_WRITE addr:0x30, reg:0x76, data:0xff, +I (829) sccb: SCCB_WRITE addr:0x30, reg:0x33, data:0xa0, +I (839) sccb: SCCB_WRITE addr:0x30, reg:0x42, data:0x20, +I (839) sccb: SCCB_WRITE addr:0x30, reg:0x43, data:0x18, +I (849) sccb: SCCB_WRITE addr:0x30, reg:0x4c, data:0x00, +I (849) sccb: SCCB_WRITE addr:0x30, reg:0x87, data:0x50, +I (859) sccb: SCCB_WRITE addr:0x30, reg:0x88, data:0x3f, +I (869) sccb: SCCB_WRITE addr:0x30, reg:0xd7, data:0x03, +I (869) sccb: SCCB_WRITE addr:0x30, reg:0xd9, data:0x10, +I (879) sccb: SCCB_WRITE addr:0x30, reg:0xd3, data:0x82, +I (879) sccb: SCCB_WRITE addr:0x30, reg:0xc8, data:0x08, +I (889) sccb: SCCB_WRITE addr:0x30, reg:0xc9, data:0x80, +I (899) sccb: SCCB_WRITE addr:0x30, reg:0x7c, data:0x00, +I (899) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x00, +I (909) sccb: SCCB_WRITE addr:0x30, reg:0x7c, data:0x03, +I (909) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x48, +I (919) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x48, +I (929) sccb: SCCB_WRITE addr:0x30, reg:0x7c, data:0x08, +I (929) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x20, +I (939) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x10, +I (939) sccb: SCCB_WRITE addr:0x30, reg:0x7d, data:0x0e, +I (949) sccb: SCCB_WRITE addr:0x30, reg:0x90, data:0x00, +I (959) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x0e, +I (959) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x1a, +I (969) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x31, +I (969) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x5a, +I (979) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x69, +I (989) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x75, +I (989) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x7e, +I (999) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x88, +I (999) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x8f, +I (1009) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x96, +I (1019) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0xa3, +I (1019) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0xaf, +I (1029) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0xc4, +I (1029) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0xd7, +I (1039) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0xe8, +I (1049) sccb: SCCB_WRITE addr:0x30, reg:0x91, data:0x20, +I (1049) sccb: SCCB_WRITE addr:0x30, reg:0x92, data:0x00, +I (1059) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x06, +I (1069) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0xe3, +I (1069) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x05, +I (1079) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x05, +I (1079) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1089) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x04, +I (1099) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1099) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1109) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1109) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1119) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1129) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1129) sccb: SCCB_WRITE addr:0x30, reg:0x93, data:0x00, +I (1139) sccb: SCCB_WRITE addr:0x30, reg:0x96, data:0x00, +I (1139) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x08, +I (1149) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x19, +I (1159) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x02, +I (1159) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x0c, +I (1169) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x24, +I (1169) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x30, +I (1179) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x28, +I (1189) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x26, +I (1189) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x02, +I (1199) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x98, +I (1199) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x80, +I (1209) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x00, +I (1219) sccb: SCCB_WRITE addr:0x30, reg:0x97, data:0x00, +I (1219) sccb: SCCB_WRITE addr:0x30, reg:0xa4, data:0x00, +I (1229) sccb: SCCB_WRITE addr:0x30, reg:0xa8, data:0x00, +I (1239) sccb: SCCB_WRITE addr:0x30, reg:0xc5, data:0x11, +I (1239) sccb: SCCB_WRITE addr:0x30, reg:0xc6, data:0x51, +I (1249) sccb: SCCB_WRITE addr:0x30, reg:0xbf, data:0x80, +I (1249) sccb: SCCB_WRITE addr:0x30, reg:0xc7, data:0x10, +I (1259) sccb: SCCB_WRITE addr:0x30, reg:0xb6, data:0x66, +I (1269) sccb: SCCB_WRITE addr:0x30, reg:0xb8, data:0xa5, +I (1269) sccb: SCCB_WRITE addr:0x30, reg:0xb7, data:0x64, +I (1279) sccb: SCCB_WRITE addr:0x30, reg:0xb9, data:0x7c, +I (1279) sccb: SCCB_WRITE addr:0x30, reg:0xb3, data:0xaf, +I (1289) sccb: SCCB_WRITE addr:0x30, reg:0xb4, data:0x97, +I (1299) sccb: SCCB_WRITE addr:0x30, reg:0xb5, data:0xff, +I (1299) sccb: SCCB_WRITE addr:0x30, reg:0xb0, data:0xc5, +I (1309) sccb: SCCB_WRITE addr:0x30, reg:0xb1, data:0x94, +I (1309) sccb: SCCB_WRITE addr:0x30, reg:0xb2, data:0x0f, +I (1319) sccb: SCCB_WRITE addr:0x30, reg:0xc4, data:0x5c, +I (1329) sccb: SCCB_WRITE addr:0x30, reg:0xc3, data:0xfd, +I (1329) sccb: SCCB_WRITE addr:0x30, reg:0x7f, data:0x00, +I (1339) sccb: SCCB_WRITE addr:0x30, reg:0xe5, data:0x1f, +I (1339) sccb: SCCB_WRITE addr:0x30, reg:0xe1, data:0x67, +I (1349) sccb: SCCB_WRITE addr:0x30, reg:0xdd, data:0x7f, +I (1359) sccb: SCCB_WRITE addr:0x30, reg:0xda, data:0x00, +I (1359) sccb: SCCB_WRITE addr:0x30, reg:0xe0, data:0x00, +I (1369) sccb: SCCB_WRITE addr:0x30, reg:0x05, data:0x00, +I (1379) cam_hal: buffer_size: 32768, half_buffer_size: 4096, node_buffer_size: 2048, node_cnt: 16, total_cnt: 2 +I (1389) cam_hal: Allocating 11520 Byte frame buffer in PSRAM +E (1389) cam_hal: cam_dma_config(301): frame buffer malloc failed +E (1399) cam_hal: cam_config(390): cam_dma_config failed +E (1399) camera: Camera config failed with error 0xffffffff +E (1409) example:take_picture: Camera Init Failed +I (1419) main_task: Returned from app_main() \ No newline at end of file diff --git a/src/PicoIris.cpp b/src/PicoIris.cpp index ee22d59..c5155e1 100644 --- a/src/PicoIris.cpp +++ b/src/PicoIris.cpp @@ -22,7 +22,7 @@ camera_config_t left_eye_config = { .pin_xclk = 3, /*!< GPIO pin for camera XCLK line */ //? in theory could be shared or perhaps ommited? .pin_sccb_sda = 4, /*!< GPIO pin for camera SDA line */ .pin_sccb_scl = 5, /*!< GPIO pin for camera SCL line */ - .pin_data_base = 6, /*!< this pin + 7 consecutive will be used D0-D7 */ + .pin_data_base = 6, /*!< this pin + 7 consecutive will be used D0-D7 PCLK HREF */ .pin_vsync = 16, /*!< GPIO pin for camera VSYNC line */ .xclk_freq_hz = 0, /*!< Frequency of XCLK signal, in Hz. */ //! Figure out the highest it can go to .sccb_ctrl = 0, /* Select i2c controller ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio2 */ @@ -35,17 +35,17 @@ int main() sleep_ms(4000); //printf("Hello World!"); - //printf("construct OV2640!"); OV2640 left_cam = OV2640(left_eye_config); - //printf("begin OV2640!"); left_cam.begin(DMA_IRQ_0); //left_cam.capture_frame(); //fwrite(left_cam.fb, 1, sizeof(left_cam.fb), stdout); while (true) { - //printf("Hello, world!\n"); - //sleep_ms(1000); + // //printf("Hello, world!\n"); + // //sleep_ms(1000); + left_cam.capture_frame(); - fwrite(left_cam.fb, 1, sizeof(left_cam.fb), stdout); - memset(&left_cam.fb, 0x00, sizeof(left_cam.fb)); - } + fwrite(&left_cam.fb, 1, sizeof(left_cam.fb), stdout); + // memset(&left_cam.fb, 0x00, sizeof(left_cam.fb)); + sleep_ms(1000); + } } diff --git a/src/ov2640/SCCB.cpp b/src/ov2640/SCCB.cpp index b738ce4..84a460a 100644 --- a/src/ov2640/SCCB.cpp +++ b/src/ov2640/SCCB.cpp @@ -2,6 +2,7 @@ #include #include "hardware/i2c.h" #include "pico/stdlib.h" +#include "stdio.h" #include "src/pio/i2c/pio_i2c.h" SCCB::SCCB(uint8_t sda_pin, uint8_t scl_pin) { @@ -72,11 +73,26 @@ void SCCB::writeRegister(uint8_t reg, uint8_t value) buf[1] = value; if (this->ctrl < 2) { - i2c_write_blocking(this->i2cc, OV2640_ADDR, buf, 2, false); + int ret = i2c_write_blocking(this->i2cc, OV2640_ADDR, buf, 2, false); + if(ret == PICO_ERROR_GENERIC) { + printf("Problem i2c write failed!"); + sleep_ms(1000); + } }else { //pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, buf, 2); } - sleep_ms(20); + sleep_ms(30); +} + +void SCCB::writeMaskRegister(uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value) +{ + uint8_t buf[2]; + buf[0] = reg; + buf[1] = value; + + uint8_t old_val = this->readRegister(reg); + uint8_t new_value = (old_val & ~(mask << offset)) | ((value & mask) << offset); + this->writeRegister(reg, new_value); } void SCCB::writeList(const register_val_t *cfg, diff --git a/src/ov2640/SCCB.hpp b/src/ov2640/SCCB.hpp index b797663..9b6ec09 100644 --- a/src/ov2640/SCCB.hpp +++ b/src/ov2640/SCCB.hpp @@ -17,6 +17,7 @@ public: int readRegister(uint8_t reg); void writeRegister(uint8_t reg, uint8_t value); + void writeMaskRegister(uint8_t reg, uint8_t offset, uint8_t mask, uint8_t value); void writeList(const register_val_t *cfg, uint16_t len); private: diff --git a/src/ov2640/camera.cpp b/src/ov2640/camera.cpp index 85d86bb..80c0b8c 100644 --- a/src/ov2640/camera.cpp +++ b/src/ov2640/camera.cpp @@ -13,6 +13,24 @@ #include "src/pio/image/image.pio.h" + +static volatile bool frameReady = false; // true at end-of-frame +static volatile bool suspended = true; + +static void iCap_vsync_irq(uint gpio, uint32_t events) { + if (!suspended) { + // Clear PIO FIFOs and start DMA transfer + pio_sm_clear_fifos(pio2, 0); + dma_channel_start(0); + } + } + static void iCap_dma_finish_irq() { + frameReady = true; + suspended = true; + //printf("iCap_dma_finish_irq"); + dma_hw->ints0 = 1u << 0; + } + // TODO: Stolen from Adafruit repo (Check if correct) // PIO code in this table is modified at runtime so that PCLK is @@ -32,6 +50,169 @@ static struct pio_program cap_pio_program = { .length = sizeof capture_pio_opcodes / sizeof capture_pio_opcodes[0], .origin = -1, }; + + +register_val_t OV2640_stolem_jpeg_init[] = { + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR}, + {OV2640_REG1_COM7, OV2640_COM7_SRST}, + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, + {0x2c, 0xff}, + {OV2640_REG1_ADDVSH, 0xdf}, + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR}, + {0x3c, 0x32}, + {0x11, 0x01}, + {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}, + {0x06, 0x88}, + {0x07, 0xc0}, + {0x0d, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {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}, + {0x3d, 0x34}, + {0x5a, 0x57}, + {0x4f, 0xbb}, + {0x50, 0x9c}, + {0x12, 0x20}, + {0x17, 0x11}, + {0x18, 0x43}, + {0x19, 0x00}, + {0x1a, 0x25}, + {0x32, 0x89}, + {0x37, 0xc0}, + {0x4f, 0xca}, + {0x50, 0xa8}, + {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, 0x50}, + {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}, + {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}, + {0xc3, 0xfd}, + {0x7f, 0x00}, + {0xe5, 0x1f}, + {0xe1, 0x67}, + {0xdd, 0x7f}, + {0xda, 0x00}, + {0xe0, 0x00}, + {0x05, 0x00} +}; register_val_t OV2640_init[] = { // Ideas from rp2040_ov2640-main repo @@ -284,73 +465,15 @@ register_val_t OV2640_init[] = { {OV2640_REG0_ZMOH, 0x78}, // OUTH low bits {OV2640_REG0_ZMHH, 0x00}, // OUTW/H high bits {OV2640_REG0_R_DVP_SP, 0x02}, // Manual DVP PCLK setting - {OV2640_REG0_RESET, 0x00}}; // Go -// TODO: figure out how to set to JPEG and 260x260 -register_val_t OV2640_qqvga[] = - {// Configure OV2640 for QQVGA output - {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0 - {OV2640_REG0_RESET, OV2640_RESET_DVP}, - {OV2640_REG0_HSIZE8, 0x64}, // HSIZE high bits - {OV2640_REG0_VSIZE8, 0x4B}, // VSIZE high bits - {OV2640_REG0_CTRL2, OV2640_CTRL2_DCW | OV2640_CTRL2_SDE | - OV2640_CTRL2_UV_AVG | OV2640_CTRL2_CMX}, - {OV2640_REG0_CTRLI, OV2640_CTRLI_LP_DP | 0x12}, - {OV2640_REG0_HSIZE, 0xC8}, // H_SIZE low bits - {OV2640_REG0_VSIZE, 0x96}, // V_SIZE low bits - {OV2640_REG0_XOFFL, 0x00}, // OFFSET_X low bits - {OV2640_REG0_YOFFL, 0x00}, // OFFSET_Y low bits - {OV2640_REG0_VHYX, 0x00}, // V/H/Y/X high bits - {OV2640_REG0_TEST, 0x00}, // ? - {OV2640_REG0_ZMOW, 0x28}, // OUTW low bits - {OV2640_REG0_ZMOH, 0x1E}, // OUTH low bits - {OV2640_REG0_ZMHH, 0x00}, // OUTW/H high bits - {OV2640_REG0_R_DVP_SP, 0x08}, // Manual DVP PCLK setting - {OV2640_REG0_RESET, 0x00} - }; // Go - register_val_t ov2640_uxga_cif[] = { - {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} - }; + {OV2640_REG0_RESET, 0x00} +}; // Go - register_val_t OV2640_rgb[] = { - {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0 - {OV2640_REG0_RESET, OV2640_RESET_DVP}, - {OV2640_REG0_IMAGE_MODE, OV2640_IMAGE_MODE_DVP_RGB565}, - {0xD7, 0x03}, // Mystery init values - {0xE1, 0x77}, // seen in other examples - {OV2640_REG0_RESET, 0x00} - }; // Go - register_val_t OV2640_yuv[] = { - {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0 - {OV2640_REG0_RESET, OV2640_RESET_DVP}, - {OV2640_REG0_IMAGE_MODE, - OV2640_IMAGE_MODE_JPEG | OV2640_IMAGE_MODE_JPEG_HREF}, - {0xD7, 0x01}, // Mystery init values - {0xE1, 0x67}, // seen in other examples - {OV2640_REG0_RESET, 0x00} - }; // Go - // Stolem from esp32-camera register_val_t OV2640_jpeg[] = { - {0xFF, 0x0}, - {0xE0, 0x10 | 0x04}, - {0xDA, 0x10 | 0x02}, + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, + {OV2640_REG0_RESET, OV2640_RESET_JPEG | OV2640_RESET_DVP}, + {OV2640_REG0_IMAGE_MODE, OV2640_IMAGE_MODE_JPEG | OV2640_IMAGE_MODE_JPEG_HREF }, {0xD7, 0x03}, {0xE1, 0x77}, {0xE5, 0x1F}, @@ -360,11 +483,103 @@ register_val_t OV2640_jpeg[] = { {0x3C, 0x10}, {0xEB, 0x30}, {0xDD, 0x7F}, - {0xE0, 0x00}, + {OV2640_REG0_RESET, 0x00}, {0, 0} }; -//uint8_t image_buf[160*120*3]; +register_val_t OV2640_CIF[] = { + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR}, + {OV2640_REG1_COM7, OV2640_COM7_RES_CIF}, + + //Set the sensor output window + {OV2640_REG1_COM1, 0x0A}, + {OV2640_REG1_REG32, OV2640_REG32_CIF}, + {HSTART, 0x11}, + {HSTOP, 0x43}, + {VSTART, 0x00}, + {VSTOP, 0x25}, + + {CLKRC, 0x00}, + {OV2640_REG1_BD50, 0xca}, + {OV2640_REG1_BD60, 0xa8}, + {0x5a, 0x23}, + {0x6d, 0x00}, + {0x3d, 0x38}, + {0x39, 0x92}, + {0x35, 0xda}, + {0x22, 0x1a}, + {0x37, 0xc3}, + {0x23, 0x00}, + {OV2640_REG1_ARCOM2, 0xc0}, + {0x06, 0x88}, + {0x07, 0xc0}, + {OV2640_REG1_COM4, 0x87}, + {0x0e, 0x41}, + {0x4c, 0x00}, + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, + {OV2640_REG0_RESET, OV2640_RESET_DVP}, + + //Set the sensor resolution (UXGA, SVGA, CIF) + {OV2640_REG0_HSIZE8, 0x32}, + {OV2640_REG0_VSIZE8, 0x25}, + {OV2640_REG0_SIZEL, 0x00}, + + //Set the image window size >= output size + {OV2640_REG0_HSIZE, 0x64}, + {OV2640_REG0_VSIZE, 0x4a}, + {OV2640_REG0_XOFFL, 0x00}, + {OV2640_REG0_YOFFL, 0x00}, + {OV2640_REG0_VHYX, 0x00}, + {OV2640_REG0_TEST, 0x00}, + + {OV2640_REG0_CTRL2, OV2640_CTRL2_DCW | 0x1D}, + {OV2640_REG0_CTRLI, OV2640_CTRLI_LP_DP | 0x00}, + {R_DVP_SP, 0x08}, + {OV2640_REG0_RESET, 0x00}, + {0, 0} +}; + +register_val_t ov2640_uxga_cif[] = { + {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, 0x0f}, + {0xe0, 0x00} +}; + +register_val_t OV2640_rgb[] = { + {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0 + {OV2640_REG0_RESET, OV2640_RESET_DVP}, + {OV2640_REG0_IMAGE_MODE, OV2640_IMAGE_MODE_DVP_RGB565 | + OV2640_IMAGE_MODE_BYTE_SWAP}, + {0xD7, 0x03}, // Mystery init values + {0xE1, 0x77}, // seen in other examples + {OV2640_REG0_RESET, 0x00} + }; // Go + + +// static const uint8_t special_effects_regs[7 + 1][5] = { +// {0x7C, 0x7D, 0x7C, 0x7D, 0x7D }, +// {0x00, 0X00, 0x05, 0X80, 0X80 }, /* no effect */ +// {0x00, 0X40, 0x05, 0X80, 0X80 }, /* negative */ +// {0x00, 0X18, 0x05, 0X80, 0X80 }, /* black and white */ +// {0x00, 0X18, 0x05, 0X40, 0XC0 }, /* reddish */ +// {0x00, 0X18, 0x05, 0X40, 0X40 }, /* greenish */ +// {0x00, 0X18, 0x05, 0XA0, 0X40 }, /* blue */ +// {0x00, 0X18, 0x05, 0X40, 0XA6 }, /* retro */ +// }; OV2640::OV2640(camera_config_t config) { @@ -398,8 +613,8 @@ int OV2640::begin(int dma_irq) gpio_set_function(this->config.pin_xclk, GPIO_FUNC_PWM); uint slice_num = pwm_gpio_to_slice_num(this->config.pin_xclk); // 8 cycles (0 to 7), 150 MHz / 8 = ~18.71 MHz wrap rate - pwm_set_wrap(slice_num, 7); - pwm_set_gpio_level(this->config.pin_xclk, 4); + pwm_set_wrap(slice_num, 5); + pwm_set_gpio_level(this->config.pin_xclk, 3); pwm_set_enabled(slice_num, true); // Init SCCB @@ -419,14 +634,49 @@ int OV2640::begin(int dma_irq) sleep_ms(300); // Datasheet: tS:RESET = 1 ms // Init main camera settings - //prtintf("Write list of init\n"); - this->sccb.writeList(OV2640_init, sizeof OV2640_init / sizeof OV2640_init[0]); - //prtintf("Write list of qqvga\n"); - this->sccb.writeList(ov2640_uxga_cif, sizeof ov2640_uxga_cif / sizeof ov2640_uxga_cif[0]); - //prtintf("Write list of jpeg\n"); - this->sccb.writeList(OV2640_jpeg, sizeof OV2640_jpeg / sizeof OV2640_jpeg[0]); + //printf("Stolemjpg init\n"); + //this->sccb.writeList(OV2640_stolem_jpeg_init, sizeof(OV2640_stolem_jpeg_init)/sizeof(OV2640_stolem_jpeg_init[0])); + //printf("Stolemjpg init DONE\n"); + this->sccb.writeList(OV2640_init, sizeof(OV2640_init)/sizeof(OV2640_init[0])); + this->sccb.writeList(ov2640_uxga_cif, sizeof(ov2640_uxga_cif)/sizeof(ov2640_uxga_cif[0])); + this->sccb.writeList(OV2640_jpeg, sizeof(OV2640_jpeg)/sizeof(OV2640_jpeg[0])); + //this->sccb.writeRegister(0xd3, 0x0f); + + + // this->set_framesize(); + // sleep_ms(10); + // this->sccb.writeList(OV2640_jpeg, sizeof(OV2640_jpeg)/sizeof(OV2640_jpeg[0])); + + //this->set_gainceiling(GAINCEILING_2X); + //sleep_ms(10); + //this->set_bpc(false); + //sleep_ms(10); + //this->set_wpc(true); + //sleep_ms(10); + //this->set_lenc(true); + //sleep_ms(10); + this->set_quality(5); + sleep_ms(10); + this->sccb.writeList(OV2640_jpeg, sizeof(OV2640_jpeg)/sizeof(OV2640_jpeg[0])); + + this->set_quality(5); + + //prtintf("Write list of init\n"); + // sleep_ms(10); + // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); + sleep_ms(10); + //this->sccb.writeRegister(0xd3, 0x05); + sleep_ms(10); + + + // // for (int i=0; i<5; i++) { + // // this->sccb.writeRegister(0xff, 0x00); + // // this->sccb.writeRegister(special_effects_regs[0][i], special_effects_regs[3][i]); + // // } + + this->sccb.writeRegister(0xff, 0x00); + this->sccb.writeRegister(0xd3, 0x05); // try 0x80 next - this->set_quality(10); //prtintf("Gpio init\n"); gpio_init(this->config.pin_vsync); @@ -436,6 +686,7 @@ int OV2640::begin(int dma_irq) { gpio_init(this->config.pin_data_base + i); gpio_set_dir(this->config.pin_data_base + i, GPIO_IN); + //gpio_pull_down(this->config.pin_data_base + i); } //prtintf("Gpio init done\n"); @@ -505,10 +756,69 @@ int OV2640::begin(int dma_irq) uint offset = pio_add_program(pio2, &image_program); image_program_init(pio2, 0, offset, this->config.pin_data_base); - //prtintf("IRQ init done\n"); + //printf("IRQ init done\n"); + + //printf("config done"); + dma_channel_config c = dma_channel_get_default_config(0); + channel_config_set_transfer_data_size(&c, DMA_SIZE_16); + channel_config_set_read_increment(&c, false); + channel_config_set_write_increment(&c, true); + channel_config_set_bswap(&c, true); + // Set PIO RX as DMA trigger. Input shift register saturates at 16 bits + // (1 pixel), configured in data size above and in PIO setup elsewhere. + channel_config_set_dreq(&c, + pio_get_dreq(pio2, 0, false)); + // Set up baseline DMA configuration...it's initially lacking destination + // and count, set later (dma_change()) after resolution is known. DMA + // isn't started until later, and is triggered in the vsync interrupt. + dma_channel_configure(0, &c, &this->fb, + &pio2->rxf[0], sizeof(this->fb), false); + + // Set up end-of-DMA interrupt + dma_channel_set_irq0_enabled(0, true); + irq_set_exclusive_handler(DMA_IRQ_0, iCap_dma_finish_irq); + irq_set_enabled(DMA_IRQ_0, true); + + // SET UP VSYNC INTERRUPT ------------------------------------------------ + + gpio_set_irq_enabled_with_callback(this->config.pin_vsync, GPIO_IRQ_EDGE_RISE, true, + &iCap_vsync_irq); return 0; } +//! You need to set pixformat after this +void OV2640::set_framesize() { + // uint8_t max_x = 75; + // uint8_t max_y = 74; + // uint8_t w = 60; + // uint8_t h = 60; + + // register_val_t win_regs[] = { + // {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, + // {OV2640_REG0_HSIZE, 75}, + // {OV2640_REG0_VSIZE, 74}, + // {OV2640_REG0_XOFFL, 50}, + // {OV2640_REG0_YOFFL, 0}, + // {OV2640_REG0_VHYX, ((max_y >> 1) & 0X80) | ((0 >> 4) & 0X70) | ((max_x >> 5) & 0X08) | ((50 >> 8) & 0X07)}, + // {OV2640_REG0_TEST, (max_x >> 2) & 0X80}, + // {OV2640_REG0_ZMOW, (w)&0xFF}, + // {OV2640_REG0_ZMOH, (h)&0xFF}, + // {OV2640_REG0_ZMHH, ((h>>6)&0x04)|((w>>8)&0x03)}, + // {0, 0} + // }; + + // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); + // this->sccb.writeRegister(OV2640_REG0_R_BYPASS, OV2640_R_BYPASS_DSP_BYPASS); + // this->sccb.writeList(OV2640_CIF, sizeof(OV2640_CIF)/sizeof(OV2640_CIF[0])); + // this->sccb.writeList(win_regs, sizeof(win_regs)/sizeof(win_regs[0])); + // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR); + // this->sccb.writeRegister(OV2640_REG1_CLKRC, 0); + // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); + // this->sccb.writeRegister(OV2640_REG0_R_DVP_SP, 8); + // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); + // this->sccb.writeRegister(OV2640_REG0_R_BYPASS, OV2640_R_BYPASS_DSP_ENABLE); +} + void OV2640::set_quality(int quality) { if(quality < 0) { quality = 0; @@ -520,30 +830,58 @@ void OV2640::set_quality(int quality) { this->sccb.writeRegister(0x44, quality); // set quality } + +void OV2640::set_gainceiling(gainceiling_t gainceiling) { + this->sccb.writeRegister(0xFF, 0x01); + this->sccb.writeMaskRegister(0x14, 5, 7, gainceiling); + +} + +void OV2640::set_bpc(bool enable) { + this->sccb.writeRegister(0xFF, 0x00); + this->sccb.writeMaskRegister(0x87, 7, 1, enable?1:0); +} + +void OV2640::set_wpc(bool enable) { + this->sccb.writeRegister(0xFF, 0x00); + this->sccb.writeMaskRegister(0x87, 6, 1, enable?1:0); +} + +void OV2640::set_lenc(bool enable) { + this->sccb.writeRegister(0xFF, 0x00); + this->sccb.writeMaskRegister(0xC3, 1, 1, enable?1:0); +} + + void OV2640::capture_frame() { - dma_channel_config c = dma_channel_get_default_config(0); - channel_config_set_read_increment(&c, false); - channel_config_set_write_increment(&c, true); - channel_config_set_dreq(&c, pio_get_dreq(pio2, 0, false)); - channel_config_set_transfer_data_size(&c, DMA_SIZE_8); + + + suspended = false; + while(!frameReady); + return; + // dma_channel_config c = dma_channel_get_default_config(0); + // channel_config_set_read_increment(&c, false); + // channel_config_set_write_increment(&c, true); + // channel_config_set_dreq(&c, pio_get_dreq(pio2, 0, false)); + // channel_config_set_transfer_data_size(&c, DMA_SIZE_16); - dma_channel_configure( - 0, &c, - &this->fb, - &pio2->rxf[0], - sizeof(this->fb), - false - ); + // dma_channel_configure( + // 0, &c, + // &this->fb, + // &pio2->rxf[0], + // sizeof(this->fb), + // false + // ); - // Wait for vsync rising edge to start frame - ////prtintf("pin_vsync) == true\n"); - while (gpio_get(this->config.pin_vsync) == true); - ////prtintf("pin_vsync) == false\n"); - while (gpio_get(this->config.pin_vsync) == false); - ////prtintf("after while loops\n"); + // // Wait for vsync rising edge to start frame + // ////prtintf("pin_vsync) == true\n"); + // while (gpio_get(this->config.pin_vsync) == true); + // ////prtintf("pin_vsync) == false\n"); + // while (gpio_get(this->config.pin_vsync) == false); + // ////prtintf("after while loops\n"); - dma_channel_start(0); - dma_channel_wait_for_finish_blocking(0); + // dma_channel_start(0); + // dma_channel_wait_for_finish_blocking(0); } diff --git a/src/ov2640/camera.hpp b/src/ov2640/camera.hpp index e23f28e..a38ef27 100644 --- a/src/ov2640/camera.hpp +++ b/src/ov2640/camera.hpp @@ -20,6 +20,15 @@ typedef struct { int dma_channel; } sm_dma_config_t; +typedef enum { + GAINCEILING_2X, + GAINCEILING_4X, + GAINCEILING_8X, + GAINCEILING_16X, + GAINCEILING_32X, + GAINCEILING_64X, + GAINCEILING_128X, +} gainceiling_t; class OV2640 { public: @@ -28,9 +37,14 @@ public: int begin(int dma_irq); void set_quality(int quality); + void set_gainceiling(gainceiling_t gainceiling); + void set_bpc(bool enable); + void set_wpc(bool enable); + void set_lenc(bool enable); + void set_framesize(); void capture_frame(); - uint8_t fb[160*120*3]; + uint8_t fb[(352*288)]; camera_config_t config; private: @@ -44,6 +58,11 @@ private: #define OV2640_ADDR 0x30 +#define HSTART 0x17 +#define HSTOP 0x18 +#define VSTART 0x19 +#define VSTOP 0x1A + #define OV2640_REG_RA_DLMT 0xFF //< Register bank select #define OV2640_RA_DLMT_DSP 0x00 //< Bank 0 - DSP address #define OV2640_RA_DLMT_SENSOR 0x01 //< Bank 1 - Sensor address @@ -206,7 +225,7 @@ private: #define OV2640_COM7_SRST 0x80 //< System reset #define OV2640_COM7_RES_MASK 0x70 //< Resolution mask #define OV2640_COM7_RES_UXGA 0x00 //< UXGA (full size) mode -#define OV2640_COM7_RES_CIF 0x10 //< CIF mode +#define OV2640_COM7_RES_CIF 0x20 //< CIF mode #define OV2640_COM7_RES_SVGA 0x40 //< SVGA mode #define OV2640_COM7_ZOOM 0x04 //< Zoom mode #define OV2640_COM7_COLORBAR 0x02 //< Color bar test pattern enable @@ -275,6 +294,7 @@ private: #define OV2640_REG32_PCLK_DIV4 0xC0 //< PCLK frequency / 4 #define OV2640_REG32_HREFEND_MASK 0x38 //< HREFEND LSBs #define OV2640_REG32_HREFST_MASK 0x07 //< HREFST LSBs +#define OV2640_REG32_CIF 0x89 #define OV2640_REG1_ARCOM2 0x34 //< ? #define OV2640_ARCOM2_ZOOM 0x04 //< Zoom window horiz start point #define OV2640_REG1_REG45 0x45 //< Register 45: @@ -296,4 +316,215 @@ private: #define OV2640_REG1_REG5F 0x5F //< AVGsel[23:16] #define OV2640_REG1_REG60 0x60 //< AVGsel[31:24] #define OV2640_REG1_HISTO_LOW 0x61 //< Histogram low level -#define OV2640_REG1_HISTO_HIGH 0x62 //< Histogram high level \ No newline at end of file +#define OV2640_REG1_HISTO_HIGH 0x62 //< Histogram high level + + +#ifndef __REG_REGS_H__ +#define __REG_REGS_H__ +/* DSP register bank FF=0x00*/ +#define R_BYPASS 0x05 +#define QS 0x44 +#define CTRLI 0x50 +#define HSIZE 0x51 +#define VSIZE 0x52 +#define XOFFL 0x53 +#define YOFFL 0x54 +#define VHYX 0x55 +#define DPRP 0x56 +#define TEST 0x57 +#define ZMOW 0x5A +#define ZMOH 0x5B +#define ZMHH 0x5C +#define BPADDR 0x7C +#define BPDATA 0x7D +#define CTRL2 0x86 +#define CTRL3 0x87 +#define SIZEL 0x8C +#define HSIZE8 0xC0 +#define VSIZE8 0xC1 +#define CTRL0 0xC2 +#define CTRL1 0xC3 +#define R_DVP_SP 0xD3 +#define IMAGE_MODE 0xDA +#define RESET 0xE0 +#define MS_SP 0xF0 +#define SS_ID 0xF7 +#define SS_CTRL 0xF7 +#define MC_BIST 0xF9 +#define MC_AL 0xFA +#define MC_AH 0xFB +#define MC_D 0xFC +#define P_CMD 0xFD +#define P_STATUS 0xFE +#define BANK_SEL 0xFF + +#define CTRLI_LP_DP 0x80 +#define CTRLI_ROUND 0x40 + +#define CTRL0_AEC_EN 0x80 +#define CTRL0_AEC_SEL 0x40 +#define CTRL0_STAT_SEL 0x20 +#define CTRL0_VFIRST 0x10 +#define CTRL0_YUV422 0x08 +#define CTRL0_YUV_EN 0x04 +#define CTRL0_RGB_EN 0x02 +#define CTRL0_RAW_EN 0x01 + +#define CTRL2_DCW_EN 0x20 +#define CTRL2_SDE_EN 0x10 +#define CTRL2_UV_ADJ_EN 0x08 +#define CTRL2_UV_AVG_EN 0x04 +#define CTRL2_CMX_EN 0x01 + +#define CTRL3_BPC_EN 0x80 +#define CTRL3_WPC_EN 0x40 + +#define R_DVP_SP_AUTO_MODE 0x80 + +#define R_BYPASS_DSP_EN 0x00 +#define R_BYPASS_DSP_BYPAS 0x01 + +#define IMAGE_MODE_Y8_DVP_EN 0x40 +#define IMAGE_MODE_JPEG_EN 0x10 +#define IMAGE_MODE_YUV422 0x00 +#define IMAGE_MODE_RAW10 0x04 +#define IMAGE_MODE_RGB565 0x08 +#define IMAGE_MODE_HREF_VSYNC 0x02 +#define IMAGE_MODE_LBYTE_FIRST 0x01 + +#define RESET_MICROC 0x40 +#define RESET_SCCB 0x20 +#define RESET_JPEG 0x10 +#define RESET_DVP 0x04 +#define RESET_IPU 0x02 +#define RESET_CIF 0x01 + +#define MC_BIST_RESET 0x80 +#define MC_BIST_BOOT_ROM_SEL 0x40 +#define MC_BIST_12KB_SEL 0x20 +#define MC_BIST_12KB_MASK 0x30 +#define MC_BIST_512KB_SEL 0x08 +#define MC_BIST_512KB_MASK 0x0C +#define MC_BIST_BUSY_BIT_R 0x02 +#define MC_BIST_MC_RES_ONE_SH_W 0x02 +#define MC_BIST_LAUNCH 0x01 + + +typedef enum { + BANK_DSP, BANK_SENSOR, BANK_MAX +} ov2640_bank_t; + +/* Sensor register bank FF=0x01*/ +#define GAIN 0x00 +#define COM1 0x03 +#define REG04 0x04 +#define REG08 0x08 +#define COM2 0x09 +#define REG_PID 0x0A +#define REG_VER 0x0B +#define COM3 0x0C +#define COM4 0x0D +#define AEC 0x10 +#define CLKRC 0x11 +#define COM7 0x12 +#define COM8 0x13 +#define COM9 0x14 /* AGC gain ceiling */ +#define COM10 0x15 +#define HSTART 0x17 +#define HSTOP 0x18 +#define VSTART 0x19 +#define VSTOP 0x1A +#define REG_MIDH 0x1C +#define REG_MIDL 0x1D +#define AEW 0x24 +#define AEB 0x25 +#define VV 0x26 +#define REG2A 0x2A +#define FRARL 0x2B +#define ADDVSL 0x2D +#define ADDVSH 0x2E +#define YAVG 0x2F +#define HSDY 0x30 +#define HEDY 0x31 +#define REG32 0x32 +#define ARCOM2 0x34 +#define REG45 0x45 +#define FLL 0x46 +#define FLH 0x47 +#define COM19 0x48 +#define ZOOMS 0x49 +#define COM22 0x4B +#define COM25 0x4E +#define BD50 0x4F +#define BD60 0x50 +#define REG5D 0x5D +#define REG5E 0x5E +#define REG5F 0x5F +#define REG60 0x60 +#define HISTO_LOW 0x61 +#define HISTO_HIGH 0x62 + +#define REG04_DEFAULT 0x28 +#define REG04_HFLIP_IMG 0x80 +#define REG04_VFLIP_IMG 0x40 +#define REG04_VREF_EN 0x10 +#define REG04_HREF_EN 0x08 +#define REG04_SET(x) (REG04_DEFAULT|x) + +#define COM2_STDBY 0x10 +#define COM2_OUT_DRIVE_1x 0x00 +#define COM2_OUT_DRIVE_2x 0x01 +#define COM2_OUT_DRIVE_3x 0x02 +#define COM2_OUT_DRIVE_4x 0x03 + +#define COM3_DEFAULT 0x38 +#define COM3_BAND_50Hz 0x04 +#define COM3_BAND_60Hz 0x00 +#define COM3_BAND_AUTO 0x02 +#define COM3_BAND_SET(x) (COM3_DEFAULT|x) + +#define COM7_SRST 0x80 +#define COM7_RES_UXGA 0x00 /* UXGA */ +#define COM7_RES_SVGA 0x40 /* SVGA */ +#define COM7_RES_CIF 0x20 /* CIF */ +#define COM7_ZOOM_EN 0x04 /* Enable Zoom */ +#define COM7_COLOR_BAR 0x02 /* Enable Color Bar Test */ + +#define COM8_DEFAULT 0xC0 +#define COM8_BNDF_EN 0x20 /* Enable Banding filter */ +#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */ +#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */ +#define COM8_SET(x) (COM8_DEFAULT|x) + +#define COM9_DEFAULT 0x08 +#define COM9_AGC_GAIN_2x 0x00 /* AGC: 2x */ +#define COM9_AGC_GAIN_4x 0x01 /* AGC: 4x */ +#define COM9_AGC_GAIN_8x 0x02 /* AGC: 8x */ +#define COM9_AGC_GAIN_16x 0x03 /* AGC: 16x */ +#define COM9_AGC_GAIN_32x 0x04 /* AGC: 32x */ +#define COM9_AGC_GAIN_64x 0x05 /* AGC: 64x */ +#define COM9_AGC_GAIN_128x 0x06 /* AGC: 128x */ +#define COM9_AGC_SET(x) (COM9_DEFAULT|(x<<5)) + +#define COM10_HREF_EN 0x80 /* HSYNC changes to HREF */ +#define COM10_HSYNC_EN 0x40 /* HREF changes to HSYNC */ +#define COM10_PCLK_FREE 0x20 /* PCLK output option: free running PCLK */ +#define COM10_PCLK_EDGE 0x10 /* Data is updated at the rising edge of PCLK */ +#define COM10_HREF_NEG 0x08 /* HREF negative */ +#define COM10_VSYNC_NEG 0x02 /* VSYNC negative */ +#define COM10_HSYNC_NEG 0x01 /* HSYNC negative */ + +#define CTRL1_AWB 0x08 /* Enable AWB */ + +#define VV_AGC_TH_SET(h,l) ((h<<4)|(l&0x0F)) + +#define REG32_UXGA 0x36 +#define REG32_SVGA 0x09 +#define REG32_CIF 0x89 + +#define CLKRC_2X 0x80 +#define CLKRC_2X_UXGA (0x01 | CLKRC_2X) +#define CLKRC_2X_SVGA CLKRC_2X +#define CLKRC_2X_CIF CLKRC_2X + +#endif //__REG_REGS_H__ \ No newline at end of file diff --git a/src/pio/image/image.pio.h b/src/pio/image/image.pio.h index 91d02b0..7e7a3fd 100644 --- a/src/pio/image/image.pio.h +++ b/src/pio/image/image.pio.h @@ -16,13 +16,21 @@ #define image_wrap 3 #define image_pio_version 1 +// static const uint16_t image_program_instructions[] = { +// // .wrap_target +// 0x20a9, // 0: wait 1 pin, 9 +// 0x20a8, // 1: wait 1 pin, 8 +// 0x4008, // 2: in pins, 8 +// 0x2028, // 3: wait 0 pin, 8 +// // .wrap +// }; static const uint16_t image_program_instructions[] = { - // .wrap_target + // .wrap_target 0x20a9, // 0: wait 1 pin, 9 0x20a8, // 1: wait 1 pin, 8 0x4008, // 2: in pins, 8 0x2028, // 3: wait 0 pin, 8 - // .wrap + // .wrap }; #if !PICO_NO_HARDWARE @@ -46,7 +54,7 @@ void image_program_init(PIO pio, uint sm, uint offset, uint pin_base) { pio_sm_set_consecutive_pindirs(pio, sm, pin_base, 10, false); pio_sm_config c = image_program_get_default_config(offset); sm_config_set_in_pins(&c, pin_base); - sm_config_set_in_shift(&c, false, true, 8); + sm_config_set_in_shift(&c, false, true, 16); // TODO: if something is not working check this i.e revert back to 8 together with dma transfer sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); pio_sm_init(pio, sm, offset, &c); pio_sm_set_enabled(pio, sm, true);