Digital IO
Arduino/libraries/DigitalIO/SoftI2cMaster.cpp
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  */
00028 #include <SoftI2cMaster.h>
00029 //------------------------------------------------------------------------------
00051 bool I2cMasterBase::transfer(uint8_t addrRW,
00052                              void *buf, size_t nbytes, uint8_t option) {
00053   uint8_t* p = reinterpret_cast<uint8_t*>(buf);
00054   if (_state != STATE_REP_START) {
00055     start();
00056   }
00057   if (!write(addrRW)) {
00058     _state = addrRW & I2C_READ ? STATE_RX_ADDR_NACK : STATE_TX_ADDR_NACK;
00059     return false;
00060   }
00061   _state = addrRW & I2C_READ ? STATE_RX_DATA : STATE_TX_DATA;
00062   return transferContinue(buf, nbytes, option);
00063 }
00064 //------------------------------------------------------------------------------
00080 bool I2cMasterBase::transferContinue(void *buf, size_t nbytes, uint8_t option) {
00081   uint8_t* p = reinterpret_cast<uint8_t*>(buf);
00082   if (_state == STATE_RX_DATA) {
00083     for (size_t i = 0; i < nbytes; i++) {
00084         p[i] = read(i == (nbytes - 1) && option != I2C_CONTINUE);
00085     }
00086   } else if (_state == STATE_TX_DATA) {
00087     for (size_t i = 0; i < nbytes; i++) {
00088       if (!write(p[i])) {
00089         _state = STATE_TX_DATA_NACK;
00090         return false;
00091       }
00092     }
00093   } else {
00094     return false;
00095   }
00096   if (option == I2C_STOP) {
00097     stop();
00098     _state = STATE_STOP;
00099   } else if (option == I2C_REP_START) {
00100     start();
00101     _state = STATE_STOP;
00102   }
00103   return true;
00104 }
00105 //==============================================================================
00106 // WARNING don't change SoftI2cMaster unless you verify the change with a scope
00107 //------------------------------------------------------------------------------
00115 SoftI2cMaster::SoftI2cMaster(uint8_t sclPin, uint8_t sdaPin) {
00116   begin(sclPin, sdaPin);
00117 }
00118 //------------------------------------------------------------------------------
00126 void SoftI2cMaster::begin(uint8_t sclPin, uint8_t sdaPin) {
00127   uint8_t port;
00128 
00129   // Get bit mask and address of scl registers.
00130   _sclBit = digitalPinToBitMask(sclPin);
00131   port = digitalPinToPort(sclPin);
00132   _sclDDR = portModeRegister(port);
00133   volatile uint8_t* sclOutReg = portOutputRegister(port);
00134 
00135   // Get bit mask and address of sda registers.
00136   _sdaBit = digitalPinToBitMask(sdaPin);
00137   port = digitalPinToPort(sdaPin);
00138   _sdaDDR = portModeRegister(port);
00139   _sdaInReg = portInputRegister(port);
00140   volatile uint8_t* sdaOutReg = portOutputRegister(port);
00141 
00142   // Clear PORT bit for scl and sda.
00143   uint8_t s = SREG;
00144   noInterrupts();
00145   *sclOutReg &= ~_sclBit;
00146   *sdaOutReg &= ~_sdaBit;
00147   SREG = s;
00148 
00149   // Set scl and sda high.
00150   writeScl(HIGH);
00151   writeSda(HIGH);
00152 }
00153 //------------------------------------------------------------------------------
00154 /* Read a byte and send ACK if more reads follow else NACK to terminate read.
00155  *
00156  * @param[in] last Set true to terminate the read else false.
00157  *
00158  * @return The byte read from the I2C bus.
00159  */
00160 uint8_t SoftI2cMaster::read(uint8_t last) {
00161   uint8_t b = 0;
00162 
00163   // Set sda to high Z mode for read.
00164   writeSda(HIGH);
00165   // Read a byte.
00166   for (uint8_t i = 0; i < 8; i++) {
00167     // Don't change this loop unless you verify the change with a scope.
00168     b <<= 1;
00169     sclDelay(16);
00170     writeScl(HIGH);
00171     sclDelay(12);
00172     if (readSda()) b |= 1;
00173     writeScl(LOW);
00174   }
00175   // send ACK or NACK
00176   writeSda(last);
00177   sclDelay(12);
00178   writeScl(HIGH);
00179   sclDelay(18);
00180   writeScl(LOW);
00181   writeSda(LOW);
00182   return b;
00183 }
00184 //------------------------------------------------------------------------------
00185 /* Issue a start condition. */
00186 void SoftI2cMaster::start() {
00187   if (!readSda()) {
00188     writeSda(HIGH);
00189     writeScl(HIGH);
00190     sclDelay(20);
00191   }
00192   writeSda(LOW);
00193   sclDelay(20);
00194   writeScl(LOW);
00195 }
00196 //------------------------------------------------------------------------------
00197   /*  Issue a stop condition. */
00198 void SoftI2cMaster::stop(void) {
00199   writeSda(LOW);
00200   sclDelay(20);
00201   writeScl(HIGH);
00202   sclDelay(20);
00203   writeSda(HIGH);
00204   sclDelay(20);
00205 }
00206 //------------------------------------------------------------------------------
00207 /*
00208  * Write a byte.
00209  *
00210  * @param[in] data The byte to send.
00211  *
00212  * @return The value true, 1, if the slave returned an ACK or false for NACK.
00213  */
00214 bool SoftI2cMaster::write(uint8_t data) {
00215   // write byte
00216   for (uint8_t m = 0X80; m != 0; m >>= 1) {
00217     // don't change this loop unless you verify the change with a scope
00218     writeSda(m & data);
00219     sclDelay(8);
00220     writeScl(HIGH);
00221     sclDelay(18);
00222     writeScl(LOW);
00223   }
00224   sclDelay(8);
00225   // Go to sda high Z mode for input.
00226   writeSda(HIGH);
00227   writeScl(HIGH);
00228   sclDelay(16);
00229 
00230   // Get ACK or NACK.
00231   uint8_t rtn = readSda();
00232 
00233   // pull scl low.
00234   writeScl(LOW);
00235 
00236   // Pull sda low.
00237   writeSda(LOW);
00238   return rtn == 0;
00239 }
 All Classes Files Functions Variables Defines