diff --git a/extras/fast_i2c/component.mk b/extras/fast_i2c/component.mk new file mode 100644 index 0000000..795c501 --- /dev/null +++ b/extras/fast_i2c/component.mk @@ -0,0 +1,10 @@ +# Component makefile for fast_i2c/i2c + +# expected anyone using i2c driver includes it as 'fast_i2c/i2c.h' +INC_DIRS += $(i2c_ROOT).. + +# args for passing into compile rule generation +i2c_INC_DIR = +i2c_SRC_DIR = $(i2c_ROOT) + +$(eval $(call component_compile_rules,i2c)) diff --git a/extras/fast_i2c/i2c.c b/extras/fast_i2c/i2c.c new file mode 100644 index 0000000..72ec26e --- /dev/null +++ b/extras/fast_i2c/i2c.c @@ -0,0 +1,161 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lilian Marazano (github.com/Zaltora) + * Based on Baoshi i2c library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "i2c.h" + +static uint8_t _scl_pin; +static uint8_t _sda_pin; + +void i2c_init(uint8_t scl_pin, uint8_t sda_pin) { + + _scl_pin = scl_pin ; + _sda_pin = sda_pin ; + + gpio_enable(_sda_pin, GPIO_OUT_OPEN_DRAIN); + gpio_enable(_scl_pin, GPIO_OUT_OPEN_DRAIN); + // Set idle bus high + _SDA1; + _SCL1; + + return; +} + +uint8_t i2c_start(void) { + + _SDA1; + _SCL1; + _DELAY; + if (_SDAX == 0) return false; // Bus busy + _SDA0; + _DELAY; + _SCL0; + return true; +} + +void i2c_stop(void) { + + _SDA0; + _SCL1; + _DELAY; + while (_SCLX == 0); // clock stretching + _SDA1; + _DELAY; +} + +uint8_t i2c_write(uint8_t data) { + + uint8_t ibit; + uint8_t ret; + + for (ibit = 0; ibit < 8; ++ibit) + { + if (data & 0x80) + _SDA1; + else + _SDA0; + _DELAY; + _SCL1; + _DELAY; + data = data << 1; + _SCL0; + } + _SDA1; + _DELAY; + _SCL1; + _DELAY; + ret = (_SDAX == 0); + _SCL0; + _DELAY; + + return ret; +} + +uint8_t i2c_read(uint8_t ack) { + + uint8_t data = 0; + uint8_t ibit = 8; + + _SDA1; + while (ibit--) + { + data = data << 1; + _SCL0; + _DELAY; + _SCL1; + _DELAY; + if (_SDAX) + data = data | 0x01; + } + _SCL0; + if (ack) + _SDA0; // ACK + else + _SDA1; // NACK + _DELAY; + // Send clock + _SCL1; + _DELAY; + _SCL0; + _DELAY; + // ACK end + _SDA1; + + return data; +} + +bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint16_t len) { + + i2c_start(); + if(!i2c_write(slave_addr<<1)) goto fail_send; // adress + W + if(!i2c_write(data)) goto fail_send; //Send byte + i2c_start(); // restart condition + if(!i2c_write((slave_addr<<1) | 1)) goto fail_send; // adress + R + + while(--len) { + *(buf++) = i2c_read(1); + } + *buf = i2c_read(0); + i2c_stop(); + return true; + + fail_send: + i2c_stop(); + return false ; +} + +bool i2c_slave_write(uint8_t slave_addr, uint8_t *buf, uint16_t len) { + + i2c_start(); + if(!i2c_write(slave_addr<<1)) goto fail_send ; // adress + W + while (len--) { + if(!i2c_write((uint8_t) *(buf++))) goto fail_send ; + } + i2c_stop(); + return true; + + fail_send: + i2c_stop(); + return false ; +} diff --git a/extras/fast_i2c/i2c.h b/extras/fast_i2c/i2c.h new file mode 100644 index 0000000..b9f54b4 --- /dev/null +++ b/extras/fast_i2c/i2c.h @@ -0,0 +1,102 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015 Lilian Marazano (github.com/Zaltora) + * Based on Baoshi i2c library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __I2C_H__ +#define __I2C_H__ +#endif + +#include +#include // sdk_os_delay_us +#include +#include + + +//#define _DELAY sdk_os_delay_us(1) // can up to 300kHz max +#define _DELAY for (volatile uint32_t __j = 3; __j > 0; __j--) // can up to 1.9MHz max at 160MHz clock + +// if you want use an other API for GPIO or use GPIO16, change here +#define _SDA1 gpio_write(_sda_pin, 1) +#define _SDA0 gpio_write(_sda_pin, 0) + +#define _SCL1 gpio_write(_scl_pin, 1) +#define _SCL0 gpio_write(_scl_pin, 0) + +#define _SDAX gpio_read(_sda_pin) +#define _SCLX gpio_read(_scl_pin) + + +/** + * @brief Init I2C bus + * @param scl_pin SCL pin number + * @param sda_pin SDA pin number + */ +void i2c_init(uint8_t scl_pin, uint8_t sda_pin) ; + +/** + * @brief Send data to I2C bus + * @param data Data to send + * @return true if ACK is received at end of sending. False if not ACK'ed + */ +uint8_t i2c_write(uint8_t data); + +/** + * @brief Read data from I2C bus + * @param ack ACK (true) or NACK (false) + * @return Data read + */ +uint8_t i2c_read(uint8_t ack); + + + +/** + * @brief Send I2C start bit + * @return true if start successfully. Otherwise the bus is busy + */ +uint8_t i2c_start(void); + +/** + * @brief Send I2C stop bit + */ +void i2c_stop(void); + +/** + * @brief Write multiple bytes to a device. + * @param slave_addr I2C slave device address + * @param buf Buffer to copy new data from + * @param len Number of bytes to write + * @return Status of operation (true = success) + */ +bool i2c_slave_write(uint8_t slave_addr, uint8_t *buf, uint16_t len); + +/** + * @brief Read multiple bytes from a device register. + * @param slave_addr I2C slave device address + * @param data First register to read from + * @param buf Buffer to store read data in + * @param len Number of bytes to read + * @return Status of read operation (true = success) + */ +bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint16_t len); +