Skip to content

Commit

Permalink
feat(sccb): new esp sccb component
Browse files Browse the repository at this point in the history
  • Loading branch information
Icarus113 committed Feb 27, 2024
1 parent e524886 commit d80a1e8
Show file tree
Hide file tree
Showing 11 changed files with 479 additions and 0 deletions.
16 changes: 16 additions & 0 deletions esp_driver_sccb/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
set(srcs)

set(include "include" "interface")

list(APPEND srcs "src/sccb.c")

if(CONFIG_SOC_I2C_SUPPORTED)
list(APPEND srcs "sccb_i2c/src/sccb_i2c.c" "src/sccb.c")
endif()

list(APPEND include "sccb_i2c/include")

idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include}
REQUIRES esp_driver_i2c
)
9 changes: 9 additions & 0 deletions esp_driver_sccb/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
menu "SCCB Configurations"

config SCCB_ISR_IRAM_SAFE
bool "Place SCCB ISR functions into IRAM"
default n
help
Place SCCB ISR functions into IRAM.

endmenu
7 changes: 7 additions & 0 deletions esp_driver_sccb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ESP SCCB COMPONENT

This component is so-called SCCB component which is implemented by

- esp_driver_i2c

It is a protocol layer driver for communicating with all kinds of camera sensors.
5 changes: 5 additions & 0 deletions esp_driver_sccb/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: "1.0.0"
description: "ESP SCCB COMPONENT"
url: https://github.com/espressif/idf-extra-components/tree/master/esp_driver_sccb
dependencies:
idf: ">=5.2"
79 changes: 79 additions & 0 deletions esp_driver_sccb/include/esp_sccb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "sccb_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Perform a write transaction.
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[in] write_buffer Data bytes to send on the sccb bus.
* @param[in] write_size Size, in bytes, of the write buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb transmit success
* - ESP_ERR_INVALID_ARG: sccb transmit parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t esp_sccb_transmit(esp_sccb_handle_t handle, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms);

/**
* @brief Perform a read transaction
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[out] read_buffer Data bytes received from sccb bus.
* @param[in] read_size Size, in bytes, of the read buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb receive success
* - ESP_ERR_INVALID_ARG: sccb receive parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t esp_sccb_receive(esp_sccb_handle_t handle, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);

/**
* @brief Perform a write-read transaction
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[in] write_buffer Data bytes to send on the sccb bus.
* @param[in] write_size Size, in bytes, of the write buffer.
* @param[out] read_buffer Data bytes received from sccb bus.
* @param[in] read_size Size, in bytes, of the read buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb transmit-receive success
* - ESP_ERR_INVALID_ARG: sccb transmit parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t esp_sccb_transmit_receive(esp_sccb_handle_t handle, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);

/**
* @brief Delete sccb controller
*
* @param[in] handle SCCB handle
* @return
* - ESP_OK: If controller is successfully deleted.
*/
esp_err_t esp_sccb_del_ctlr(esp_sccb_handle_t handle);

#ifdef __cplusplus
}
#endif
24 changes: 24 additions & 0 deletions esp_driver_sccb/include/sccb_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <stdint.h>
#include "esp_err.h"
#include "hal/gpio_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief sccb handle type
*/
typedef struct sccb_controller_t *esp_sccb_handle_t;

#ifdef __cplusplus
}
#endif
89 changes: 89 additions & 0 deletions esp_driver_sccb/interface/sccb_controller_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <stdbool.h>
#include "esp_err.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief sccb controller type
*/
typedef struct sccb_controller_t sccb_controller_t;

/**
* @brief sccb controller type
*/
struct sccb_controller_t {

/**
* @brief Perform a write transaction.
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[in] write_buffer Data bytes to send on the sccb bus.
* @param[in] write_size Size, in bytes, of the write buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb transmit success
* - ESP_ERR_INVALID_ARG: sccb transmit parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t (*transmit)(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms);

/**
* @brief Perform a write-read transaction
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[in] write_buffer Data bytes to send on the sccb bus.
* @param[in] write_size Size, in bytes, of the write buffer.
* @param[out] read_buffer Data bytes received from sccb bus.
* @param[in] read_size Size, in bytes, of the read buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb transmit-receive success
* - ESP_ERR_INVALID_ARG: sccb transmit parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t (*transmit_receive)(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);

/**
* @brief Perform a read transaction
* The transaction will be undergoing until it finishes or it reaches
* the timeout provided.
*
* @param[in] handle SCCB handle
* @param[out] read_buffer Data bytes received from sccb bus.
* @param[in] read_size Size, in bytes, of the read buffer.
* @param[in] xfer_timeout_ms Wait timeout, in ms. Note: -1 means wait forever.
* @return
* - ESP_OK: sccb receive success
* - ESP_ERR_INVALID_ARG: sccb receive parameter invalid.
* - ESP_ERR_TIMEOUT: Operation timeout(larger than xfer_timeout_ms) because the bus is busy or hardware crash.
*/
esp_err_t (*receive)(sccb_controller_t *handle, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);

/**
* @brief Delete sccb controller
*
* @param[in] handle SCCB handle
* @return
* - ESP_OK: If controller is successfully deleted.
*/
esp_err_t (*del)(sccb_controller_t *handle);

void *user_data; ///< User data
};

#ifdef __cplusplus
}
#endif
41 changes: 41 additions & 0 deletions esp_driver_sccb/sccb_i2c/include/sccb_i2c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "driver/i2c_master.h"
#include "sccb_types.h"

/**
* @brief Type of sccb i2c controller handle
*/
typedef struct sccb_i2c_controller_t *esp_sccb_i2c_handle_t;

