Digital IO
 All Classes Files Functions Variables Macros Groups Pages
SoftI2cMaster.cpp
Go to the documentation of this file.
1 /* Arduino DigitalIO Library
2  * Copyright (C) 2013 by William Greiman
3  *
4  * This file is part of the Arduino DigitalIO Library
5  *
6  * This Library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This Library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with the Arduino DigitalIO Library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20  #if defined(__AVR__) || defined(DOXYGEN) // AVR only
21 
29 #include <SoftI2cMaster.h>
30 //------------------------------------------------------------------------------
52 bool I2cMasterBase::transfer(uint8_t addrRW,
53  void *buf, size_t nbytes, uint8_t option) {
54  uint8_t* p = reinterpret_cast<uint8_t*>(buf);
55  if (_state != STATE_REP_START) {
56  start();
57  }
58  if (!write(addrRW)) {
59  _state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK;
60  return false;
61  }
62  _state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA;
63  return transferContinue(buf, nbytes, option);
64 }
65 //------------------------------------------------------------------------------
81 bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
82  uint8_t* p = reinterpret_cast<uint8_t*>(buf);
83  if (_state == STATE_RX_DATA) {
84  for (size_t i = 0; i < nbytes; i++) {
85  p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE);
86  }
87  } else if (_state == STATE_TX_DATA) {
88  for (size_t i = 0; i < nbytes; i++) {
89  if (!write(p[i])) {
90  _state = STATE_TX_DATA_NACK;
91  return false;
92  }
93  }
94  } else {
95  return false;
96  }
97  if (option == I2C_STOP) {
98  stop();
99  _state = STATE_STOP;
100  } else if (option == I2C_REP_START) {
101  start();
102  _state = STATE_STOP;
103  }
104  return true;
105 }
106 //==============================================================================
107 // WARNING don't change SoftI2cMaster unless you verify the change with a scope
108 //------------------------------------------------------------------------------
116 SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
117  begin(sclPin, sdaPin);
118 }
119 //------------------------------------------------------------------------------
127 void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
128  uint8_t port;
129 
130  // Get bit mask and address of scl registers.
131  _sclBit = digitalPinToBitMask(sclPin);
132  port = digitalPinToPort(sclPin);
133  _sclDDR = portModeRegister(port);
134  volatile uint8_t* sclOutReg = portOutputRegister(port);
135 
136  // Get bit mask and address of sda registers.
137  _sdaBit = digitalPinToBitMask(sdaPin);
138  port = digitalPinToPort(sdaPin);
139  _sdaDDR = portModeRegister(port);
140  _sdaInReg = portInputRegister(port);
141  volatile uint8_t* sdaOutReg = portOutputRegister(port);
142 
143  // Clear PORT bit for scl and sda.
144  uint8_t s = SREG;
145  noInterrupts();
146  *sclOutReg &= ~_sclBit;
147  *sdaOutReg &= ~_sdaBit;
148  SREG = s;
149 
150  // Set scl and sda high.
151  writeScl(HIGH);
152  writeSda(HIGH);
153 }
154 //------------------------------------------------------------------------------
155 /* Read a byte and send ACK if more reads follow else NACK to terminate read.
156  *
157  * @param[in] last Set true to terminate the read else false.
158  *
159  * @return The byte read from the I2C bus.
160  */
161 uint8_t SoftI2cMaster::read(uint8_t last) {
162  uint8_t b = 0;
163 
164  // Set sda to high Z mode for read.
165  writeSda(HIGH);
166  // Read a byte.
167  for (uint8_t i = 0; i < 8; i++) {
168  // Don't change this loop unless you verify the change with a scope.
169  b <<= 1;
170  sclDelay(16);
171  writeScl(HIGH);
172  sclDelay(12);
173  if (readSda()) b |= 1;
174  writeScl(LOW);
175  }
176  // send ACK or NACK
177  writeSda(last);
178  sclDelay(12);
179  writeScl(HIGH);
180  sclDelay(18);
181  writeScl(LOW);
182  writeSda(LOW);
183  return b;
184 }
185 //------------------------------------------------------------------------------
186 /* Issue a start condition. */
188  if (!readSda()) {
189  writeSda(HIGH);
190  writeScl(HIGH);
191  sclDelay(20);
192  }
193  writeSda(LOW);
194  sclDelay(20);
195  writeScl(LOW);
196 }
197 //------------------------------------------------------------------------------
198  /* Issue a stop condition. */
200  writeSda(LOW);
201  sclDelay(20);
202  writeScl(HIGH);
203  sclDelay(20);
204  writeSda(HIGH);
205  sclDelay(20);
206 }
207 //------------------------------------------------------------------------------
208 /*
209  * Write a byte.
210  *
211  * @param[in] data The byte to send.
212  *
213  * @return The value true, 1, if the slave returned an ACK or false for NACK.
214  */
215 bool SoftI2cMaster::write(uint8_t data) {
216  // write byte
217  for (uint8_t m = 0X80; m != 0; m >>= 1) {
218  // don't change this loop unless you verify the change with a scope
219  writeSda(m & data);
220  sclDelay(8);
221  writeScl(HIGH);
222  sclDelay(18);
223  writeScl(LOW);
224  }
225  sclDelay(8);
226  // Go to sda high Z mode for input.
227  writeSda(HIGH);
228  writeScl(HIGH);
229  sclDelay(16);
230 
231  // Get ACK or NACK.
232  uint8_t rtn = readSda();
233 
234  // pull scl low.
235  writeScl(LOW);
236 
237  // Pull sda low.
238  writeSda(LOW);
239  return rtn == 0;
240 }
241 #endif __AVR__
242 
virtual uint8_t read(uint8_t last)=0
bool transfer(uint8_t addressRW, void *buf, size_t nbyte, uint8_t option=I2C_STOP)
const uint8_t STATE_TX_DATA_NACK
Definition: SoftI2cMaster.h:56
const uint8_t I2C_REP_START
Definition: I2cConstants.h:42
uint8_t read(uint8_t last)
AVR Software I2C library.
const uint8_t STATE_TX_ADDR_NACK
Definition: SoftI2cMaster.h:54
const uint8_t I2C_STOP
Definition: I2cConstants.h:38
virtual void stop()=0
const uint8_t STATE_RX_DATA
Definition: SoftI2cMaster.h:45
const uint8_t STATE_REP_START
Definition: SoftI2cMaster.h:42
bool write(uint8_t b)
virtual void start()=0
void stop(void)
const uint8_t STATE_STOP
Definition: SoftI2cMaster.h:39
bool transferContinue(void *buf, size_t nbyte, uint8_t option=I2C_STOP)
const uint8_t STATE_TX_DATA
Definition: SoftI2cMaster.h:48
const uint8_t I2C_READ
Definition: I2cConstants.h:51
const uint8_t I2C_CONTINUE
Definition: I2cConstants.h:34
void begin(uint8_t sclPin, uint8_t sdaPin)
virtual bool write(uint8_t data)=0
const uint8_t STATE_RX_ADDR_NACK
Definition: SoftI2cMaster.h:51