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