Home | History | Annotate | Download | only in Wire
      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 
     20 extern "C" {
     21   #include <stdlib.h>
     22   #include <string.h>
     23   #include <inttypes.h>
     24   #include "twi.h"
     25 }
     26 
     27 #include "Wire.h"
     28 
     29 // Initialize Class Variables //////////////////////////////////////////////////
     30 
     31 uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
     32 uint8_t TwoWire::rxBufferIndex = 0;
     33 uint8_t TwoWire::rxBufferLength = 0;
     34 
     35 uint8_t TwoWire::txAddress = 0;
     36 uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
     37 uint8_t TwoWire::txBufferIndex = 0;
     38 uint8_t TwoWire::txBufferLength = 0;
     39 
     40 uint8_t TwoWire::transmitting = 0;
     41 void (*TwoWire::user_onRequest)(void);
     42 void (*TwoWire::user_onReceive)(int);
     43 
     44 // Constructors ////////////////////////////////////////////////////////////////
     45 
     46 TwoWire::TwoWire()
     47 {
     48 }
     49 
     50 // Public Methods //////////////////////////////////////////////////////////////
     51 
     52 void TwoWire::begin(void)
     53 {
     54   rxBufferIndex = 0;
     55   rxBufferLength = 0;
     56 
     57   txBufferIndex = 0;
     58   txBufferLength = 0;
     59 
     60   twi_init();
     61 }
     62 
     63 void TwoWire::begin(uint8_t address)
     64 {
     65   twi_setAddress(address);
     66   twi_attachSlaveTxEvent(onRequestService);
     67   twi_attachSlaveRxEvent(onReceiveService);
     68   begin();
     69 }
     70 
     71 void TwoWire::begin(int address)
     72 {
     73   begin((uint8_t)address);
     74 }
     75 
     76 uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
     77 {
     78   // clamp to buffer length
     79   if(quantity > BUFFER_LENGTH){
     80     quantity = BUFFER_LENGTH;
     81   }
     82   // perform blocking read into buffer
     83   uint8_t read = twi_readFrom(address, rxBuffer, quantity);
     84   // set rx buffer iterator vars
     85   rxBufferIndex = 0;
     86   rxBufferLength = read;
     87 
     88   return read;
     89 }
     90 
     91 uint8_t TwoWire::requestFrom(int address, int quantity)
     92 {
     93   return requestFrom((uint8_t)address, (uint8_t)quantity);
     94 }
     95 
     96 void TwoWire::beginTransmission(uint8_t address)
     97 {
     98   // indicate that we are transmitting
     99   transmitting = 1;
    100   // set address of targeted slave
    101   txAddress = address;
    102   // reset tx buffer iterator vars
    103   txBufferIndex = 0;
    104   txBufferLength = 0;
    105 }
    106 
    107 void TwoWire::beginTransmission(int address)
    108 {
    109   beginTransmission((uint8_t)address);
    110 }
    111 
    112 uint8_t TwoWire::endTransmission(void)
    113 {
    114   // transmit buffer (blocking)
    115   int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
    116   // reset tx buffer iterator vars
    117   txBufferIndex = 0;
    118   txBufferLength = 0;
    119   // indicate that we are done transmitting
    120   transmitting = 0;
    121   return ret;
    122 }
    123 
    124 // must be called in:
    125 // slave tx event callback
    126 // or after beginTransmission(address)
    127 void TwoWire::send(uint8_t data)
    128 {
    129   if(transmitting){
    130   // in master transmitter mode
    131     // don't bother if buffer is full
    132     if(txBufferLength >= BUFFER_LENGTH){
    133       return;
    134     }
    135     // put byte in tx buffer
    136     txBuffer[txBufferIndex] = data;
    137     ++txBufferIndex;
    138     // update amount in buffer
    139     txBufferLength = txBufferIndex;
    140   }else{
    141   // in slave send mode
    142     // reply to master
    143     twi_transmit(&data, 1);
    144   }
    145 }
    146 
    147 // must be called in:
    148 // slave tx event callback
    149 // or after beginTransmission(address)
    150 void TwoWire::send(uint8_t* data, uint8_t quantity)
    151 {
    152   if(transmitting){
    153   // in master transmitter mode
    154     for(uint8_t i = 0; i < quantity; ++i){
    155       send(data[i]);
    156     }
    157   }else{
    158   // in slave send mode
    159     // reply to master
    160     twi_transmit(data, quantity);
    161   }
    162 }
    163 
    164 // must be called in:
    165 // slave tx event callback
    166 // or after beginTransmission(address)
    167 void TwoWire::send(char* data)
    168 {
    169   send((uint8_t*)data, strlen(data));
    170 }
    171 
    172 // must be called in:
    173 // slave tx event callback
    174 // or after beginTransmission(address)
    175 void TwoWire::send(int data)
    176 {
    177   send((uint8_t)data);
    178 }
    179 
    180 // must be called in:
    181 // slave rx event callback
    182 // or after requestFrom(address, numBytes)
    183 uint8_t TwoWire::available(void)
    184 {
    185   return rxBufferLength - rxBufferIndex;
    186 }
    187 
    188 // must be called in:
    189 // slave rx event callback
    190 // or after requestFrom(address, numBytes)
    191 uint8_t TwoWire::receive(void)
    192 {
    193   // default to returning null char
    194   // for people using with char strings
    195   uint8_t value = '\0';
    196 
    197   // get each successive byte on each call
    198   if(rxBufferIndex < rxBufferLength){
    199     value = rxBuffer[rxBufferIndex];
    200     ++rxBufferIndex;
    201   }
    202 
    203   return value;
    204 }
    205 
    206 // behind the scenes function that is called when data is received
    207 void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
    208 {
    209   // don't bother if user hasn't registered a callback
    210   if(!user_onReceive){
    211     return;
    212   }
    213   // don't bother if rx buffer is in use by a master requestFrom() op
    214   // i know this drops data, but it allows for slight stupidity
    215   // meaning, they may not have read all the master requestFrom() data yet
    216   if(rxBufferIndex < rxBufferLength){
    217     return;
    218   }
    219   // copy twi rx buffer into local read buffer
    220   // this enables new reads to happen in parallel
    221   for(uint8_t i = 0; i < numBytes; ++i){
    222     rxBuffer[i] = inBytes[i];
    223   }
    224   // set rx iterator vars
    225   rxBufferIndex = 0;
    226   rxBufferLength = numBytes;
    227   // alert user program
    228   user_onReceive(numBytes);
    229 }
    230 
    231 // behind the scenes function that is called when data is requested
    232 void TwoWire::onRequestService(void)
    233 {
    234   // don't bother if user hasn't registered a callback
    235   if(!user_onRequest){
    236     return;
    237   }
    238   // reset tx buffer iterator vars
    239   // !!! this will kill any pending pre-master sendTo() activity
    240   txBufferIndex = 0;
    241   txBufferLength = 0;
    242   // alert user program
    243   user_onRequest();
    244 }
    245 
    246 // sets function called on slave write
    247 void TwoWire::onReceive( void (*function)(int) )
    248 {
    249   user_onReceive = function;
    250 }
    251 
    252 // sets function called on slave read
    253 void TwoWire::onRequest( void (*function)(void) )
    254 {
    255   user_onRequest = function;
    256 }
    257 
    258 // Preinstantiate Objects //////////////////////////////////////////////////////
    259 
    260 TwoWire Wire = TwoWire();
    261 
    262