This library provides simplified I2C access to a Microchip MCP23x17 GPIO expender device, including a general interface for any GPIO expender
MCP23017_I2C.h
- Committer:
- Yann
- Date:
- 2015-01-13
- Revision:
- 3:b902729a1675
- Parent:
- 2:3bea48e1505c
File content as of revision 3:b902729a1675:
/* mbed simplified access to Microchip MCP23x17 GPIO expender devices (I2C) * Copyright (c) 2014-2015 ygarcia, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include <map> #include "Debug.h" #include "AbstractGpioExpender.h" namespace MCP23017_I2C { /** This class provides simplified I2C access to a Microchip 2MCP28x17 GPIO expender. V0.0.0.1 * * Note that if the LPC1768 is powered in 3.3V and Microchip MCP28x17 GPIO expender device could be powered at 3.3V or 5V. * In this case, you shall use a bi-directional level shifter for I2C-bus. Please refer to AN97055 (http://ics.nxp.com/support/documents/interface/pdf/an97055.pdf) * Microchip MCP28x17 GPIO expender device reference: DS21952B * * Note that for I2C details, please visit http://www.datelec.fr/fiches/I2C.htm * * Note that this header file include following headers: * - <string> * - <vector> * - <mbed.h> * * @author Yann Garcia (Don't hesitate to contact me: garcia.yann@gmail.com) */ class CMCP23017_I2C : public AbstractGpioExpender { /** Reference counter used to guarentee unicity of the instance of I2C class */ static unsigned char I2CModuleRefCounter; /** Device address input: A0, A1, A2 (Pins <1,3>). See DS21203K/DS21189D - Figure 5-1: Control Byte Format for address format details */ unsigned char _slaveAddress; /** Interrupt on GPIOA */ InterruptIn *_intA; /** Interrupt on GPIOB */ InterruptIn *_intB; /** Device reset pin */ DigitalOut *_reset; /** PortA config */ unsigned char _gpioAFlags; /** PortB config */ unsigned char _gpioBFlags; /** Map of declared buses */ std::map<unsigned char, std::list<unsigned char> > _buses; /** Buses identifier index */ unsigned char _busesIndex; /** An unique instance of I2C class */ I2C *_i2cInstance; public: /** Constructor with Write Protect command pin wired. Use it to manage the first I2C module on 3.3V or 5V network * * @param p_sda: MBed pin for SDA * @param p_scl: MBed pin for SCL * @param p_address: Device address input: A0, A1, A2 (Pins <1,3>) * @param p_intA: MBed pin to manage interrupt on GPIOA, default value is NC, not connected * @param p_intB: MBed pin to manage device reset. If NC, WP is not managed, default value is NC, not connected * @param p_reset: MBed pin to manage Write Protect input. If NC, WP is not managed, default value is NC, not connected * @param p_internalPullUp: Set to true to use internal pull-up resistor, default value is true * @param p_frequency: Frequency of the I2C interface (SCL), default value is 400KHz * Example: * - If A1 and A2 pins are tired to Vdd and A0 is tired to Vss, address shall '00000110'B * - If A0 and A1 pins are tired to Vss and A2 is tired to Vdd, address shall '00000100'B */ CMCP23017_I2C(const PinName p_sda, const PinName p_scl, const unsigned char p_address, const PinName p_intA = NC, const PinName p_intB = NC, const PinName p_reset = NC, const bool p_internalPullUp = true, const unsigned int p_frequency = 400000); /** Destructor */ virtual ~CMCP23017_I2C(); /** Initialize the module, configuring the module and starting the clock * @param p_gpioAFlags GPIO A port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs * @param p_gpioBFlags GPIO B port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs * * @return true on success, false otherwise */ bool Initialize(const unsigned char p_gpioAFlags = 0x00, const unsigned char p_gpioBFlags = 0x00); /** Used to return the unique instance of I2C instance */ inline const I2C * operator * () { return (const I2C *)_i2cInstance; }; /** Reset the device */ virtual void reset(); /** Setup device interrupt mechanism * @param p_mirroring Set to 0x00 to disable INTA/B mirroring, 0x01 otherwise. Default: 0x00 * @param p_openDrain Set to 0x00 for active driver output, 0x01 for opn drain output. Default: 0x00 * @param p_polarity Set to 0x00 for interrupt active low, 0x01 otherwise. Default: 0x00 */ virtual void setupInterrupts(const unsigned char mirroring = 0x00, const unsigned char p_openDrain = 0x00, const unsigned char polarity = 0x00); /** Setup interrupt for a specific IO port * @param p_pinId The IO port identifier * @param p_mode The interrupt mode * @return 0 on success, -1 on wrong parameters and -2 otherwise */ virtual int setupInterruptPin(const unsigned char p_gpioId, const InterruptModes p_mode = OnRising); /** Setup pull mode for a specific IO port * @param p_gpioId The IO port identifier * @param p_mode The interrupt mode * @return 0 on success, -1 on wrong parameters and -2 otherwise */ virtual int setupPullPin(const unsigned char p_gpioId, const PullModes p_mode = PullOff); /** Get interrupt information and clear it * @param p_gpioId The IO port identifier where the interrupt occured * @param p_value The logic value on the pin port where the interrupt occured * @return 0 on success, -1 on wrong parameters and -2 otherwise */ virtual int getLastInterruptPinAndValue(unsigned char * p_gpioId, unsigned char * p_value); /** Read the specific GPIO port pin * @param p_gpioId The GPIO port pin to be read * @param p_value The GPIO port pin value * @return 0 on success, -1 on wrong parameters and -2 otherwise */ virtual int read(const unsigned char p_gpioId, unsigned char * p_value); /** Write value to the specific GPIO port pin * @param p_gpioId The GPIO port pin to be written * @param p_value The GPIO port pin value * @return 0 on success, -1 on wrong parameters and -2 otherwise */ virtual int write(const unsigned char p_gpioId, const unsigned char p_value); virtual unsigned char createBus(const std::list<unsigned char> p_lines, const PinMode p_mode = PullNone); virtual void deleteBus(const unsigned char p_busId); virtual int busRead(const unsigned char p_busId, unsigned short * p_value); virtual int busWrite(const unsigned char p_busId, const unsigned short p_value); /** Attach a function to call when a interrupt occurs on the GPIOA input ports * @param p_fptr The pointer to the "C" callback function */ virtual void setIntrACallback(void (* p_fptr)(void)); /** Attach a function to call when a interrupt occurs on the GPIOB input ports * @param p_fptr The pointer to the "C" callback function */ virtual void setIntrBCallback(void (* p_fptr)(void)); /** Attach a member function to call when a interrupt occurs on the GPIOA input ports */ template<typename T> void setIntrACallback(const T * p_tptr, void(T::* p_mptr)(void)); /** Attach a member function to call when a rising edge occurs on the input */ template<typename T> void setIntrBCallback(const T * p_tptr, void(T::* p_mptr)(void)); private: /** Configure the device: * BANK0 (A register followed by B register) * INTs: active low * INTs for all ports * INTs are not mirrored * @param p_gpioAFlags GPIO A port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs * @param p_gpioBFlags GPIO B port configuration: bit set for input mode, 0 for output mode. Default: ports as outputs */ void configure(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags); bool registerIdFromGpioId(const unsigned char p_gpioId, unsigned char * p_gpioRegisterId); inline unsigned char gpioBitFromGpioId(const unsigned char p_gpioId) { return static_cast<unsigned char>((p_gpioId < GPIO_MED) ? p_gpioId : (p_gpioId - GPIO_MED)); }; inline bool isBitSet(const unsigned char p_gpioRegisterValue, const unsigned char p_gpioBit) { return (bool)((unsigned char)(p_gpioRegisterValue >> p_gpioBit) == 0x01); }; inline bool isBitEqual(const unsigned char p_gpioRegisterValue, const unsigned char p_gpioBit, const unsigned char p_value) { return (bool)((unsigned char)(p_gpioRegisterValue >> p_gpioBit) == (p_value & 0x01)); }; inline unsigned char setBit(unsigned char p_gpioRegisterValue, const unsigned char p_gpioBit, const unsigned char p_value) { return (p_gpioRegisterValue & ~(1 << p_gpioBit)) | ((p_value & 0x01) << p_gpioBit); }; protected: /** Write value to a register * @param p_address The register address * @param p_byte The value to write to the register * @return 1 on success, false otherwise */ virtual bool writeRegister(const unsigned char p_registerId, const unsigned char p_value); virtual bool readRegister(const unsigned char p_registerId, unsigned char * p_value); private: /** Internal reference identifier */ std::string _internalId; void DumpRegisters(); void DumpRegister(unsigned int p_registerId); }; // End of class CMCP23017_I2C } // End of namespace _MCP23017_I2C using namespace MCP23017_I2C;