Library for MAX7300 GPIO Expander

Dependents:   MAX14871_Shield

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers max7300.cpp Source File

max7300.cpp

Go to the documentation of this file.
00001 /******************************************************************//**
00002 * @file max7300.cpp
00003 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
00004 *
00005 * Permission is hereby granted, free of charge, to any person obtaining a
00006 * copy of this software and associated documentation files (the "Software"),
00007 * to deal in the Software without restriction, including without limitation
00008 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009 * and/or sell copies of the Software, and to permit persons to whom the
00010 * Software is furnished to do so, subject to the following conditions:
00011 *
00012 * The above copyright notice and this permission notice shall be included
00013 * in all copies or substantial portions of the Software.
00014 *
00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00019 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00020 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00021 * OTHER DEALINGS IN THE SOFTWARE.
00022 *
00023 * Except as contained in this notice, the name of Maxim Integrated
00024 * Products, Inc. shall not be used except as stated in the Maxim Integrated
00025 * Products, Inc. Branding Policy.
00026 *
00027 * The mere transfer of this software does not imply any licenses
00028 * of trade secrets, proprietary technology, copyrights, patents,
00029 * trademarks, maskwork rights, or any other form of intellectual
00030 * property whatsoever. Maxim Integrated Products, Inc. retains all
00031 * ownership rights.
00032 **********************************************************************/
00033 
00034 
00035 #include "max7300.h"
00036 
00037 
00038 //configuration register bits
00039 #define MAX7300_S_BIT                   (0x01)
00040 #define MAX7300_M_BIT                   (0x80)
00041 
00042 //registers
00043 #define MAX7300_CONFIGURATION           (0x04)
00044 #define MAX7300_TRANSITION_DETECT_MASK  (0x06)
00045 #define MAX7300_PORT_CONFIGURATION      (0x09)
00046 #define MAX7300_PORT_ONLY_BASE_ADRS     (0x20)
00047 
00048 //helper for calclating register addresses in 8 port wide fxs
00049 #define MAX7300_8_PORTS_OFFSET          (0x40)
00050 
00051 
00052 //*********************************************************************
00053 Max7300::Max7300(I2C *i2c_bus, max7300_i2c_adrs_t i2c_adrs): _p_i2c(i2c_bus)
00054 {
00055     _i2c_owner = false;
00056     
00057     _r_adrs = ((i2c_adrs << 1) | 1);
00058     _w_adrs = (i2c_adrs << 1);
00059 }
00060 
00061 
00062 //*********************************************************************
00063 Max7300::Max7300(PinName sda, PinName scl, max7300_i2c_adrs_t i2c_adrs)
00064 {
00065     _p_i2c = new I2C(sda, scl);
00066     _i2c_owner = true;
00067     
00068     _r_adrs = ((i2c_adrs << 1) | 1);
00069     _w_adrs = (i2c_adrs << 1);
00070 }
00071 
00072 
00073 //*********************************************************************
00074 Max7300::~Max7300()
00075 {
00076     if(_i2c_owner) 
00077     {
00078         delete _p_i2c;
00079     }
00080 }
00081 
00082 
00083 //*********************************************************************
00084 int16_t Max7300::enable_ports(void)
00085 {
00086     int16_t result = -1;
00087     
00088     result = write_config_register(true, MAX7300_S_BIT);
00089 
00090     return result;
00091 }
00092 
00093 
00094 //*********************************************************************
00095 int16_t Max7300::disable_ports(void)
00096 {
00097     int16_t result = -1;
00098     
00099     result = write_config_register(false, MAX7300_S_BIT);
00100 
00101     return result;
00102 }
00103 
00104 
00105 //*********************************************************************
00106 int16_t Max7300::enable_transition_detection(void)
00107 {
00108     int16_t result = -1;
00109     
00110     result = write_config_register(true, MAX7300_M_BIT);
00111 
00112     return result;
00113 }
00114 
00115 
00116 //*********************************************************************
00117 int16_t Max7300::disable_transition_detection(void)
00118 {
00119     int16_t result = -1;
00120     
00121     result = write_config_register(false, MAX7300_M_BIT);
00122 
00123     return result;
00124 }
00125 
00126 
00127 //*********************************************************************
00128 int16_t Max7300::config_port(max7300_port_number_t port_num, max7300_port_type_t port_type)
00129 {
00130     int16_t result = -1;
00131     char data[2];
00132     uint8_t cnt = 0;
00133     
00134     //get address of port configuration register 
00135     data[cnt++]  = ((port_num/4) + 8);
00136     
00137     //get port config bits offset in that register
00138     uint8_t offset = (port_num % 4);
00139     
00140     //set internal register pointer to port configuration register
00141     result = _p_i2c->write(_w_adrs, data, 1, true);
00142     if(!result)
00143     {
00144         //get current port configuration register
00145         result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
00146         
00147         if(!result)
00148         {
00149             //clear old port configuration, do not increment count
00150             data[cnt] &= ~(0x03 << (offset*2));
00151             //set port configuration bits
00152             data[cnt++] |= ((port_type & 0x03) << (offset*2));
00153             
00154             //write back to device
00155             result = _p_i2c->write(_w_adrs, data, cnt, false);
00156         } 
00157     }
00158     
00159     return result;
00160 }
00161 
00162 
00163 //*********************************************************************
00164 int16_t Max7300::config_4_ports(max7300_port_number_t low_port, uint8_t data)
00165 {
00166     int16_t result = -1;
00167     char local_data[2];
00168     uint8_t cnt = 0;
00169     
00170     if(low_port <= MAX7300_PORT_28)
00171     {
00172         if((low_port % 4) == 0)
00173         {
00174             local_data[cnt++] = ((low_port/4) + 8);
00175             local_data[cnt++] = data;
00176             
00177             //no need for read, modify, write.  
00178             //Fx is intended to write whole register
00179             result = _p_i2c->write(_w_adrs, local_data, cnt, false);
00180         }
00181     }
00182     
00183     return result;
00184 }
00185 
00186 //*********************************************************************
00187 int16_t Max7300::config_all_ports(max7300_port_type_t port_type)
00188 {
00189     int16_t result = -1;
00190     char data[8];
00191     char local_type = 0;
00192     uint8_t cnt = 0;
00193     
00194     //build byte for each port configuration register
00195     local_type = ((port_type << 6) | (port_type << 4) | (port_type << 2) | port_type);
00196     
00197     //stuff packet
00198     data[cnt++] = MAX7300_PORT_CONFIGURATION;
00199     for(/**/;cnt < 8; cnt++)
00200     {
00201         data[cnt] = local_type;
00202     }
00203     
00204     result = _p_i2c->write(_w_adrs, data, cnt, false);
00205  
00206     return result;
00207 }
00208 
00209 
00210 //*********************************************************************
00211 int16_t Max7300::read_port(max7300_port_number_t port_num)
00212 {
00213     int16_t result = -1;
00214     char data[2];
00215     
00216     data[0] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
00217     
00218     //set internal register pointer to port data register
00219     result = _p_i2c->write(_w_adrs, data, 1, true);
00220     if(!result)
00221     {
00222         //get port data
00223         result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
00224         if(!result)
00225         {
00226             result = data[1];
00227         }
00228         else
00229         {
00230             result = -1;
00231         }
00232     }
00233      
00234     return result;
00235 }
00236 
00237 
00238 //*********************************************************************
00239 int16_t Max7300::write_port(max7300_port_number_t port_num, uint8_t data)
00240 {
00241     int16_t result = -1;
00242     char local_data[2];
00243     uint8_t cnt = 0;
00244     
00245     local_data[cnt++] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
00246     local_data[cnt++] = data;
00247     
00248     //no need for read, modify, write.  
00249     //Fx is intended to write whole register
00250     result = _p_i2c->write(_w_adrs, local_data, cnt, false);
00251     
00252     return result;
00253 }
00254 
00255 
00256 //*********************************************************************
00257 int16_t Max7300::read_8_ports(max7300_port_number_t low_port)
00258 {
00259     int16_t result = -1;
00260     char data[2];
00261     
00262     if((low_port >= MAX7300_PORT_04) && (low_port <= MAX7300_PORT_24))
00263     {
00264         data[0] = low_port + MAX7300_8_PORTS_OFFSET;
00265         
00266         //set internal register pointer to port data register
00267         result = _p_i2c->write(_w_adrs, data, 1, true);
00268         if(!result)
00269         {
00270             //get port data
00271             result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
00272             if(!result)
00273             {
00274                 result = data[1];
00275             }
00276             else
00277             {
00278                 result = -1;
00279             }
00280         }
00281     } 
00282      
00283     return result;
00284 }
00285 
00286 
00287 //*********************************************************************
00288 int16_t Max7300::write_8_ports(max7300_port_number_t low_port, uint8_t data)
00289 {
00290     int16_t result = -1;
00291     char local_data[2];
00292     uint8_t cnt = 0;
00293     
00294     if(low_port <= MAX7300_PORT_24)
00295     {
00296         local_data[cnt++] = low_port + MAX7300_8_PORTS_OFFSET;
00297         local_data[cnt++] = data;
00298     
00299         //no need for read, modify, write.  
00300         //Fx is intended to write whole register
00301         result = _p_i2c->write(_w_adrs, local_data, cnt, false);
00302     }
00303     
00304     return result;
00305 }
00306 
00307 
00308 //*********************************************************************
00309 int16_t Max7300::read_mask_register(bool enable_snapshot)
00310 {
00311     int16_t result = -1;
00312     char data[2];
00313     
00314     data[0] = MAX7300_TRANSITION_DETECT_MASK;
00315     
00316     //set internal register pointer to mask register
00317     result = _p_i2c->write(_w_adrs, data, 1, true);
00318     if(!result)
00319     {
00320         //get mask data
00321         result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
00322         if(!result)
00323         {
00324             if(enable_snapshot)
00325             {
00326                 result = enable_transition_detection();
00327                 if(!result)
00328                 {
00329                     result = data[1];
00330                 }
00331                 else
00332                 {
00333                     result = -1;
00334                 }
00335             }
00336             else
00337             {
00338                 result = data[1];
00339             }
00340         }
00341         else
00342         {
00343             result = -1;
00344         }
00345     }
00346     
00347     return result;
00348 }
00349 
00350 
00351 //*********************************************************************
00352 int16_t Max7300::write_mask_register(uint8_t data)
00353 {
00354     int16_t result = -1;
00355     char local_data[2];
00356     uint8_t cnt = 0;
00357     
00358     local_data[cnt++] = MAX7300_TRANSITION_DETECT_MASK;
00359     local_data[cnt++] = data;
00360 
00361     //no need for read, modify, write.  
00362     //Fx is intended to write whole register
00363     result = _p_i2c->write(_w_adrs, local_data, cnt, false);
00364     
00365     return result;
00366 }
00367 
00368 
00369 //*********************************************************************
00370 int16_t Max7300::write_config_register(bool set_clear, uint8_t data)
00371 {
00372     int16_t result = -1;
00373     char local_data[2];
00374     uint8_t cnt = 0;
00375     
00376     local_data[cnt++] = MAX7300_CONFIGURATION;
00377     
00378     //set internal register pointer to configuration register
00379     result = _p_i2c->write(_w_adrs, local_data, 1, true);
00380     if(!result)
00381     {
00382         //get current configuration register
00383         result = _p_i2c->read(_r_adrs, (local_data + 1), 1, false);
00384         
00385         if(!result)
00386         {
00387             if(set_clear)
00388             {
00389                 local_data[cnt++] |= data;
00390             }
00391             else
00392             {
00393                 local_data[cnt++] &= ~data;
00394             }
00395         
00396             //write back to device
00397             result = _p_i2c->write(_w_adrs, local_data, cnt, false);
00398         } 
00399     }
00400 
00401     return result;
00402 }