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
mcp23009.cpp@0:d829b4edd564, 2016-06-03 (annotated)
- Committer:
- wbeaumont
- Date:
- Fri Jun 03 12:40:49 2016 +0000
- Revision:
- 0:d829b4edd564
- Child:
- 1:9146d773a5a3
initial version not tested with hw
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wbeaumont | 0:d829b4edd564 | 1 | #include "mcp23009.h" |
wbeaumont | 0:d829b4edd564 | 2 | //#include "mbed.h" // should not be in only for printf debug ? |
wbeaumont | 0:d829b4edd564 | 3 | |
wbeaumont | 0:d829b4edd564 | 4 | |
wbeaumont | 0:d829b4edd564 | 5 | #define VERSION_MCP23009_SRC "0.10" |
wbeaumont | 0:d829b4edd564 | 6 | |
wbeaumont | 0:d829b4edd564 | 7 | // definition registers |
wbeaumont | 0:d829b4edd564 | 8 | |
wbeaumont | 0:d829b4edd564 | 9 | #define IODIR 0 |
wbeaumont | 0:d829b4edd564 | 10 | #define IPOL 1 |
wbeaumont | 0:d829b4edd564 | 11 | #define GPINTEN 2 |
wbeaumont | 0:d829b4edd564 | 12 | #define DEFVAL 3 |
wbeaumont | 0:d829b4edd564 | 13 | #define INTCON 4 |
wbeaumont | 0:d829b4edd564 | 14 | #define IOCON 5 |
wbeaumont | 0:d829b4edd564 | 15 | #define GPPU 6 |
wbeaumont | 0:d829b4edd564 | 16 | #define INTF 7 |
wbeaumont | 0:d829b4edd564 | 17 | #define INTCAP 8 |
wbeaumont | 0:d829b4edd564 | 18 | #define GPIO 9 |
wbeaumont | 0:d829b4edd564 | 19 | #define OLAT 10 |
wbeaumont | 0:d829b4edd564 | 20 | |
wbeaumont | 0:d829b4edd564 | 21 | MCP23009::MCP23009(I2CInterface* i2cinterface, int device_address_bits ): |
wbeaumont | 0:d829b4edd564 | 22 | getVersion( VERSION_MCP23009_HDR,VERSION_MCP23009_SRC, __TIME__, __DATE__),_i2c_interface(i2cinterface) { |
wbeaumont | 0:d829b4edd564 | 23 | int _adrbytes= device_address_bits & 7; |
wbeaumont | 0:d829b4edd564 | 24 | // Assemble the full I2C device address. |
wbeaumont | 0:d829b4edd564 | 25 | _device_address = 0x40; // Prime the full device address with the device code. |
wbeaumont | 0:d829b4edd564 | 26 | _device_address |= (_adrbytes<<1); |
wbeaumont | 0:d829b4edd564 | 27 | |
wbeaumont | 0:d829b4edd564 | 28 | data[0]=IOCON; data[1]=0x20; // set no increase addr pointer, all intterupt off |
wbeaumont | 0:d829b4edd564 | 29 | _i2c_interface->write(_device_address, data,2); |
wbeaumont | 0:d829b4edd564 | 30 | } |
wbeaumont | 0:d829b4edd564 | 31 | |
wbeaumont | 0:d829b4edd564 | 32 | int MCP23009::status( int pinnr){ |
wbeaumont | 0:d829b4edd564 | 33 | int result=0; |
wbeaumont | 0:d829b4edd564 | 34 | data[0]=GPIO; |
wbeaumont | 0:d829b4edd564 | 35 | result= _i2c_interface->write(_device_address, data,1); // set reg |
wbeaumont | 0:d829b4edd564 | 36 | if ( result ) return -1; |
wbeaumont | 0:d829b4edd564 | 37 | char rb[0]; |
wbeaumont | 0:d829b4edd564 | 38 | result = _i2c_interface->read(_device_address,rb,1); // read the current status |
wbeaumont | 0:d829b4edd564 | 39 | if ( result ) return -2; |
wbeaumont | 0:d829b4edd564 | 40 | if ( pinnr != 8) { |
wbeaumont | 0:d829b4edd564 | 41 | rb[0] = rb[0] >> pinnr; |
wbeaumont | 0:d829b4edd564 | 42 | rb[0] = 1 &rb[0]; |
wbeaumont | 0:d829b4edd564 | 43 | } |
wbeaumont | 0:d829b4edd564 | 44 | return rb[0]; |
wbeaumont | 0:d829b4edd564 | 45 | } |
wbeaumont | 0:d829b4edd564 | 46 | |
wbeaumont | 0:d829b4edd564 | 47 | int MCP23009::set( int pinnr , int value){ |
wbeaumont | 0:d829b4edd564 | 48 | int result=0; |
wbeaumont | 0:d829b4edd564 | 49 | data[0]=OLAT; |
wbeaumont | 0:d829b4edd564 | 50 | if ( pinnr != 8) { |
wbeaumont | 0:d829b4edd564 | 51 | bool vb=false; |
wbeaumont | 0:d829b4edd564 | 52 | if ( value > 0) {vb=true;} |
wbeaumont | 0:d829b4edd564 | 53 | result=pinmanipulation( vb , pinnr); |
wbeaumont | 0:d829b4edd564 | 54 | } |
wbeaumont | 0:d829b4edd564 | 55 | else { |
wbeaumont | 0:d829b4edd564 | 56 | data[1]= (unsigned char) value ; |
wbeaumont | 0:d829b4edd564 | 57 | result = _i2c_interface->write(_device_address, data,2); |
wbeaumont | 0:d829b4edd564 | 58 | } |
wbeaumont | 0:d829b4edd564 | 59 | return result; |
wbeaumont | 0:d829b4edd564 | 60 | } |
wbeaumont | 0:d829b4edd564 | 61 | |
wbeaumont | 0:d829b4edd564 | 62 | int MCP23009::set_as_input(int pinnr,int pullup, int polarity ){ |
wbeaumont | 0:d829b4edd564 | 63 | return set_io_pin(true , pinnr, pullup, polarity ); |
wbeaumont | 0:d829b4edd564 | 64 | } |
wbeaumont | 0:d829b4edd564 | 65 | int MCP23009::set_as_output(int pinnr,int pullup, int polarity ){ |
wbeaumont | 0:d829b4edd564 | 66 | return set_io_pin(false , pinnr, pullup, polarity ); |
wbeaumont | 0:d829b4edd564 | 67 | } |
wbeaumont | 0:d829b4edd564 | 68 | |
wbeaumont | 0:d829b4edd564 | 69 | int MCP23009::set_io_pin(bool input ,int pinnr,int pullup, int polarity ){ |
wbeaumont | 0:d829b4edd564 | 70 | int result=0; |
wbeaumont | 0:d829b4edd564 | 71 | if ( pinnr >8 || pinnr < 0 ) return -20; |
wbeaumont | 0:d829b4edd564 | 72 | |
wbeaumont | 0:d829b4edd564 | 73 | data[0]=IODIR; |
wbeaumont | 0:d829b4edd564 | 74 | result=pinmanipulation( input , pinnr); |
wbeaumont | 0:d829b4edd564 | 75 | if ( result ) return result; |
wbeaumont | 0:d829b4edd564 | 76 | if (pullup >= 0) { |
wbeaumont | 0:d829b4edd564 | 77 | data[0]=GPPU; |
wbeaumont | 0:d829b4edd564 | 78 | bool pullup_b=false; |
wbeaumont | 0:d829b4edd564 | 79 | if ( pullup > 0) pullup_b =true; |
wbeaumont | 0:d829b4edd564 | 80 | result=pinmanipulation( pullup_b , pinnr); |
wbeaumont | 0:d829b4edd564 | 81 | if ( result ) return result; |
wbeaumont | 0:d829b4edd564 | 82 | } |
wbeaumont | 0:d829b4edd564 | 83 | if (polarity >= 0) { |
wbeaumont | 0:d829b4edd564 | 84 | data[0]=IPOL; |
wbeaumont | 0:d829b4edd564 | 85 | bool pol_b=false; |
wbeaumont | 0:d829b4edd564 | 86 | if ( polarity > 0) pol_b =true; |
wbeaumont | 0:d829b4edd564 | 87 | result=pinmanipulation( pol_b , pinnr); |
wbeaumont | 0:d829b4edd564 | 88 | if ( result ) return result; |
wbeaumont | 0:d829b4edd564 | 89 | } |
wbeaumont | 0:d829b4edd564 | 90 | return 0; |
wbeaumont | 0:d829b4edd564 | 91 | } |
wbeaumont | 0:d829b4edd564 | 92 | |
wbeaumont | 0:d829b4edd564 | 93 | |
wbeaumont | 0:d829b4edd564 | 94 | int MCP23009::pinmanipulation ( bool active , int pinnr ){ |
wbeaumont | 0:d829b4edd564 | 95 | int result=-10; |
wbeaumont | 0:d829b4edd564 | 96 | if (pinnr < 8 ) { |
wbeaumont | 0:d829b4edd564 | 97 | result= _i2c_interface->write(_device_address, data,1); // set to ioreg |
wbeaumont | 0:d829b4edd564 | 98 | if ( result ) return -1; |
wbeaumont | 0:d829b4edd564 | 99 | char rb[0]; |
wbeaumont | 0:d829b4edd564 | 100 | result = _i2c_interface->read(_device_address, rb,1); // read the current status |
wbeaumont | 0:d829b4edd564 | 101 | if ( result ) return -2; |
wbeaumont | 0:d829b4edd564 | 102 | data[1]= 1<<pinnr; |
wbeaumont | 0:d829b4edd564 | 103 | if ( active ) { data[1] |= rb[0]; } // new reg value for pinnr input |
wbeaumont | 0:d829b4edd564 | 104 | else { data[1] = ~data[1]; |
wbeaumont | 0:d829b4edd564 | 105 | data[1] &= rb[0]; // new reg value for pinnr ouput |
wbeaumont | 0:d829b4edd564 | 106 | } |
wbeaumont | 0:d829b4edd564 | 107 | if ( rb[0] != data[1]) { // only write if different |
wbeaumont | 0:d829b4edd564 | 108 | result=_i2c_interface->write(_device_address, data,2); |
wbeaumont | 0:d829b4edd564 | 109 | } |
wbeaumont | 0:d829b4edd564 | 110 | } |
wbeaumont | 0:d829b4edd564 | 111 | else { // change all pins |
wbeaumont | 0:d829b4edd564 | 112 | if ( active) data[1]=0xFF; else data[1]=0; |
wbeaumont | 0:d829b4edd564 | 113 | result=_i2c_interface->write(_device_address, data,2); |
wbeaumont | 0:d829b4edd564 | 114 | } |
wbeaumont | 0:d829b4edd564 | 115 | return result; |
wbeaumont | 0:d829b4edd564 | 116 | } |
wbeaumont | 0:d829b4edd564 | 117 |