Digital IO
|
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