Softi2c with pull up enabled

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SoftI2C.cpp Source File

SoftI2C.cpp

00001 #include "SoftI2C.h"
00002 
00003 SoftI2C::SoftI2C(PinName sda, PinName scl) : _sda(sda), _scl(scl) {
00004     // Set defaults
00005     _sda.input();
00006     _scl.input();
00007     _sda.mode(PullUp);
00008     _scl.mode(PullUp);
00009   
00010     frequency(100000);
00011     
00012     active = false;
00013     
00014     }
00015     
00016 void SoftI2C::frequency(int hz) {
00017     delay_us = 1000000 / hz / 4; //delay is a quarter of the total period
00018 }
00019 
00020 int SoftI2C::read(int address, char *data, int length, bool repeated) {
00021     start();
00022     
00023     // Write address with LSB to one
00024     if (write(address | 0x01) == 0) {
00025         return 1;
00026     }  
00027     
00028     // Read the data
00029     for(int i = 0; i<length - 1; i++) {
00030         data[i] = read(1);
00031     }
00032     data[length-1] = read(0);
00033     
00034     if (repeated == false) {
00035         stop();
00036     }
00037     return 0;
00038 }
00039 
00040 int SoftI2C::write(int address, const char *data, int length, bool repeated) {
00041     start();
00042     
00043     // Write address with LSB to zero
00044     if (write(address & 0xFE) == 0) {
00045         return 1;
00046     }  
00047     
00048     // Write the data
00049     for(int i = 0; i<length; i++) {
00050         if(write(data[i]) == 0) {
00051             return 1;
00052         }
00053     }
00054     
00055     if (repeated == false) {
00056         stop();
00057     }
00058     return 0;
00059 }
00060 
00061 int SoftI2C::read(int ack) {
00062     int retval = 0;
00063     _scl.output();
00064     
00065     // Shift the bits out, msb first
00066     for (int i = 7; i>=0; i--) {
00067         //SCL low
00068         _scl.write(0);
00069         _sda.input();
00070         wait_us(delay_us);
00071         
00072         //read SDA
00073         retval |= _sda.read() << i;
00074         wait_us(delay_us);
00075         
00076         //SCL high again
00077         _scl.write(1);
00078         wait_us(delay_us << 1); //wait two delays
00079     }
00080     
00081     // Last cycle to set the ACK
00082     _scl.write(0);
00083     if ( ack ) {
00084         _sda.output();
00085         _sda.write(0);
00086     } else {
00087         _sda.input();
00088     }
00089     wait_us(delay_us << 1);
00090     
00091     _scl.write(1);
00092     wait_us(delay_us << 1);
00093 
00094     
00095     return retval;
00096 }
00097 
00098 int SoftI2C::write(int data) {
00099      _scl.output();
00100      
00101     // Shift the bits out, msb first
00102     for (int i = 7; i>=0; i--) {
00103         //SCL low
00104         _scl.write(0);
00105         wait_us(delay_us);
00106         
00107         //Change SDA depending on the bit
00108         if ( (data >> i) & 0x01 ) {
00109             _sda.input();
00110             _sda.mode(PullUp);
00111         } else {
00112             _sda.output();
00113             _sda.write(0);
00114         }
00115         wait_us(delay_us);
00116         
00117         //SCL high again
00118         _scl.write(1);
00119         wait_us(delay_us << 1); //wait two delays
00120     }
00121     
00122     // Last cycle to get the ACK
00123     _scl.write(0);
00124     wait_us(delay_us);
00125     
00126     _sda.input();
00127     _sda.mode(PullUp);
00128     wait_us(delay_us);
00129     
00130     _scl.write(1);
00131     wait_us(delay_us);
00132     int retval = ~_sda.read(); //Read the ack
00133     wait_us(delay_us);
00134     
00135     return retval;
00136 }
00137 
00138 void SoftI2C::start(void) {
00139     if (active) { //if repeated start
00140         //Set SDA high, toggle scl
00141         _sda.input();
00142         _sda.mode(PullUp);
00143         _scl.output();
00144         _scl.write(0);
00145         wait_us(delay_us << 1);
00146         _scl.write(1);
00147         wait_us(delay_us << 1);
00148     }
00149     // Pull SDA low
00150     _sda.output();
00151     _sda.write(0);
00152     wait_us(delay_us);
00153     active = true;
00154 }
00155 
00156 void SoftI2C::stop(void) {
00157     // Float SDA high
00158     _scl.output();
00159     _scl.write(0);
00160     _sda.output();
00161     _sda.write(0);
00162     wait_us(delay_us);
00163     _scl.input();
00164     _scl.mode(PullUp);
00165     wait_us(delay_us);
00166     _sda.input();
00167     _sda.mode(PullUp);
00168     wait_us(delay_us);
00169     
00170     active = false;
00171 }