Softi2c with pull up enabled

Committer:
wkleunen
Date:
Wed May 29 06:37:22 2019 +0000
Revision:
2:7e8f03569953
Parent:
1:05473196d133
Enable pull up on softi2c

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