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

Dependents:   MCP23017App

Revision:
0:ebd3a7cc9b92
Child:
1:ec9e770173d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017_I2C.h	Fri Jan 09 14:37:42 2015 +0000
@@ -0,0 +1,197 @@
+/* mbed simplified access to Microchip MCP28x17 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;
+        
+        std::map<unsigned char, std::list<unsigned char> > _buses;
+        
+        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();
+        
+        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, negative value otherwise
+         */
+        virtual int setupInterruptPin(const unsigned char p_gpioId, const InterruptModes p_mode = OnRising);
+        virtual int getLastInterruptPin(unsigned char * p_gpioId, unsigned char * p_value);
+        
+        virtual int read(const unsigned char p_gpioId, unsigned char * p_value);
+        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);
+        virtual int busWrite(const unsigned char p_busId, const unsigned char p_value);
+        
+        /** Attach a function to call when a interrupt occurs on the GPIOA input ports
+         */
+        virtual void setIntrACallback(void (* p_fptr)(void));
+        
+        /** Attach a function to call when a rising edge occurs on the input
+         */
+        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;