Library for MAX7300 GPIO Expander

Dependents:   MAX14871_Shield

Committer:
j3
Date:
Thu May 12 23:35:32 2016 +0000
Revision:
7:e75913818f75
Parent:
6:3674af0a03cf
updated docs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
j3 0:350a850a7191 1 /******************************************************************//**
j3 4:4ffbd5539b69 2 * @file max7300.cpp
j3 0:350a850a7191 3 * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
j3 0:350a850a7191 4 *
j3 0:350a850a7191 5 * Permission is hereby granted, free of charge, to any person obtaining a
j3 0:350a850a7191 6 * copy of this software and associated documentation files (the "Software"),
j3 0:350a850a7191 7 * to deal in the Software without restriction, including without limitation
j3 0:350a850a7191 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
j3 0:350a850a7191 9 * and/or sell copies of the Software, and to permit persons to whom the
j3 0:350a850a7191 10 * Software is furnished to do so, subject to the following conditions:
j3 0:350a850a7191 11 *
j3 0:350a850a7191 12 * The above copyright notice and this permission notice shall be included
j3 0:350a850a7191 13 * in all copies or substantial portions of the Software.
j3 0:350a850a7191 14 *
j3 0:350a850a7191 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
j3 0:350a850a7191 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
j3 0:350a850a7191 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
j3 0:350a850a7191 18 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
j3 0:350a850a7191 19 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
j3 0:350a850a7191 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
j3 0:350a850a7191 21 * OTHER DEALINGS IN THE SOFTWARE.
j3 0:350a850a7191 22 *
j3 0:350a850a7191 23 * Except as contained in this notice, the name of Maxim Integrated
j3 0:350a850a7191 24 * Products, Inc. shall not be used except as stated in the Maxim Integrated
j3 0:350a850a7191 25 * Products, Inc. Branding Policy.
j3 0:350a850a7191 26 *
j3 0:350a850a7191 27 * The mere transfer of this software does not imply any licenses
j3 0:350a850a7191 28 * of trade secrets, proprietary technology, copyrights, patents,
j3 0:350a850a7191 29 * trademarks, maskwork rights, or any other form of intellectual
j3 0:350a850a7191 30 * property whatsoever. Maxim Integrated Products, Inc. retains all
j3 0:350a850a7191 31 * ownership rights.
j3 0:350a850a7191 32 **********************************************************************/
j3 0:350a850a7191 33
j3 0:350a850a7191 34
j3 0:350a850a7191 35 #include "max7300.h"
j3 0:350a850a7191 36
j3 0:350a850a7191 37
j3 1:e1ee2549a047 38 //configuration register bits
j3 3:e044960e516c 39 #define MAX7300_S_BIT (0x01)
j3 3:e044960e516c 40 #define MAX7300_M_BIT (0x80)
j3 1:e1ee2549a047 41
j3 1:e1ee2549a047 42 //registers
j3 3:e044960e516c 43 #define MAX7300_CONFIGURATION (0x04)
j3 3:e044960e516c 44 #define MAX7300_TRANSITION_DETECT_MASK (0x06)
j3 3:e044960e516c 45 #define MAX7300_PORT_CONFIGURATION (0x09)
j3 3:e044960e516c 46 #define MAX7300_PORT_ONLY_BASE_ADRS (0x20)
j3 1:e1ee2549a047 47
j3 1:e1ee2549a047 48 //helper for calclating register addresses in 8 port wide fxs
j3 3:e044960e516c 49 #define MAX7300_8_PORTS_OFFSET (0x40)
j3 1:e1ee2549a047 50
j3 1:e1ee2549a047 51
j3 0:350a850a7191 52 //*********************************************************************
j3 0:350a850a7191 53 Max7300::Max7300(I2C *i2c_bus, max7300_i2c_adrs_t i2c_adrs): _p_i2c(i2c_bus)
j3 0:350a850a7191 54 {
j3 0:350a850a7191 55 _i2c_owner = false;
j3 0:350a850a7191 56
j3 0:350a850a7191 57 _r_adrs = ((i2c_adrs << 1) | 1);
j3 0:350a850a7191 58 _w_adrs = (i2c_adrs << 1);
j3 0:350a850a7191 59 }
j3 0:350a850a7191 60
j3 0:350a850a7191 61
j3 0:350a850a7191 62 //*********************************************************************
j3 0:350a850a7191 63 Max7300::Max7300(PinName sda, PinName scl, max7300_i2c_adrs_t i2c_adrs)
j3 0:350a850a7191 64 {
j3 0:350a850a7191 65 _p_i2c = new I2C(sda, scl);
j3 0:350a850a7191 66 _i2c_owner = true;
j3 0:350a850a7191 67
j3 0:350a850a7191 68 _r_adrs = ((i2c_adrs << 1) | 1);
j3 0:350a850a7191 69 _w_adrs = (i2c_adrs << 1);
j3 0:350a850a7191 70 }
j3 0:350a850a7191 71
j3 0:350a850a7191 72
j3 0:350a850a7191 73 //*********************************************************************
j3 0:350a850a7191 74 Max7300::~Max7300()
j3 0:350a850a7191 75 {
j3 0:350a850a7191 76 if(_i2c_owner)
j3 0:350a850a7191 77 {
j3 0:350a850a7191 78 delete _p_i2c;
j3 0:350a850a7191 79 }
j3 0:350a850a7191 80 }
j3 0:350a850a7191 81
j3 0:350a850a7191 82
j3 0:350a850a7191 83 //*********************************************************************
j3 0:350a850a7191 84 int16_t Max7300::enable_ports(void)
j3 0:350a850a7191 85 {
j3 0:350a850a7191 86 int16_t result = -1;
j3 0:350a850a7191 87
j3 1:e1ee2549a047 88 result = write_config_register(true, MAX7300_S_BIT);
j3 0:350a850a7191 89
j3 0:350a850a7191 90 return result;
j3 0:350a850a7191 91 }
j3 0:350a850a7191 92
j3 0:350a850a7191 93
j3 0:350a850a7191 94 //*********************************************************************
j3 0:350a850a7191 95 int16_t Max7300::disable_ports(void)
j3 0:350a850a7191 96 {
j3 0:350a850a7191 97 int16_t result = -1;
j3 1:e1ee2549a047 98
j3 1:e1ee2549a047 99 result = write_config_register(false, MAX7300_S_BIT);
j3 1:e1ee2549a047 100
j3 1:e1ee2549a047 101 return result;
j3 1:e1ee2549a047 102 }
j3 1:e1ee2549a047 103
j3 1:e1ee2549a047 104
j3 1:e1ee2549a047 105 //*********************************************************************
j3 1:e1ee2549a047 106 int16_t Max7300::enable_transition_detection(void)
j3 1:e1ee2549a047 107 {
j3 1:e1ee2549a047 108 int16_t result = -1;
j3 0:350a850a7191 109
j3 1:e1ee2549a047 110 result = write_config_register(true, MAX7300_M_BIT);
j3 1:e1ee2549a047 111
j3 1:e1ee2549a047 112 return result;
j3 1:e1ee2549a047 113 }
j3 1:e1ee2549a047 114
j3 1:e1ee2549a047 115
j3 1:e1ee2549a047 116 //*********************************************************************
j3 1:e1ee2549a047 117 int16_t Max7300::disable_transition_detection(void)
j3 1:e1ee2549a047 118 {
j3 1:e1ee2549a047 119 int16_t result = -1;
j3 1:e1ee2549a047 120
j3 1:e1ee2549a047 121 result = write_config_register(false, MAX7300_M_BIT);
j3 0:350a850a7191 122
j3 0:350a850a7191 123 return result;
j3 0:350a850a7191 124 }
j3 0:350a850a7191 125
j3 0:350a850a7191 126
j3 0:350a850a7191 127 //*********************************************************************
j3 0:350a850a7191 128 int16_t Max7300::config_port(max7300_port_number_t port_num, max7300_port_type_t port_type)
j3 0:350a850a7191 129 {
j3 0:350a850a7191 130 int16_t result = -1;
j3 0:350a850a7191 131 char data[2];
j3 1:e1ee2549a047 132 uint8_t cnt = 0;
j3 0:350a850a7191 133
j3 0:350a850a7191 134 //get address of port configuration register
j3 1:e1ee2549a047 135 data[cnt++] = ((port_num/4) + 8);
j3 0:350a850a7191 136
j3 0:350a850a7191 137 //get port config bits offset in that register
j3 0:350a850a7191 138 uint8_t offset = (port_num % 4);
j3 0:350a850a7191 139
j3 0:350a850a7191 140 //set internal register pointer to port configuration register
j3 0:350a850a7191 141 result = _p_i2c->write(_w_adrs, data, 1, true);
j3 0:350a850a7191 142 if(!result)
j3 0:350a850a7191 143 {
j3 0:350a850a7191 144 //get current port configuration register
j3 6:3674af0a03cf 145 result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
j3 0:350a850a7191 146
j3 0:350a850a7191 147 if(!result)
j3 0:350a850a7191 148 {
j3 1:e1ee2549a047 149 //clear old port configuration, do not increment count
j3 1:e1ee2549a047 150 data[cnt] &= ~(0x03 << (offset*2));
j3 0:350a850a7191 151 //set port configuration bits
j3 1:e1ee2549a047 152 data[cnt++] |= ((port_type & 0x03) << (offset*2));
j3 0:350a850a7191 153
j3 0:350a850a7191 154 //write back to device
j3 1:e1ee2549a047 155 result = _p_i2c->write(_w_adrs, data, cnt, false);
j3 0:350a850a7191 156 }
j3 0:350a850a7191 157 }
j3 0:350a850a7191 158
j3 0:350a850a7191 159 return result;
j3 0:350a850a7191 160 }
j3 0:350a850a7191 161
j3 0:350a850a7191 162
j3 0:350a850a7191 163 //*********************************************************************
j3 1:e1ee2549a047 164 int16_t Max7300::config_4_ports(max7300_port_number_t low_port, uint8_t data)
j3 0:350a850a7191 165 {
j3 0:350a850a7191 166 int16_t result = -1;
j3 1:e1ee2549a047 167 char local_data[2];
j3 1:e1ee2549a047 168 uint8_t cnt = 0;
j3 1:e1ee2549a047 169
j3 1:e1ee2549a047 170 if(low_port <= MAX7300_PORT_28)
j3 1:e1ee2549a047 171 {
j3 1:e1ee2549a047 172 if((low_port % 4) == 0)
j3 1:e1ee2549a047 173 {
j3 1:e1ee2549a047 174 local_data[cnt++] = ((low_port/4) + 8);
j3 1:e1ee2549a047 175 local_data[cnt++] = data;
j3 1:e1ee2549a047 176
j3 1:e1ee2549a047 177 //no need for read, modify, write.
j3 1:e1ee2549a047 178 //Fx is intended to write whole register
j3 1:e1ee2549a047 179 result = _p_i2c->write(_w_adrs, local_data, cnt, false);
j3 1:e1ee2549a047 180 }
j3 1:e1ee2549a047 181 }
j3 0:350a850a7191 182
j3 1:e1ee2549a047 183 return result;
j3 1:e1ee2549a047 184 }
j3 1:e1ee2549a047 185
j3 1:e1ee2549a047 186 //*********************************************************************
j3 1:e1ee2549a047 187 int16_t Max7300::config_all_ports(max7300_port_type_t port_type)
j3 1:e1ee2549a047 188 {
j3 1:e1ee2549a047 189 int16_t result = -1;
j3 1:e1ee2549a047 190 char data[8];
j3 1:e1ee2549a047 191 char local_type = 0;
j3 1:e1ee2549a047 192 uint8_t cnt = 0;
j3 0:350a850a7191 193
j3 1:e1ee2549a047 194 //build byte for each port configuration register
j3 1:e1ee2549a047 195 local_type = ((port_type << 6) | (port_type << 4) | (port_type << 2) | port_type);
j3 1:e1ee2549a047 196
j3 1:e1ee2549a047 197 //stuff packet
j3 1:e1ee2549a047 198 data[cnt++] = MAX7300_PORT_CONFIGURATION;
j3 1:e1ee2549a047 199 for(/**/;cnt < 8; cnt++)
j3 1:e1ee2549a047 200 {
j3 1:e1ee2549a047 201 data[cnt] = local_type;
j3 1:e1ee2549a047 202 }
j3 1:e1ee2549a047 203
j3 1:e1ee2549a047 204 result = _p_i2c->write(_w_adrs, data, cnt, false);
j3 1:e1ee2549a047 205
j3 0:350a850a7191 206 return result;
j3 0:350a850a7191 207 }
j3 0:350a850a7191 208
j3 0:350a850a7191 209
j3 0:350a850a7191 210 //*********************************************************************
j3 0:350a850a7191 211 int16_t Max7300::read_port(max7300_port_number_t port_num)
j3 0:350a850a7191 212 {
j3 0:350a850a7191 213 int16_t result = -1;
j3 0:350a850a7191 214 char data[2];
j3 0:350a850a7191 215
j3 1:e1ee2549a047 216 data[0] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
j3 0:350a850a7191 217
j3 0:350a850a7191 218 //set internal register pointer to port data register
j3 0:350a850a7191 219 result = _p_i2c->write(_w_adrs, data, 1, true);
j3 0:350a850a7191 220 if(!result)
j3 0:350a850a7191 221 {
j3 0:350a850a7191 222 //get port data
j3 6:3674af0a03cf 223 result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
j3 0:350a850a7191 224 if(!result)
j3 0:350a850a7191 225 {
j3 0:350a850a7191 226 result = data[1];
j3 0:350a850a7191 227 }
j3 0:350a850a7191 228 else
j3 0:350a850a7191 229 {
j3 0:350a850a7191 230 result = -1;
j3 0:350a850a7191 231 }
j3 0:350a850a7191 232 }
j3 0:350a850a7191 233
j3 0:350a850a7191 234 return result;
j3 0:350a850a7191 235 }
j3 0:350a850a7191 236
j3 0:350a850a7191 237
j3 0:350a850a7191 238 //*********************************************************************
j3 0:350a850a7191 239 int16_t Max7300::write_port(max7300_port_number_t port_num, uint8_t data)
j3 0:350a850a7191 240 {
j3 0:350a850a7191 241 int16_t result = -1;
j3 1:e1ee2549a047 242 char local_data[2];
j3 1:e1ee2549a047 243 uint8_t cnt = 0;
j3 1:e1ee2549a047 244
j3 1:e1ee2549a047 245 local_data[cnt++] = (port_num + MAX7300_PORT_ONLY_BASE_ADRS);
j3 1:e1ee2549a047 246 local_data[cnt++] = data;
j3 0:350a850a7191 247
j3 0:350a850a7191 248 //no need for read, modify, write.
j3 0:350a850a7191 249 //Fx is intended to write whole register
j3 1:e1ee2549a047 250 result = _p_i2c->write(_w_adrs, local_data, cnt, false);
j3 1:e1ee2549a047 251
j3 1:e1ee2549a047 252 return result;
j3 1:e1ee2549a047 253 }
j3 1:e1ee2549a047 254
j3 1:e1ee2549a047 255
j3 1:e1ee2549a047 256 //*********************************************************************
j3 1:e1ee2549a047 257 int16_t Max7300::read_8_ports(max7300_port_number_t low_port)
j3 1:e1ee2549a047 258 {
j3 1:e1ee2549a047 259 int16_t result = -1;
j3 1:e1ee2549a047 260 char data[2];
j3 1:e1ee2549a047 261
j3 1:e1ee2549a047 262 if((low_port >= MAX7300_PORT_04) && (low_port <= MAX7300_PORT_24))
j3 1:e1ee2549a047 263 {
j3 1:e1ee2549a047 264 data[0] = low_port + MAX7300_8_PORTS_OFFSET;
j3 1:e1ee2549a047 265
j3 1:e1ee2549a047 266 //set internal register pointer to port data register
j3 1:e1ee2549a047 267 result = _p_i2c->write(_w_adrs, data, 1, true);
j3 1:e1ee2549a047 268 if(!result)
j3 1:e1ee2549a047 269 {
j3 1:e1ee2549a047 270 //get port data
j3 6:3674af0a03cf 271 result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
j3 1:e1ee2549a047 272 if(!result)
j3 1:e1ee2549a047 273 {
j3 1:e1ee2549a047 274 result = data[1];
j3 1:e1ee2549a047 275 }
j3 1:e1ee2549a047 276 else
j3 1:e1ee2549a047 277 {
j3 1:e1ee2549a047 278 result = -1;
j3 1:e1ee2549a047 279 }
j3 1:e1ee2549a047 280 }
j3 1:e1ee2549a047 281 }
j3 1:e1ee2549a047 282
j3 1:e1ee2549a047 283 return result;
j3 1:e1ee2549a047 284 }
j3 1:e1ee2549a047 285
j3 1:e1ee2549a047 286
j3 1:e1ee2549a047 287 //*********************************************************************
j3 1:e1ee2549a047 288 int16_t Max7300::write_8_ports(max7300_port_number_t low_port, uint8_t data)
j3 1:e1ee2549a047 289 {
j3 1:e1ee2549a047 290 int16_t result = -1;
j3 1:e1ee2549a047 291 char local_data[2];
j3 1:e1ee2549a047 292 uint8_t cnt = 0;
j3 1:e1ee2549a047 293
j3 1:e1ee2549a047 294 if(low_port <= MAX7300_PORT_24)
j3 1:e1ee2549a047 295 {
j3 1:e1ee2549a047 296 local_data[cnt++] = low_port + MAX7300_8_PORTS_OFFSET;
j3 1:e1ee2549a047 297 local_data[cnt++] = data;
j3 1:e1ee2549a047 298
j3 1:e1ee2549a047 299 //no need for read, modify, write.
j3 1:e1ee2549a047 300 //Fx is intended to write whole register
j3 1:e1ee2549a047 301 result = _p_i2c->write(_w_adrs, local_data, cnt, false);
j3 1:e1ee2549a047 302 }
j3 0:350a850a7191 303
j3 0:350a850a7191 304 return result;
j3 0:350a850a7191 305 }
j3 0:350a850a7191 306
j3 0:350a850a7191 307
j3 0:350a850a7191 308 //*********************************************************************
j3 1:e1ee2549a047 309 int16_t Max7300::read_mask_register(bool enable_snapshot)
j3 0:350a850a7191 310 {
j3 0:350a850a7191 311 int16_t result = -1;
j3 0:350a850a7191 312 char data[2];
j3 0:350a850a7191 313
j3 1:e1ee2549a047 314 data[0] = MAX7300_TRANSITION_DETECT_MASK;
j3 0:350a850a7191 315
j3 1:e1ee2549a047 316 //set internal register pointer to mask register
j3 0:350a850a7191 317 result = _p_i2c->write(_w_adrs, data, 1, true);
j3 0:350a850a7191 318 if(!result)
j3 0:350a850a7191 319 {
j3 1:e1ee2549a047 320 //get mask data
j3 6:3674af0a03cf 321 result = _p_i2c->read(_r_adrs, (data + 1), 1, false);
j3 0:350a850a7191 322 if(!result)
j3 0:350a850a7191 323 {
j3 1:e1ee2549a047 324 if(enable_snapshot)
j3 1:e1ee2549a047 325 {
j3 1:e1ee2549a047 326 result = enable_transition_detection();
j3 1:e1ee2549a047 327 if(!result)
j3 1:e1ee2549a047 328 {
j3 1:e1ee2549a047 329 result = data[1];
j3 1:e1ee2549a047 330 }
j3 1:e1ee2549a047 331 else
j3 1:e1ee2549a047 332 {
j3 1:e1ee2549a047 333 result = -1;
j3 1:e1ee2549a047 334 }
j3 1:e1ee2549a047 335 }
j3 1:e1ee2549a047 336 else
j3 1:e1ee2549a047 337 {
j3 1:e1ee2549a047 338 result = data[1];
j3 1:e1ee2549a047 339 }
j3 0:350a850a7191 340 }
j3 0:350a850a7191 341 else
j3 0:350a850a7191 342 {
j3 0:350a850a7191 343 result = -1;
j3 0:350a850a7191 344 }
j3 0:350a850a7191 345 }
j3 1:e1ee2549a047 346
j3 1:e1ee2549a047 347 return result;
j3 1:e1ee2549a047 348 }
j3 1:e1ee2549a047 349
j3 1:e1ee2549a047 350
j3 1:e1ee2549a047 351 //*********************************************************************
j3 1:e1ee2549a047 352 int16_t Max7300::write_mask_register(uint8_t data)
j3 1:e1ee2549a047 353 {
j3 1:e1ee2549a047 354 int16_t result = -1;
j3 1:e1ee2549a047 355 char local_data[2];
j3 1:e1ee2549a047 356 uint8_t cnt = 0;
j3 1:e1ee2549a047 357
j3 1:e1ee2549a047 358 local_data[cnt++] = MAX7300_TRANSITION_DETECT_MASK;
j3 1:e1ee2549a047 359 local_data[cnt++] = data;
j3 1:e1ee2549a047 360
j3 1:e1ee2549a047 361 //no need for read, modify, write.
j3 1:e1ee2549a047 362 //Fx is intended to write whole register
j3 1:e1ee2549a047 363 result = _p_i2c->write(_w_adrs, local_data, cnt, false);
j3 1:e1ee2549a047 364
j3 0:350a850a7191 365 return result;
j3 0:350a850a7191 366 }
j3 0:350a850a7191 367
j3 0:350a850a7191 368
j3 0:350a850a7191 369 //*********************************************************************
j3 1:e1ee2549a047 370 int16_t Max7300::write_config_register(bool set_clear, uint8_t data)
j3 0:350a850a7191 371 {
j3 0:350a850a7191 372 int16_t result = -1;
j3 1:e1ee2549a047 373 char local_data[2];
j3 1:e1ee2549a047 374 uint8_t cnt = 0;
j3 1:e1ee2549a047 375
j3 1:e1ee2549a047 376 local_data[cnt++] = MAX7300_CONFIGURATION;
j3 0:350a850a7191 377
j3 1:e1ee2549a047 378 //set internal register pointer to configuration register
j3 1:e1ee2549a047 379 result = _p_i2c->write(_w_adrs, local_data, 1, true);
j3 1:e1ee2549a047 380 if(!result)
j3 1:e1ee2549a047 381 {
j3 1:e1ee2549a047 382 //get current configuration register
j3 6:3674af0a03cf 383 result = _p_i2c->read(_r_adrs, (local_data + 1), 1, false);
j3 1:e1ee2549a047 384
j3 1:e1ee2549a047 385 if(!result)
j3 1:e1ee2549a047 386 {
j3 1:e1ee2549a047 387 if(set_clear)
j3 1:e1ee2549a047 388 {
j3 1:e1ee2549a047 389 local_data[cnt++] |= data;
j3 1:e1ee2549a047 390 }
j3 1:e1ee2549a047 391 else
j3 1:e1ee2549a047 392 {
j3 1:e1ee2549a047 393 local_data[cnt++] &= ~data;
j3 1:e1ee2549a047 394 }
j3 1:e1ee2549a047 395
j3 1:e1ee2549a047 396 //write back to device
j3 1:e1ee2549a047 397 result = _p_i2c->write(_w_adrs, local_data, cnt, false);
j3 1:e1ee2549a047 398 }
j3 1:e1ee2549a047 399 }
j3 1:e1ee2549a047 400
j3 0:350a850a7191 401 return result;
j3 0:350a850a7191 402 }