diff --git a/.gitignore b/.gitignore index 10561bd..d40747b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/ -.vscode \ No newline at end of file +.vscode +.DS_Store diff --git a/bus_scan.c b/bus_scan.c index f54b19d..f87ce07 100644 --- a/bus_scan.c +++ b/bus_scan.c @@ -38,7 +38,8 @@ bool reserved_addr(uint8_t addr) { return (addr & 0x78) == 0 || (addr & 0x78) == 0x78; } - +#define PICO_DEFAULT_I2C_SDA_PIN 22 +#define PICO_DEFAULT_I2C_SCL_PIN 19 int main() { // Enable UART so we can print status output stdio_init_all(); @@ -47,47 +48,51 @@ int main() { puts("Default I2C pins were not defined"); #else // This example will use I2C0 on the default SDA and SCL pins (GP4, GP5 on a Pico) - gpio_set_function(3, GPIO_FUNC_PWM); - uint slice_num = pwm_gpio_to_slice_num(3); + gpio_set_function(11, GPIO_FUNC_PWM); + uint slice_num = pwm_gpio_to_slice_num(11); // 6 cycles (0 to 5), 125 MHz / 6 = ~20.83 MHz wrap rate pwm_set_wrap(slice_num, 5); - pwm_set_gpio_level(3, 3); + pwm_set_gpio_level(11, 3); pwm_set_enabled(slice_num, true); sleep_ms(1000); - i2c_init(i2c_default, 100 * 1000); - gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C); - gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C); - gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); - gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN); + i2c_init(i2c1, 100 * 1000); + gpio_set_function(22, GPIO_FUNC_I2C); + gpio_set_function(19, GPIO_FUNC_I2C); + gpio_pull_up(22); + gpio_pull_up(19); // Make the I2C pins available to picotool - bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C)); + bi_decl(bi_2pins_with_func(22, 19, GPIO_FUNC_I2C)); + while(true){ + printf("\nI2C Bus Scan\n"); + printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); - printf("\nI2C Bus Scan\n"); - printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); + for (int addr = 0; addr < (1 << 7); ++addr) { + if (addr % 16 == 0) { + printf("%02x ", addr); + } - for (int addr = 0; addr < (1 << 7); ++addr) { - if (addr % 16 == 0) { - printf("%02x ", addr); + // Perform a 1-byte dummy read from the probe address. If a slave + // acknowledges this address, the function returns the number of bytes + // transferred. If the address byte is ignored, the function returns + // -1. + + // Skip over any reserved addresses. + int ret; + uint8_t rxdata; + if (reserved_addr(addr)) + ret = PICO_ERROR_GENERIC; + else + ret = i2c_read_blocking(i2c1, addr, &rxdata, 1, false); + + + printf(ret < 0 ? "." : "@"); + printf(addr % 16 == 15 ? "\n" : " "); } - - // Perform a 1-byte dummy read from the probe address. If a slave - // acknowledges this address, the function returns the number of bytes - // transferred. If the address byte is ignored, the function returns - // -1. - - // Skip over any reserved addresses. - int ret; - uint8_t rxdata; - if (reserved_addr(addr)) - ret = PICO_ERROR_GENERIC; - else - ret = i2c_read_blocking(i2c_default, addr, &rxdata, 1, false); - - printf(ret < 0 ? "." : "@"); - printf(addr % 16 == 15 ? "\n" : " "); + printf("Done.\n"); + sleep_ms(1000); } - printf("Done.\n"); + return 0; #endif } \ No newline at end of file diff --git a/image_receiver.py b/image_receiver.py index 4b07816..41d6611 100644 --- a/image_receiver.py +++ b/image_receiver.py @@ -8,7 +8,7 @@ import cv2 # Added OpenCV for image processing # Configure serial port - this will connect to the USB serial port from the Pico PORT = '/dev/tty.usbmodem101' # Adjust for your system -BAUD_RATE = 57600 # Reduced to match the Pico's baud rate for debugging +BAUD_RATE = 3000 # Reduced to match the Pico's baud rate for debugging TIMEOUT = 60 # Increased timeout for slower data transfer # Enable detailed debugging information @@ -231,14 +231,14 @@ def process_binary_data(data): if received_checksum != calculated_checksum: print("Error: Checksum mismatch") - return None + #return None # Verify frame footer footer_start = checksum_start + 4 footer = data[footer_start:footer_start+len(FRAME_FOOTER)] if footer != FRAME_FOOTER: print("Error: Invalid frame footer") - return None + #return None print("Frame successfully extracted and verified!") return frame_data diff --git a/src/PicoIris.cpp b/src/PicoIris.cpp index 03b1f11..a209684 100644 --- a/src/PicoIris.cpp +++ b/src/PicoIris.cpp @@ -26,13 +26,22 @@ const int FRAME_MARKER_SIZE = 4; camera_config_t left_eye_config = { .pin_pwdn = -1, /*!< GPIO pin for camera power down line */ .pin_reset = -1, /*!< GPIO pin for camera reset line */ - .pin_xclk = 3, /*!< GPIO pin for camera XCLK line */ - .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 */ + .pin_xclk = 11, /*!< GPIO pin for camera XCLK line */ + .pin_sccb_sda = 22, /*!< GPIO pin for camera SDA line */ + .pin_sccb_scl = 19, /*!< GPIO pin for camera SCL line */ + .pin_data_9 = 14, /*!< this pin + 7 consecutive will be used D0-D7 PCLK HREF */ + .pin_data_8 = 12, + .pin_data_7 = 10, + .pin_data_6 = 8, + .pin_data_5 = 6, + .pin_data_4 = 5, + .pin_data_3 = 4, + .pin_data_2 = 3, + .pin_vsync = 17, /*!< GPIO pin for camera VSYNC line */ + .pin_hsync = 15, /*!< GPIO pin for camera VSYNC line */ + .xclk_freq_hz = 0, /*!< Frequency of XCLK signal, in Hz. */ - .sccb_ctrl = 0, /* Select i2c controller ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio2 */ + .sccb_ctrl = 1, /* Select i2c controller ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio2 */ }; // Send a properly framed image using printf for binary data @@ -46,7 +55,9 @@ void send_frame(const void* buffer, size_t size) { // Send frame header fwrite(FRAME_HEADER, 1, FRAME_MARKER_SIZE, stdout); - + sleep_ms(100); // Small delay to ensure the text is transmitted separately + printf("test...."); + // Send frame size (4 bytes, little-endian) uint8_t size_bytes[4]; size_bytes[0] = size & 0xFF; @@ -54,7 +65,8 @@ void send_frame(const void* buffer, size_t size) { size_bytes[2] = (size >> 16) & 0xFF; size_bytes[3] = (size >> 24) & 0xFF; fwrite(size_bytes, 1, 4, stdout); - + printf("test2...."); + // Calculate checksum uint32_t checksum = 0; const uint8_t* buf = (const uint8_t*)buffer; @@ -64,7 +76,8 @@ void send_frame(const void* buffer, size_t size) { // Send frame data fwrite(buf, 1, size, stdout); - + sleep_ms(100); // Small delay to ensure the text is transmitted separately + // Send checksum (4 bytes) uint8_t checksum_bytes[4]; checksum_bytes[0] = checksum & 0xFF; @@ -72,10 +85,11 @@ void send_frame(const void* buffer, size_t size) { checksum_bytes[2] = (checksum >> 16) & 0xFF; checksum_bytes[3] = (checksum >> 24) & 0xFF; fwrite(checksum_bytes, 1, 4, stdout); - + sleep_ms(100); // Small delay to ensure the text is transmitted separately // Send frame footer fwrite(FRAME_FOOTER, 1, FRAME_MARKER_SIZE, stdout); - + sleep_ms(100); // Small delay to ensure the text is transmitted separately + // Flush to ensure all binary data is sent fflush(stdout); diff --git a/src/ov2640/SCCB.cpp b/src/ov2640/SCCB.cpp index f4028f3..52d44bb 100644 --- a/src/ov2640/SCCB.cpp +++ b/src/ov2640/SCCB.cpp @@ -22,7 +22,7 @@ int SCCB::begin(uint8_t ctrl) this->ctrl = ctrl; if (ctrl < 2) { this->i2cc = ctrl == 0 ? i2c0 : i2c1; - i2c_init(this->i2cc, 5 * 1000); + i2c_init(this->i2cc, 100 * 1000); gpio_set_function(this->sda, GPIO_FUNC_I2C); gpio_set_function(this->scl, GPIO_FUNC_I2C); gpio_pull_up(this->sda); diff --git a/src/ov2640/camera.cpp b/src/ov2640/camera.cpp index 7199aef..c63b8a2 100644 --- a/src/ov2640/camera.cpp +++ b/src/ov2640/camera.cpp @@ -610,9 +610,8 @@ register_val_t OV2640_qqvga[] = { OV2640::OV2640(camera_config_t config) { - uint8_t fb[160 * 120 * 2]; this->config = config; - memset(&this->fb, 0x00, sizeof(this->fb)); + memset(&this->fb, 0x00, sizeof(this->fb)); pointer = &this->fb; //this->fb = image_buf; } @@ -675,10 +674,10 @@ int OV2640::begin(int dma_irq) this->sccb.writeList(OV2640_rgb, sizeof(OV2640_rgb)/sizeof(OV2640_rgb[0])); // // Enable color bar test pattern for debugging - // printf("Enabling color bar test pattern...\n"); - // this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR); - // this->sccb.writeRegister(OV2640_REG1_COM7, OV2640_COM7_COLORBAR); // Output test pattern - // printf("Test pattern enabled\n"); + //printf("Enabling color bar test pattern...\n"); + //this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR); + //this->sccb.writeRegister(OV2640_REG1_COM7, OV2640_COM7_COLORBAR); // Output test pattern + //printf("Test pattern enabled\n"); // GPIO pin setup printf("Setting up GPIO pins for camera data...\n"); @@ -686,19 +685,47 @@ int OV2640::begin(int dma_irq) gpio_set_dir(this->config.pin_vsync, GPIO_IN); gpio_pull_down(this->config.pin_vsync); - printf("Initializing data pins %d through %d...\n", - this->config.pin_data_base, this->config.pin_data_base + 9); - for (uint8_t i = 0; i < 10; i++) - { - gpio_init(this->config.pin_data_base + i); - gpio_set_dir(this->config.pin_data_base + i, GPIO_IN); - } + + + gpio_init(this->config.pin_data_9 ); + gpio_set_dir(this->config.pin_data_9, GPIO_IN); + gpio_init(this->config.pin_data_8 ); + gpio_set_dir(this->config.pin_data_8, GPIO_IN); + gpio_init(this->config.pin_data_7 ); + gpio_set_dir(this->config.pin_data_7, GPIO_IN); + gpio_init(this->config.pin_data_6 ); + gpio_set_dir(this->config.pin_data_6, GPIO_IN); + gpio_init(this->config.pin_data_5 ); + gpio_set_dir(this->config.pin_data_5, GPIO_IN); + gpio_init(this->config.pin_data_4 ); + gpio_set_dir(this->config.pin_data_4, GPIO_IN); + gpio_init(this->config.pin_data_3 ); + gpio_set_dir(this->config.pin_data_3, GPIO_IN); + gpio_init(this->config.pin_data_2 ); + gpio_set_dir(this->config.pin_data_2, GPIO_IN); + + + + + + + printf("GPIO initialization complete\n"); // PIO setup for image capture printf("Setting up PIO for image capture...\n"); uint offset = pio_add_program(pio2, &image_program); - image_program_init(pio2, 0, offset, this->config.pin_data_base); + + image_program_init(pio2, 0, offset, this->config.pin_data_9); + image_program_init(pio2, 0, offset, this->config.pin_data_8); + image_program_init(pio2, 0, offset, this->config.pin_data_7); + image_program_init(pio2, 0, offset, this->config.pin_data_6); + image_program_init(pio2, 0, offset, this->config.pin_data_5); + image_program_init(pio2, 0, offset, this->config.pin_data_4); + image_program_init(pio2, 0, offset, this->config.pin_data_3); + image_program_init(pio2, 0, offset, this->config.pin_data_2); + image_program_init(pio2, 0, offset, this->config.pin_hsync); + printf("PIO setup complete\n"); // DMA setup @@ -854,6 +881,40 @@ void OV2640::capture_frame() { printf("Frame captured successfully\n"); } +// void OV2640::set_resolution(uint16_t width, uint16_t height) { +// // Set resolution registers +// this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); // DSP bank select 0 +// this->sccb.writeRegister(OV2640_REG0_HSIZE8, (width >> 3) & 0xFF); // HSIZE high bits +// this->sccb.writeRegister(OV2640_REG0_VSIZE8, (height >> 3) & 0xFF); // VSIZE high bits +// this->sccb.writeRegister(OV2640_REG0_HSIZE, width & 0xFF); // HSIZE low bits +// this->sccb.writeRegister(OV2640_REG0_VSIZE, height & 0xFF); // VSIZE low bits +// this->sccb.writeRegister(OV2640_REG0_ZMOW, width & 0xFF); // OUTW low bits +// this->sccb.writeRegister(OV2640_REG0_ZMOH, height & 0xFF); // OUTH low bits +// this->sccb.writeRegister(OV2640_REG0_ZMHH, ((height >> 8) & 0x04) | ((width >> 8) & 0x03)); // OUTW/H high bits +// printf("Resolution set to %dx%d\n", width, height); +// } + +// void OV2640::set_resolution_vga() { +// // Set resolution to VGA (640x480) +// uint16_t width = 640; +// uint16_t height = 480; + +// // Adjust frame buffer size for VGA resolution +// this->fb = new uint8_t[width * height * 2]; // Assuming 2 bytes per pixel (RGB565) +// pointer = this->fb; + +// // Set resolution registers +// this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP); // DSP bank select 0 +// this->sccb.writeRegister(OV2640_REG0_HSIZE8, (width >> 3) & 0xFF); // HSIZE high bits +// this->sccb.writeRegister(OV2640_REG0_VSIZE8, (height >> 3) & 0xFF); // VSIZE high bits +// this->sccb.writeRegister(OV2640_REG0_HSIZE, width & 0xFF); // HSIZE low bits +// this->sccb.writeRegister(OV2640_REG0_VSIZE, height & 0xFF); // VSIZE low bits +// this->sccb.writeRegister(OV2640_REG0_ZMOW, width & 0xFF); // OUTW low bits +// this->sccb.writeRegister(OV2640_REG0_ZMOH, height & 0xFF); // OUTH low bits +// this->sccb.writeRegister(OV2640_REG0_ZMHH, ((height >> 8) & 0x04) | ((width >> 8) & 0x03)); // OUTW/H high bits + +// printf("Resolution set to VGA (640x480)\n"); +// } //! https://forums.raspberrypi.com/viewtopic.php?t=339299 // TODO: change to switches and experiment with state machines, check if I can kinda reserve dma's so 0-3 would indicate state machines 0-3 diff --git a/src/ov2640/camera.hpp b/src/ov2640/camera.hpp index 9b3624e..5259a6e 100644 --- a/src/ov2640/camera.hpp +++ b/src/ov2640/camera.hpp @@ -9,8 +9,16 @@ typedef struct { int pin_xclk; /*!< GPIO pin for camera XCLK line */ //? in theory could be shared or perhaps ommited? int pin_sccb_sda; /*!< GPIO pin for camera SDA line */ 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_data_9; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_8; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_7; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_6; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_5; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_4; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_3; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ + int pin_data_2; /*!< this pin + 9 consecutive will be used D0-D7 PCLK HREF */ int pin_vsync; /*!< GPIO pin for camera VSYNC line */ + int pin_hsync; /*!< GPIO pin for camera VSYNC line */ int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. */ //! 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; @@ -49,7 +57,7 @@ public: void set_framesize(); void capture_frame(); - uint8_t fb[(352*288)]; + uint8_t* fb; // Changed from fixed array to pointer camera_config_t config; private: diff --git a/src/ov2640/image_pio_wrapper.cpp b/src/ov2640/image_pio_wrapper.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/pio/image/image.pio.h b/src/pio/image/image.pio.h index 7e7a3fd..ccc51d1 100644 --- a/src/pio/image/image.pio.h +++ b/src/pio/image/image.pio.h @@ -60,5 +60,7 @@ void image_program_init(PIO pio, uint sm, uint offset, uint pin_base) { pio_sm_set_enabled(pio, sm, true); } +// New function to initialize PIO with camera configuration pins - declaration only +// In image.pio.h, replace the implementation with a declaration #endif