Skip to content

feat: change sccb APIs for sharing i2c port with other devices #413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sscb_sda = CAM_PIN_SIOD,
.pin_sscb_scl = CAM_PIN_SIOC,
.pin_sccb_sda = CAM_PIN_SIOD,
.pin_sccb_scl = CAM_PIN_SIOC,

.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
Expand Down
32 changes: 21 additions & 11 deletions driver/esp_camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ static const sensor_func_t g_sensors[] = {

static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model)
{
esp_err_t ret = ESP_OK;
*out_camera_model = CAMERA_NONE;
if (s_state != NULL) {
return ESP_ERR_INVALID_STATE;
Expand All @@ -156,9 +157,17 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
CAMERA_ENABLE_OUT_CLOCK(config);
}

if (config->pin_sscb_sda != -1) {
ESP_LOGD(TAG, "Initializing SSCB");
SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
if (config->pin_sccb_sda != -1) {
ESP_LOGD(TAG, "Initializing SCCB");
ret = SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl);
} else {
ESP_LOGD(TAG, "Using existing I2C port");
ret = SCCB_Use_Port(config->sccb_i2c_port);
}

if(ret != ESP_OK) {
ESP_LOGE(TAG, "sccb init err");
goto err;
}

if (config->pin_pwdn >= 0) {
Expand Down Expand Up @@ -188,15 +197,14 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
vTaskDelay(10 / portTICK_PERIOD_MS);
}


ESP_LOGD(TAG, "Searching for camera address");
vTaskDelay(10 / portTICK_PERIOD_MS);

uint8_t slv_addr = SCCB_Probe();

if (slv_addr == 0) {
CAMERA_DISABLE_OUT_CLOCK();
return ESP_ERR_NOT_FOUND;
ret = ESP_ERR_NOT_FOUND;
goto err;
}

ESP_LOGI(TAG, "Detected camera at address=0x%02x", slv_addr);
Expand All @@ -221,19 +229,21 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
}

if (CAMERA_NONE == *out_camera_model) { //If no supported sensors are detected
CAMERA_DISABLE_OUT_CLOCK();
ESP_LOGE(TAG, "Detected camera not supported.");
return ESP_ERR_NOT_SUPPORTED;
ret = ESP_ERR_NOT_SUPPORTED;
goto err;
}

ESP_LOGI(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x",
id->PID, id->VER, id->MIDH, id->MIDL);

ESP_LOGD(TAG, "Doing SW reset of sensor");
vTaskDelay(10 / portTICK_PERIOD_MS);
s_state->sensor.reset(&s_state->sensor);

return ESP_OK;

return s_state->sensor.reset(&s_state->sensor);
err :
CAMERA_DISABLE_OUT_CLOCK();
return ret;
}

