MCP23009 is a general IO I2C chip . This lib provide higher level interface ( set pin value, set io modes etc ) without need to have knowledge of the I2C registers
Diff: mcp23009.cpp
- Revision:
- 0:d829b4edd564
- Child:
- 1:9146d773a5a3
diff -r 000000000000 -r d829b4edd564 mcp23009.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcp23009.cpp Fri Jun 03 12:40:49 2016 +0000 @@ -0,0 +1,117 @@ +#include "mcp23009.h" +//#include "mbed.h" // should not be in only for printf debug ? + + +#define VERSION_MCP23009_SRC "0.10" + +// definition registers + +#define IODIR 0 +#define IPOL 1 +#define GPINTEN 2 +#define DEFVAL 3 +#define INTCON 4 +#define IOCON 5 +#define GPPU 6 +#define INTF 7 +#define INTCAP 8 +#define GPIO 9 +#define OLAT 10 + +MCP23009::MCP23009(I2CInterface* i2cinterface, int device_address_bits ): + getVersion( VERSION_MCP23009_HDR,VERSION_MCP23009_SRC, __TIME__, __DATE__),_i2c_interface(i2cinterface) { + int _adrbytes= device_address_bits & 7; + // Assemble the full I2C device address. + _device_address = 0x40; // Prime the full device address with the device code. + _device_address |= (_adrbytes<<1); + + data[0]=IOCON; data[1]=0x20; // set no increase addr pointer, all intterupt off + _i2c_interface->write(_device_address, data,2); +} + +int MCP23009::status( int pinnr){ + int result=0; + data[0]=GPIO; + result= _i2c_interface->write(_device_address, data,1); // set reg + if ( result ) return -1; + char rb[0]; + result = _i2c_interface->read(_device_address,rb,1); // read the current status + if ( result ) return -2; + if ( pinnr != 8) { + rb[0] = rb[0] >> pinnr; + rb[0] = 1 &rb[0]; + } + return rb[0]; +} + +int MCP23009::set( int pinnr , int value){ + int result=0; + data[0]=OLAT; + if ( pinnr != 8) { + bool vb=false; + if ( value > 0) {vb=true;} + result=pinmanipulation( vb , pinnr); + } + else { + data[1]= (unsigned char) value ; + result = _i2c_interface->write(_device_address, data,2); + } + return result; +} + + int MCP23009::set_as_input(int pinnr,int pullup, int polarity ){ + return set_io_pin(true , pinnr, pullup, polarity ); +} + int MCP23009::set_as_output(int pinnr,int pullup, int polarity ){ + return set_io_pin(false , pinnr, pullup, polarity ); +} + +int MCP23009::set_io_pin(bool input ,int pinnr,int pullup, int polarity ){ + int result=0; + if ( pinnr >8 || pinnr < 0 ) return -20; + + data[0]=IODIR; + result=pinmanipulation( input , pinnr); + if ( result ) return result; + if (pullup >= 0) { + data[0]=GPPU; + bool pullup_b=false; + if ( pullup > 0) pullup_b =true; + result=pinmanipulation( pullup_b , pinnr); + if ( result ) return result; + } + if (polarity >= 0) { + data[0]=IPOL; + bool pol_b=false; + if ( polarity > 0) pol_b =true; + result=pinmanipulation( pol_b , pinnr); + if ( result ) return result; + } + return 0; +} + + +int MCP23009::pinmanipulation ( bool active , int pinnr ){ + int result=-10; + if (pinnr < 8 ) { + result= _i2c_interface->write(_device_address, data,1); // set to ioreg + if ( result ) return -1; + char rb[0]; + result = _i2c_interface->read(_device_address, rb,1); // read the current status + if ( result ) return -2; + data[1]= 1<<pinnr; + if ( active ) { data[1] |= rb[0]; } // new reg value for pinnr input + else { data[1] = ~data[1]; + data[1] &= rb[0]; // new reg value for pinnr ouput + } + if ( rb[0] != data[1]) { // only write if different + result=_i2c_interface->write(_device_address, data,2); + } + } + else { // change all pins + if ( active) data[1]=0xFF; else data[1]=0; + result=_i2c_interface->write(_device_address, data,2); + } + return result; +} +