Test application for the library MCP23017_I2C

Dependencies:   DebugLibrary MCP23017_I2C mbed

Files at this revision

API Documentation at this revision

Comitter:
Yann
Date:
Wed Jan 07 09:49:59 2015 +0000
Child:
1:e981573db063
Commit message:
Start implementing support of MCP28017

Changed in this revision

DebugLibrary.lib Show annotated file Show diff for this revision Revisions of this file
MCP23017_I2C/AbstractGpioExpender.h Show annotated file Show diff for this revision Revisions of this file
MCP23017_I2C/MCP23017_I2C.cpp Show annotated file Show diff for this revision Revisions of this file
MCP23017_I2C/MCP23017_I2C.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebugLibrary.lib	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Yann/code/DebugLibrary/#a11adabe9ded
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017_I2C/AbstractGpioExpender.h	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,43 @@
+#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017_I2C/MCP23017_I2C.cpp	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,268 @@
+/* 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017_I2C/MCP23017_I2C.h	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,145 @@
+/* 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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,66 @@
+#include <string>
+#include <iostream>
+#include <iomanip>
+
+#include "MCP23017_I2C.h"
+
+/*
+ * Declare functions
+ */
+void AvailableIndicator(); // LED1 flashing for program while program is alive
+DigitalOut g_availableLed(LED1); // To verify if program in running
+Ticker g_available; // LED1 will flash with a period of 2s
+char DisplayMenuAndGetChoice();
+
+static CMCP23017_I2C g_gpioExp(p9, p10, 0x27, p15, p16, p17);
+
+int main() {
+    // Launch available indicator
+    g_available.attach(&AvailableIndicator, 2.0);
+    
+    g_gpioExp.Initialize();
+
+    while(true) {
+        switch (DisplayMenuAndGetChoice()) {
+            case 'a':
+                g_gpioExp.write(GPB0, 1);
+                break;
+            case 'b':
+                g_gpioExp.write(GPB0, 0);
+                break;
+            case 'c':
+                g_gpioExp.write(GPB2, 1);
+                break;
+            case 'd':
+                g_gpioExp.write(GPB2, 0);
+                break;
+            case 'r':
+                g_gpioExp.reset();
+                break;
+            default:
+                std::cout << "Invalid user choice\r" << std::endl;
+                break;
+        } // End of 'switch' statement
+        
+    } // End of 'while' loop
+}
+
+void AvailableIndicator()
+{
+    g_availableLed = !g_availableLed;
+} // End of AvailableIndicator
+
+char DisplayMenuAndGetChoice()
+{
+    char value;
+    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 << "\tUnset PortB-2 :\t\td\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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jan 07 09:49:59 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/4fc01daae5a5
\ No newline at end of file