Library for MAX7300 GPIO Expander

Dependents:   MAX14871_Shield

Revision:
1:e1ee2549a047
Parent:
0:350a850a7191
Child:
3:e044960e516c
--- a/max7300.cpp	Wed Jul 15 15:10:04 2015 +0000
+++ b/max7300.cpp	Thu Jul 16 21:27:05 2015 +0000
@@ -46,6 +46,20 @@
 #include "max7300.h"
 
 
+//configuration register bits
+#define MAX7300_S_BIT                   0x01
+#define MAX7300_M_BIT                   0x80
+
+//registers
+#define MAX7300_CONFIGURATION           0x04
+#define MAX7300_TRANSITION_DETECT_MASK  0x06
+#define MAX7300_PORT_CONFIGURATION      0x09
+#define MAX7300_PORT_ONLY_BASE_ADRS     0x20
+
+//helper for calclating register addresses in 8 port wide fxs
+#define MAX7300_8_PORTS_OFFSET          0x40
+
+
 //*********************************************************************
 Max7300::Max7300(I2C *i2c_bus, max7300_i2c_adrs_t i2c_adrs): _p_i2c(i2c_bus)
 {
@@ -81,24 +95,8 @@
 int16_t Max7300::enable_ports(void)
 {
     int16_t result = -1;
-    char data[] = {MAX7300_CONFIGURATION, 0};
     
-    //set internal register pointer to configuration register
-    result = _p_i2c->write(_w_adrs, data, 1, true);
-    if(!result)
-    {
-        //get current configuration register
-        result = _p_i2c->read(_w_adrs, (data +1 ), 1, true);
-        
-        if(!result)
-        {
-            //set 'S' bit
-            data[1] |= 0x01;
-            
-            //write back to device
-            result = result = _p_i2c->write(_w_adrs, data, 2, false);
-        } 
-    }
+    result = write_config_register(true, MAX7300_S_BIT);
 
     return result;
 }
@@ -108,24 +106,30 @@
 int16_t Max7300::disable_ports(void)
 {
     int16_t result = -1;
-    char data[] = {MAX7300_CONFIGURATION, 0};
+    
+    result = write_config_register(false, MAX7300_S_BIT);
+
+    return result;
+}
+
+
+//*********************************************************************
+int16_t Max7300::enable_transition_detection(void)
+{
+    int16_t result = -1;
     
-    //set internal register pointer to configuration register
-    result = _p_i2c->write(_w_adrs, data, 1, true);
-    if(!result)
-    {
-        //get current configuration register
-        result = _p_i2c->read(_w_adrs, (data +1 ), 1, true);
-        
-        if(!result)
-        {
-            //clear 'S' bit
-            data[1] &= ~0x01;
-            
-            //write back to device
-            result = result = _p_i2c->write(_w_adrs, data, 2, false);
-        } 
-    }
+    result = write_config_register(true, MAX7300_M_BIT);
+
+    return result;
+}
+
+
+//*********************************************************************
+int16_t Max7300::disable_transition_detection(void)
+{
+    int16_t result = -1;
+    
+    result = write_config_register(false, MAX7300_M_BIT);
 
     return result;
 }
@@ -136,9 +140,10 @@
 {
     int16_t result = -1;
     char data[2];
+    uint8_t cnt = 0;
     
     //get address of port configuration register 
-    data[0]  = ((port_num/4) + 8);
+    data[cnt++]  = ((port_num/4) + 8);
     
     //get port config bits offset in that register
     uint8_t offset = (port_num % 4);
@@ -148,17 +153,17 @@
     if(!result)
     {
         //get current port configuration register
-        result = _p_i2c->read(_w_adrs, (data +1 ), 1, true);
+        result = _p_i2c->read(_w_adrs, (data + 1), 1, true);
         
         if(!result)
         {
-            //clear old port configuration
-            data[1] &= ~(0x03 << (offset*2));
+            //clear old port configuration, do not increment count
+            data[cnt] &= ~(0x03 << (offset*2));
             //set port configuration bits
-            data[1] |= ((port_type & 0x03) << (offset*2));
+            data[cnt++] |= ((port_type & 0x03) << (offset*2));
             
             //write back to device
-            result = result = _p_i2c->write(_w_adrs, data, 2, false);
+            result = _p_i2c->write(_w_adrs, data, cnt, false);
         } 
     }
     
@@ -167,15 +172,48 @@
 
 
 //*********************************************************************
-int16_t Max7300::config_ports(max7300_registers_t reg, uint8_t data)
+int16_t Max7300::config_4_ports(max7300_port_number_t low_port, uint8_t data)
 {
     int16_t result = -1;
-    char local_data[] = {reg, data};
+    char local_data[2];
+    uint8_t cnt = 0;
+    
+    if(low_port <= MAX7300_PORT_28)
+    {
+        if((low_port % 4) == 0)
+        {
+            local_data[cnt++] = ((low_port/4) + 8);
+            local_data[cnt++] = data;
+            
+            //no need for read, modify, write.  
+            //Fx is intended to write whole register
+            result = _p_i2c->write(_w_adrs, local_data, cnt, false);
+        }
+    }
     
-    //no need for read, modify, write.  
-    //Fx is intended to write whole register
-    result = _p_i2c->write(_w_adrs, local_data, 2, false);
+    return result;
+}
+
+//*********************************************************************
+int16_t Max7300::config_all_ports(max7300_port_type_t port_type)
+{
+    int16_t result = -1;
+    char data[8];
+    char local_type = 0;
+    uint8_t cnt = 0;
     
+    //build byte for each port configuration register
+    local_type = ((port_type << 6) | (port_type << 4) | (port_type << 2) | port_type);
+    
+    //stuff packet
+    data[cnt++] = MAX7300_PORT_CONFIGURATION;
+    for(/**/;cnt < 8; cnt++)
+    {
+        data[cnt] = local_type;
+    }
+    
+    result = _p_i2c->write(_w_adrs, data, cnt, false);
+ 
     return result;
 }
 
@@ -186,14 +224,14 @@
     int16_t result = -1;
     char data[2];
     
-    data[0] = (port_num + 0x20);
+    data[0] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
     
     //set internal register pointer to port data register
     result = _p_i2c->write(_w_adrs, data, 1, true);
     if(!result)
     {
         //get port data
-        result = _p_i2c->read(_w_adrs, (data +1 ), 1, false);
+        result = _p_i2c->read(_w_adrs, (data + 1), 1, false);
         if(!result)
         {
             result = data[1];
@@ -212,56 +250,164 @@
 int16_t Max7300::write_port(max7300_port_number_t port_num, uint8_t data)
 {
     int16_t result = -1;
-    char local_data[] = {(port_num + 0x20), data};
+    char local_data[2];
+    uint8_t cnt = 0;
+    
+    local_data[cnt++] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
+    local_data[cnt++] = data;
     
     //no need for read, modify, write.  
     //Fx is intended to write whole register
-    result = _p_i2c->write(_w_adrs, local_data, 2, false);
+    result = _p_i2c->write(_w_adrs, local_data, cnt, false);
+    
+    return result;
+}
+
+
+//*********************************************************************
+int16_t Max7300::read_8_ports(max7300_port_number_t low_port)
+{
+    int16_t result = -1;
+    char data[2];
+    
+    if((low_port >= MAX7300_PORT_04) && (low_port <= MAX7300_PORT_24))
+    {
+        data[0] = low_port + MAX7300_8_PORTS_OFFSET;
+        
+        //set internal register pointer to port data register
+        result = _p_i2c->write(_w_adrs, data, 1, true);
+        if(!result)
+        {
+            //get port data
+            result = _p_i2c->read(_w_adrs, (data + 1), 1, false);
+            if(!result)
+            {
+                result = data[1];
+            }
+            else
+            {
+                result = -1;
+            }
+        }
+    } 
+     
+    return result;
+}
+
+
+//*********************************************************************
+int16_t Max7300::write_8_ports(max7300_port_number_t low_port, uint8_t data)
+{
+    int16_t result = -1;
+    char local_data[2];
+    uint8_t cnt = 0;
+    
+    if(low_port <= MAX7300_PORT_24)
+    {
+        local_data[cnt++] = low_port + MAX7300_8_PORTS_OFFSET;
+        local_data[cnt++] = data;
+    
+        //no need for read, modify, write.  
+        //Fx is intended to write whole register
+        result = _p_i2c->write(_w_adrs, local_data, cnt, false);
+    }
     
     return result;
 }
 
 
 //*********************************************************************
-int16_t Max7300::read_eight_ports(max7300_registers_t reg)
+int16_t Max7300::read_mask_register(bool enable_snapshot)
 {
     int16_t result = -1;
     char data[2];
     
-    data[0] = reg;
+    data[0] = MAX7300_TRANSITION_DETECT_MASK;
     
-    //set internal register pointer to port data register
+    //set internal register pointer to mask register
     result = _p_i2c->write(_w_adrs, data, 1, true);
     if(!result)
     {
-        //get port data
-        result = _p_i2c->read(_w_adrs, (data +1 ), 1, false);
+        //get mask data
+        result = _p_i2c->read(_w_adrs, (data + 1), 1, false);
         if(!result)
         {
-            result = data[1];
+            if(enable_snapshot)
+            {
+                result = enable_transition_detection();
+                if(!result)
+                {
+                    result = data[1];
+                }
+                else
+                {
+                    result = -1;
+                }
+            }
+            else
+            {
+                result = data[1];
+            }
         }
         else
         {
             result = -1;
         }
     }
-     
+    
+    return result;
+}
+
+
+//*********************************************************************
+int16_t Max7300::write_mask_register(uint8_t data)
+{
+    int16_t result = -1;
+    char local_data[2];
+    uint8_t cnt = 0;
+    
+    local_data[cnt++] = MAX7300_TRANSITION_DETECT_MASK;
+    local_data[cnt++] = data;
+
+    //no need for read, modify, write.  
+    //Fx is intended to write whole register
+    result = _p_i2c->write(_w_adrs, local_data, cnt, false);
+    
     return result;
 }
 
 
 //*********************************************************************
-int16_t Max7300::write_eight_ports(max7300_registers_t reg, uint8_t data)
+int16_t Max7300::write_config_register(bool set_clear, uint8_t data)
 {
     int16_t result = -1;
-    char local_data[] = {reg, data};
+    char local_data[2];
+    uint8_t cnt = 0;
+    
+    local_data[cnt++] = MAX7300_CONFIGURATION;
     
-    //no need for read, modify, write.  
-    //Fx is intended to write whole register
-    result = _p_i2c->write(_w_adrs, local_data, 2, false);
-    
+    //set internal register pointer to configuration register
+    result = _p_i2c->write(_w_adrs, local_data, 1, true);
+    if(!result)
+    {
+        //get current configuration register
+        result = _p_i2c->read(_w_adrs, (local_data + 1), 1, true);
+        
+        if(!result)
+        {
+            if(set_clear)
+            {
+                local_data[cnt++] |= data;
+            }
+            else
+            {
+                local_data[cnt++] &= ~data;
+            }
+        
+            //write back to device
+            result = _p_i2c->write(_w_adrs, local_data, cnt, false);
+        } 
+    }
+
     return result;
 }
-
-
-