Committer:
GobertPierre
Date:
Fri Apr 13 17:44:17 2012 +0000
Revision:
0:d76c38ee24ab

        

Who changed what in which revision?

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