Fix compilation issues
mmm yes debugging with printf
This commit is contained in:
parent
76bf0c144e
commit
c36531c679
@ -35,7 +35,8 @@ pico_sdk_init()
|
|||||||
|
|
||||||
# Add executable. Default name is the project name, version 0.1
|
# Add executable. Default name is the project name, version 0.1
|
||||||
|
|
||||||
add_executable(PicoIris src/PicoIris.cpp )
|
add_executable(PicoIris src/PicoIris.cpp src/ov2640/camera.cpp src/ov2640/SCCB.cpp src/pio/i2c/pio_i2c.c)
|
||||||
|
#add_executable(PicoIris bus_scan.c)
|
||||||
|
|
||||||
pico_set_program_name(PicoIris "PicoIris")
|
pico_set_program_name(PicoIris "PicoIris")
|
||||||
pico_set_program_version(PicoIris "0.1")
|
pico_set_program_version(PicoIris "0.1")
|
||||||
@ -47,22 +48,21 @@ pico_generate_pio_header(PicoIris ${CMAKE_CURRENT_LIST_DIR}/src/pio/i2c/i2c.pio)
|
|||||||
pico_enable_stdio_uart(PicoIris 0)
|
pico_enable_stdio_uart(PicoIris 0)
|
||||||
pico_enable_stdio_usb(PicoIris 1)
|
pico_enable_stdio_usb(PicoIris 1)
|
||||||
|
|
||||||
# Add the standard library to the build
|
|
||||||
target_link_libraries(PicoIris
|
|
||||||
pico_stdlib)
|
|
||||||
|
|
||||||
# Add the standard include files to the build
|
# Add the standard include files to the build
|
||||||
target_include_directories(PicoIris PRIVATE
|
target_include_directories(PicoIris PRIVATE
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
src/
|
src/
|
||||||
src/ov2640/
|
src/ov2640/
|
||||||
|
src/pio/i2c/
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add any user requested libraries
|
# Add any user requested libraries
|
||||||
target_link_libraries(PicoIris
|
target_link_libraries(PicoIris
|
||||||
|
pico_stdlib
|
||||||
hardware_spi
|
hardware_spi
|
||||||
hardware_i2c
|
hardware_i2c
|
||||||
hardware_dma
|
hardware_dma
|
||||||
|
hardware_pwm
|
||||||
hardware_pio
|
hardware_pio
|
||||||
hardware_interp
|
hardware_interp
|
||||||
hardware_timer
|
hardware_timer
|
||||||
|
|||||||
93
bus_scan.c
Normal file
93
bus_scan.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Sweep through all 7-bit I2C addresses, to see if any slaves are present on
|
||||||
|
// the I2C bus. Print out a table that looks like this:
|
||||||
|
//
|
||||||
|
// I2C Bus Scan
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
|
// 00 . . . . . . . . . . . . . . . .
|
||||||
|
// 10 . . @ . . . . . . . . . . . . .
|
||||||
|
// 20 . . . . . . . . . . . . . . . .
|
||||||
|
// 30 . . . . @ . . . . . . . . . . .
|
||||||
|
// 40 . . . . . . . . . . . . . . . .
|
||||||
|
// 50 . . . . . . . . . . . . . . . .
|
||||||
|
// 60 . . . . . . . . . . . . . . . .
|
||||||
|
// 70 . . . . . . . . . . . . . . . .
|
||||||
|
// E.g. if addresses 0x12 and 0x34 were acknowledged.
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "pico/binary_info.h"
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/spi.h"
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
#include "hardware/dma.h"
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
#include "hardware/interp.h"
|
||||||
|
#include "hardware/timer.h"
|
||||||
|
#include "hardware/pwm.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
#include "hardware/uart.h"
|
||||||
|
// I2C reserves some addresses for special purposes. We exclude these from the scan.
|
||||||
|
// These are any addresses of the form 000 0xxx or 111 1xxx
|
||||||
|
bool reserved_addr(uint8_t addr) {
|
||||||
|
return (addr & 0x78) == 0 || (addr & 0x78) == 0x78;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Enable UART so we can print status output
|
||||||
|
stdio_init_all();
|
||||||
|
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
|
||||||
|
#warning i2c/bus_scan example requires a board with I2C pins
|
||||||
|
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);
|
||||||
|
// 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_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);
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@ -18,13 +18,13 @@
|
|||||||
camera_config_t left_eye_config = {
|
camera_config_t left_eye_config = {
|
||||||
.pin_pwdn = -1, /*!< GPIO pin for camera power down line */ //? Also called PWDN, or set to -1 and tie to GND
|
.pin_pwdn = -1, /*!< GPIO pin for camera power down line */ //? Also called PWDN, or set to -1 and tie to GND
|
||||||
.pin_reset = -1, /*!< GPIO pin for camera reset line */ //? Cam reset, or set to -1 and tie to 3.3V
|
.pin_reset = -1, /*!< GPIO pin for camera reset line */ //? Cam reset, or set to -1 and tie to 3.3V
|
||||||
.pin_xclk = 0, /*!< GPIO pin for camera XCLK line */ //? in theory could be shared or perhaps ommited?
|
.pin_xclk = 3, /*!< GPIO pin for camera XCLK line */ //? in theory could be shared or perhaps ommited?
|
||||||
.pin_sccb_sda = 0, /*!< GPIO pin for camera SDA line */
|
.pin_sccb_sda = 4, /*!< GPIO pin for camera SDA line */
|
||||||
.pin_sccb_scl = 0, /*!< GPIO pin for camera SCL line */
|
.pin_sccb_scl = 5, /*!< GPIO pin for camera SCL line */
|
||||||
.pin_data_base = 0, /*!< this pin + 7 consecutive will be used D0-D7 */
|
.pin_data_base = 6, /*!< this pin + 7 consecutive will be used D0-D7 */
|
||||||
.pin_vsync = 0, /*!< GPIO pin for camera VSYNC line */
|
.pin_vsync = 16, /*!< GPIO pin for camera VSYNC line */
|
||||||
.pin_href = 0, /*!< GPIO pin for camera HREF line */
|
.pin_href = 15, /*!< GPIO pin for camera HREF line */
|
||||||
.pin_pclk = 0, /*!< GPIO pin for camera PCLK line */
|
.pin_pclk = 14, /*!< GPIO pin for camera PCLK line */
|
||||||
.xclk_freq_hz = 0, /*!< Frequency of XCLK signal, in Hz. */ //! Figure out the highest it can go to
|
.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 */
|
.sccb_ctrl = 0, /* Select i2c controller ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio2 */
|
||||||
};
|
};
|
||||||
@ -33,11 +33,18 @@ int main()
|
|||||||
{
|
{
|
||||||
stdio_init_all();
|
stdio_init_all();
|
||||||
|
|
||||||
|
sleep_ms(4000);
|
||||||
|
printf("Hello World!");
|
||||||
|
|
||||||
|
printf("construct OV2640!");
|
||||||
OV2640 left_cam = OV2640(left_eye_config);
|
OV2640 left_cam = OV2640(left_eye_config);
|
||||||
|
printf("begin OV2640!");
|
||||||
left_cam.begin(DMA_IRQ_0);
|
left_cam.begin(DMA_IRQ_0);
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printf("Hello, world!\n");
|
//printf("Hello, world!\n");
|
||||||
sleep_ms(1000);
|
//sleep_ms(1000);
|
||||||
|
tight_loop_contents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,8 +59,8 @@ int SCCB::readRegister(uint8_t reg)
|
|||||||
i2c_write_blocking(this->i2cc, OV2640_ADDR, ®, 1, true); // TODO: check if true or false is correct here
|
i2c_write_blocking(this->i2cc, OV2640_ADDR, ®, 1, true); // TODO: check if true or false is correct here
|
||||||
i2c_read_blocking(this->i2cc, OV2640_ADDR, buf, 1, false); // false - finished with bus
|
i2c_read_blocking(this->i2cc, OV2640_ADDR, buf, 1, false); // false - finished with bus
|
||||||
}else {
|
}else {
|
||||||
pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, ®, 1);
|
//pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, ®, 1);
|
||||||
pio_i2c_read_blocking(this->pio, this->sm, OV2640_ADDR, buf, 1);
|
//pio_i2c_read_blocking(this->pio, this->sm, OV2640_ADDR, buf, 1);
|
||||||
}
|
}
|
||||||
return buf[0];
|
return buf[0];
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ void SCCB::writeRegister(uint8_t reg, uint8_t value)
|
|||||||
if (this->ctrl < 2) {
|
if (this->ctrl < 2) {
|
||||||
i2c_write_blocking(this->i2cc, OV2640_ADDR, buf, 2, false);
|
i2c_write_blocking(this->i2cc, OV2640_ADDR, buf, 2, false);
|
||||||
}else {
|
}else {
|
||||||
pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, buf, 2);
|
//pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, buf, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +84,6 @@ void SCCB::writeList(const register_val_t *cfg,
|
|||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
writeRegister(cfg[i].reg, cfg[i].value);
|
writeRegister(cfg[i].reg, cfg[i].value);
|
||||||
sleep_ms(1000); // Some cams require, else lockup on init
|
sleep_ms(10); // Some cams require, else lockup on init
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,3 +1,8 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/i2c.h"
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t reg; ///< Register address
|
uint8_t reg; ///< Register address
|
||||||
uint8_t value; ///< Value to store
|
uint8_t value; ///< Value to store
|
||||||
@ -17,8 +22,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
uint8_t sda;
|
uint8_t sda;
|
||||||
uint8_t scl;
|
uint8_t scl;
|
||||||
uint ctrl;
|
int ctrl;
|
||||||
i2c_inst_t* i2cc;
|
i2c_inst_t* i2cc;
|
||||||
pio_hw_t* pio;
|
pio_hw_t* pio;
|
||||||
uint sm;
|
int sm;
|
||||||
};
|
};
|
||||||
@ -1,5 +1,7 @@
|
|||||||
#include <camera.hpp>
|
|
||||||
#include <SCCB.hpp>
|
#include <SCCB.hpp>
|
||||||
|
#include <camera.hpp>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
#include "../../hardware_dma/include/hardware/dma.h"
|
#include "../../hardware_dma/include/hardware/dma.h"
|
||||||
@ -281,7 +283,7 @@ register_val_t OV2640_init[] = {
|
|||||||
{OV2640_REG0_R_DVP_SP, 0x02}, // Manual DVP PCLK setting
|
{OV2640_REG0_R_DVP_SP, 0x02}, // Manual DVP PCLK setting
|
||||||
{OV2640_REG0_RESET, 0x00}}; // Go
|
{OV2640_REG0_RESET, 0x00}}; // Go
|
||||||
// TODO: figure out how to set to JPEG and 260x260
|
// TODO: figure out how to set to JPEG and 260x260
|
||||||
/*OV2640_qqvga[] =
|
register_val_t OV2640_qqvga[] =
|
||||||
{// Configure OV2640 for QQVGA output
|
{// Configure OV2640 for QQVGA output
|
||||||
{OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0
|
{OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0
|
||||||
{OV2640_REG0_RESET, OV2640_RESET_DVP},
|
{OV2640_REG0_RESET, OV2640_RESET_DVP},
|
||||||
@ -300,16 +302,18 @@ register_val_t OV2640_init[] = {
|
|||||||
{OV2640_REG0_ZMOH, 0x1E}, // OUTH low bits
|
{OV2640_REG0_ZMOH, 0x1E}, // OUTH low bits
|
||||||
{OV2640_REG0_ZMHH, 0x00}, // OUTW/H high bits
|
{OV2640_REG0_ZMHH, 0x00}, // OUTW/H high bits
|
||||||
{OV2640_REG0_R_DVP_SP, 0x08}, // Manual DVP PCLK setting
|
{OV2640_REG0_R_DVP_SP, 0x08}, // Manual DVP PCLK setting
|
||||||
{OV2640_REG0_RESET, 0x00}}, // Go
|
{OV2640_REG0_RESET, 0x00}
|
||||||
OV2640_rgb[] = {{OV2640_REG_RA_DLMT,
|
}; // Go
|
||||||
OV2640_RA_DLMT_DSP}, // DSP bank select 0
|
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_RESET, OV2640_RESET_DVP},
|
||||||
{OV2640_REG0_IMAGE_MODE, OV2640_IMAGE_MODE_DVP_RGB565 |
|
{OV2640_REG0_IMAGE_MODE, OV2640_IMAGE_MODE_DVP_RGB565 |
|
||||||
OV2640_IMAGE_MODE_BYTE_SWAP},
|
OV2640_IMAGE_MODE_BYTE_SWAP},
|
||||||
{0xD7, 0x03}, // Mystery init values
|
{0xD7, 0x03}, // Mystery init values
|
||||||
{0xE1, 0x77}, // seen in other examples
|
{0xE1, 0x77}, // seen in other examples
|
||||||
{OV2640_REG0_RESET, 0x00}}, // Go
|
{OV2640_REG0_RESET, 0x00}
|
||||||
OV2640_yuv[] = {
|
}; // Go
|
||||||
|
register_val_t OV2640_yuv[] = {
|
||||||
{OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0
|
{OV2640_REG_RA_DLMT, OV2640_RA_DLMT_DSP}, // DSP bank select 0
|
||||||
{OV2640_REG0_RESET, OV2640_RESET_DVP},
|
{OV2640_REG0_RESET, OV2640_RESET_DVP},
|
||||||
{OV2640_REG0_IMAGE_MODE,
|
{OV2640_REG0_IMAGE_MODE,
|
||||||
@ -317,15 +321,34 @@ OV2640_yuv[] = {
|
|||||||
{0xD7, 0x01}, // Mystery init values
|
{0xD7, 0x01}, // Mystery init values
|
||||||
{0xE1, 0x67}, // seen in other examples
|
{0xE1, 0x67}, // seen in other examples
|
||||||
{OV2640_REG0_RESET, 0x00}
|
{OV2640_REG0_RESET, 0x00}
|
||||||
}; // Go*/
|
}; // Go
|
||||||
|
|
||||||
uint8_t image_buf[3][13 * 1024];
|
uint8_t image_buf[352*288*2];
|
||||||
sm_dma_config_t gpios[48];
|
sm_dma_config_t gpios[48];
|
||||||
|
int dma_channel;
|
||||||
|
int sm;
|
||||||
|
|
||||||
OV2640::OV2640(camera_config_t config)
|
OV2640::OV2640(camera_config_t config)
|
||||||
{
|
{
|
||||||
this->config = config;
|
this->config = config;
|
||||||
this->fb = &image_buf;
|
//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)
|
int OV2640::begin(int dma_irq)
|
||||||
@ -341,26 +364,36 @@ int OV2640::begin(int dma_irq)
|
|||||||
pwm_set_enabled(slice_num, true);
|
pwm_set_enabled(slice_num, true);
|
||||||
|
|
||||||
// Init SCCB
|
// Init SCCB
|
||||||
|
printf("Init SCCB\n");
|
||||||
this->sccb = SCCB(this->config.pin_sccb_sda, this->config.pin_sccb_scl);
|
this->sccb = SCCB(this->config.pin_sccb_sda, this->config.pin_sccb_scl);
|
||||||
this->sccb.begin(this->config.sccb_ctrl);
|
this->sccb.begin(this->config.sccb_ctrl);
|
||||||
|
printf("Inited SCCB\n");
|
||||||
|
|
||||||
// ENABLE AND/OR RESET CAMERA --------------------------------------------
|
// ENABLE AND/OR RESET CAMERA --------------------------------------------
|
||||||
// Unsure of camera startup time from beginning of input clock.
|
// Unsure of camera startup time from beginning of input clock.
|
||||||
// Let's guess it's similar to tS:REG (300 ms) from datasheet.
|
// Let's guess it's similar to tS:REG (300 ms) from datasheet.
|
||||||
sleep_ms(300000);
|
sleep_ms(300);
|
||||||
|
|
||||||
// Perform a soft reset (we dont wanna waste GPIO on wiring in reset pins)
|
// Perform a soft reset (we dont wanna waste GPIO on wiring in reset pins)
|
||||||
this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR); // Bank select 1
|
this->sccb.writeRegister(OV2640_REG_RA_DLMT, OV2640_RA_DLMT_SENSOR); // Bank select 1
|
||||||
this->sccb.writeRegister(OV2640_REG1_COM7, OV2640_COM7_SRST); // System reset
|
this->sccb.writeRegister(OV2640_REG1_COM7, OV2640_COM7_SRST); // System reset
|
||||||
sleep_ms(1); // Datasheet: tS:RESET = 1 ms
|
sleep_ms(300); // Datasheet: tS:RESET = 1 ms
|
||||||
|
|
||||||
// Init main camera settings
|
// Init main camera settings
|
||||||
|
printf("Write list of init\n");
|
||||||
this->sccb.writeList(OV2640_init, sizeof OV2640_init / sizeof OV2640_init[0]);
|
this->sccb.writeList(OV2640_init, sizeof OV2640_init / sizeof OV2640_init[0]);
|
||||||
|
printf("Write list of qqvga\n");
|
||||||
|
this->sccb.writeList(OV2640_qqvga, sizeof OV2640_qqvga / sizeof OV2640_qqvga[0]);
|
||||||
|
printf("Write list of rgb\n");
|
||||||
|
this->sccb.writeList(OV2640_rgb, sizeof OV2640_rgb / sizeof OV2640_rgb[0]);
|
||||||
|
|
||||||
|
|
||||||
|
printf("Gpio init\n");
|
||||||
gpio_init(this->config.pin_pclk);
|
gpio_init(this->config.pin_pclk);
|
||||||
gpio_set_dir(this->config.pin_pclk, GPIO_IN);
|
gpio_set_dir(this->config.pin_pclk, GPIO_IN);
|
||||||
gpio_init(this->config.pin_vsync);
|
gpio_init(this->config.pin_vsync);
|
||||||
gpio_set_dir(this->config.pin_vsync, GPIO_IN);
|
gpio_set_dir(this->config.pin_vsync, GPIO_IN);
|
||||||
|
gpio_pull_down(this->config.pin_vsync);
|
||||||
gpio_init(this->config.pin_href);
|
gpio_init(this->config.pin_href);
|
||||||
gpio_set_dir(this->config.pin_href, GPIO_IN);
|
gpio_set_dir(this->config.pin_href, GPIO_IN);
|
||||||
for (uint8_t i = 0; i < 8; i++)
|
for (uint8_t i = 0; i < 8; i++)
|
||||||
@ -368,19 +401,21 @@ int OV2640::begin(int dma_irq)
|
|||||||
gpio_init(this->config.pin_data_base + i);
|
gpio_init(this->config.pin_data_base + i);
|
||||||
gpio_set_dir(this->config.pin_data_base + i, GPIO_IN);
|
gpio_set_dir(this->config.pin_data_base + i, GPIO_IN);
|
||||||
}
|
}
|
||||||
|
printf("Gpio init done\n");
|
||||||
|
|
||||||
// PIO periph to use is currently specified by the user in the arch struct,
|
// PIO periph to use is currently specified by the user in the arch struct,
|
||||||
// but I suppose this could be written to use whatever PIO has resources.
|
// but I suppose this could be written to use whatever PIO has resources.
|
||||||
|
|
||||||
// Mask the GPIO pin used PCLK into the PIO opcodes -- see notes at top
|
// Mask the GPIO pin used PCLK into the PIO opcodes -- see notes at top
|
||||||
// TODO: check if this is correct (code made for rp2040 not rp2350 so it might differ)
|
// TODO: check if this is correct (code made for rp2040 not rp2350 so it might differ)
|
||||||
|
printf("PIO init\n");
|
||||||
capture_pio_opcodes[0] |= (this->config.pin_href & 31);
|
capture_pio_opcodes[0] |= (this->config.pin_href & 31);
|
||||||
capture_pio_opcodes[1] |= (this->config.pin_pclk & 31);
|
capture_pio_opcodes[1] |= (this->config.pin_pclk & 31);
|
||||||
capture_pio_opcodes[3] |= (this->config.pin_pclk & 31);
|
capture_pio_opcodes[3] |= (this->config.pin_pclk & 31);
|
||||||
|
|
||||||
uint offset = pio_add_program(pio2, &cap_pio_program);
|
uint offset = pio_add_program(pio2, &cap_pio_program);
|
||||||
this->sm = pio_claim_unused_sm(pio2, true); // 0-3
|
this->sm = pio_claim_unused_sm(pio2, true); // 0-3
|
||||||
|
sm = this->sm;
|
||||||
pio_sm_set_consecutive_pindirs(pio2, this->sm, this->config.pin_data_base, 8, false);
|
pio_sm_set_consecutive_pindirs(pio2, this->sm, this->config.pin_data_base, 8, false);
|
||||||
|
|
||||||
pio_sm_config c = pio_get_default_sm_config();
|
pio_sm_config c = pio_get_default_sm_config();
|
||||||
@ -393,11 +428,12 @@ int OV2640::begin(int dma_irq)
|
|||||||
|
|
||||||
pio_sm_init(pio2, this->sm, offset, &c);
|
pio_sm_init(pio2, this->sm, offset, &c);
|
||||||
pio_sm_set_enabled(pio2, this->sm, true);
|
pio_sm_set_enabled(pio2, this->sm, true);
|
||||||
|
printf("PIO init done\n");
|
||||||
|
|
||||||
// SET UP DMA ------------------------------------------------------------
|
// SET UP DMA ------------------------------------------------------------
|
||||||
|
printf("DMA init\n");
|
||||||
this->dma_channel = dma_claim_unused_channel(false); // don't panic
|
this->dma_channel = dma_claim_unused_channel(false); // don't panic
|
||||||
|
dma_channel = this->dma_channel;
|
||||||
this->dma_config = dma_channel_get_default_config(this->dma_channel);
|
this->dma_config = dma_channel_get_default_config(this->dma_channel);
|
||||||
channel_config_set_transfer_data_size(&this->dma_config, DMA_SIZE_16);
|
channel_config_set_transfer_data_size(&this->dma_config, DMA_SIZE_16);
|
||||||
channel_config_set_read_increment(&this->dma_config, false);
|
channel_config_set_read_increment(&this->dma_config, false);
|
||||||
@ -416,7 +452,7 @@ int OV2640::begin(int dma_irq)
|
|||||||
|
|
||||||
// Set up end-of-DMA interrupt
|
// Set up end-of-DMA interrupt
|
||||||
dma_channel_set_irq0_enabled(this->dma_channel, true);
|
dma_channel_set_irq0_enabled(this->dma_channel, true);
|
||||||
|
printf("DMA init done\n");
|
||||||
//? setup diffrent handlers for each cam???
|
//? setup diffrent handlers for each cam???
|
||||||
//? check with a button or smth if this fires all events or only one
|
//? check with a button or smth if this fires all events or only one
|
||||||
//? cuz then I would be able to do dma_finish_irq_cam1, dma_finish_irq_cam2, dma_finish_irq_cam3
|
//? cuz then I would be able to do dma_finish_irq_cam1, dma_finish_irq_cam2, dma_finish_irq_cam3
|
||||||
@ -428,29 +464,17 @@ int OV2640::begin(int dma_irq)
|
|||||||
//? This also could be redone with hardcoded values
|
//? This also could be redone with hardcoded values
|
||||||
gpio_set_irq_enabled_with_callback(this->config.pin_vsync, GPIO_IRQ_EDGE_RISE, true,
|
gpio_set_irq_enabled_with_callback(this->config.pin_vsync, GPIO_IRQ_EDGE_RISE, true,
|
||||||
&vsync_irq);
|
&vsync_irq);
|
||||||
|
printf("IRQ init done\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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, archptr->sm);
|
|
||||||
dma_channel_start(archptr->dma_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dma_finish_irq()
|
|
||||||
{
|
|
||||||
// Channel MUST be reconfigured each time (to reset the dest address).
|
|
||||||
dma_channel_set_write_addr(archptr->dma_channel,
|
|
||||||
(uint8_t *)(image_buf), false);
|
|
||||||
dma_hw->ints0 = 1u << archptr->dma_channel; // Clear IRQ
|
|
||||||
}
|
|
||||||
|
|
||||||
//! https://forums.raspberrypi.com/viewtopic.php?t=339299
|
//! 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
|
// 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
|
||||||
/* Read the flags
|
/* Read the flags
|
||||||
|
pio0_hw->irq;
|
||||||
uint32_t flags = read_register(PIO0_BASE, PIO_IRQ_OFFSET)
|
uint32_t flags = read_register(PIO0_BASE, PIO_IRQ_OFFSET)
|
||||||
// Check the flags to determine which state machine made the request
|
// Check the flags to determine which state machine made the request
|
||||||
if (flags & 0b0001) { handle_sm_0(); }
|
if (flags & 0b0001) { handle_sm_0(); }
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "../../hardware_dma/include/hardware/dma.h"
|
||||||
// TODO: Add XCLK settings
|
// TODO: Add XCLK settings
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int pin_pwdn; /*!< GPIO pin for camera power down line */ //? Also called PWDN, or set to -1 and tie to GND
|
int pin_pwdn; /*!< GPIO pin for camera power down line */ //? Also called PWDN, or set to -1 and tie to GND
|
||||||
@ -14,8 +17,8 @@ typedef struct {
|
|||||||
} camera_config_t;
|
} camera_config_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint sm;
|
int sm;
|
||||||
uint dma_channel;
|
int dma_channel;
|
||||||
} sm_dma_config_t;
|
} sm_dma_config_t;
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +32,8 @@ private:
|
|||||||
camera_config_t config;
|
camera_config_t config;
|
||||||
SCCB sccb;
|
SCCB sccb;
|
||||||
uint8_t* (*fb)[3];
|
uint8_t* (*fb)[3];
|
||||||
uint sm;
|
int sm;
|
||||||
uint dma_channel;
|
int dma_channel;
|
||||||
dma_channel_config dma_config;
|
dma_channel_config dma_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
#include "pio_i2c.h"
|
||||||
#include "pio_i2c.hpp"
|
#include "i2c.pio.h"
|
||||||
|
|
||||||
const int PIO_I2C_ICOUNT_LSB = 10;
|
const int PIO_I2C_ICOUNT_LSB = 10;
|
||||||
const int PIO_I2C_FINAL_LSB = 9;
|
const int PIO_I2C_FINAL_LSB = 9;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user