An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.
Dependencies: mbed FastIO FastPWM USBDevice
Fork of Pinscape_Controller by
BitBangI2C.cpp
00001 // Bit Bang BitBangI2C implementation for KL25Z 00002 // 00003 00004 #include "mbed.h" 00005 #include "BitBangI2C.h" 00006 00007 00008 // -------------------------------------------------------------------------- 00009 // 00010 // Debugging: 00011 // 00012 // 0 -> no debugging 00013 // 1 -> print (on console) error messages only 00014 // 2 -> print full diagnostics 00015 // 00016 // dprintf() = general debug diagnostics (printed only in case 2) 00017 // eprintf() = error diagnostics (printed in case 1 and above) 00018 // 00019 #define BBI2C_DEBUG 0 00020 #if BBI2C_DEBUG 00021 # define eprintf(...) printf(__VA_ARGS__) 00022 # if BBI2C_DEBUG >= 2 00023 # define dprintf(...) printf(__VA_ARGS__) 00024 # else 00025 # define dprintf(...) 00026 # endif 00027 static const char *dbgbytes(const uint8_t *bytes, size_t len) 00028 { 00029 static char buf[128]; 00030 char *p = buf; 00031 for (int i = 0 ; i < len && p + 4 < buf + sizeof(buf) ; ++i) 00032 { 00033 if (i > 0) *p++ = ','; 00034 sprintf(p, "%02x", bytes[i]); 00035 p += 2; 00036 } 00037 *p = '\0'; 00038 return buf; 00039 } 00040 #else 00041 # define dprintf(...) 00042 # define eprintf(...) 00043 #endif 00044 00045 // -------------------------------------------------------------------------- 00046 // 00047 // Bit-bang I2C implementation 00048 // 00049 BitBangI2C::BitBangI2C(PinName sda, PinName scl, bool internalPullup) : 00050 sdaPin(sda, internalPullup), sclPin(scl, internalPullup) 00051 { 00052 // set the default frequency to 100kHz 00053 frequency(100000); 00054 00055 // we're initially in a stop 00056 inStop = true; 00057 } 00058 00059 void BitBangI2C::frequency(uint32_t freq) 00060 { 00061 // figure the clock time per cycle 00062 clkPeriod_us = 1000000/freq; 00063 00064 // Figure wait times according to frequency 00065 if (freq <= 100000) 00066 { 00067 // standard mode I2C bus - up to 100kHz 00068 00069 // nanosecond parameters 00070 tLow = calcHiResWaitTime(4700); 00071 tHigh = calcHiResWaitTime(4000); 00072 tHdSta = calcHiResWaitTime(4000); 00073 tSuSta = calcHiResWaitTime(4700); 00074 tSuSto = calcHiResWaitTime(4000); 00075 tAck = calcHiResWaitTime(300); 00076 tSuDat = calcHiResWaitTime(250); 00077 tBuf = calcHiResWaitTime(4700); 00078 } 00079 else if (freq <= 400000) 00080 { 00081 // fast mode I2C - up to 400kHz 00082 00083 // nanosecond parameters 00084 tLow = calcHiResWaitTime(1300); 00085 tHigh = calcHiResWaitTime(600); 00086 tHdSta = calcHiResWaitTime(600); 00087 tSuSta = calcHiResWaitTime(600); 00088 tSuSto = calcHiResWaitTime(600); 00089 tAck = calcHiResWaitTime(100); 00090 tSuDat = calcHiResWaitTime(100); 00091 tBuf = calcHiResWaitTime(1300); 00092 } 00093 else 00094 { 00095 // fast mode plus - up to 1MHz 00096 00097 // nanosecond parameters 00098 tLow = calcHiResWaitTime(500); 00099 tHigh = calcHiResWaitTime(260); 00100 tHdSta = calcHiResWaitTime(260); 00101 tSuSta = calcHiResWaitTime(260); 00102 tSuSto = calcHiResWaitTime(260); 00103 tAck = calcHiResWaitTime(50); 00104 tSuDat = calcHiResWaitTime(50); 00105 tBuf = calcHiResWaitTime(500); 00106 } 00107 } 00108 00109 void BitBangI2C::start() 00110 { 00111 // check to see if we're starting after a stop, or if this is a 00112 // repeated start 00113 if (inStop) 00114 { 00115 // in a stop - make sure we waited for the minimum hold time 00116 hiResWait(tBuf); 00117 } 00118 else 00119 { 00120 // repeated start - take data high 00121 sdaHi(); 00122 hiResWait(tSuDat); 00123 00124 // take clock high 00125 sclHi(); 00126 00127 // wait for the minimum setup period 00128 hiResWait(tSuSta); 00129 } 00130 00131 // take data low 00132 sdaLo(); 00133 00134 // wait for the setup period and take clock low 00135 hiResWait(tHdSta); 00136 sclLo(); 00137 00138 // wait for the low period 00139 hiResWait(tLow); 00140 00141 // no longer in a stop 00142 inStop = false; 00143 } 00144 00145 void BitBangI2C::stop() 00146 { 00147 // if we're not in a stop, enter one 00148 if (!inStop) 00149 { 00150 // take SDA low 00151 sdaLo(); 00152 00153 // take SCL high 00154 sclHi(); 00155 hiResWait(tSuSto); 00156 00157 // take SDA high 00158 sdaHi(); 00159 00160 // we're in a stop 00161 inStop = true; 00162 } 00163 } 00164 00165 bool BitBangI2C::wait(uint32_t timeout_us) 00166 { 00167 // set up a timer to monitor the timeout period 00168 Timer t; 00169 t.start(); 00170 00171 // wait for an ACK 00172 for (;;) 00173 { 00174 // if SDA is low, it's an ACK 00175 if (!sdaPin.read()) 00176 return true; 00177 00178 // if we've reached the timeout, abort 00179 if (t.read_us() > timeout_us) 00180 return false; 00181 } 00182 } 00183 00184 void BitBangI2C::reset() 00185 { 00186 // write out 9 '1' bits 00187 for (int i = 0 ; i < 9 ; ++i) 00188 writeBit(1); 00189 00190 // issue a start sequence 00191 start(); 00192 00193 // take the clock high 00194 sclHi(); 00195 00196 // wait for a few clock cycles 00197 wait_us(4*clkPeriod_us); 00198 } 00199 00200 int BitBangI2C::write(uint8_t addr, const uint8_t *data, size_t len, bool repeated) 00201 { 00202 dprintf("i2c.write, addr=%02x [%s] %srepeat\r\n", 00203 addr, dbgbytes(data, len), repeated ? "" : "no "); 00204 00205 // send the start signal 00206 start(); 00207 00208 // send the address with the R/W bit set to WRITE (0) 00209 if (write(addr)) 00210 { 00211 eprintf(". i2c.write, address write failed, addr=%02x [%s] %srepeat\r\n", 00212 addr, dbgbytes(data, len), repeated ? "": "no "); 00213 return -1; 00214 } 00215 00216 // send the data bytes 00217 for (int i = 0 ; i < len ; ++i) 00218 { 00219 if (write(data[i])) 00220 { 00221 eprintf(". i2c.write, write failed at byte %d, addr=%02x [%s] %srepeat\r\n", 00222 i, addr, dbgbytes(data, len), repeated ? "" : "no "); 00223 return -2; 00224 } 00225 } 00226 00227 // send the stop, unless the start is to be repeated 00228 if (!repeated) 00229 stop(); 00230 00231 // success 00232 return 0; 00233 } 00234 00235 int BitBangI2C::read(uint8_t addr, uint8_t *data, size_t len, bool repeated) 00236 { 00237 dprintf("i2c.read, addr=%02x\r\n", addr); 00238 00239 // send the start signal 00240 start(); 00241 00242 // send the address with the R/W bit set to READ (1) 00243 if (write(addr | 0x01)) 00244 { 00245 eprintf(". i2c.read, read addr write failed, addr=%02x [%s] %srepeat\r\n", 00246 addr, dbgbytes(data, len), repeated ? "" : "no "); 00247 return -1; 00248 } 00249 00250 // Read the data. Send an ACK after each byte except the last, 00251 // where we send a NAK. 00252 for ( ; len != 0 ; --len, ++data) 00253 *data = read(len > 1); 00254 00255 // send the stop signal, unless a repeated start is indicated 00256 if (!repeated) 00257 stop(); 00258 00259 // success 00260 return 0; 00261 } 00262 00263 int BitBangI2C::write(uint8_t data) 00264 { 00265 // write the bits, most significant first 00266 for (int i = 0 ; i < 8 ; ++i, data <<= 1) 00267 writeBit(data & 0x80); 00268 00269 // release SDA so the device can control it 00270 sdaHi(); 00271 00272 // read the ACK bit 00273 int ack = readBit(); 00274 00275 // take SDA low again 00276 sdaLo(); 00277 00278 // return success if ACK was 0 00279 return ack; 00280 } 00281 00282 int BitBangI2C::read(bool ack) 00283 { 00284 // take SDA high before reading 00285 sdaHi(); 00286 00287 // read 8 bits, most significant first 00288 uint8_t data = 0; 00289 for (int i = 0 ; i < 8 ; ++i) 00290 data = (data << 1) | readBit(); 00291 00292 // switch to output mode and send the ACK bit 00293 writeBit(!ack); 00294 00295 // release SDA 00296 sdaHi(); 00297 00298 // return the data byte we read 00299 return data; 00300 } 00301 00302 int BitBangI2C::readBit() 00303 { 00304 // take the clock high (actually, release it to the pull-up) 00305 sclHi(); 00306 00307 // Wait (within reason) for it to actually read as high. The device 00308 // can intentionally pull the clock line low to tell us to wait while 00309 // it's working on preparing the data for us. 00310 int t = 0; 00311 do 00312 { 00313 // if the clock is high, we're ready to go 00314 if (sclPin.read()) 00315 { 00316 // wait for the data setup time 00317 hiResWait(tSuDat); 00318 00319 // read the bit 00320 bool bit = sdaPin.read(); 00321 00322 // take the clock low again 00323 sclLo(); 00324 hiResWait(tLow); 00325 00326 // return the bit 00327 return bit; 00328 } 00329 } 00330 while (t++ < 100000); 00331 00332 // we timed out 00333 eprintf("i2c.readBit, clock stretching timeout\r\n"); 00334 return 0; 00335 }
Generated on Wed Jul 13 2022 03:30:10 by 1.7.2