Skip to content

Commit 2521c1e

Browse files
committed
Wire library with i2c master support
1 parent d754597 commit 2521c1e

9 files changed

Lines changed: 1433 additions & 0 deletions

File tree

libraries/Wire/Wire.cpp

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
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+
extern "C" {
23+
#include <stdlib.h>
24+
#include <string.h>
25+
#include <inttypes.h>
26+
}
27+
28+
#include "i2c.h"
29+
#include "Wire.h"
30+
31+
// Initialize Class Variables //////////////////////////////////////////////////
32+
33+
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
34+
uint8_t TwoWire::rxBufferIndex = 0;
35+
uint8_t TwoWire::rxBufferLength = 0;
36+
37+
uint8_t TwoWire::txAddress = 0;
38+
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
39+
uint8_t TwoWire::txBufferIndex = 0;
40+
uint8_t TwoWire::txBufferLength = 0;
41+
42+
uint8_t TwoWire::transmitting = 0;
43+
void (*TwoWire::user_onRequest)(void);
44+
void (*TwoWire::user_onReceive)(int);
45+
46+
// Constructors ////////////////////////////////////////////////////////////////
47+
48+
TwoWire::TwoWire()
49+
{
50+
}
51+
52+
// Public Methods //////////////////////////////////////////////////////////////
53+
54+
void TwoWire::pins(int sda, int scl)
55+
{
56+
i2c_init(sda, scl);
57+
}
58+
59+
void TwoWire::begin(void)
60+
{
61+
rxBufferIndex = 0;
62+
rxBufferLength = 0;
63+
64+
txBufferIndex = 0;
65+
txBufferLength = 0;
66+
67+
}
68+
69+
void TwoWire::begin(uint8_t address)
70+
{
71+
// twi_setAddress(address);
72+
// twi_attachSlaveTxEvent(onRequestService);
73+
// twi_attachSlaveRxEvent(onReceiveService);
74+
// begin();
75+
}
76+
77+
void TwoWire::begin(int address)
78+
{
79+
// begin((uint8_t)address);
80+
}
81+
82+
void TwoWire::setClock(uint32_t frequency)
83+
{
84+
i2c_freq(frequency);
85+
}
86+
size_t TwoWire::requestFrom(uint8_t address, size_t size, bool sendStop)
87+
{
88+
// clamp to buffer length
89+
if(size > BUFFER_LENGTH){
90+
size = BUFFER_LENGTH;
91+
}
92+
// perform blocking read into buffer
93+
size_t read = i2c_master_read_from(address, rxBuffer, size, sendStop);
94+
// set rx buffer iterator vars
95+
rxBufferIndex = 0;
96+
rxBufferLength = read;
97+
98+
return read;
99+
}
100+
101+
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
102+
{
103+
return requestFrom(address, static_cast<size_t>(quantity), static_cast<bool>(sendStop));
104+
}
105+
106+
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
107+
{
108+
return requestFrom(address, static_cast<size_t>(quantity), true);
109+
}
110+
111+
uint8_t TwoWire::requestFrom(int address, int quantity)
112+
{
113+
return requestFrom(static_cast<uint8_t>(address), static_cast<size_t>(quantity), true);
114+
}
115+
116+
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
117+
{
118+
return requestFrom(static_cast<uint8_t>(address), static_cast<size_t>(quantity), static_cast<bool>(sendStop));
119+
}
120+
121+
void TwoWire::beginTransmission(uint8_t address)
122+
{
123+
// indicate that we are transmitting
124+
transmitting = 1;
125+
// set address of targeted slave
126+
txAddress = address;
127+
// reset tx buffer iterator vars
128+
txBufferIndex = 0;
129+
txBufferLength = 0;
130+
}
131+
132+
void TwoWire::beginTransmission(int address)
133+
{
134+
beginTransmission((uint8_t)address);
135+
}
136+
137+
//
138+
// Originally, 'endTransmission' was an f(void) function.
139+
// It has been modified to take one parameter indicating
140+
// whether or not a STOP should be performed on the bus.
141+
// Calling endTransmission(false) allows a sketch to
142+
// perform a repeated start.
143+
//
144+
// WARNING: Nothing in the library keeps track of whether
145+
// the bus tenure has been properly ended with a STOP. It
146+
// is very possible to leave the bus in a hung state if
147+
// no call to endTransmission(true) is made. Some I2C
148+
// devices will behave oddly if they do not see a STOP.
149+
//
150+
uint8_t TwoWire::endTransmission(uint8_t sendStop)
151+
{
152+
// transmit buffer (blocking)
153+
int8_t ret = i2c_master_write_to(txAddress, txBuffer, txBufferLength, sendStop);
154+
// reset tx buffer iterator vars
155+
txBufferIndex = 0;
156+
txBufferLength = 0;
157+
// indicate that we are done transmitting
158+
transmitting = 0;
159+
return ret;
160+
}
161+
162+
// This provides backwards compatibility with the original
163+
// definition, and expected behaviour, of endTransmission
164+
//
165+
uint8_t TwoWire::endTransmission(void)
166+
{
167+
return endTransmission(true);
168+
}
169+
170+
// must be called in:
171+
// slave tx event callback
172+
// or after beginTransmission(address)
173+
size_t TwoWire::write(uint8_t data)
174+
{
175+
if(transmitting){
176+
// in master transmitter mode
177+
// don't bother if buffer is full
178+
if(txBufferLength >= BUFFER_LENGTH){
179+
setWriteError();
180+
return 0;
181+
}
182+
// put byte in tx buffer
183+
txBuffer[txBufferIndex] = data;
184+
++txBufferIndex;
185+
// update amount in buffer
186+
txBufferLength = txBufferIndex;
187+
}else{
188+
// in slave send mode
189+
// reply to master
190+
// i2c_slave_transmit(&data, 1);
191+
}
192+
return 1;
193+
}
194+
195+
// must be called in:
196+
// slave tx event callback
197+
// or after beginTransmission(address)
198+
size_t TwoWire::write(const uint8_t *data, size_t quantity)
199+
{
200+
if(transmitting){
201+
// in master transmitter mode
202+
for(size_t i = 0; i < quantity; ++i){
203+
write(data[i]);
204+
}
205+
}else{
206+
// in slave send mode
207+
// reply to master
208+
// i2c_slave_transmit(data, quantity);
209+
}
210+
return quantity;
211+
}
212+
213+
// must be called in:
214+
// slave rx event callback
215+
// or after requestFrom(address, numBytes)
216+
int TwoWire::available(void)
217+
{
218+
return rxBufferLength - rxBufferIndex;
219+
}
220+
221+
// must be called in:
222+
// slave rx event callback
223+
// or after requestFrom(address, numBytes)
224+
int TwoWire::read(void)
225+
{
226+
int value = -1;
227+
228+
// get each successive byte on each call
229+
if(rxBufferIndex < rxBufferLength){
230+
value = rxBuffer[rxBufferIndex];
231+
++rxBufferIndex;
232+
}
233+
234+
return value;
235+
}
236+
237+
// must be called in:
238+
// slave rx event callback
239+
// or after requestFrom(address, numBytes)
240+
int TwoWire::peek(void)
241+
{
242+
int value = -1;
243+
244+
if(rxBufferIndex < rxBufferLength){
245+
value = rxBuffer[rxBufferIndex];
246+
}
247+
248+
return value;
249+
}
250+
251+
void TwoWire::flush(void)
252+
{
253+
// XXX: to be implemented.
254+
}
255+
256+
// behind the scenes function that is called when data is received
257+
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
258+
{
259+
// don't bother if user hasn't registered a callback
260+
// if(!user_onReceive){
261+
// return;
262+
// }
263+
// // don't bother if rx buffer is in use by a master requestFrom() op
264+
// // i know this drops data, but it allows for slight stupidity
265+
// // meaning, they may not have read all the master requestFrom() data yet
266+
// if(rxBufferIndex < rxBufferLength){
267+
// return;
268+
// }
269+
// // copy twi rx buffer into local read buffer
270+
// // this enables new reads to happen in parallel
271+
// for(uint8_t i = 0; i < numBytes; ++i){
272+
// rxBuffer[i] = inBytes[i];
273+
// }
274+
// // set rx iterator vars
275+
// rxBufferIndex = 0;
276+
// rxBufferLength = numBytes;
277+
// // alert user program
278+
// user_onReceive(numBytes);
279+
}
280+
281+
// behind the scenes function that is called when data is requested
282+
void TwoWire::onRequestService(void)
283+
{
284+
// // don't bother if user hasn't registered a callback
285+
// if(!user_onRequest){
286+
// return;
287+
// }
288+
// // reset tx buffer iterator vars
289+
// // !!! this will kill any pending pre-master sendTo() activity
290+
// txBufferIndex = 0;
291+
// txBufferLength = 0;
292+
// // alert user program
293+
// user_onRequest();
294+
}
295+
296+
// sets function called on slave write
297+
void TwoWire::onReceive( void (*function)(int) )
298+
{
299+
// user_onReceive = function;
300+
}
301+
302+
// sets function called on slave read
303+
void TwoWire::onRequest( void (*function)(void) )
304+
{
305+
// user_onRequest = function;
306+
}
307+
308+
// Preinstantiate Objects //////////////////////////////////////////////////////
309+
310+
TwoWire Wire = TwoWire();
311+

