diff --git a/src/PicoIris.cpp b/src/PicoIris.cpp index ddf1dff..df98c8e 100644 --- a/src/PicoIris.cpp +++ b/src/PicoIris.cpp @@ -22,9 +22,9 @@ 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 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 + .pin_data_base = 7, /*!< this pin + 7 consecutive will be used D0-D7 PCLK HREF */ + .pin_vsync = 18, /*!< GPIO pin for camera VSYNC line */ + .xclk_div = 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 */ }; @@ -36,7 +36,7 @@ int main() //printf("Hello World!"); OV2640 left_cam = OV2640(left_eye_config); - left_cam.begin(DMA_IRQ_0); + left_cam.begin(DMA_IRQ_0, 1); //left_cam.capture_frame(); //fwrite(left_cam.fb, 1, sizeof(left_cam.fb), stdout); while (true) { diff --git a/src/ov2640/camera.cpp b/src/ov2640/camera.cpp index cba2553..b44c43e 100644 --- a/src/ov2640/camera.cpp +++ b/src/ov2640/camera.cpp @@ -16,7 +16,7 @@ static volatile bool frameReady = false; // true at end-of-frame static volatile bool suspended = true; -void* pointer; +static void* pointer; static void iCap_vsync_irq(uint gpio, uint32_t events) { if (!suspended) { @@ -29,11 +29,9 @@ static void iCap_vsync_irq(uint gpio, uint32_t events) { static void iCap_dma_finish_irq() { frameReady = true; suspended = true; - //printf("iCap_dma_finish_irq"); dma_channel_set_write_addr(0, (uint8_t *)(pointer), false); - printf("0x%\n", (uintptr_t)pointer); dma_hw->ints0 = 1u << 0; - } +} // TODO: Stolen from Adafruit repo (Check if correct) @@ -49,6 +47,7 @@ static uint16_t capture_pio_opcodes[] = { 0b0010000000000000, // WAIT 0 GPIO 0 (mask in PCLK pin before use) }; + static struct pio_program cap_pio_program = { .instructions = capture_pio_opcodes, .length = sizeof capture_pio_opcodes / sizeof capture_pio_opcodes[0], @@ -56,6 +55,7 @@ static struct pio_program cap_pio_program = { }; +// Complete camera init dumped from running esp32 (240x240 JPEG qty: 7) register_val_t OV2640_stolem_jpeg_init[] = { {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR}, {OV2640_REG1_COM7, OV2640_COM7_SRST}, @@ -218,6 +218,7 @@ register_val_t OV2640_stolem_jpeg_init[] = { {0x05, 0x00} }; + register_val_t OV2640_init[] = { // Ideas from rp2040_ov2640-main repo // OV2640 camera initialization after reset @@ -472,7 +473,6 @@ register_val_t OV2640_init[] = { {OV2640_REG0_RESET, 0x00} }; // Go - // Stolem from esp32-camera register_val_t OV2640_jpeg[] = { {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, @@ -567,11 +567,12 @@ 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}, + OV2640_IMAGE_MODE_BYTE_SWAP}, // TODO: Check if byteswap is supposed to be enabled? {0xD7, 0x03}, // Mystery init values {0xE1, 0x77}, // seen in other examples {OV2640_REG0_RESET, 0x00} }; // Go + register_val_t OV2640_qqvga[] = { {OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0 {OV2640_REG0_RESET, OV2640_RESET_DVP}, @@ -610,43 +611,25 @@ OV2640::OV2640(camera_config_t config) this->config = config; memset(&this->fb, 0x00, sizeof(this->fb)); pointer = &this->fb; - //this->fb = image_buf; } -// Pin interrupt on VSYNC calls this to start DMA transfer (unless suspended). -// static void vsync_irq(uint gpio, uint32_t events) -// { -// pio_sm_clear_fifos(pio2, sm); -// dma_channel_start(dma_channel); -// } -// static void dma_finish_irq() -// { -// // Channel MUST be reconfigured each time (to reset the dest address). -// dma_channel_set_write_addr(dma_channel, -// (uint8_t *)(image_buf), false); -// dma_hw->ints0 = 1u << dma_channel; // Clear IRQ -// uint32_t data = pio2->rxf[sm]; -// fwrite(&data, 1, 32, stdout); -// } - -int OV2640::begin(int dma_irq) +// mode 0 - adafruit rgb, 1 - meine jpeg, 2 - stolem jpeg +int OV2640::begin(int dma_irq, int mode) // mode is just here to make debbuging easier { // Initialize peripherals for parallel+I2C camera: // XCLK generation (~18.71 MHz) 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, this->config.xclk_div - 1); + pwm_set_gpio_level(this->config.xclk_div / 2, 4); pwm_set_enabled(slice_num, true); // Init SCCB - //prtintf("Init SCCB\n"); this->sccb = SCCB(this->config.pin_sccb_sda, this->config.pin_sccb_scl); this->sccb.begin(this->config.sccb_ctrl); - //prtintf("Inited SCCB\n"); // ENABLE AND/OR RESET CAMERA -------------------------------------------- // Unsure of camera startup time from beginning of input clock. @@ -658,20 +641,30 @@ int OV2640::begin(int dma_irq) this->sccb.writeRegister(OV2640_REG1_COM7, OV2640_COM7_SRST); // System reset sleep_ms(300); // Datasheet: tS:RESET = 1 ms - // Init main camera settings - //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_qqvga, sizeof(OV2640_qqvga)/sizeof(OV2640_qqvga[0])); - this->sccb.writeList(OV2640_rgb, sizeof(OV2640_rgb)/sizeof(OV2640_rgb[0])); + switch(mode) { + case 0: + this->sccb.writeList(OV2640_init, sizeof(OV2640_init)/sizeof(OV2640_init[0])); + this->sccb.writeList(OV2640_CIF, sizeof(OV2640_CIF)/sizeof(OV2640_CIF[0])); + this->sccb.writeList(OV2640_rgb, sizeof(OV2640_rgb)/sizeof(OV2640_qqvga[0])); + break; + case 1: + this->sccb.writeList(OV2640_init, sizeof(OV2640_init)/sizeof(OV2640_init[0])); + this->sccb.writeList(OV2640_CIF, sizeof(OV2640_CIF)/sizeof(OV2640_CIF[0])); + this->sccb.writeList(OV2640_jpeg, sizeof(OV2640_jpeg)/sizeof(OV2640_jpeg[0])); + break; + case 2: + this->sccb.writeList(OV2640_stolem_jpeg_init, sizeof(OV2640_stolem_jpeg_init)/sizeof(OV2640_stolem_jpeg_init[0])); + break; + } + + //this->sccb.writeList(OV2640_test_ptrn, sizeof(OV2640_test_ptrn)/sizeof(OV2640_test_ptrn[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->sccb.writeList(OV2640_jpeg, sizeof(OV2640_jpeg)/sizeof(OV2640_jzpeg[0])); //this->set_gainceiling(GAINCEILING_2X); //sleep_ms(10); @@ -814,35 +807,35 @@ int OV2640::begin(int dma_irq) //! 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; + 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} - // }; + 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); + 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) { @@ -921,4 +914,5 @@ if (flags & 0b0100) { handle_sm_2(); } if (flags & 0b1000) { handle_sm_3(); } */ -// TODO: add all of the specific controls like brightness and all of that scheiße \ No newline at end of file +// TODO: add all of the specific controls like brightness and all of that scheiße +// THERE ARE MORE COMMENTS THEN ACTUAL CODE AT THIS POINT??? \ No newline at end of file diff --git a/src/ov2640/camera.hpp b/src/ov2640/camera.hpp index a38ef27..c90ea83 100644 --- a/src/ov2640/camera.hpp +++ b/src/ov2640/camera.hpp @@ -11,7 +11,7 @@ typedef struct { int pin_sccb_scl; /*!< GPIO pin for camera SCL line */ int pin_data_base; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ int pin_vsync; /*!< GPIO pin for camera VSYNC line */ - int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. */ //! Figure out the highest it can go to + int xclk_div; /*!< XCLK divider; 150 / div = XCLK freq. 8 = ~18.71 MHz */ //! Figure out the highest it can go to uint8_t sccb_ctrl; /* Select i2c controller ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio2 */ } camera_config_t; @@ -35,7 +35,7 @@ public: OV2640(camera_config_t config); ~OV2640(); - int begin(int dma_irq); + int begin(int dma_irq, int mode); void set_quality(int quality); void set_gainceiling(gainceiling_t gainceiling); void set_bpc(bool enable); @@ -44,7 +44,7 @@ public: void set_framesize(); void capture_frame(); - uint8_t fb[(352*288)]; + uint8_t fb[(352*288)]; // TODO: at some point change to a pointer camera_config_t config; private: