/**************************************************************************** * * Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED. * * This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT * be copied by any method or incorporated into another program without * the express written consent of Aerospace C.Power. This Information or any portion * thereof remains the property of Aerospace C.Power. The Information contained herein * is believed to be accurate and Aerospace C.Power assumes no responsibility or * liability for its use in any way and conveys no license or title under * any patent or copyright and makes no representation or warranty that this * Information is free from patent or copyright infringement. * * ****************************************************************************/ #include "iot_errno.h" #include "iot_app_api.h" #include "iot_i2c_api.h" #include "mcp_io_drv.h" #include "iot_io_api.h" #include "os_utils_api.h" #include "iot_gpio_api.h" iot_i2c_module_cfg_t g_cfg; static uint32_t mcp_write_command(uint8_t reg, uint8_t val) { uint8_t ret; char buf[3]; buf[0] = reg; buf[1] = val; ret = iot_i2c_write(g_cfg.port, MCP_SLAVER_ADDR, buf, 2); os_delay(100); //iot_cus_printf("\nMCP : WRITE REG#%02x, DATA#%02x", 0xFF & ((int)reg), 0xFF & ((int)val)); return (ERR_OK == ret) ? ERR_OK : ERR_FAIL; } uint32_t mcp_read_command(uint8_t reg, uint8_t *data, uint8_t len) { uint8_t ret; char buf[3]; buf[0] = reg; ret = iot_i2c_write(g_cfg.port, MCP_SLAVER_ADDR, buf, 1); os_delay(10); if (ERR_OK != ret) { return ERR_FAIL; } ret = iot_i2c_read(g_cfg.port, MCP_SLAVER_ADDR, (char *)data, len); os_delay(100); if (ERR_OK != ret) { iot_cus_printf("\nMCP : READ REG#%02x , TIMEOUT", 0xFF & ((int)reg)); return ERR_FAIL; } // iot_cus_printf("\nMCP : READ REG#%02x, DATA#%02x", 0xFF & ((int)reg), 0xFF & ((int)*data)); return ERR_OK; } uint32_t mcp_gpio_get_value(uint32_t gpio) { uint32_t ret; uint8_t data; if (!MCP_GPIO_VALID(gpio)) { return ERR_FAIL; } ret = mcp_read_command(GPIO(gpio), &data, 1); if (ERR_OK != ret) { return ERR_FAIL; } return MCP_IO_GET(data, gpio); } uint32_t mcp_gpio_set_value(uint32_t gpio, uint32_t val) { uint32_t ret; uint8_t data; if (!MCP_GPIO_VALID(gpio)) { return ERR_FAIL; } ret = mcp_read_command(GPIO(gpio), &data, 1); if (ERR_OK != ret) { return ERR_FAIL; } if (0 == val) { MCP_IO_CLEAR(data, gpio); } else { MCP_IO_SET(data, gpio); } ret = mcp_write_command(GPIO(gpio), data); if (ERR_OK != ret) { return ERR_FAIL; } return ERR_OK; } uint32_t mcp_gpio_set_dir(uint32_t gpio, uint32_t dir) { uint32_t ret; uint8_t data; if (!MCP_GPIO_VALID(gpio)) { return ERR_FAIL; } ret = mcp_read_command(IODIR(gpio), &data, 1); if (ERR_OK != ret) { return ERR_FAIL; } if (MCP_GPIO_INPUT == dir) { MCP_IO_SET(data, gpio); } else { MCP_IO_CLEAR(data, gpio); } ret = mcp_write_command(IODIR(gpio), data); if (ERR_OK != ret) { return ERR_FAIL; } return ERR_OK; } uint32_t mcp_gpio_set_interrupt(uint32_t gpio, uint32_t enable, uint32_t mode) { uint32_t ret; uint8_t gpinten, defval, intcon; if ((!MCP_GPIO_VALID(gpio) || (enable && (MCP_GPIO_RAISING != mode) && (MCP_GPIO_FALLING != mode) && (MCP_GPIO_BOTH_EDGE != mode)))) { return ERR_FAIL; } ret = mcp_read_command(GPINTEN(gpio), &gpinten, 1); if (enable) { ret |= mcp_read_command(DEFVAL(gpio), &defval, 1); ret |= mcp_read_command(INTCON(gpio), &intcon, 1); } if (ERR_OK != ret) { return ERR_FAIL; } if (enable) { MCP_IO_SET(gpinten, gpio); if (MCP_GPIO_RAISING == mode) { MCP_IO_SET(intcon, gpio); MCP_IO_CLEAR(defval, gpio); } else if (MCP_GPIO_FALLING == mode) { MCP_IO_SET(intcon, gpio); MCP_IO_SET(defval, gpio); } else { MCP_IO_CLEAR(intcon, gpio); } ret = mcp_write_command(DEFVAL(gpio), defval); ret |= mcp_write_command(INTCON(gpio), intcon); if (ERR_OK != ret) { return ERR_FAIL; } } else { MCP_IO_CLEAR(gpinten, gpio); } ret = mcp_write_command(GPINTEN(gpio), gpinten); if (ERR_OK != ret) { return ERR_FAIL; } return ERR_OK; } uint32_t mcp_gpio_get_int_gpio(void) { uint32_t port, final_pend = 0; uint8_t intcap[MCP_GPMAX], intf, int_flag = 0; for (port = 0; port < MCP_GPMAX; port++) { mcp_read_command(INTF(port * MCP_MAX_GPIO_NUM_PER_PORT), &intf, 1); if (intf) { int_flag = 1; /* Walk all port, no break. */ } } if (0 == int_flag) { return 0; } /* Read GPIO or INTCAP will clear the interrupt satus. */ for (port = 0; port < MCP_GPMAX; port++) { mcp_read_command(INTCAP(port * MCP_MAX_GPIO_NUM_PER_PORT), &intcap[port], 1); } for (port = MCP_GPMAX; port > 0; port--) { final_pend <<= (8 * sizeof(intcap[0])); final_pend |= intcap[port - 1]; } return final_pend; } uint32_t mcp_gpio_set_pullup(uint32_t gpio, uint32_t enable) { uint32_t ret; uint8_t data; if (!MCP_GPIO_VALID(gpio)) { return ERR_FAIL; } ret = mcp_read_command(GPPU(gpio), &data, 1); if (ERR_OK != ret) { return ERR_FAIL; } if (enable) { MCP_IO_SET(data, gpio); } else { MCP_IO_CLEAR(data, gpio); } ret = mcp_write_command(GPPU(gpio), data); if (ERR_OK != ret) { return ERR_FAIL; } return ERR_OK; } uint32_t mcp_init(void) { g_cfg.port = IOT_I2C_PORT_0; g_cfg.nack_wait_num = 10; g_cfg.baud = 400; g_cfg.gpio.scl = MCP_SCL_GPIO; g_cfg.gpio.sda = MCP_SDA_GPIO; if ((ERR_OK != iot_gpio_open_as_output(g_cfg.gpio.scl)) || (ERR_OK != iot_gpio_open_as_output(g_cfg.gpio.sda))) { return ERR_FAIL; } iot_gpio_set_pull_mode(g_cfg.gpio.scl, GPIO_PULL_UP); iot_gpio_set_pull_mode(g_cfg.gpio.sda, GPIO_PULL_UP); if (ERR_OK != iot_i2c_module_init(&g_cfg)) { iot_gpio_close(g_cfg.gpio.scl); iot_gpio_close(g_cfg.gpio.sda); return ERR_FAIL; } return ERR_OK; }