libraries/Wire/Wire.h

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
TwoWire.h - TWI/I2C library for Arduino & Wiring
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 TwoWire_h
23+
#define TwoWire_h
24+
25+
#include <inttypes.h>
26+
#include "Stream.h"
27+
28+
29+
30+
#define BUFFER_LENGTH 32
31+
32+
class TwoWire : public Stream
33+
{
34+
private:
35+
static uint8_t rxBuffer[];
36+
static uint8_t rxBufferIndex;
37+
static uint8_t rxBufferLength;
38+
39+
static uint8_t txAddress;
40+
static uint8_t txBuffer[];
41+
static uint8_t txBufferIndex;
42+
static uint8_t txBufferLength;
43+
44+
static uint8_t transmitting;
45+
static void (*user_onRequest)(void);
46+
static void (*user_onReceive)(int);
47+
static void onRequestService(void);
48+
static void onReceiveService(uint8_t*, int);
49+
public:
50+
TwoWire();
51+
void pins(int sda, int scl);
52+
void begin();
53+
void begin(uint8_t);
54+
void begin(int);
55+
void setClock(uint32_t);
56+
void beginTransmission(uint8_t);
57+
void beginTransmission(int);
58+
uint8_t endTransmission(void);
59+
uint8_t endTransmission(uint8_t);
60+
size_t requestFrom(uint8_t address, size_t size, bool sendStop);
61+
62+
uint8_t requestFrom(uint8_t, uint8_t);
63+
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
64+
uint8_t requestFrom(int, int);
65+
uint8_t requestFrom(int, int, int);
66+
67+
virtual size_t write(uint8_t);
68+
virtual size_t write(const uint8_t *, size_t);
69+
virtual int available(void);
70+
virtual int read(void);
71+
virtual int peek(void);
72+
virtual void flush(void);
73+
void onReceive( void (*)(int) );
74+
void onRequest( void (*)(void) );
75+
76+
inline size_t write(unsigned long n) { return write((uint8_t)n); }
77+
inline size_t write(long n) { return write((uint8_t)n); }
78+
inline size_t write(unsigned int n) { return write((uint8_t)n); }
79+
inline size_t write(int n) { return write((uint8_t)n); }
80+
using Print::write;
81+
};
82+
83+
extern TwoWire Wire;
84+
85+
#endif
86+

0 commit comments

Comments
 (0)