source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/libraries/Wire/Wire.cpp@ 175

Last change on this file since 175 was 175, checked in by ertl-honda, 8 years ago

ライブラリを Arduino IDE 1.7.9 にupdate

File size: 7.4 KB
Line 
1/*
2 * TWI/I2C library for Arduino Zero
3 * Copyright (c) 2015 Arduino LLC. All rights 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
20extern "C" {
21#include <string.h>
22}
23
24#include <Arduino.h>
25#include <wiring_private.h>
26
27#include "Wire.h"
28
29TwoWire::TwoWire(SERCOM * s, uint8_t pinSDA, uint8_t pinSCL)
30{
31 this->sercom = s;
32 this->_uc_pinSDA=pinSDA;
33 this->_uc_pinSCL=pinSCL;
34 transmissionBegun = false;
35}
36
37void TwoWire::begin(void) {
38 //Master Mode
39 sercom->initMasterWIRE(TWI_CLOCK);
40 sercom->enableWIRE();
41
42 pinPeripheral(_uc_pinSDA, g_APinDescription[_uc_pinSDA].ulPinType);
43 pinPeripheral(_uc_pinSCL, g_APinDescription[_uc_pinSCL].ulPinType);
44}
45
46void TwoWire::begin(uint8_t address) {
47 //Slave mode
48 sercom->initSlaveWIRE(address);
49 sercom->enableWIRE();
50
51 pinPeripheral(_uc_pinSDA, g_APinDescription[_uc_pinSDA].ulPinType);
52 pinPeripheral(_uc_pinSCL, g_APinDescription[_uc_pinSCL].ulPinType);
53}
54
55void TwoWire::setClock(uint32_t baudrate) {
56 sercom->disableWIRE();
57 sercom->initMasterWIRE(baudrate);
58 sercom->enableWIRE();
59}
60
61void TwoWire::end() {
62 sercom->disableWIRE();
63}
64
65uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
66{
67 if(quantity == 0)
68 {
69 return 0;
70 }
71
72 size_t byteRead = 0;
73
74 if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG))
75 {
76 // Read first data
77 rxBuffer.store_char(sercom->readDataWIRE());
78
79 // Connected to slave
80 for (byteRead = 1; byteRead < quantity; ++byteRead)
81 {
82 sercom->prepareAckBitWIRE(); // Prepare Acknowledge
83 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave
84 rxBuffer.store_char(sercom->readDataWIRE()); // Read data and send the ACK
85 }
86 sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission
87 //sercom->readDataWIRE(); // Clear data register to send NACK
88
89 if (stopBit)
90 {
91 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop
92 }
93 }
94
95 return byteRead;
96}
97
98uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
99{
100 return requestFrom(address, quantity, true);
101}
102
103void TwoWire::beginTransmission(uint8_t address) {
104 // save address of target and clear buffer
105 txAddress = address;
106 txBuffer.clear();
107
108 transmissionBegun = true;
109}
110
111// Errors:
112// 0 : Success
113// 1 : Data too long
114// 2 : NACK on transmit of address
115// 3 : NACK on transmit of data
116// 4 : Other error
117uint8_t TwoWire::endTransmission(bool stopBit)
118{
119 transmissionBegun = false ;
120
121 // Start I2C transmission
122 if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) )
123 {
124 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
125 return 2 ; // Address error
126 }
127
128 // Send all buffer
129 while( txBuffer.available() )
130 {
131 // Trying to send data
132 if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) )
133 {
134 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
135 return 3 ; // Nack or error
136 }
137 }
138
139 if (stopBit)
140 {
141 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
142 }
143
144 return 0;
145}
146
147uint8_t TwoWire::endTransmission()
148{
149 return endTransmission(true);
150}
151
152size_t TwoWire::write(uint8_t ucData)
153{
154 if(sercom->isMasterWIRE())
155 {
156 // No writing, without begun transmission or a full buffer
157 if ( !transmissionBegun || txBuffer.isFull() )
158 {
159 return 0 ;
160 }
161
162 txBuffer.store_char( ucData ) ;
163
164 return 1 ;
165 }
166 else
167 {
168 if(sercom->sendDataSlaveWIRE( ucData ))
169 {
170 return 1;
171 }
172 }
173
174 return 0;
175}
176
177size_t TwoWire::write(const uint8_t *data, size_t quantity)
178{
179 //Try to store all data
180 for(size_t i = 0; i < quantity; ++i)
181 {
182 //Return the number of data stored, when the buffer is full (if write return 0)
183 if(!write(data[i]))
184 return i;
185 }
186
187 //All data stored
188 return quantity;
189}
190
191int TwoWire::available(void)
192{
193 return rxBuffer.available();
194}
195
196int TwoWire::read(void)
197{
198 return rxBuffer.read_char();
199}
200
201int TwoWire::peek(void)
202{
203 return rxBuffer.peek();
204}
205
206void TwoWire::flush(void)
207{
208 // Do nothing, use endTransmission(..) to force
209 // data transfer.
210}
211
212void TwoWire::onReceive(void(*function)(int))
213{
214 onReceiveCallback = function;
215}
216
217void TwoWire::onRequest(void(*function)(void))
218{
219 onRequestCallback = function;
220}
221
222void TwoWire::onService(void)
223{
224 if ( sercom->isSlaveWIRE() )
225 {
226 if(sercom->isStopDetectedWIRE() ||
227 (sercom->isAddressMatch() && sercom->isRestartDetectedWIRE() && !sercom->isMasterReadOperationWIRE())) //Stop or Restart detected
228 {
229 sercom->prepareAckBitWIRE();
230 sercom->prepareCommandBitsWire(0x03);
231
232 //Calling onReceiveCallback, if exists
233 if(onReceiveCallback)
234 {
235 onReceiveCallback(available());
236 }
237
238 rxBuffer.clear();
239 }
240 else if(sercom->isAddressMatch()) //Address Match
241 {
242 sercom->prepareAckBitWIRE();
243 sercom->prepareCommandBitsWire(0x03);
244
245 if(sercom->isMasterReadOperationWIRE()) //Is a request ?
246 {
247 // wait for data ready flag,
248 // before calling request callback
249 while(!sercom->isDataReadyWIRE());
250
251 //Calling onRequestCallback, if exists
252 if(onRequestCallback)
253 {
254 onRequestCallback();
255 }
256 }
257 }
258 else if(sercom->isDataReadyWIRE()) //Received data
259 {
260 if (rxBuffer.isFull()) {
261 sercom->prepareNackBitWIRE();
262 } else {
263 //Store data
264 rxBuffer.store_char(sercom->readDataWIRE());
265
266 sercom->prepareAckBitWIRE();
267 }
268
269 sercom->prepareCommandBitsWire(0x03);
270 }
271 }
272}
273
274#if WIRE_INTERFACES_COUNT > 0
275 /* In case new variant doesn't define these macros,
276 * we put here the ones for Arduino Zero.
277 *
278 * These values should be different on some variants!
279 */
280 #ifndef PERIPH_WIRE
281 #define PERIPH_WIRE sercom3
282 #define WIRE_IT_HANDLER SERCOM3_Handler
283 #endif // PERIPH_WIRE
284 TwoWire Wire(&PERIPH_WIRE, PIN_WIRE_SDA, PIN_WIRE_SCL);
285
286 void WIRE_IT_HANDLER(void) {
287 Wire.onService();
288 }
289#endif
290
291#if WIRE_INTERFACES_COUNT > 1
292 TwoWire Wire1(&PERIPH_WIRE1, PIN_WIRE1_SDA, PIN_WIRE1_SCL);
293
294 void WIRE1_IT_HANDLER(void) {
295 Wire1.onService();
296 }
297#endif
298
299#if WIRE_INTERFACES_COUNT > 2
300 TwoWire Wire2(&PERIPH_WIRE2, PIN_WIRE2_SDA, PIN_WIRE2_SCL);
301
302 void WIRE2_IT_HANDLER(void) {
303 Wire2.onService();
304 }
305#endif
306
307#if WIRE_INTERFACES_COUNT > 3
308 TwoWire Wire3(&PERIPH_WIRE3, PIN_WIRE3_SDA, PIN_WIRE3_SCL);
309
310 void WIRE3_IT_HANDLER(void) {
311 Wire3.onService();
312 }
313#endif
314
315#if WIRE_INTERFACES_COUNT > 4
316 TwoWire Wire4(&PERIPH_WIRE4, PIN_WIRE4_SDA, PIN_WIRE4_SCL);
317
318 void WIRE4_IT_HANDLER(void) {
319 Wire4.onService();
320 }
321#endif
322
323#if WIRE_INTERFACES_COUNT > 5
324 TwoWire Wire5(&PERIPH_WIRE5, PIN_WIRE5_SDA, PIN_WIRE5_SCL);
325
326 void WIRE5_IT_HANDLER(void) {
327 Wire5.onService();
328 }
329#endif
330
Note: See TracBrowser for help on using the repository browser.