pikapython/package/ESP32/pika_hal_ESP32_IIC.c

280 lines
7.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../PikaStdDevice/pika_hal.h"
#include "driver/i2c.h"
#define TEMP_SDA_IO 41 // 这里应该备多组i2c的io以对应不同I2Cx
#define TEMP_SCL_IO 42
typedef struct
{
i2c_config_t conf;
int port;
unsigned int timeout;
PIKA_HAL_IIC_MEM_ADDR mem_addr;
PIKA_HAL_IIC_MEM_ADDR_ENA mem_addr_ena;
PIKA_HAL_IIC_MEM_ADDR_SIZE mem_addr_size;
unsigned int slave_addr;
} esp_iic_t;
int pika_hal_platform_IIC_open(pika_dev *dev, char *name)
{
esp_iic_t *platform_i2c = pikaMalloc(sizeof(esp_iic_t));
memset(platform_i2c, 0, sizeof(esp_iic_t));
dev->platform_data = platform_i2c;
int iic_num = fast_atoi(name + 3);
if (!(name[0] == 'I' && name[1] == 'I' && name[2] == 'C') || iic_num <= I2C_NUM_MAX)
{
__platform_printf("IIC: Open %s failed\r\n", name);
goto err;
}
platform_i2c->port = iic_num;
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_close(pika_dev *dev)
{
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
if (NULL == platform_i2c)
{
goto err;
}
pikaFree(platform_i2c, sizeof(esp_iic_t));
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_ioctl_config(pika_dev *dev,
pika_hal_IIC_config *cfg)
{
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
if (dev->is_enabled)
{
goto err;
}
platform_i2c->timeout = cfg->timeout;
platform_i2c->mem_addr = cfg->mem_addr;
platform_i2c->mem_addr_ena = cfg->mem_addr_ena;
platform_i2c->mem_addr_size = cfg->mem_addr_size;
platform_i2c->slave_addr = cfg->slave_addr;
platform_i2c->conf.sda_io_num = TEMP_SDA_IO;
platform_i2c->conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
platform_i2c->conf.scl_io_num = TEMP_SCL_IO;
platform_i2c->conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
switch (cfg->master_or_slave)
{
case PIKA_HAL_IIC_MASTER:
platform_i2c->conf.mode = I2C_MODE_MASTER;
platform_i2c->conf.master.clk_speed = cfg->speed;
break;
case PIKA_HAL_IIC_SLAVE:
platform_i2c->conf.mode = I2C_MODE_SLAVE;
if (cfg->address_width == PIKA_HAL_IIC_ADDRESS_WIDTH_7BIT)
{
platform_i2c->conf.slave.addr_10bit_en = 0;
}
else if (cfg->address_width == PIKA_HAL_IIC_ADDRESS_WIDTH_10BIT)
{
platform_i2c->conf.slave.addr_10bit_en = 1;
}
platform_i2c->conf.slave.maximum_speed = cfg->speed;
break;
default:
goto err;
}
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_ioctl_enable(pika_dev *dev)
{
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
if (dev->is_enabled)
{
goto err;
}
i2c_config_t conf = platform_i2c->conf;
esp_err_t res = i2c_param_config(platform_i2c->port, &conf);
if (res != ESP_OK)
{
goto err;
}
i2c_driver_install(platform_i2c->port, conf.mode, 0, 0, 0);
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_ioctl_disable(pika_dev *dev)
{
if (!dev->is_enabled)
{
goto err;
}
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
i2c_driver_delete(platform_i2c->port);
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_write(pika_dev *dev, void *buf, size_t count)
{
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
int res = ESP_OK;
if (platform_i2c->conf.mode == I2C_MODE_MASTER)
{
uint8_t buffer[360] = {0};
i2c_cmd_handle_t handle = i2c_cmd_link_create_static(buffer, sizeof(buffer));
assert(handle != NULL);
res = i2c_master_start(handle);
if (res != ESP_OK)
{
goto end;
}
res = i2c_master_write_byte(handle, platform_i2c->slave_addr << 1 | I2C_MASTER_WRITE, true);
if (res != ESP_OK)
{
goto end;
}
if (platform_i2c->mem_addr_ena)
{
if (platform_i2c->mem_addr_size == PIKA_HAL_IIC_MEM_ADDR_SIZE_8BIT)
{
res = i2c_master_write(handle, (uint8_t *)&platform_i2c->mem_addr, 1, true);
}
else if (platform_i2c->mem_addr_size == PIKA_HAL_IIC_MEM_ADDR_SIZE_16BIT)
{
res = i2c_master_write(handle, (uint8_t *)&platform_i2c->mem_addr, 2, true);
}
if (res != ESP_OK)
{
goto end;
}
}
res = i2c_master_write(handle, (uint8_t*)buf, count, true);
if (res != ESP_OK)
{
goto end;
}
i2c_master_stop(handle);
res = i2c_master_cmd_begin(platform_i2c->port, handle, platform_i2c->timeout / portTICK_PERIOD_MS);
end:
i2c_cmd_link_delete_static(handle);
if (res != ESP_OK)
{
goto err;
}
}
else if (platform_i2c->conf.mode == I2C_MODE_SLAVE)
{
res = i2c_slave_write_buffer(platform_i2c->port, (uint8_t*)buf, count, platform_i2c->timeout / portTICK_PERIOD_MS);
if (res != ESP_OK)
{
goto err;
}
}
return 0;
err:
return -1;
}
int pika_hal_platform_IIC_read(pika_dev *dev, void *buf, size_t count)
{
esp_iic_t *platform_i2c = (esp_iic_t *)dev->platform_data;
int res = ESP_OK;
if (platform_i2c->conf.mode == I2C_MODE_MASTER)
{
uint8_t buffer[360] = {0}; // 360是底层宏运算出来的结果原宏为sizeof(i2c_cmd_desc_t) + sizeof(i2c_cmd_link_t) * 8在components/driver/i2c.c中
i2c_cmd_handle_t handle = i2c_cmd_link_create_static(buffer, sizeof(buffer));
assert(handle != NULL);
res = i2c_master_start(handle);
if (res != ESP_OK)
{
goto end;
}
if (platform_i2c->mem_addr_ena)
{
res = i2c_master_write_byte(handle, platform_i2c->slave_addr << 1 | I2C_MASTER_WRITE, true);
if (res != ESP_OK)
{
goto end;
}
if (platform_i2c->mem_addr_size == PIKA_HAL_IIC_MEM_ADDR_SIZE_8BIT)
{
res = i2c_master_write(handle, (uint8_t *)&platform_i2c->mem_addr, 1, true);
if (res != ESP_OK)
{
goto end;
}
}
else if (platform_i2c->mem_addr_size == PIKA_HAL_IIC_MEM_ADDR_SIZE_16BIT)
{
res = i2c_master_write(handle, (uint8_t *)&platform_i2c->mem_addr, 2, true);
if (res != ESP_OK)
{
goto end;
}
}
res = i2c_master_start(handle);
if (res != ESP_OK)
{
goto end;
}
}
res = i2c_master_write_byte(handle, platform_i2c->slave_addr << 1 | I2C_MASTER_READ, true);
if (res != ESP_OK)
{
goto end;
}
res = i2c_master_read(handle, (uint8_t*)buf, count, I2C_MASTER_LAST_NACK);
if (res != ESP_OK)
{
goto end;
}
i2c_master_stop(handle);
res = i2c_master_cmd_begin(platform_i2c->port, handle, platform_i2c->timeout);
end:
i2c_cmd_link_delete_static(handle);
if (res != ESP_OK)
{
goto err;
}
}
else if (platform_i2c->conf.mode == I2C_MODE_SLAVE)
{
res = i2c_slave_read_buffer(platform_i2c->port, (uint8_t*)buf, count, platform_i2c->timeout / portTICK_PERIOD_MS);
if (res != ESP_OK)
{
goto err;
}
}
return 0;
err:
return -1;
}