Added support for banked registers

Dependents:   Component_Test_Interface FalconWing MX_Spoile_Test Simple_Power_Distribution ... more

Files at this revision

API Documentation at this revision

Comitter:
wim
Date:
Mon Feb 13 21:54:29 2012 +0000
Parent:
3:72da9cd002bd
Child:
5:5696b886a895
Commit message:
v05

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
--- a/MCP23017.cpp	Sun Aug 21 13:59:48 2011 +0000
+++ b/MCP23017.cpp	Mon Feb 13 21:54:29 2012 +0000
@@ -6,6 +6,7 @@
 * version 0.2 Initial Release
 * version 0.3 Cleaned up
 * version 0.4 Fixed problem with _read method
+* version 0.5 Added support for 'Banked' access to registers
 */
 
 #include "mbed.h"
@@ -57,7 +58,10 @@
 * @returns 
 */
 void MCP23017::_init() {
-    _write(IOCON, (IOCON_BYTE_MODE | IOCON_HAEN )); // Hardware addressing on, operations toggle between A and B registers
+  
+  _bankMode = NOT_BNK;  // This may not be true after software reset without hardware reset !!!
+  
+  _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)
 
 }
 
@@ -67,7 +71,7 @@
 * @param char direction pin direction (0 = output, 1 = input)
 */
 void MCP23017::direction(Port port, char direction) {
-    _write(port + IODIRA, direction);
+    _write(IODIR_AB[_bankMode][port], direction);
 }
 
 /** Set Pull-Up Resistors on specified MCP23017 Port
@@ -76,40 +80,73 @@
 * @param char offOrOn per pin (0 = off, 1 = on)
 */
 void MCP23017::configurePullUps(Port port, char offOrOn) {
-    _write(port + GPPUA, offOrOn);
+  
+  _write(GPPU_AB[_bankMode][port], offOrOn); 
 }
 
+/** Configere the Banked or Non-Banked mode
+*
+* @param Bank bankMode
+* @param char offOrOn per pin (0 = off, 1 = on)
+*/
+void MCP23017::configureBanked(Bank bankMode) {
+
+    if (bankMode == NOT_BNK) {
+      // Non-Banked sequential registers (default POR)
+      // Hardware addressing on, , no-autoincrement, 16 bit mode (operations do toggle between A and B registers)          
+      _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BYTE_MODE | IOCON_HAEN ));
+      _bankMode = NOT_BNK;
+    }  
+    else {
+      // Banked registers
+      // Hardware addressing on, no-autoincrement, 8 bit mode           
+      _write(IOCON_AB[_bankMode][PORT_A], (IOCON_BANK | IOCON_BYTE_MODE | IOCON_HAEN ));
+      _bankMode = BNK;
+    }
+}
+
+
 void MCP23017::interruptEnable(Port port, char interruptsEnabledMask) {
-    _write(port + GPINTENA, interruptsEnabledMask);
+  
+  _write(GPINTEN_AB[_bankMode][port], interruptsEnabledMask);    
+   
 }
 
 void MCP23017::mirrorInterrupts(bool mirror) {
- char iocon = _read(IOCON);
-    if (mirror) {
-        iocon = iocon | INTERRUPT_MIRROR_BIT;
-    } else {
-        iocon = iocon & ~INTERRUPT_MIRROR_BIT;
-    }
-    _write(IOCON, iocon);
+  char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
+
+  if (mirror) {
+    iocon = iocon | INTERRUPT_MIRROR_BIT;
+  }
+  else {
+    iocon = iocon & ~INTERRUPT_MIRROR_BIT;
+  }
+
+  _write(IOCON_AB[_bankMode][PORT_A], iocon);
 
 }
 
 void  MCP23017::interruptPolarity(Polarity polarity) {
-    char iocon = _read(IOCON);
+    char iocon = _read(IOCON_AB[_bankMode][PORT_A]);
+    
     if (polarity == ACTIVE_LOW) {
         iocon = iocon & ~INTERRUPT_POLARITY_BIT;
     } else {
         iocon = iocon | INTERRUPT_POLARITY_BIT;
     }
-    _write(IOCON, iocon);
+    _write(IOCON_AB[_bankMode][PORT_A], iocon);
 }
 
 void MCP23017::defaultValue(Port port, char valuesToCompare) {
-    _write(port + DEFVALA, valuesToCompare);
+    
+  _write(DEFVAL_AB[_bankMode][port], valuesToCompare);
+    
 }
 
 void MCP23017::interruptControl(Port port, char interruptControlBits) {
-    _write(port + INTCONA, interruptControlBits);
+    
+  _write(INTCON_AB[_bankMode][port], interruptControlBits);
+    
 }
 
 /** Write to specified MCP23017 Port
@@ -118,7 +155,7 @@
 * @param char byte data to write
 */
 void MCP23017::write(Port port, char byte) {
-    _write(port + OLATA, byte);
+    _write(OLAT_AB[_bankMode][port], byte);
 }
     
 /** Read from specified MCP23017 Port
@@ -127,6 +164,6 @@
 * @returns data from Port 
 */
 char MCP23017::read(Port port) {
-    return _read(port + GPIOA);
+    return _read(GPIO_AB[_bankMode][port]);
 }
 
