105 lines
2.9 KiB
C++
105 lines
2.9 KiB
C++
#include <SCCB.hpp>
|
|
#include <camera.hpp>
|
|
#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) {
|
|
this->sda = sda_pin;
|
|
this->scl = scl_pin;
|
|
}
|
|
|
|
SCCB::~SCCB() {}
|
|
|
|
// ctrl: 0 - i2c0, 1 - i2c1, 2 - pio0, 3 - pio1, 4 - pio1
|
|
// TODO: add proper return values when failure
|
|
// TODO: panic if scl != sda + 1
|
|
int SCCB::begin(uint8_t ctrl)
|
|
{
|
|
// Set up XCLK out unless it's a self-clocking camera. This must be done
|
|
// BEFORE any I2C commands, as cam may require clock for I2C timing.
|
|
this->ctrl = ctrl;
|
|
if (ctrl < 2) {
|
|
this->i2cc = ctrl == 0 ? i2c0 : i2c1;
|
|
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);
|
|
gpio_pull_up(this->scl);
|
|
}
|
|
else {
|
|
PIO pio;
|
|
switch (ctrl) {
|
|
case 2:
|
|
this->pio = pio0;
|
|
break;
|
|
case 3:
|
|
this->pio = pio1;
|
|
break;
|
|
case 4:
|
|
this->pio = pio1;
|
|
break;
|
|
default:
|
|
this->pio = pio0;
|
|
break;
|
|
};
|
|
|
|
uint sm = pio_claim_unused_sm(this->pio, true);
|
|
uint offset = pio_add_program(this->pio, &i2c_program);
|
|
i2c_program_init(this->pio, this->sm, offset, this->sda, this->scl);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SCCB::readRegister(uint8_t reg)
|
|
{
|
|
uint8_t buf[1];
|
|
if (this->ctrl < 2) {
|
|
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
|
|
}else {
|
|
//pio_i2c_write_blocking(this->pio, this->sm, OV2640_ADDR, ®, 1);
|
|
//pio_i2c_read_blocking(this->pio, this->sm, OV2640_ADDR, buf, 1);
|
|
}
|
|
return buf[0];
|
|
}
|
|
|
|
void SCCB::writeRegister(uint8_t reg, uint8_t value)
|
|
{
|
|
uint8_t buf[2];
|
|
buf[0] = reg;
|
|
buf[1] = value;
|
|
|
|
if (this->ctrl < 2) {
|
|
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);
|
|
}
|
|
}
|
|
|
|
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,
|
|
uint16_t len)
|
|
{
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
writeRegister(cfg[i].reg, cfg[i].value);
|
|
sleep_ms(2); // Some cams require, else lockup on init
|
|
}
|
|
} |