diff --git a/DOCUMENTATION.MD b/DOCUMENTATION.MD new file mode 100644 index 0000000..219c471 --- /dev/null +++ b/DOCUMENTATION.MD @@ -0,0 +1,721 @@ +
+ +
+ + +++ + + + + + +
+ +
+
+MCP23017 16-Bit I/O Expander with Serial Interface +
+ +
+ + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + +
+ +## Public Member Functions + +
+ +#### [MCP23017](#mcp23017) (uint8\_t address, TwoWire \&bus=Wire) +#### void [init](#init)() +#### void [begin](#BEGIN)(uint8\_t pullup\_a=0x00, uint8\_t pullup\_b=0x00) +#### void [portMode](#400)(MCP23017\_PORT port, uint8\_t modes, uint8\_t pullups=0xff, uint8\_t inverteds=0x00) +#### void [pinMode](#500)(uint8\_t pin, uint8\_t mode, bool inverted=false) +#### void [digitalWrite](#600)(uint8\_t pin, uint8\_t state) +#### uint8\_t [digitalRead](#700)(uint8\_t pin) +#### void [writePort](#800)(MCP23017\_PORT port, uint8\_t values) +#### void [write](#900)(uint16\_t values) +#### uint8\_t [readPort](#1000)(MCP23017\_PORT port) +#### uint16\_t [read](#1100)() +#### void [writeRegister](#1200)(MCP23017\_REGISTER reg, uint8\_t value) +#### void [writeRegister](#1300)(MCP23017\_REGISTER reg, uint8\_t portA, uint8\_t portB) +#### uint8\_t [readRegister](#1400)(MCP23017\_REGISTER reg) +#### void [readRegister](#1500)(MCP23017\_REGISTER reg, uint8\_t \&portA, uint8\_t \&portB) +#### void [interruptMode](#1600)(MCP23017\_INTMODE intMode) +#### void [interrupt](#1700)(MCP23017\_PORT port, uint8\_t mode) +#### void [disableInterrupt](#1800)(MCP23017\_PORT port) +#### void [interruptedBy](#1900)(uint8\_t \&portA, uint8\_t \&portB) +#### void [clearInterrupts](#2000)() +#### void [clearInterrupts](#2100)(uint8\_t \&portA, uint8\_t \&portB) + +## Constructor & Destructor Documentation + +## [◆ ](#TOC)MCP23017() + +
+ +
+ +| | | | | +| ------------------ | - | --------- | -------------- | +| MCP23017::MCP23017 | ( | uint8\_t | *address*, | +| | | TwoWire & | *bus* = `Wire` | +| | ) | | | + +
+ +
+ +Instantiates a new instance to interact with a MCP23017 at the specified +address. + + - Parameters + + | | | + | ------- | -------------------------------------- | + | address | bus address of MCP23017 (0x20 \~ 0x27) | + | bus | refence to i2c bus object | + + +
+ +
+ +## Member Function Documentation + +## [◆ ](#TOC)begin() + +
+ +
+ +| | | | | +| -------------------- | - | -------- | --------------------- | +| void MCP23017::begin | ( | uint8\_t | *pullup\_a* = `0x00`, | +| | | uint8\_t | *pullup\_b* = `0x00` | +| | ) | | | + +
+ +
+ +Initializes the chip with the default configuration. Enables Byte mode +(IOCON.BANK = 0 and IOCON.SEQOP = 1). Enables pull-up resistors for all +pins by default. This will only be effective for input pins. + + - Note + See: "3.2.1 Byte mode and Sequential mode" + + + + - Parameters + + | | | + | --------- | ------------------------------------------------------------- | + | pullup\_a | bitmask for port A | + | pullup\_b | bitmask for port B See "3.2.1 Byte mode and Sequential mode". | + + +
+ +
+ + + +## [◆ ](#TOC)clearInterrupts() \[1/2\] + +
+ +
+ +Clears interrupts on both ports. + + - Note + See: "3.5.9 INTERRUPT CAPTURED REGISTER" + +
+ +
+ + + +## [◆ ](#TOC)clearInterrupts() \[2/2\] + +
+ +
+ +| | | | | +| ------------------------------ | - | ---------- | -------- | +| void MCP23017::clearInterrupts | ( | uint8\_t & | *portA*, | +| | | uint8\_t & | *portB* | +| | ) | | | + +
+ +
+ +Clear interrupts on both ports. Returns port values at the time the +interrupt occured. + + - Note + See: "3.5.9 INTERRUPT CAPTURED REGISTER" + + + + - Parameters + + | | | + | ----- | --------------------------------------------------------- | + | portA | reference to port A value; returns the value by reference | + | portB | reference to port B value; returns the value by reference | + + +
+ +
+ + + +## [◆ ](#TOC)digitalRead() + +
+ +
+ +Reads a single pin state. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ------ | ---------------------------------------------------------------- | + | pin | Pin 0-7 for port A, 8-15 for port B. | + | return | HIGH or 0x01, LOW or 0x00 depending the hardwarestate of the pin | + + +
+ +
+ + + +## [◆ ](#TOC)digitalWrite() + +
+ +
+ +| | | | | +| --------------------------- | - | -------- | ------- | +| void MCP23017::digitalWrite | ( | uint8\_t | *pin*, | +| | | uint8\_t | *state* | +| | ) | | | + +
+ +
+ +Writes a single pin state. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ----- | ------------------------------------ | + | pin | Pin 0-7 for port A, 8-15 for port B. | + | state | HIGH or 0x01 LOW or 0x00 | + + +
+ +
+ + + +## [◆ ](#TOC)disableInterrupt() + +
+ +
+ +| | | | | | +| ------------------------------- | - | -------------- | ------ | - | +| void MCP23017::disableInterrupt | ( | MCP23017\_PORT | *port* | ) | + +
+ +
+ +Disables interrupts for the specified port. + + - Note + See: "3.5.3 INTERRUPT-ON-CHANGE CONTROL REGISTER" + + + + - Parameters + + | | | + | ---- | -------------------- | + | port | MCP23017 port A or B | + + +
+ +
+ + + +## [◆ ](#TOC)interrupt() + +
+ +
+ +| | | | | +| ------------------------ | - | -------------- | ------- | +| void MCP23017::interrupt | ( | MCP23017\_PORT | *port*, | +| | | uint8\_t | *mode* | +| | ) | | | + +
+ +
+ +Configures interrupt registers using an Arduino-like API-mode . + + - Note + See: "3.5.3 INTERRUPT-ON-CHANGE CONTROL REGISTER" + + + + - Parameters + + | | | + | ---- | --------------------------------------- | + | port | MCP23017 port A or B | + | mode | Can be one of CHANGE, FALLING or RISING | + + +
+ +
+ + + +## [◆ ](#TOC)interruptedBy() + +
+ +
+ +| | | | | +| ---------------------------- | - | ---------- | -------- | +| void MCP23017::interruptedBy | ( | uint8\_t & | *portA*, | +| | | uint8\_t & | *portB* | +| | ) | | | + +
+ +
+ +Reads which pin caused the interrupt. + + - Note + See: "3.5.9 GPINTEN: INTERRUPT CAPTURED REGISTER" + + + + - Parameters + + | | | + | ----- | --------------------------------------------------------- | + | portA | reference to port A value; returns the value by reference | + | portB | reference to port B value; returns the value by reference | + + +
+ +
+ + + +## [◆ ](#TOC)interruptMode() + +
+ +
+ +| | | | | | +| ---------------------------- | - | ----------------- | --------- | - | +| void MCP23017::interruptMode | ( | MCP23017\_INTMODE | *intMode* | ) | + +
+ +
+ +Controls how the interrupt pins act with each other. If intMode is +SEPARATED, interrupt conditions on a port will cause its respective INT +pin to active. If intMode is OR, interrupt pins are OR'ed so an +interrupt on one of the port will cause both pints to active. + + - Note + See: "3.5.6 I/O EXPANDER CONFIGURATION REGISTER" + + + + - Parameters + + | | | + | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | + | intMode | When OR, the INTn pins are functionally OR’ed so that an interrupt on either port will cause both pins to activate. Otherwise use SEPARATED as parameter. | + + +
+ +
+ + + +## [◆ ](#TOC)pinMode() + +
+ +
+ +| | | | | +| ---------------------- | - | -------- | -------------------- | +| void MCP23017::pinMode | ( | uint8\_t | *pin*, | +| | | uint8\_t | *mode*, | +| | | bool | *inverted* = `false` | +| | ) | | | + +
+ +
+ +Sets a single pins' direction. When the pin is an input pin a pullup +and/or an inverted option can be specified. + + - Note + See: "3.5.1 I/O IODIR I/O DIRECTION REGISTER", "3.5.2 INPUT POLARITY REGISTER", "3.5.7 PULL-UP RESISTOR CONFIGURATION REGISTER" + + + + - Parameters + + | | | + | ---- | -------------------------------------------------------------------- | + | pin | Controls a single pin direction. Pin 0-7 for port A, 8-15 fo port B. | + | mode | INPUT or 0x00 INPUT\_PULLUP or 0x02 OUTPUT or 0x01 | + + +
+ +
+ + + +## [◆ ](#TOC)portMode() + +
+ +
+ +| | | | | +| ----------------------- | - | -------------- | -------------------- | +| void MCP23017::portMode | ( | MCP23017\_PORT | *port*, | +| | | uint8\_t | *modes*, | +| | | uint8\_t | *pullups* = `0xff`, | +| | | uint8\_t | *inverteds* = `0x00` | +| | ) | | | + +
+ +
+ +Controls the pins direction on a whole port at once. + + - Note + See: "3.5.1 I/O IODIR I/O DIRECTION REGISTER", "3.5.2 INPUT POLARITY REGISTER", "3.5.7 PULL-UP RESISTOR CONFIGURATION REGISTER + + + + - Parameters + + | | | + | --------- | -------------------------------------------------- | + | port | MCP23017 port A or B | + | modes | direction of whole port INPUT or 0x0 OUTPUT or0x01 | + | pullup | bitmask for internal 100k pullup resistors | + | inverteds | bitmask for inverted mode | + + +
+ +
+ + + +## [◆ ](#TOC)read() + +
+ +
+ +Reads pins state for both ports. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ------ | ---------------------------------------------------------------- | + | return | HIGH or 0x01, LOW or 0x00 depending the hardwarestate of the pin | + + +
+ +
+ + + +## [◆ ](#TOC)readPort() + +
+ +
+ +| | | | | | +| --------------------------- | - | -------------- | ------ | - | +| uint8\_t MCP23017::readPort | ( | MCP23017\_PORT | *port* | ) | + +
+ +
+ +Reads pins state for a whole port. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ------ | ---------------------------------------------------------------- | + | port | MCP23017 port A or B | + | return | HIGH or 0x01, LOW or 0x00 depending the hardwarestate of the pin | + + +
+ +
+ + + +## [◆ ](#TOC)readRegister() \[1/2\] + +
+ +
+ +| | | | | | +| ------------------------------- | - | ------------------ | ----- | - | +| uint8\_t MCP23017::readRegister | ( | MCP23017\_REGISTER | *reg* | ) | + +
+ +
+ +Reads a single registers value. + + - Parameters + + | | | + | --- | -------------------------------------------------------- | + | reg | register to read port A: 0x00 \~ 0A0 port B: 0x10 \~ 1A0 | + + +
+ +
+ + + +## [◆ ](#TOC)readRegister() \[2/2\] + +
+ +
+ +| | | | | +| --------------------------- | - | ------------------ | -------- | +| void MCP23017::readRegister | ( | MCP23017\_REGISTER | *reg*, | +| | | uint8\_t & | *portA*, | +| | | uint8\_t & | *portB* | +| | ) | | | + +
+ +
+ +Reads the values from a register pair. + + - Parameters + + | | | + | ----- | --------------------------------------------------------- | + | reg | register to read port A: 0x00 \~ 0A0 | + | portA | reference to port A value; returns the value by reference | + | portB | reference to port B value; returns the value by reference | + + + + + - Note + For portA and portB variable to effectively match the desired port, + you have to supply a portA register address to reg. Otherwise, + values will be reversed due to the way the MCP23017 works in Byte + mode. + +
+ +
+ + + +## [◆ ](#TOC)write() + +
+ +
+ +| | | | | | +| -------------------- | - | --------- | -------- | - | +| void MCP23017::write | ( | uint16\_t | *values* | ) | + +
+ +
+ +Writes pins state to both ports. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ------ | -------------------------------------------- | + | values | bitmask to manipulate all OUTPUT of the chip | + + +
+ +
+ + + +## [◆ ](#TOC)writePort() + +
+ +
+ +| | | | | +| ------------------------ | - | -------------- | -------- | +| void MCP23017::writePort | ( | MCP23017\_PORT | *port*, | +| | | uint8\_t | *values* | +| | ) | | | + +
+ +
+ +Writes pins state to a whole port. + + - Note + See: "3.5.10 Port register" + + + + - Parameters + + | | | + | ------ | ---------------------------------------------- | + | port | MCP23017 port A or B | + | values | bitmask to manipulate the given port as OUTPUT | + + +
+ +
+ + + +## [◆ ](#TOC)writeRegister() + +
+ +
+ +| | | | | +| ---------------------------- | - | ------------------ | -------- | +| void MCP23017::writeRegister | ( | MCP23017\_REGISTER | *reg*, | +| | | uint8\_t | *portA*, | +| | | uint8\_t | *portB* | +| | ) | | | + +
+ +
+ +Writes values to a register pair. + + - Note + For portA and portB variable to effectively match the desired port, + you have to supply a portA register address to reg. Otherwise, + values will be reversed due to the way the MCP23017 works in Byte + mode. + +
+ +
+ +----- \ No newline at end of file diff --git a/examples/InvertedInputs/InvertedInputs.ino b/examples/InvertedInputs/InvertedInputs.ino new file mode 100644 index 0000000..cd57b90 --- /dev/null +++ b/examples/InvertedInputs/InvertedInputs.ino @@ -0,0 +1,145 @@ +#include + +#define MCP23017_INTERRUPT_SUPPORT 1 +#include + +/** + * This sketch demonstrates the pin capabilities in pin- and portmode. + * Each of the 16 bits can eigher be an input which is inverted or not + * or having a 100k pullup resistor in same mode or just beeing an output. + * + * Some Interrupt capabilites are also shown + * + * Please connect: + * A5 => SCL (ON UNO R3) + * A4 => SDA (ON UNO R3) + * A3 => RST (ON UNO R3) + * INTA => D2 (ON UNO R3) + * INTB => D3 (ON UNO R3) + * A0 => B0 + * A1 => B1 + * A2 => B2 + * A3 => B3 + * A4 => B4 + * A5 => B5 + * A6 => B6 + * A7 => B7 + */ + +#define MCP23017_ADDR 0x20 + +MCP23017 mcp = MCP23017(MCP23017_ADDR); + +void int_pinA(){ + Serial.println("\n##### INTERRUPT PORT A FIRED #####\n"); +} + +void int_pinB(){ + Serial.println("\n##### INTERRUPT PORT B FIRED #####\n"); +} + +void setup() +{ + Serial.begin(115200); + delay(200); + // Serial.write(27); Serial.print("[2J"); // CLRSCR + // Serial.write(27); Serial.print("[H"); // HOME + + // reset pin + pinMode(A3, OUTPUT); + digitalWrite(A3, LOW); + delay(50); + digitalWrite(A3, HIGH); + delay(50); + + // interrupt pins + pinMode(2, INPUT_PULLUP); + pinMode(3, INPUT_PULLUP); + + attachInterrupt(digitalPinToInterrupt(2), int_pinA, RISING); + attachInterrupt(digitalPinToInterrupt(3), int_pinB, RISING); + + Wire.begin(); + mcp.begin(0x00, 0x00); + mcp.interruptMode(MCP23017_INTMODE::SEPARATED); + mcp.interrupt(MCP23017_PORT::A, CHANGE); + mcp.interrupt(MCP23017_PORT::B, CHANGE); + + bool error = false; + + // PORT A is input inverted with pullups + mcp.portMode( MCP23017_PORT::A, INPUT, 0xFF, 0xFF); + mcp.clearInterrupts(); + + // PORT B is output + mcp.portMode(MCP23017_PORT::B, OUTPUT); + + // Set all output pins to HIGH + mcp.writePort(MCP23017_PORT::B, 0xFF); + + Serial.println("##### Checking setting port mode #####\n"); + for (uint8_t i = 0; i < 8; i++) + { + + error |= (mcp.digitalRead(i) != mcp.digitalRead(i + 8)); + if (error) + { + Serial.print("Your connection "); + Serial.print(i); + Serial.print(" was wrong, please check it: "); + Serial.print("IN: "); + Serial.print(mcp.digitalRead(i) ? "HIGH" : "LOW"); + Serial.print(", OUT: "); + Serial.println(mcp.digitalRead(i + 8) ? "HIGH" : "LOW"); + } + } + + if (error) + Serial.println("--------- FAILED (see above) ----------"); + else + Serial.println("------------- SUCCEEDED --------------"); + + error = false; + mcp.clearInterrupts(); + + Serial.println("\n##### Checking setting pin mode #####\n"); + + for (uint8_t i = 0; i < 16; i++) + { + if (i < 8) + { + // PORT A is output for now + mcp.pinMode(i, OUTPUT); + } + else + { + // PORT B is input for now, inverted inputs with pullups + mcp.pinMode(i, INPUT_PULLUP, true); + } + } + + // Set all output pins to HIGH + mcp.writePort(MCP23017_PORT::A, 0xFF); + + for (uint8_t i = 0; i < 8; i++) + { + error |= (mcp.digitalRead(i) != mcp.digitalRead(i + 8)); + if (error) + { + Serial.print("Your connection "); + Serial.print(i); + Serial.print(" was wrong, please check it: "); + Serial.print("IN: "); + Serial.print(mcp.digitalRead(i + 8) ? "HIGH" : "LOW"); + Serial.print(", OUT: "); + Serial.println(mcp.digitalRead(i) ? "HIGH" : "LOW"); + } + } + + if (error) + Serial.println("--------- FAILED (see above) ----------"); + else + Serial.println("------------- SUCCEEDED --------------"); +} + +void loop() {} diff --git a/src/MCP23017.cpp b/src/MCP23017.cpp index 293675d..da02b49 100644 --- a/src/MCP23017.cpp +++ b/src/MCP23017.cpp @@ -7,40 +7,79 @@ MCP23017::MCP23017(uint8_t address, TwoWire& bus) { MCP23017::~MCP23017() {} -void MCP23017::init() -{ - //BANK = 0 : sequential register addresses - //MIRROR = 0 : use configureInterrupt - //SEQOP = 1 : sequential operation disabled, address pointer does not increment - //DISSLW = 0 : slew rate enabled - //HAEN = 0 : hardware address pin is always enabled on 23017 - //ODR = 0 : open drain output - //INTPOL = 0 : interrupt active low +void MCP23017::begin(uint8_t pullup_a, uint8_t pullup_b) +{ + //IOCON.BANK = 0 : sequential register addresses + //IOCON.MIRROR = 0 : use configureInterrupt + //IOCON.SEQOP = 1 : sequential operation disabled, address pointer does not increment + //IOCON.DISSLW = 0 : slew rate enabled + //IOCON.HAEN = 0 : hardware address pin is always enabled on 23017 + //IOCON.ODR = 0 : open drain output + //IOCON.INTPOL = 0 : interrupt active low + //IOCON bit 0 is spare writeRegister(MCP23017_REGISTER::IOCON, 0b00100000); //enable all pull up resistors (will be effective for input pins only) - writeRegister(MCP23017_REGISTER::GPPUA, 0xFF, 0xFF); + writeRegister(MCP23017_REGISTER::GPPUA, pullup_a, pullup_b); } -void MCP23017::portMode(MCP23017_PORT port, uint8_t value) +void MCP23017::portMode(MCP23017_PORT port, uint8_t modes, uint8_t pullups, uint8_t inverteds) { - writeRegister(MCP23017_REGISTER::IODIRA + port, value); + writeRegister(MCP23017_REGISTER::IODIRA + port, modes); + writeRegister(MCP23017_REGISTER::IPOLA + port, inverteds); + writeRegister(MCP23017_REGISTER::GPPUA + port, pullups); } -void MCP23017::pinMode(uint8_t pin, uint8_t mode) +void MCP23017::pinMode(uint8_t pin, uint8_t mode, bool inverted) { MCP23017_REGISTER iodirreg = MCP23017_REGISTER::IODIRA; - uint8_t iodir; + MCP23017_REGISTER polreg = MCP23017_REGISTER::IPOLA; + MCP23017_REGISTER pullreg = MCP23017_REGISTER::GPPUA; + if(pin > 7) { iodirreg = MCP23017_REGISTER::IODIRB; + polreg = MCP23017_REGISTER::IPOLB; + pullreg = MCP23017_REGISTER::GPPUB; pin -= 8; } - iodir = readRegister(iodirreg); - if(mode == OUTPUT) iodir &= ~_BV(pin); - else iodir |= _BV(pin); + uint8_t iodir = readRegister(iodirreg); + uint8_t pol = readRegister(polreg); + uint8_t pull = readRegister(pullreg); + + if(mode == OUTPUT) + { + iodir |= _BV(pin); + pol &= ~_BV(pin); + pull &= ~_BV(pin); + } + else + { + iodir &= ~_BV(pin); + + if(mode==INPUT_PULLUP) + { + pull |= _BV(pin); + } + else + { + pull &= ~_BV(pin); + } + + + if(inverted) + { + pol |= _BV(pin); + } + else + { + pol &= ~_BV(pin); + } + } + writeRegister(polreg, pol); + writeRegister(pullreg, pull); writeRegister(iodirreg, iodir); } @@ -76,14 +115,14 @@ uint8_t MCP23017::digitalRead(uint8_t pin) return LOW; } -void MCP23017::writePort(MCP23017_PORT port, uint8_t value) +void MCP23017::writePort(MCP23017_PORT port, uint8_t values) { - writeRegister(MCP23017_REGISTER::GPIOA + port, value); + writeRegister(MCP23017_REGISTER::GPIOA + port, values); } -void MCP23017::write(uint16_t value) +void MCP23017::write(uint16_t values) { - writeRegister(MCP23017_REGISTER::GPIOA, lowByte(value), highByte(value)); + writeRegister(MCP23017_REGISTER::GPIOA, lowByte(values), highByte(values)); } uint8_t MCP23017::readPort(MCP23017_PORT port) @@ -185,7 +224,7 @@ void MCP23017::disableInterrupt(MCP23017_PORT port) void MCP23017::clearInterrupts() { - uint8_t a, b; + uint8_t a=0, b=0; clearInterrupts(a, b); } @@ -194,4 +233,4 @@ void MCP23017::clearInterrupts(uint8_t& portA, uint8_t& portB) readRegister(MCP23017_REGISTER::INTCAPA, portA, portB); } -#endif +#endif // _MCP23017_INTERRUPT_SUPPORT_ diff --git a/src/MCP23017.h b/src/MCP23017.h index d467567..a23524f 100644 --- a/src/MCP23017.h +++ b/src/MCP23017.h @@ -3,7 +3,7 @@ #include #include -#define _MCP23017_INTERRUPT_SUPPORT_ ///< Enables support for MCP23017 interrupts. +#define _MCP23017_INTERRUPT_SUPPORT_ ///< Enables support for MCP23017 interrupts. enum class MCP23017_PORT : uint8_t { @@ -13,7 +13,7 @@ enum class MCP23017_PORT : uint8_t /** * Controls if the two interrupt pins mirror each other. - * See "3.6 Interrupt Logic". + * */ enum class MCP23017_INTMODE : uint8_t { @@ -24,7 +24,7 @@ enum class MCP23017_INTMODE : uint8_t /** * Registers addresses. * The library use addresses for IOCON.BANK = 0. - * See "3.2.1 Byte mode and Sequential mode". + * */ enum class MCP23017_REGISTER : uint8_t { @@ -51,6 +51,7 @@ enum class MCP23017_REGISTER : uint8_t OLATB = 0x15, ///< Provides access to the port B output latches. }; +/// @brief operator for adding a B-offset to the A-register inline MCP23017_REGISTER operator+(MCP23017_REGISTER a, MCP23017_PORT b) { return static_cast(static_cast(a) + static_cast(b)); }; @@ -63,119 +64,146 @@ class MCP23017 public: /** * Instantiates a new instance to interact with a MCP23017 at the specified address. + * @param address: bus address of MCP23017 (0x20 ~ 0x27) + * @param bus: refence to i2c bus object */ MCP23017(uint8_t address, TwoWire& bus = Wire); ~MCP23017(); #ifdef _DEBUG void debug(); #endif + + /** + * @brief deprecated, for backward compability only + * + */ + inline void init(){ + begin(); + } + /** * Initializes the chip with the default configuration. * Enables Byte mode (IOCON.BANK = 0 and IOCON.SEQOP = 1). - * Enables pull-up resistors for all pins. This will only be effective for input pins. + * Enables pull-up resistors for all pins by default. + * This will only be effective for input pins. + * * + * @param pullup_a: bitmask for port A + * @param pullup_b: bitmask for port B * See "3.2.1 Byte mode and Sequential mode". */ - void init(); + void begin(uint8_t pullup_a=0x00, uint8_t pullup_b=0x00); + /** * Controls the pins direction on a whole port at once. + * ", + * "3.5.2 I NPUT POLARITY REGISTER <0x01>", + * "3.5.7 PULL-UP RESISTOR CONFIGURATION REGISTER <0x06>"> + * @param port: MCP23017 port A or B + * @param modes: direction of whole port + * INPUT or 0x0 + * OUTPUT or0x01 + * @param pullup: bitmask for internal 100k pullup resistors + * @param inverteds: bitmask for inverted mode * - * 1 = Pin is configured as an input. - * 0 = Pin is configured as an output. - * - * See "3.5.1 I/O Direction register". */ - void portMode(MCP23017_PORT port, uint8_t value); + void portMode(MCP23017_PORT port, uint8_t modes, uint8_t pullups=0xff, uint8_t inverteds=0x00); + /** - * Controls a single pin direction. - * Pin 0-7 for port A, 8-15 fo port B. - * - * 1 = Pin is configured as an input. - * 0 = Pin is configured as an output. - * - * See "3.5.1 I/O Direction register". + * Sets a single pins' direction. When the pin is an input pin + * a pullup and/or an inverted option can be specified + * ", + * "3.5.2 I NPUT POLARITY REGISTER <0x01>", + * "3.5.7 PULL-UP RESISTOR CONFIGURATION REGISTER <0x06>"> + * @param pin: Controls a single pin direction. + * Pin 0-7 for port A, 8-15 fo port B. + * @param mode: + * INPUT or 0x00 + * INPUT_PULLUP or 0x02 + * OUTPUT or 0x01 */ - void pinMode(uint8_t pin, uint8_t mode); + void pinMode(uint8_t pin, uint8_t mode, bool inverted=false); /** * Writes a single pin state. - * Pin 0-7 for port A, 8-15 for port B. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param pin: Pin 0-7 for port A, 8-15 for port B. + * @param state: HIGH or 0x01 + * LOW or 0x00 */ void digitalWrite(uint8_t pin, uint8_t state); + /** * Reads a single pin state. - * Pin 0-7 for port A, 8-15 for port B. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param pin: Pin 0-7 for port A, 8-15 for port B. + * @param return HIGH or 0x01, LOW or 0x00 + * depending the hardwarestate of the pin */ uint8_t digitalRead(uint8_t pin); /** * Writes pins state to a whole port. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param port: MCP23017 port A or B + * @param values: bitmask to manipulate the given port as OUTPUT */ - void writePort(MCP23017_PORT port, uint8_t value); + void writePort(MCP23017_PORT port, uint8_t values); + /** * Writes pins state to both ports. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param values: bitmask to manipulate all OUTPUT of the chip */ - void write(uint16_t value); + void write(uint16_t values); /** * Reads pins state for a whole port. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param port: MCP23017 port A or B + * @param return HIGH or 0x01, LOW or 0x00 + * depending the hardwarestate of the pin */ uint8_t readPort(MCP23017_PORT port); + /** * Reads pins state for both ports. - * - * 1 = Logic-high - * 0 = Logic-low - * - * See "3.5.10 Port register". + * ".> + * @param return HIGH or 0x01, LOW or 0x00 + * depending the hardwarestate of the pin */ uint16_t read(); /** - * Writes a single register value. + * Writes a single register @reg with the specified value @val. */ void writeRegister(MCP23017_REGISTER reg, uint8_t value); + /** * Writes values to a register pair. * - * For portA and portB variable to effectively match the desired port, + * @note For portA and portB variable to effectively match the desired port, * you have to supply a portA register address to reg. Otherwise, values * will be reversed due to the way the MCP23017 works in Byte mode. */ void writeRegister(MCP23017_REGISTER reg, uint8_t portA, uint8_t portB); + /** - * Reads a single register value. + * Reads a single registers value. + * @param reg: register to read + * port A: 0x00 ~ 0A0 + * port B: 0x10 ~ 1A0 */ uint8_t readRegister(MCP23017_REGISTER reg); + /** * Reads the values from a register pair. + * @param reg: register to read + * port A: 0x00 ~ 0A0 + * @param portA: reference to port A value; returns the value by reference + * @param portB: reference to port B value; returns the value by reference * - * For portA and portB variable to effectively match the desired port, + * @note For portA and portB variable to effectively match the desired port, * you have to supply a portA register address to reg. Otherwise, values * will be reversed due to the way the MCP23017 works in Byte mode. */ @@ -184,35 +212,56 @@ class MCP23017 #ifdef _MCP23017_INTERRUPT_SUPPORT_ /** - * Controls how the interrupt pins act with each other. + * @brief Controls how the interrupt pins act with each other. * If intMode is SEPARATED, interrupt conditions on a port will cause its respective INT pin to active. * If intMode is OR, interrupt pins are OR'ed so an interrupt on one of the port will cause both pints to active. + * ".> * - * Controls the IOCON.MIRROR bit. - * See "3.5.6 Configuration register". + * @param intMode When OR, the INTn pins are functionally OR’ed so that an interrupt on either port will cause both pins to activate. Otherwise use SEPARATED as parameter. */ void interruptMode(MCP23017_INTMODE intMode); + /** - * Configures interrupt registers using an Arduino-like API. - * mode can be one of CHANGE, FALLING or RISING. + * @brief Configures interrupt registers using an Arduino-like API-mode . + * + * + * @param port MCP23017 port A or B + * @param mode Can be one of CHANGE, FALLING or RISING */ void interrupt(MCP23017_PORT port, uint8_t mode); + + /** - * Disable interrupts for the specified port. + * @brief Disables interrupts for the specified port. + * + * + * @param port MCP23017 port A or B */ void disableInterrupt(MCP23017_PORT port); + /** - * Reads which pin caused the interrupt. + * @brief Reads which pin caused the interrupt. + * + * + * @param portA reference to port A value; returns the value by reference + * @param portB reference to port B value; returns the value by reference */ void interruptedBy(uint8_t& portA, uint8_t& portB); + /** - * Clears interrupts on both ports. + * @brief Clears interrupts on both ports. + * */ void clearInterrupts(); + /** - * Clear interrupts on both ports. Returns port values at the time the interrupt occured. + * @brief Clear interrupts on both ports. Returns port values at the time the interrupt occured. + * + * + * @param portA reference to port A value; returns the value by reference + * @param portB reference to port B value; returns the value by reference */ void clearInterrupts(uint8_t& portA, uint8_t& portB); -#endif -}; \ No newline at end of file +#endif // _MCP23017_INTERRUPT_SUPPORT_ +};