Digital IO
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  if (_state != STATE_REP_START) {
55  start();
56  }
57  if (!write(addrRW)) {
58  _state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK;
59  return false;
60  }
61  _state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA;
62  return transferContinue(buf, nbytes, option);
63 }
64 //------------------------------------------------------------------------------
80 bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
81  uint8_t* p = reinterpret_cast<uint8_t*>(buf);
82  if (_state == STATE_RX_DATA) {
83  for (size_t i = 0; i < nbytes; i++) {
84  p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE);
85  }
86  } else if (_state == STATE_TX_DATA) {
87  for (size_t i = 0; i < nbytes; i++) {
88  if (!write(p[i])) {
89  _state = STATE_TX_DATA_NACK;
90  return false;
91  }
92  }
93  } else {
94  return false;
95  }
96  if (option == I2C_STOP) {
97  stop();
98  _state = STATE_STOP;
99  } else if (option == I2C_REP_START) {
100  start();
101  _state = STATE_STOP;
102  }
103  return true;
104 }
105 //==============================================================================
106 // WARNING don't change SoftI2cMaster unless you verify the change with a scope
107 //------------------------------------------------------------------------------
115 SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
116  begin(sclPin, sdaPin);
117 }
118 //------------------------------------------------------------------------------
126 void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
127  uint8_t port;
128 
129  // Get bit mask and address of scl registers.
130  _sclBit = digitalPinToBitMask(sclPin);
131  port = digitalPinToPort(sclPin);
132  _sclDDR = portModeRegister(port);
133  volatile uint8_t* sclOutReg = portOutputRegister(port);
134 
135  // Get bit mask and address of sda registers.
136  _sdaBit = digitalPinToBitMask(sdaPin);
137  port = digitalPinToPort(sdaPin);
138  _sdaDDR = portModeRegister(port);
139  _sdaInReg = portInputRegister(port);
140  volatile uint8_t* sdaOutReg = portOutputRegister(port);
141 
142  // Clear PORT bit for scl and sda.
143  uint8_t s = SREG;
144  noInterrupts();
145  *sclOutReg &= ~_sclBit;
146  *sdaOutReg &= ~_sdaBit;
147  SREG = s;
148 
149  // Set scl and sda high.
150  writeScl(HIGH);
151  writeSda(HIGH);
152 }
153 //------------------------------------------------------------------------------
154 /* Read a byte and send ACK if more reads follow else NACK to terminate read.
155  *
156  * @param[in] last Set true to terminate the read else false.
157  *
158  * @return The byte read from the I2C bus.
159  */
160 uint8_t SoftI2cMaster::read(uint8_t last) {
161  uint8_t b = 0;
162 
163  // Set sda to high Z mode for read.
164  writeSda(HIGH);
165  // Read a byte.
166  for (uint8_t i = 0; i < 8; i++) {
167  // Don't change this loop unless you verify the change with a scope.
168  b <<= 1;
169  sclDelay(16);
170  writeScl(HIGH);
171  sclDelay(12);
172  if (readSda()) b |= 1;
173  writeScl(LOW);
174  }
175  // send ACK or NACK
176  writeSda(last);
177  sclDelay(12);
178  writeScl(HIGH);
179  sclDelay(18);
180  writeScl(LOW);
181  writeSda(LOW);
182  return b;
183 }
184 //------------------------------------------------------------------------------
185 /* Issue a start condition. */
187  if (!readSda()) {
188  writeSda(HIGH);
189  writeScl(HIGH);
190  sclDelay(20);
191  }
192  writeSda(LOW);
193  sclDelay(20);
194  writeScl(LOW);
195 }
196 //------------------------------------------------------------------------------
197  /* Issue a stop condition. */
199  writeSda(LOW);
200  sclDelay(20);
201  writeScl(HIGH);
202  sclDelay(20);
203  writeSda(HIGH);
204  sclDelay(20);
205 }
206 //------------------------------------------------------------------------------
207 /*
208  * Write a byte.
209  *
210  * @param[in] data The byte to send.
211  *
212  * @return The value true, 1, if the slave returned an ACK or false for NACK.
213  */
214 bool SoftI2cMaster::write(uint8_t data) {
215  // write byte
216  for (uint8_t m = 0X80; m != 0; m >>= 1) {
217  // don't change this loop unless you verify the change with a scope
218  writeSda(m & data);
219  sclDelay(8);
220  writeScl(HIGH);
221  sclDelay(18);
222  writeScl(LOW);
223  }
224  sclDelay(8);
225  // Go to sda high Z mode for input.
226  writeSda(HIGH);
227  writeScl(HIGH);
228  sclDelay(16);
229 
230  // Get ACK or NACK.
231  uint8_t rtn = readSda();
232 
233  // pull scl low.
234  writeScl(LOW);
235 
236  // Pull sda low.
237  writeSda(LOW);
238  return rtn == 0;
239 }
240 #endif // __AVR__
241 
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