This library provides simplified I2C access to a Microchip MCP23x17 GPIO expender device, including a general interface for any GPIO expender

Dependents:   MCP23017App

Committer:
Yann
Date:
Fri Jan 09 15:35:40 2015 +0000
Revision:
1:ec9e770173d5
Parent:
0:ebd3a7cc9b92
Child:
2:3bea48e1505c
Bug fixed in read method; Add bus support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Yann 1:ec9e770173d5 1 /* mbed simplified access to Microchip MCP23x17 GPIO expender devices (I2C)
Yann 0:ebd3a7cc9b92 2 * Copyright (c) 2010-2012 ygarcia, MIT License
Yann 0:ebd3a7cc9b92 3 *
Yann 0:ebd3a7cc9b92 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Yann 0:ebd3a7cc9b92 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
Yann 0:ebd3a7cc9b92 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
Yann 0:ebd3a7cc9b92 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
Yann 0:ebd3a7cc9b92 8 * furnished to do so, subject to the following conditions:
Yann 0:ebd3a7cc9b92 9 *
Yann 0:ebd3a7cc9b92 10 * The above copyright notice and this permission notice shall be included in all copies or
Yann 0:ebd3a7cc9b92 11 * substantial pinions of the Software.
Yann 0:ebd3a7cc9b92 12 *
Yann 0:ebd3a7cc9b92 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Yann 0:ebd3a7cc9b92 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Yann 0:ebd3a7cc9b92 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Yann 0:ebd3a7cc9b92 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Yann 0:ebd3a7cc9b92 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Yann 0:ebd3a7cc9b92 18 */
Yann 0:ebd3a7cc9b92 19 #include <iostream>
Yann 0:ebd3a7cc9b92 20 #include <sstream>
Yann 0:ebd3a7cc9b92 21
Yann 0:ebd3a7cc9b92 22 #include "MCP23017_I2C.h"
Yann 0:ebd3a7cc9b92 23
Yann 0:ebd3a7cc9b92 24 #define IODIRA 0x00
Yann 0:ebd3a7cc9b92 25 #define IODIRB 0x01
Yann 0:ebd3a7cc9b92 26 #define IPOLA 0x02
Yann 0:ebd3a7cc9b92 27 #define IPOLB 0x03
Yann 0:ebd3a7cc9b92 28 #define GPINTENA 0x04
Yann 0:ebd3a7cc9b92 29 #define GPINTENB 0x05
Yann 0:ebd3a7cc9b92 30 #define DEFVALA 0x06
Yann 0:ebd3a7cc9b92 31 #define DEFVALB 0x07
Yann 0:ebd3a7cc9b92 32 #define INTCONA 0x08
Yann 0:ebd3a7cc9b92 33 #define INTCONB 0x09
Yann 0:ebd3a7cc9b92 34 #define IOCONA 0x0a
Yann 0:ebd3a7cc9b92 35 #define IOCONB 0x0b
Yann 0:ebd3a7cc9b92 36 #define GPPUA 0x0c
Yann 0:ebd3a7cc9b92 37 #define GPPUB 0x0d
Yann 0:ebd3a7cc9b92 38 #define INTFA 0x0e
Yann 0:ebd3a7cc9b92 39 #define INTFB 0x0f
Yann 0:ebd3a7cc9b92 40 #define INTCAPA 0x10
Yann 0:ebd3a7cc9b92 41 #define INTCAPB 0x11
Yann 0:ebd3a7cc9b92 42 #define GPIOA 0x12
Yann 0:ebd3a7cc9b92 43 #define GPIOB 0x13
Yann 0:ebd3a7cc9b92 44 #define OLATA 0x14
Yann 0:ebd3a7cc9b92 45 #define OLATB 0x15
Yann 0:ebd3a7cc9b92 46
Yann 0:ebd3a7cc9b92 47 namespace MCP23017_I2C {
Yann 0:ebd3a7cc9b92 48
Yann 0:ebd3a7cc9b92 49 unsigned char CMCP23017_I2C::I2CModuleRefCounter = 0;
Yann 0:ebd3a7cc9b92 50
Yann 0:ebd3a7cc9b92 51 CMCP23017_I2C::CMCP23017_I2C(const PinName p_sda, const PinName p_scl, const unsigned char p_address, const PinName p_intA, const PinName p_intB, const PinName p_reset, const bool p_internalPullUp, const unsigned int p_frequency) : _gpioAFlags(0x00), _gpioBFlags(0x00), _buses(), _busesIndex(0x00), _internalId("") {
Yann 0:ebd3a7cc9b92 52 DEBUG_ENTER("CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 53
Yann 0:ebd3a7cc9b92 54 if (CMCP23017_I2C::I2CModuleRefCounter != 0) {
Yann 0:ebd3a7cc9b92 55 error("CMCP23017_I2C: Wrong params");
Yann 0:ebd3a7cc9b92 56 }
Yann 0:ebd3a7cc9b92 57 #ifdef __DEBUG
Yann 0:ebd3a7cc9b92 58 std::ostringstream out(std::ostringstream::out);
Yann 0:ebd3a7cc9b92 59 out << "CMCP23017_I2C #" << CMCP23017_I2C::I2CModuleRefCounter;
Yann 0:ebd3a7cc9b92 60 _internalId.assign(out.str());
Yann 0:ebd3a7cc9b92 61 DEBUG("CMCP23017_I2C: _internalId='%s'", _internalId.c_str())
Yann 0:ebd3a7cc9b92 62 #endif // __DEBUG
Yann 0:ebd3a7cc9b92 63 _i2cInstance = new I2C(p_sda, p_scl);
Yann 0:ebd3a7cc9b92 64 CMCP23017_I2C::I2CModuleRefCounter += 1;
Yann 0:ebd3a7cc9b92 65 DEBUG_ENTER("CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter)
Yann 0:ebd3a7cc9b92 66
Yann 0:ebd3a7cc9b92 67 _slaveAddress = (p_address << 1) | 0x40; // Slave address format is: 0 0 1 0 A3 A2 A1 R/W
Yann 0:ebd3a7cc9b92 68 DEBUG("CMCP23017_I2C: I2C slave adress: 0x%02x", _slaveAddress)
Yann 0:ebd3a7cc9b92 69 _i2cInstance->frequency(p_frequency); // Set the frequency of the I2C interface
Yann 0:ebd3a7cc9b92 70
Yann 0:ebd3a7cc9b92 71 if (p_intA != NC) {
Yann 0:ebd3a7cc9b92 72 DEBUG("CMCP23017_I2C: INTA managed");
Yann 0:ebd3a7cc9b92 73 _intA = new InterruptIn(p_intA);
Yann 0:ebd3a7cc9b92 74 if (p_internalPullUp) _intA->mode(PullDown);
Yann 0:ebd3a7cc9b92 75 _intA->enable_irq(); // Enable interrupt
Yann 0:ebd3a7cc9b92 76 } else {
Yann 0:ebd3a7cc9b92 77 DEBUG("CMCP23017_I2C: INTA not managed");
Yann 0:ebd3a7cc9b92 78 _intA = NULL; // Not used
Yann 0:ebd3a7cc9b92 79 }
Yann 0:ebd3a7cc9b92 80 if (p_intB != NC) {
Yann 0:ebd3a7cc9b92 81 DEBUG("CMCP23017_I2C: INTB managed");
Yann 0:ebd3a7cc9b92 82 _intB = new InterruptIn(p_intB);
Yann 0:ebd3a7cc9b92 83 if (p_internalPullUp) _intB->mode(PullDown);
Yann 0:ebd3a7cc9b92 84 _intB->enable_irq(); // Enable interrupt
Yann 0:ebd3a7cc9b92 85 } else {
Yann 0:ebd3a7cc9b92 86 DEBUG("CMCP23017_I2C: INTB not managed");
Yann 0:ebd3a7cc9b92 87 _intB = NULL; // Not used
Yann 0:ebd3a7cc9b92 88 }
Yann 0:ebd3a7cc9b92 89 if (p_reset != NC) {
Yann 0:ebd3a7cc9b92 90 DEBUG("CMCP23017_I2C: RESET managed");
Yann 0:ebd3a7cc9b92 91 _reset = new DigitalOut(p_reset);
Yann 0:ebd3a7cc9b92 92 _reset->write(1); // Disable reset
Yann 0:ebd3a7cc9b92 93 } else {
Yann 0:ebd3a7cc9b92 94 DEBUG("CMCP23017_I2C: RESET not managed");
Yann 0:ebd3a7cc9b92 95 _reset = NULL; // Not used
Yann 0:ebd3a7cc9b92 96 }
Yann 0:ebd3a7cc9b92 97
Yann 0:ebd3a7cc9b92 98 DEBUG_LEAVE("CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 99 }
Yann 0:ebd3a7cc9b92 100
Yann 0:ebd3a7cc9b92 101 CMCP23017_I2C::~CMCP23017_I2C() {
Yann 0:ebd3a7cc9b92 102 DEBUG_ENTER("~CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 103
Yann 0:ebd3a7cc9b92 104 // Release I2C instance
Yann 0:ebd3a7cc9b92 105 DEBUG_ENTER("~CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter)
Yann 0:ebd3a7cc9b92 106 CMCP23017_I2C::I2CModuleRefCounter -= 1;
Yann 0:ebd3a7cc9b92 107 if (CMCP23017_I2C::I2CModuleRefCounter == 0) {
Yann 0:ebd3a7cc9b92 108 delete _i2cInstance;
Yann 0:ebd3a7cc9b92 109 _i2cInstance = NULL;
Yann 0:ebd3a7cc9b92 110 }
Yann 0:ebd3a7cc9b92 111 // Release _wp if required
Yann 0:ebd3a7cc9b92 112 if (_intA != NULL) {
Yann 0:ebd3a7cc9b92 113 delete _intA;
Yann 0:ebd3a7cc9b92 114 }
Yann 0:ebd3a7cc9b92 115 if (_intB != NULL) {
Yann 0:ebd3a7cc9b92 116 delete _intB;
Yann 0:ebd3a7cc9b92 117 }
Yann 0:ebd3a7cc9b92 118 if (_reset != NULL) {
Yann 0:ebd3a7cc9b92 119 delete _reset;
Yann 0:ebd3a7cc9b92 120 }
Yann 0:ebd3a7cc9b92 121
Yann 0:ebd3a7cc9b92 122 DEBUG_LEAVE("~CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 123 }
Yann 0:ebd3a7cc9b92 124
Yann 0:ebd3a7cc9b92 125 bool CMCP23017_I2C::Initialize(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) {
Yann 0:ebd3a7cc9b92 126
Yann 0:ebd3a7cc9b92 127 // Configure default behavior
Yann 0:ebd3a7cc9b92 128 _gpioAFlags = p_gpioAFlags;
Yann 0:ebd3a7cc9b92 129 _gpioBFlags = p_gpioBFlags;
Yann 0:ebd3a7cc9b92 130 configure(_gpioAFlags, _gpioBFlags);
Yann 0:ebd3a7cc9b92 131
Yann 0:ebd3a7cc9b92 132 return true;
Yann 0:ebd3a7cc9b92 133 }
Yann 0:ebd3a7cc9b92 134
Yann 0:ebd3a7cc9b92 135 void CMCP23017_I2C::configure(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) { // TODO Optimization with sequential access
Yann 0:ebd3a7cc9b92 136 // DEBUG_ENTER("CMCP23017_I2C::configure: 0x%02x 0x%02x", p_gpioAFlags, p_gpioBFlags)
Yann 0:ebd3a7cc9b92 137
Yann 0:ebd3a7cc9b92 138 // Setup IOCON - See REGISTER 1-6: IOCON – I/O EXPANDER CONFIGURATION REGISTER
Yann 0:ebd3a7cc9b92 139 writeRegister(IOCONA, 0x10); // Sequential operation disabled
Yann 0:ebd3a7cc9b92 140 writeRegister(IOCONB, 0x10); // Sequential operation disabled
Yann 0:ebd3a7cc9b92 141 // Setup IODIR - See REGISTER 1-1: IODIR – I/O DIRECTION REGISTER (ADDR 0x00)
Yann 0:ebd3a7cc9b92 142 writeRegister(IODIRA, p_gpioAFlags);
Yann 0:ebd3a7cc9b92 143 writeRegister(IODIRB, p_gpioBFlags);
Yann 0:ebd3a7cc9b92 144 // Setup IPOL - See REGISTER 1-2: IPOL – INPUT POLARITY PORT REGISTER
Yann 0:ebd3a7cc9b92 145 writeRegister(IPOLA, 0x00); // GPIO register bit will reflect the same logic state of the input pin
Yann 0:ebd3a7cc9b92 146 writeRegister(IPOLB, 0x00);
Yann 0:ebd3a7cc9b92 147 // Setup GPPU - See REGISTER 1-7: GPPU – GPIO PULL-UP RESISTOR REGISTER
Yann 0:ebd3a7cc9b92 148 writeRegister(GPPUA, 0x00);
Yann 0:ebd3a7cc9b92 149 writeRegister(GPPUB, 0x00);
Yann 0:ebd3a7cc9b92 150
Yann 0:ebd3a7cc9b92 151 // Setup interrupt
Yann 0:ebd3a7cc9b92 152 if (_intA != NULL) {
Yann 0:ebd3a7cc9b92 153 DEBUG("CMCP23017_I2C::configure: Setup INTA")
Yann 0:ebd3a7cc9b92 154 // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS
Yann 0:ebd3a7cc9b92 155 writeRegister(GPINTENA, 0x00); // Disable GPIO interrupt-on-change events
Yann 0:ebd3a7cc9b92 156 // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER
Yann 0:ebd3a7cc9b92 157 writeRegister(DEFVALA, 0x00); // Pin level change from 0 to 1 raises an interrupt
Yann 0:ebd3a7cc9b92 158 // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
Yann 0:ebd3a7cc9b92 159 writeRegister(INTCONA, 0xff); // Pin level change from 0 to 1 raises an interrupt
Yann 0:ebd3a7cc9b92 160 }
Yann 0:ebd3a7cc9b92 161 if (_intB != NULL) {
Yann 0:ebd3a7cc9b92 162 DEBUG("CMCP23017_I2C::configure: Setup INTB")
Yann 0:ebd3a7cc9b92 163 // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS
Yann 0:ebd3a7cc9b92 164 writeRegister(GPINTENB, 0x00); // Disable GPIO interrupt-on-change events
Yann 0:ebd3a7cc9b92 165 // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER
Yann 0:ebd3a7cc9b92 166 writeRegister(DEFVALB, 0x00); // Pin level change from 0 to 1 raises an interrupt
Yann 0:ebd3a7cc9b92 167 // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
Yann 0:ebd3a7cc9b92 168 writeRegister(INTCONB, 0xff); // Pin level change from 0 to 1 raises an interrupt
Yann 0:ebd3a7cc9b92 169 }
Yann 0:ebd3a7cc9b92 170
Yann 0:ebd3a7cc9b92 171 // DumpRegisters();
Yann 0:ebd3a7cc9b92 172
Yann 0:ebd3a7cc9b92 173 // DEBUG_LEAVE("CMCP23017_I2C::configure")
Yann 0:ebd3a7cc9b92 174 }
Yann 0:ebd3a7cc9b92 175
Yann 0:ebd3a7cc9b92 176 void CMCP23017_I2C::reset() {
Yann 0:ebd3a7cc9b92 177 // DEBUG_ENTER("CMCP23017_I2C::reset")
Yann 0:ebd3a7cc9b92 178 if (_reset != NULL) {
Yann 0:ebd3a7cc9b92 179 _reset->write(0);
Yann 0:ebd3a7cc9b92 180 wait_us(1);
Yann 0:ebd3a7cc9b92 181 _reset->write(1);
Yann 0:ebd3a7cc9b92 182 wait_us(1);
Yann 0:ebd3a7cc9b92 183 if ((_gpioAFlags != 0x00) || (_gpioBFlags != 0x00)) { // Apply configuration
Yann 0:ebd3a7cc9b92 184 configure(_gpioAFlags, _gpioBFlags);
Yann 0:ebd3a7cc9b92 185 } // else, POR reset values, see DS21952B-page 10 Clause 1.6 Configuration and Control Registers
Yann 0:ebd3a7cc9b92 186 }
Yann 0:ebd3a7cc9b92 187 // DEBUG_LEAVE("CMCP23017_I2C::reset")
Yann 0:ebd3a7cc9b92 188 }
Yann 0:ebd3a7cc9b92 189
Yann 0:ebd3a7cc9b92 190 void CMCP23017_I2C::setIntrACallback(void (* p_fptr)(void)) {
Yann 0:ebd3a7cc9b92 191 if (_intA != NULL) {
Yann 0:ebd3a7cc9b92 192 unsigned char vregister;
Yann 0:ebd3a7cc9b92 193 if (!readRegister(IOCONA, &vregister)) {
Yann 0:ebd3a7cc9b92 194 return;
Yann 0:ebd3a7cc9b92 195 }
Yann 0:ebd3a7cc9b92 196 if (isBitSet(vregister, 1)) {
Yann 0:ebd3a7cc9b92 197 _intA->rise(p_fptr);
Yann 0:ebd3a7cc9b92 198 } else {
Yann 0:ebd3a7cc9b92 199 _intA->fall(p_fptr);
Yann 0:ebd3a7cc9b92 200 }
Yann 0:ebd3a7cc9b92 201 }
Yann 0:ebd3a7cc9b92 202 }
Yann 0:ebd3a7cc9b92 203
Yann 0:ebd3a7cc9b92 204 void CMCP23017_I2C::setIntrBCallback(void (* p_fptr)(void)) {
Yann 0:ebd3a7cc9b92 205 if (_intB != NULL) {
Yann 0:ebd3a7cc9b92 206 unsigned char vregister;
Yann 0:ebd3a7cc9b92 207 if (!readRegister(IOCONB, &vregister)) {
Yann 0:ebd3a7cc9b92 208 return;
Yann 0:ebd3a7cc9b92 209 }
Yann 0:ebd3a7cc9b92 210 if (isBitSet(vregister, 1)) {
Yann 0:ebd3a7cc9b92 211 _intB->rise(p_fptr);
Yann 0:ebd3a7cc9b92 212 } else {
Yann 0:ebd3a7cc9b92 213 _intB->fall(p_fptr);
Yann 0:ebd3a7cc9b92 214 }
Yann 0:ebd3a7cc9b92 215 }
Yann 0:ebd3a7cc9b92 216 }
Yann 0:ebd3a7cc9b92 217
Yann 0:ebd3a7cc9b92 218 template<typename T>
Yann 0:ebd3a7cc9b92 219 void CMCP23017_I2C::setIntrACallback (const T * p_tptr, void(T::* p_mptr)(void)) {
Yann 0:ebd3a7cc9b92 220 if (_intA != NULL) {
Yann 0:ebd3a7cc9b92 221 unsigned char vregister;
Yann 0:ebd3a7cc9b92 222 if (!readRegister(IOCONA, &vregister)) {
Yann 0:ebd3a7cc9b92 223 return;
Yann 0:ebd3a7cc9b92 224 }
Yann 0:ebd3a7cc9b92 225 if (isBitSet(vregister, 1)) {
Yann 0:ebd3a7cc9b92 226 _intA->rise(p_tptr, p_mptr);
Yann 0:ebd3a7cc9b92 227 } else {
Yann 0:ebd3a7cc9b92 228 _intA->fall(p_tptr, p_mptr);
Yann 0:ebd3a7cc9b92 229 }
Yann 0:ebd3a7cc9b92 230 }
Yann 0:ebd3a7cc9b92 231 }
Yann 0:ebd3a7cc9b92 232
Yann 0:ebd3a7cc9b92 233 template<typename T>
Yann 0:ebd3a7cc9b92 234 void CMCP23017_I2C::setIntrBCallback (const T * p_tptr, void(T::* p_mptr)(void)) {
Yann 0:ebd3a7cc9b92 235 unsigned char vregister;
Yann 0:ebd3a7cc9b92 236 if (!readRegister(IOCONB, &vregister)) {
Yann 0:ebd3a7cc9b92 237 return;
Yann 0:ebd3a7cc9b92 238 }
Yann 0:ebd3a7cc9b92 239 if (isBitSet(vregister, 1)) {
Yann 0:ebd3a7cc9b92 240 _intB->rise(p_tptr, p_mptr);
Yann 0:ebd3a7cc9b92 241 } else {
Yann 0:ebd3a7cc9b92 242 _intB->fall(p_tptr, p_mptr);
Yann 0:ebd3a7cc9b92 243 }
Yann 0:ebd3a7cc9b92 244 }
Yann 0:ebd3a7cc9b92 245
Yann 0:ebd3a7cc9b92 246 void CMCP23017_I2C::setupInterrupts(const unsigned char p_mirroring, const unsigned char p_openDrain, const unsigned char p_polarity) {
Yann 0:ebd3a7cc9b92 247 DEBUG_ENTER("CMCP23017_I2C::setupInterrupts: %02x, %02x, %02x", p_mirroring, p_openDrain, p_polarity)
Yann 0:ebd3a7cc9b92 248
Yann 0:ebd3a7cc9b92 249 // Setup IOCONA
Yann 0:ebd3a7cc9b92 250 unsigned char vregister;
Yann 0:ebd3a7cc9b92 251 if (!readRegister(INTCONA, &vregister)) {
Yann 0:ebd3a7cc9b92 252 return;
Yann 0:ebd3a7cc9b92 253 }
Yann 0:ebd3a7cc9b92 254 // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
Yann 0:ebd3a7cc9b92 255 vregister = setBit(vregister, 6, p_mirroring);
Yann 0:ebd3a7cc9b92 256 vregister = setBit(vregister, 2, p_openDrain);
Yann 0:ebd3a7cc9b92 257 vregister = setBit(vregister, 1, p_polarity);
Yann 0:ebd3a7cc9b92 258 writeRegister(INTCONA, vregister);
Yann 0:ebd3a7cc9b92 259
Yann 0:ebd3a7cc9b92 260 // Setup IOCONB
Yann 0:ebd3a7cc9b92 261 if (!readRegister(INTCONB, &vregister)) {
Yann 0:ebd3a7cc9b92 262 return;
Yann 0:ebd3a7cc9b92 263 }
Yann 0:ebd3a7cc9b92 264 // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
Yann 0:ebd3a7cc9b92 265 vregister = setBit(vregister, 6, p_mirroring);
Yann 0:ebd3a7cc9b92 266 vregister = setBit(vregister, 2, p_openDrain);
Yann 0:ebd3a7cc9b92 267 vregister = setBit(vregister, 1, p_polarity);
Yann 0:ebd3a7cc9b92 268 writeRegister(INTCONB, vregister);
Yann 0:ebd3a7cc9b92 269
Yann 0:ebd3a7cc9b92 270 }
Yann 0:ebd3a7cc9b92 271
Yann 0:ebd3a7cc9b92 272 int CMCP23017_I2C::setupInterruptPin(const unsigned char p_gpioId, const InterruptModes p_mode) {
Yann 0:ebd3a7cc9b92 273 DEBUG_ENTER("CMCP23017_I2C::setupInterruptPin: %02x, %02x", p_gpioId, p_mode)
Yann 0:ebd3a7cc9b92 274
Yann 0:ebd3a7cc9b92 275 // Retrive the register address
Yann 0:ebd3a7cc9b92 276 unsigned char gpioIntconId, gpioDefvalId, gpioGpintenId;
Yann 0:ebd3a7cc9b92 277 if (!registerIdFromGpioId(p_gpioId, &gpioIntconId)) {
Yann 0:ebd3a7cc9b92 278 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -1")
Yann 0:ebd3a7cc9b92 279 return -1;
Yann 0:ebd3a7cc9b92 280 }
Yann 0:ebd3a7cc9b92 281 if (gpioIntconId == GPIOA) {
Yann 0:ebd3a7cc9b92 282 gpioIntconId = INTCONA;
Yann 0:ebd3a7cc9b92 283 gpioDefvalId = DEFVALA;
Yann 0:ebd3a7cc9b92 284 gpioGpintenId = GPINTENA;
Yann 0:ebd3a7cc9b92 285 } else {
Yann 0:ebd3a7cc9b92 286 gpioIntconId = INTCONB;
Yann 0:ebd3a7cc9b92 287 gpioDefvalId = DEFVALB;
Yann 0:ebd3a7cc9b92 288 gpioGpintenId = GPINTENB;
Yann 0:ebd3a7cc9b92 289 }
Yann 0:ebd3a7cc9b92 290 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconId=%02x gpioDefvalId=%02x gpioGpintenId=%02x", gpioIntconId, gpioDefvalId, gpioGpintenId)
Yann 0:ebd3a7cc9b92 291
Yann 0:ebd3a7cc9b92 292 // Retrive the GPIO pin number
Yann 0:ebd3a7cc9b92 293 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 0:ebd3a7cc9b92 294 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioBit=%02x", gpioBit)
Yann 0:ebd3a7cc9b92 295
Yann 0:ebd3a7cc9b92 296 // Read it
Yann 0:ebd3a7cc9b92 297 unsigned char gpioIntconValue, gpioDefvalValue, gpioGpintenValue;
Yann 0:ebd3a7cc9b92 298 if (!readRegister(gpioIntconId, &gpioIntconValue)) {
Yann 0:ebd3a7cc9b92 299 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 300 return -2;
Yann 0:ebd3a7cc9b92 301 }
Yann 0:ebd3a7cc9b92 302 if (!readRegister(gpioDefvalId, &gpioDefvalValue)) {
Yann 0:ebd3a7cc9b92 303 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 304 return -2;
Yann 0:ebd3a7cc9b92 305 }
Yann 0:ebd3a7cc9b92 306 if (!readRegister(gpioGpintenId, &gpioGpintenValue)) {
Yann 0:ebd3a7cc9b92 307 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 308 return -2;
Yann 0:ebd3a7cc9b92 309 }
Yann 0:ebd3a7cc9b92 310 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconValue=%02x gpioDefvalValue=%02x gpioGpintenValue=%02x", gpioIntconValue, gpioDefvalValue, gpioGpintenValue)
Yann 0:ebd3a7cc9b92 311
Yann 0:ebd3a7cc9b92 312 //
Yann 0:ebd3a7cc9b92 313 switch (static_cast<unsigned char>(p_mode)) {
Yann 0:ebd3a7cc9b92 314 case static_cast<unsigned char>(OnChange):
Yann 0:ebd3a7cc9b92 315 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 316 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 317 break;
Yann 0:ebd3a7cc9b92 318 case static_cast<unsigned char>(OnRising):
Yann 0:ebd3a7cc9b92 319 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 320 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 321 break;
Yann 0:ebd3a7cc9b92 322 case static_cast<unsigned char>(OnFalling):
Yann 0:ebd3a7cc9b92 323 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 324 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 325 break;
Yann 0:ebd3a7cc9b92 326 } // End of 'switch' statement
Yann 0:ebd3a7cc9b92 327
Yann 0:ebd3a7cc9b92 328 // Enable interrupt
Yann 0:ebd3a7cc9b92 329 gpioGpintenValue = setBit(gpioGpintenValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 330
Yann 0:ebd3a7cc9b92 331 // Write register
Yann 0:ebd3a7cc9b92 332 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconValue=%02x gpioDefvalValue=%02x gpioGpintenValue=%02x", gpioIntconValue, gpioDefvalValue, gpioGpintenValue)
Yann 0:ebd3a7cc9b92 333 writeRegister(gpioDefvalId, gpioDefvalValue);
Yann 0:ebd3a7cc9b92 334 writeRegister(gpioIntconId, gpioIntconValue);
Yann 0:ebd3a7cc9b92 335 writeRegister(gpioGpintenId, gpioGpintenValue);
Yann 0:ebd3a7cc9b92 336
Yann 0:ebd3a7cc9b92 337 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: 0")
Yann 0:ebd3a7cc9b92 338 return 0;
Yann 0:ebd3a7cc9b92 339 }
Yann 0:ebd3a7cc9b92 340
Yann 0:ebd3a7cc9b92 341 int CMCP23017_I2C::getLastInterruptPin(unsigned char * p_gpioId, unsigned char * p_value) {
Yann 0:ebd3a7cc9b92 342 DEBUG_ENTER("CMCP23017_I2C::getLastInterruptPin")
Yann 0:ebd3a7cc9b92 343
Yann 0:ebd3a7cc9b92 344 // Read first INTFA if required
Yann 0:ebd3a7cc9b92 345 unsigned char vregister;
Yann 0:ebd3a7cc9b92 346 if (_gpioAFlags != 0x00) {
Yann 0:ebd3a7cc9b92 347 if (!readRegister(INTFA, &vregister)) {
Yann 0:ebd3a7cc9b92 348 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -1")
Yann 0:ebd3a7cc9b92 349 return -1;
Yann 0:ebd3a7cc9b92 350 }
Yann 0:ebd3a7cc9b92 351 vregister &= _gpioAFlags; // Cannot have interrupt on output port
Yann 0:ebd3a7cc9b92 352 for (unsigned char bit = 0; bit < GPIO_SIZE; bit++) {
Yann 0:ebd3a7cc9b92 353 if (isBitSet(vregister, bit)) {
Yann 0:ebd3a7cc9b92 354 *p_gpioId = bit;
Yann 0:ebd3a7cc9b92 355 readRegister(INTCAPA, p_value);
Yann 0:ebd3a7cc9b92 356 *p_value = (*p_value >> bit) & 0x01;
Yann 0:ebd3a7cc9b92 357
Yann 0:ebd3a7cc9b92 358 DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPin (A): %02x %02x", *p_gpioId, *p_value)
Yann 0:ebd3a7cc9b92 359 return 0;
Yann 0:ebd3a7cc9b92 360 }
Yann 0:ebd3a7cc9b92 361 } // End of 'for' statement
Yann 0:ebd3a7cc9b92 362 }
Yann 0:ebd3a7cc9b92 363
Yann 0:ebd3a7cc9b92 364 // If not interrupt on GPIOA, try with GPIOB
Yann 0:ebd3a7cc9b92 365 if (_gpioBFlags != 0x00) {
Yann 0:ebd3a7cc9b92 366 if (!readRegister(INTFB, &vregister)) {
Yann 0:ebd3a7cc9b92 367 DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 368 return -2;
Yann 0:ebd3a7cc9b92 369 }
Yann 0:ebd3a7cc9b92 370 vregister &= _gpioBFlags; // Cannot have interrupt on output port
Yann 0:ebd3a7cc9b92 371 for (unsigned char bit = 0; bit < GPIO_SIZE; bit++) {
Yann 0:ebd3a7cc9b92 372 if (isBitSet(vregister, bit)) {
Yann 0:ebd3a7cc9b92 373 *p_gpioId = bit + GPIO_SIZE;
Yann 0:ebd3a7cc9b92 374 readRegister(INTCAPB, p_value);
Yann 0:ebd3a7cc9b92 375 *p_value = (*p_value >> bit) & 0x01;
Yann 0:ebd3a7cc9b92 376
Yann 0:ebd3a7cc9b92 377 DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPin (B): %02x %02x", *p_gpioId, *p_value)
Yann 0:ebd3a7cc9b92 378 return 0;
Yann 0:ebd3a7cc9b92 379 }
Yann 0:ebd3a7cc9b92 380 } // End of 'for' statement
Yann 0:ebd3a7cc9b92 381 }
Yann 0:ebd3a7cc9b92 382
Yann 0:ebd3a7cc9b92 383 DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPin: 0")
Yann 0:ebd3a7cc9b92 384 return 0;
Yann 0:ebd3a7cc9b92 385 }
Yann 0:ebd3a7cc9b92 386
Yann 0:ebd3a7cc9b92 387 int CMCP23017_I2C::read(const unsigned char p_gpioId, unsigned char * p_value) {
Yann 0:ebd3a7cc9b92 388 DEBUG_ENTER("CMCP23017_I2C::read: 0x%02x", p_gpioId)
Yann 0:ebd3a7cc9b92 389
Yann 0:ebd3a7cc9b92 390 // Retrive the register address
Yann 0:ebd3a7cc9b92 391 unsigned char gpioRegisterId;
Yann 0:ebd3a7cc9b92 392 if (!registerIdFromGpioId(p_gpioId, &gpioRegisterId)) {
Yann 0:ebd3a7cc9b92 393 DEBUG_LEAVE("CMCP23017_I2C::read: -1")
Yann 0:ebd3a7cc9b92 394 return -1;
Yann 0:ebd3a7cc9b92 395 }
Yann 0:ebd3a7cc9b92 396 DEBUG("CMCP23017_I2C::read: gpioRegisterId=%02x", gpioRegisterId)
Yann 0:ebd3a7cc9b92 397 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 0:ebd3a7cc9b92 398 DEBUG("CMCP23017_I2C::read: gpioBit=%02x", gpioBit)
Yann 0:ebd3a7cc9b92 399
Yann 0:ebd3a7cc9b92 400 // Read it
Yann 0:ebd3a7cc9b92 401 unsigned char gpioRegisterValue;
Yann 0:ebd3a7cc9b92 402 if (!readRegister(gpioRegisterId, &gpioRegisterValue)) {
Yann 0:ebd3a7cc9b92 403 DEBUG_LEAVE("CMCP23017_I2C::read: -2")
Yann 0:ebd3a7cc9b92 404 return -2;
Yann 0:ebd3a7cc9b92 405 }
Yann 0:ebd3a7cc9b92 406 DEBUG("CMCP23017_I2C::read: gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 407
Yann 1:ec9e770173d5 408 *p_value = (isBitSet(gpioRegisterValue, gpioBit)) ? 0x01 : 0x00;
Yann 1:ec9e770173d5 409 DEBUG("CMCP23017_I2C::read: p_value=%02x", *p_value)
Yann 1:ec9e770173d5 410
Yann 0:ebd3a7cc9b92 411 DEBUG_LEAVE("CMCP23017_I2C::read: 0")
Yann 0:ebd3a7cc9b92 412 return 0;
Yann 0:ebd3a7cc9b92 413 }
Yann 0:ebd3a7cc9b92 414
Yann 0:ebd3a7cc9b92 415 bool CMCP23017_I2C::registerIdFromGpioId(const unsigned char p_gpioId, unsigned char * p_gpioRegisterId) {
Yann 0:ebd3a7cc9b92 416 DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: 0x%02x", p_gpioId)
Yann 0:ebd3a7cc9b92 417
Yann 0:ebd3a7cc9b92 418 // Sanity check
Yann 0:ebd3a7cc9b92 419 if (p_gpioId > GPIO_MAX) {
Yann 0:ebd3a7cc9b92 420 DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: false")
Yann 0:ebd3a7cc9b92 421 return false;
Yann 0:ebd3a7cc9b92 422 }
Yann 0:ebd3a7cc9b92 423
Yann 0:ebd3a7cc9b92 424 *p_gpioRegisterId = (p_gpioId < GPIO_MED) ? GPIOA : GPIOB;
Yann 0:ebd3a7cc9b92 425
Yann 0:ebd3a7cc9b92 426 DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: true")
Yann 0:ebd3a7cc9b92 427 return true;
Yann 0:ebd3a7cc9b92 428 }
Yann 0:ebd3a7cc9b92 429
Yann 0:ebd3a7cc9b92 430 int CMCP23017_I2C::write(const unsigned char p_gpioId, const unsigned char p_value) {
Yann 0:ebd3a7cc9b92 431 DEBUG_ENTER("CMCP23017_I2C::write: 0x%02x 0x%02x", p_gpioId, p_value)
Yann 0:ebd3a7cc9b92 432
Yann 0:ebd3a7cc9b92 433 // Retrive the register address
Yann 0:ebd3a7cc9b92 434 unsigned char gpioRegisterId;
Yann 0:ebd3a7cc9b92 435 if (!registerIdFromGpioId(p_gpioId, &gpioRegisterId)) {
Yann 0:ebd3a7cc9b92 436 DEBUG_LEAVE("CMCP23017_I2C::write: -1")
Yann 0:ebd3a7cc9b92 437 return -1;
Yann 0:ebd3a7cc9b92 438 }
Yann 0:ebd3a7cc9b92 439 DEBUG("CMCP23017_I2C::write: gpioRegisterId=%02x", gpioRegisterId)
Yann 0:ebd3a7cc9b92 440
Yann 0:ebd3a7cc9b92 441 // Retrive the GPIO pin number
Yann 0:ebd3a7cc9b92 442 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 0:ebd3a7cc9b92 443 DEBUG("CMCP23017_I2C::write: gpioBit=%02x", gpioBit)
Yann 0:ebd3a7cc9b92 444
Yann 0:ebd3a7cc9b92 445 // Read it
Yann 0:ebd3a7cc9b92 446 unsigned char gpioRegisterValue;
Yann 0:ebd3a7cc9b92 447 if (!readRegister(gpioRegisterId, &gpioRegisterValue)) {
Yann 0:ebd3a7cc9b92 448 DEBUG_LEAVE("CMCP23017_I2C::write: -2")
Yann 0:ebd3a7cc9b92 449 return -2;
Yann 0:ebd3a7cc9b92 450 }
Yann 0:ebd3a7cc9b92 451 DEBUG("CMCP23017_I2C::write: gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 452
Yann 0:ebd3a7cc9b92 453 // Update GPIO bit
Yann 0:ebd3a7cc9b92 454 if (!isBitEqual(gpioRegisterValue, gpioBit, p_value)) {
Yann 0:ebd3a7cc9b92 455 // Write it if required
Yann 0:ebd3a7cc9b92 456 gpioRegisterValue = setBit(gpioRegisterValue, gpioBit, p_value);
Yann 0:ebd3a7cc9b92 457 DEBUG("CMCP23017_I2C::write: New gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 458 if (!writeRegister(gpioRegisterId, gpioRegisterValue)) {
Yann 0:ebd3a7cc9b92 459 DEBUG_LEAVE("CMCP23017_I2C::write: -3")
Yann 0:ebd3a7cc9b92 460 return -3;
Yann 0:ebd3a7cc9b92 461 }
Yann 0:ebd3a7cc9b92 462 }
Yann 0:ebd3a7cc9b92 463
Yann 0:ebd3a7cc9b92 464 DEBUG_LEAVE("CMCP23017_I2C::write: 0")
Yann 0:ebd3a7cc9b92 465 return 0;
Yann 0:ebd3a7cc9b92 466 }
Yann 0:ebd3a7cc9b92 467
Yann 0:ebd3a7cc9b92 468 unsigned char CMCP23017_I2C::createBus(const std::list<unsigned char> p_lines, const PinMode p_mode) {
Yann 0:ebd3a7cc9b92 469 unsigned char busId = _busesIndex++;
Yann 0:ebd3a7cc9b92 470
Yann 0:ebd3a7cc9b92 471 _buses.insert(_buses.end(), std::pair<unsigned char, std::list<unsigned char> >(busId, p_lines));
Yann 0:ebd3a7cc9b92 472
Yann 0:ebd3a7cc9b92 473 return busId;
Yann 0:ebd3a7cc9b92 474 }
Yann 0:ebd3a7cc9b92 475
Yann 0:ebd3a7cc9b92 476 void CMCP23017_I2C::deleteBus(const unsigned char p_busId) {
Yann 0:ebd3a7cc9b92 477 // Sanity check
Yann 0:ebd3a7cc9b92 478 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 0:ebd3a7cc9b92 479 if (result == _buses.end()) { // Invalid bus identifier
Yann 0:ebd3a7cc9b92 480 return;
Yann 0:ebd3a7cc9b92 481 }
Yann 0:ebd3a7cc9b92 482
Yann 0:ebd3a7cc9b92 483 _buses.erase(p_busId);
Yann 0:ebd3a7cc9b92 484 }
Yann 0:ebd3a7cc9b92 485
Yann 1:ec9e770173d5 486 int CMCP23017_I2C::busRead(const unsigned char p_busId, unsigned short * p_value) {
Yann 1:ec9e770173d5 487 // Sanity checks
Yann 1:ec9e770173d5 488 if (_buses.size() == 0) {
Yann 1:ec9e770173d5 489 return -1;
Yann 1:ec9e770173d5 490 }
Yann 1:ec9e770173d5 491 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 1:ec9e770173d5 492 if (result == _buses.end()) { // Invalid bus identifier
Yann 1:ec9e770173d5 493 return -1;
Yann 1:ec9e770173d5 494 }
Yann 1:ec9e770173d5 495
Yann 1:ec9e770173d5 496 std::list<unsigned char>::reverse_iterator rit;
Yann 1:ec9e770173d5 497 for (std::list<unsigned char>::reverse_iterator rit = result->second.rbegin(); rit != result->second.rend(); ++rit) {
Yann 1:ec9e770173d5 498 unsigned char regvalue;
Yann 1:ec9e770173d5 499 if (read(*rit, &regvalue) == 0) {
Yann 1:ec9e770173d5 500 *p_value = (*p_value | regvalue) << 1;
Yann 1:ec9e770173d5 501 } else {
Yann 1:ec9e770173d5 502 *p_value <<= 1;
Yann 1:ec9e770173d5 503 }
Yann 1:ec9e770173d5 504 } // End of 'for' statement
Yann 1:ec9e770173d5 505
Yann 1:ec9e770173d5 506 return 0;
Yann 0:ebd3a7cc9b92 507 }
Yann 0:ebd3a7cc9b92 508
Yann 1:ec9e770173d5 509 int CMCP23017_I2C::busWrite(const unsigned char p_busId, const unsigned short p_value) {
Yann 1:ec9e770173d5 510 // Sanity checks
Yann 1:ec9e770173d5 511 if (_buses.size() == 0) {
Yann 1:ec9e770173d5 512 return -1;
Yann 1:ec9e770173d5 513 }
Yann 1:ec9e770173d5 514 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 1:ec9e770173d5 515 if (result == _buses.end()) { // Invalid bus identifier
Yann 1:ec9e770173d5 516 return -1;
Yann 1:ec9e770173d5 517 }
Yann 1:ec9e770173d5 518
Yann 1:ec9e770173d5 519 std::list<unsigned char>::reverse_iterator rit;
Yann 1:ec9e770173d5 520 unsigned short value = p_value;
Yann 1:ec9e770173d5 521 for (std::list<unsigned char>::reverse_iterator rit = result->second.rbegin(); rit != result->second.rend(); ++rit) {
Yann 1:ec9e770173d5 522 write(*rit, value & 0x01);
Yann 1:ec9e770173d5 523 value >>= 1;
Yann 1:ec9e770173d5 524 } // End of 'for' statement
Yann 1:ec9e770173d5 525
Yann 1:ec9e770173d5 526 return 0;
Yann 0:ebd3a7cc9b92 527 }
Yann 0:ebd3a7cc9b92 528
Yann 0:ebd3a7cc9b92 529 bool CMCP23017_I2C::writeRegister(const unsigned char p_registerId, const unsigned char p_value) {
Yann 0:ebd3a7cc9b92 530 // DEBUG_ENTER("CMCP23017_I2C::writeRegister: Memory address: 0x%02x - 0x%02x", p_registerId, p_value)
Yann 0:ebd3a7cc9b92 531
Yann 0:ebd3a7cc9b92 532 // 1.Prepare buffer
Yann 0:ebd3a7cc9b92 533 char i2cBuffer[2]; // Register address + one byte of data
Yann 0:ebd3a7cc9b92 534 // 1.1. Memory address
Yann 0:ebd3a7cc9b92 535 i2cBuffer[0] = p_registerId;
Yann 0:ebd3a7cc9b92 536 // 1.2. Datas
Yann 0:ebd3a7cc9b92 537 i2cBuffer[1] = p_value;
Yann 0:ebd3a7cc9b92 538 // DEBUG("CMCP23017_I2C::writeRegister: Data=0x%02x 0x%02x", i2cBuffer[0], i2cBuffer[1])
Yann 0:ebd3a7cc9b92 539
Yann 0:ebd3a7cc9b92 540 // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop
Yann 0:ebd3a7cc9b92 541 int result = _i2cInstance->write(_slaveAddress, i2cBuffer, 2);
Yann 0:ebd3a7cc9b92 542 // wait(0.02);
Yann 0:ebd3a7cc9b92 543
Yann 0:ebd3a7cc9b92 544 // DEBUG_LEAVE("CMCP23017_I2C::writeRegister %x", (bool)(result == 0))
Yann 0:ebd3a7cc9b92 545 return (bool)(result == 0);
Yann 0:ebd3a7cc9b92 546 }
Yann 0:ebd3a7cc9b92 547
Yann 0:ebd3a7cc9b92 548 bool CMCP23017_I2C::readRegister(const unsigned char p_registerId, unsigned char * p_value) {
Yann 0:ebd3a7cc9b92 549 // DEBUG_ENTER("CMCP23017_I2C::readRegister: Memory address: 0x%02x", p_registerId)
Yann 0:ebd3a7cc9b92 550
Yann 0:ebd3a7cc9b92 551 // 1.Prepare buffer
Yann 0:ebd3a7cc9b92 552 char i2cBuffer[1]; // Register address + one byte of data
Yann 0:ebd3a7cc9b92 553 // 1.1. Memory address
Yann 0:ebd3a7cc9b92 554 i2cBuffer[0] = p_registerId;
Yann 0:ebd3a7cc9b92 555 // DEBUG("CMCP23017_I2C::readRegister: Data=0x%02x", i2cBuffer[0])
Yann 0:ebd3a7cc9b92 556
Yann 0:ebd3a7cc9b92 557 // 2. Send I2C start + memory address
Yann 0:ebd3a7cc9b92 558 if (_i2cInstance->write(_slaveAddress, i2cBuffer, 1, true) == 0) {
Yann 0:ebd3a7cc9b92 559 // wait(0.02);
Yann 0:ebd3a7cc9b92 560 // DEBUG("CMCP23017_I2C::readRegister: Write memory done")
Yann 0:ebd3a7cc9b92 561 // 2. Read data + I2C stop
Yann 0:ebd3a7cc9b92 562 int result = _i2cInstance->read(_slaveAddress, (char *)p_value, 1);
Yann 0:ebd3a7cc9b92 563 // wait(0.02);
Yann 0:ebd3a7cc9b92 564
Yann 0:ebd3a7cc9b92 565 // DEBUG_LEAVE("C24LCXX_I2C::readRegister (byte): %x", (bool)(result == 0))
Yann 0:ebd3a7cc9b92 566 return (bool)(result == 0);
Yann 0:ebd3a7cc9b92 567 }
Yann 0:ebd3a7cc9b92 568
Yann 0:ebd3a7cc9b92 569 // DEBUG_LEAVE("CMCP23017_I2C::readRegister false")
Yann 0:ebd3a7cc9b92 570 return false;
Yann 0:ebd3a7cc9b92 571 }
Yann 0:ebd3a7cc9b92 572
Yann 0:ebd3a7cc9b92 573 void CMCP23017_I2C::DumpRegisters() {
Yann 0:ebd3a7cc9b92 574
Yann 0:ebd3a7cc9b92 575 unsigned char value;
Yann 0:ebd3a7cc9b92 576 for (unsigned int registerId = 0; registerId < 0x16; registerId++) {
Yann 0:ebd3a7cc9b92 577 readRegister(registerId, &value);
Yann 0:ebd3a7cc9b92 578 DEBUG("CMCP23017_I2C::DumpRegisters: register[%d] = 0x%02x", registerId, value)
Yann 0:ebd3a7cc9b92 579 }
Yann 0:ebd3a7cc9b92 580 }
Yann 0:ebd3a7cc9b92 581
Yann 0:ebd3a7cc9b92 582 void CMCP23017_I2C::DumpRegister(unsigned int p_registerId) {
Yann 0:ebd3a7cc9b92 583
Yann 0:ebd3a7cc9b92 584 unsigned char value;
Yann 0:ebd3a7cc9b92 585 readRegister(p_registerId, &value);
Yann 0:ebd3a7cc9b92 586 DEBUG("CMCP23017_I2C::DumpRegister: register[%d] = 0x%02x", p_registerId, value)
Yann 0:ebd3a7cc9b92 587 }
Yann 0:ebd3a7cc9b92 588
Yann 0:ebd3a7cc9b92 589 } // End of namespace MCP23017_I2C