#include <stdio.h>
#include <string.h>
#include <driver/i2c.h>
#include "hal/atca_hal.h"
#include "esp_err.h"
#include "esp_log.h"
#define SDA_PIN 16
#define SCL_PIN 17
#define ACK_CHECK_EN 0x1
#define ACK_CHECK_DIS 0x0
#define ACK_VAL 0x0
#define NACK_VAL 0x1
#ifndef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#endif
#define MAX_I2C_BUSES 2
typedef struct atcaI2Cmaster
{
int id;
int ref_ct;
int bus_index;
} ATCAI2CMaster_t;
ATCAI2CMaster_t *i2c_hal_data[MAX_I2C_BUSES];
int i2c_bus_ref_ct = 0;
i2c_config_t conf;
const char* TAG = "HAL_I2C";
void hal_i2c_change_baud(ATCAIface iface, uint32_t speed)
{
esp_err_t rc;
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
int bus = cfg->atcai2c.bus;
conf.master.clk_speed = speed;
rc = i2c_param_config(i2c_hal_data[bus]->id, &conf);
if (rc == ESP_OK)
{
}
else
{
}
}
ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg)
{
esp_err_t rc;
int bus = cfg->atcai2c.bus;
ATCAHAL_t *phal = (ATCAHAL_t*)hal;
if (i2c_bus_ref_ct == 0)
{
for (int i = 0; i < MAX_I2C_BUSES; i++)
{
i2c_hal_data[i] = NULL;
}
}
i2c_bus_ref_ct++;
if (bus >= 0 && bus < MAX_I2C_BUSES)
{
if (i2c_hal_data[bus] == NULL)
{
i2c_hal_data[bus] = malloc(sizeof(ATCAI2CMaster_t));
i2c_hal_data[bus]->ref_ct = 1;
switch (bus)
{
case 0:
i2c_hal_data[bus]->id = I2C_NUM_0;
break;
case 1:
i2c_hal_data[bus]->id = I2C_NUM_1;
break;
}
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = SDA_PIN;
conf.scl_io_num = SCL_PIN;
conf.sda_pullup_en = GPIO_PULLUP_DISABLE;
conf.scl_pullup_en = GPIO_PULLUP_DISABLE;
conf.master.clk_speed = 100000; rc = i2c_param_config(i2c_hal_data[bus]->id, &conf);
rc = i2c_driver_install(i2c_hal_data[bus]->id, I2C_MODE_MASTER, 0, 0, 0);
i2c_hal_data[bus]->bus_index = bus;
}
else
{
i2c_hal_data[bus]->ref_ct++;
}
phal->hal_data = i2c_hal_data[bus];
return ATCA_SUCCESS;
}
return ATCA_COMM_FAIL;
}
ATCA_STATUS hal_i2c_post_init(ATCAIface iface)
{
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
ATCAIfaceCfg *cfg = iface->mIfaceCFG;
esp_err_t rc;
txdata[0] = 0x03; txlength++;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
(void)i2c_master_start(cmd);
(void)i2c_master_write_byte(cmd, cfg->atcai2c.slave_address | I2C_MASTER_WRITE, ACK_CHECK_EN);
(void)i2c_master_write(cmd, txdata, txlength, ACK_CHECK_EN);
(void)i2c_master_stop(cmd);
rc = i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
if (ESP_OK != rc)
{
return ATCA_COMM_FAIL;
}
else
{
return ATCA_SUCCESS;
}
}
ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
{
ATCAIfaceCfg *cfg = iface->mIfaceCFG;
esp_err_t rc;
i2c_cmd_handle_t cmd;
int high = 0;
int low = 0;
cmd = i2c_cmd_link_create();
(void)i2c_master_start(cmd);
(void)i2c_master_write_byte(cmd, cfg->atcai2c.slave_address | I2C_MASTER_READ, ACK_CHECK_EN);
(void)i2c_master_read_byte(cmd, rxdata, ACK_VAL);
rc = i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
if (ESP_OK != rc)
{
return ATCA_COMM_FAIL;
}
*rxlength = rxdata[0];
if (*rxlength > 1)
{
cmd = i2c_cmd_link_create();
if (*rxlength > 2)
{
(void)i2c_master_read(cmd, &rxdata[1], (*rxlength) - 2, ACK_VAL);
}
(void)i2c_master_read_byte(cmd, rxdata + (*rxlength) - 1, NACK_VAL);
(void)i2c_master_stop(cmd);
rc = i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
}
else
{
cmd = i2c_cmd_link_create();
(void)i2c_master_stop(cmd);
rc = i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
}
if (ESP_OK != rc)
{
return ATCA_COMM_FAIL;
}
else
{
return ATCA_SUCCESS;
}
}
ATCA_STATUS hal_i2c_release(void *hal_data)
{
ATCAI2CMaster_t *hal = (ATCAI2CMaster_t*)hal_data;
i2c_bus_ref_ct--;
if (hal && --(hal->ref_ct) <= 0 && i2c_hal_data[hal->bus_index] != NULL)
{
i2c_driver_delete(hal->bus_index);
free(i2c_hal_data[hal->bus_index]);
i2c_hal_data[hal->bus_index] = NULL;
}
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint16_t rxlen;
uint8_t data[4] = { 0 };
const uint8_t expected[4] = { 0x04, 0x11, 0x33, 0x43 };
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
(void)i2c_master_start(cmd);
(void)i2c_master_write_byte(cmd, I2C_MASTER_WRITE, ACK_CHECK_DIS);
(void)i2c_master_stop(cmd);
(void)i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
atca_delay_ms(10);
rxlen = 4;
hal_i2c_receive(iface, data, &rxlen);
if (memcmp(data, expected, 4) == 0)
{
return ATCA_SUCCESS;
}
return ATCA_COMM_FAIL;
}
ATCA_STATUS hal_i2c_idle(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t idle_data = 0x02;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
(void)i2c_master_start(cmd);
(void)i2c_master_write_byte(cmd, cfg->atcai2c.slave_address | I2C_MASTER_WRITE, ACK_CHECK_EN);
(void)i2c_master_write(cmd, &idle_data, 1, ACK_CHECK_DIS);
(void)i2c_master_stop(cmd);
(void)i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_sleep(ATCAIface iface)
{
ATCAIfaceCfg *cfg = atgetifacecfg(iface);
uint8_t sleep_data = 0x01;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
(void)i2c_master_start(cmd);
(void)i2c_master_write_byte(cmd, cfg->atcai2c.slave_address | I2C_MASTER_WRITE, ACK_CHECK_EN);
(void)i2c_master_write(cmd, &sleep_data, 1, ACK_CHECK_DIS);
(void)i2c_master_stop(cmd);
(void)i2c_master_cmd_begin(cfg->atcai2c.bus, cmd, 10);
(void)i2c_cmd_link_delete(cmd);
return ATCA_SUCCESS;
}
ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses)
{
return ATCA_UNIMPLEMENTED;
}
ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg *cfg, int *found)
{
return ATCA_UNIMPLEMENTED;
}