From 513dda8ea7e8c4bb668c89dba035f387dfcaa741 Mon Sep 17 00:00:00 2001 From: "Alexander V. Ribchansky" Date: Wed, 5 Apr 2017 12:18:49 +0300 Subject: [PATCH] Ported from esp8266/Arduino i2c HAL and Wire library Ported from esp8266/Arduino i2c HAL, faster by direct pin manipulation not via digitalWrite, some additional features of i2c bus implemented --- Sming/Libraries/BH1750FVI/BH1750FVI.cpp | 2 +- Sming/SmingCore/Wire.cpp | 304 ++++++++++++++++-------- Sming/SmingCore/Wire.h | 129 ++++++---- Sming/SmingCore/core_esp8266_si2c.cpp | 213 +++++++++++++++++ Sming/SmingCore/twi.h | 48 ++++ Sming/Wiring/I2cMaster.cpp | 142 ----------- Sming/Wiring/I2cMaster.h | 86 ------- Sming/Wiring/WiringFrameworkIncludes.h | 1 - 8 files changed, 546 insertions(+), 379 deletions(-) create mode 100644 Sming/SmingCore/core_esp8266_si2c.cpp create mode 100644 Sming/SmingCore/twi.h delete mode 100644 Sming/Wiring/I2cMaster.cpp delete mode 100644 Sming/Wiring/I2cMaster.h diff --git a/Sming/Libraries/BH1750FVI/BH1750FVI.cpp b/Sming/Libraries/BH1750FVI/BH1750FVI.cpp index 6831f7535f..a3b61d3aa3 100644 --- a/Sming/Libraries/BH1750FVI/BH1750FVI.cpp +++ b/Sming/Libraries/BH1750FVI/BH1750FVI.cpp @@ -48,7 +48,7 @@ uint16_t BH1750FVI::getLightIntensity(void) { uint16_t Intensity_value; Wire.beginTransmission(address_value); - int res = Wire.requestFrom(address_value, 2); + int res = Wire.requestFrom(address_value, (uint8_t)2); Intensity_value = Wire.read(); Intensity_value <<= 8; Intensity_value |= Wire.read(); diff --git a/Sming/SmingCore/Wire.cpp b/Sming/SmingCore/Wire.cpp index 75554fb9f7..36e3c2c932 100644 --- a/Sming/SmingCore/Wire.cpp +++ b/Sming/SmingCore/Wire.cpp @@ -1,145 +1,249 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ +/* + TwoWire.cpp - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts + Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support + Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support +*/ + +extern "C" { + #include + #include + #include +} -#include "../SmingCore/Wire.h" +#include "twi.h" +#include "Wire.h" -#include "../SmingCore/Digital.h" -#include "../Wiring/WiringFrameworkIncludes.h" +// Initialize Class Variables ////////////////////////////////////////////////// -TwoWire::TwoWire(int pinSCL, int pinSDA) -{ - SCL = pinSCL; - SDA = pinSDA; - targetAddress = -1; - txLen = 0; - rxPos = 0; - rxLen = 0; - master = NULL; -} +uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::rxBufferIndex = 0; +uint8_t TwoWire::rxBufferLength = 0; -TwoWire::~TwoWire() -{ - if (master != NULL) - delete master; +uint8_t TwoWire::txAddress = 0; +uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::txBufferIndex = 0; +uint8_t TwoWire::txBufferLength = 0; + +uint8_t TwoWire::transmitting = 0; +void (*TwoWire::user_onRequest)(void); +void (*TwoWire::user_onReceive)(int); + +static int default_sda_pin = 2; +static int default_scl_pin = 0; + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire(){} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(int scl, int sda){ + default_sda_pin = sda; + default_scl_pin = scl; + twi_init(sda, scl); + flush(); } -void TwoWire::pins(int pinSCL, int pinSDA) -{ - SCL = pinSCL; - SDA = pinSDA; +void TwoWire::pins(int scl, int sda){ + default_sda_pin = sda; + default_scl_pin = scl; } -void TwoWire::begin() -{ - if (master != NULL) return; - master = new SoftI2cMaster(SDA, SCL); - master->stop(); // Ready to work +void TwoWire::begin(void){ + begin(default_scl_pin, default_sda_pin); } -void TwoWire::beginTransmission(uint8_t address) -{ - if (targetAddress != -1) - endTransmission(); +void TwoWire::begin(uint8_t address){ + // twi_setAddress(address); + // twi_attachSlaveTxEvent(onRequestService); + // twi_attachSlaveRxEvent(onReceiveService); + begin(); +} - targetAddress = (uint8_t)(address << 1); - txLen = 0; - rxPos = 0; - rxLen = 0; +uint8_t TwoWire::status(){ + return twi_status(); } -uint8_t TwoWire::endTransmission(bool sendStop /*= true*/) -{ - if (targetAddress == -1) return 4; // other error +void TwoWire::begin(int address){ + begin((uint8_t)address); +} - uint8_t result = 0; - result = pushData(); +void TwoWire::setClock(uint32_t frequency){ + twi_setClock(frequency); +} - if (sendStop) - master->stop(); - else - { - // Restart mode not tested!!! - digitalWrite(SDA, HIGH); - digitalWrite(SCL, HIGH); - } - return result; +void TwoWire::setClockStretchLimit(uint32_t limit){ + twi_setClockStretchLimit(limit); } -uint8_t TwoWire::pushData() -{ - if (txLen == -1) return 1; // data too long to fit in transmit buffer +size_t TwoWire::requestFrom(uint8_t address, size_t size, bool sendStop){ + if(size > BUFFER_LENGTH){ + size = BUFFER_LENGTH; + } + size_t read = (twi_readFrom(address, rxBuffer, size, sendStop) == 0)?size:0; + rxBufferIndex = 0; + rxBufferLength = read; + return read; +} - if (!master->start(targetAddress | I2C_WRITE)) return 2; // received NACK on transmit of address +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop){ + return requestFrom(address, static_cast(quantity), static_cast(sendStop)); +} - for (int i = 0; i < txLen; i++) - if (!master->write(txBuf[i])) - return 3; // received NACK on transmit of data +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity){ + return requestFrom(address, static_cast(quantity), true); +} - targetAddress = -1; - txLen = 0; - return 0; +uint8_t TwoWire::requestFrom(int address, int quantity){ + return requestFrom(static_cast(address), static_cast(quantity), true); } -uint8_t TwoWire::requestFrom(int address, int quantity, bool sendStop /* = true*/) -{ - rxPos = 0; - rxLen = 0; +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop){ + return requestFrom(static_cast(address), static_cast(quantity), static_cast(sendStop)); +} - if (!master->start(((uint8_t)(address << 1)) | I2C_READ)) return 0; // received NACK on transmit of address +void TwoWire::beginTransmission(uint8_t address){ + transmitting = 1; + txAddress = address; + txBufferIndex = 0; + txBufferLength = 0; +} - for (int i = 0; i < quantity; i++) - rxBuf[rxLen++] = master->read(quantity == i + 1); +void TwoWire::beginTransmission(int address){ + beginTransmission((uint8_t)address); +} - if(sendStop) - master->stop(); +uint8_t TwoWire::endTransmission(uint8_t sendStop){ + int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, sendStop); + txBufferIndex = 0; + txBufferLength = 0; + transmitting = 0; + return ret; +} - return quantity; +uint8_t TwoWire::endTransmission(void){ + return endTransmission(true); } -size_t TwoWire::write(uint8_t data) -{ - if(txLen >= BUFFER_LENGTH || txLen == -1) - { - txLen = -1; // Overflow :( +size_t TwoWire::write(uint8_t data){ + if(transmitting){ + if(txBufferLength >= BUFFER_LENGTH){ + setWriteError(); return 0; } + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + txBufferLength = txBufferIndex; + } else { + // i2c_slave_transmit(&data, 1); + } + return 1; +} - txBuf[txLen++] = data; - return 1; +size_t TwoWire::write(const uint8_t *data, size_t quantity){ + if(transmitting){ + for(size_t i = 0; i < quantity; ++i){ + if(!write(data[i])) return i; + } + }else{ + // i2c_slave_transmit(data, quantity); + } + return quantity; } -int TwoWire::available() -{ - return rxLen - rxPos; +int TwoWire::available(void){ + int result = rxBufferLength - rxBufferIndex; + return result; } -int TwoWire::read() -{ - if (rxLen > rxPos) - return rxBuf[rxPos++]; - else - return -1; +int TwoWire::read(void){ + int value = -1; + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + return value; } -int TwoWire::peek() -{ - return rxBuf[rxPos]; +int TwoWire::peek(void){ + int value = -1; + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + } + return value; } -void TwoWire::flush() -{ +void TwoWire::flush(void){ + rxBufferIndex = 0; + rxBufferLength = 0; + txBufferIndex = 0; + txBufferLength = 0; } -size_t TwoWire::write(const uint8_t *data, size_t quantity) +void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) { - for(size_t i = 0; i < quantity; i++) - write(data[i]); + // don't bother if user hasn't registered a callback + // if(!user_onReceive){ + // return; + // } + // // don't bother if rx buffer is in use by a master requestFrom() op + // // i know this drops data, but it allows for slight stupidity + // // meaning, they may not have read all the master requestFrom() data yet + // if(rxBufferIndex < rxBufferLength){ + // return; + // } + // // copy twi rx buffer into local read buffer + // // this enables new reads to happen in parallel + // for(uint8_t i = 0; i < numBytes; ++i){ + // rxBuffer[i] = inBytes[i]; + // } + // // set rx iterator vars + // rxBufferIndex = 0; + // rxBufferLength = numBytes; + // // alert user program + // user_onReceive(numBytes); +} - return quantity; +void TwoWire::onRequestService(void){ + // // don't bother if user hasn't registered a callback + // if(!user_onRequest){ + // return; + // } + // // reset tx buffer iterator vars + // // !!! this will kill any pending pre-master sendTo() activity + // txBufferIndex = 0; + // txBufferLength = 0; + // // alert user program + // user_onRequest(); } -TwoWire Wire = TwoWire(I2C_DEFAULT_SCL_PIN, I2C_DEFAULT_SDA_PIN); +void TwoWire::onReceive( void (*function)(int) ){ + //user_onReceive = function; +} + +void TwoWire::onRequest( void (*function)(void) ){ + //user_onRequest = function; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) +TwoWire Wire; +#endif diff --git a/Sming/SmingCore/Wire.h b/Sming/SmingCore/Wire.h index bd6009f6a2..f2ca80880d 100644 --- a/Sming/SmingCore/Wire.h +++ b/Sming/SmingCore/Wire.h @@ -1,60 +1,91 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/anakod/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - ****/ +/* + TwoWire.h - TWI/I2C library for Arduino & Wiring + Copyright (c) 2006 Nicholas Zambetti. All right reserved. -#ifndef _SMING_CORE_WIRE_H_ -#define _SMING_CORE_WIRE_H_ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. -#include "../Wiring/WiringFrameworkDependencies.h" -#include "../Wiring/Stream.h" + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. -// Default values -#define I2C_DEFAULT_SCL_PIN 0 -#define I2C_DEFAULT_SDA_PIN 2 -#define BUFFER_LENGTH 48 + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -class SoftI2cMaster; + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts + Modified December 2014 by Ivan Grokhotkov (ivan@esp8266.com) - esp8266 support + Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support +*/ + +#ifndef TwoWire_h +#define TwoWire_h + +#include +#include "Stream.h" + +#define BUFFER_LENGTH 32 class TwoWire : public Stream { -public: - TwoWire(int pinSCL, int pinSDA); - virtual ~TwoWire(); - - void pins(int pinSCL, int pinSDA); // Can be called only before begin() - void begin(); - - void beginTransmission(uint8_t address); - uint8_t endTransmission(bool sendStop = true); - uint8_t requestFrom(int address, int quantity, bool sendStop = true); - - virtual int available(); - virtual int read(); - virtual int peek(); - virtual void flush(); - size_t write(uint8_t data); - size_t write(const uint8_t *data, size_t quantity); - -protected: - uint8_t pushData(); - -private: - SoftI2cMaster* master; - int SCL; - int SDA; - int targetAddress; - - uint8_t txBuf[BUFFER_LENGTH]; - int txLen; - - uint8_t rxBuf[BUFFER_LENGTH]; - int rxLen; - int rxPos; + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + static uint8_t transmitting; + static void (*user_onRequest)(void); + static void (*user_onReceive)(int); + static void onRequestService(void); + static void onReceiveService(uint8_t*, int); + public: + TwoWire(); + void begin(int scl, int sda); + void pins(int scl, int sda); + void begin(); + void begin(uint8_t); + void begin(int); + void setClock(uint32_t); + void setClockStretchLimit(uint32_t); + void beginTransmission(uint8_t); + void beginTransmission(int); + uint8_t endTransmission(void); + uint8_t endTransmission(uint8_t); + size_t requestFrom(uint8_t address, size_t size, bool sendStop); + uint8_t status(); + + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(uint8_t, uint8_t, uint8_t); + uint8_t requestFrom(int, int); + uint8_t requestFrom(int, int, int); + + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *, size_t); + virtual int available(void); + virtual int read(void); + virtual int peek(void); + virtual void flush(void); + void onReceive( void (*)(int) ); + void onRequest( void (*)(void) ); + + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } + using Print::write; }; +#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) extern TwoWire Wire; +#endif + +#endif -#endif /* _SMING_CORE_WIRE_H_ */ diff --git a/Sming/SmingCore/core_esp8266_si2c.cpp b/Sming/SmingCore/core_esp8266_si2c.cpp new file mode 100644 index 0000000000..2bef2063ed --- /dev/null +++ b/Sming/SmingCore/core_esp8266_si2c.cpp @@ -0,0 +1,213 @@ +/* + si2c.c - Software I2C library for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "twi.h" +#include "Digital.h" + +unsigned char twi_dcount = 18; +static unsigned char twi_sda, twi_scl; +static uint32_t twi_clockStretchLimit; + +#define SDA_LOW() (GPES = (1 << twi_sda)) //Enable SDA (becomes output and since GPO is 0 for the pin, it will pull the line low) +#define SDA_HIGH() (GPEC = (1 << twi_sda)) //Disable SDA (becomes input and since it has pullup it will go high) +#define SDA_READ() ((GPI & (1 << twi_sda)) != 0) +#define SCL_LOW() (GPES = (1 << twi_scl)) +#define SCL_HIGH() (GPEC = (1 << twi_scl)) +#define SCL_READ() ((GPI & (1 << twi_scl)) != 0) + +#ifndef FCPU80 +#define FCPU80 80000000L +#endif + +#if F_CPU == FCPU80 +#define TWI_CLOCK_STRETCH_MULTIPLIER 3 +#else +#define TWI_CLOCK_STRETCH_MULTIPLIER 6 +#endif + +void twi_setClock(unsigned int freq){ +#if F_CPU == FCPU80 + if(freq <= 100000) twi_dcount = 19;//about 100KHz + else if(freq <= 200000) twi_dcount = 8;//about 200KHz + else if(freq <= 300000) twi_dcount = 3;//about 300KHz + else if(freq <= 400000) twi_dcount = 1;//about 400KHz + else twi_dcount = 1;//about 400KHz +#else + if(freq <= 100000) twi_dcount = 32;//about 100KHz + else if(freq <= 200000) twi_dcount = 14;//about 200KHz + else if(freq <= 300000) twi_dcount = 8;//about 300KHz + else if(freq <= 400000) twi_dcount = 5;//about 400KHz + else if(freq <= 500000) twi_dcount = 3;//about 500KHz + else if(freq <= 600000) twi_dcount = 2;//about 600KHz + else twi_dcount = 1;//about 700KHz +#endif +} + +void twi_setClockStretchLimit(uint32_t limit){ + twi_clockStretchLimit = limit * TWI_CLOCK_STRETCH_MULTIPLIER; +} + +void twi_init(unsigned char sda, unsigned char scl){ + twi_sda = sda; + twi_scl = scl; + pinMode(twi_sda, INPUT_PULLUP); + pinMode(twi_scl, INPUT_PULLUP); + twi_setClock(100000); + twi_setClockStretchLimit(230); // default value is 230 uS +} + + +void twi_stop(void){ + pinMode(twi_sda, INPUT); + pinMode(twi_scl, INPUT); +} + +static void twi_delay(unsigned char v){ + unsigned int i; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + unsigned int reg; + for(i=0;i0){ //if SDA low, read the bits slaves have to sent to a max + twi_read_bit(); + if (SCL_READ()==0) return I2C_SCL_HELD_LOW_AFTER_READ; //I2C bus error. SCL held low beyond slave clock stretch time + } + + if (SDA_READ()==0) return I2C_SDA_HELD_LOW; //I2C bus error. SDA line held low by slave/another_master after n bits. + + if(!twi_write_start()) return I2C_SDA_HELD_LOW_AFTER_INIT; //line busy. SDA again held low by another device. 2nd master? + else return I2C_OK; //all ok +} \ No newline at end of file diff --git a/Sming/SmingCore/twi.h b/Sming/SmingCore/twi.h new file mode 100644 index 0000000000..fb564278cd --- /dev/null +++ b/Sming/SmingCore/twi.h @@ -0,0 +1,48 @@ +/* + twi.h - Software I2C library for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef SI2C_h +#define SI2C_h +#include "../Wiring/WiringFrameworkDependencies.h" +#include "espinc/peri.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2C_OK 0 +#define I2C_SCL_HELD_LOW 1 +#define I2C_SCL_HELD_LOW_AFTER_READ 2 +#define I2C_SDA_HELD_LOW 3 +#define I2C_SDA_HELD_LOW_AFTER_INIT 4 + +void twi_init(unsigned char sda, unsigned char scl); +void twi_stop(void); +void twi_setClock(unsigned int freq); +void twi_setClockStretchLimit(uint32_t limit); +uint8_t twi_writeTo(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop); +uint8_t twi_readFrom(unsigned char address, unsigned char * buf, unsigned int len, unsigned char sendStop); +uint8_t twi_status(); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Sming/Wiring/I2cMaster.cpp b/Sming/Wiring/I2cMaster.cpp deleted file mode 100644 index 0afc65aaef..0000000000 --- a/Sming/Wiring/I2cMaster.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Arduino I2cMaster Library - * Copyright (C) 2010 by William Greiman - * - * This file is part of the Arduino I2cMaster Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino I2cMaster Library. If not, see - * . - */ - -#include "I2cMaster.h" - -#include "../SmingCore/Clock.h" -#include "../SmingCore/Digital.h" -#include "WiringFrameworkIncludes.h" - - -//============================================================================== -// WARNING don't change SoftI2cMaster unless you verify the change with a scope -//------------------------------------------------------------------------------ -/** - * Initialize SCL/SDA pins and set the bus high. - * - * \param[in] sdaPin The software SDA pin number. - * - * \param[in] sclPin The software SCL pin number. - */ -SoftI2cMaster::SoftI2cMaster(uint8_t sdaPin, uint8_t sclPin) { - sdaPin_ = sdaPin; - pinMode(sdaPin_, OUTPUT); - digitalWrite(sdaPin_, HIGH); - sclPin_ = sclPin; - pinMode(sclPin_, OUTPUT); - digitalWrite(sclPin_, HIGH); -} -//------------------------------------------------------------------------------ -/** Read a byte and send Ack if more reads follow else Nak to terminate read. - * - * \param[in] last Set true to terminate the read else false. - * - * \return The byte read from the I2C bus. - */ -uint8_t SoftI2cMaster::read(uint8_t last) { - uint8_t b = 0; - // make sure pull-up enabled - digitalWrite(sdaPin_, HIGH); - pinMode(sdaPin_, INPUT); - // read byte - for (uint8_t i = 0; i < 8; i++) { - // don't change this loop unless you verify the change with a scope - b <<= 1; - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sclPin_, HIGH); - if (digitalRead(sdaPin_)) b |= 1; - digitalWrite(sclPin_, LOW); - } - // send Ack or Nak - pinMode(sdaPin_, OUTPUT); - digitalWrite(sdaPin_, last); - digitalWrite(sclPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sclPin_, LOW); - digitalWrite(sdaPin_, LOW); - return b; -} -//------------------------------------------------------------------------------ -/** Issue a restart condition. - * - * \param[in] addressRW I2C address with read/write bit. - * - * \return The value true, 1, for success or false, 0, for failure. - */ -bool SoftI2cMaster::restart(uint8_t addressRW) { - digitalWrite(sdaPin_, HIGH); - digitalWrite(sclPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); - return start(addressRW); -} -//------------------------------------------------------------------------------ -/** Issue a start condition. - * - * \param[in] addressRW I2C address with read/write bit. - * - * \return The value true, 1, for success or false, 0, for failure. - */ -bool SoftI2cMaster::start(uint8_t addressRW) { - digitalWrite(sdaPin_, HIGH); - digitalWrite(sclPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sdaPin_, LOW); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sclPin_, LOW); - return write(addressRW); -} -//------------------------------------------------------------------------------ - /** Issue a stop condition. */ -void SoftI2cMaster::stop(void) { - digitalWrite(sdaPin_, LOW); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sclPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sdaPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); -} -//------------------------------------------------------------------------------ -/** - * Write a byte. - * - * \param[in] data The byte to send. - * - * \return The value true, 1, if the slave returned an Ack or false for Nak. - */ -bool SoftI2cMaster::write(uint8_t data) { - // write byte - for (uint8_t m = 0X80; m != 0; m >>= 1) { - // don't change this loop unless you verify the change with a scope - digitalWrite(sdaPin_, m & data); - digitalWrite(sclPin_, HIGH); - delayMicroseconds(I2C_DELAY_USEC); - digitalWrite(sclPin_, LOW); - } - // get Ack or Nak - pinMode(sdaPin_, INPUT); - // enable pullup - digitalWrite(sdaPin_, HIGH); - digitalWrite(sclPin_, HIGH); - uint8_t rtn = digitalRead(sdaPin_); - digitalWrite(sclPin_, LOW); - pinMode(sdaPin_, OUTPUT); - digitalWrite(sdaPin_, LOW); - return rtn == 0; -} diff --git a/Sming/Wiring/I2cMaster.h b/Sming/Wiring/I2cMaster.h deleted file mode 100644 index 705c602bc9..0000000000 --- a/Sming/Wiring/I2cMaster.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Arduino I2cMaster Library - * Copyright (C) 2010 by William Greiman - * - * This file is part of the Arduino I2cMaster Library - * - * This Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Arduino I2cMaster Library. If not, see - * . - */ -#ifndef I2C_MASTER_H -#define I2C_MASTER_H -/** - * \file - * \brief Software I2C and hardware TWI library - */ -#include "WiringFrameworkDependencies.h" - -/** Delay used for software I2C */ -uint8_t const I2C_DELAY_USEC = 2; - -/** Bit to or with address for read start and read restart */ -uint8_t const I2C_READ = 1; - -/** Bit to or with address for write start and write restart */ -uint8_t const I2C_WRITE = 0; - -/** - * \class I2cMasterBase - * \brief Base class for SoftI2cMaster and TwiMaster - */ -class I2cMasterBase -{ -public: - /** Read a byte - * \param[in] last send Ack if last is false else Nak to terminate read - * \return byte read from I2C bus - */ - virtual uint8_t read(uint8_t last) = 0; - /** Send new address and read/write bit without sending a stop. - * \param[in] addressRW i2c address with read/write bit - * \return true for success false for failure - */ - virtual bool restart(uint8_t addressRW) = 0; - /** Issue a start condition - * \param[in] addressRW i2c address with read/write bit - * \return true for success false for failure - */ - virtual bool start(uint8_t addressRW) = 0; - /** Issue a stop condition. */ - virtual void stop(void) = 0; - /** Write a byte - * \param[in] data byte to write - * \return true for Ack or false for Nak */ - virtual bool write(uint8_t data) = 0; -}; -//------------------------------------------------------------------------------ -/** - * \class SoftI2cMaster - * \brief Software I2C master class - */ -class SoftI2cMaster : public I2cMasterBase -{ -public: - SoftI2cMaster(uint8_t sdaPin, uint8_t sclPin); - uint8_t read(uint8_t last); - bool restart(uint8_t addressRW); - bool start(uint8_t addressRW); - void stop(void); - bool write(uint8_t b); -private: - // SoftI2cMaster() : sdaPin_(0), sclPin_(0) {} - uint8_t sdaPin_; - uint8_t sclPin_; -}; - -#endif // I2C_MASTER_H diff --git a/Sming/Wiring/WiringFrameworkIncludes.h b/Sming/Wiring/WiringFrameworkIncludes.h index ca5f90f936..61ae080956 100644 --- a/Sming/Wiring/WiringFrameworkIncludes.h +++ b/Sming/Wiring/WiringFrameworkIncludes.h @@ -25,7 +25,6 @@ #include "Stream.h" #include "Display.h" #include "WHashMap.h" -#include "I2cMaster.h" #include "IPAddress.h" #endif /* WIRING_WIRINGFRAMEWORKINCLUDES_H_ */