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