Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
Diff: source/family/arm/musca_b/i2c_gpio.c
- Revision:
- 0:01f31e923fe2
diff -r 000000000000 -r 01f31e923fe2 source/family/arm/musca_b/i2c_gpio.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/family/arm/musca_b/i2c_gpio.c Tue Apr 07 12:55:42 2020 +0200 @@ -0,0 +1,262 @@ +/** + * @file i2c_gpio.c + * @brief I2C GPIO control for musca PCA9537 + * + * DAPLink Interface Firmware + * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "string.h" +#include "stdio.h" +#include "stdint.h" + +#include "gpio.h" +#include "utils.h" +#include "i2c_gpio.h" + +// Clock registers +#define I2CGPIO_FREQ 6 // Sets OSC Clock SCL frequency +#define I2CGPIO_WR 0 // Write command +#define I2CGPIO_RD 1 // Read command +#define I2CGPIO_ADDR 0x49 // Default slave address for PCA9537 + +/*---------------------------------------------------------------------------- + I2C Address + Wr + A + *----------------------------------------------------------------------------*/ +void i2c_gpio_addr(unsigned int addr, unsigned int read) +{ + unsigned int loop, data; + + // Repeated Start condition (if required after Command) + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Start condition 'S' (DATA > CLK) + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + + // Addr is 7 bits so add Read + data = (addr << 1) & 0xFE; + if (read) + data |= 0x01; + + // Clock out the 8 bits + for (loop = 0; loop < 8; loop++) + { + if (data & (0x80 >> loop)) + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + else + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + } + + // Set data low + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Transmission clock 'A' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); +} + +/*---------------------------------------------------------------------------- + I2C Command + A + *----------------------------------------------------------------------------*/ +void i2c_gpio_cmd(unsigned int cmd) +{ + unsigned int loop; + + // Clock out the 8 bits + for (loop = 0; loop < 8; loop++) + { + if (cmd & (0x80 >> loop)) + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + else + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + } + + // Set data low + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Transmission clock 'A' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); +} + +/*---------------------------------------------------------------------------- + I2C Write Data + A + P + *----------------------------------------------------------------------------*/ +void i2c_gpio_write(unsigned int data) +{ + unsigned int loop; + + // Clock out the 8 bits + for (loop = 0; loop < 8; loop++) + { + if (data & (0x80 >> loop)) + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + else + { + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + } + + // Set data low + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Transmission clock 'A' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + + // Stop condition 'P' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); +} + +/*---------------------------------------------------------------------------- + I2C Read Data + A + P + *----------------------------------------------------------------------------*/ +void i2c_gpio_read(unsigned int *data, unsigned int ack) +{ + unsigned int loop; + + // Set SDA high (O/D) and allow PCA9537 to drive SDA + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Clock in the 8 bits + *data = 0; + for (loop = 0; loop < 8; loop++) + { + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + if (LPC_GPIO->DIR[PIN_I2C_SDA_PORT] & PIN_I2C_SDA) + *data &= ~(0x80 >> loop); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + } + + // Set data for acknowledge + delay_us(I2CGPIO_FREQ); + if (ack) + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + else + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Transmission clock 'A' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] |= PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + + // End of acknowledge + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] |= PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); + + // Stop condition 'P' + LPC_GPIO->DIR[PIN_I2C_SCL_PORT] &= ~PIN_I2C_SCL; + delay_us(I2CGPIO_FREQ); + LPC_GPIO->DIR[PIN_I2C_SDA_PORT] &= ~PIN_I2C_SDA; + delay_us(I2CGPIO_FREQ); +} + +/*---------------------------------------------------------------------------- + I2C Write byte + *----------------------------------------------------------------------------*/ +void i2c_gpio_wbyte(unsigned int cmd, unsigned int data) +{ + // Set slave address write + i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_WR); + // Set command + i2c_gpio_cmd(cmd); + // Write the data + i2c_gpio_write(data); +} + +/*---------------------------------------------------------------------------- + I2C Read byte + *----------------------------------------------------------------------------*/ +void i2c_gpio_rbyte(unsigned int cmd, unsigned int *data) +{ + // Set slave address write + i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_WR); + // Set command + i2c_gpio_cmd(cmd); + + // Set slave address write + i2c_gpio_addr(I2CGPIO_ADDR, I2CGPIO_RD); + // Read the data + i2c_gpio_read(data, 0); +} + +// end of i2c_gpio.c