Library for MAX7300 GPIO Expander

Dependents:   MAX14871_Shield

Files at this revision

API Documentation at this revision

Comitter:
j3
Date:
Thu Jul 16 21:27:05 2015 +0000
Parent:
0:350a850a7191
Child:
2:fd2de5d21702
Commit message:
Finished library, ready for review.

Changed in this revision

max7300.cpp Show annotated file Show diff for this revision Revisions of this file
max7300.h Show annotated file Show diff for this revision Revisions of this file
--- 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;
 }
-
-
-
--- a/max7300.h	Wed Jul 15 15:10:04 2015 +0000
+++ b/max7300.h	Thu Jul 16 21:27:05 2015 +0000
@@ -10,7 +10,6 @@
 * Updated: 
 *
 * @brief Header file for Max7300 class
-*
 ***********************************************************************
 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
 *
@@ -116,53 +115,6 @@
     }max7300_port_number_t;
     
     
-    typedef enum
-    {
-        MAX7300_NO_OP = 0,
-        MAX7300_CONFIGURATION = 4,
-        MAX7300_MASK = 6,
-        MAX7300_PORT_CONFIG_P07_P04 = 9,
-        MAX7300_PORT_CONFIG_P11_P8,
-        MAX7300_PORT_CONFIG_P15_P12,
-        MAX7300_PORT_CONFIG_P19_P16,
-        MAX7300_PORT_CONFIG_P23_P20,
-        MAX7300_PORT_CONFIG_P27_P24,
-        MAX7300_PORT_CONFIG_P31_P28,
-        MAX7300_PORT_04_DATA = 0x24,
-        MAX7300_PORT_05_DATA,
-        MAX7300_PORT_06_DATA,
-        MAX7300_PORT_07_DATA,
-        MAX7300_PORT_08_DATA,
-        MAX7300_PORT_09_DATA,
-        MAX7300_PORT_10_DATA,
-        MAX7300_PORT_11_DATA,
-        MAX7300_PORT_12_DATA,
-        MAX7300_PORT_13_DATA,
-        MAX7300_PORT_14_DATA,
-        MAX7300_PORT_15_DATA,
-        MAX7300_PORT_16_DATA,
-        MAX7300_PORT_17_DATA,
-        MAX7300_PORT_18_DATA,
-        MAX7300_PORT_19_DATA,
-        MAX7300_PORT_20_DATA,
-        MAX7300_PORT_21_DATA,
-        MAX7300_PORT_22_DATA,
-        MAX7300_PORT_23_DATA,
-        MAX7300_PORT_24_DATA,
-        MAX7300_PORT_25_DATA,
-        MAX7300_PORT_26_DATA,
-        MAX7300_PORT_27_DATA,
-        MAX7300_PORT_28_DATA,
-        MAX7300_PORT_29_DATA,
-        MAX7300_PORT_30_DATA,
-        MAX7300_PORT_31_DATA,
-        MAX7300_8_PORTS_P04_P11_DATA = 0x44,
-        MAX7300_8_PORTS_P12_P19_DATA = 0x4C,
-        MAX7300_8_PORTS_P20_P27_DATA = 0x54,
-        MAX7300_8_PORTS_P24_P31_DATA = 0x58
-    }max7300_registers_t;
-    
-    
     /**********************************************************//**
     * @brief Constructor for Max7300 Class.  
     * 
@@ -235,6 +187,32 @@
     
     
     /**********************************************************//**
+    * @brief Enables Transition Detection
+    *
+    * @details Sets 'M' bit of configuration register
+    *
+    * On Entry:
+    *
+    * On Exit:
+    *    @return 0 on success, non-0 on failure
+    **************************************************************/
+    int16_t enable_transition_detection(void);
+    
+    
+    /**********************************************************//**
+    * @brief Disables Transition Detection
+    *
+    * @details Clears 'M' bit of configuration register
+    *
+    * On Entry:
+    *
+    * On Exit:
+    *    @return 0 on success, non-0 on failure
+    **************************************************************/
+    int16_t disable_transition_detection(void);
+    
+    
+    /**********************************************************//**
     * @brief Configures a single MAX7300 GPIO port
     *
     * @details  Configures MAX7300 GPIO port as either an output,
@@ -259,14 +237,8 @@
     * @details  Allows user to configure 4 ports at a time
     *
     * On Entry:
-    *    @param[in] reg - One of the following 7 registers
-    *                     MAX7300_PORT_CONFIG_P7_P4,
-    *                     MAX7300_PORT_CONFIG_P11_P8,
-    *                     MAX7300_PORT_CONFIG_P15_P12,
-    *                     MAX7300_PORT_CONFIG_P19_P16,
-    *                     MAX7300_PORT_CONFIG_P23_P20,
-    *                     MAX7300_PORT_CONFIG_P27_P24,
-    *                     MAX7300_PORT_CONFIG_P31_P28
+    *    @param[in] low_port - lowest of 4 ports to configure, 
+    *                          on 4 port boundaries as in datasheet
     *
     *    @param[in] data - Byte with each ports desired type with 
     *                      the following format - xx|xx|xx|xx
@@ -274,7 +246,24 @@
     * On Exit:
     *    @return 0 on success, non-0 on failure
     **************************************************************/
