Softi2c with pull up enabled

Committer:
Sissors
Date:
Mon Nov 28 19:55:30 2016 +0000
Revision:
1:05473196d133
Parent:
0:fee70b6fe0e9
Child:
2:7e8f03569953
Changed scl to push pull during transactions
; More efficient and we don't support clock stretching anyway
; Using OpenDrain mode maybe for future, however is device dependent

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:fee70b6fe0e9 1 #include "SoftI2C.h"
Sissors 0:fee70b6fe0e9 2
Sissors 0:fee70b6fe0e9 3 SoftI2C::SoftI2C(PinName sda, PinName scl) : _sda(sda), _scl(scl) {
Sissors 0:fee70b6fe0e9 4 // Set defaults
Sissors 0:fee70b6fe0e9 5 _sda.mode(PullNone);
Sissors 0:fee70b6fe0e9 6 _scl.mode(PullNone);
Sissors 0:fee70b6fe0e9 7 _sda.input();
Sissors 0:fee70b6fe0e9 8 _scl.input();
Sissors 0:fee70b6fe0e9 9 frequency(100000);
Sissors 0:fee70b6fe0e9 10
Sissors 0:fee70b6fe0e9 11 active = false;
Sissors 0:fee70b6fe0e9 12
Sissors 0:fee70b6fe0e9 13 }
Sissors 0:fee70b6fe0e9 14
Sissors 0:fee70b6fe0e9 15 void SoftI2C::frequency(int hz) {
Sissors 0:fee70b6fe0e9 16 delay_us = 1000000 / hz / 4; //delay is a quarter of the total period
Sissors 0:fee70b6fe0e9 17 }
Sissors 0:fee70b6fe0e9 18
Sissors 0:fee70b6fe0e9 19 int SoftI2C::read(int address, char *data, int length, bool repeated) {
Sissors 0:fee70b6fe0e9 20 start();
Sissors 0:fee70b6fe0e9 21
Sissors 0:fee70b6fe0e9 22 // Write address with LSB to one
Sissors 0:fee70b6fe0e9 23 if (write(address | 0x01) == 0) {
Sissors 0:fee70b6fe0e9 24 return 1;
Sissors 0:fee70b6fe0e9 25 }
Sissors 0:fee70b6fe0e9 26
Sissors 0:fee70b6fe0e9 27 // Read the data
Sissors 0:fee70b6fe0e9 28 for(int i = 0; i<length - 1; i++) {
Sissors 0:fee70b6fe0e9 29 data[i] = read(1);
Sissors 0:fee70b6fe0e9 30 }
Sissors 0:fee70b6fe0e9 31 data[length-1] = read(0);
Sissors 0:fee70b6fe0e9 32
Sissors 0:fee70b6fe0e9 33 if (repeated == false) {
Sissors 0:fee70b6fe0e9 34 stop();
Sissors 0:fee70b6fe0e9 35 }
Sissors 0:fee70b6fe0e9 36 return 0;
Sissors 0:fee70b6fe0e9 37 }
Sissors 0:fee70b6fe0e9 38
Sissors 0:fee70b6fe0e9 39 int SoftI2C::write(int address, const char *data, int length, bool repeated) {
Sissors 0:fee70b6fe0e9 40 start();
Sissors 0:fee70b6fe0e9 41
Sissors 0:fee70b6fe0e9 42 // Write address with LSB to zero
Sissors 0:fee70b6fe0e9 43 if (write(address & 0xFE) == 0) {
Sissors 0:fee70b6fe0e9 44 return 1;
Sissors 0:fee70b6fe0e9 45 }
Sissors 0:fee70b6fe0e9 46
Sissors 0:fee70b6fe0e9 47 // Write the data
Sissors 0:fee70b6fe0e9 48 for(int i = 0; i<length; i++) {
Sissors 0:fee70b6fe0e9 49 if(write(data[i]) == 0) {
Sissors 0:fee70b6fe0e9 50 return 1;
Sissors 0:fee70b6fe0e9 51 }
Sissors 0:fee70b6fe0e9 52 }
Sissors 0:fee70b6fe0e9 53
Sissors 0:fee70b6fe0e9 54 if (repeated == false) {
Sissors 0:fee70b6fe0e9 55 stop();
Sissors 0:fee70b6fe0e9 56 }
Sissors 0:fee70b6fe0e9 57 return 0;
Sissors 0:fee70b6fe0e9 58 }
Sissors 0:fee70b6fe0e9 59
Sissors 0:fee70b6fe0e9 60 int SoftI2C::read(int ack) {
Sissors 0:fee70b6fe0e9 61 int retval = 0;
Sissors 1:05473196d133 62 _scl.output();
Sissors 0:fee70b6fe0e9 63
Sissors 0:fee70b6fe0e9 64 // Shift the bits out, msb first
Sissors 0:fee70b6fe0e9 65 for (int i = 7; i>=0; i--) {
Sissors 0:fee70b6fe0e9 66 //SCL low
Sissors 0:fee70b6fe0e9 67 _scl.write(0);
Sissors 0:fee70b6fe0e9 68 _sda.input();
Sissors 0:fee70b6fe0e9 69 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 70
Sissors 0:fee70b6fe0e9 71 //read SDA
Sissors 0:fee70b6fe0e9 72 retval |= _sda.read() << i;
Sissors 0:fee70b6fe0e9 73 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 74
Sissors 0:fee70b6fe0e9 75 //SCL high again
Sissors 1:05473196d133 76 _scl.write(1);
Sissors 0:fee70b6fe0e9 77 wait_us(delay_us << 1); //wait two delays
Sissors 0:fee70b6fe0e9 78 }
Sissors 0:fee70b6fe0e9 79
Sissors 0:fee70b6fe0e9 80 // Last cycle to set the ACK
Sissors 0:fee70b6fe0e9 81 _scl.write(0);
Sissors 0:fee70b6fe0e9 82 if ( ack ) {
Sissors 0:fee70b6fe0e9 83 _sda.output();
Sissors 0:fee70b6fe0e9 84 _sda.write(0);
Sissors 0:fee70b6fe0e9 85 } else {
Sissors 0:fee70b6fe0e9 86 _sda.input();
Sissors 0:fee70b6fe0e9 87 }
Sissors 0:fee70b6fe0e9 88 wait_us(delay_us << 1);
Sissors 0:fee70b6fe0e9 89
Sissors 1:05473196d133 90 _scl.write(1);
Sissors 0:fee70b6fe0e9 91 wait_us(delay_us << 1);
Sissors 0:fee70b6fe0e9 92
Sissors 0:fee70b6fe0e9 93
Sissors 0:fee70b6fe0e9 94 return retval;
Sissors 0:fee70b6fe0e9 95 }
Sissors 0:fee70b6fe0e9 96
Sissors 0:fee70b6fe0e9 97 int SoftI2C::write(int data) {
Sissors 1:05473196d133 98 _scl.output();
Sissors 1:05473196d133 99
Sissors 0:fee70b6fe0e9 100 // Shift the bits out, msb first
Sissors 0:fee70b6fe0e9 101 for (int i = 7; i>=0; i--) {
Sissors 0:fee70b6fe0e9 102 //SCL low
Sissors 0:fee70b6fe0e9 103 _scl.write(0);
Sissors 0:fee70b6fe0e9 104 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 105
Sissors 0:fee70b6fe0e9 106 //Change SDA depending on the bit
Sissors 0:fee70b6fe0e9 107 if ( (data >> i) & 0x01 ) {
Sissors 0:fee70b6fe0e9 108 _sda.input();
Sissors 0:fee70b6fe0e9 109 } else {
Sissors 0:fee70b6fe0e9 110 _sda.output();
Sissors 0:fee70b6fe0e9 111 _sda.write(0);
Sissors 0:fee70b6fe0e9 112 }
Sissors 0:fee70b6fe0e9 113 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 114
Sissors 0:fee70b6fe0e9 115 //SCL high again
Sissors 1:05473196d133 116 _scl.write(1);
Sissors 0:fee70b6fe0e9 117 wait_us(delay_us << 1); //wait two delays
Sissors 0:fee70b6fe0e9 118 }
Sissors 0:fee70b6fe0e9 119
Sissors 0:fee70b6fe0e9 120 // Last cycle to get the ACK
Sissors 0:fee70b6fe0e9 121 _scl.write(0);
Sissors 0:fee70b6fe0e9 122 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 123
Sissors 0:fee70b6fe0e9 124 _sda.input();
Sissors 0:fee70b6fe0e9 125 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 126
Sissors 1:05473196d133 127 _scl.write(1);
Sissors 0:fee70b6fe0e9 128 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 129 int retval = ~_sda.read(); //Read the ack
Sissors 0:fee70b6fe0e9 130 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 131
Sissors 0:fee70b6fe0e9 132 return retval;
Sissors 0:fee70b6fe0e9 133 }
Sissors 0:fee70b6fe0e9 134
Sissors 0:fee70b6fe0e9 135 void SoftI2C::start(void) {
Sissors 0:fee70b6fe0e9 136 if (active) { //if repeated start
Sissors 0:fee70b6fe0e9 137 //Set SDA high, toggle scl
Sissors 0:fee70b6fe0e9 138 _sda.input();
Sissors 0:fee70b6fe0e9 139 _scl.output();
Sissors 0:fee70b6fe0e9 140 _scl.write(0);
Sissors 0:fee70b6fe0e9 141 wait_us(delay_us << 1);
Sissors 1:05473196d133 142 _scl.write(1);
Sissors 0:fee70b6fe0e9 143 wait_us(delay_us << 1);
Sissors 0:fee70b6fe0e9 144 }
Sissors 0:fee70b6fe0e9 145 // Pull SDA low
Sissors 0:fee70b6fe0e9 146 _sda.output();
Sissors 0:fee70b6fe0e9 147 _sda.write(0);
Sissors 0:fee70b6fe0e9 148 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 149 active = true;
Sissors 0:fee70b6fe0e9 150 }
Sissors 0:fee70b6fe0e9 151
Sissors 0:fee70b6fe0e9 152 void SoftI2C::stop(void) {
Sissors 0:fee70b6fe0e9 153 // Float SDA high
Sissors 0:fee70b6fe0e9 154 _scl.output();
Sissors 0:fee70b6fe0e9 155 _scl.write(0);
Sissors 0:fee70b6fe0e9 156 _sda.output();
Sissors 0:fee70b6fe0e9 157 _sda.write(0);
Sissors 0:fee70b6fe0e9 158 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 159 _scl.input();
Sissors 0:fee70b6fe0e9 160 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 161 _sda.input();
Sissors 0:fee70b6fe0e9 162 wait_us(delay_us);
Sissors 0:fee70b6fe0e9 163
Sissors 0:fee70b6fe0e9 164 active = false;
Sissors 0:fee70b6fe0e9 165 }