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_
+};