Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SoftI2C by
SoftI2C.cpp@1:05473196d133, 2016-11-28 (annotated)
- Committer:
- Sissors
- Date:
- Mon Nov 28 19:55:30 2016 +0000
- Revision:
- 1:05473196d133
- Parent:
- 0:fee70b6fe0e9
- Child:
- 2:b174177b2bf2
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?
| User | Revision | Line number | New 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 | } |
