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.
Diff: SoftI2C.cpp
- Revision:
- 0:fee70b6fe0e9
- Child:
- 1:05473196d133
diff -r 000000000000 -r fee70b6fe0e9 SoftI2C.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftI2C.cpp Tue Nov 22 20:45:35 2016 +0000
@@ -0,0 +1,166 @@
+#include "SoftI2C.h"
+
+SoftI2C::SoftI2C(PinName sda, PinName scl) : _sda(sda), _scl(scl) {
+ // Set defaults
+ _sda.mode(PullNone);
+ _scl.mode(PullNone);
+ _sda.input();
+ _scl.input();
+ frequency(100000);
+
+ active = false;
+
+ }
+
+void SoftI2C::frequency(int hz) {
+ delay_us = 1000000 / hz / 4; //delay is a quarter of the total period
+}
+
+int SoftI2C::read(int address, char *data, int length, bool repeated) {
+ start();
+
+ // Write address with LSB to one
+ if (write(address | 0x01) == 0) {
+ return 1;
+ }
+
+ // Read the data
+ for(int i = 0; i<length - 1; i++) {
+ data[i] = read(1);
+ }
+ data[length-1] = read(0);
+
+ if (repeated == false) {
+ stop();
+ }
+ return 0;
+}
+
+int SoftI2C::write(int address, const char *data, int length, bool repeated) {
+ start();
+
+ // Write address with LSB to zero
+ if (write(address & 0xFE) == 0) {
+ return 1;
+ }
+
+ // Write the data
+ for(int i = 0; i<length; i++) {
+ if(write(data[i]) == 0) {
+ return 1;
+ }
+ }
+
+ if (repeated == false) {
+ stop();
+ }
+ return 0;
+}
+
+int SoftI2C::read(int ack) {
+ int retval = 0;
+
+ // Shift the bits out, msb first
+ for (int i = 7; i>=0; i--) {
+ //SCL low
+ _scl.output();
+ _scl.write(0);
+ _sda.input();
+ wait_us(delay_us);
+
+ //read SDA
+ retval |= _sda.read() << i;
+ wait_us(delay_us);
+
+ //SCL high again
+ _scl.input();
+ wait_us(delay_us << 1); //wait two delays
+ }
+
+ // Last cycle to set the ACK
+ _scl.output();
+ _scl.write(0);
+ if ( ack ) {
+ _sda.output();
+ _sda.write(0);
+ } else {
+ _sda.input();
+ }
+ wait_us(delay_us << 1);
+
+ _scl.input();
+ wait_us(delay_us << 1);
+
+
+ return retval;
+}
+
+int SoftI2C::write(int data) {
+ // Shift the bits out, msb first
+ for (int i = 7; i>=0; i--) {
+ //SCL low
+ _scl.output();
+ _scl.write(0);
+ wait_us(delay_us);
+
+ //Change SDA depending on the bit
+ if ( (data >> i) & 0x01 ) {
+ _sda.input();
+ } else {
+ _sda.output();
+ _sda.write(0);
+ }
+ wait_us(delay_us);
+
+ //SCL high again
+ _scl.input();
+ wait_us(delay_us << 1); //wait two delays
+ }
+
+ // Last cycle to get the ACK
+ _scl.output();
+ _scl.write(0);
+ wait_us(delay_us);
+
+ _sda.input();
+ wait_us(delay_us);
+
+ _scl.input();
+ wait_us(delay_us);
+ int retval = ~_sda.read(); //Read the ack
+ wait_us(delay_us);
+
+ return retval;
+}
+
+void SoftI2C::start(void) {
+ if (active) { //if repeated start
+ //Set SDA high, toggle scl
+ _sda.input();
+ _scl.output();
+ _scl.write(0);
+ wait_us(delay_us << 1);
+ _scl.input();
+ wait_us(delay_us << 1);
+ }
+ // Pull SDA low
+ _sda.output();
+ _sda.write(0);
+ wait_us(delay_us);
+ active = true;
+}
+
+void SoftI2C::stop(void) {
+ // Float SDA high
+ _scl.output();
+ _scl.write(0);
+ _sda.output();
+ _sda.write(0);
+ wait_us(delay_us);
+ _scl.input();
+ wait_us(delay_us);
+ _sda.input();
+ wait_us(delay_us);
+
+ active = false;
+}
\ No newline at end of file