New project

Dependencies:   mbed TextLCD

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MCP23017.cpp Source File

MCP23017.cpp

00001 /* MCP23017 - drive the Microchip MCP23017 16-bit Port Extender using I2C
00002 * Copyright (c) 2010 Wim Huiskamp, Romilly Cocking (original version for SPI)
00003 *
00004 * Released under the MIT License: http://mbed.org/license/mit
00005 *
00006 * version 0.2 Initial Release
00007 * version 0.3 Cleaned up
00008 * version 0.4 Fixed problem with _read method
00009 * version 0.5 Added support for 'Banked' access to registers
00010 */
00011 
00012 #include "mbed.h"
00013 #include "MCP23017.h"
00014 
00015 /** Create an MCP23017 object connected to the specified I2C object and using the specified deviceAddress
00016 *
00017 * @param I2C &i2c the I2C port to connect to 
00018 * @param char deviceAddress the address of the MCP23017
00019 */
00020 MCP23017::MCP23017(I2C &i2c, char deviceAddress) : _i2c(i2c) {
00021     _writeOpcode = deviceAddress & 0xFE; // low order bit = 0 for write
00022     _readOpcode  = deviceAddress | 0x01; // low order bit = 1 for read
00023     _init();
00024 }
00025 
00026 /** Read from specified MCP23017 register
00027 *
00028 * @param char address the internal registeraddress of the MCP23017
00029 * @returns data from register 
00030 */
00031 char MCP23017::_read(char address) {
00032     char data[2];
00033 
00034     data[0] = address;
00035     _i2c.write(_writeOpcode, data, 1);     // Select Register for reading
00036     _i2c.read(_readOpcode, data, 1);       // Read from selected Register
00037     
00038     return data[0];
00039 }
00040 
00041 
00042 /** Write to specified MCP23017 register
00043 *
00044 * @param char address the internal registeraddress of the MCP23017
00045 */
00046 void MCP23017::_write(char address, char byte) {
00047     char data[2];
00048 
00049     data[0] = address;
00050     data[1] = byte;
00051     _i2c.write(_writeOpcode, data, 2);    // Write data to selected Register
00052 }
00053 
00054 
00055 /** Init MCP23017
00056 *
00057 * @param
00058 * @returns 
00059 */
00060 void MCP23017::_init() {
00061   
00062   _bankMode = NOT_BNK;  // This may not be true after software reset without hardware reset !!!
00063   
00064   _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BYTE_MODE | IOCON_HAEN )); // Hardware addressing on, no-autoincrement, 16 bit mode (operations toggle between A and B registers)
00065 
00066 }
00067 
00068 /** Set I/O direction of specified MCP23017 Port
00069 *
00070 * @param Port Port address (Port_A or Port_B)
00071 * @param char direction pin direction (0 = output, 1 = input)
00072 */
00073 void MCP23017::direction(Port port, char direction) {
00074     _write(IODIR_AB[_bankMode][port], direction);
00075 }
00076 
00077 /** Set Pull-Up Resistors on specified MCP23017 Port
00078 *
00079 * @param Port Port address (Port_A or Port_B)
00080 * @param char offOrOn per pin (0 = off, 1 = on)
00081 */
00082 void MCP23017::configurePullUps(Port port, char offOrOn) {
00083   
00084   _write(GPPU_AB[_bankMode][port], offOrOn); 
00085 }
00086 
00087 /** Configere the Banked or Non-Banked mode
00088 *
00089 * @param Bank bankMode
00090 * @param char offOrOn per pin (0 = off, 1 = on)
00091 */
00092 void MCP23017::configureBanked(Bank bankMode) {
00093 
00094     if (bankMode == NOT_BNK) {
00095       // Non-Banked sequential registers (default POR)
00096       // Hardware addressing on, , no-autoincrement, 16 bit mode (operations do toggle between A and B registers)          
00097       _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BYTE_MODE | IOCON_HAEN ));
00098       _bankMode = NOT_BNK;
00099     }  
00100     else {
00101       // Banked registers
00102       // Hardware addressing on, no-autoincrement, 8 bit mode           
00103       _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BANK | IOCON_BYTE_MODE | IOCON_HAEN ));
00104       _bankMode = BNK;
00105     }
00106 }
00107 
00108 
00109 void MCP23017::interruptEnable(Port port, char interruptsEnabledMask) {
00110   
00111   _write(GPINTEN_AB[_bankMode][port], interruptsEnabledMask);    
00112    
00113 }
00114 
00115 void MCP23017::mirrorInterrupts(bool mirror) {
00116   char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
00117 
00118   if (mirror) {
00119     iocon = iocon | INTERRUPT_MIRROR_BIT;
00120   }
00121   else {
00122     iocon = iocon & ~INTERRUPT_MIRROR_BIT;
00123   }
00124 
00125   _write(IOCON_AB[_bankMode][PORT_A], iocon);
00126 
00127 }
00128 
00129 void  MCP23017::interruptPolarity(Polarity polarity) {
00130     char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
00131     
00132     if (polarity == ACTIVE_LOW) {
00133         iocon = iocon & ~INTERRUPT_POLARITY_BIT;
00134     } else {
00135         iocon = iocon | INTERRUPT_POLARITY_BIT;
00136     }
00137     _write(IOCON_AB[_bankMode][PORT_A], iocon);
00138 }
00139 
00140 void MCP23017::defaultValue(Port port, char valuesToCompare) {
00141     
00142   _write(DEFVAL_AB[_bankMode][port], valuesToCompare);
00143     
00144 }
00145 
00146 void MCP23017::interruptControl(Port port, char interruptControlBits) {
00147     
00148   _write(INTCON_AB[_bankMode][port], interruptControlBits);
00149     
00150 }
00151 
00152 /** Write to specified MCP23017 Port
00153 *
00154 * @param Port Port address (Port_A or Port_B)
00155 * @param char byte data to write
00156 */
00157 void MCP23017::write(Port port, char byte) {
00158     _write(OLAT_AB[_bankMode][port], byte);
00159 }
00160     
00161 /** Read from specified MCP23017 Port
00162 *
00163 * @param Port Port address (Port_A or Port_B)
00164 * @returns data from Port 
00165 */
00166 char MCP23017::read(Port port) {
00167     return _read(GPIO_AB[_bankMode][port]);
00168 }
00169