• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TwoWire()46 TwoWire::TwoWire()
47 {
48 }
49 
50 // Public Methods //////////////////////////////////////////////////////////////
51 
begin(void)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 
begin(uint8_t address)63 void TwoWire::begin(uint8_t address)
64 {
65   twi_setAddress(address);
66   twi_attachSlaveTxEvent(onRequestService);
67   twi_attachSlaveRxEvent(onReceiveService);
68   begin();
69 }
70 
begin(int address)71 void TwoWire::begin(int address)
72 {
73   begin((uint8_t)address);
74 }
75 
requestFrom(uint8_t address,uint8_t quantity)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 
requestFrom(int address,int quantity)91 uint8_t TwoWire::requestFrom(int address, int quantity)
92 {
93   return requestFrom((uint8_t)address, (uint8_t)quantity);
94 }
95 
beginTransmission(uint8_t address)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 
beginTransmission(int address)107 void TwoWire::beginTransmission(int address)
108 {
109   beginTransmission((uint8_t)address);
110 }
111 
endTransmission(void)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)
send(uint8_t data)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)
send(uint8_t * data,uint8_t quantity)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)
send(char * data)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)
send(int data)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)
available(void)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)
receive(void)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
onReceiveService(uint8_t * inBytes,int numBytes)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
onRequestService(void)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
onReceive(void (* function)(int))247 void TwoWire::onReceive( void (*function)(int) )
248 {
249   user_onReceive = function;
250 }
251 
252 // sets function called on slave read
onRequest(void (* function)(void))253 void TwoWire::onRequest( void (*function)(void) )
254 {
255   user_onRequest = function;
256 }
257 
258 // Preinstantiate Objects //////////////////////////////////////////////////////
259 
260 TwoWire Wire = TwoWire();
261 
262