--- a/MCP23017.h	Sun Aug 21 13:59:48 2011 +0000
+++ b/MCP23017.h	Mon Feb 13 21:54:29 2012 +0000
@@ -6,6 +6,7 @@
 * version 0.2 Initial Release
 * version 0.3 Cleaned up
 * version 0.4 Fixed problem with _read method
+* version 0.5 Added support for 'Banked' access to registers
 */
 #include "mbed.h"
 
@@ -15,14 +16,16 @@
 // All register addresses assume IOCON.BANK = 0 (POR default)
 #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 IOCON    0x0B
+#define IOCONA   0x0A
+#define IOCONB   0x0B
 #define GPPUA    0x0C
 #define GPPUB    0x0D
 #define INTFA    0x0E
@@ -34,10 +37,50 @@
 #define OLATA    0x14
 #define OLATB    0x15
 
+// The following register addresses assume IOCON.BANK = 1 
+#define IODIRA_BNK   0x00
+#define IPOLA_BNK    0x01
+#define GPINTENA_BNK 0x02
+#define DEFVALA_BNK  0x03
+#define INTCONA_BNK  0x04
+#define GPPUA_BNK    0x05
+#define INTFA_BNK    0x06
+#define IOCONA_BNK   0x07
+#define INTCAPA_BNK  0x08
+#define GPIOA_BNK    0x09
+#define OLATA_BNK    0x0A
+
+#define IODIRB_BNK   0x10
+#define IPOLB_BNK    0x11
+#define GPINTENB_BNK 0x12
+#define DEFVALB_BNK  0x13
+#define INTCONB_BNK  0x14
+#define IOCONB_BNK   0x15
+#define GPPUB_BNK    0x16
+#define INTFB_BNK    0x17
+#define INTCAPB_BNK  0x18
+#define GPIOB_BNK    0x19
+#define OLATB_BNK    0x1A
+
+// This array allows structured access to Port_A and Port_B registers for both bankModes
+const int IODIR_AB[2][2]   = {{IODIRA, IODIRB},     {IODIRA_BNK, IODIRB_BNK}};
+const int IPOL_AB[2][2]    = {{IPOLA, IPOLB},       {IPOLA_BNK, IPOLB_BNK}};
+const int GPINTEN_AB[2][2] = {{GPINTENA, GPINTENB}, {GPINTENA_BNK, GPINTENB_BNK}};
+const int DEFVAL_AB[2][2]  = {{DEFVALA, DEFVALB},   {DEFVALA_BNK, DEFVALB_BNK}};
+const int INTCON_AB[2][2]  = {{INTCONA, INTCONB},   {INTCONA_BNK, INTCONB_BNK}};
+const int IOCON_AB[2][2]   = {{IOCONA, IOCONB},     {IOCONA_BNK, IOCONB_BNK}};
+const int GPPU_AB[2][2]    = {{GPPUA, GPPUB},       {GPPUA_BNK, GPPUB_BNK}};
+const int INTF_AB[2][2]    = {{INTFA, INTFB},       {INTFA_BNK, INTFB_BNK}};
+const int INTCAP_AB[2][2]  = {{INTCAPA, INTCAPB},   {INTCAPA_BNK, INTCAPB_BNK}};
+const int GPIO_AB[2][2]    = {{GPIOA, GPIOB},       {GPIOA_BNK, GPIOB_BNK}};
+const int OLAT_AB[2][2]    = {{OLATA, OLATB},       {OLATA_BNK, OLATB_BNK}};
+
+
 // Control settings
 #define IOCON_BANK      0x80 // Banked registers for Port A and B
 #define IOCON_BYTE_MODE 0x20 // Disables sequential operation, Address Ptr does not increment
                              //   If Disabled and Bank = 0, operations toggle between Port A and B registers
+                             //   If Disabled and Bank = 1, operations do not increment registeraddress                             
 #define IOCON_HAEN      0x08 // Hardware address enable
 
 #define INTERRUPT_POLARITY_BIT 0x02
@@ -47,7 +90,8 @@
 #define PORT_DIR_IN    0xFF
 
 enum Polarity { ACTIVE_LOW , ACTIVE_HIGH };
-enum Port { PORT_A, PORT_B };
+enum Port { PORT_A=0, PORT_B=1 };
+enum Bank { NOT_BNK=0, BNK=1 };
 
 class MCP23017 {
 public:
@@ -72,6 +116,7 @@
     */    
     void configurePullUps(Port port, char offOrOn);
 
+    void configureBanked(Bank bankmode);  
     void interruptEnable(Port port, char interruptsEnabledMask);
     void interruptPolarity(Polarity polarity);
     void mirrorInterrupts(bool mirror);
@@ -96,6 +141,7 @@
     I2C &_i2c;
     char _readOpcode;
     char _writeOpcode;
+    Bank _bankMode; 
     
     /** Init MCP23017
     *