-    int16_t config_ports(max7300_registers_t reg, uint8_t data);
+    int16_t config_4_ports(max7300_port_number_t low_port, uint8_t data);
+    
+    
+    /**********************************************************//**
+    * @brief Configures all MAX7300 GPIO ports
+    *
+    * @details  Allows user to configure all ports to a single type
+    *
+    * On Entry:
+    *    @param[in] port_type - One of the following port types
+    *                            MAX7300_PORT_OUTPUT
+    *                            MAX7300_PORT_INPUT
+    *                            MAX7300_PORT_INPUT_PULLUP
+    *
+    * On Exit:
+    *    @return 0 on success, non-0 on failure
+    **************************************************************/
+    int16_t config_all_ports(max7300_port_type_t port_type);
     
     
     /**********************************************************//**
@@ -283,9 +272,10 @@
     * @details
     *
     * On Entry:
+    *    @param[in] port_num - MAX7300 port number to read
     *
     * On Exit:
-    *    @return state of port, or  
+    *    @return state of port, or -1 on failure
     **************************************************************/
     int16_t read_port(max7300_port_number_t port_num);
     
@@ -296,9 +286,11 @@
     * @details
     *
     * On Entry:
+    *    @param[in] port_num - MAX7300 port to write
+    *    @param[in] data - lsb of byte is written to port
     *
     * On Exit:
-    *    @return none 
+    *    @return 0 on success, non-0 on failure
     **************************************************************/
     int16_t write_port(max7300_port_number_t port_num, uint8_t data);
     
@@ -309,11 +301,14 @@
     * @details
     *
     * On Entry:
+    *    @param[in] low_port - lowest port of 8 ports to read, 
+    *                          on 8 port boundaries as in datasheet.
+    *                          Max is port 24
     *
     * On Exit:
-    *    @return none 
+    *    @return state of ports, or -1 on failure
     **************************************************************/
-    int16_t read_eight_ports(max7300_registers_t reg);
+    int16_t read_8_ports(max7300_port_number_t low_port);
     
     
     /**********************************************************//**
@@ -322,23 +317,48 @@
     * @details
     *
     * On Entry:
+    *    @param[in] low_port - lowest port of 8 ports to write, 
+    *                          on 8 port boundaries as in datasheet.
+    *                          Max is port 24
+    *
+    *    @param[in] data - Data is written to ports
     *
     * On Exit:
-    *    @return none 
+    *    @return 0 on success, non-0 on failure
     **************************************************************/
-    int16_t write_eight_ports(max7300_registers_t reg, uint8_t data);
+    int16_t write_8_ports(max7300_port_number_t low_port, uint8_t data);
+    
+    
+     /**********************************************************//**
+    * @brief Read transition detection mask register
+    *
+    * @details See page 11 of DS, right hand side column, paragraph 2
+    *          for details on one-shot event.
+    *          
+    * On Entry:
+    *    @param[in] enable_snapshot - true to re-enable transition
+    *                                 detection
+    *
+    * On Exit:
+    *    @return contents of mask register, or -1 on failure
+    **************************************************************/
+    int16_t read_mask_register(bool enable_snapshot);
     
     
     /**********************************************************//**
-    * @brief 
+    * @brief Write transition detection mask register
     *
-    * @details
+    * @details Enables transition detection on Ports 30-24
+    *          
     *
     * On Entry:
+    *    @param[in] data - Bits to set
     *
     * On Exit:
-    *    @return none 
+    *    @return 0 on success, non-0 on failure
     **************************************************************/
+    int16_t write_mask_register(uint8_t data);
+    
     
     private:
     
@@ -346,5 +366,21 @@
     bool _i2c_owner;
     uint8_t _w_adrs;
     uint8_t _r_adrs;
+    
+    
+    /**********************************************************//**
+    * @brief Write MAX7300 configuration register
+    *
+    * @details
+    *
+    * On Entry:
+    *    @param[in] set_clear - If true set bit defined by data
+    *
+    *    @param[in] data - 'S' or 'M' bit of configuration register
+    *
+    * On Exit:
+    *    @return 0 on success, non-0 on failure
+    **************************************************************/
+    int16_t write_config_register(bool set_clear, uint8_t data);
 };
 #endif /* MAX7300_H*/
\ No newline at end of file