Mbed for ESIMEos / Mbed 2 deprecated FRDM-KL46Z_LCD_I2C_demo

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Wire.cpp Source File

Wire.cpp

00001 /*
00002   TwoWire.cpp - TWI/I2C library for Wiring & Arduino
00003   Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
00004   This library is free software; you can redistribute it and/or
00005   modify it under the terms of the GNU Lesser General Public
00006   License as published by the Free Software Foundation; either
00007   version 2.1 of the License, or (at your option) any later version.
00008   This library is distributed in the hope that it will be useful,
00009   but WITHOUT ANY WARRANTY; without even the implied warranty of
00010   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011   Lesser General Public License for more details.
00012   You should have received a copy of the GNU Lesser General Public
00013   License along with this library; if not, write to the Free Software
00014   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00015  
00016   Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
00017 */
00018 
00019 #if defined(__AVR__)
00020 
00021 #include "Wire.h"
00022 
00023 extern "C" {
00024   #include <stdlib.h>
00025   #include <string.h>
00026   #include <inttypes.h>
00027   #include "twi.h"
00028 }
00029 
00030 
00031 // Initialize Class Variables //////////////////////////////////////////////////
00032 
00033 uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
00034 uint8_t TwoWire::rxBufferIndex = 0;
00035 uint8_t TwoWire::rxBufferLength = 0;
00036 
00037 uint8_t TwoWire::txAddress = 0;
00038 uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
00039 uint8_t TwoWire::txBufferIndex = 0;
00040 uint8_t TwoWire::txBufferLength = 0;
00041 
00042 uint8_t TwoWire::transmitting = 0;
00043 void (*TwoWire::user_onRequest)(void);
00044 void (*TwoWire::user_onReceive)(int);
00045 
00046 // Constructors ////////////////////////////////////////////////////////////////
00047 
00048 TwoWire::TwoWire()
00049 {
00050 }
00051 
00052 // Public Methods //////////////////////////////////////////////////////////////
00053 
00054 void TwoWire::begin(void)
00055 {
00056   rxBufferIndex = 0;
00057   rxBufferLength = 0;
00058 
00059   txBufferIndex = 0;
00060   txBufferLength = 0;
00061 
00062   twi_init();
00063 }
00064 
00065 void TwoWire::begin(uint8_t address)
00066 {
00067   twi_setAddress(address);
00068   twi_attachSlaveTxEvent(onRequestService);
00069   twi_attachSlaveRxEvent(onReceiveService);
00070   begin();
00071 }
00072 
00073 void TwoWire::begin(int address)
00074 {
00075   begin((uint8_t)address);
00076 }
00077 
00078 void TwoWire::end()
00079 {
00080   TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));
00081   digitalWrite(SDA, 0);
00082   digitalWrite(SCL, 0);
00083 }
00084 
00085 void TwoWire::setClock(uint32_t frequency)
00086 {
00087   TWBR = ((F_CPU / frequency) - 16) / 2;
00088 }
00089 
00090 void TwoWire::setSDA(uint8_t pin)
00091 {
00092 }
00093 
00094 void TwoWire::setSCL(uint8_t pin)
00095 {
00096 }
00097 
00098 uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
00099 {
00100   // clamp to buffer length
00101   if(quantity > BUFFER_LENGTH){
00102     quantity = BUFFER_LENGTH;
00103   }
00104   // perform blocking read into buffer
00105   uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
00106   // set rx buffer iterator vars
00107   rxBufferIndex = 0;
00108   rxBufferLength = read;
00109 
00110   return read;
00111 }
00112 
00113 uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
00114 {
00115   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
00116 }
00117 
00118 uint8_t TwoWire::requestFrom(int address, int quantity)
00119 {
00120   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
00121 }
00122 
00123 uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
00124 {
00125   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
00126 }
00127 
00128 void TwoWire::beginTransmission(uint8_t address)
00129 {
00130   // indicate that we are transmitting
00131   transmitting = 1;
00132   // set address of targeted slave
00133   txAddress = address;
00134   // reset tx buffer iterator vars
00135   txBufferIndex = 0;
00136   txBufferLength = 0;
00137 }
00138 
00139 void TwoWire::beginTransmission(int address)
00140 {
00141   beginTransmission((uint8_t)address);
00142 }
00143 
00144 //
00145 //  Originally, 'endTransmission' was an f(void) function.
00146 //  It has been modified to take one parameter indicating
00147 //  whether or not a STOP should be performed on the bus.
00148 //  Calling endTransmission(false) allows a sketch to 
00149 //  perform a repeated start. 
00150 //
00151 //  WARNING: Nothing in the library keeps track of whether
00152 //  the bus tenure has been properly ended with a STOP. It
00153 //  is very possible to leave the bus in a hung state if
00154 //  no call to endTransmission(true) is made. Some I2C
00155 //  devices will behave oddly if they do not see a STOP.
00156 //
00157 uint8_t TwoWire::endTransmission(uint8_t sendStop)
00158 {
00159   // transmit buffer (blocking)
00160   int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
00161   // reset tx buffer iterator vars
00162   txBufferIndex = 0;
00163   txBufferLength = 0;
00164   // indicate that we are done transmitting
00165   transmitting = 0;
00166   return ret;
00167 }
00168 
00169 //  This provides backwards compatibility with the original
00170 //  definition, and expected behaviour, of endTransmission
00171 //
00172 uint8_t TwoWire::endTransmission(void)
00173 {
00174   return endTransmission(true);
00175 }
00176 
00177 // must be called in:
00178 // slave tx event callback
00179 // or after beginTransmission(address)
00180 size_t TwoWire::write(uint8_t data)
00181 {
00182   if(transmitting){
00183   // in master transmitter mode
00184     // don't bother if buffer is full
00185     if(txBufferLength >= BUFFER_LENGTH){
00186       setWriteError();
00187       return 0;
00188     }
00189     // put byte in tx buffer
00190     txBuffer[txBufferIndex] = data;
00191     ++txBufferIndex;
00192     // update amount in buffer   
00193     txBufferLength = txBufferIndex;
00194   }else{
00195   // in slave send mode
00196     // reply to master
00197     twi_transmit(&data, 1);
00198   }
00199   return 1;
00200 }
00201 
00202 // must be called in:
00203 // slave tx event callback
00204 // or after beginTransmission(address)
00205 size_t TwoWire::write(const uint8_t *data, size_t quantity)
00206 {
00207   if(transmitting){
00208   // in master transmitter mode
00209     for(size_t i = 0; i < quantity; ++i){
00210       write(data[i]);
00211     }
00212   }else{
00213   // in slave send mode
00214     // reply to master
00215     twi_transmit(data, quantity);
00216   }
00217   return quantity;
00218 }
00219 
00220 // must be called in:
00221 // slave rx event callback
00222 // or after requestFrom(address, numBytes)
00223 int TwoWire::available(void)
00224 {
00225   return rxBufferLength - rxBufferIndex;
00226 }
00227 
00228 // must be called in:
00229 // slave rx event callback
00230 // or after requestFrom(address, numBytes)
00231 int TwoWire::read(void)
00232 {
00233   int value = -1;
00234   
00235   // get each successive byte on each call
00236   if(rxBufferIndex < rxBufferLength){
00237     value = rxBuffer[rxBufferIndex];
00238     ++rxBufferIndex;
00239   }
00240 
00241   return value;
00242 }
00243 
00244 // must be called in:
00245 // slave rx event callback
00246 // or after requestFrom(address, numBytes)
00247 int TwoWire::peek(void)
00248 {
00249   int value = -1;
00250   
00251   if(rxBufferIndex < rxBufferLength){
00252     value = rxBuffer[rxBufferIndex];
00253   }
00254 
00255   return value;
00256 }
00257 
00258 void TwoWire::flush(void)
00259 {
00260   // XXX: to be implemented.
00261 }
00262 
00263 // behind the scenes function that is called when data is received
00264 void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
00265 {
00266   // don't bother if user hasn't registered a callback
00267   if(!user_onReceive){
00268     return;
00269   }
00270   // don't bother if rx buffer is in use by a master requestFrom() op
00271   // i know this drops data, but it allows for slight stupidity
00272   // meaning, they may not have read all the master requestFrom() data yet
00273   if(rxBufferIndex < rxBufferLength){
00274     return;
00275   }
00276   // copy twi rx buffer into local read buffer
00277   // this enables new reads to happen in parallel
00278   for(uint8_t i = 0; i < numBytes; ++i){
00279     rxBuffer[i] = inBytes[i];    
00280   }
00281   // set rx iterator vars
00282   rxBufferIndex = 0;
00283   rxBufferLength = numBytes;
00284   // alert user program
00285   user_onReceive(numBytes);
00286 }
00287 
00288 // behind the scenes function that is called when data is requested
00289 void TwoWire::onRequestService(void)
00290 {
00291   // don't bother if user hasn't registered a callback
00292   if(!user_onRequest){
00293     return;
00294   }
00295   // reset tx buffer iterator vars
00296   // !!! this will kill any pending pre-master sendTo() activity
00297   txBufferIndex = 0;
00298   txBufferLength = 0;
00299   // alert user program
00300   user_onRequest();
00301 }
00302 
00303 // sets function called on slave write
00304 void TwoWire::onReceive( void (*function)(int) )
00305 {
00306   user_onReceive = function;
00307 }
00308 
00309 // sets function called on slave read
00310 void TwoWire::onRequest( void (*function)(void) )
00311 {
00312   user_onRequest = function;
00313 }
00314 
00315 // Preinstantiate Objects //////////////////////////////////////////////////////
00316 
00317 TwoWire Wire = TwoWire();
00318 
00319 #endif // __AVR__