Files at this revision

API Documentation at this revision

Comitter:
GobertPierre
Date:
Fri Apr 13 17:44:17 2012 +0000
Commit message:

Changed in this revision

MCP23017.cpp Show annotated file Show diff for this revision Revisions of this file
MCP23017.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017.cpp	Fri Apr 13 17:44:17 2012 +0000
@@ -0,0 +1,242 @@
+/*  MCP23017 library for Arduino
+    Copyright (C) 2009 David Pye    <davidmpye@gmail.com
+    Modified for use on the MBED ARM platform
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "MCP23017.h"
+#include "mbed.h"
+
+union {
+    uint8_t  value8[2];
+    uint16_t value16;
+} tmp_data;
+
+/*-----------------------------------------------------------------------------
+ *
+ */
+MCP23017::MCP23017(PinName sda, PinName scl, int i2cAddress)  : _i2c(sda, scl) {
+    MCP23017_i2cAddress = i2cAddress;
+    reset();                                  // initialise chip to power-on condition
+}
+
+/*-----------------------------------------------------------------------------
+ * reset
+ * Set configuration (IOCON) and direction(IODIR) registers to initial state
+ */
+void MCP23017::reset() {
+//
+// First make sure that the device is in BANK=0 mode
+//
+    writeRegister(0x05, (unsigned char)0x00);
+//
+// set direction registers to inputs
+//
+    writeRegister(IODIR, (unsigned short)0xFFFF);
+//
+// set all other registers to zero (last of 10 registers is OLAT)
+//
+    for (int reg_addr = 2 ; reg_addr <= OLAT ; reg_addr+=2) {
+        writeRegister(reg_addr, (unsigned short)0x0000);
+    }
+//
+// Set the shadow registers to power-on state
+//
+    shadow_IODIR = 0xFFFF;
+    shadow_GPIO  = 0;
+    shadow_GPPU  = 0;
+    shadow_IPOL  = 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * write_bit
+ * Write a 1/0 to a single bit of the 16-bit port
+ */
+void MCP23017::write_bit(int value, int bit_number) {
+    if (value == 0) {
+        shadow_GPIO &= ~(1 << bit_number);
+    } else {
+        shadow_GPIO |= 1 << bit_number;
+    }
+    writeRegister(GPIO, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * Write a combination of bits to the 16-bit port
+ */
+void MCP23017::write_mask(unsigned short data, unsigned short mask) {
+    shadow_GPIO = (shadow_GPIO & ~mask) | data;
+    writeRegister(GPIO, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * read_bit
+ * Read a single bit from the 16-bit port
+ */
+int  MCP23017::read_bit(int bit_number) {
+    shadow_GPIO = readRegister(GPIO);
+    return  ((shadow_GPIO >> bit_number) & 0x0001);
+}
+
+/*-----------------------------------------------------------------------------
+ * read_mask
+ */
+int  MCP23017::read_mask(unsigned short mask) {
+    shadow_GPIO = readRegister(GPIO);
+    return (shadow_GPIO & mask);
+}
+
+/*-----------------------------------------------------------------------------
+ * Config
+ * set direction and pull-up registers
+ */
+void MCP23017::config(unsigned short dir_config, unsigned short pullup_config,  unsigned short polarity_config) {
+    shadow_IODIR = dir_config;
+    writeRegister(IODIR, (unsigned short)shadow_IODIR);
+    shadow_GPPU = pullup_config;
+    writeRegister(GPPU, (unsigned short)shadow_GPPU);
+    shadow_IPOL = polarity_config;
+    writeRegister(IPOL, (unsigned short)shadow_IPOL);
+}
+
+/*-----------------------------------------------------------------------------
+ * writeRegister
+ * write a byte
+ */
+void MCP23017::writeRegister(int regAddress, unsigned char data) {
+    char  buffer[2];
+
+    buffer[0] = regAddress;
+    buffer[1] = data;
+    _i2c.write(MCP23017_i2cAddress, buffer, 2);
+}
+
+/*----------------------------------------------------------------------------
+ * write Register
+ * write two bytes
+ */ 
+void MCP23017::writeRegister(int regAddress, unsigned short data) {
+    char  buffer[3];
+
+    buffer[0] = regAddress;
+    tmp_data.value16 = data;
+    buffer[1] = tmp_data.value8[0];
+    buffer[2] = tmp_data.value8[1];
+
+    _i2c.write(MCP23017_i2cAddress, buffer, 3);
+}
+
+/*-----------------------------------------------------------------------------
+ * readRegister
+ */
+int MCP23017::readRegister(int regAddress) {
+    char buffer[2];
+
+    buffer[0] = regAddress;
+    _i2c.write(MCP23017_i2cAddress, buffer, 1);
+    _i2c.read(MCP23017_i2cAddress, buffer, 2);
+
+    return ((int)(buffer[0] + (buffer[1]<<8)));
+}
+
+/*-----------------------------------------------------------------------------
+ * pinMode
+ */
+void MCP23017::pinMode(int pin, int mode) {
+    if (DIR_INPUT) {
+        shadow_IODIR |= 1 << pin;
+    } else {
+        shadow_IODIR &= ~(1 << pin);
+    }
+    writeRegister(IODIR, (unsigned short)shadow_IODIR);
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalRead
+ */
+int MCP23017::digitalRead(int pin) {
+    shadow_GPIO = readRegister(GPIO);
+    if ( shadow_GPIO & (1 << pin)) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWrite
+ */
+void MCP23017::digitalWrite(int pin, int val) {
+    //If this pin is an INPUT pin, a write here will
+    //enable the internal pullup
+    //otherwise, it will set the OUTPUT voltage
+    //as appropriate.
+    bool isOutput = !(shadow_IODIR & 1<<pin);
+
+    if (isOutput) {
+        //This is an output pin so just write the value
+        if (val) shadow_GPIO |= 1 << pin;
+        else shadow_GPIO &= ~(1 << pin);
+        writeRegister(GPIO, (unsigned short)shadow_GPIO);
+    } else {
+        //This is an input pin, so we need to enable the pullup
+        if (val) {
+            shadow_GPPU |= 1 << pin;
+        } else {
+            shadow_GPPU &= ~(1 << pin);
+        }
+        writeRegister(GPPU, (unsigned short)shadow_GPPU);
+    }
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWordRead
+ */
+unsigned short MCP23017::digitalWordRead() {
+    shadow_GPIO = readRegister(GPIO);
+    return shadow_GPIO;
+}
+
+/*-----------------------------------------------------------------------------
+ * digitalWordWrite
+ */
+void MCP23017::digitalWordWrite(unsigned short w) {
+    shadow_GPIO = w;
+    writeRegister(GPIO, (unsigned short)shadow_GPIO);
+}
+
+/*-----------------------------------------------------------------------------
+ * inputPolarityMask
+ */
+void MCP23017::inputPolarityMask(unsigned short mask) {
+    writeRegister(IPOL, mask);
+}
+
+/*-----------------------------------------------------------------------------
+ * inputoutputMask
+ */
+void MCP23017::inputOutputMask(unsigned short mask) {
+    shadow_IODIR = mask;
+    writeRegister(IODIR, (unsigned short)shadow_IODIR);
+}
+
+/*-----------------------------------------------------------------------------
+ * internalPullupMask
+ */
+void MCP23017::internalPullupMask(unsigned short mask) {
+    shadow_GPPU = mask;
+    writeRegister(GPPU, (unsigned short)shadow_GPPU);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MCP23017.h	Fri Apr 13 17:44:17 2012 +0000
@@ -0,0 +1,143 @@
+/*  MCP23017 library for Arduino
+    Copyright (C) 2009 David Pye    <davidmpye@gmail.com
+    Modified for use on the MBED ARM platform
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef     MBED_MCP23017_H
+#define     MBED_MCP23017_H
+
+#include    "mbed.h"
+
+//
+// Register defines from data sheet - we set IOCON.BANK to 0
+// as it is easier to manage the registers sequentially.
+//
+#define     IODIR       0x00
+#define     IPOL        0x02
+#define     GPINTEN     0x04
+#define     DEFVAL      0x06
+#define     INTCON      0x08
+#define     IOCON       0x0A
+#define     GPPU        0x0C
+#define     INTF        0x0E
+#define     INTCAP      0x10
+#define     GPIO        0x12
+#define     OLAT        0x14
+
+#define     I2C_BASE_ADDRESS    0x40
+
+#define     DIR_OUTPUT      0
+#define     DIR_INPUT       1
+
+/** MCP23017 class
+ *
+ * Allow access to an I2C connected MCP23017 16-bit I/O extender chip
+ * Example:
+ * @code
+ *      MCP23017     *par_port; 
+ * @endcode
+ *
+ */
+class MCP23017 {
+public:
+    /** Constructor for the MCP23017 connected to specified I2C pins at a specific address
+     *
+     * 16-bit I/O expander with I2C interface
+     *
+     * @param   sda         I2C data pin
+     * @param   scl         I2C clock pin
+     * @param   i2cAddress  I2C address
+     */
+    MCP23017(PinName sda, PinName scl, int i2cAddress);
+
+    /** Reset MCP23017 device to its power-on state
+     */    
+    void reset(void);
+
+    /** Write a 0/1 value to an output bit
+     *
+     * @param   value         0 or 1
+     * @param   bit_number    bit number range 0 --> 15
+     */   
+    void write_bit(int value, int bit_number);
+      
+    /** Write a masked 16-bit value to the device
+     *
+     * @param   data    16-bit data value
+     * @param   mask    16-bit mask value
+     */       
+    void write_mask(unsigned short data, unsigned short mask);
+
+    /** Read a 0/1 value from an input bit
+     *
+     * @param   bit_number    bit number range 0 --> 15
+     * @return                0/1 value read
+     */       
+    int  read_bit(int bit_number);
+    
+    /** Read a 16-bit value from the device and apply mask
+     *
+     * @param   mask    16-bit mask value
+     * @return          16-bit data with mask applied
+     */     
+    int  read_mask(unsigned short mask);
+
+    /** Configure an MCP23017 device
+     *
+     * @param   dir_config         data direction value (1 = input, 0 = output)
+     * @param   pullup_config      100k pullup value (1 = enabled, 0 = disabled)
+     * @param   polarity_config    polarity value (1 = flip, 0 = normal)
+     */           
+    void config(unsigned short dir_config, unsigned short pullup_config, unsigned short polarity_config);
+
+    void writeRegister(int regAddress, unsigned char  val);
+    void writeRegister(int regAddress, unsigned short val);
+    int  readRegister(int regAddress);
+
+/*----------------------------------------------------------------------------- 
+ * pinmode
+ * Set units to sequential, bank0 mode
+ */  
+    void pinMode(int pin, int mode); 
+    void digitalWrite(int pin, int val);
+    int  digitalRead(int pin);
+
+// These provide a more advanced mapping of the chip functionality
+// See the data sheet for more information on what they do
+
+//Returns a word with the current pin states (ie contents of the GPIO register)
+    unsigned short digitalWordRead();
+// Allows you to write a word to the GPIO register
+    void digitalWordWrite(unsigned short w);
+// Sets up the polarity mask that the MCP23017 supports
+// if set to 1, it will flip the actual pin value.
+    void inputPolarityMask(unsigned short mask);
+//Sets which pins are inputs or outputs (1 = input, 0 = output) NB Opposite to arduino's
+//definition for these
+    void inputOutputMask(unsigned short mask);
+// Allows enabling of the internal 100k pullup resisters (1 = enabled, 0 = disabled)
+    void internalPullupMask(unsigned short mask);
+    int read(void);
+    void write(int data);
+
+protected:
+    I2C     _i2c;
+    int     MCP23017_i2cAddress;                        // physical I2C address
+    unsigned short   shadow_GPIO, shadow_IODIR, shadow_GPPU, shadow_IPOL;     // Cached copies of the register values
+    
+};
+
+#endif
\ No newline at end of file