#if CONFIG_CAMERA_CONVERTER_ENABLED
Expand Down
16 changes: 12 additions & 4 deletions driver/include/esp_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
.pin_pwdn = PIN_PWDN,
.pin_reset = PIN_RESET,
.pin_xclk = PIN_XCLK,
.pin_sscb_sda = PIN_SIOD,
.pin_sscb_scl = PIN_SIOC,
.pin_sccb_sda = PIN_SIOD,
.pin_sccb_scl = PIN_SIOC,
.pin_d7 = PIN_D7,
.pin_d6 = PIN_D6,
.pin_d5 = PIN_D5,
Expand Down Expand Up @@ -112,8 +112,14 @@ typedef struct {
int pin_pwdn; /*!< GPIO pin for camera power down line */
int pin_reset; /*!< GPIO pin for camera reset line */
int pin_xclk; /*!< GPIO pin for camera XCLK line */
int pin_sscb_sda; /*!< GPIO pin for camera SDA line */
int pin_sscb_scl; /*!< GPIO pin for camera SCL line */
union {
int pin_sccb_sda; /*!< GPIO pin for camera SDA line */
int pin_sscb_sda __attribute__((deprecated("please use pin_sccb_sda instead"))); /*!< GPIO pin for camera SDA line (legacy name) */
};
union {
int pin_sccb_scl; /*!< GPIO pin for camera SCL line */
int pin_sscb_scl __attribute__((deprecated("please use pin_sccb_scl instead"))); /*!< GPIO pin for camera SCL line (legacy name) */
};
int pin_d7; /*!< GPIO pin for camera D7 line */
int pin_d6; /*!< GPIO pin for camera D6 line */
int pin_d5; /*!< GPIO pin for camera D5 line */
Expand Down Expand Up @@ -141,6 +147,8 @@ typedef struct {
#if CONFIG_CAMERA_CONVERTER_ENABLED
camera_conv_mode_t conv_mode; /*!< RGB<->YUV Conversion mode */
#endif

int sccb_i2c_port; /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */
} camera_config_t;

/**
Expand Down
2 changes: 1 addition & 1 deletion driver/include/sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ typedef struct _sensor {

// Sensor function pointers
int (*init_status) (sensor_t *sensor);
int (*reset) (sensor_t *sensor);
int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
int (*set_contrast) (sensor_t *sensor, int level);
Expand Down
1 change: 1 addition & 0 deletions driver/private_include/sccb.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define __SCCB_H__
#include <stdint.h>
int SCCB_Init(int pin_sda, int pin_scl);
int SCCB_Use_Port(int sccb_i2c_port);
int SCCB_Deinit(void);
uint8_t SCCB_Probe();
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg);
Expand Down
65 changes: 41 additions & 24 deletions driver/sccb.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,47 +38,64 @@ static const char* TAG = "sccb";
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
#if CONFIG_SCCB_HARDWARE_I2C_PORT1
const int SCCB_I2C_PORT = 1;
const int SCCB_I2C_PORT_DEFAULT = 1;
#else
const int SCCB_I2C_PORT = 0;
const int SCCB_I2C_PORT_DEFAULT = 0;
#endif

static int sccb_i2c_port;
static bool sccb_owns_i2c_port;

int SCCB_Init(int pin_sda, int pin_scl)
{
ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl);
i2c_config_t conf;
esp_err_t ret;

memset(&conf, 0, sizeof(i2c_config_t));

sccb_i2c_port = SCCB_I2C_PORT_DEFAULT;
sccb_owns_i2c_port = true;
ESP_LOGI(TAG, "sccb_i2c_port=%d\n", sccb_i2c_port);

conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = pin_sda;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = pin_scl;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = SCCB_FREQ;

i2c_param_config(SCCB_I2C_PORT, &conf);
i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
return 0;
if ((ret = i2c_param_config(sccb_i2c_port, &conf)) != ESP_OK) {
return ret;
}

return i2c_driver_install(sccb_i2c_port, conf.mode, 0, 0, 0);
}

int SCCB_Use_Port(int i2c_num) { // sccb use an already initialized I2C port
if (sccb_owns_i2c_port) {
SCCB_Deinit();
}
if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) {
return ESP_ERR_INVALID_ARG;
}
sccb_i2c_port = i2c_num;
return ESP_OK;
}

int SCCB_Deinit(void)
{
return i2c_driver_delete(SCCB_I2C_PORT);
if (!sccb_owns_i2c_port) {
return ESP_OK;
}
sccb_owns_i2c_port = false;
return i2c_driver_delete(sccb_i2c_port);
}

uint8_t SCCB_Probe(void)
{
uint8_t slave_addr = 0x0;
// for (size_t i = 1; i < 0x80; i++) {
// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, ( i << 1 ) | WRITE_BIT, ACK_CHECK_EN);
// i2c_master_stop(cmd);
// esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
// i2c_cmd_link_delete(cmd);
// if( ret == ESP_OK) {
// ESP_LOGW(TAG, "Found I2C Device at 0x%02X", i);
// }
// }

for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) {
if (slave_addr == camera_sensor[i].sccb_addr) {
continue;
Expand All @@ -88,7 +105,7 @@ uint8_t SCCB_Probe(void)
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
esp_err_t ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if( ret == ESP_OK) {
return slave_addr;
Expand All @@ -106,15 +123,15 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) return -1;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &data, NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
Expand All @@ -131,7 +148,7 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
Expand All @@ -151,15 +168,15 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) return -1;
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &data, NACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
Expand All @@ -180,7 +197,7 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN);
i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
Expand Down
4 changes: 2 additions & 2 deletions examples/main/take_picture.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sscb_sda = CAM_PIN_SIOD,
.pin_sscb_scl = CAM_PIN_SIOC,
.pin_sccb_sda = CAM_PIN_SIOD,
.pin_sccb_scl = CAM_PIN_SIOC,

.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
Expand Down
Loading