Basic library of routines to interface to a Microchip MCP23017 16-bit I/O expander using an I2C interface.

Dependents:   Assignment_2_herpe Final_V1 ass2 ass2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MCP23017.cpp Source File

MCP23017.cpp

00001 /*  MCP23017 library for Arduino
00002     Copyright (C) 2009 David Pye    <davidmpye@gmail.com
00003     Modified for use on the MBED ARM platform
00004 
00005     This program is free software: you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation, either version 3 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 */
00018 
00019 #include "MCP23017.h"
00020 #include "mbed.h"
00021 
00022 union {
00023     uint8_t  value8[2];
00024     uint16_t value16;
00025 } tmp_data;
00026 
00027 /*-----------------------------------------------------------------------------
00028  *
00029  */
00030 MCP23017::MCP23017(PinName sda, PinName scl, int i2cAddress)  : _i2c(sda, scl) {
00031     MCP23017_i2cAddress = i2cAddress;
00032     reset();                                  // initialise chip to power-on condition
00033 }
00034 
00035 /*-----------------------------------------------------------------------------
00036  * reset
00037  * Set configuration (IOCON) and direction(IODIR) registers to initial state
00038  */
00039 void MCP23017::reset() {
00040 //
00041 // First make sure that the device is in BANK=0 mode
00042 //
00043     writeRegister(0x05, (unsigned char)0x00);
00044 //
00045 // set direction registers to inputs
00046 //
00047     writeRegister(IODIR, (unsigned short)0xFFFF);
00048 //
00049 // set all other registers to zero (last of 10 registers is OLAT)
00050 //
00051     for (int reg_addr = 2 ; reg_addr <= OLAT ; reg_addr+=2) {
00052         writeRegister(reg_addr, (unsigned short)0x0000);
00053     }
00054 //
00055 // Set the shadow registers to power-on state
00056 //
00057     shadow_IODIR = 0xFFFF;
00058     shadow_GPIO  = 0;
00059     shadow_GPPU  = 0;
00060     shadow_IPOL  = 0;
00061 }
00062 
00063 /*-----------------------------------------------------------------------------
00064  * write_bit
00065  * Write a 1/0 to a single bit of the 16-bit port
00066  */
00067 void MCP23017::write_bit(int value, int bit_number) {
00068     if (value == 0) {
00069         shadow_GPIO &= ~(1 << bit_number);
00070     } else {
00071         shadow_GPIO |= 1 << bit_number;
00072     }
00073     writeRegister(GPIO, (unsigned short)shadow_GPIO);
00074 }
00075 
00076 /*-----------------------------------------------------------------------------
00077  * Write a combination of bits to the 16-bit port
00078  */
00079 void MCP23017::write_mask(unsigned short data, unsigned short mask) {
00080     shadow_GPIO = (shadow_GPIO & ~mask) | data;
00081     writeRegister(GPIO, (unsigned short)shadow_GPIO);
00082 }
00083 
00084 /*-----------------------------------------------------------------------------
00085  * read_bit
00086  * Read a single bit from the 16-bit port
00087  */
00088 int  MCP23017::read_bit(int bit_number) {
00089     shadow_GPIO = readRegister(GPIO);
00090     return  ((shadow_GPIO >> bit_number) & 0x0001);
00091 }
00092 
00093 /*-----------------------------------------------------------------------------
00094  * read_mask
00095  */
00096 int  MCP23017::read_mask(unsigned short mask) {
00097     shadow_GPIO = readRegister(GPIO);
00098     return (shadow_GPIO & mask);
00099 }
00100 
00101 /*-----------------------------------------------------------------------------
00102  * Config
00103  * set direction and pull-up registers
00104  */
00105 void MCP23017::config(unsigned short dir_config, unsigned short pullup_config,  unsigned short polarity_config) {
00106     shadow_IODIR = dir_config;
00107     writeRegister(IODIR, (unsigned short)shadow_IODIR);
00108     shadow_GPPU = pullup_config;
00109     writeRegister(GPPU, (unsigned short)shadow_GPPU);
00110     shadow_IPOL = polarity_config;
00111     writeRegister(IPOL, (unsigned short)shadow_IPOL);
00112 }
00113 
00114 /*-----------------------------------------------------------------------------
00115  * writeRegister
00116  * write a byte
00117  */
00118 void MCP23017::writeRegister(int regAddress, unsigned char data) {
00119     char  buffer[2];
00120 
00121     buffer[0] = regAddress;
00122     buffer[1] = data;
00123     _i2c.write(MCP23017_i2cAddress, buffer, 2);
00124 }
00125 
00126 /*----------------------------------------------------------------------------
00127  * write Register
00128  * write two bytes
00129  */ 
00130 void MCP23017::writeRegister(int regAddress, unsigned short data) {
00131     char  buffer[3];
00132 
00133     buffer[0] = regAddress;
00134     tmp_data.value16 = data;
00135     buffer[1] = tmp_data.value8[0];
00136     buffer[2] = tmp_data.value8[1];
00137 
00138     _i2c.write(MCP23017_i2cAddress, buffer, 3);
00139 }
00140 
00141 /*-----------------------------------------------------------------------------
00142  * readRegister
00143  */
00144 int MCP23017::readRegister(int regAddress) {
00145     char buffer[2];
00146 
00147     buffer[0] = regAddress;
00148     _i2c.write(MCP23017_i2cAddress, buffer, 1);
00149     _i2c.read(MCP23017_i2cAddress, buffer, 2);
00150 
00151     return ((int)(buffer[0] + (buffer[1]<<8)));
00152 }
00153 
00154 /*-----------------------------------------------------------------------------
00155  * pinMode
00156  */
00157 void MCP23017::pinMode(int pin, int mode) {
00158     if (DIR_INPUT) {
00159         shadow_IODIR |= 1 << pin;
00160     } else {
00161         shadow_IODIR &= ~(1 << pin);
00162     }
00163     writeRegister(IODIR, (unsigned short)shadow_IODIR);
00164 }
00165 
00166 /*-----------------------------------------------------------------------------
00167  * digitalRead
00168  */
00169 int MCP23017::digitalRead(int pin) {
00170     shadow_GPIO = readRegister(GPIO);
00171     if ( shadow_GPIO & (1 << pin)) {
00172         return 1;
00173     } else {
00174         return 0;
00175     }
00176 }
00177 
00178 /*-----------------------------------------------------------------------------
00179  * digitalWrite
00180  */
00181 void MCP23017::digitalWrite(int pin, int val) {
00182     //If this pin is an INPUT pin, a write here will
00183     //enable the internal pullup
00184     //otherwise, it will set the OUTPUT voltage
00185     //as appropriate.
00186     bool isOutput = !(shadow_IODIR & 1<<pin);
00187 
00188     if (isOutput) {
00189         //This is an output pin so just write the value
00190         if (val) shadow_GPIO |= 1 << pin;
00191         else shadow_GPIO &= ~(1 << pin);
00192         writeRegister(GPIO, (unsigned short)shadow_GPIO);
00193     } else {
00194         //This is an input pin, so we need to enable the pullup
00195         if (val) {
00196             shadow_GPPU |= 1 << pin;
00197         } else {
00198             shadow_GPPU &= ~(1 << pin);
00199         }
00200         writeRegister(GPPU, (unsigned short)shadow_GPPU);
00201     }
00202 }
00203 
00204 /*-----------------------------------------------------------------------------
00205  * digitalWordRead
00206  */
00207 unsigned short MCP23017::digitalWordRead() {
00208     shadow_GPIO = readRegister(GPIO);
00209     return shadow_GPIO;
00210 }
00211 
00212 /*-----------------------------------------------------------------------------
00213  * digitalWordWrite
00214  */
00215 void MCP23017::digitalWordWrite(unsigned short w) {
00216     shadow_GPIO = w;
00217     writeRegister(GPIO, (unsigned short)shadow_GPIO);
00218 }
00219 
00220 /*-----------------------------------------------------------------------------
00221  * inputPolarityMask
00222  */
00223 void MCP23017::inputPolarityMask(unsigned short mask) {
00224     writeRegister(IPOL, mask);
00225 }
00226 
00227 /*-----------------------------------------------------------------------------
00228  * inputoutputMask
00229  */
00230 void MCP23017::inputOutputMask(unsigned short mask) {
00231     shadow_IODIR = mask;
00232     writeRegister(IODIR, (unsigned short)shadow_IODIR);
00233 }
00234 
00235 /*-----------------------------------------------------------------------------
00236  * internalPullupMask
00237  */
00238 void MCP23017::internalPullupMask(unsigned short mask) {
00239     shadow_GPPU = mask;
00240     writeRegister(GPPU, (unsigned short)shadow_GPPU);
00241 }
00242