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
diff -r 000000000000 -r d76c38ee24ab MCP23017.cpp
--- /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);
+}
+
diff -r 000000000000 -r d76c38ee24ab MCP23017.h
--- /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