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

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

ライブラリとOS及びベーシックなサンプルの追加.

File size: 7.8 KB
Line 
1/*
2 * TwoWire.h - TWI/I2C library for Arduino Zero
3 * based on Copyright (c) 2011 Cristian Maglie <c.maglie@bug.st>.
4 * Copyright (c) 2014 Arduino.
5 * All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22extern "C" {
23#include <string.h>
24}
25
26#include "Wire.h"
27#include "variant.h"
28#include "wiring_digital.h"
29
30TwoWire::TwoWire(SERCOM * s)
31{
32 this->sercom = s;
33 transmissionBegun = false;
34}
35
36void TwoWire::begin(void) {
37 //Master Mode
38 sercom->initMasterWIRE(TWI_CLOCK);
39 sercom->enableWIRE();
40
41 pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
42 pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
43}
44
45void TwoWire::begin(uint8_t address) {
46 //Slave mode
47 sercom->initSlaveWIRE(address);
48 sercom->enableWIRE();
49}
50
51uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
52{
53 if(quantity == 0)
54 {
55 return 0;
56 }
57
58
59 size_t byteRead = 0;
60
61 if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG))
62 {
63
64 // Read first data
65 rxBuffer.store_char(sercom->readDataWIRE());
66
67 // Connected to slave
68 //while(toRead--)
69 for(byteRead = 0; byteRead < quantity; ++byteRead)
70 {
71 if( byteRead == quantity - 1) // Stop transmission
72 {
73 sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission
74 //sercom->readDataWIRE(); // Clear data register to send NACK
75 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop
76 }
77 else // Continue transmission
78 {
79 sercom->prepareAckBitWIRE(); // Prepare Acknowledge
80 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave
81 rxBuffer.store_char( sercom->readDataWIRE() ); // Read data and send the ACK
82 }
83 }
84 }
85
86 return byteRead;
87}
88
89uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
90{
91 return requestFrom(address, quantity, true);
92}
93
94void TwoWire::beginTransmission(uint8_t address) {
95 // save address of target and clear buffer
96 txAddress = address;
97 txBuffer.clear();
98
99 transmissionBegun = true;
100}
101
102// Errors:
103// 0 : Success
104// 1 : Data too long
105// 2 : NACK on transmit of address
106// 3 : NACK on transmit of data
107// 4 : Other error
108uint8_t TwoWire::endTransmission(bool stopBit)
109{
110 transmissionBegun = false ;
111
112 // Check if there are data to send
113 if ( txBuffer.available() == 0)
114 {
115 return 4 ;
116 }
117
118 // Start I2C transmission
119 if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) )
120 {
121 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
122 return 2 ; // Address error
123 }
124
125 // Send all buffer
126 while( txBuffer.available() )
127 {
128
129 // Trying to send data
130 if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) )
131 {
132 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
133 return 3 ; // Nack or error
134 }
135
136
137 if(txBuffer.available() == 0)
138 {
139 sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
140 }
141 }
142
143 return 0;
144}
145
146uint8_t TwoWire::endTransmission()
147{
148 return endTransmission(true);
149}
150
151size_t TwoWire::write(uint8_t ucData)
152{
153 if(sercom->isMasterWIRE())
154 {
155 // No writing, without begun transmission or a full buffer
156 if ( !transmissionBegun || txBuffer.isFull() )
157 {
158 return 0 ;
159 }
160
161 txBuffer.store_char( ucData ) ;
162
163 return 1 ;
164 }
165 else
166 {
167 if(sercom->sendDataSlaveWIRE( ucData ))
168 {
169 return 1;
170 }
171 }
172
173 return 0;
174}
175
176size_t TwoWire::write(const uint8_t *data, size_t quantity)
177{
178 //Try to store all data
179 for(size_t i = 0; i < quantity; ++i)
180 {
181 //Return the number of data stored, when the buffer is full (if write return 0)
182 if(!write(data[i]))
183 return i;
184 }
185
186 //All data stored
187 return quantity;
188}
189
190int TwoWire::available(void)
191{
192 return rxBuffer.available();
193}
194
195int TwoWire::read(void)
196{
197 return rxBuffer.read_char();
198}
199
200int TwoWire::peek(void)
201{
202 return rxBuffer.peek();
203}
204
205void TwoWire::flush(void)
206{
207 // Do nothing, use endTransmission(..) to force
208 // data transfer.
209}
210
211void TwoWire::onReceive(void(*function)(int))
212{
213 onReceiveCallback = function;
214}
215
216void TwoWire::onRequest(void(*function)(void))
217{
218 onRequestCallback = function;
219}
220
221
222void TwoWire::onService(void)
223{
224 if ( sercom->isSlaveWIRE() )
225 {
226 //Received data
227 if(sercom->isDataReadyWIRE())
228 {
229 //Store data
230 rxBuffer.store_char(sercom->readDataWIRE());
231
232 //Stop or Restart detected
233 if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE())
234 {
235 //Calling onReceiveCallback, if exists
236 if(onReceiveCallback)
237 {
238 onReceiveCallback(available());
239 }
240 }
241 }
242
243 //Address Match
244 if(sercom->isAddressMatch())
245 {
246 //Is a request ?
247 if(sercom->isMasterReadOperationWIRE())
248 {
249 //Calling onRequestCallback, if exists
250 if(onRequestCallback)
251 {
252 onRequestCallback();
253 }
254 }
255 }
256 }
257}
258
259/*
260void TwoWire::onService(void)
261{
262 // Retrieve interrupt status
263 uint32_t sr = TWI_GetStatus(twi);
264
265 if (status == SLAVE_IDLE && TWI_STATUS_SVACC(sr)) {
266 TWI_DisableIt(twi, TWI_IDR_SVACC);
267 TWI_EnableIt(twi, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK
268 | TWI_IER_EOSACC | TWI_IER_SCL_WS | TWI_IER_TXCOMP);
269
270 srvBufferLength = 0;
271 srvBufferIndex = 0;
272
273 // Detect if we should go into RECV or SEND status
274 // SVREAD==1 means *master* reading -> SLAVE_SEND
275 if (!TWI_STATUS_SVREAD(sr)) {
276 status = SLAVE_RECV;
277 } else {
278 status = SLAVE_SEND;
279
280 // Alert calling program to generate a response ASAP
281 if (onRequestCallback)
282 onRequestCallback();
283 else
284 // create a default 1-byte response
285 write((uint8_t) 0);
286 }
287 }
288
289 if (status != SLAVE_IDLE) {
290 if (TWI_STATUS_TXCOMP(sr) && TWI_STATUS_EOSACC(sr)) {
291 if (status == SLAVE_RECV && onReceiveCallback) {
292 // Copy data into rxBuffer
293 // (allows to receive another packet while the
294 // user program reads actual data)
295 for (uint8_t i = 0; i < srvBufferLength; ++i)
296 rxBuffer[i] = srvBuffer[i];
297 rxBufferIndex = 0;
298 rxBufferLength = srvBufferLength;
299
300 // Alert calling program
301 onReceiveCallback( rxBufferLength);
302 }
303
304 // Transfer completed
305 TWI_EnableIt(twi, TWI_SR_SVACC);
306 TWI_DisableIt(twi, TWI_IDR_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK
307 | TWI_IDR_EOSACC | TWI_IDR_SCL_WS | TWI_IER_TXCOMP);
308 status = SLAVE_IDLE;
309 }
310 }
311
312 if (status == SLAVE_RECV) {
313 if (TWI_STATUS_RXRDY(sr)) {
314 if (srvBufferLength < BUFFER_LENGTH)
315 srvBuffer[srvBufferLength++] = TWI_ReadByte(twi);
316 }
317 }
318
319 if (status == SLAVE_SEND) {
320 if (TWI_STATUS_TXRDY(sr) && !TWI_STATUS_NACK(sr)) {
321 uint8_t c = 'x';
322 if (srvBufferIndex < srvBufferLength)
323 c = srvBuffer[srvBufferIndex++];
324 TWI_WriteByte(twi, c);
325 }
326 }
327}
328*/
329
330#if WIRE_INTERFACES_COUNT > 0
331/*static void Wire_Init(void) {
332 pmc_enable_periph_clk(WIRE_INTERFACE_ID);
333 PIO_Configure(
334 g_APinDescription[PIN_WIRE_SDA].pPort,
335 g_APinDescription[PIN_WIRE_SDA].ulPinType,
336 g_APinDescription[PIN_WIRE_SDA].ulPin,
337 g_APinDescription[PIN_WIRE_SDA].ulPinConfiguration);
338 PIO_Configure(
339 g_APinDescription[PIN_WIRE_SCL].pPort,
340 g_APinDescription[PIN_WIRE_SCL].ulPinType,
341 g_APinDescription[PIN_WIRE_SCL].ulPin,
342 g_APinDescription[PIN_WIRE_SCL].ulPinConfiguration);
343
344 NVIC_DisableIRQ(WIRE_ISR_ID);
345 NVIC_ClearPendingIRQ(WIRE_ISR_ID);
346 NVIC_SetPriority(WIRE_ISR_ID, 0);
347 NVIC_EnableIRQ(WIRE_ISR_ID);
348}*/
349
350
351TwoWire Wire(&sercom3);
352
353void SERCOM3_Handler(void) {
354 Wire.onService();
355}
356
357#endif
Note: See TracBrowser for help on using the repository browser.