From 6599a7273232c696c9001a582cf087afb5aa668f Mon Sep 17 00:00:00 2001 From: Jean-Marc Paratte Date: Wed, 3 May 2017 10:06:48 +0100 Subject: [PATCH] 1.0.1 1.0.1: jm_Write.h and jm_Wire.cpp files are now exactly the same as the original Wire.h and Wire.cpp as found in Arduino 1.8.2 with a little update of declaratives in jm_Wire.cpp. All true updates are in files jm_twi.h and jm_twi.c. --- README.md | 16 +- .../LiquidCrystal_I2C.cpp | 9 - .../jm_LiquidCrystal_I2C_demo.ino | 8 +- jm_Wire.cpp | 303 ---------------- keywords.txt | 10 +- library.properties | 4 +- src/jm_Wire.cpp | 332 ++++++++++++++++++ jm_Wire.h => src/jm_Wire.h | 10 +- {utility => src/utility}/jm_twi.c | 54 ++- src/utility/jm_twi.h | 69 ++++ utility/jm_twi.h | 57 --- 11 files changed, 493 insertions(+), 379 deletions(-) delete mode 100644 jm_Wire.cpp create mode 100644 src/jm_Wire.cpp rename jm_Wire.h => src/jm_Wire.h (92%) rename {utility => src/utility}/jm_twi.c (94%) create mode 100644 src/utility/jm_twi.h delete mode 100644 utility/jm_twi.h diff --git a/README.md b/README.md index b057a9b..6be0b41 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# jm_Wire - A revisited Wire Library for Arduino +# jm_Wire - Revisited Wire Library for Arduino + +2017-05-03: 1.0.1 2017-05-01: Initial commit. -This library eliminate all freezing cases and waiting loop. +This library eliminate all freezing cases and waiting loops. The provided _jm_LiquidCrystal_I2C_demo_ example demonstrates how it is possible to send data to a Hitachi HD44780 or compatible chipsets via I2C without abandon multitasking request. @@ -20,16 +23,25 @@ To illustrate the last sentence, think that the Hitachi HD44780 need about 4.5ms The example shows also how to write I2C packets with various delays, by using a fifo buffer. The multitasking is provided by the jm_Scheduler library. +1.0.1: jm_Write.h and jm_Wire.cpp files are now exactly the same as the original Wire.h and Wire.cpp as found in Arduino 1.8.2 with a little update of declaratives in jm_Wire.cpp. +All true updates are in files jm_twi.h and jm_twi.c. + ## Example #include #include + extern uint16_t twi_readFrom_timeout; + extern uint16_t twi_writeTo_timeout; + extern bool twi_readFrom_wait; + extern bool twi_writeTo_wait; // your code... void setup(void) { Wire.begin(); + twi_readFrom_wait = false; // Suppress twi_readFrom() waiting loop + twi_writeTo_wait = false; // Suppress twi_writeTo() waiting loop } void loop(void) diff --git a/examples/jm_LiquidCrystal_I2C_demo/LiquidCrystal_I2C.cpp b/examples/jm_LiquidCrystal_I2C_demo/LiquidCrystal_I2C.cpp index d210357..b159cf6 100644 --- a/examples/jm_LiquidCrystal_I2C_demo/LiquidCrystal_I2C.cpp +++ b/examples/jm_LiquidCrystal_I2C_demo/LiquidCrystal_I2C.cpp @@ -296,14 +296,10 @@ void LiquidCrystal_I2C::pulseEnable (uint8_t data) wait(200); _i2cio.write (data & ~_En); // En LOW wait(200); -#else -#if 0 - lcd_i2c_write(data); #else _i2cio.write (data | _En); // En HIGH _i2cio.write (data & ~_En); // En LOW #endif -#endif } void LiquidCrystal_I2C::wait(uint16_t us) @@ -314,12 +310,7 @@ void LiquidCrystal_I2C::wait(uint16_t us) #if 0 delayMicroseconds( us ); -#else -#if 0 - lcd_i2c_write(0xFF); - lcd_i2c_write((us + (20 - 1))/20); #else _i2cio.wait(us); #endif -#endif } diff --git a/examples/jm_LiquidCrystal_I2C_demo/jm_LiquidCrystal_I2C_demo.ino b/examples/jm_LiquidCrystal_I2C_demo/jm_LiquidCrystal_I2C_demo.ino index ab434c8..3201296 100644 --- a/examples/jm_LiquidCrystal_I2C_demo/jm_LiquidCrystal_I2C_demo.ino +++ b/examples/jm_LiquidCrystal_I2C_demo/jm_LiquidCrystal_I2C_demo.ino @@ -9,6 +9,10 @@ //#include #include +extern uint16_t twi_readFrom_timeout; +extern uint16_t twi_writeTo_timeout; +extern bool twi_readFrom_wait; +extern bool twi_writeTo_wait; //////////////////////////////////////////////////////////////////////////////// @@ -26,7 +30,6 @@ const uint8_t charBitmap[8][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F } - }; //////////////////////////////////////////////////////////////////////////////// @@ -99,6 +102,9 @@ void setup() Serial.println(); Wire.begin(); + twi_readFrom_wait = false; // Suppress twi_readFrom() waiting loop + twi_writeTo_wait = false; // Suppress twi_writeTo() waiting loop + lcd.begin(); while (lcd._i2cio.yield_request()) jm_Scheduler::yield(); diff --git a/jm_Wire.cpp b/jm_Wire.cpp deleted file mode 100644 index e287c6c..0000000 --- a/jm_Wire.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - TwoWire.cpp - TWI/I2C library for Wiring & Arduino - 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 -*/ - -extern "C" { - #include - #include - #include -// #include "twi.h" - #include "jm_twi.h" -} - -//#include "Wire.h" -#include "jm_Wire.h" - -// Initialize Class Variables ////////////////////////////////////////////////// - -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -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); - -// Constructors //////////////////////////////////////////////////////////////// - -TwoWire::TwoWire() -{ -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void TwoWire::begin(void) -{ - rxBufferIndex = 0; - rxBufferLength = 0; - - txBufferIndex = 0; - txBufferLength = 0; - - twi_init(); -} - -void TwoWire::begin(uint8_t address) -{ - twi_setAddress(address); - twi_attachSlaveTxEvent(onRequestService); - twi_attachSlaveRxEvent(onReceiveService); - begin(); -} - -void TwoWire::begin(int address) -{ - begin((uint8_t)address); -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) -{ - // clamp to buffer length - if(quantity > BUFFER_LENGTH){ - quantity = BUFFER_LENGTH; - } - // perform blocking read into buffer - uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); - // set rx buffer iterator vars - rxBufferIndex = 0; - rxBufferLength = read; - - return read; -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); -} - -void TwoWire::beginTransmission(uint8_t address) -{ - // indicate that we are transmitting - transmitting = 1; - // set address of targeted slave - txAddress = address; - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; -} - -void TwoWire::beginTransmission(int address) -{ - beginTransmission((uint8_t)address); -} - -// -// Originally, 'endTransmission' was an f(void) function. -// It has been modified to take one parameter indicating -// whether or not a STOP should be performed on the bus. -// Calling endTransmission(false) allows a sketch to -// perform a repeated start. -// -// WARNING: Nothing in the library keeps track of whether -// the bus tenure has been properly ended with a STOP. It -// is very possible to leave the bus in a hung state if -// no call to endTransmission(true) is made. Some I2C -// devices will behave oddly if they do not see a STOP. -// -uint8_t TwoWire::endTransmission(uint8_t sendStop) -{ - // transmit buffer (blocking) - -// int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); - int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 0, sendStop); - - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - // indicate that we are done transmitting - transmitting = 0; - return ret; -} - -// This provides backwards compatibility with the original -// definition, and expected behaviour, of endTransmission -// -uint8_t TwoWire::endTransmission(void) -{ - return endTransmission(true); -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(uint8_t data) -{ - if(transmitting){ - // in master transmitter mode - // don't bother if buffer is full - if(txBufferLength >= BUFFER_LENGTH){ - setWriteError(); - return 0; - } - // put byte in tx buffer - txBuffer[txBufferIndex] = data; - ++txBufferIndex; - // update amount in buffer - txBufferLength = txBufferIndex; - }else{ - // in slave send mode - // reply to master - twi_transmit(&data, 1); - } - return 1; -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(const uint8_t *data, size_t quantity) -{ - if(transmitting){ - // in master transmitter mode - for(size_t i = 0; i < quantity; ++i){ - write(data[i]); - } - }else{ - // in slave send mode - // reply to master - twi_transmit(data, quantity); - } - return quantity; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::available(void) -{ - return rxBufferLength - rxBufferIndex; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::read(void) -{ - int value = -1; - - // get each successive byte on each call - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - ++rxBufferIndex; - } - - return value; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::peek(void) -{ - int value = -1; - - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - } - - return value; -} - -void TwoWire::flush(void) -{ - // XXX: to be implemented. -} - -// behind the scenes function that is called when data is received -void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) -{ - // 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); -} - -// behind the scenes function that is called when data is requested -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(); -} - -// sets function called on slave write -void TwoWire::onReceive( void (*function)(int) ) -{ - user_onReceive = function; -} - -// sets function called on slave read -void TwoWire::onRequest( void (*function)(void) ) -{ - user_onRequest = function; -} - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -TwoWire Wire = TwoWire(); - diff --git a/keywords.txt b/keywords.txt index 96a1b30..715660d 100644 --- a/keywords.txt +++ b/keywords.txt @@ -7,7 +7,6 @@ ####################################### TwoWire KEYWORD1 -Wire KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -25,6 +24,15 @@ peek KEYWORD2 flush KEYWORD2 twi_readFrom_timeout KEYWORD2 +twi_writeTo_timeout KEYWORD2 +twi_readFrom_wait KEYWORD2 +twi_writeTo_wait KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/library.properties b/library.properties index e38cc1a..142a7cd 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=jm_Wire -version=1.0.0 +version=1.0.1 author=Jean-Marc Paratte maintainer=Jean-Marc Paratte sentence=Revisited Arduino Wire Library. -paragraph=Eliminates all freezing cases and waiting loop. +paragraph=Eliminates all freezing cases and waiting loops. category=Communication url=https://github.com/jmparatte/jm_Wire architectures=avr diff --git a/src/jm_Wire.cpp b/src/jm_Wire.cpp new file mode 100644 index 0000000..af393dc --- /dev/null +++ b/src/jm_Wire.cpp @@ -0,0 +1,332 @@ +/* + TwoWire.cpp - TWI/I2C library for Wiring & Arduino + 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 +*/ + +extern "C" { + #include + #include + #include +// #include "utility/twi.h" + #include "utility/jm_twi.h" +} + +//#include "Wire.h" +#include "jm_Wire.h" + +// Initialize Class Variables ////////////////////////////////////////////////// + +uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::rxBufferIndex = 0; +uint8_t TwoWire::rxBufferLength = 0; + +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); + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire() +{ +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) +{ + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + twi_init(); +} + +void TwoWire::begin(uint8_t address) +{ + twi_setAddress(address); + twi_attachSlaveTxEvent(onRequestService); + twi_attachSlaveRxEvent(onReceiveService); + begin(); +} + +void TwoWire::begin(int address) +{ + begin((uint8_t)address); +} + +void TwoWire::end(void) +{ + twi_disable(); +} + +void TwoWire::setClock(uint32_t clock) +{ + twi_setFrequency(clock); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop) +{ + if (isize > 0) { + // send internal address; this mode allows sending a repeated start to access + // some devices' internal registers. This function is executed by the hardware + // TWI module on other processors (for example Due's TWI_IADR and TWI_MMR registers) + + beginTransmission(address); + + // the maximum size of internal address is 3 bytes + if (isize > 3){ + isize = 3; + } + + // write internal register address - most significant byte first + while (isize-- > 0) + write((uint8_t)(iaddress >> (isize*8))); + endTransmission(false); + } + + // clamp to buffer length + if(quantity > BUFFER_LENGTH){ + quantity = BUFFER_LENGTH; + } + // perform blocking read into buffer + uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = read; + + return read; +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) { + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)sendStop); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +{ + return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); +} + +void TwoWire::beginTransmission(uint8_t address) +{ + // indicate that we are transmitting + transmitting = 1; + // set address of targeted slave + txAddress = address; + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) +{ + beginTransmission((uint8_t)address); +} + +// +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. +// +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// no call to endTransmission(true) is made. Some I2C +// devices will behave oddly if they do not see a STOP. +// +uint8_t TwoWire::endTransmission(uint8_t sendStop) +{ + // transmit buffer (blocking) + uint8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + // indicate that we are done transmitting + transmitting = 0; + return ret; +} + +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission +// +uint8_t TwoWire::endTransmission(void) +{ + return endTransmission(true); +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(uint8_t data) +{ + if(transmitting){ + // in master transmitter mode + // don't bother if buffer is full + if(txBufferLength >= BUFFER_LENGTH){ + setWriteError(); + return 0; + } + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + // update amount in buffer + txBufferLength = txBufferIndex; + }else{ + // in slave send mode + // reply to master + twi_transmit(&data, 1); + } + return 1; +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +size_t TwoWire::write(const uint8_t *data, size_t quantity) +{ + if(transmitting){ + // in master transmitter mode + for(size_t i = 0; i < quantity; ++i){ + write(data[i]); + } + }else{ + // in slave send mode + // reply to master + twi_transmit(data, quantity); + } + return quantity; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::available(void) +{ + return rxBufferLength - rxBufferIndex; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::read(void) +{ + int value = -1; + + // get each successive byte on each call + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +int TwoWire::peek(void) +{ + int value = -1; + + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + } + + return value; +} + +void TwoWire::flush(void) +{ + // XXX: to be implemented. +} + +// behind the scenes function that is called when data is received +void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) +{ + // 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); +} + +// behind the scenes function that is called when data is requested +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(); +} + +// sets function called on slave write +void TwoWire::onReceive( void (*function)(int) ) +{ + user_onReceive = function; +} + +// sets function called on slave read +void TwoWire::onRequest( void (*function)(void) ) +{ + user_onRequest = function; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +TwoWire Wire = TwoWire(); + diff --git a/jm_Wire.h b/src/jm_Wire.h similarity index 92% rename from jm_Wire.h rename to src/jm_Wire.h index a93d0f5..702f37d 100644 --- a/jm_Wire.h +++ b/src/jm_Wire.h @@ -27,6 +27,9 @@ #define BUFFER_LENGTH 32 +// WIRE_HAS_END means Wire has end() +#define WIRE_HAS_END 1 + class TwoWire : public Stream { private: @@ -49,12 +52,15 @@ class TwoWire : public Stream void begin(); void begin(uint8_t); void begin(int); + void end(); + void setClock(uint32_t); void beginTransmission(uint8_t); void beginTransmission(int); uint8_t endTransmission(void); uint8_t endTransmission(uint8_t); uint8_t requestFrom(uint8_t, uint8_t); uint8_t requestFrom(uint8_t, uint8_t, uint8_t); + uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t); uint8_t requestFrom(int, int); uint8_t requestFrom(int, int, int); virtual size_t write(uint8_t); @@ -62,10 +68,10 @@ class TwoWire : public Stream virtual int available(void); virtual int read(void); virtual int peek(void); - virtual void flush(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); } diff --git a/utility/jm_twi.c b/src/utility/jm_twi.c similarity index 94% rename from utility/jm_twi.c rename to src/utility/jm_twi.c index ac510d2..57eeab2 100644 --- a/utility/jm_twi.c +++ b/src/utility/jm_twi.c @@ -96,8 +96,33 @@ pinMode(SCL, INPUT_PULLUP); // // enable twi module, acks, and twi interrupt TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); - twi_readFrom_timeout = 0; +twi_readFrom_timeout = 0; +twi_writeTo_timeout = 0; + +twi_readFrom_wait = true; +twi_writeTo_wait = true; +} + +/* + * Function twi_disable + * Desc disables twi pins + * Input none + * Output none + */ +void twi_disable(void) +#if 0 +{ + // disable twi module, acks, and twi interrupt + TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA)); + + // deactivate internal pullups for twi. + digitalWrite(SDA, 0); + digitalWrite(SCL, 0); } +#else +{ +} +#endif /* * Function twi_slaveInit @@ -111,6 +136,27 @@ void twi_setAddress(uint8_t address) TWAR = address << 1; } +/* + * Function twi_setClock + * Desc sets twi bit rate + * Input Clock Frequency + * Output none + */ +void twi_setFrequency(uint32_t frequency) +#if 0 +{ + TWBR = ((F_CPU / frequency) - 16) / 2; + + /* twi bit rate formula from atmega128 manual pg 204 + SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) + note: TWBR should be 10 or higher for master mode + It is 72 for a 16mhz Wiring board with 100kHz TWI */ +} +#else +{ +} +#endif + /* * Function twi_readFrom * Desc attempts to become twi bus master and read a @@ -171,6 +217,9 @@ if (twi_state != TWI_READY) return 0; // + 2015-08-14 // send start condition TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); +//if (!wait) return 0; +if (!twi_readFrom_wait) return 0; + // wait for read operation to complete // while(TWI_MRX == twi_state){ // continue; @@ -270,7 +319,8 @@ if (twi_state != TWI_READY) return 5; // + 2015-08-12 // send start condition TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs -if (!wait) return 0; +//if (!wait) return 0; +if (!twi_writeTo_wait) return 0; // wait for write operation to complete // while(wait && (TWI_MTX == twi_state)){ // - 2015-08-12 diff --git a/src/utility/jm_twi.h b/src/utility/jm_twi.h new file mode 100644 index 0000000..b1917cf --- /dev/null +++ b/src/utility/jm_twi.h @@ -0,0 +1,69 @@ +/* + twi.h - TWI/I2C library for Wiring & Arduino + 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 +*/ + +#ifndef twi_h +#define twi_h + + #include + + //#define ATMEGA8 + + #ifndef TWI_FREQ + #define TWI_FREQ 100000L +//#define TWI_FREQ 400000L +//#define TWI_FREQ 800000L + #endif + + #ifndef TWI_BUFFER_LENGTH + #define TWI_BUFFER_LENGTH 32 + #endif + + #define TWI_READY 0 + #define TWI_MRX 1 + #define TWI_MTX 2 + #define TWI_SRX 3 + #define TWI_STX 4 + +uint16_t twi_readFrom_timeout; +uint16_t twi_writeTo_timeout; +bool twi_readFrom_wait; +bool twi_writeTo_wait; + + void twi_init(void); +// void twi_setAddress(uint8_t); +void twi_disable(void); + void twi_setAddress(uint8_t address); +void twi_setFrequency(uint32_t); +// uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); + uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop); +// uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); + uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop); +// uint8_t twi_transmit(const uint8_t*, uint8_t); + uint8_t twi_transmit(const uint8_t* data, uint8_t length); +// void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); + void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ); +// void twi_attachSlaveTxEvent( void (*)(void) ); + void twi_attachSlaveTxEvent( void (*function)(void) ); +// void twi_reply(uint8_t); + void twi_reply(uint8_t ack); + void twi_stop(void); + void twi_releaseBus(void); + +#endif + diff --git a/utility/jm_twi.h b/utility/jm_twi.h deleted file mode 100644 index 1de8908..0000000 --- a/utility/jm_twi.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - twi.h - TWI/I2C library for Wiring & Arduino - 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 -*/ - -#ifndef twi_h -#define twi_h - - #include - - //#define ATMEGA8 - - #ifndef TWI_FREQ - #define TWI_FREQ 100000L -//#define TWI_FREQ 400000L -//#define TWI_FREQ 800000L - #endif - - #ifndef TWI_BUFFER_LENGTH - #define TWI_BUFFER_LENGTH 32 - #endif - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - uint16_t twi_readFrom_timeout; - - void twi_init(void); - void twi_setAddress(uint8_t); - uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); - uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); - uint8_t twi_transmit(const uint8_t*, uint8_t); - void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); - void twi_attachSlaveTxEvent( void (*)(void) ); - void twi_reply(uint8_t); - void twi_stop(void); - void twi_releaseBus(void); - -#endif -