Basic library of routines to interface to a Microchip MCP23017 16-bit I/O expander using an I2C interface.

Dependents:   acd52832_beep_buzzer_ints

Fork of MCP23017 by jim herd

Committer:
jurica238814
Date:
Fri Sep 23 12:12:24 2016 +0000
Revision:
14:2e65b7f39273
Parent:
12:6d9d2b277f26
IO expander ints done.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jimherd 0:a6a5d942b58f 1 /* MCP23017 library for Arduino
jimherd 0:a6a5d942b58f 2 Copyright (C) 2009 David Pye <davidmpye@gmail.com
jimherd 12:6d9d2b277f26 3 Modified for use on the MBED ARM platform
jimherd 0:a6a5d942b58f 4
jimherd 0:a6a5d942b58f 5 This program is free software: you can redistribute it and/or modify
jimherd 0:a6a5d942b58f 6 it under the terms of the GNU General Public License as published by
jimherd 0:a6a5d942b58f 7 the Free Software Foundation, either version 3 of the License, or
jimherd 0:a6a5d942b58f 8 (at your option) any later version.
jimherd 0:a6a5d942b58f 9
jimherd 0:a6a5d942b58f 10 This program is distributed in the hope that it will be useful,
jimherd 0:a6a5d942b58f 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
jimherd 0:a6a5d942b58f 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
jimherd 0:a6a5d942b58f 13 GNU General Public License for more details.
jimherd 0:a6a5d942b58f 14
jimherd 0:a6a5d942b58f 15 You should have received a copy of the GNU General Public License
jimherd 0:a6a5d942b58f 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
jimherd 0:a6a5d942b58f 17 */
jimherd 4:32fd6ee97dff 18
jimherd 4:32fd6ee97dff 19 #include "MCP23017.h"
jimherd 2:2a17f52c550a 20 #include "mbed.h"
jimherd 0:a6a5d942b58f 21
jurica238814 14:2e65b7f39273 22 bool interrupt = 0;
jurica238814 14:2e65b7f39273 23
jurica238814 14:2e65b7f39273 24 void setInt(){
jurica238814 14:2e65b7f39273 25 interrupt = 1;
jurica238814 14:2e65b7f39273 26 }
jurica238814 14:2e65b7f39273 27 void clearInt(){
jurica238814 14:2e65b7f39273 28 interrupt = 0;
jurica238814 14:2e65b7f39273 29 }
jurica238814 14:2e65b7f39273 30 bool getInt(){
jurica238814 14:2e65b7f39273 31 return interrupt;
jurica238814 14:2e65b7f39273 32 }
jurica238814 14:2e65b7f39273 33
jimherd 0:a6a5d942b58f 34 union {
jimherd 0:a6a5d942b58f 35 uint8_t value8[2];
jimherd 0:a6a5d942b58f 36 uint16_t value16;
jimherd 0:a6a5d942b58f 37 } tmp_data;
jimherd 0:a6a5d942b58f 38
jimherd 12:6d9d2b277f26 39 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 40 *
jimherd 0:a6a5d942b58f 41 */
jimherd 0:a6a5d942b58f 42 MCP23017::MCP23017(PinName sda, PinName scl, int i2cAddress) : _i2c(sda, scl) {
jimherd 0:a6a5d942b58f 43 MCP23017_i2cAddress = i2cAddress;
jimherd 0:a6a5d942b58f 44 reset(); // initialise chip to power-on condition
jimherd 0:a6a5d942b58f 45 }
jimherd 0:a6a5d942b58f 46
jimherd 12:6d9d2b277f26 47 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 48 * reset
jimherd 0:a6a5d942b58f 49 * Set configuration (IOCON) and direction(IODIR) registers to initial state
jimherd 0:a6a5d942b58f 50 */
jimherd 0:a6a5d942b58f 51 void MCP23017::reset() {
jimherd 0:a6a5d942b58f 52 //
jimherd 0:a6a5d942b58f 53 // First make sure that the device is in BANK=0 mode
jimherd 0:a6a5d942b58f 54 //
jimherd 0:a6a5d942b58f 55 writeRegister(0x05, (unsigned char)0x00);
jimherd 0:a6a5d942b58f 56 //
jimherd 0:a6a5d942b58f 57 // set direction registers to inputs
jimherd 0:a6a5d942b58f 58 //
jimherd 0:a6a5d942b58f 59 writeRegister(IODIR, (unsigned short)0xFFFF);
jimherd 0:a6a5d942b58f 60 //
jimherd 9:e08c29541bc4 61 // set all other registers to zero (last of 10 registers is OLAT)
jimherd 0:a6a5d942b58f 62 //
jimherd 0:a6a5d942b58f 63 for (int reg_addr = 2 ; reg_addr <= OLAT ; reg_addr+=2) {
jimherd 0:a6a5d942b58f 64 writeRegister(reg_addr, (unsigned short)0x0000);
jimherd 0:a6a5d942b58f 65 }
jimherd 0:a6a5d942b58f 66 //
jimherd 0:a6a5d942b58f 67 // Set the shadow registers to power-on state
jimherd 0:a6a5d942b58f 68 //
jimherd 0:a6a5d942b58f 69 shadow_IODIR = 0xFFFF;
jimherd 0:a6a5d942b58f 70 shadow_GPIO = 0;
jimherd 0:a6a5d942b58f 71 shadow_GPPU = 0;
jimherd 0:a6a5d942b58f 72 shadow_IPOL = 0;
jimherd 0:a6a5d942b58f 73 }
jimherd 0:a6a5d942b58f 74
jimherd 12:6d9d2b277f26 75 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 76 * write_bit
jimherd 0:a6a5d942b58f 77 * Write a 1/0 to a single bit of the 16-bit port
jimherd 0:a6a5d942b58f 78 */
jimherd 0:a6a5d942b58f 79 void MCP23017::write_bit(int value, int bit_number) {
jimherd 0:a6a5d942b58f 80 if (value == 0) {
jimherd 0:a6a5d942b58f 81 shadow_GPIO &= ~(1 << bit_number);
jimherd 0:a6a5d942b58f 82 } else {
jimherd 0:a6a5d942b58f 83 shadow_GPIO |= 1 << bit_number;
jimherd 0:a6a5d942b58f 84 }
jimherd 0:a6a5d942b58f 85 writeRegister(GPIO, (unsigned short)shadow_GPIO);
jimherd 0:a6a5d942b58f 86 }
jimherd 0:a6a5d942b58f 87
jimherd 12:6d9d2b277f26 88 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 89 * Write a combination of bits to the 16-bit port
jimherd 0:a6a5d942b58f 90 */
jimherd 0:a6a5d942b58f 91 void MCP23017::write_mask(unsigned short data, unsigned short mask) {
jimherd 0:a6a5d942b58f 92 shadow_GPIO = (shadow_GPIO & ~mask) | data;
jimherd 0:a6a5d942b58f 93 writeRegister(GPIO, (unsigned short)shadow_GPIO);
jimherd 0:a6a5d942b58f 94 }
jimherd 0:a6a5d942b58f 95
jimherd 12:6d9d2b277f26 96 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 97 * read_bit
jimherd 0:a6a5d942b58f 98 * Read a single bit from the 16-bit port
jimherd 0:a6a5d942b58f 99 */
jimherd 0:a6a5d942b58f 100 int MCP23017::read_bit(int bit_number) {
jimherd 0:a6a5d942b58f 101 shadow_GPIO = readRegister(GPIO);
jimherd 0:a6a5d942b58f 102 return ((shadow_GPIO >> bit_number) & 0x0001);
jimherd 0:a6a5d942b58f 103 }
jimherd 0:a6a5d942b58f 104
jimherd 12:6d9d2b277f26 105 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 106 * read_mask
jimherd 0:a6a5d942b58f 107 */
jimherd 0:a6a5d942b58f 108 int MCP23017::read_mask(unsigned short mask) {
jimherd 0:a6a5d942b58f 109 shadow_GPIO = readRegister(GPIO);
jimherd 0:a6a5d942b58f 110 return (shadow_GPIO & mask);
jimherd 0:a6a5d942b58f 111 }
jimherd 0:a6a5d942b58f 112
jimherd 12:6d9d2b277f26 113 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 114 * Config
jimherd 0:a6a5d942b58f 115 * set direction and pull-up registers
jimherd 0:a6a5d942b58f 116 */
jimherd 0:a6a5d942b58f 117 void MCP23017::config(unsigned short dir_config, unsigned short pullup_config, unsigned short polarity_config) {
jimherd 0:a6a5d942b58f 118 shadow_IODIR = dir_config;
jimherd 0:a6a5d942b58f 119 writeRegister(IODIR, (unsigned short)shadow_IODIR);
jimherd 0:a6a5d942b58f 120 shadow_GPPU = pullup_config;
jimherd 0:a6a5d942b58f 121 writeRegister(GPPU, (unsigned short)shadow_GPPU);
jimherd 0:a6a5d942b58f 122 shadow_IPOL = polarity_config;
jimherd 0:a6a5d942b58f 123 writeRegister(IPOL, (unsigned short)shadow_IPOL);
jimherd 0:a6a5d942b58f 124 }
jimherd 0:a6a5d942b58f 125
jimherd 12:6d9d2b277f26 126 /*-----------------------------------------------------------------------------
jimherd 12:6d9d2b277f26 127 * writeRegister
jimherd 12:6d9d2b277f26 128 * write a byte
jimherd 12:6d9d2b277f26 129 */
jimherd 12:6d9d2b277f26 130 void MCP23017::writeRegister(int regAddress, unsigned char data) {
jimherd 12:6d9d2b277f26 131 char buffer[2];
jimherd 12:6d9d2b277f26 132
jimherd 12:6d9d2b277f26 133 buffer[0] = regAddress;
jimherd 12:6d9d2b277f26 134 buffer[1] = data;
jimherd 12:6d9d2b277f26 135 _i2c.write(MCP23017_i2cAddress, buffer, 2);
jimherd 12:6d9d2b277f26 136 }
jimherd 12:6d9d2b277f26 137
jimherd 12:6d9d2b277f26 138 /*----------------------------------------------------------------------------
jimherd 12:6d9d2b277f26 139 * write Register
jimherd 12:6d9d2b277f26 140 * write two bytes
jimherd 12:6d9d2b277f26 141 */
jimherd 12:6d9d2b277f26 142 void MCP23017::writeRegister(int regAddress, unsigned short data) {
jimherd 12:6d9d2b277f26 143 char buffer[3];
jimherd 12:6d9d2b277f26 144
jimherd 12:6d9d2b277f26 145 buffer[0] = regAddress;
jimherd 12:6d9d2b277f26 146 tmp_data.value16 = data;
jimherd 12:6d9d2b277f26 147 buffer[1] = tmp_data.value8[0];
jimherd 12:6d9d2b277f26 148 buffer[2] = tmp_data.value8[1];
jimherd 12:6d9d2b277f26 149
jimherd 12:6d9d2b277f26 150 _i2c.write(MCP23017_i2cAddress, buffer, 3);
jimherd 12:6d9d2b277f26 151 }
jimherd 12:6d9d2b277f26 152
jimherd 12:6d9d2b277f26 153 /*-----------------------------------------------------------------------------
jimherd 12:6d9d2b277f26 154 * readRegister
jimherd 12:6d9d2b277f26 155 */
jimherd 12:6d9d2b277f26 156 int MCP23017::readRegister(int regAddress) {
jimherd 12:6d9d2b277f26 157 char buffer[2];
jimherd 12:6d9d2b277f26 158
jimherd 12:6d9d2b277f26 159 buffer[0] = regAddress;
jimherd 12:6d9d2b277f26 160 _i2c.write(MCP23017_i2cAddress, buffer, 1);
jimherd 12:6d9d2b277f26 161 _i2c.read(MCP23017_i2cAddress, buffer, 2);
jimherd 12:6d9d2b277f26 162
jimherd 12:6d9d2b277f26 163 return ((int)(buffer[0] + (buffer[1]<<8)));
jimherd 12:6d9d2b277f26 164 }
jimherd 12:6d9d2b277f26 165
jimherd 12:6d9d2b277f26 166 /*-----------------------------------------------------------------------------
jimherd 12:6d9d2b277f26 167 * pinMode
jimherd 12:6d9d2b277f26 168 */
jimherd 12:6d9d2b277f26 169 void MCP23017::pinMode(int pin, int mode) {
jimherd 12:6d9d2b277f26 170 if (DIR_INPUT) {
jimherd 12:6d9d2b277f26 171 shadow_IODIR |= 1 << pin;
jimherd 12:6d9d2b277f26 172 } else {
jimherd 12:6d9d2b277f26 173 shadow_IODIR &= ~(1 << pin);
jimherd 12:6d9d2b277f26 174 }
jimherd 12:6d9d2b277f26 175 writeRegister(IODIR, (unsigned short)shadow_IODIR);
jimherd 12:6d9d2b277f26 176 }
jimherd 12:6d9d2b277f26 177
jimherd 12:6d9d2b277f26 178 /*-----------------------------------------------------------------------------
jimherd 12:6d9d2b277f26 179 * digitalRead
jimherd 12:6d9d2b277f26 180 */
jimherd 12:6d9d2b277f26 181 int MCP23017::digitalRead(int pin) {
jimherd 12:6d9d2b277f26 182 shadow_GPIO = readRegister(GPIO);
jimherd 12:6d9d2b277f26 183 if ( shadow_GPIO & (1 << pin)) {
jimherd 12:6d9d2b277f26 184 return 1;
jimherd 12:6d9d2b277f26 185 } else {
jimherd 12:6d9d2b277f26 186 return 0;
jimherd 12:6d9d2b277f26 187 }
jimherd 12:6d9d2b277f26 188 }
jimherd 12:6d9d2b277f26 189
jimherd 12:6d9d2b277f26 190 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 191 * digitalWrite
jimherd 0:a6a5d942b58f 192 */
jimherd 0:a6a5d942b58f 193 void MCP23017::digitalWrite(int pin, int val) {
jimherd 0:a6a5d942b58f 194 //If this pin is an INPUT pin, a write here will
jimherd 0:a6a5d942b58f 195 //enable the internal pullup
jimherd 0:a6a5d942b58f 196 //otherwise, it will set the OUTPUT voltage
jimherd 0:a6a5d942b58f 197 //as appropriate.
jimherd 0:a6a5d942b58f 198 bool isOutput = !(shadow_IODIR & 1<<pin);
jimherd 0:a6a5d942b58f 199
jimherd 0:a6a5d942b58f 200 if (isOutput) {
jimherd 0:a6a5d942b58f 201 //This is an output pin so just write the value
jimherd 0:a6a5d942b58f 202 if (val) shadow_GPIO |= 1 << pin;
jimherd 0:a6a5d942b58f 203 else shadow_GPIO &= ~(1 << pin);
jimherd 0:a6a5d942b58f 204 writeRegister(GPIO, (unsigned short)shadow_GPIO);
jimherd 0:a6a5d942b58f 205 } else {
jimherd 0:a6a5d942b58f 206 //This is an input pin, so we need to enable the pullup
jimherd 0:a6a5d942b58f 207 if (val) {
jimherd 0:a6a5d942b58f 208 shadow_GPPU |= 1 << pin;
jimherd 0:a6a5d942b58f 209 } else {
jimherd 0:a6a5d942b58f 210 shadow_GPPU &= ~(1 << pin);
jimherd 0:a6a5d942b58f 211 }
jimherd 0:a6a5d942b58f 212 writeRegister(GPPU, (unsigned short)shadow_GPPU);
jimherd 0:a6a5d942b58f 213 }
jimherd 0:a6a5d942b58f 214 }
jimherd 0:a6a5d942b58f 215
jimherd 12:6d9d2b277f26 216 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 217 * digitalWordRead
jimherd 0:a6a5d942b58f 218 */
jimherd 0:a6a5d942b58f 219 unsigned short MCP23017::digitalWordRead() {
jimherd 0:a6a5d942b58f 220 shadow_GPIO = readRegister(GPIO);
jimherd 0:a6a5d942b58f 221 return shadow_GPIO;
jimherd 0:a6a5d942b58f 222 }
jimherd 0:a6a5d942b58f 223
jimherd 12:6d9d2b277f26 224 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 225 * digitalWordWrite
jimherd 0:a6a5d942b58f 226 */
jimherd 0:a6a5d942b58f 227 void MCP23017::digitalWordWrite(unsigned short w) {
jimherd 0:a6a5d942b58f 228 shadow_GPIO = w;
jimherd 0:a6a5d942b58f 229 writeRegister(GPIO, (unsigned short)shadow_GPIO);
jimherd 0:a6a5d942b58f 230 }
jimherd 0:a6a5d942b58f 231
jimherd 12:6d9d2b277f26 232 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 233 * inputPolarityMask
jimherd 0:a6a5d942b58f 234 */
jimherd 0:a6a5d942b58f 235 void MCP23017::inputPolarityMask(unsigned short mask) {
jimherd 0:a6a5d942b58f 236 writeRegister(IPOL, mask);
jimherd 0:a6a5d942b58f 237 }
jimherd 0:a6a5d942b58f 238
jimherd 12:6d9d2b277f26 239 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 240 * inputoutputMask
jimherd 0:a6a5d942b58f 241 */
jimherd 0:a6a5d942b58f 242 void MCP23017::inputOutputMask(unsigned short mask) {
jimherd 0:a6a5d942b58f 243 shadow_IODIR = mask;
jimherd 0:a6a5d942b58f 244 writeRegister(IODIR, (unsigned short)shadow_IODIR);
jimherd 0:a6a5d942b58f 245 }
jimherd 0:a6a5d942b58f 246
jimherd 12:6d9d2b277f26 247 /*-----------------------------------------------------------------------------
jimherd 0:a6a5d942b58f 248 * internalPullupMask
jimherd 0:a6a5d942b58f 249 */
jimherd 0:a6a5d942b58f 250 void MCP23017::internalPullupMask(unsigned short mask) {
jimherd 0:a6a5d942b58f 251 shadow_GPPU = mask;
jimherd 0:a6a5d942b58f 252 writeRegister(GPPU, (unsigned short)shadow_GPPU);
jimherd 0:a6a5d942b58f 253 }
jimherd 0:a6a5d942b58f 254