/**
* @brief ESP SCCB I2C configuration
*/
typedef struct {
i2c_port_num_t i2c_port; ///< I2C port number, `-1` for auto selecting
gpio_num_t sda_io_num; ///< GPIO number of I2C SDA signal, pulled-up internally
gpio_num_t scl_io_num; ///< GPIO number of I2C SCL signal, pulled-up internally
i2c_addr_bit_len_t dev_addr_length; ///< Select the address length of the slave device
uint16_t device_address; ///< I2C device raw address. (The 7/10 bit address without read/write bit)
uint32_t scl_speed_hz; ///< I2C SCL line frequency
i2c_clock_source_t clk_source; ///< Clock source of I2C master bus, channels in the same group must use the same clock source
} esp_sccb_i2c_config_t;

/**
* @brief new esp sccb i2c controller
*
* @note This API will own I2C bus
*
* @param[in] config esp sccb i2c configuration
* @param[in] ret_handle esp sccb handle
*
* @return
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_NO_MEM If out of memory
* - ESP_OK On success
*/
esp_err_t esp_sccb_new_i2c_ctlr(const esp_sccb_i2c_config_t *config, esp_sccb_handle_t *ret_handle);
117 changes: 117 additions & 0 deletions esp_driver_sccb/sccb_i2c/src/sccb_i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <esp_types.h>
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "driver/i2c_master.h"
#include "sccb_types.h"
#include "sccb_i2c.h"
#include "sccb_i2c_internal.h"
#include "sccb_controller_interface.h"

#if CONFIG_SCCB_ISR_IRAM_SAFE
#define SCCB_I2C_MEM_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define SCCB_I2C_MEM_CAPS MALLOC_CAP_DEFAULT
#endif

static const char *TAG = "sccb_i2c";

static esp_err_t s_sccb_i2c_transmit(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms);
static esp_err_t s_sccb_i2c_receive(sccb_controller_t *handle, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);
static esp_err_t s_sccb_i2c_transmit_receive(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms);
static esp_err_t s_sccb_i2c_destroy(sccb_controller_t *handle);

esp_err_t esp_sccb_new_i2c_ctlr(const esp_sccb_i2c_config_t *config, esp_sccb_handle_t *ret_handle)
{
esp_err_t ret = ESP_FAIL;
i2c_master_bus_handle_t bus_handle = NULL;
sccb_i2c_controller_t *ctlr = NULL;

i2c_master_bus_config_t i2c_bus_config = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = config->i2c_port,
.sda_io_num = config->sda_io_num,
.scl_io_num = config->scl_io_num,
};
ESP_RETURN_ON_ERROR(i2c_new_master_bus(&i2c_bus_config, &bus_handle), TAG, "failed to new i2c master bus");

i2c_device_config_t dev_cfg = {
.dev_addr_length = config->dev_addr_length,
.device_address = config->device_address,
.scl_speed_hz = config->scl_speed_hz,
};
i2c_master_dev_handle_t dev_handle = NULL;
ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle), err, TAG, "failed to add device");

ctlr = heap_caps_calloc(1, sizeof(sccb_i2c_controller_t), SCCB_I2C_MEM_CAPS);
ESP_GOTO_ON_FALSE(ctlr, ESP_ERR_NO_MEM, err, TAG, "no mem for csi controller context");

ctlr->bus_handle = bus_handle;
ctlr->dev_handle = dev_handle;
ctlr->base.transmit = s_sccb_i2c_transmit;
ctlr->base.receive = s_sccb_i2c_receive;
ctlr->base.transmit_receive = s_sccb_i2c_transmit_receive;
ctlr->base.del = s_sccb_i2c_destroy;
*ret_handle = (void *) & (ctlr->base);

return ESP_OK;

err:

if (bus_handle) {
i2c_del_master_bus(bus_handle);
}

if (dev_handle) {
i2c_master_bus_rm_device(dev_handle);
}

if (ctlr) {
free(ctlr);
}

return ret;
}

static esp_err_t s_sccb_i2c_transmit(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, int xfer_timeout_ms)
{
sccb_i2c_controller_t *ctlr = __containerof(handle, sccb_i2c_controller_t, base);
ESP_RETURN_ON_ERROR(i2c_master_transmit(ctlr->dev_handle, write_buffer, write_size, xfer_timeout_ms), TAG, "failed to i2c transmit");

return ESP_OK;
}

static esp_err_t s_sccb_i2c_receive(sccb_controller_t *handle, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms)
{
sccb_i2c_controller_t *ctlr = __containerof(handle, sccb_i2c_controller_t, base);
ESP_RETURN_ON_ERROR(i2c_master_receive(ctlr->dev_handle, read_buffer, read_size, xfer_timeout_ms), TAG, "failed to i2c receive");

return ESP_OK;
}

static esp_err_t s_sccb_i2c_transmit_receive(sccb_controller_t *handle, const uint8_t *write_buffer, size_t write_size, uint8_t *read_buffer, size_t read_size, int xfer_timeout_ms)
{
sccb_i2c_controller_t *ctlr = __containerof(handle, sccb_i2c_controller_t, base);
ESP_RETURN_ON_ERROR(i2c_master_transmit_receive(ctlr->dev_handle, write_buffer, write_size, read_buffer, read_size, xfer_timeout_ms), TAG, "faled to transmit receive");

return ESP_OK;
}

static esp_err_t s_sccb_i2c_destroy(sccb_controller_t *handle)
{
sccb_i2c_controller_t *ctlr = __containerof(handle, sccb_i2c_controller_t, base);
ESP_RETURN_ON_ERROR(i2c_master_bus_rm_device(ctlr->dev_handle), TAG, "failed to remove device");
ESP_RETURN_ON_ERROR(i2c_del_master_bus(ctlr->bus_handle), TAG, "failed to delete bus");

return ESP_OK;
}
Loading

0 comments on commit d80a1e8

Please sign in to comment.