Daniel Wyatt / MCP23008
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MCP23008.cpp Source File

MCP23008.cpp

00001 #include "MCP23008.hpp"
00002 
00003 namespace {
00004 const uint8_t MCP23008_ADDRESS  = 0x40;
00005 
00006 /* MCP23008 registers */
00007 const uint8_t IODIR             = 0x00;
00008 const uint8_t IPOL              = 0x01;
00009 const uint8_t GPINTEN           = 0x02;
00010 const uint8_t DEFVAL            = 0x03;
00011 const uint8_t INTCON            = 0x04;
00012 const uint8_t IOCON             = 0x05;
00013 const uint8_t GPPU              = 0x06;
00014 const uint8_t INTF              = 0x07;
00015 const uint8_t INTCAP            = 0x08;
00016 const uint8_t GPIO              = 0x09;
00017 const uint8_t OLAT              = 0x0A;
00018 };
00019 
00020 MCP23008::MCP23008 ( PinName sda, PinName scl, uint8_t address, Frequency freq )
00021         : i2c ( sda, scl ),
00022         i2c_address ( MCP23008_ADDRESS | address ) {
00023     if ( address > 7 )
00024         error ( "MCP23008::MCP23008: address is out of range, must be <= 7\n" );
00025 
00026     i2c.frequency ( ( int ) freq );
00027     reset ();
00028 }
00029 
00030 void MCP23008::set_input_pins ( uint8_t pins ) {
00031     uint8_t value = read_register ( IODIR );
00032     write_register ( IODIR, value | pins );
00033 }
00034 
00035 void MCP23008::set_output_pins ( uint8_t pins ) {
00036     uint8_t value = read_register ( IODIR );
00037     write_register ( IODIR, value & ~pins );
00038 }
00039 
00040 void MCP23008::write_outputs ( uint8_t values ) {
00041     write_register ( GPIO, values );
00042 }
00043 
00044 uint8_t MCP23008::read_outputs () {
00045     return read_register ( OLAT );
00046 }
00047 
00048 uint8_t MCP23008::read_inputs () {
00049     return read_register ( GPIO );
00050 }
00051 
00052 void MCP23008::set_input_polarity ( uint8_t values ) {
00053     write_register ( IPOL, values );
00054 }
00055 
00056 uint8_t MCP23008::get_input_polarity () {
00057     return read_register ( IPOL );
00058 }
00059 
00060 void MCP23008::set_pullups ( uint8_t values ) {
00061     write_register ( GPPU, values );
00062 }
00063 
00064 uint8_t MCP23008::get_pullups () {
00065     return read_register ( GPPU );
00066 }
00067 
00068 void MCP23008::interrupt_on_changes ( uint8_t pins ) {
00069     uint8_t value = read_register ( INTCON );
00070     value &= ~pins;
00071     write_register ( INTCON, value );
00072     value = read_register ( GPINTEN );
00073     value |= pins;
00074     write_register ( GPINTEN, value );
00075 }
00076 
00077 void MCP23008::disable_interrupts ( uint8_t pins ) {
00078     uint8_t value = read_register ( GPINTEN );
00079     value &= ~pins;
00080     write_register ( GPINTEN, value );
00081 }
00082 
00083 void MCP23008::acknowledge_interrupt ( uint8_t &pin, uint8_t &values ) {
00084     pin = read_register ( INTF );
00085     values = read_register ( INTCAP );
00086 }
00087 
00088 uint8_t MCP23008::read_register ( uint8_t reg ) {
00089     char data[] = {reg};
00090     if ( 0 != i2c.write ( i2c_address, data, 1 ) )
00091         error ( "MCP23008::read_register: Missing ACK for write\n" );
00092 
00093     if ( 0 != i2c.read ( i2c_address, data, 1 ) )
00094         error ( "MCP23008:read_register: Missing ACK for read\n" );
00095 
00096     return data[0];
00097 }
00098 
00099 void MCP23008::write_register ( uint8_t reg, uint8_t value ) {
00100     char data[] = {reg, value};
00101     if ( 0 != i2c.write ( i2c_address, data, 2 ) )
00102         error ( "MCP23008::write_register: Missing ACK for write\n" );
00103 }
00104 
00105 void MCP23008::write_mask ( uint8_t reg, uint8_t mask, bool value ) {
00106     uint8_t val;
00107     val = read_register ( reg );
00108     if ( value )
00109         val |= mask;
00110     else
00111         val &= ~mask;
00112 
00113     write_register ( reg, val );
00114 }
00115 
00116 void MCP23008::reset ( ) {
00117     write_register ( IODIR, 0xFF );
00118     for ( uint8_t reg = IPOL; reg <= OLAT; reg++ )
00119         write_register ( reg, 0 );
00120 }