Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:4f712bd739d0, committed 2012-06-15
- Comitter:
- dewyatt
- Date:
- Fri Jun 15 03:31:48 2012 +0000
- Commit message:
Changed in this revision
MCP23008.cpp | Show annotated file Show diff for this revision Revisions of this file |
MCP23008.hpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 4f712bd739d0 MCP23008.cpp --- /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 ); +}
diff -r 000000000000 -r 4f712bd739d0 MCP23008.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MCP23008.hpp Fri Jun 15 03:31:48 2012 +0000 @@ -0,0 +1,162 @@ +#include "mbed.h" + +/** MCP23008 class + * + * Allow access to an I2C connected MCP23008 8-bit I/O extender chip + * + */ +class MCP23008 { +public: + enum Frequency { + Frequency_100KHz = 100000, + Frequency_400KHz = 400000, + /* Note: 1.7MHz probably won't work for mbed */ + Frequency_1700KHz = 1700000 + }; + enum Pin { + Pin_GP0 = 0x01, + Pin_GP1 = 0x02, + Pin_GP2 = 0x04, + Pin_GP3 = 0x08, + Pin_GP4 = 0x10, + Pin_GP5 = 0x20, + Pin_GP6 = 0x40, + Pin_GP7 = 0x80, + Pin_All = 0xFF + }; + /** Constructor + * + * @param sda I2C sda pin + * @param scl I2C scl pin + * @param address The hardware address of the MCP23008. This is the 3-bit + * value that is physically set via A0, A1, and A2. + * @param freq The I2C frequency. Should probably be 100KHz or 400KHz. + */ + MCP23008 ( PinName sda, PinName scl, uint8_t address, Frequency freq = Frequency_100KHz ); + + /** Set pins to input mode + * + * This function is used to set which pins are inputs (if any). Example: + * set_inputs ( Pin_GP0 | Pin_GP1 | Pin_GP2 ); + * Note that these are set to input in addition to the previously set. + * In other words, the following: + * set_inputs ( Pin_GP1 ); + * set_inputs ( Pin_GP2 ); + * Results in at least two pins set to input. + * + * @param pins A bitmask of pins to set to input mode. + */ + void set_input_pins ( uint8_t pins ); + /** Set pins to output mode + * + * This function is used to set which pins are outputs (if any). Example: + * set_outputs ( Pin_GP0 | Pin_GP1 | Pin_GP2 ); + * Note that these are set to output in addition to the previously set. + * In other words, the following: + * set_outputs ( Pin_GP1 ); + * set_outputs ( Pin_GP2 ); + * Results in at least two pins set to output. + * + * @param pins A bitmask of pins to set to output mode. + */ + void set_output_pins ( uint8_t pins ); + + /** Write to the output pins. + * + * This function is used to set output pins on or off. + * + * @param values A bitmask indicating whether a pin should be on or off. + */ + void write_outputs ( uint8_t values ); + /** Read back the outputs. + * + * This function is used to read the last values written to the output pins. + * + * @returns The value from the OLAT register. + */ + uint8_t read_outputs (); + + /** Read from the input pins. + * + * This function is used to read the values from the input pins. + * + * @returns A bitmask of the current state of the input pins. + */ + uint8_t read_inputs (); + + /** Set the input pin polarity. + * + * This function sets the polarity of the input pins. + * A 1 bit is inverted polarity, a 0 is normal. + * + * @param values A bitmask of the input polarity. + */ + void set_input_polarity ( uint8_t values ); + /** Read back the current input pin polarity. + * + * This function reads the current state of the input pin polarity. + * + * @returns The value from the IPOL register. + */ + uint8_t get_input_polarity (); + + /** Enable and disable the internal pull-up resistors for input pins. + * + * This function enables the internal 100 kΩ pull-up resistors. + * A 1 bit enables the pull-up resistor for the corresponding input pin. + * + * @param values A bitmask indicating which pull-up resistors should be enabled/disabled. + */ + void set_pullups ( uint8_t values ); + /** Get the current state of the internal pull-up resistors. + * + * @returns The current state of the pull-up resistors. + */ + uint8_t get_pullups (); + + /** Generate an interrupt when a pin changes. + * + * This function enables interrupt generation for the specified pins. + * The interrupt is active-low by default. + * The function acknowledge_interrupt must be called before another + * interrupt will be generated. + * Example: + * @code + * InterruptIn in ( p16 ); + * MCP23008 mcp ( p9, p10, 0 ); + * in.fall ( &interrupt ); + * mcp.interrupt_on_changes ( MCP23008::Pin_GP0 ); + * while ( 1 ) { + * wait ( 1 ); + * } + * @endcode + * + * @param pins A bitmask of the pins that may generate an interrupt. + */ + void interrupt_on_changes ( uint8_t pins ); + /** Disables interrupts for the specified pins. + * + * @param values A bitmask indicating which interrupts should be disabled. + */ + void disable_interrupts ( uint8_t pins ); + + /** Acknowledge a generated interrupt. + * + * This function must be called when an interrupt is generated to discover + * which pin caused the interrupt and to enable future interrupts. + * + * @param pin An output paramter that specifies which pin generated the interrupt. + * @param values The current state of the input pins. + */ + void acknowledge_interrupt ( uint8_t &pin, uint8_t &values ); + +private: + uint8_t read_register ( uint8_t reg ); + void write_register ( uint8_t reg, uint8_t value ); + void write_mask ( uint8_t reg, uint8_t mask, bool value ); + + void reset (); + + I2C i2c; + uint8_t i2c_address; +};