First release of a Software I2C implementation, Tested and confirmed to work with the BMP085 Barometric Pressure Sensor

Dependents:   SoftwareI2C_Test

mbed Library to use a software master i2c interface on any GPIO pins
Copyright (c) 2012 Christopher Pepper
Released under the MIT License: http://mbed.org/license/mit

Files at this revision

API Documentation at this revision

Comitter:
p3p
Date:
Sun Apr 01 22:52:47 2012 +0000
Parent:
1:6966eacc5914
Commit message:
Added the option to change the frequency (delay between GPIO toggles so blocking)

Changed in this revision

SoftwareI2C.cpp Show annotated file Show diff for this revision Revisions of this file
SoftwareI2C.h Show annotated file Show diff for this revision Revisions of this file
diff -r 6966eacc5914 -r 8670e78c4b63 SoftwareI2C.cpp
--- a/SoftwareI2C.cpp	Sun Apr 01 19:27:03 2012 +0000
+++ b/SoftwareI2C.cpp	Sun Apr 01 22:52:47 2012 +0000
@@ -1,211 +1,212 @@
-/* 
- * mbed Library to use a software master i2c interface on any GPIO pins
- * Copyright (c) 2012 Christopher Pepper
- * Released under the MIT License: http://mbed.org/license/mit
- */
-
-#include "SoftwareI2C.h"
-
-/**
- * @brief Initializes interface
- * @param sda GPIO pin to use as I2C SDA
- * @param scl GPIO pin to use as I2C SCL
- */
-
-SoftwareI2C::SoftwareI2C(PinName sda, PinName scl) : _sda(sda) , _scl(scl) {
-    _scl.output();
-    _scl.mode(OpenDrain);
-    _sda.output();
-    _sda.mode(OpenDrain);
-
-    _device_address = 0;
-
-    initialise();
-}
-
-SoftwareI2C::~SoftwareI2C() {
-
-}
-
-/**
- * @brief Read 1 or more bytes from the I2C slave
- * @param device_address The address of the device to read from
- * @param data An allocated array to read the data into
- * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data)
- */
-void SoftwareI2C::read(uint8_t device_address, uint8_t* data, uint8_t data_bytes) {
-    if (data == 0 || data_bytes == 0) return;
-
-    device_address = device_address | 0x01;
-    start();
-    putByte(device_address);
-    getAck();
-    for (int x = 0; x < data_bytes; ++x) {
-        data[x] = getByte();
-        if ( x < (data_bytes -1)) { //ack all but the final byte
-            giveAck();
-        }
-    }
-    stop();
-}
-
-/**
- * @brief Write 1 or more bytes to the I2C slave
- * @param device_address The address of the device to write to
- * @param data An array to write the data from
- * @param data_bytes Number of bytes to write from array
- */
-void SoftwareI2C::write(uint8_t device_address, uint8_t* data,  uint8_t data_bytes) {
-    if (data == 0 || data_bytes == 0) return;
-
-    device_address = device_address & 0xFE;
-    start();
-    putByte(device_address);
-    getAck();
-    for ( int x = 0; x < data_bytes; ++x ) {
-        putByte(data[x]);
-        getAck();
-    }
-    stop();
-}
-
-/**
- * @brief Write 1 byte to the I2C slave
- * @param device_address The address of the device to write to
- * @param byte The data to write
- */
-void SoftwareI2C::write(uint8_t device_address, uint8_t byte) {
-    device_address = device_address & 0xFE;
-    start();
-    putByte(device_address);
-    getAck();
-    putByte(byte);
-    getAck();
-    stop();
-}
-
-/**
- * @brief Read 1 or more bytes from the I2C slave at the specified memory address
- * @param device_address The address of the device to read from
- * @param start_address The memory address to read from
- * @param data The allocated array to read into
- * @param data_bytes The number of bytes to read
- */
-void SoftwareI2C::randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
-    if (data == 0 || data_bytes == 0) return;
-
-    device_address = device_address & 0xFE;
-    start();
-    putByte(device_address);
-    if (!getAck()) {
-        return;
-    }
-    putByte(start_address);
-    if (!getAck()) {
-        return;
-    }
-
-    device_address=device_address | 0x01;
-    start();
-    putByte(device_address);
-    if (!getAck()) {
-        return;
-    }
-    for ( int x = 0; x < data_bytes; ++x) {
-        data[x] = getByte();
-        if (x != (data_bytes - 1)) giveAck();
-    }
-    stop();
-}
-
-/**
- * @brief Write 1 byte to the I2C slave at the specified memory address
- * @param device_address The address of the device to write to
- * @param start_address The memory address to write to
- * @param byte The data to write
- */
-void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte) {
-    device_address = device_address & 0xFE;
-    start();
-    putByte(device_address);
-    getAck();
-    putByte(start_address);
-    getAck();
-    putByte(byte);
-    getAck();
-    stop();
-}
-
-/**
- * @brief Write 1 or more bytes to the I2C slave at the specified memory address
- * @param device_address The address of the device to write to
- * @param start_address The memory address to write to
- * @param data The data to write
- * @param data_bytes The number of bytes to write
- */
-void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
-    if (data == 0 || data_bytes == 0) return;
-
-    device_address = device_address & 0xFE;
-    start();
-    putByte(device_address);
-    getAck();
-    putByte(start_address);
-    getAck();
-    for ( int x = 0; x <= data_bytes; ++x ) {
-        putByte(data[x]);
-        getAck();
-    }
-    stop();
-}
-
-/**
- * @brief Read 2 bytes from the I2C slave at the specified memory address and return them as an 16bit unsigned integer
- * @param device_address The address of the device to read from
- * @param start_address The memory address to read from
- * @return MSB 16bit unsigned integer
- */
-uint16_t SoftwareI2C::read16(uint8_t device_address, uint8_t start_address) {
-    uint8_t short_array[2] = {0, 0};
-    randomRead(device_address, start_address, short_array, 2 );
-    uint16_t value = 0;
-    value = short_array[0] << 8;
-    value |= short_array[1];
-
-    return value;
-}
-
-/**
- * @brief Read 3 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
- * @param device_address The address of the device to read from
- * @param start_address The memory address to read from
- * @return MSB 32bit unsigned integer 
- */
-uint32_t SoftwareI2C::read24(uint8_t device_address, uint8_t start_address) {
-    uint8_t value_array[4] = {0, 0, 0};
-    randomRead(device_address, start_address, value_array, 3 );
-    uint32_t value = 0;
-    value = value_array[0] << 16;
-    value |= value_array[1] << 8;
-    value |= value_array[2];
-
-    return value;
-}
-
-/**
- * @brief Read 4 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
- * @param device_address The address of the device to read from
- * @param start_address The memory address to read from
- * @return MSB 32bit unsigned integer
- */
-uint32_t SoftwareI2C::read32(uint8_t device_address, uint8_t start_address) {
-    uint8_t value_array[4] = {0, 0, 0, 0};
-    randomRead(device_address, start_address, value_array, 4 );
-    uint32_t value = 0;
-    value = value_array[0] << 24;
-    value |= value_array[1] << 16;
-    value |= value_array[2] << 8;
-    value |= value_array[3];
-
-    return value;
+/* 
+ * mbed Library to use a software master i2c interface on any GPIO pins
+ * Copyright (c) 2012 Christopher Pepper
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "SoftwareI2C.h"
+
+/**
+ * @brief Initializes interface
+ * @param sda GPIO pin to use as I2C SDA
+ * @param scl GPIO pin to use as I2C SCL
+ */
+
+SoftwareI2C::SoftwareI2C(PinName sda, PinName scl) : _sda(sda) , _scl(scl) {
+    _scl.output();
+    _scl.mode(OpenDrain);
+    _sda.output();
+    _sda.mode(OpenDrain);
+
+    _device_address = 0;
+    _frequency_delay = 1;
+
+    initialise();
+}
+
+SoftwareI2C::~SoftwareI2C() {
+
+}
+
+/**
+ * @brief Read 1 or more bytes from the I2C slave
+ * @param device_address The address of the device to read from
+ * @param data An allocated array to read the data into
+ * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data)
+ */
+void SoftwareI2C::read(uint8_t device_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address | 0x01;
+    start();
+    putByte(device_address);
+    getAck();
+    for (int x = 0; x < data_bytes; ++x) {
+        data[x] = getByte();
+        if ( x < (data_bytes -1)) { //ack all but the final byte
+            giveAck();
+        }
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 or more bytes to the I2C slave
+ * @param device_address The address of the device to write to
+ * @param data An array to write the data from
+ * @param data_bytes Number of bytes to write from array
+ */
+void SoftwareI2C::write(uint8_t device_address, uint8_t* data,  uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    for ( int x = 0; x < data_bytes; ++x ) {
+        putByte(data[x]);
+        getAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 byte to the I2C slave
+ * @param device_address The address of the device to write to
+ * @param byte The data to write
+ */
+void SoftwareI2C::write(uint8_t device_address, uint8_t byte) {
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(byte);
+    getAck();
+    stop();
+}
+
+/**
+ * @brief Read 1 or more bytes from the I2C slave at the specified memory address
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @param data The allocated array to read into
+ * @param data_bytes The number of bytes to read
+ */
+void SoftwareI2C::randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    if (!getAck()) {
+        return;
+    }
+    putByte(start_address);
+    if (!getAck()) {
+        return;
+    }
+
+    device_address=device_address | 0x01;
+    start();
+    putByte(device_address);
+    if (!getAck()) {
+        return;
+    }
+    for ( int x = 0; x < data_bytes; ++x) {
+        data[x] = getByte();
+        if (x != (data_bytes - 1)) giveAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 byte to the I2C slave at the specified memory address
+ * @param device_address The address of the device to write to
+ * @param start_address The memory address to write to
+ * @param byte The data to write
+ */
+void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte) {
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(start_address);
+    getAck();
+    putByte(byte);
+    getAck();
+    stop();
+}
+
+/**
+ * @brief Write 1 or more bytes to the I2C slave at the specified memory address
+ * @param device_address The address of the device to write to
+ * @param start_address The memory address to write to
+ * @param data The data to write
+ * @param data_bytes The number of bytes to write
+ */
+void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(start_address);
+    getAck();
+    for ( int x = 0; x <= data_bytes; ++x ) {
+        putByte(data[x]);
+        getAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Read 2 bytes from the I2C slave at the specified memory address and return them as an 16bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 16bit unsigned integer
+ */
+uint16_t SoftwareI2C::read16(uint8_t device_address, uint8_t start_address) {
+    uint8_t short_array[2] = {0, 0};
+    randomRead(device_address, start_address, short_array, 2 );
+    uint16_t value = 0;
+    value = short_array[0] << 8;
+    value |= short_array[1];
+
+    return value;
+}
+
+/**
+ * @brief Read 3 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 32bit unsigned integer 
+ */
+uint32_t SoftwareI2C::read24(uint8_t device_address, uint8_t start_address) {
+    uint8_t value_array[4] = {0, 0, 0};
+    randomRead(device_address, start_address, value_array, 3 );
+    uint32_t value = 0;
+    value = value_array[0] << 16;
+    value |= value_array[1] << 8;
+    value |= value_array[2];
+
+    return value;
+}
+
+/**
+ * @brief Read 4 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 32bit unsigned integer
+ */
+uint32_t SoftwareI2C::read32(uint8_t device_address, uint8_t start_address) {
+    uint8_t value_array[4] = {0, 0, 0, 0};
+    randomRead(device_address, start_address, value_array, 4 );
+    uint32_t value = 0;
+    value = value_array[0] << 24;
+    value |= value_array[1] << 16;
+    value |= value_array[2] << 8;
+    value |= value_array[3];
+
+    return value;
 }
\ No newline at end of file
diff -r 6966eacc5914 -r 8670e78c4b63 SoftwareI2C.h
--- a/SoftwareI2C.h	Sun Apr 01 19:27:03 2012 +0000
+++ b/SoftwareI2C.h	Sun Apr 01 22:52:47 2012 +0000
@@ -33,6 +33,10 @@
     void setDeviceAddress(uint8_t address){
         _device_address = address;
     }
+    
+    void setFrequency(uint32_t frequency){
+        _frequency_delay = 1000000 / frequency;
+    }
 
     inline void initialise() {
         _scl.output();
@@ -40,7 +44,7 @@
         
         _sda = 1;
         _scl = 0;
-        wait_us(10);
+        wait_us(_frequency_delay);
 
         for ( int n = 0; n <= 3; ++n ) {
             stop();
@@ -50,33 +54,33 @@
 private:
     inline void start() {
         _sda.output();
-        wait_us(1);
+        wait_us(_frequency_delay);
         _scl = 1;
         _sda = 1;
-        wait_us(1);
+        wait_us(_frequency_delay);
         _sda = 0;
-        wait_us(1);
+        wait_us(_frequency_delay);
         _scl = 0;
-        wait_us(1);
+        wait_us(_frequency_delay);
     }
 
     inline void stop() {
         _sda.output();
-        wait_us(1);
+        wait_us(_frequency_delay);
         _sda = 0;
-        wait_us(1);
+        wait_us(_frequency_delay);
         _scl = 1;
-        wait_us(1);
+        wait_us(_frequency_delay);
         _sda = 1;
     }
 
     inline void putByte(uint8_t byte) {
         _sda.output();
         for ( int n = 8; n > 0; --n) {
-            wait_us(1);
+            wait_us(_frequency_delay);
             _sda = byte & (1 << (n-1));
             _scl = 1;
-            wait_us(1);
+            wait_us(_frequency_delay);
             _scl = 0;
         }
         _sda = 1;
@@ -88,15 +92,15 @@
         _sda.input();          //release the data line
         _sda.mode(OpenDrain);
         
-        wait_us(1);
+        wait_us(_frequency_delay);
 
         for ( int n = 8; n > 0; --n ) {
             _scl=1;            //set clock high
-            wait_us(1);
+            wait_us(_frequency_delay);
             byte |= _sda << (n-1); //read the bit
-            wait_us(1);
+            wait_us(_frequency_delay);
             _scl=0;            //set clock low
-            wait_us(1);
+            wait_us(_frequency_delay);
         }
 
         _sda.output();         //take data line back
@@ -106,10 +110,10 @@
 
     inline void giveAck() {
         _sda.output();
-        wait_us(1);
+        wait_us(_frequency_delay);
         _sda = 0;
         _scl = 1;
-        wait_us(1);
+        wait_us(_frequency_delay);
         _scl = 0;
         _sda = 1;
 
@@ -121,12 +125,12 @@
         _scl = 1;
         _sda.input();
         _sda.mode(OpenDrain);
-        wait_us(1);
+        wait_us(_frequency_delay);
         _scl = 0;
 
         if(_sda != 0){return false;}
 
-        wait_us(1);
+        wait_us(_frequency_delay);
         return true;
     }
 
@@ -134,6 +138,7 @@
     DigitalInOut _scl;
     
     uint8_t _device_address;
+    uint32_t _frequency_delay;
 };
 
 #endif
\ No newline at end of file