mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-02-19 03:13:14 +00:00
I2C and GPIO improvements
This commit is contained in:
parent
d6e1c0d9cb
commit
e389cb00db
@ -9,6 +9,7 @@
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
|
||||
#define TAG LOG_TAG(esp32_i2c)
|
||||
#define ACK_CHECK_EN 1
|
||||
|
||||
struct InternalData {
|
||||
Mutex mutex { 0 };
|
||||
@ -30,7 +31,7 @@ struct InternalData {
|
||||
|
||||
extern "C" {
|
||||
|
||||
static int read(Device* device, uint8_t address, uint8_t* data, size_t data_size, TickType_t timeout) {
|
||||
static error_t read(Device* device, uint8_t address, uint8_t* data, size_t data_size, TickType_t timeout) {
|
||||
vPortAssertIfInISR();
|
||||
auto* driver_data = GET_DATA(device);
|
||||
lock(driver_data);
|
||||
@ -40,7 +41,7 @@ static int read(Device* device, uint8_t address, uint8_t* data, size_t data_size
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static int write(Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
||||
static error_t write(Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
||||
vPortAssertIfInISR();
|
||||
auto* driver_data = GET_DATA(device);
|
||||
lock(driver_data);
|
||||
@ -50,7 +51,7 @@ static int write(Device* device, uint8_t address, const uint8_t* data, uint16_t
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static int write_read(Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) {
|
||||
static error_t write_read(Device* device, uint8_t address, const uint8_t* write_data, size_t write_data_size, uint8_t* read_data, size_t read_data_size, TickType_t timeout) {
|
||||
vPortAssertIfInISR();
|
||||
auto* driver_data = GET_DATA(device);
|
||||
lock(driver_data);
|
||||
@ -60,14 +61,59 @@ static int write_read(Device* device, uint8_t address, const uint8_t* write_data
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static int start(Device* device) {
|
||||
static error_t read_register(Device* device, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout) {
|
||||
auto* driver_data = GET_DATA(device);
|
||||
|
||||
lock(driver_data);
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
// Set address pointer
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write(cmd, ®, 1, ACK_CHECK_EN);
|
||||
// Read length of response from current pointer
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
|
||||
if (dataSize > 1) {
|
||||
i2c_master_read(cmd, data, dataSize - 1, I2C_MASTER_ACK);
|
||||
}
|
||||
i2c_master_read_byte(cmd, data + dataSize - 1, I2C_MASTER_NACK);
|
||||
i2c_master_stop(cmd);
|
||||
// TODO: We're passing an inaccurate timeout value as we already lost time with locking
|
||||
esp_err_t esp_error = i2c_master_cmd_begin(GET_CONFIG(device)->port, cmd, timeout);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
unlock(driver_data);
|
||||
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_error);
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static error_t write_register(Device* device, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
||||
auto* driver_data = GET_DATA(device);
|
||||
|
||||
lock(driver_data);
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
|
||||
i2c_master_write(cmd, (uint8_t*) data, dataSize, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
// TODO: We're passing an inaccurate timeout value as we already lost time with locking
|
||||
esp_err_t esp_error = i2c_master_cmd_begin(GET_CONFIG(device)->port, cmd, timeout);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
unlock(driver_data);
|
||||
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_error);
|
||||
return esp_err_to_error(esp_error);
|
||||
}
|
||||
|
||||
static error_t start(Device* device) {
|
||||
ESP_LOGI(TAG, "start %s", device->name);
|
||||
auto* data = new InternalData();
|
||||
device_set_driver_data(device, data);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static int stop(Device* device) {
|
||||
static error_t stop(Device* device) {
|
||||
ESP_LOGI(TAG, "stop %s", device->name);
|
||||
auto* driver_data = static_cast<InternalData*>(device_get_driver_data(device));
|
||||
device_set_driver_data(device, nullptr);
|
||||
@ -75,10 +121,13 @@ static int stop(Device* device) {
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
const static I2cControllerApi esp32_i2c_api = {
|
||||
.read = read,
|
||||
.write = write,
|
||||
.write_read = write_read
|
||||
.write_read = write_read,
|
||||
.read_register = read_register,
|
||||
.write_register = write_register
|
||||
};
|
||||
|
||||
Driver esp32_i2c_driver = {
|
||||
|
||||
@ -10,17 +10,85 @@ extern "C" {
|
||||
#include <tactility/error.h>
|
||||
|
||||
struct GpioControllerApi {
|
||||
/**
|
||||
* @brief Sets the logical level of a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[in] high true to set the pin high, false to set it low
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t (*set_level)(struct Device* device, gpio_pin_t pin, bool high);
|
||||
|
||||
/**
|
||||
* @brief Gets the logical level of a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[out] high pointer to store the pin level
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t (*get_level)(struct Device* device, gpio_pin_t pin, bool* high);
|
||||
|
||||
/**
|
||||
* @brief Configures the options for a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[in] options configuration flags (direction, pull-up/down, etc.)
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t (*set_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t options);
|
||||
|
||||
/**
|
||||
* @brief Gets the configuration options for a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[out] options pointer to store the configuration flags
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t (*get_options)(struct Device* device, gpio_pin_t pin, gpio_flags_t* options);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Sets the logical level of a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[in] high true to set the pin high, false to set it low
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t gpio_controller_set_level(struct Device* device, gpio_pin_t pin, bool high);
|
||||
|
||||
/**
|
||||
* @brief Gets the logical level of a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[out] high pointer to store the pin level
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t gpio_controller_get_level(struct Device* device, gpio_pin_t pin, bool* high);
|
||||
|
||||
/**
|
||||
* @brief Configures the options for a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[in] options configuration flags (direction, pull-up/down, etc.)
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t gpio_controller_set_options(struct Device* device, gpio_pin_t pin, gpio_flags_t options);
|
||||
|
||||
/**
|
||||
* @brief Gets the configuration options for a GPIO pin.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] pin the pin index
|
||||
* @param[out] options pointer to store the configuration flags
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
error_t gpio_controller_get_options(struct Device* device, gpio_pin_t pin, gpio_flags_t* options);
|
||||
|
||||
/**
|
||||
* @brief Configures the options for a GPIO pin using a pin configuration structure.
|
||||
* @param[in] device the GPIO controller device
|
||||
* @param[in] config the pin configuration structure
|
||||
* @return ERROR_NONE if successful
|
||||
*/
|
||||
static inline error_t gpio_set_options_config(struct Device* device, const struct GpioPinConfig* config) {
|
||||
return gpio_controller_set_options(device, config->pin, config->flags);
|
||||
}
|
||||
|
||||
@ -13,18 +13,154 @@ extern "C" {
|
||||
#include <tactility/freertos/freertos.h>
|
||||
#include <tactility/error.h>
|
||||
|
||||
/**
|
||||
* @brief API for I2C controller drivers.
|
||||
*/
|
||||
struct I2cControllerApi {
|
||||
/**
|
||||
* @brief Reads data from an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[out] data the buffer to store the read data
|
||||
* @param[in] dataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the read operation was successful
|
||||
* @retval ERROR_TIMEOUT when the operation timed out
|
||||
*/
|
||||
error_t (*read)(struct Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] data the buffer containing the data to write
|
||||
* @param[in] dataSize the number of bytes to write
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the write operation was successful
|
||||
* @retval ERROR_TIMEOUT when the operation timed out
|
||||
*/
|
||||
error_t (*write)(struct Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to then reads data from an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] writeData the buffer containing the data to write
|
||||
* @param[in] writeDataSize the number of bytes to write
|
||||
* @param[out] readData the buffer to store the read data
|
||||
* @param[in] readDataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the operation was successful
|
||||
* @retval ERROR_TIMEOUT when the operation timed out
|
||||
*/
|
||||
error_t (*write_read)(struct Device* device, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Reads data from a register of an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] reg the register address to read from
|
||||
* @param[out] data the buffer to store the read data
|
||||
* @param[in] dataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the read operation was successful
|
||||
* @retval ERROR_TIMEOUT when the operation timed out
|
||||
*/
|
||||
error_t (*read_register)(struct Device* device, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to a register of an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] reg the register address to write to
|
||||
* @param[in] data the buffer containing the data to write
|
||||
* @param[in] dataSize the number of bytes to write
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the write operation was successful
|
||||
* @retval ERROR_TIMEOUT when the operation timed out
|
||||
*/
|
||||
error_t (*write_register)(struct Device* device, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Reads data from an I2C device using the specified controller.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[out] data the buffer to store the read data
|
||||
* @param[in] dataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the read operation was successful
|
||||
*/
|
||||
error_t i2c_controller_read(struct Device* device, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to an I2C device using the specified controller.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] data the buffer containing the data to write
|
||||
* @param[in] dataSize the number of bytes to write
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the write operation was successful
|
||||
*/
|
||||
error_t i2c_controller_write(struct Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to then reads data from an I2C device using the specified controller.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] writeData the buffer containing the data to write
|
||||
* @param[in] writeDataSize the number of bytes to write
|
||||
* @param[out] readData the buffer to store the read data
|
||||
* @param[in] readDataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the operation was successful
|
||||
*/
|
||||
error_t i2c_controller_write_read(struct Device* device, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Reads data from a register of an I2C device using the specified controller.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] reg the register address to read from
|
||||
* @param[out] data the buffer to store the read data
|
||||
* @param[in] dataSize the number of bytes to read
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the read operation was successful
|
||||
*/
|
||||
error_t i2c_controller_read_register(struct Device* device, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes data to a register of an I2C device using the specified controller.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] reg the register address to write to
|
||||
* @param[in] data the buffer containing the data to write
|
||||
* @param[in] dataSize the number of bytes to write
|
||||
* @param[in] timeout the maximum time to wait for the operation to complete
|
||||
* @retval ERROR_NONE when the write operation was successful
|
||||
*/
|
||||
error_t i2c_controller_write_register(struct Device* device, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Writes an array of register-value pairs to an I2C device.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address of the slave device
|
||||
* @param[in] data an array of bytes where even indices are register addresses and odd indices are values
|
||||
* @param[in] dataSize the number of bytes in the data array (must be even)
|
||||
* @param[in] timeout the maximum time to wait for each operation to complete
|
||||
* @retval ERROR_NONE when all write operations were successful
|
||||
*/
|
||||
error_t i2c_controller_write_register_array(struct Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Checks if an I2C device is present at the specified address.
|
||||
* @param[in] device the I2C controller device
|
||||
* @param[in] address the 7-bit I2C address to check
|
||||
* @param[in] timeout the maximum time to wait for the check to complete
|
||||
* @retval ERROR_NONE when a device responded at the address
|
||||
*/
|
||||
error_t i2c_controller_has_device_at_address(struct Device* device, uint8_t address, TickType_t timeout);
|
||||
|
||||
extern const struct DeviceType I2C_CONTROLLER_TYPE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include <tactility/log.h>
|
||||
#include <atomic>
|
||||
|
||||
#define TAG LOG_TAG("Dispatcher")
|
||||
#define TAG LOG_TAG(Dispatcher)
|
||||
|
||||
static constexpr EventBits_t BACKPRESSURE_WARNING_COUNT = 100U;
|
||||
static constexpr EventBits_t WAIT_FLAG = 1U;
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include <string>
|
||||
|
||||
static const size_t LOCAL_STORAGE_SELF_POINTER_INDEX = 0;
|
||||
static const char* TAG = LOG_TAG("Thread");
|
||||
static const char* TAG = LOG_TAG(Thread);
|
||||
|
||||
struct Thread {
|
||||
TaskHandle_t taskHandle = nullptr;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#include <tactility/freertos/task.h>
|
||||
#include <tactility/log.h>
|
||||
|
||||
static const auto* TAG = LOG_TAG("Kernel");
|
||||
static const auto* TAG = LOG_TAG(Kernel);
|
||||
|
||||
static void log_memory_info() {
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
@ -23,6 +23,33 @@ error_t i2c_controller_write_read(Device* device, uint8_t address, const uint8_t
|
||||
return I2C_DRIVER_API(driver)->write_read(device, address, writeData, writeDataSize, readData, readDataSize, timeout);
|
||||
}
|
||||
|
||||
error_t i2c_controller_read_register(Device* device, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
return I2C_DRIVER_API(driver)->read_register(device, address, reg, data, dataSize, timeout);
|
||||
}
|
||||
|
||||
error_t i2c_controller_write_register(Device* device, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
return I2C_DRIVER_API(driver)->write_register(device, address, reg, data, dataSize, timeout);
|
||||
}
|
||||
|
||||
error_t i2c_controller_write_register_array(Device* device, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
assert(dataSize % 2 == 0);
|
||||
error_t error;
|
||||
for (int i = 0; i < dataSize; i += 2) {
|
||||
error = I2C_DRIVER_API(driver)->write_register(device, address, data[i], &data[i + 1], 1, timeout);
|
||||
if (error != ERROR_NONE) break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
error_t i2c_controller_has_device_at_address(Device* device, uint8_t address, TickType_t timeout) {
|
||||
const auto* driver = device_get_driver(device);
|
||||
uint8_t message[2] = { 0, 0 };
|
||||
return I2C_DRIVER_API(driver)->write(device, address, message, 2, timeout);
|
||||
}
|
||||
|
||||
const struct DeviceType I2C_CONTROLLER_TYPE { 0 };
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user