/ libraries / Wire / Wire.cpp
Wire.cpp
  1  /*
  2    TwoWire.cpp - TWI/I2C library for Wiring & Arduino
  3    Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
  4  
  5    This library is free software; you can redistribute it and/or
  6    modify it under the terms of the GNU Lesser General Public
  7    License as published by the Free Software Foundation; either
  8    version 2.1 of the License, or (at your option) any later version.
  9  
 10    This library is distributed in the hope that it will be useful,
 11    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13    Lesser General Public License for more details.
 14  
 15    You should have received a copy of the GNU Lesser General Public
 16    License along with this library; if not, write to the Free Software
 17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18   
 19    Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
 20  */
 21  
 22  #ifndef __AVR_ATtiny85__
 23  
 24  extern "C" {
 25    #include <stdlib.h>
 26    #include <string.h>
 27    #include <inttypes.h>
 28    #include "twi.h"
 29  }
 30  
 31  #include "Wire.h"
 32  
 33  // Initialize Class Variables //////////////////////////////////////////////////
 34  
 35  uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
 36  uint8_t TwoWire::rxBufferIndex = 0;
 37  uint8_t TwoWire::rxBufferLength = 0;
 38  
 39  uint8_t TwoWire::txAddress = 0;
 40  uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
 41  uint8_t TwoWire::txBufferIndex = 0;
 42  uint8_t TwoWire::txBufferLength = 0;
 43  
 44  uint8_t TwoWire::transmitting = 0;
 45  void (*TwoWire::user_onRequest)(void);
 46  void (*TwoWire::user_onReceive)(int);
 47  
 48  // Constructors ////////////////////////////////////////////////////////////////
 49  
 50  TwoWire::TwoWire()
 51  {
 52  }
 53  
 54  // Public Methods //////////////////////////////////////////////////////////////
 55  
 56  void TwoWire::begin(void)
 57  {
 58    rxBufferIndex = 0;
 59    rxBufferLength = 0;
 60  
 61    txBufferIndex = 0;
 62    txBufferLength = 0;
 63  
 64    twi_init();
 65  }
 66  
 67  void TwoWire::begin(uint8_t address)
 68  {
 69    twi_setAddress(address);
 70    twi_attachSlaveTxEvent(onRequestService);
 71    twi_attachSlaveRxEvent(onReceiveService);
 72    begin();
 73  }
 74  
 75  void TwoWire::begin(int address)
 76  {
 77    begin((uint8_t)address);
 78  }
 79  
 80  void TwoWire::end(void)
 81  {
 82    twi_disable();
 83  }
 84  
 85  void TwoWire::setClock(uint32_t clock)
 86  {
 87    twi_setFrequency(clock);
 88  }
 89  
 90  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
 91  {
 92    // clamp to buffer length
 93    if(quantity > BUFFER_LENGTH){
 94      quantity = BUFFER_LENGTH;
 95    }
 96    // perform blocking read into buffer
 97    uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
 98    // set rx buffer iterator vars
 99    rxBufferIndex = 0;
100    rxBufferLength = read;
101  
102    return read;
103  }
104  
105  uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
106  {
107    return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
108  }
109  
110  uint8_t TwoWire::requestFrom(int address, int quantity)
111  {
112    return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
113  }
114  
115  uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
116  {
117    return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
118  }
119  
120  void TwoWire::beginTransmission(uint8_t address)
121  {
122    // indicate that we are transmitting
123    transmitting = 1;
124    // set address of targeted slave
125    txAddress = address;
126    // reset tx buffer iterator vars
127    txBufferIndex = 0;
128    txBufferLength = 0;
129  }
130  
131  void TwoWire::beginTransmission(int address)
132  {
133    beginTransmission((uint8_t)address);
134  }
135  
136  //
137  //	Originally, 'endTransmission' was an f(void) function.
138  //	It has been modified to take one parameter indicating
139  //	whether or not a STOP should be performed on the bus.
140  //	Calling endTransmission(false) allows a sketch to 
141  //	perform a repeated start. 
142  //
143  //	WARNING: Nothing in the library keeps track of whether
144  //	the bus tenure has been properly ended with a STOP. It
145  //	is very possible to leave the bus in a hung state if
146  //	no call to endTransmission(true) is made. Some I2C
147  //	devices will behave oddly if they do not see a STOP.
148  //
149  uint8_t TwoWire::endTransmission(uint8_t sendStop)
150  {
151    // transmit buffer (blocking)
152    int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
153    // reset tx buffer iterator vars
154    txBufferIndex = 0;
155    txBufferLength = 0;
156    // indicate that we are done transmitting
157    transmitting = 0;
158    return ret;
159  }
160  
161  //	This provides backwards compatibility with the original
162  //	definition, and expected behaviour, of endTransmission
163  //
164  uint8_t TwoWire::endTransmission(void)
165  {
166    return endTransmission(true);
167  }
168  
169  // must be called in:
170  // slave tx event callback
171  // or after beginTransmission(address)
172  size_t TwoWire::write(uint8_t data)
173  {
174    if(transmitting){
175    // in master transmitter mode
176      // don't bother if buffer is full
177      if(txBufferLength >= BUFFER_LENGTH){
178        setWriteError();
179        return 0;
180      }
181      // put byte in tx buffer
182      txBuffer[txBufferIndex] = data;
183      ++txBufferIndex;
184      // update amount in buffer   
185      txBufferLength = txBufferIndex;
186    }else{
187    // in slave send mode
188      // reply to master
189      twi_transmit(&data, 1);
190    }
191    return 1;
192  }
193  
194  // must be called in:
195  // slave tx event callback
196  // or after beginTransmission(address)
197  size_t TwoWire::write(const uint8_t *data, size_t quantity)
198  {
199    if(transmitting){
200    // in master transmitter mode
201      for(size_t i = 0; i < quantity; ++i){
202        write(data[i]);
203      }
204    }else{
205    // in slave send mode
206      // reply to master
207      twi_transmit(data, quantity);
208    }
209    return quantity;
210  }
211  
212  // must be called in:
213  // slave rx event callback
214  // or after requestFrom(address, numBytes)
215  int TwoWire::available(void)
216  {
217    return rxBufferLength - rxBufferIndex;
218  }
219  
220  // must be called in:
221  // slave rx event callback
222  // or after requestFrom(address, numBytes)
223  int TwoWire::read(void)
224  {
225    int value = -1;
226    
227    // get each successive byte on each call
228    if(rxBufferIndex < rxBufferLength){
229      value = rxBuffer[rxBufferIndex];
230      ++rxBufferIndex;
231    }
232  
233    return value;
234  }
235  
236  // must be called in:
237  // slave rx event callback
238  // or after requestFrom(address, numBytes)
239  int TwoWire::peek(void)
240  {
241    int value = -1;
242    
243    if(rxBufferIndex < rxBufferLength){
244      value = rxBuffer[rxBufferIndex];
245    }
246  
247    return value;
248  }
249  
250  void TwoWire::flush(void)
251  {
252    // XXX: to be implemented.
253  }
254  
255  // behind the scenes function that is called when data is received
256  void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
257  {
258    // don't bother if user hasn't registered a callback
259    if(!user_onReceive){
260      return;
261    }
262    // don't bother if rx buffer is in use by a master requestFrom() op
263    // i know this drops data, but it allows for slight stupidity
264    // meaning, they may not have read all the master requestFrom() data yet
265    if(rxBufferIndex < rxBufferLength){
266      return;
267    }
268    // copy twi rx buffer into local read buffer
269    // this enables new reads to happen in parallel
270    for(uint8_t i = 0; i < numBytes; ++i){
271      rxBuffer[i] = inBytes[i];    
272    }
273    // set rx iterator vars
274    rxBufferIndex = 0;
275    rxBufferLength = numBytes;
276    // alert user program
277    user_onReceive(numBytes);
278  }
279  
280  // behind the scenes function that is called when data is requested
281  void TwoWire::onRequestService(void)
282  {
283    // don't bother if user hasn't registered a callback
284    if(!user_onRequest){
285      return;
286    }
287    // reset tx buffer iterator vars
288    // !!! this will kill any pending pre-master sendTo() activity
289    txBufferIndex = 0;
290    txBufferLength = 0;
291    // alert user program
292    user_onRequest();
293  }
294  
295  // sets function called on slave write
296  void TwoWire::onReceive( void (*function)(int) )
297  {
298    user_onReceive = function;
299  }
300  
301  // sets function called on slave read
302  void TwoWire::onRequest( void (*function)(void) )
303  {
304    user_onRequest = function;
305  }
306  
307  // Preinstantiate Objects //////////////////////////////////////////////////////
308  
309  TwoWire Wire = TwoWire();
310  
311  #endif //attiny85