Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Wire / Wire.cpp @ 58d82c77

History | View | Annotate | Download (6.2 KB)

1 58d82c77 Tom Mullins
/*
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
size_t TwoWire::write(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
      setWriteError();
134
      return 0;
135
    }
136
    // put byte in tx buffer
137
    txBuffer[txBufferIndex] = data;
138
    ++txBufferIndex;
139
    // update amount in buffer   
140
    txBufferLength = txBufferIndex;
141
  }else{
142
  // in slave send mode
143
    // reply to master
144
    twi_transmit(&data, 1);
145
  }
146
  return 1;
147
}
148
149
// must be called in:
150
// slave tx event callback
151
// or after beginTransmission(address)
152
size_t TwoWire::write(const uint8_t *data, size_t quantity)
153
{
154
  if(transmitting){
155
  // in master transmitter mode
156
    for(size_t i = 0; i < quantity; ++i){
157
      write(data[i]);
158
    }
159
  }else{
160
  // in slave send mode
161
    // reply to master
162
    twi_transmit(data, quantity);
163
  }
164
  return quantity;
165
}
166
167
// must be called in:
168
// slave rx event callback
169
// or after requestFrom(address, numBytes)
170
int TwoWire::available(void)
171
{
172
  return rxBufferLength - rxBufferIndex;
173
}
174
175
// must be called in:
176
// slave rx event callback
177
// or after requestFrom(address, numBytes)
178
int TwoWire::read(void)
179
{
180
  int value = -1;
181
  
182
  // get each successive byte on each call
183
  if(rxBufferIndex < rxBufferLength){
184
    value = rxBuffer[rxBufferIndex];
185
    ++rxBufferIndex;
186
  }
187
188
  return value;
189
}
190
191
// must be called in:
192
// slave rx event callback
193
// or after requestFrom(address, numBytes)
194
int TwoWire::peek(void)
195
{
196
  int value = -1;
197
  
198
  if(rxBufferIndex < rxBufferLength){
199
    value = rxBuffer[rxBufferIndex];
200
  }
201
202
  return value;
203
}
204
205
void TwoWire::flush(void)
206
{
207
  // XXX: to be implemented.
208
}
209
210
// behind the scenes function that is called when data is received
211
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
212
{
213
  // don't bother if user hasn't registered a callback
214
  if(!user_onReceive){
215
    return;
216
  }
217
  // don't bother if rx buffer is in use by a master requestFrom() op
218
  // i know this drops data, but it allows for slight stupidity
219
  // meaning, they may not have read all the master requestFrom() data yet
220
  if(rxBufferIndex < rxBufferLength){
221
    return;
222
  }
223
  // copy twi rx buffer into local read buffer
224
  // this enables new reads to happen in parallel
225
  for(uint8_t i = 0; i < numBytes; ++i){
226
    rxBuffer[i] = inBytes[i];    
227
  }
228
  // set rx iterator vars
229
  rxBufferIndex = 0;
230
  rxBufferLength = numBytes;
231
  // alert user program
232
  user_onReceive(numBytes);
233
}
234
235
// behind the scenes function that is called when data is requested
236
void TwoWire::onRequestService(void)
237
{
238
  // don't bother if user hasn't registered a callback
239
  if(!user_onRequest){
240
    return;
241
  }
242
  // reset tx buffer iterator vars
243
  // !!! this will kill any pending pre-master sendTo() activity
244
  txBufferIndex = 0;
245
  txBufferLength = 0;
246
  // alert user program
247
  user_onRequest();
248
}
249
250
// sets function called on slave write
251
void TwoWire::onReceive( void (*function)(int) )
252
{
253
  user_onReceive = function;
254
}
255
256
// sets function called on slave read
257
void TwoWire::onRequest( void (*function)(void) )
258
{
259
  user_onRequest = function;
260
}
261
262
// Preinstantiate Objects //////////////////////////////////////////////////////
263
264
TwoWire Wire = TwoWire();