ArduinoLibs
|
00001 /* 00002 * Copyright (C) 2012 Southern Storm Software, Pty Ltd. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00019 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00020 * DEALINGS IN THE SOFTWARE. 00021 */ 00022 00023 #include "SoftI2C.h" 00024 #if defined(ARDUINO) && ARDUINO >= 100 00025 #include <Arduino.h> 00026 #else 00027 #include <WProgram.h> 00028 #endif 00029 00045 #define i2cDelay() delayMicroseconds(5) 00046 00050 SoftI2C::SoftI2C(uint8_t dataPin, uint8_t clockPin) 00051 : _dataPin(dataPin) 00052 , _clockPin(clockPin) 00053 , started(false) 00054 , acked(true) 00055 , inWrite(false) 00056 , readCount(0) 00057 { 00058 // Initially set the CLOCK and DATA lines to be outputs in the high state. 00059 pinMode(_clockPin, OUTPUT); 00060 pinMode(_dataPin, OUTPUT); 00061 digitalWrite(_clockPin, HIGH); 00062 digitalWrite(_dataPin, HIGH); 00063 } 00064 00065 unsigned int SoftI2C::maxTransferSize() const 00066 { 00067 return 0xFFFF; 00068 } 00069 00070 void SoftI2C::start() 00071 { 00072 pinMode(_dataPin, OUTPUT); 00073 if (started) { 00074 // Already started, so send a restart condition. 00075 digitalWrite(_dataPin, HIGH); 00076 digitalWrite(_clockPin, HIGH); 00077 i2cDelay(); 00078 } 00079 digitalWrite(_dataPin, LOW); 00080 i2cDelay(); 00081 digitalWrite(_clockPin, LOW); 00082 i2cDelay(); 00083 started = true; 00084 acked = true; 00085 } 00086 00087 void SoftI2C::stop() 00088 { 00089 pinMode(_dataPin, OUTPUT); 00090 digitalWrite(_dataPin, LOW); 00091 digitalWrite(_clockPin, HIGH); 00092 i2cDelay(); 00093 digitalWrite(_dataPin, HIGH); 00094 i2cDelay(); 00095 started = false; 00096 inWrite = false; 00097 } 00098 00099 #define I2C_WRITE 0x00 00100 #define I2C_WRITE10 0xF0 00101 #define I2C_READ 0x01 00102 #define I2C_READ10 0xF1 00103 00104 void SoftI2C::startWrite(unsigned int address) 00105 { 00106 start(); 00107 inWrite = true; 00108 if (address < 0x80) { 00109 // 7-bit address. 00110 write((uint8_t)((address << 1) | I2C_WRITE)); 00111 } else { 00112 // 10-bit address. 00113 write((uint8_t)(((address >> 7) & 0x06)) | I2C_WRITE10); 00114 write((uint8_t)address); 00115 } 00116 } 00117 00118 void SoftI2C::write(uint8_t value) 00119 { 00120 uint8_t mask = 0x80; 00121 while (mask != 0) { 00122 writeBit((value & mask) != 0); 00123 mask >>= 1; 00124 } 00125 if (readBit()) // 0: ACK, 1: NACK 00126 acked = false; 00127 } 00128 00129 bool SoftI2C::endWrite() 00130 { 00131 stop(); 00132 return acked; 00133 } 00134 00135 bool SoftI2C::startRead(unsigned int address, unsigned int count) 00136 { 00137 start(); 00138 inWrite = false; 00139 if (address < 0x80) { 00140 // 7-bit address. 00141 write((uint8_t)((address << 1) | I2C_READ)); 00142 } else { 00143 // 10-bit address. 00144 write((uint8_t)(((address >> 7) & 0x06)) | I2C_READ10); 00145 write((uint8_t)address); 00146 } 00147 if (!acked) { 00148 readCount = 0; 00149 return false; 00150 } 00151 readCount = count; 00152 return true; 00153 } 00154 00155 unsigned int SoftI2C::available() 00156 { 00157 return readCount; 00158 } 00159 00160 uint8_t SoftI2C::read() 00161 { 00162 uint8_t value = 0; 00163 for (uint8_t bit = 0; bit < 8; ++bit) 00164 value = (value << 1) | readBit(); 00165 if (readCount > 1) { 00166 // More bytes left to read - send an ACK. 00167 writeBit(false); 00168 --readCount; 00169 } else { 00170 // Last byte - send the NACK and a stop condition. 00171 writeBit(true); 00172 stop(); 00173 readCount = 0; 00174 } 00175 return value; 00176 } 00177 00178 void SoftI2C::writeBit(bool bit) 00179 { 00180 pinMode(_dataPin, OUTPUT); 00181 if (bit) 00182 digitalWrite(_dataPin, HIGH); 00183 else 00184 digitalWrite(_dataPin, LOW); 00185 i2cDelay(); 00186 digitalWrite(_clockPin, HIGH); 00187 i2cDelay(); 00188 digitalWrite(_clockPin, LOW); 00189 i2cDelay(); 00190 } 00191 00192 bool SoftI2C::readBit() 00193 { 00194 pinMode(_dataPin, INPUT); 00195 digitalWrite(_dataPin, HIGH); 00196 digitalWrite(_clockPin, HIGH); 00197 bool bit = digitalRead(_dataPin); 00198 i2cDelay(); 00199 digitalWrite(_clockPin, LOW); 00200 i2cDelay(); 00201 return bit; 00202 }