jm6wud

Committer:
jm6wud
Date:
Mon Oct 12 10:35:45 2020 +0000
Revision:
0:1f9d90cd7d0d
jm6wud

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jm6wud 0:1f9d90cd7d0d 1 /* mbed Microcontroller Library
jm6wud 0:1f9d90cd7d0d 2 * Copyright (c) 2006-2015 ARM Limited
jm6wud 0:1f9d90cd7d0d 3 * SPDX-License-Identifier: Apache-2.0
jm6wud 0:1f9d90cd7d0d 4 *
jm6wud 0:1f9d90cd7d0d 5 * Licensed under the Apache License, Version 2.0 (the "License");
jm6wud 0:1f9d90cd7d0d 6 * you may not use this file except in compliance with the License.
jm6wud 0:1f9d90cd7d0d 7 * You may obtain a copy of the License at
jm6wud 0:1f9d90cd7d0d 8 *
jm6wud 0:1f9d90cd7d0d 9 * http://www.apache.org/licenses/LICENSE-2.0
jm6wud 0:1f9d90cd7d0d 10 *
jm6wud 0:1f9d90cd7d0d 11 * Unless required by applicable law or agreed to in writing, software
jm6wud 0:1f9d90cd7d0d 12 * distributed under the License is distributed on an "AS IS" BASIS,
jm6wud 0:1f9d90cd7d0d 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jm6wud 0:1f9d90cd7d0d 14 * See the License for the specific language governing permissions and
jm6wud 0:1f9d90cd7d0d 15 * limitations under the License.
jm6wud 0:1f9d90cd7d0d 16 */
jm6wud 0:1f9d90cd7d0d 17 #ifndef MBED_I2C_H
jm6wud 0:1f9d90cd7d0d 18 #define MBED_I2C_H
jm6wud 0:1f9d90cd7d0d 19
jm6wud 0:1f9d90cd7d0d 20 #include "platform/platform.h"
jm6wud 0:1f9d90cd7d0d 21 #include "hal/gpio_api.h"
jm6wud 0:1f9d90cd7d0d 22
jm6wud 0:1f9d90cd7d0d 23 #if DEVICE_I2C || defined(DOXYGEN_ONLY)
jm6wud 0:1f9d90cd7d0d 24
jm6wud 0:1f9d90cd7d0d 25 #include "hal/i2c_api.h"
jm6wud 0:1f9d90cd7d0d 26 #include "platform/SingletonPtr.h"
jm6wud 0:1f9d90cd7d0d 27 #include "platform/PlatformMutex.h"
jm6wud 0:1f9d90cd7d0d 28 #include "platform/NonCopyable.h"
jm6wud 0:1f9d90cd7d0d 29
jm6wud 0:1f9d90cd7d0d 30 #if DEVICE_I2C_ASYNCH
jm6wud 0:1f9d90cd7d0d 31 #include "platform/CThunk.h"
jm6wud 0:1f9d90cd7d0d 32 #include "hal/dma_api.h"
jm6wud 0:1f9d90cd7d0d 33 #include "platform/FunctionPointer.h"
jm6wud 0:1f9d90cd7d0d 34 #endif
jm6wud 0:1f9d90cd7d0d 35
jm6wud 0:1f9d90cd7d0d 36 namespace mbed {
jm6wud 0:1f9d90cd7d0d 37 /** \addtogroup drivers */
jm6wud 0:1f9d90cd7d0d 38
jm6wud 0:1f9d90cd7d0d 39 /** An I2C Master, used for communicating with I2C slave devices
jm6wud 0:1f9d90cd7d0d 40 *
jm6wud 0:1f9d90cd7d0d 41 * @note Synchronization level: Thread safe
jm6wud 0:1f9d90cd7d0d 42 *
jm6wud 0:1f9d90cd7d0d 43 * Example:
jm6wud 0:1f9d90cd7d0d 44 * @code
jm6wud 0:1f9d90cd7d0d 45 * Read temperature from LM75BD
jm6wud 0:1f9d90cd7d0d 46 * #include "mbed.h"
jm6wud 0:1f9d90cd7d0d 47 * I2C i2c(I2C_SDA , I2C_SCL);
jm6wud 0:1f9d90cd7d0d 48 * const int addr7bit = 0x48; // 7-bit I2C address
jm6wud 0:1f9d90cd7d0d 49 * const int addr8bit = 0x48 << 1; // 8-bit I2C address, 0x90
jm6wud 0:1f9d90cd7d0d 50 *
jm6wud 0:1f9d90cd7d0d 51 * int main() {
jm6wud 0:1f9d90cd7d0d 52 * char cmd[2];
jm6wud 0:1f9d90cd7d0d 53 * while (1) {
jm6wud 0:1f9d90cd7d0d 54 * cmd[0] = 0x01;
jm6wud 0:1f9d90cd7d0d 55 * cmd[1] = 0x00;
jm6wud 0:1f9d90cd7d0d 56 *
jm6wud 0:1f9d90cd7d0d 57 * // read and write takes the 8-bit version of the address.
jm6wud 0:1f9d90cd7d0d 58 * // set up configuration register (at 0x01)
jm6wud 0:1f9d90cd7d0d 59 * i2c.write(addr8bit, cmd, 2);
jm6wud 0:1f9d90cd7d0d 60 *
jm6wud 0:1f9d90cd7d0d 61 * wait(0.5);
jm6wud 0:1f9d90cd7d0d 62 *
jm6wud 0:1f9d90cd7d0d 63 * // read temperature register
jm6wud 0:1f9d90cd7d0d 64 * cmd[0] = 0x00;
jm6wud 0:1f9d90cd7d0d 65 * i2c.write(addr8bit, cmd, 1);
jm6wud 0:1f9d90cd7d0d 66 * i2c.read( addr8bit, cmd, 2);
jm6wud 0:1f9d90cd7d0d 67 *
jm6wud 0:1f9d90cd7d0d 68 * float tmp = (float((cmd[0]<<8)|cmd[1]) / 256.0);
jm6wud 0:1f9d90cd7d0d 69 * printf("Temp = %.2f\n", tmp);
jm6wud 0:1f9d90cd7d0d 70 * }
jm6wud 0:1f9d90cd7d0d 71 * }
jm6wud 0:1f9d90cd7d0d 72 * @endcode
jm6wud 0:1f9d90cd7d0d 73 * @ingroup drivers
jm6wud 0:1f9d90cd7d0d 74 */
jm6wud 0:1f9d90cd7d0d 75 class I2C : private NonCopyable<I2C> {
jm6wud 0:1f9d90cd7d0d 76
jm6wud 0:1f9d90cd7d0d 77 public:
jm6wud 0:1f9d90cd7d0d 78 enum RxStatus {
jm6wud 0:1f9d90cd7d0d 79 NoData,
jm6wud 0:1f9d90cd7d0d 80 MasterGeneralCall,
jm6wud 0:1f9d90cd7d0d 81 MasterWrite,
jm6wud 0:1f9d90cd7d0d 82 MasterRead
jm6wud 0:1f9d90cd7d0d 83 };
jm6wud 0:1f9d90cd7d0d 84
jm6wud 0:1f9d90cd7d0d 85 enum Acknowledge {
jm6wud 0:1f9d90cd7d0d 86 NoACK = 0,
jm6wud 0:1f9d90cd7d0d 87 ACK = 1
jm6wud 0:1f9d90cd7d0d 88 };
jm6wud 0:1f9d90cd7d0d 89
jm6wud 0:1f9d90cd7d0d 90 /** Create an I2C Master interface, connected to the specified pins
jm6wud 0:1f9d90cd7d0d 91 *
jm6wud 0:1f9d90cd7d0d 92 * @param sda I2C data line pin
jm6wud 0:1f9d90cd7d0d 93 * @param scl I2C clock line pin
jm6wud 0:1f9d90cd7d0d 94 */
jm6wud 0:1f9d90cd7d0d 95 I2C(PinName sda, PinName scl);
jm6wud 0:1f9d90cd7d0d 96
jm6wud 0:1f9d90cd7d0d 97 /** Set the frequency of the I2C interface
jm6wud 0:1f9d90cd7d0d 98 *
jm6wud 0:1f9d90cd7d0d 99 * @param hz The bus frequency in hertz
jm6wud 0:1f9d90cd7d0d 100 */
jm6wud 0:1f9d90cd7d0d 101 void frequency(int hz);
jm6wud 0:1f9d90cd7d0d 102
jm6wud 0:1f9d90cd7d0d 103 /** Read from an I2C slave
jm6wud 0:1f9d90cd7d0d 104 *
jm6wud 0:1f9d90cd7d0d 105 * Performs a complete read transaction. The bottom bit of
jm6wud 0:1f9d90cd7d0d 106 * the address is forced to 1 to indicate a read.
jm6wud 0:1f9d90cd7d0d 107 *
jm6wud 0:1f9d90cd7d0d 108 * @param address 8-bit I2C slave address [ addr | 1 ]
jm6wud 0:1f9d90cd7d0d 109 * @param data Pointer to the byte-array to read data in to
jm6wud 0:1f9d90cd7d0d 110 * @param length Number of bytes to read
jm6wud 0:1f9d90cd7d0d 111 * @param repeated Repeated start, true - don't send stop at end
jm6wud 0:1f9d90cd7d0d 112 * default value is false.
jm6wud 0:1f9d90cd7d0d 113 *
jm6wud 0:1f9d90cd7d0d 114 * @returns
jm6wud 0:1f9d90cd7d0d 115 * 0 on success (ack),
jm6wud 0:1f9d90cd7d0d 116 * nonzero on failure (nack)
jm6wud 0:1f9d90cd7d0d 117 */
jm6wud 0:1f9d90cd7d0d 118 int read(int address, char *data, int length, bool repeated = false);
jm6wud 0:1f9d90cd7d0d 119
jm6wud 0:1f9d90cd7d0d 120 /** Read a single byte from the I2C bus
jm6wud 0:1f9d90cd7d0d 121 *
jm6wud 0:1f9d90cd7d0d 122 * @param ack indicates if the byte is to be acknowledged (1 = acknowledge)
jm6wud 0:1f9d90cd7d0d 123 *
jm6wud 0:1f9d90cd7d0d 124 * @returns
jm6wud 0:1f9d90cd7d0d 125 * the byte read
jm6wud 0:1f9d90cd7d0d 126 */
jm6wud 0:1f9d90cd7d0d 127 int read(int ack);
jm6wud 0:1f9d90cd7d0d 128
jm6wud 0:1f9d90cd7d0d 129 /** Write to an I2C slave
jm6wud 0:1f9d90cd7d0d 130 *
jm6wud 0:1f9d90cd7d0d 131 * Performs a complete write transaction. The bottom bit of
jm6wud 0:1f9d90cd7d0d 132 * the address is forced to 0 to indicate a write.
jm6wud 0:1f9d90cd7d0d 133 *
jm6wud 0:1f9d90cd7d0d 134 * @param address 8-bit I2C slave address [ addr | 0 ]
jm6wud 0:1f9d90cd7d0d 135 * @param data Pointer to the byte-array data to send
jm6wud 0:1f9d90cd7d0d 136 * @param length Number of bytes to send
jm6wud 0:1f9d90cd7d0d 137 * @param repeated Repeated start, true - do not send stop at end
jm6wud 0:1f9d90cd7d0d 138 * default value is false.
jm6wud 0:1f9d90cd7d0d 139 *
jm6wud 0:1f9d90cd7d0d 140 * @returns
jm6wud 0:1f9d90cd7d0d 141 * 0 on success (ack),
jm6wud 0:1f9d90cd7d0d 142 * nonzero on failure (nack)
jm6wud 0:1f9d90cd7d0d 143 */
jm6wud 0:1f9d90cd7d0d 144 int write(int address, const char *data, int length, bool repeated = false);
jm6wud 0:1f9d90cd7d0d 145
jm6wud 0:1f9d90cd7d0d 146 /** Write single byte out on the I2C bus
jm6wud 0:1f9d90cd7d0d 147 *
jm6wud 0:1f9d90cd7d0d 148 * @param data data to write out on bus
jm6wud 0:1f9d90cd7d0d 149 *
jm6wud 0:1f9d90cd7d0d 150 * @returns
jm6wud 0:1f9d90cd7d0d 151 * '0' - NAK was received
jm6wud 0:1f9d90cd7d0d 152 * '1' - ACK was received,
jm6wud 0:1f9d90cd7d0d 153 * '2' - timeout
jm6wud 0:1f9d90cd7d0d 154 */
jm6wud 0:1f9d90cd7d0d 155 int write(int data);
jm6wud 0:1f9d90cd7d0d 156
jm6wud 0:1f9d90cd7d0d 157 /** Creates a start condition on the I2C bus
jm6wud 0:1f9d90cd7d0d 158 */
jm6wud 0:1f9d90cd7d0d 159 void start(void);
jm6wud 0:1f9d90cd7d0d 160
jm6wud 0:1f9d90cd7d0d 161 /** Creates a stop condition on the I2C bus
jm6wud 0:1f9d90cd7d0d 162 */
jm6wud 0:1f9d90cd7d0d 163 void stop(void);
jm6wud 0:1f9d90cd7d0d 164
jm6wud 0:1f9d90cd7d0d 165 /** Acquire exclusive access to this I2C bus
jm6wud 0:1f9d90cd7d0d 166 */
jm6wud 0:1f9d90cd7d0d 167 virtual void lock(void);
jm6wud 0:1f9d90cd7d0d 168
jm6wud 0:1f9d90cd7d0d 169 /** Release exclusive access to this I2C bus
jm6wud 0:1f9d90cd7d0d 170 */
jm6wud 0:1f9d90cd7d0d 171 virtual void unlock(void);
jm6wud 0:1f9d90cd7d0d 172
jm6wud 0:1f9d90cd7d0d 173 virtual ~I2C()
jm6wud 0:1f9d90cd7d0d 174 {
jm6wud 0:1f9d90cd7d0d 175 // Do nothing
jm6wud 0:1f9d90cd7d0d 176 }
jm6wud 0:1f9d90cd7d0d 177
jm6wud 0:1f9d90cd7d0d 178 #if DEVICE_I2C_ASYNCH
jm6wud 0:1f9d90cd7d0d 179
jm6wud 0:1f9d90cd7d0d 180 /** Start nonblocking I2C transfer.
jm6wud 0:1f9d90cd7d0d 181 *
jm6wud 0:1f9d90cd7d0d 182 * This function locks the deep sleep until any event has occurred
jm6wud 0:1f9d90cd7d0d 183 *
jm6wud 0:1f9d90cd7d0d 184 * @param address 8/10 bit I2C slave address
jm6wud 0:1f9d90cd7d0d 185 * @param tx_buffer The TX buffer with data to be transferred
jm6wud 0:1f9d90cd7d0d 186 * @param tx_length The length of TX buffer in bytes
jm6wud 0:1f9d90cd7d0d 187 * @param rx_buffer The RX buffer, which is used for received data
jm6wud 0:1f9d90cd7d0d 188 * @param rx_length The length of RX buffer in bytes
jm6wud 0:1f9d90cd7d0d 189 * @param event The logical OR of events to modify
jm6wud 0:1f9d90cd7d0d 190 * @param callback The event callback function
jm6wud 0:1f9d90cd7d0d 191 * @param repeated Repeated start, true - do not send stop at end
jm6wud 0:1f9d90cd7d0d 192 * default value is false.
jm6wud 0:1f9d90cd7d0d 193 *
jm6wud 0:1f9d90cd7d0d 194 * @returns Zero if the transfer has started, or -1 if I2C peripheral is busy
jm6wud 0:1f9d90cd7d0d 195 */
jm6wud 0:1f9d90cd7d0d 196 int transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t &callback, int event = I2C_EVENT_TRANSFER_COMPLETE, bool repeated = false);
jm6wud 0:1f9d90cd7d0d 197
jm6wud 0:1f9d90cd7d0d 198 /** Abort the ongoing I2C transfer
jm6wud 0:1f9d90cd7d0d 199 */
jm6wud 0:1f9d90cd7d0d 200 void abort_transfer();
jm6wud 0:1f9d90cd7d0d 201
jm6wud 0:1f9d90cd7d0d 202 #if !defined(DOXYGEN_ONLY)
jm6wud 0:1f9d90cd7d0d 203 protected:
jm6wud 0:1f9d90cd7d0d 204 /** Lock deep sleep only if it is not yet locked */
jm6wud 0:1f9d90cd7d0d 205 void lock_deep_sleep();
jm6wud 0:1f9d90cd7d0d 206
jm6wud 0:1f9d90cd7d0d 207 /** Unlock deep sleep only if it has been locked */
jm6wud 0:1f9d90cd7d0d 208 void unlock_deep_sleep();
jm6wud 0:1f9d90cd7d0d 209
jm6wud 0:1f9d90cd7d0d 210 void irq_handler_asynch(void);
jm6wud 0:1f9d90cd7d0d 211 event_callback_t _callback;
jm6wud 0:1f9d90cd7d0d 212 CThunk<I2C> _irq;
jm6wud 0:1f9d90cd7d0d 213 DMAUsage _usage;
jm6wud 0:1f9d90cd7d0d 214 bool _deep_sleep_locked;
jm6wud 0:1f9d90cd7d0d 215 #endif
jm6wud 0:1f9d90cd7d0d 216 #endif
jm6wud 0:1f9d90cd7d0d 217
jm6wud 0:1f9d90cd7d0d 218 #if !defined(DOXYGEN_ONLY)
jm6wud 0:1f9d90cd7d0d 219 protected:
jm6wud 0:1f9d90cd7d0d 220 void aquire();
jm6wud 0:1f9d90cd7d0d 221
jm6wud 0:1f9d90cd7d0d 222 i2c_t _i2c;
jm6wud 0:1f9d90cd7d0d 223 static I2C *_owner;
jm6wud 0:1f9d90cd7d0d 224 int _hz;
jm6wud 0:1f9d90cd7d0d 225 static SingletonPtr<PlatformMutex> _mutex;
jm6wud 0:1f9d90cd7d0d 226 PinName _sda;
jm6wud 0:1f9d90cd7d0d 227 PinName _scl;
jm6wud 0:1f9d90cd7d0d 228
jm6wud 0:1f9d90cd7d0d 229 private:
jm6wud 0:1f9d90cd7d0d 230 /** Recover I2C bus, when stuck with SDA low
jm6wud 0:1f9d90cd7d0d 231 * @note : Initialization of I2C bus is required after this API.
jm6wud 0:1f9d90cd7d0d 232 *
jm6wud 0:1f9d90cd7d0d 233 * @param sda I2C data line pin
jm6wud 0:1f9d90cd7d0d 234 * @param scl I2C clock line pin
jm6wud 0:1f9d90cd7d0d 235 *
jm6wud 0:1f9d90cd7d0d 236 * @returns
jm6wud 0:1f9d90cd7d0d 237 * '0' - Successfully recovered
jm6wud 0:1f9d90cd7d0d 238 * 'I2C_ERROR_BUS_BUSY' - In case of failure
jm6wud 0:1f9d90cd7d0d 239 *
jm6wud 0:1f9d90cd7d0d 240 */
jm6wud 0:1f9d90cd7d0d 241 int recover(PinName sda, PinName scl);
jm6wud 0:1f9d90cd7d0d 242 #endif
jm6wud 0:1f9d90cd7d0d 243 };
jm6wud 0:1f9d90cd7d0d 244
jm6wud 0:1f9d90cd7d0d 245 } // namespace mbed
jm6wud 0:1f9d90cd7d0d 246
jm6wud 0:1f9d90cd7d0d 247 #endif
jm6wud 0:1f9d90cd7d0d 248
jm6wud 0:1f9d90cd7d0d 249 #endif