aboutsummaryrefslogtreecommitdiff
path: root/core/libraries/Wire/Wire.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/libraries/Wire/Wire.cpp')
-rwxr-xr-xcore/libraries/Wire/Wire.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/core/libraries/Wire/Wire.cpp b/core/libraries/Wire/Wire.cpp
new file mode 100755
index 0000000..73369b3
--- /dev/null
+++ b/core/libraries/Wire/Wire.cpp
@@ -0,0 +1,262 @@
+/*
+ TwoWire.cpp - TWI/I2C library for Wiring & Arduino
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+extern "C" {
+ #include <stdlib.h>
+ #include <string.h>
+ #include <inttypes.h>
+ #include "twi.h"
+}
+
+#include "Wire.h"
+
+// Initialize Class Variables //////////////////////////////////////////////////
+
+uint8_t* TwoWire::rxBuffer = 0;
+uint8_t TwoWire::rxBufferIndex = 0;
+uint8_t TwoWire::rxBufferLength = 0;
+
+uint8_t TwoWire::txAddress = 0;
+uint8_t* TwoWire::txBuffer = 0;
+uint8_t TwoWire::txBufferIndex = 0;
+uint8_t TwoWire::txBufferLength = 0;
+
+uint8_t TwoWire::transmitting = 0;
+void (*TwoWire::user_onRequest)(void);
+void (*TwoWire::user_onReceive)(int);
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+TwoWire::TwoWire()
+{
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void TwoWire::begin(void)
+{
+ // init buffer for reads
+ rxBuffer = (uint8_t*) calloc(BUFFER_LENGTH, sizeof(uint8_t));
+ rxBufferIndex = 0;
+ rxBufferLength = 0;
+
+ // init buffer for writes
+ txBuffer = (uint8_t*) calloc(BUFFER_LENGTH, sizeof(uint8_t));
+ txBufferIndex = 0;
+ txBufferLength = 0;
+
+ twi_init();
+}
+
+void TwoWire::begin(uint8_t address)
+{
+ twi_setAddress(address);
+ twi_attachSlaveTxEvent(onRequestService);
+ twi_attachSlaveRxEvent(onReceiveService);
+ begin();
+}
+
+void TwoWire::begin(int address)
+{
+ begin((uint8_t)address);
+}
+
+void TwoWire::requestFrom(uint8_t address, uint8_t quantity)
+{
+ // clamp to buffer length
+ if(quantity > BUFFER_LENGTH){
+ quantity = BUFFER_LENGTH;
+ }
+ // perform blocking read into buffer
+ twi_readFrom(address, rxBuffer, quantity);
+ // set rx buffer iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = quantity;
+}
+
+void TwoWire::requestFrom(int address, int quantity)
+{
+ requestFrom((uint8_t)address, (uint8_t)quantity);
+}
+
+void TwoWire::beginTransmission(uint8_t address)
+{
+ // indicate that we are transmitting
+ transmitting = 1;
+ // set address of targeted slave
+ txAddress = address;
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+}
+
+void TwoWire::beginTransmission(int address)
+{
+ beginTransmission((uint8_t)address);
+}
+
+void TwoWire::endTransmission(void)
+{
+ // transmit buffer (blocking)
+ twi_writeTo(txAddress, txBuffer, txBufferLength, 1);
+ // reset tx buffer iterator vars
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ // indicate that we are done transmitting
+ transmitting = 0;
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+void TwoWire::send(uint8_t data)
+{
+ if(transmitting){
+ // in master transmitter mode
+ // don't bother if buffer is full
+ if(txBufferLength >= BUFFER_LENGTH){
+ return;
+ }
+ // put byte in tx buffer
+ txBuffer[txBufferIndex] = data;
+ ++txBufferIndex;
+ // update amount in buffer
+ txBufferLength = txBufferIndex;
+ }else{
+ // in slave send mode
+ // reply to master
+ twi_transmit(&data, 1);
+ }
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+void TwoWire::send(uint8_t* data, uint8_t quantity)
+{
+ if(transmitting){
+ // in master transmitter mode
+ for(uint8_t i = 0; i < quantity; ++i){
+ send(data[i]);
+ }
+ }else{
+ // in slave send mode
+ // reply to master
+ twi_transmit(data, quantity);
+ }
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+void TwoWire::send(char* data)
+{
+ send((uint8_t*)data, strlen(data));
+}
+
+// must be called in:
+// slave tx event callback
+// or after beginTransmission(address)
+void TwoWire::send(int data)
+{
+ send((uint8_t)data);
+}
+
+// must be called in:
+// slave rx event callback
+// or after requestFrom(address, numBytes)
+uint8_t TwoWire::available(void)
+{
+ return rxBufferLength - rxBufferIndex;
+}
+
+// must be called in:
+// slave rx event callback
+// or after requestFrom(address, numBytes)
+uint8_t TwoWire::receive(void)
+{
+ // default to returning null char
+ // for people using with char strings
+ uint8_t value = '\0';
+
+ // get each successive byte on each call
+ if(rxBufferIndex < rxBufferLength){
+ value = rxBuffer[rxBufferIndex];
+ ++rxBufferIndex;
+ }
+
+ return value;
+}
+
+// behind the scenes function that is called when data is received
+void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
+{
+ // don't bother if user hasn't registered a callback
+ if(!user_onReceive){
+ return;
+ }
+ // don't bother if rx buffer is in use by a master requestFrom() op
+ // i know this drops data, but it allows for slight stupidity
+ // meaning, they may not have read all the master requestFrom() data yet
+ if(rxBufferIndex < rxBufferLength){
+ return;
+ }
+ // copy twi rx buffer into local read buffer
+ // this enables new reads to happen in parallel
+ for(uint8_t i = 0; i < numBytes; ++i){
+ rxBuffer[i] = inBytes[i];
+ }
+ // set rx iterator vars
+ rxBufferIndex = 0;
+ rxBufferLength = numBytes;
+ // alert user program
+ user_onReceive(numBytes);
+}
+
+// behind the scenes function that is called when data is requested
+void TwoWire::onRequestService(void)
+{
+ // don't bother if user hasn't registered a callback
+ if(!user_onRequest){
+ return;
+ }
+ // reset tx buffer iterator vars
+ // !!! this will kill any pending pre-master sendTo() activity
+ txBufferIndex = 0;
+ txBufferLength = 0;
+ // alert user program
+ user_onRequest();
+}
+
+// sets function called on slave write
+void TwoWire::onReceive( void (*function)(int) )
+{
+ user_onReceive = function;
+}
+
+// sets function called on slave read
+void TwoWire::onRequest( void (*function)(void) )
+{
+ user_onRequest = function;
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+TwoWire Wire = TwoWire();
+