Test application for the library MCP23017_I2C

Dependencies:   DebugLibrary MCP23017_I2C mbed

Files at this revision

API Documentation at this revision

Comitter:
Yann
Date:
Fri Jan 09 14:37:46 2015 +0000
Parent:
0:1d91b4046326
Child:
2:83b9df729e73
Commit message:
Add support of interruptions

Changed in this revision

MCP23017_I2C.lib Show annotated file Show diff for this revision Revisions of this file
MCP23017_I2C/AbstractGpioExpender.h Show diff for this revision Revisions of this file
MCP23017_I2C/MCP23017_I2C.cpp Show diff for this revision Revisions of this file
MCP23017_I2C/MCP23017_I2C.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017_I2C.lib	Fri Jan 09 14:37:46 2015 +0000
@@ -0,0 +1,1 @@
+MCP23017_I2C#ebd3a7cc9b92
--- a/MCP23017_I2C/AbstractGpioExpender.h	Wed Jan 07 09:49:59 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#pragma once
-
-#include <list>
-
-#include <mbed.h>
-
-#define GPA0    0
-#define GPA1    1
-#define GPA2    2
-#define GPA3    3
-#define GPA4    4
-#define GPA5    5
-#define GPA6    6
-#define GPA7    7
-#define GPB0    8
-#define GPB1    9
-#define GPB2    10
-#define GPB3    11
-#define GPB4    12
-#define GPB5    13
-#define GPB6    14
-#define GPB7    15
-
-class AbstractGpioExpender {
-public:
-    virtual void reset() = 0;
-
-    virtual void setupInterrupts(const unsigned char p_mirroring, const unsigned char p_open, const unsigned char p_polarity) = 0;
-    virtual void setupInterruptPin(const unsigned char p_pinId, const unsigned char p_mode) = 0;
-
-    virtual int read(const unsigned char p_pinId) = 0;
-    virtual int write(const unsigned char p_pinId, const unsigned char p_value) = 0;
-    
-    virtual unsigned char createBus(const std::list<unsigned char> p_lines, const PinMode p_mode = PullNone) = 0;
-    virtual void deleteBus(const unsigned char p_busId) = 0;
-    virtual int busRead(const unsigned char p_busId) = 0;
-    virtual int busWrite(const unsigned char p_busId, const unsigned char p_value) = 0;
-    
-protected:
-    virtual bool writeRegister(const unsigned char p_registerId, const unsigned char p_value) = 0;
-    virtual bool readRegister(const unsigned char p_registerId, unsigned char * p_value) = 0;
-
-}; // End of class AbstractGpioExpender 
\ No newline at end of file
--- a/MCP23017_I2C/MCP23017_I2C.cpp	Wed Jan 07 09:49:59 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,268 +0,0 @@
-/* mbed simplified access to Microchip MCP28x17 GPIO expender devices (I2C)
- * Copyright (c) 2010-2012 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 pinions 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.
- */
-#include <iostream>
-#include <sstream>
-
-#include "MCP23017_I2C.h"
-
-#define IODIRA      0x00
-#define IODIRB      0x01
-#define IPOLA       0x02
-#define IPOLB       0x03
-#define GPINTENA    0x04
-#define GPINTENB    0x05
-#define DEFVALA     0x06
-#define DEFVALB     0x07
-#define INTCONA     0x08
-#define INTCONB     0x09
-#define IOCON       0x0a
-#define GPPUA       0x0c
-#define GPPUB       0x0d
-#define INTFA       0x0e
-#define INTFB       0x0f
-#define INTCAPA     0x10
-#define INTCAPB     0x11
-#define GPIOA       0x12
-#define GPIOB       0x13
-#define OLATA       0x14
-#define OLATB       0x15
-
-namespace MCP23017_I2C {
-
-    unsigned char CMCP23017_I2C::I2CModuleRefCounter = 0;
-
-    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), _internalId("") {
-        DEBUG_ENTER("CMCP23017_I2C")
-
-        if (CMCP23017_I2C::I2CModuleRefCounter != 0) {
-            error("CMCP23017_I2C: Wrong params");
-        }
-#ifdef __DEBUG
-        std::ostringstream out(std::ostringstream::out);
-        out << "CMCP23017_I2C #" << CMCP23017_I2C::I2CModuleRefCounter;
-        _internalId.assign(out.str());
-        DEBUG("CMCP23017_I2C: _internalId='%s'", _internalId.c_str())
-#endif // __DEBUG
-        _i2cInstance = new I2C(p_sda, p_scl);
-        CMCP23017_I2C::I2CModuleRefCounter += 1;
-        DEBUG_ENTER("CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter)
-
-        _slaveAddress = (p_address << 1) | 0x40; // Slave address format is: 0 0 1 0 A3 A2 A1 R/W
-        DEBUG("CMCP23017_I2C: I2C slave adress: 0x%02x", _slaveAddress)
-        _i2cInstance->frequency(p_frequency); // Set the frequency of the I2C interface
-        
-        if (p_intA != NC) {
-            DEBUG("CMCP23017_I2C: INTA managed");
-            _intA = new InterruptIn(p_intA);
-            if (p_internalPullUp) _intA->mode(PullDown);
-            _intA->enable_irq(); // Enable interrupt
-        } else {
-            DEBUG("CMCP23017_I2C: INTA not managed");
-            _intA = NULL; // Not used
-        }
-        if (p_intB != NC) {
-            DEBUG("CMCP23017_I2C: INTB managed");
-            _intB = new InterruptIn(p_intB);
-            if (p_internalPullUp) _intB->mode(PullDown);
-            _intB->enable_irq(); // Enable interrupt
-        } else {
-            DEBUG("CMCP23017_I2C: INTB not managed");
-            _intB = NULL; // Not used
-        }
-        if (p_reset != NC) {
-            DEBUG("CMCP23017_I2C: RESET managed");
-            _reset = new DigitalOut(p_reset);
-            _reset->write(1); // Disable reset
-        } else {
-            DEBUG("CMCP23017_I2C: RESET not managed");
-            _reset = NULL; // Not used
-        }
-    
-        DEBUG_LEAVE("CMCP23017_I2C")
-    }
-
-    CMCP23017_I2C::~CMCP23017_I2C() {
-        DEBUG_ENTER("~CMCP23017_I2C")
-    
-        // Release I2C instance
-        DEBUG_ENTER("~CMCP23017_I2C: refCounter=%d", CMCP23017_I2C::I2CModuleRefCounter)
-        CMCP23017_I2C::I2CModuleRefCounter -= 1;
-        if (CMCP23017_I2C::I2CModuleRefCounter == 0) {
-            delete _i2cInstance;
-            _i2cInstance = NULL;
-        }
-        // Release _wp if required
-        if (_intA != NULL) {
-            delete _intA;
-        }
-        if (_intB != NULL) {
-            delete _intB;
-        }
-        if (_reset != NULL) {
-            delete _reset;
-        }
-    
-        DEBUG_LEAVE("~CMCP23017_I2C")
-    }
-    
-    bool CMCP23017_I2C::Initialize(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) {
-        
-        // Configure default behavior
-        _gpioAFlags = p_gpioAFlags;
-        _gpioBFlags = p_gpioBFlags;
-        configure(_gpioAFlags, _gpioBFlags);
-        
-        return true;
-    }
-    
-    void CMCP23017_I2C::reset() {
-        DEBUG_ENTER("CMCP23017_I2C::reset")
-        if (_reset != NULL) {
-            _reset->write(0);
-            wait_us(1);
-            _reset->write(1);
-            wait_us(1);
-            configure(_gpioAFlags, _gpioBFlags);
-        }
-        DEBUG_LEAVE("CMCP23017_I2C::reset")
-    }
-    
-    void CMCP23017_I2C::setupInterrupts(const unsigned char p_mirroring, const unsigned char p_open, const unsigned char p_polarity) {
-    }
-    
-    void CMCP23017_I2C::setupInterruptPin(const unsigned char p_pinId, const unsigned char p_mode) {
-    }
-    
-    int CMCP23017_I2C::read(const unsigned char p_pinId) {
-        DEBUG_ENTER("CMCP23017_I2C::read")
-        DEBUG_LEAVE("CMCP23017_I2C::read")
-        return -1;
-    }
-    
-    int CMCP23017_I2C::write(const unsigned char p_pinId, const unsigned char p_value) {
-        DEBUG_ENTER("CMCP23017_I2C::write")
-        
-        DEBUG_LEAVE("CMCP23017_I2C::write")
-        return -1;
-    }
-    
-    unsigned char CMCP23017_I2C::createBus(const std::list<unsigned char> p_lines, const PinMode p_mode) {
-        return 0xff;
-    }
-
-    void CMCP23017_I2C::deleteBus(const unsigned char p_busId) {
-    }
-
-    int CMCP23017_I2C::busRead(const unsigned char p_busId) {
-        return -1;
-    }
-
-    int CMCP23017_I2C::busWrite(const unsigned char p_busId, const unsigned char p_value) {
-        return -1;
-    }
-
-    void CMCP23017_I2C::configure(const unsigned char p_gpioAFlags, const unsigned char p_gpioBFlags) { // TODO Optimization with sequential access
-        DEBUG_ENTER("CMCP23017_I2C::configure")
-        
-        // Setup IOCON - See REGISTER 1-6: IOCON – I/O EXPANDER CONFIGURATION REGISTER
-        unsigned char vregister = 0x08;
-        writeRegister(IOCON, vregister);
-        // Setup IODIR - See REGISTER 1-1: IODIR – I/O DIRECTION REGISTER (ADDR 0x00)
-        writeRegister(IODIRA, p_gpioAFlags);
-        writeRegister(IODIRB, p_gpioBFlags);
-        // Setup IPOL - See REGISTER 1-2: IPOL – INPUT POLARITY PORT REGISTER
-        vregister = 0x00; // GPIO register bit will reflect the same logic state of the input pin
-        writeRegister(IPOLA, vregister);
-        writeRegister(IPOLB, vregister);
-        // Setup GPPU - See REGISTER 1-7: GPPU – GPIO PULL-UP RESISTOR REGISTER
-        writeRegister(GPPUA, p_gpioAFlags);
-        writeRegister(GPPUB, p_gpioBFlags);
-        
-        // Setup interrupt       
-        if (_intA != NULL) {
-            DEBUG("CMCP23017_I2C::configure: Setup INTA")
-            // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS
-            writeRegister(GPINTENA, p_gpioAFlags); // Enable GPIO input pin for interrupt-on-change event
-            // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER
-            vregister = 0x00; // Pin level change from 0 to 1 raises an interrupt
-            writeRegister(DEFVALA, vregister);
-            // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
-            vregister = 0xff; // Pin level change from 0 to 1 raises an interrupt
-            writeRegister(INTCONA, vregister);
-        }
-        if (_intB != NULL) {
-            DEBUG("CMCP23017_I2C::configure: Setup INTB")
-            // Setup GPINTEN - See GPINTEN – INTERRUPT-ON-CHANGE PINS
-            writeRegister(GPINTENB, p_gpioBFlags); // Enable GPIO input pin for interrupt-on-change event
-            // Setup DEFVAL - See REGISTER 1-4: DEFVAL – DEFAULT VALUE REGISTER
-            vregister = 0x00; // Pin level change from 0 to 1 raises an interrupt
-            writeRegister(DEFVALB, vregister);
-            // Setup INTCON - REGISTER 1-5: INTCON – INTERRUPT-ON-CHANGE CONTROL REGISTER
-            vregister = 0xff; // Pin level change from 0 to 1 raises an interrupt
-            writeRegister(INTCONB, vregister);
-        }
-        
-        DEBUG_LEAVE("CMCP23017_I2C::configure")
-    }
-    
-    bool CMCP23017_I2C::writeRegister(const unsigned char p_registerId, const unsigned char p_value) {
-        DEBUG_ENTER("CMCP23017_I2C::writeRegister: Memory address: 0x%02x - 0x%02x", p_registerId, p_value)
-    
-        // 1.Prepare buffer
-        char i2cBuffer[2]; // Register address + one byte of data
-        // 1.1. Memory address
-        i2cBuffer[0] = p_registerId;
-        // 1.2. Datas
-        i2cBuffer[1] = p_value;
-        DEBUG("CMCP23017_I2C::writeRegister: Data=0x%02x 0x%02x", i2cBuffer[0], i2cBuffer[1])
-    
-        // 2. Send I2C start + I2C address + Memory Address + Datas + I2C stop
-        int result = _i2cInstance->write(_slaveAddress, i2cBuffer, 2);
-        wait(0.02);
-    
-        DEBUG_LEAVE("CMCP23017_I2C::writeRegister %x", (bool)(result == 0))
-        return (bool)(result == 0);
-    }
-    
-    bool CMCP23017_I2C::readRegister(const unsigned char p_registerId, unsigned char * p_value) {
-        DEBUG_ENTER("CMCP23017_I2C::readRegister: Memory address: 0x%02x", p_registerId)
-    
-        // 1.Prepare buffer
-        char i2cBuffer[1]; // Register address + one byte of data
-        // 1.1. Memory address
-        i2cBuffer[0] = p_registerId;
-        DEBUG("CMCP23017_I2C::readRegister: Data=0x%02x", i2cBuffer[0])
-    
-        // 2. Send I2C start + memory address
-        if (_i2cInstance->write(_slaveAddress, i2cBuffer, 1, true) == 0) {
-            wait(0.02);
-//            DEBUG("CMCP23017_I2C::readRegister: Write memory done")
-            // 2. Read data + I2C stop
-            int result = _i2cInstance->read(_slaveAddress, (char *)p_value, 1);
-            wait(0.02);
-    
-            DEBUG_LEAVE("C24LCXX_I2C::readRegister (byte): %x", (bool)(result == 0))
-            return (bool)(result == 0);
-        }
-            
-        DEBUG_LEAVE("CMCP23017_I2C::readRegister false")
-        return false;
-    }
-    
-} // End of namespace MCP23017_I2C
--- a/MCP23017_I2C/MCP23017_I2C.h	Wed Jan 07 09:49:59 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/* 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 "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;
-        /** 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, const unsigned char open, const unsigned char polarity);
-        virtual void setupInterruptPin(const unsigned char p_pinId, const unsigned char mode);
-        
-        virtual int read(const unsigned char p_portId);
-        virtual int write(const unsigned char p_portId, 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);
-        
-    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);
-        
-        /** 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;
-
-    }; // End of class CMCP23017_I2C
-
-} // End of namespace _MCP23017_I2C
-
-using namespace MCP23017_I2C;
--- a/main.cpp	Wed Jan 07 09:49:59 2015 +0000
+++ b/main.cpp	Fri Jan 09 14:37:46 2015 +0000
@@ -11,6 +11,7 @@
 DigitalOut g_availableLed(LED1); // To verify if program in running
 Ticker g_available; // LED1 will flash with a period of 2s
 char DisplayMenuAndGetChoice();
+void GpioAIntr(); // Interrupt on GPIOA
 
 static CMCP23017_I2C g_gpioExp(p9, p10, 0x27, p15, p16, p17);
 
@@ -18,7 +19,9 @@
     // Launch available indicator
     g_available.attach(&AvailableIndicator, 2.0);
     
-    g_gpioExp.Initialize();
+    g_gpioExp.Initialize(0x01); // GpioA<0> as input port, no interrupt mirroring, Active low  
+    g_gpioExp.setupInterruptPin(GPA0, AbstractGpioExpender::OnFalling); // A switch with pull-up is connected to GPIOA<0>, interrupt on falling mode
+    g_gpioExp.setIntrACallback(GpioAIntr); // Set callback for interrup on GPIOA<0>
 
     while(true) {
         switch (DisplayMenuAndGetChoice()) {
@@ -34,6 +37,18 @@
             case 'd':
                 g_gpioExp.write(GPB2, 0);
                 break;
+            case 'e':
+                g_gpioExp.write(GPB3, 1);
+                break;
+            case 'f':
+                g_gpioExp.write(GPB3, 0);
+                break;
+            case 'g':
+                g_gpioExp.write(GPB7, 1);
+                break;
+            case 'h':
+                g_gpioExp.write(GPB7, 0);
+                break;
             case 'r':
                 g_gpioExp.reset();
                 break;
@@ -56,11 +71,23 @@
     std::cout << "\r" << std::endl << "\r" << std::endl << "MCP23017_I2C v0.1\r" << std::endl;
     std::cout << "\tSet PortB-0   :\t\ta\r" << std::endl;
     std::cout << "\tUnset PortB-0 :\t\tb\r" << std::endl;
-    std::cout << "\tUnset PortB-2 :\t\tc\r" << std::endl;
+    std::cout << "\tSet PortB-2   :\t\tc\r" << std::endl;
     std::cout << "\tUnset PortB-2 :\t\td\r" << std::endl;
+    std::cout << "\tSet PortB-3   :\t\te\r" << std::endl;
+    std::cout << "\tUnset PortB-3 :\t\tf\r" << std::endl;
+    std::cout << "\tSet PortB-7   :\t\tg\r" << std::endl;
+    std::cout << "\tUnset PortB-7 :\t\th\r" << std::endl;
     std::cout << "\tReset device  :\t\tr\r" << std::endl;
     std::cout << "Enter your choice: " << std::flush;
     value = getchar(); 
     std::cout << "\r" << std::endl;
     return value;
 }
+
+void GpioAIntr() {
+    unsigned char gpioId, gpioValue;
+    wait(0.6); // Debounce timer
+    g_gpioExp.getLastInterruptPin(&gpioId, &gpioValue); // Get interrupt info and clear it
+    std::cout << "\r" << std::endl << "GpioAIntr: interrupt on pin #" << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(gpioId) << " - value: " << static_cast<unsigned int>(gpioValue) << "\r" << std::endl;
+}
+