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:
Tue Jan 13 10:20:02 2015 +0000
Revision:
3:b902729a1675
Parent:
2:3bea48e1505c
Remove DEBUG info

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 3:b902729a1675 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 3:b902729a1675 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 3:b902729a1675 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 3:b902729a1675 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 3:b902729a1675 72 // DEBUG("CMCP23017_I2C: INTA managed");
Yann 0:ebd3a7cc9b92 73 _intA = new InterruptIn(p_intA);
Yann 2:3bea48e1505c 74 if (p_internalPullUp) _intA->mode(::PullDown);
Yann 0:ebd3a7cc9b92 75 _intA->enable_irq(); // Enable interrupt
Yann 0:ebd3a7cc9b92 76 } else {
Yann 3:b902729a1675 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 3:b902729a1675 81 // DEBUG("CMCP23017_I2C: INTB managed");
Yann 0:ebd3a7cc9b92 82 _intB = new InterruptIn(p_intB);
Yann 2:3bea48e1505c 83 if (p_internalPullUp) _intB->mode(::PullDown);
Yann 0:ebd3a7cc9b92 84 _intB->enable_irq(); // Enable interrupt
Yann 0:ebd3a7cc9b92 85 } else {
Yann 3:b902729a1675 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 3:b902729a1675 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 3:b902729a1675 94 // DEBUG("CMCP23017_I2C: RESET not managed");
Yann 0:ebd3a7cc9b92 95 _reset = NULL; // Not used
Yann 0:ebd3a7cc9b92 96 }
Yann 0:ebd3a7cc9b92 97
Yann 3:b902729a1675 98 // DEBUG_LEAVE("CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 99 }
Yann 0:ebd3a7cc9b92 100
Yann 0:ebd3a7cc9b92 101 CMCP23017_I2C::~CMCP23017_I2C() {
Yann 3:b902729a1675 102 // DEBUG_ENTER("~CMCP23017_I2C")
Yann 0:ebd3a7cc9b92 103
Yann 0:ebd3a7cc9b92 104 // Release I2C instance
Yann 3:b902729a1675 105 // DEBUG("~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 3:b902729a1675 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 3:b902729a1675 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 3:b902729a1675 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 2:3bea48e1505c 275 // Retrieve the register address
Yann 0:ebd3a7cc9b92 276 unsigned char gpioIntconId, gpioDefvalId, gpioGpintenId;
Yann 0:ebd3a7cc9b92 277 if (!registerIdFromGpioId(p_gpioId, &gpioIntconId)) {
Yann 3:b902729a1675 278 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -1")
Yann 0:ebd3a7cc9b92 279 return -1;
Yann 0:ebd3a7cc9b92 280 }
Yann 2:3bea48e1505c 281 unsigned char gpioFlags;
Yann 0:ebd3a7cc9b92 282 if (gpioIntconId == GPIOA) {
Yann 0:ebd3a7cc9b92 283 gpioIntconId = INTCONA;
Yann 0:ebd3a7cc9b92 284 gpioDefvalId = DEFVALA;
Yann 0:ebd3a7cc9b92 285 gpioGpintenId = GPINTENA;
Yann 2:3bea48e1505c 286 gpioFlags = _gpioAFlags;
Yann 0:ebd3a7cc9b92 287 } else {
Yann 0:ebd3a7cc9b92 288 gpioIntconId = INTCONB;
Yann 0:ebd3a7cc9b92 289 gpioDefvalId = DEFVALB;
Yann 0:ebd3a7cc9b92 290 gpioGpintenId = GPINTENB;
Yann 2:3bea48e1505c 291 gpioFlags = _gpioBFlags;
Yann 0:ebd3a7cc9b92 292 }
Yann 2:3bea48e1505c 293 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconId=%02x gpioDefvalId=%02x gpioGpintenId=%02x gpioFlags=%02x", gpioIntconId, gpioDefvalId, gpioGpintenId, gpioFlags)
Yann 0:ebd3a7cc9b92 294
Yann 2:3bea48e1505c 295 // Retrieve the GPIO pin number
Yann 0:ebd3a7cc9b92 296 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 0:ebd3a7cc9b92 297 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioBit=%02x", gpioBit)
Yann 2:3bea48e1505c 298 if (!isBitEqual(gpioFlags, gpioBit, 0x01)) { // Port pin is not configure as input
Yann 3:b902729a1675 299 // DEBUG_LEAVE("CMCP23017_I2C::setupPullPin: -1")
Yann 2:3bea48e1505c 300 return -1;
Yann 2:3bea48e1505c 301 }
Yann 0:ebd3a7cc9b92 302 // Read it
Yann 0:ebd3a7cc9b92 303 unsigned char gpioIntconValue, gpioDefvalValue, gpioGpintenValue;
Yann 0:ebd3a7cc9b92 304 if (!readRegister(gpioIntconId, &gpioIntconValue)) {
Yann 3:b902729a1675 305 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 306 return -2;
Yann 0:ebd3a7cc9b92 307 }
Yann 0:ebd3a7cc9b92 308 if (!readRegister(gpioDefvalId, &gpioDefvalValue)) {
Yann 3:b902729a1675 309 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 310 return -2;
Yann 0:ebd3a7cc9b92 311 }
Yann 0:ebd3a7cc9b92 312 if (!readRegister(gpioGpintenId, &gpioGpintenValue)) {
Yann 3:b902729a1675 313 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 314 return -2;
Yann 0:ebd3a7cc9b92 315 }
Yann 0:ebd3a7cc9b92 316 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconValue=%02x gpioDefvalValue=%02x gpioGpintenValue=%02x", gpioIntconValue, gpioDefvalValue, gpioGpintenValue)
Yann 0:ebd3a7cc9b92 317
Yann 0:ebd3a7cc9b92 318 //
Yann 0:ebd3a7cc9b92 319 switch (static_cast<unsigned char>(p_mode)) {
Yann 0:ebd3a7cc9b92 320 case static_cast<unsigned char>(OnChange):
Yann 0:ebd3a7cc9b92 321 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 322 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 323 break;
Yann 0:ebd3a7cc9b92 324 case static_cast<unsigned char>(OnRising):
Yann 0:ebd3a7cc9b92 325 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 326 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x00);
Yann 0:ebd3a7cc9b92 327 break;
Yann 0:ebd3a7cc9b92 328 case static_cast<unsigned char>(OnFalling):
Yann 0:ebd3a7cc9b92 329 gpioIntconValue = setBit(gpioIntconValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 330 gpioDefvalValue = setBit(gpioDefvalValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 331 break;
Yann 0:ebd3a7cc9b92 332 } // End of 'switch' statement
Yann 0:ebd3a7cc9b92 333
Yann 0:ebd3a7cc9b92 334 // Enable interrupt
Yann 0:ebd3a7cc9b92 335 gpioGpintenValue = setBit(gpioGpintenValue, gpioBit, 0x01);
Yann 0:ebd3a7cc9b92 336
Yann 0:ebd3a7cc9b92 337 // Write register
Yann 0:ebd3a7cc9b92 338 DEBUG("CMCP23017_I2C::setupInterruptPin: gpioIntconValue=%02x gpioDefvalValue=%02x gpioGpintenValue=%02x", gpioIntconValue, gpioDefvalValue, gpioGpintenValue)
Yann 0:ebd3a7cc9b92 339 writeRegister(gpioDefvalId, gpioDefvalValue);
Yann 0:ebd3a7cc9b92 340 writeRegister(gpioIntconId, gpioIntconValue);
Yann 0:ebd3a7cc9b92 341 writeRegister(gpioGpintenId, gpioGpintenValue);
Yann 0:ebd3a7cc9b92 342
Yann 3:b902729a1675 343 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: 0")
Yann 0:ebd3a7cc9b92 344 return 0;
Yann 0:ebd3a7cc9b92 345 }
Yann 0:ebd3a7cc9b92 346
Yann 2:3bea48e1505c 347 int CMCP23017_I2C::setupPullPin(const unsigned char p_gpioId, const PullModes p_mode) {
Yann 3:b902729a1675 348 // DEBUG_ENTER("CMCP23017_I2C::setupPullPin: %02x, %02x", p_gpioId, p_mode)
Yann 2:3bea48e1505c 349
Yann 2:3bea48e1505c 350 // Retrieve the register address
Yann 2:3bea48e1505c 351 unsigned char gpioGppuId;
Yann 2:3bea48e1505c 352 if (!registerIdFromGpioId(p_gpioId, &gpioGppuId)) {
Yann 3:b902729a1675 353 // DEBUG_LEAVE("CMCP23017_I2C::setupPullPin: -1")
Yann 2:3bea48e1505c 354 return -1;
Yann 2:3bea48e1505c 355 }
Yann 2:3bea48e1505c 356 unsigned char gpioFlags;
Yann 2:3bea48e1505c 357 if (gpioGppuId == GPIOA) {
Yann 2:3bea48e1505c 358 gpioGppuId = GPPUA;
Yann 2:3bea48e1505c 359 gpioFlags = _gpioAFlags;
Yann 2:3bea48e1505c 360 } else {
Yann 2:3bea48e1505c 361 gpioGppuId = GPPUB;
Yann 2:3bea48e1505c 362 gpioFlags = _gpioBFlags;
Yann 2:3bea48e1505c 363 }
Yann 3:b902729a1675 364 // DEBUG("CMCP23017_I2C::setupPullPin: gpioGppuId=%02x gpioFlags=%02x", gpioGppuId, gpioFlags)
Yann 2:3bea48e1505c 365
Yann 2:3bea48e1505c 366 // Retrieve the GPIO pin number
Yann 2:3bea48e1505c 367 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 3:b902729a1675 368 // DEBUG("CMCP23017_I2C::setupPullPin: gpioBit=%02x", gpioBit)
Yann 2:3bea48e1505c 369 if (!isBitEqual(gpioFlags, gpioBit, 0x01)) { // Port pin is not configure as input
Yann 3:b902729a1675 370 // DEBUG_LEAVE("CMCP23017_I2C::setupPullPin: -1")
Yann 2:3bea48e1505c 371 return -1;
Yann 2:3bea48e1505c 372 }
Yann 2:3bea48e1505c 373
Yann 2:3bea48e1505c 374 // Read it
Yann 2:3bea48e1505c 375 unsigned char gpioGppuValue;
Yann 2:3bea48e1505c 376 if (!readRegister(gpioGppuId, &gpioGppuValue)) {
Yann 3:b902729a1675 377 // DEBUG_LEAVE("CMCP23017_I2C::setupPullPin: -2")
Yann 2:3bea48e1505c 378 return -2;
Yann 2:3bea48e1505c 379 }
Yann 3:b902729a1675 380 // DEBUG("CMCP23017_I2C::setupPullPin: gpioGppuId=%02x", gpioGppuId)
Yann 2:3bea48e1505c 381
Yann 2:3bea48e1505c 382 //
Yann 2:3bea48e1505c 383 switch (static_cast<unsigned char>(p_mode)) {
Yann 2:3bea48e1505c 384 case static_cast<unsigned char>(AbstractGpioExpender::PullOff):
Yann 2:3bea48e1505c 385 gpioGppuValue = setBit(gpioGppuValue, gpioBit, 0x00);
Yann 2:3bea48e1505c 386 break;
Yann 2:3bea48e1505c 387 case static_cast<unsigned char>(AbstractGpioExpender::PullUp):
Yann 2:3bea48e1505c 388 gpioGppuValue = setBit(gpioGppuValue, gpioBit, 0x01);
Yann 2:3bea48e1505c 389 break;
Yann 2:3bea48e1505c 390 case static_cast<unsigned char>(AbstractGpioExpender::PullDown):
Yann 2:3bea48e1505c 391 // Not supporte, nothing to do
Yann 2:3bea48e1505c 392 break;
Yann 2:3bea48e1505c 393 } // End of 'switch' statement
Yann 2:3bea48e1505c 394
Yann 2:3bea48e1505c 395 // Write register
Yann 3:b902729a1675 396 // DEBUG("CMCP23017_I2C::setupPullPin: gpioGppuValue=%02x", gpioGppuValue)
Yann 2:3bea48e1505c 397 writeRegister(gpioGppuId, gpioGppuValue);
Yann 2:3bea48e1505c 398
Yann 2:3bea48e1505c 399
Yann 3:b902729a1675 400 // DEBUG_LEAVE("CMCP23017_I2C::setupPullPin: 0")
Yann 2:3bea48e1505c 401 return 0;
Yann 2:3bea48e1505c 402 }
Yann 2:3bea48e1505c 403
Yann 2:3bea48e1505c 404 int CMCP23017_I2C::getLastInterruptPinAndValue(unsigned char * p_gpioId, unsigned char * p_value) {
Yann 3:b902729a1675 405 // DEBUG_ENTER("CMCP23017_I2C::getLastInterruptPinAndValue")
Yann 0:ebd3a7cc9b92 406
Yann 0:ebd3a7cc9b92 407 // Read first INTFA if required
Yann 0:ebd3a7cc9b92 408 unsigned char vregister;
Yann 0:ebd3a7cc9b92 409 if (_gpioAFlags != 0x00) {
Yann 0:ebd3a7cc9b92 410 if (!readRegister(INTFA, &vregister)) {
Yann 3:b902729a1675 411 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -1")
Yann 0:ebd3a7cc9b92 412 return -1;
Yann 0:ebd3a7cc9b92 413 }
Yann 0:ebd3a7cc9b92 414 vregister &= _gpioAFlags; // Cannot have interrupt on output port
Yann 0:ebd3a7cc9b92 415 for (unsigned char bit = 0; bit < GPIO_SIZE; bit++) {
Yann 0:ebd3a7cc9b92 416 if (isBitSet(vregister, bit)) {
Yann 0:ebd3a7cc9b92 417 *p_gpioId = bit;
Yann 0:ebd3a7cc9b92 418 readRegister(INTCAPA, p_value);
Yann 0:ebd3a7cc9b92 419 *p_value = (*p_value >> bit) & 0x01;
Yann 0:ebd3a7cc9b92 420
Yann 3:b902729a1675 421 // DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPinAndValue (A): %02x %02x", *p_gpioId, *p_value)
Yann 0:ebd3a7cc9b92 422 return 0;
Yann 0:ebd3a7cc9b92 423 }
Yann 0:ebd3a7cc9b92 424 } // End of 'for' statement
Yann 0:ebd3a7cc9b92 425 }
Yann 0:ebd3a7cc9b92 426
Yann 0:ebd3a7cc9b92 427 // If not interrupt on GPIOA, try with GPIOB
Yann 0:ebd3a7cc9b92 428 if (_gpioBFlags != 0x00) {
Yann 0:ebd3a7cc9b92 429 if (!readRegister(INTFB, &vregister)) {
Yann 3:b902729a1675 430 // DEBUG_LEAVE("CMCP23017_I2C::setupInterruptPin: -2")
Yann 0:ebd3a7cc9b92 431 return -2;
Yann 0:ebd3a7cc9b92 432 }
Yann 0:ebd3a7cc9b92 433 vregister &= _gpioBFlags; // Cannot have interrupt on output port
Yann 0:ebd3a7cc9b92 434 for (unsigned char bit = 0; bit < GPIO_SIZE; bit++) {
Yann 0:ebd3a7cc9b92 435 if (isBitSet(vregister, bit)) {
Yann 0:ebd3a7cc9b92 436 *p_gpioId = bit + GPIO_SIZE;
Yann 0:ebd3a7cc9b92 437 readRegister(INTCAPB, p_value);
Yann 0:ebd3a7cc9b92 438 *p_value = (*p_value >> bit) & 0x01;
Yann 0:ebd3a7cc9b92 439
Yann 3:b902729a1675 440 // DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPinAndValue (B): %02x %02x", *p_gpioId, *p_value)
Yann 0:ebd3a7cc9b92 441 return 0;
Yann 0:ebd3a7cc9b92 442 }
Yann 0:ebd3a7cc9b92 443 } // End of 'for' statement
Yann 0:ebd3a7cc9b92 444 }
Yann 0:ebd3a7cc9b92 445
Yann 3:b902729a1675 446 // DEBUG_LEAVE("CMCP23017_I2C::getLastInterruptPinAndValue: 0")
Yann 0:ebd3a7cc9b92 447 return 0;
Yann 0:ebd3a7cc9b92 448 }
Yann 0:ebd3a7cc9b92 449
Yann 0:ebd3a7cc9b92 450 int CMCP23017_I2C::read(const unsigned char p_gpioId, unsigned char * p_value) {
Yann 3:b902729a1675 451 // DEBUG_ENTER("CMCP23017_I2C::read: 0x%02x", p_gpioId)
Yann 0:ebd3a7cc9b92 452
Yann 2:3bea48e1505c 453 // Retrieve the register address
Yann 0:ebd3a7cc9b92 454 unsigned char gpioRegisterId;
Yann 0:ebd3a7cc9b92 455 if (!registerIdFromGpioId(p_gpioId, &gpioRegisterId)) {
Yann 3:b902729a1675 456 // DEBUG_LEAVE("CMCP23017_I2C::read: -1")
Yann 0:ebd3a7cc9b92 457 return -1;
Yann 0:ebd3a7cc9b92 458 }
Yann 3:b902729a1675 459 // DEBUG("CMCP23017_I2C::read: gpioRegisterId=%02x", gpioRegisterId)
Yann 0:ebd3a7cc9b92 460 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 3:b902729a1675 461 // DEBUG("CMCP23017_I2C::read: gpioBit=%02x", gpioBit)
Yann 0:ebd3a7cc9b92 462
Yann 0:ebd3a7cc9b92 463 // Read it
Yann 0:ebd3a7cc9b92 464 unsigned char gpioRegisterValue;
Yann 0:ebd3a7cc9b92 465 if (!readRegister(gpioRegisterId, &gpioRegisterValue)) {
Yann 3:b902729a1675 466 // DEBUG_LEAVE("CMCP23017_I2C::read: -2")
Yann 0:ebd3a7cc9b92 467 return -2;
Yann 0:ebd3a7cc9b92 468 }
Yann 3:b902729a1675 469 // DEBUG("CMCP23017_I2C::read: gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 470
Yann 1:ec9e770173d5 471 *p_value = (isBitSet(gpioRegisterValue, gpioBit)) ? 0x01 : 0x00;
Yann 3:b902729a1675 472 // DEBUG("CMCP23017_I2C::read: p_value=%02x", *p_value)
Yann 1:ec9e770173d5 473
Yann 3:b902729a1675 474 // DEBUG_LEAVE("CMCP23017_I2C::read: 0")
Yann 0:ebd3a7cc9b92 475 return 0;
Yann 0:ebd3a7cc9b92 476 }
Yann 0:ebd3a7cc9b92 477
Yann 0:ebd3a7cc9b92 478 bool CMCP23017_I2C::registerIdFromGpioId(const unsigned char p_gpioId, unsigned char * p_gpioRegisterId) {
Yann 3:b902729a1675 479 // DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: 0x%02x", p_gpioId)
Yann 0:ebd3a7cc9b92 480
Yann 0:ebd3a7cc9b92 481 // Sanity check
Yann 0:ebd3a7cc9b92 482 if (p_gpioId > GPIO_MAX) {
Yann 3:b902729a1675 483 // DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: false")
Yann 0:ebd3a7cc9b92 484 return false;
Yann 0:ebd3a7cc9b92 485 }
Yann 0:ebd3a7cc9b92 486
Yann 0:ebd3a7cc9b92 487 *p_gpioRegisterId = (p_gpioId < GPIO_MED) ? GPIOA : GPIOB;
Yann 0:ebd3a7cc9b92 488
Yann 3:b902729a1675 489 // DEBUG_ENTER("CMCP23017_I2C::registerIdFromGpioId: true")
Yann 0:ebd3a7cc9b92 490 return true;
Yann 0:ebd3a7cc9b92 491 }
Yann 0:ebd3a7cc9b92 492
Yann 0:ebd3a7cc9b92 493 int CMCP23017_I2C::write(const unsigned char p_gpioId, const unsigned char p_value) {
Yann 3:b902729a1675 494 // DEBUG_ENTER("CMCP23017_I2C::write: 0x%02x 0x%02x", p_gpioId, p_value)
Yann 0:ebd3a7cc9b92 495
Yann 2:3bea48e1505c 496 // Retrieve the register address
Yann 0:ebd3a7cc9b92 497 unsigned char gpioRegisterId;
Yann 0:ebd3a7cc9b92 498 if (!registerIdFromGpioId(p_gpioId, &gpioRegisterId)) {
Yann 3:b902729a1675 499 // DEBUG_LEAVE("CMCP23017_I2C::write: -1")
Yann 0:ebd3a7cc9b92 500 return -1;
Yann 0:ebd3a7cc9b92 501 }
Yann 3:b902729a1675 502 // DEBUG("CMCP23017_I2C::write: gpioRegisterId=%02x", gpioRegisterId)
Yann 0:ebd3a7cc9b92 503
Yann 2:3bea48e1505c 504 // Retrieve the GPIO pin number
Yann 0:ebd3a7cc9b92 505 unsigned char gpioBit = gpioBitFromGpioId(p_gpioId);
Yann 3:b902729a1675 506 // DEBUG("CMCP23017_I2C::write: gpioBit=%02x", gpioBit)
Yann 0:ebd3a7cc9b92 507
Yann 0:ebd3a7cc9b92 508 // Read it
Yann 0:ebd3a7cc9b92 509 unsigned char gpioRegisterValue;
Yann 0:ebd3a7cc9b92 510 if (!readRegister(gpioRegisterId, &gpioRegisterValue)) {
Yann 3:b902729a1675 511 // DEBUG_LEAVE("CMCP23017_I2C::write: -2")
Yann 0:ebd3a7cc9b92 512 return -2;
Yann 0:ebd3a7cc9b92 513 }
Yann 3:b902729a1675 514 // DEBUG("CMCP23017_I2C::write: gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 515
Yann 0:ebd3a7cc9b92 516 // Update GPIO bit
Yann 0:ebd3a7cc9b92 517 if (!isBitEqual(gpioRegisterValue, gpioBit, p_value)) {
Yann 0:ebd3a7cc9b92 518 // Write it if required
Yann 0:ebd3a7cc9b92 519 gpioRegisterValue = setBit(gpioRegisterValue, gpioBit, p_value);
Yann 3:b902729a1675 520 // DEBUG("CMCP23017_I2C::write: New gpioRegisterValue=%02x", gpioRegisterValue)
Yann 0:ebd3a7cc9b92 521 if (!writeRegister(gpioRegisterId, gpioRegisterValue)) {
Yann 3:b902729a1675 522 // DEBUG_LEAVE("CMCP23017_I2C::write: -3")
Yann 0:ebd3a7cc9b92 523 return -3;
Yann 0:ebd3a7cc9b92 524 }
Yann 0:ebd3a7cc9b92 525 }
Yann 0:ebd3a7cc9b92 526
Yann 3:b902729a1675 527 // DEBUG_LEAVE("CMCP23017_I2C::write: 0")
Yann 0:ebd3a7cc9b92 528 return 0;
Yann 0:ebd3a7cc9b92 529 }
Yann 0:ebd3a7cc9b92 530
Yann 0:ebd3a7cc9b92 531 unsigned char CMCP23017_I2C::createBus(const std::list<unsigned char> p_lines, const PinMode p_mode) {
Yann 0:ebd3a7cc9b92 532 unsigned char busId = _busesIndex++;
Yann 0:ebd3a7cc9b92 533
Yann 0:ebd3a7cc9b92 534 _buses.insert(_buses.end(), std::pair<unsigned char, std::list<unsigned char> >(busId, p_lines));
Yann 0:ebd3a7cc9b92 535
Yann 0:ebd3a7cc9b92 536 return busId;
Yann 0:ebd3a7cc9b92 537 }
Yann 0:ebd3a7cc9b92 538
Yann 0:ebd3a7cc9b92 539 void CMCP23017_I2C::deleteBus(const unsigned char p_busId) {
Yann 0:ebd3a7cc9b92 540 // Sanity check
Yann 0:ebd3a7cc9b92 541 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 0:ebd3a7cc9b92 542 if (result == _buses.end()) { // Invalid bus identifier
Yann 0:ebd3a7cc9b92 543 return;
Yann 0:ebd3a7cc9b92 544 }
Yann 0:ebd3a7cc9b92 545
Yann 0:ebd3a7cc9b92 546 _buses.erase(p_busId);
Yann 0:ebd3a7cc9b92 547 }
Yann 0:ebd3a7cc9b92 548
Yann 1:ec9e770173d5 549 int CMCP23017_I2C::busRead(const unsigned char p_busId, unsigned short * p_value) {
Yann 2:3bea48e1505c 550 // DEBUG_ENTER("CMCP23017_I2C::busRead: 0x%02x", p_busId)
Yann 2:3bea48e1505c 551
Yann 1:ec9e770173d5 552 // Sanity checks
Yann 1:ec9e770173d5 553 if (_buses.size() == 0) {
Yann 3:b902729a1675 554 // DEBUG_LEAVE("CMCP23017_I2C::busRead: -1")
Yann 1:ec9e770173d5 555 return -1;
Yann 1:ec9e770173d5 556 }
Yann 1:ec9e770173d5 557 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 1:ec9e770173d5 558 if (result == _buses.end()) { // Invalid bus identifier
Yann 3:b902729a1675 559 // DEBUG_LEAVE("CMCP23017_I2C::busRead: -1")
Yann 1:ec9e770173d5 560 return -1;
Yann 1:ec9e770173d5 561 }
Yann 1:ec9e770173d5 562
Yann 1:ec9e770173d5 563 std::list<unsigned char>::reverse_iterator rit;
Yann 1:ec9e770173d5 564 for (std::list<unsigned char>::reverse_iterator rit = result->second.rbegin(); rit != result->second.rend(); ++rit) {
Yann 1:ec9e770173d5 565 unsigned char regvalue;
Yann 1:ec9e770173d5 566 if (read(*rit, &regvalue) == 0) {
Yann 1:ec9e770173d5 567 *p_value = (*p_value | regvalue) << 1;
Yann 1:ec9e770173d5 568 } else {
Yann 1:ec9e770173d5 569 *p_value <<= 1;
Yann 1:ec9e770173d5 570 }
Yann 1:ec9e770173d5 571 } // End of 'for' statement
Yann 1:ec9e770173d5 572
Yann 2:3bea48e1505c 573 // DEBUG_LEAVE("CMCP23017_I2C::busRead: 0")
Yann 1:ec9e770173d5 574 return 0;
Yann 0:ebd3a7cc9b92 575 }
Yann 0:ebd3a7cc9b92 576
Yann 1:ec9e770173d5 577 int CMCP23017_I2C::busWrite(const unsigned char p_busId, const unsigned short p_value) {
Yann 2:3bea48e1505c 578 // DEBUG_ENTER("CMCP23017_I2C::busWrite: 0x%02x - 0x%02x", p_busId, p_value)
Yann 2:3bea48e1505c 579
Yann 1:ec9e770173d5 580 // Sanity checks
Yann 1:ec9e770173d5 581 if (_buses.size() == 0) {
Yann 1:ec9e770173d5 582 return -1;
Yann 1:ec9e770173d5 583 }
Yann 1:ec9e770173d5 584 std::map<unsigned char, std::list<unsigned char> >::iterator result = _buses.find(p_busId);
Yann 1:ec9e770173d5 585 if (result == _buses.end()) { // Invalid bus identifier
Yann 3:b902729a1675 586 // DEBUG_LEAVE("CMCP23017_I2C::busWrite: -1")
Yann 1:ec9e770173d5 587 return -1;
Yann 1:ec9e770173d5 588 }
Yann 1:ec9e770173d5 589
Yann 1:ec9e770173d5 590 std::list<unsigned char>::reverse_iterator rit;
Yann 1:ec9e770173d5 591 unsigned short value = p_value;
Yann 1:ec9e770173d5 592 for (std::list<unsigned char>::reverse_iterator rit = result->second.rbegin(); rit != result->second.rend(); ++rit) {
Yann 1:ec9e770173d5 593 write(*rit, value & 0x01);
Yann 1:ec9e770173d5 594 value >>= 1;
Yann 1:ec9e770173d5 595 } // End of 'for' statement
Yann 1:ec9e770173d5 596
Yann 2:3bea48e1505c 597 // DEBUG_LEAVE("CMCP23017_I2C::busWrite: 0")
Yann 1:ec9e770173d5 598 return 0;
Yann 0:ebd3a7cc9b92 599 }
Yann 0:ebd3a7cc9b92 600
Yann 0:ebd3a7cc9b92 601 bool CMCP23017_I2C::writeRegister(const unsigned char p_registerId, const unsigned char p_value) {
Yann 0:ebd3a7cc9b92 602 // DEBUG_ENTER("CMCP23017_I2C::writeRegister: Memory address: 0x%02x - 0x%02x", p_registerId, p_value)
Yann 0:ebd3a7cc9b92 603
Yann 0:ebd3a7cc9b92 604 // 1.Prepare buffer
Yann 0:ebd3a7cc9b92 605 char i2cBuffer[2]; // Register address + one byte of data
Yann 0:ebd3a7cc9b92 606 // 1.1. Memory address
Yann 0:ebd3a7cc9b92 607 i2cBuffer[0] = p_registerId;
Yann 0:ebd3a7cc9b92 608 // 1.2. Datas
Yann 0:ebd3a7cc9b92 609 i2cBuffer[1] = p_value;
Yann 0:ebd3a7cc9b92 610 // DEBUG("CMCP23017_I2C::writeRegister: Data=0x%02x 0x%02x", i2cBuffer[0], i2cBuffer[1])
Yann 0:ebd3a7cc9b92 611
Yann 0:ebd3a7cc9b92 612 // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop
Yann 0:ebd3a7cc9b92 613 int result = _i2cInstance->write(_slaveAddress, i2cBuffer, 2);
Yann 0:ebd3a7cc9b92 614 // wait(0.02);
Yann 0:ebd3a7cc9b92 615
Yann 0:ebd3a7cc9b92 616 // DEBUG_LEAVE("CMCP23017_I2C::writeRegister %x", (bool)(result == 0))
Yann 0:ebd3a7cc9b92 617 return (bool)(result == 0);
Yann 0:ebd3a7cc9b92 618 }
Yann 0:ebd3a7cc9b92 619
Yann 0:ebd3a7cc9b92 620 bool CMCP23017_I2C::readRegister(const unsigned char p_registerId, unsigned char * p_value) {
Yann 0:ebd3a7cc9b92 621 // DEBUG_ENTER("CMCP23017_I2C::readRegister: Memory address: 0x%02x", p_registerId)
Yann 0:ebd3a7cc9b92 622
Yann 0:ebd3a7cc9b92 623 // 1.Prepare buffer
Yann 0:ebd3a7cc9b92 624 char i2cBuffer[1]; // Register address + one byte of data
Yann 0:ebd3a7cc9b92 625 // 1.1. Memory address
Yann 0:ebd3a7cc9b92 626 i2cBuffer[0] = p_registerId;
Yann 0:ebd3a7cc9b92 627 // DEBUG("CMCP23017_I2C::readRegister: Data=0x%02x", i2cBuffer[0])
Yann 0:ebd3a7cc9b92 628
Yann 0:ebd3a7cc9b92 629 // 2. Send I2C start + memory address
Yann 0:ebd3a7cc9b92 630 if (_i2cInstance->write(_slaveAddress, i2cBuffer, 1, true) == 0) {
Yann 0:ebd3a7cc9b92 631 // wait(0.02);
Yann 0:ebd3a7cc9b92 632 // DEBUG("CMCP23017_I2C::readRegister: Write memory done")
Yann 0:ebd3a7cc9b92 633 // 2. Read data + I2C stop
Yann 0:ebd3a7cc9b92 634 int result = _i2cInstance->read(_slaveAddress, (char *)p_value, 1);
Yann 0:ebd3a7cc9b92 635 // wait(0.02);
Yann 0:ebd3a7cc9b92 636
Yann 0:ebd3a7cc9b92 637 // DEBUG_LEAVE("C24LCXX_I2C::readRegister (byte): %x", (bool)(result == 0))
Yann 0:ebd3a7cc9b92 638 return (bool)(result == 0);
Yann 0:ebd3a7cc9b92 639 }
Yann 0:ebd3a7cc9b92 640
Yann 0:ebd3a7cc9b92 641 // DEBUG_LEAVE("CMCP23017_I2C::readRegister false")
Yann 0:ebd3a7cc9b92 642 return false;
Yann 0:ebd3a7cc9b92 643 }
Yann 0:ebd3a7cc9b92 644
Yann 0:ebd3a7cc9b92 645 void CMCP23017_I2C::DumpRegisters() {
Yann 0:ebd3a7cc9b92 646
Yann 0:ebd3a7cc9b92 647 unsigned char value;
Yann 0:ebd3a7cc9b92 648 for (unsigned int registerId = 0; registerId < 0x16; registerId++) {
Yann 0:ebd3a7cc9b92 649 readRegister(registerId, &value);
Yann 3:b902729a1675 650 // DEBUG("CMCP23017_I2C::DumpRegisters: register[%d] = 0x%02x", registerId, value)
Yann 0:ebd3a7cc9b92 651 }
Yann 0:ebd3a7cc9b92 652 }
Yann 0:ebd3a7cc9b92 653
Yann 0:ebd3a7cc9b92 654 void CMCP23017_I2C::DumpRegister(unsigned int p_registerId) {
Yann 0:ebd3a7cc9b92 655
Yann 0:ebd3a7cc9b92 656 unsigned char value;
Yann 0:ebd3a7cc9b92 657 readRegister(p_registerId, &value);
Yann 3:b902729a1675 658 // DEBUG("CMCP23017_I2C::DumpRegister: register[%d] = 0x%02x", p_registerId, value)
Yann 0:ebd3a7cc9b92 659 }
Yann 0:ebd3a7cc9b92 660
Yann 0:ebd3a7cc9b92 661 } // End of namespace MCP23017_I2C