Digital IO
Arduino/libraries/DigitalIO/SoftI2cMaster.h
Go to the documentation of this file.
00001 /* Arduino DigitalIO Library
00002  * Copyright (C) 2013 by William Greiman
00003  *
00004  * This file is part of the Arduino DigitalIO Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino DigitalIO Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 #ifndef SOFT_I2C_MASTER_H
00021 #define SOFT_I2C_MASTER_H
00022 
00030 #if ARDUINO < 100
00031 #error Requires Arduino 1.0 or greater.
00032 #else  // ARDUINO
00033 #include <Arduino.h>
00034 #endif  // ARDUINO
00035 #include <util/delay_basic.h>
00036 #include <DigitalPin.h>
00037 #include <I2cConstants.h>
00038 //------------------------------------------------------------------------------
00039 // State codes.
00040 
00042 const uint8_t STATE_STOP = 0;
00043 
00045 const uint8_t STATE_REP_START = 1;
00046 
00048 const uint8_t STATE_RX_DATA = 2;
00049 
00051 const uint8_t STATE_TX_DATA = 3;
00052 
00054 const uint8_t STATE_RX_ADDR_NACK = 4;
00055 
00057 const uint8_t STATE_TX_ADDR_NACK = 5;
00059 const uint8_t STATE_TX_DATA_NACK = 6;
00060 //==============================================================================
00065 class I2cMasterBase {
00066  public:
00067   I2cMasterBase() : _state(STATE_STOP) {}
00078   virtual uint8_t read(uint8_t last) = 0;
00079 
00085   virtual void start() = 0;
00091   virtual void stop() = 0;
00092 
00093   bool transfer(uint8_t addressRW, void *buf,
00094                 size_t nbyte, uint8_t option = I2C_STOP);
00095 
00096   bool transferContinue(void *buf, size_t nbyte, uint8_t option = I2C_STOP);
00104   virtual bool write(uint8_t data) = 0;
00105 
00106  private:
00107   uint8_t _state;
00108 };
00109 //==============================================================================
00114 class SoftI2cMaster : public I2cMasterBase {
00115  public:
00116   SoftI2cMaster() {}
00117   SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin);
00118   void begin(uint8_t sclPin, uint8_t sdaPin);
00119   uint8_t read(uint8_t last);
00120   void start();
00121   void stop(void);
00122   bool write(uint8_t b);
00123 
00124  private:
00125   uint8_t _sclBit;
00126   uint8_t _sdaBit;
00127   volatile uint8_t* _sclDDR;
00128   volatile uint8_t* _sdaDDR;
00129   volatile uint8_t* _sdaInReg;
00130   //----------------------------------------------------------------------------
00131   bool readSda() {return *_sdaInReg & _sdaBit;}
00132   //----------------------------------------------------------------------------
00133   void sclDelay(uint8_t n) {_delay_loop_1(n);}
00134   //----------------------------------------------------------------------------
00135   bool writeScl(bool value) {
00136     uint8_t s = SREG;
00137     noInterrupts();
00138     if (value == LOW) {
00139       // Pull scl low.
00140       *_sclDDR |= _sclBit;
00141     } else {
00142       // Put scl in high Z  input mode.
00143       *_sclDDR &= ~_sclBit;
00144     }
00145     SREG = s;
00146   }
00147   //----------------------------------------------------------------------------
00148   bool writeSda(bool value) {
00149     uint8_t s = SREG;
00150     noInterrupts();
00151     if (value == LOW) {
00152       // Pull sda low.
00153       *_sdaDDR |= _sdaBit;
00154     } else {
00155       // Put sda in high Z input mode.
00156       *_sdaDDR &= ~_sdaBit;
00157     }
00158     SREG = s;
00159   }
00160 };
00161 //==============================================================================
00162 // Template based fast software I2C
00163 //------------------------------------------------------------------------------
00168 template<uint8_t sclPin, uint8_t sdaPin>
00169 class FastI2cMaster : public I2cMasterBase {
00170  public:
00171   //----------------------------------------------------------------------------
00172   FastI2cMaster() {
00173     begin();
00174   }
00175   //----------------------------------------------------------------------------
00177   void begin() {
00178     fastDigitalWrite(sclPin, LOW);
00179     fastDigitalWrite(sdaPin, LOW);
00180 
00181     sclWrite(HIGH);
00182     sdaWrite(HIGH);
00183   }
00184   //----------------------------------------------------------------------------
00185   uint8_t read(uint8_t last) {
00186     uint8_t data = 0;
00187     sdaWrite(HIGH);
00188 
00189     readBit(7, &data);
00190     readBit(6, &data);
00191     readBit(5, &data);
00192     readBit(4, &data);
00193     readBit(3, &data);
00194     readBit(2, &data);
00195     readBit(1, &data);
00196     readBit(0, &data);
00197 
00198     // send ACK or NACK
00199     sdaWrite(last);
00200     sclDelay(4);
00201     sclWrite(HIGH);
00202     sclDelay(6);
00203     sclWrite(LOW);
00204     sdaWrite(LOW);
00205     return data;
00206   }
00207   //----------------------------------------------------------------------------
00208   void start() {
00209     if (!fastDigitalRead(sdaPin)) {
00210       // It's a repeat start.
00211       sdaWrite(HIGH);
00212       sclDelay(8);
00213       sclWrite(HIGH);
00214       sclDelay(8);
00215     }
00216     sdaWrite(LOW);
00217     sclDelay(8);
00218     sclWrite(LOW);
00219     sclDelay(8);
00220   }
00221   //----------------------------------------------------------------------------
00222   void stop(void) {
00223     sdaWrite(LOW);
00224     sclDelay(8);
00225     sclWrite(HIGH);
00226     sclDelay(8);
00227     sdaWrite(HIGH);
00228     sclDelay(8);
00229   }
00230   //----------------------------------------------------------------------------
00231   bool write(uint8_t data) {
00232     // write byte
00233     writeBit(7, data);
00234     writeBit(6, data);
00235     writeBit(5, data);
00236     writeBit(4, data);
00237     writeBit(3, data);
00238     writeBit(2, data);
00239     writeBit(1, data);
00240     writeBit(0, data);
00241 
00242     // get ACK or NACK
00243     sdaWrite(HIGH);
00244 
00245     sclWrite(HIGH);
00246     sclDelay(5);
00247     bool rtn = fastDigitalRead(sdaPin);
00248     sclWrite(LOW);
00249     sdaWrite(LOW);
00250     return rtn == 0;
00251   }
00252 
00253  private:
00254   //----------------------------------------------------------------------------
00255   inline __attribute__((always_inline))
00256   void sclWrite(bool value) {fastPinMode(sclPin, !value);}
00257   //----------------------------------------------------------------------------
00258   inline __attribute__((always_inline))
00259   void sdaWrite(bool value) {fastPinMode(sdaPin, !value);}
00260   //----------------------------------------------------------------------------
00261   inline __attribute__((always_inline))
00262   void readBit(uint8_t bit, uint8_t* data) {
00263     sclWrite(HIGH);
00264     sclDelay(5);
00265     if (fastDigitalRead(sdaPin)) *data |= 1 << bit;
00266     sclWrite(LOW);
00267     if (bit) sclDelay(6);
00268   }
00269   //----------------------------------------------------------------------------
00270   void sclDelay(uint8_t n) {_delay_loop_1(n);}
00271   //----------------------------------------------------------------------------
00272   inline __attribute__((always_inline))
00273   void writeBit(uint8_t bit, uint8_t data) {
00274     uint8_t mask = 1 << bit;
00275     sdaWrite(data & mask);
00276     sclWrite(HIGH);
00277     sclDelay(5);
00278     sclWrite(LOW);
00279     sclDelay(5);
00280   }
00281 };
00282 #endif  // SOFT_I2C_MASTER_H
00283 
 All Classes Files Functions Variables Defines