A library for the Microchip MCP23008 I2C 8-bit I/O expander.
Diff: MCP23008.cpp
- Revision:
- 0:4f712bd739d0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP23008.cpp Fri Jun 15 03:31:48 2012 +0000 @@ -0,0 +1,120 @@ +#include "MCP23008.hpp" + +namespace { +const uint8_t MCP23008_ADDRESS = 0x40; + +/* MCP23008 registers */ +const uint8_t IODIR = 0x00; +const uint8_t IPOL = 0x01; +const uint8_t GPINTEN = 0x02; +const uint8_t DEFVAL = 0x03; +const uint8_t INTCON = 0x04; +const uint8_t IOCON = 0x05; +const uint8_t GPPU = 0x06; +const uint8_t INTF = 0x07; +const uint8_t INTCAP = 0x08; +const uint8_t GPIO = 0x09; +const uint8_t OLAT = 0x0A; +}; + +MCP23008::MCP23008 ( PinName sda, PinName scl, uint8_t address, Frequency freq ) + : i2c ( sda, scl ), + i2c_address ( MCP23008_ADDRESS | address ) { + if ( address > 7 ) + error ( "MCP23008::MCP23008: address is out of range, must be <= 7\n" ); + + i2c.frequency ( ( int ) freq ); + reset (); +} + +void MCP23008::set_input_pins ( uint8_t pins ) { + uint8_t value = read_register ( IODIR ); + write_register ( IODIR, value | pins ); +} + +void MCP23008::set_output_pins ( uint8_t pins ) { + uint8_t value = read_register ( IODIR ); + write_register ( IODIR, value & ~pins ); +} + +void MCP23008::write_outputs ( uint8_t values ) { + write_register ( GPIO, values ); +} + +uint8_t MCP23008::read_outputs () { + return read_register ( OLAT ); +} + +uint8_t MCP23008::read_inputs () { + return read_register ( GPIO ); +} + +void MCP23008::set_input_polarity ( uint8_t values ) { + write_register ( IPOL, values ); +} + +uint8_t MCP23008::get_input_polarity () { + return read_register ( IPOL ); +} + +void MCP23008::set_pullups ( uint8_t values ) { + write_register ( GPPU, values ); +} + +uint8_t MCP23008::get_pullups () { + return read_register ( GPPU ); +} + +void MCP23008::interrupt_on_changes ( uint8_t pins ) { + uint8_t value = read_register ( INTCON ); + value &= ~pins; + write_register ( INTCON, value ); + value = read_register ( GPINTEN ); + value |= pins; + write_register ( GPINTEN, value ); +} + +void MCP23008::disable_interrupts ( uint8_t pins ) { + uint8_t value = read_register ( GPINTEN ); + value &= ~pins; + write_register ( GPINTEN, value ); +} + +void MCP23008::acknowledge_interrupt ( uint8_t &pin, uint8_t &values ) { + pin = read_register ( INTF ); + values = read_register ( INTCAP ); +} + +uint8_t MCP23008::read_register ( uint8_t reg ) { + char data[] = {reg}; + if ( 0 != i2c.write ( i2c_address, data, 1 ) ) + error ( "MCP23008::read_register: Missing ACK for write\n" ); + + if ( 0 != i2c.read ( i2c_address, data, 1 ) ) + error ( "MCP23008:read_register: Missing ACK for read\n" ); + + return data[0]; +} + +void MCP23008::write_register ( uint8_t reg, uint8_t value ) { + char data[] = {reg, value}; + if ( 0 != i2c.write ( i2c_address, data, 2 ) ) + error ( "MCP23008::write_register: Missing ACK for write\n" ); +} + +void MCP23008::write_mask ( uint8_t reg, uint8_t mask, bool value ) { + uint8_t val; + val = read_register ( reg ); + if ( value ) + val |= mask; + else + val &= ~mask; + + write_register ( reg, val ); +} + +void MCP23008::reset ( ) { + write_register ( IODIR, 0xFF ); + for ( uint8_t reg = IPOL; reg <= OLAT; reg++ ) + write_register ( reg, 0 ); +}