MySensors Library & Examples  2.3.2-42-g423b9d7
SoftI2cMaster.h
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 #ifndef SOFT_I2C_MASTER_H
21 #define SOFT_I2C_MASTER_H
22 
30 #if defined(__AVR__) || defined(DOXYGEN) // AVR only
31 #include <Arduino.h>
32 #include <util/delay_basic.h>
33 #include "DigitalPin.h"
34 #include "I2cConstants.h"
35 //------------------------------------------------------------------------------
36 // State codes.
37 
39 const uint8_t STATE_STOP = 0;
40 
42 const uint8_t STATE_REP_START = 1;
43 
45 const uint8_t STATE_RX_DATA = 2;
46 
48 const uint8_t STATE_TX_DATA = 3;
49 
51 const uint8_t STATE_RX_ADDR_NACK = 4;
52 
54 const uint8_t STATE_TX_ADDR_NACK = 5;
56 const uint8_t STATE_TX_DATA_NACK = 6;
57 //==============================================================================
63 {
64 public:
65  I2cMasterBase() : _state(STATE_STOP) {}
76  virtual uint8_t read(uint8_t last) = 0;
77 
83  virtual void start() = 0;
89  virtual void stop() = 0;
90 
91  bool transfer(uint8_t addressRW, void *buf,
92  size_t nbyte, uint8_t option = I2C_STOP);
93 
94  bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP);
102  virtual bool write(uint8_t data) = 0;
103 
104 private:
105  uint8_t _state;
106 };
107 //==============================================================================
113 {
114 public:
115  SoftI2cMaster() {}
116  SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin);
117  void begin(uint8_t sclPin, uint8_t sdaPin);
118  uint8_t read(uint8_t last);
119  void start();
120  void stop(void);
121  bool write(uint8_t b);
122 
123 private:
124  uint8_t _sclBit;
125  uint8_t _sdaBit;
126  volatile uint8_t* _sclDDR;
127  volatile uint8_t* _sdaDDR;
128  volatile uint8_t* _sdaInReg;
129  //----------------------------------------------------------------------------
130  bool readSda()
131  {
132  return *_sdaInReg & _sdaBit;
133  }
134  //----------------------------------------------------------------------------
135  void sclDelay(uint8_t n)
136  {
137  _delay_loop_1(n);
138  }
139  //----------------------------------------------------------------------------
140  void writeScl(bool value)
141  {
142  uint8_t s = SREG;
143  noInterrupts();
144  if (value == LOW) {
145  // Pull scl low.
146  *_sclDDR |= _sclBit;
147  } else {
148  // Put scl in high Z input mode.
149  *_sclDDR &= ~_sclBit;
150  }
151  SREG = s;
152  }
153  //----------------------------------------------------------------------------
154  void writeSda(bool value)
155  {
156  uint8_t s = SREG;
157  noInterrupts();
158  if (value == LOW) {
159  // Pull sda low.
160  *_sdaDDR |= _sdaBit;
161  } else {
162  // Put sda in high Z input mode.
163  *_sdaDDR &= ~_sdaBit;
164  }
165  SREG = s;
166  }
167 };
168 //==============================================================================
169 // Template based fast software I2C
170 //------------------------------------------------------------------------------
175 template<uint8_t sclPin, uint8_t sdaPin>
177 {
178 public:
179  //----------------------------------------------------------------------------
180  FastI2cMaster()
181  {
182  begin();
183  }
184  //----------------------------------------------------------------------------
186  void begin()
187  {
188  fastDigitalWrite(sclPin, LOW);
189  fastDigitalWrite(sdaPin, LOW);
190 
191  sclWrite(HIGH);
192  sdaWrite(HIGH);
193  }
194  //----------------------------------------------------------------------------
195  uint8_t read(uint8_t last)
196  {
197  uint8_t data = 0;
198  sdaWrite(HIGH);
199 
200  readBit(7, &data);
201  readBit(6, &data);
202  readBit(5, &data);
203  readBit(4, &data);
204  readBit(3, &data);
205  readBit(2, &data);
206  readBit(1, &data);
207  readBit(0, &data);
208 
209  // send ACK or NACK
210  sdaWrite(last);
211  sclDelay(4);
212  sclWrite(HIGH);
213  sclDelay(6);
214  sclWrite(LOW);
215  sdaWrite(LOW);
216  return data;
217  }
218  //----------------------------------------------------------------------------
219  void start()
220  {
221  if (!fastDigitalRead(sdaPin)) {
222  // It's a repeat start.
223  sdaWrite(HIGH);
224  sclDelay(8);
225  sclWrite(HIGH);
226  sclDelay(8);
227  }
228  sdaWrite(LOW);
229  sclDelay(8);
230  sclWrite(LOW);
231  sclDelay(8);
232  }
233  //----------------------------------------------------------------------------
234  void stop(void)
235  {
236  sdaWrite(LOW);
237  sclDelay(8);
238  sclWrite(HIGH);
239  sclDelay(8);
240  sdaWrite(HIGH);
241  sclDelay(8);
242  }
243  //----------------------------------------------------------------------------
244  bool write(uint8_t data)
245  {
246  // write byte
247  writeBit(7, data);
248  writeBit(6, data);
249  writeBit(5, data);
250  writeBit(4, data);
251  writeBit(3, data);
252  writeBit(2, data);
253  writeBit(1, data);
254  writeBit(0, data);
255 
256  // get ACK or NACK
257  sdaWrite(HIGH);
258 
259  sclWrite(HIGH);
260  sclDelay(5);
261  bool rtn = fastDigitalRead(sdaPin);
262  sclWrite(LOW);
263  sdaWrite(LOW);
264  return rtn == 0;
265  }
266 
267 private:
268  //----------------------------------------------------------------------------
269  inline __attribute__((always_inline))
270  void sclWrite(bool value)
271  {
272  fastDdrWrite(sclPin, !value);
273  }
274  //----------------------------------------------------------------------------
275  inline __attribute__((always_inline))
276  void sdaWrite(bool value)
277  {
278  fastDdrWrite(sdaPin, !value);
279  }
280  //----------------------------------------------------------------------------
281  inline __attribute__((always_inline))
282  void readBit(uint8_t bit, uint8_t* data)
283  {
284  sclWrite(HIGH);
285  sclDelay(5);
286  if (fastDigitalRead(sdaPin)) {
287  *data |= 1 << bit;
288  }
289  sclWrite(LOW);
290  if (bit) {
291  sclDelay(6);
292  }
293  }
294  //----------------------------------------------------------------------------
295  void sclDelay(uint8_t n)
296  {
297  _delay_loop_1(n);
298  }
299  //----------------------------------------------------------------------------
300  inline __attribute__((always_inline))
301  void writeBit(uint8_t bit, uint8_t data)
302  {
303  uint8_t mask = 1 << bit;
304  sdaWrite(data & mask);
305  sclWrite(HIGH);
306  sclDelay(5);
307  sclWrite(LOW);
308  sclDelay(5);
309  }
310 };
311 #endif // __AVR__
312 #endif // SOFT_I2C_MASTER_H
313 
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:654
HIGH
#define HIGH
Definition: bcm2835.h:572
FastI2cMaster::begin
void begin()
Definition: SoftI2cMaster.h:186
STATE_RX_DATA
const uint8_t STATE_RX_DATA
Definition: SoftI2cMaster.h:45
I2C_STOP
const uint8_t I2C_STOP
Definition: I2cConstants.h:38
STATE_TX_DATA
const uint8_t STATE_TX_DATA
Definition: SoftI2cMaster.h:48
SoftI2cMaster::read
uint8_t read(uint8_t last)
SoftI2cMaster::write
bool write(uint8_t b)
LOW
#define LOW
Definition: bcm2835.h:574
STATE_TX_ADDR_NACK
const uint8_t STATE_TX_ADDR_NACK
Definition: SoftI2cMaster.h:54
STATE_STOP
const uint8_t STATE_STOP
Definition: SoftI2cMaster.h:39
I2cConstants.h
Two Wire Interface constants.
FastI2cMaster::write
bool write(uint8_t data)
Definition: SoftI2cMaster.h:244
STATE_TX_DATA_NACK
const uint8_t STATE_TX_DATA_NACK
Definition: SoftI2cMaster.h:56
last
uint8_t last
8 bit - Id of last node this message passed
Definition: MyMessage.h:334
SoftI2cMaster
AVR Software I2C master class.
Definition: SoftI2cMaster.h:112
STATE_RX_ADDR_NACK
const uint8_t STATE_RX_ADDR_NACK
Definition: SoftI2cMaster.h:51
I2cMasterBase::stop
virtual void stop()=0
I2cMasterBase::start
virtual void start()=0
FastI2cMaster::start
void start()
Definition: SoftI2cMaster.h:219
I2cMasterBase::read
virtual uint8_t read(uint8_t last)=0
FastI2cMaster
AVR Fast software I2C master class.
Definition: SoftI2cMaster.h:176
__attribute__
FW config structure, stored in eeprom.
Definition: MyOTAFirmwareUpdate.h:117
SoftI2cMaster::stop
void stop(void)
SoftI2cMaster::start
void start()
I2cMasterBase::write
virtual bool write(uint8_t data)=0
STATE_REP_START
const uint8_t STATE_REP_START
Definition: SoftI2cMaster.h:42
FastI2cMaster::stop
void stop(void)
Definition: SoftI2cMaster.h:234
FastI2cMaster::read
uint8_t read(uint8_t last)
Definition: SoftI2cMaster.h:195
DigitalPin.h
Fast Digital Pin functions.
I2cMasterBase
Base class for FastI2cMaster, SoftI2cMaster.
Definition: SoftI2cMaster.h:62