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

Committer:
p3p
Date:
Sun Apr 01 19:27:03 2012 +0000
Revision:
1:6966eacc5914
Parent:
0:6f6cfcdfe3d8
Child:
2:8670e78c4b63
Documentation Fix

Who changed what in which revision?

UserRevisionLine numberNew contents of line
p3p 0:6f6cfcdfe3d8 1 /*
p3p 0:6f6cfcdfe3d8 2 * mbed Library to use a software master i2c interface on any GPIO pins
p3p 0:6f6cfcdfe3d8 3 * Copyright (c) 2012 Christopher Pepper
p3p 0:6f6cfcdfe3d8 4 * Released under the MIT License: http://mbed.org/license/mit
p3p 0:6f6cfcdfe3d8 5 */
p3p 0:6f6cfcdfe3d8 6
p3p 0:6f6cfcdfe3d8 7 #include "SoftwareI2C.h"
p3p 0:6f6cfcdfe3d8 8
p3p 1:6966eacc5914 9 /**
p3p 0:6f6cfcdfe3d8 10 * @brief Initializes interface
p3p 0:6f6cfcdfe3d8 11 * @param sda GPIO pin to use as I2C SDA
p3p 0:6f6cfcdfe3d8 12 * @param scl GPIO pin to use as I2C SCL
p3p 0:6f6cfcdfe3d8 13 */
p3p 0:6f6cfcdfe3d8 14
p3p 0:6f6cfcdfe3d8 15 SoftwareI2C::SoftwareI2C(PinName sda, PinName scl) : _sda(sda) , _scl(scl) {
p3p 0:6f6cfcdfe3d8 16 _scl.output();
p3p 0:6f6cfcdfe3d8 17 _scl.mode(OpenDrain);
p3p 0:6f6cfcdfe3d8 18 _sda.output();
p3p 0:6f6cfcdfe3d8 19 _sda.mode(OpenDrain);
p3p 0:6f6cfcdfe3d8 20
p3p 0:6f6cfcdfe3d8 21 _device_address = 0;
p3p 0:6f6cfcdfe3d8 22
p3p 0:6f6cfcdfe3d8 23 initialise();
p3p 0:6f6cfcdfe3d8 24 }
p3p 0:6f6cfcdfe3d8 25
p3p 0:6f6cfcdfe3d8 26 SoftwareI2C::~SoftwareI2C() {
p3p 0:6f6cfcdfe3d8 27
p3p 0:6f6cfcdfe3d8 28 }
p3p 0:6f6cfcdfe3d8 29
p3p 1:6966eacc5914 30 /**
p3p 0:6f6cfcdfe3d8 31 * @brief Read 1 or more bytes from the I2C slave
p3p 0:6f6cfcdfe3d8 32 * @param device_address The address of the device to read from
p3p 0:6f6cfcdfe3d8 33 * @param data An allocated array to read the data into
p3p 0:6f6cfcdfe3d8 34 * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data)
p3p 0:6f6cfcdfe3d8 35 */
p3p 0:6f6cfcdfe3d8 36 void SoftwareI2C::read(uint8_t device_address, uint8_t* data, uint8_t data_bytes) {
p3p 0:6f6cfcdfe3d8 37 if (data == 0 || data_bytes == 0) return;
p3p 0:6f6cfcdfe3d8 38
p3p 0:6f6cfcdfe3d8 39 device_address = device_address | 0x01;
p3p 0:6f6cfcdfe3d8 40 start();
p3p 0:6f6cfcdfe3d8 41 putByte(device_address);
p3p 0:6f6cfcdfe3d8 42 getAck();
p3p 0:6f6cfcdfe3d8 43 for (int x = 0; x < data_bytes; ++x) {
p3p 0:6f6cfcdfe3d8 44 data[x] = getByte();
p3p 0:6f6cfcdfe3d8 45 if ( x < (data_bytes -1)) { //ack all but the final byte
p3p 0:6f6cfcdfe3d8 46 giveAck();
p3p 0:6f6cfcdfe3d8 47 }
p3p 0:6f6cfcdfe3d8 48 }
p3p 0:6f6cfcdfe3d8 49 stop();
p3p 0:6f6cfcdfe3d8 50 }
p3p 0:6f6cfcdfe3d8 51
p3p 1:6966eacc5914 52 /**
p3p 0:6f6cfcdfe3d8 53 * @brief Write 1 or more bytes to the I2C slave
p3p 0:6f6cfcdfe3d8 54 * @param device_address The address of the device to write to
p3p 0:6f6cfcdfe3d8 55 * @param data An array to write the data from
p3p 0:6f6cfcdfe3d8 56 * @param data_bytes Number of bytes to write from array
p3p 0:6f6cfcdfe3d8 57 */
p3p 0:6f6cfcdfe3d8 58 void SoftwareI2C::write(uint8_t device_address, uint8_t* data, uint8_t data_bytes) {
p3p 0:6f6cfcdfe3d8 59 if (data == 0 || data_bytes == 0) return;
p3p 0:6f6cfcdfe3d8 60
p3p 0:6f6cfcdfe3d8 61 device_address = device_address & 0xFE;
p3p 0:6f6cfcdfe3d8 62 start();
p3p 0:6f6cfcdfe3d8 63 putByte(device_address);
p3p 0:6f6cfcdfe3d8 64 getAck();
p3p 0:6f6cfcdfe3d8 65 for ( int x = 0; x < data_bytes; ++x ) {
p3p 0:6f6cfcdfe3d8 66 putByte(data[x]);
p3p 0:6f6cfcdfe3d8 67 getAck();
p3p 0:6f6cfcdfe3d8 68 }
p3p 0:6f6cfcdfe3d8 69 stop();
p3p 0:6f6cfcdfe3d8 70 }
p3p 0:6f6cfcdfe3d8 71
p3p 1:6966eacc5914 72 /**
p3p 0:6f6cfcdfe3d8 73 * @brief Write 1 byte to the I2C slave
p3p 0:6f6cfcdfe3d8 74 * @param device_address The address of the device to write to
p3p 0:6f6cfcdfe3d8 75 * @param byte The data to write
p3p 0:6f6cfcdfe3d8 76 */
p3p 0:6f6cfcdfe3d8 77 void SoftwareI2C::write(uint8_t device_address, uint8_t byte) {
p3p 0:6f6cfcdfe3d8 78 device_address = device_address & 0xFE;
p3p 0:6f6cfcdfe3d8 79 start();
p3p 0:6f6cfcdfe3d8 80 putByte(device_address);
p3p 0:6f6cfcdfe3d8 81 getAck();
p3p 0:6f6cfcdfe3d8 82 putByte(byte);
p3p 0:6f6cfcdfe3d8 83 getAck();
p3p 0:6f6cfcdfe3d8 84 stop();
p3p 0:6f6cfcdfe3d8 85 }
p3p 0:6f6cfcdfe3d8 86
p3p 1:6966eacc5914 87 /**
p3p 0:6f6cfcdfe3d8 88 * @brief Read 1 or more bytes from the I2C slave at the specified memory address
p3p 0:6f6cfcdfe3d8 89 * @param device_address The address of the device to read from
p3p 0:6f6cfcdfe3d8 90 * @param start_address The memory address to read from
p3p 0:6f6cfcdfe3d8 91 * @param data The allocated array to read into
p3p 0:6f6cfcdfe3d8 92 * @param data_bytes The number of bytes to read
p3p 0:6f6cfcdfe3d8 93 */
p3p 0:6f6cfcdfe3d8 94 void SoftwareI2C::randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
p3p 0:6f6cfcdfe3d8 95 if (data == 0 || data_bytes == 0) return;
p3p 0:6f6cfcdfe3d8 96
p3p 0:6f6cfcdfe3d8 97 device_address = device_address & 0xFE;
p3p 0:6f6cfcdfe3d8 98 start();
p3p 0:6f6cfcdfe3d8 99 putByte(device_address);
p3p 0:6f6cfcdfe3d8 100 if (!getAck()) {
p3p 0:6f6cfcdfe3d8 101 return;
p3p 0:6f6cfcdfe3d8 102 }
p3p 0:6f6cfcdfe3d8 103 putByte(start_address);
p3p 0:6f6cfcdfe3d8 104 if (!getAck()) {
p3p 0:6f6cfcdfe3d8 105 return;
p3p 0:6f6cfcdfe3d8 106 }
p3p 0:6f6cfcdfe3d8 107
p3p 0:6f6cfcdfe3d8 108 device_address=device_address | 0x01;
p3p 0:6f6cfcdfe3d8 109 start();
p3p 0:6f6cfcdfe3d8 110 putByte(device_address);
p3p 0:6f6cfcdfe3d8 111 if (!getAck()) {
p3p 0:6f6cfcdfe3d8 112 return;
p3p 0:6f6cfcdfe3d8 113 }
p3p 0:6f6cfcdfe3d8 114 for ( int x = 0; x < data_bytes; ++x) {
p3p 0:6f6cfcdfe3d8 115 data[x] = getByte();
p3p 0:6f6cfcdfe3d8 116 if (x != (data_bytes - 1)) giveAck();
p3p 0:6f6cfcdfe3d8 117 }
p3p 0:6f6cfcdfe3d8 118 stop();
p3p 0:6f6cfcdfe3d8 119 }
p3p 0:6f6cfcdfe3d8 120
p3p 1:6966eacc5914 121 /**
p3p 0:6f6cfcdfe3d8 122 * @brief Write 1 byte to the I2C slave at the specified memory address
p3p 0:6f6cfcdfe3d8 123 * @param device_address The address of the device to write to
p3p 0:6f6cfcdfe3d8 124 * @param start_address The memory address to write to
p3p 0:6f6cfcdfe3d8 125 * @param byte The data to write
p3p 0:6f6cfcdfe3d8 126 */
p3p 0:6f6cfcdfe3d8 127 void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte) {
p3p 0:6f6cfcdfe3d8 128 device_address = device_address & 0xFE;
p3p 0:6f6cfcdfe3d8 129 start();
p3p 0:6f6cfcdfe3d8 130 putByte(device_address);
p3p 0:6f6cfcdfe3d8 131 getAck();
p3p 0:6f6cfcdfe3d8 132 putByte(start_address);
p3p 0:6f6cfcdfe3d8 133 getAck();
p3p 0:6f6cfcdfe3d8 134 putByte(byte);
p3p 0:6f6cfcdfe3d8 135 getAck();
p3p 0:6f6cfcdfe3d8 136 stop();
p3p 0:6f6cfcdfe3d8 137 }
p3p 0:6f6cfcdfe3d8 138
p3p 1:6966eacc5914 139 /**
p3p 0:6f6cfcdfe3d8 140 * @brief Write 1 or more bytes to the I2C slave at the specified memory address
p3p 0:6f6cfcdfe3d8 141 * @param device_address The address of the device to write to
p3p 0:6f6cfcdfe3d8 142 * @param start_address The memory address to write to
p3p 0:6f6cfcdfe3d8 143 * @param data The data to write
p3p 0:6f6cfcdfe3d8 144 * @param data_bytes The number of bytes to write
p3p 0:6f6cfcdfe3d8 145 */
p3p 0:6f6cfcdfe3d8 146 void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
p3p 0:6f6cfcdfe3d8 147 if (data == 0 || data_bytes == 0) return;
p3p 0:6f6cfcdfe3d8 148
p3p 0:6f6cfcdfe3d8 149 device_address = device_address & 0xFE;
p3p 0:6f6cfcdfe3d8 150 start();
p3p 0:6f6cfcdfe3d8 151 putByte(device_address);
p3p 0:6f6cfcdfe3d8 152 getAck();
p3p 0:6f6cfcdfe3d8 153 putByte(start_address);
p3p 0:6f6cfcdfe3d8 154 getAck();
p3p 0:6f6cfcdfe3d8 155 for ( int x = 0; x <= data_bytes; ++x ) {
p3p 0:6f6cfcdfe3d8 156 putByte(data[x]);
p3p 0:6f6cfcdfe3d8 157 getAck();
p3p 0:6f6cfcdfe3d8 158 }
p3p 0:6f6cfcdfe3d8 159 stop();
p3p 0:6f6cfcdfe3d8 160 }
p3p 0:6f6cfcdfe3d8 161
p3p 1:6966eacc5914 162 /**
p3p 0:6f6cfcdfe3d8 163 * @brief Read 2 bytes from the I2C slave at the specified memory address and return them as an 16bit unsigned integer
p3p 0:6f6cfcdfe3d8 164 * @param device_address The address of the device to read from
p3p 0:6f6cfcdfe3d8 165 * @param start_address The memory address to read from
p3p 0:6f6cfcdfe3d8 166 * @return MSB 16bit unsigned integer
p3p 0:6f6cfcdfe3d8 167 */
p3p 0:6f6cfcdfe3d8 168 uint16_t SoftwareI2C::read16(uint8_t device_address, uint8_t start_address) {
p3p 0:6f6cfcdfe3d8 169 uint8_t short_array[2] = {0, 0};
p3p 0:6f6cfcdfe3d8 170 randomRead(device_address, start_address, short_array, 2 );
p3p 0:6f6cfcdfe3d8 171 uint16_t value = 0;
p3p 0:6f6cfcdfe3d8 172 value = short_array[0] << 8;
p3p 0:6f6cfcdfe3d8 173 value |= short_array[1];
p3p 0:6f6cfcdfe3d8 174
p3p 0:6f6cfcdfe3d8 175 return value;
p3p 0:6f6cfcdfe3d8 176 }
p3p 0:6f6cfcdfe3d8 177
p3p 1:6966eacc5914 178 /**
p3p 0:6f6cfcdfe3d8 179 * @brief Read 3 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
p3p 0:6f6cfcdfe3d8 180 * @param device_address The address of the device to read from
p3p 0:6f6cfcdfe3d8 181 * @param start_address The memory address to read from
p3p 0:6f6cfcdfe3d8 182 * @return MSB 32bit unsigned integer
p3p 0:6f6cfcdfe3d8 183 */
p3p 0:6f6cfcdfe3d8 184 uint32_t SoftwareI2C::read24(uint8_t device_address, uint8_t start_address) {
p3p 0:6f6cfcdfe3d8 185 uint8_t value_array[4] = {0, 0, 0};
p3p 0:6f6cfcdfe3d8 186 randomRead(device_address, start_address, value_array, 3 );
p3p 0:6f6cfcdfe3d8 187 uint32_t value = 0;
p3p 0:6f6cfcdfe3d8 188 value = value_array[0] << 16;
p3p 0:6f6cfcdfe3d8 189 value |= value_array[1] << 8;
p3p 0:6f6cfcdfe3d8 190 value |= value_array[2];
p3p 0:6f6cfcdfe3d8 191
p3p 0:6f6cfcdfe3d8 192 return value;
p3p 0:6f6cfcdfe3d8 193 }
p3p 0:6f6cfcdfe3d8 194
p3p 1:6966eacc5914 195 /**
p3p 0:6f6cfcdfe3d8 196 * @brief Read 4 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
p3p 0:6f6cfcdfe3d8 197 * @param device_address The address of the device to read from
p3p 0:6f6cfcdfe3d8 198 * @param start_address The memory address to read from
p3p 0:6f6cfcdfe3d8 199 * @return MSB 32bit unsigned integer
p3p 0:6f6cfcdfe3d8 200 */
p3p 0:6f6cfcdfe3d8 201 uint32_t SoftwareI2C::read32(uint8_t device_address, uint8_t start_address) {
p3p 0:6f6cfcdfe3d8 202 uint8_t value_array[4] = {0, 0, 0, 0};
p3p 0:6f6cfcdfe3d8 203 randomRead(device_address, start_address, value_array, 4 );
p3p 0:6f6cfcdfe3d8 204 uint32_t value = 0;
p3p 0:6f6cfcdfe3d8 205 value = value_array[0] << 24;
p3p 0:6f6cfcdfe3d8 206 value |= value_array[1] << 16;
p3p 0:6f6cfcdfe3d8 207 value |= value_array[2] << 8;
p3p 0:6f6cfcdfe3d8 208 value |= value_array[3];
p3p 0:6f6cfcdfe3d8 209
p3p 0:6f6cfcdfe3d8 210 return value;
p3p 0:6f6cfcdfe3d8 211 }