Skip to content

Don't hide I2C error status. #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 55 additions & 47 deletions src/MCP23017.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ MCP23017::MCP23017(TwoWire& bus) {

MCP23017::~MCP23017() {}

void MCP23017::init()
bool MCP23017::init()
{
//BANK = 0 : sequential register addresses
//MIRROR = 0 : use configureInterrupt
Expand All @@ -24,31 +24,34 @@ void MCP23017::init()
//INTPOL = 0 : interrupt active low
//UNIMPLMENTED 0 : unimplemented: Read as ‘0’

writeRegister(MCP23017Register::IOCON, 0b00100000);
bool retval = writeRegister(MCP23017Register::IOCON, 0b00100000);

//enable all pull up resistors (will be effective for input pins only)
writeRegister(MCP23017Register::GPPU_A, 0xFF, 0xFF);
retval &= writeRegister(MCP23017Register::GPPU_A, 0xFF, 0xFF);

return retval;
}

void MCP23017::begin()
bool MCP23017::begin()
{
init();
return init();
}

void MCP23017::begin(uint8_t address)
bool MCP23017::begin(uint8_t address)
{
_deviceAddr = address;
begin();
return begin();
}

void MCP23017::portMode(MCP23017Port port, uint8_t directions, uint8_t pullups, uint8_t inverted)
bool MCP23017::portMode(MCP23017Port port, uint8_t directions, uint8_t pullups, uint8_t inverted)
{
writeRegister(MCP23017Register::IODIR_A + port, directions);
writeRegister(MCP23017Register::GPPU_A + port, pullups);
writeRegister(MCP23017Register::IPOL_A + port, inverted);
bool retVal = writeRegister(MCP23017Register::IODIR_A + port, directions);
retVal &= writeRegister(MCP23017Register::GPPU_A + port, pullups);
retVal &= writeRegister(MCP23017Register::IPOL_A + port, inverted);
return retVal;
}

void MCP23017::pinMode(uint8_t pin, uint8_t mode, bool inverted)
bool MCP23017::pinMode(uint8_t pin, uint8_t mode, bool inverted)
{
MCP23017Register iodirreg = MCP23017Register::IODIR_A;
MCP23017Register pullupreg = MCP23017Register::GPPU_A;
Expand All @@ -75,12 +78,13 @@ void MCP23017::pinMode(uint8_t pin, uint8_t mode, bool inverted)
if(inverted) bitSet(pol, pin);
else bitClear(pol, pin);

writeRegister(iodirreg, iodir);
writeRegister(pullupreg, pull);
writeRegister(polreg, pol);
bool retVal = writeRegister(iodirreg, iodir);
retVal &= writeRegister(pullupreg, pull);
retVal &= writeRegister(polreg, pol);
return retVal;
}

void MCP23017::digitalWrite(uint8_t pin, uint8_t state)
bool MCP23017::digitalWrite(uint8_t pin, uint8_t state)
{
MCP23017Register gpioreg = MCP23017Register::GPIO_A;
uint8_t gpio;
Expand All @@ -94,7 +98,7 @@ void MCP23017::digitalWrite(uint8_t pin, uint8_t state)
if(state == HIGH) bitSet(gpio, pin);
else bitClear(gpio, pin);

writeRegister(gpioreg, gpio);
return writeRegister(gpioreg, gpio);
}

uint8_t MCP23017::digitalRead(uint8_t pin)
Expand All @@ -112,14 +116,14 @@ uint8_t MCP23017::digitalRead(uint8_t pin)
return LOW;
}

void MCP23017::writePort(MCP23017Port port, uint8_t value)
bool MCP23017::writePort(MCP23017Port port, uint8_t value)
{
writeRegister(MCP23017Register::GPIO_A + port, value);
return writeRegister(MCP23017Register::GPIO_A + port, value);
}

void MCP23017::write(uint16_t value)
bool MCP23017::write(uint16_t value)
{
writeRegister(MCP23017Register::GPIO_A, lowByte(value), highByte(value));
return writeRegister(MCP23017Register::GPIO_A, lowByte(value), highByte(value));
}

uint8_t MCP23017::readPort(MCP23017Port port)
Expand All @@ -135,99 +139,103 @@ uint16_t MCP23017::read()
return a | b << 8;
}

void MCP23017::writeRegister(MCP23017Register reg, uint8_t value)
bool MCP23017::writeRegister(MCP23017Register reg, uint8_t value)
{
_bus->beginTransmission(_deviceAddr);
_bus->write(static_cast<uint8_t>(reg));
_bus->write(value);
_bus->endTransmission();
uint8_t retval = _bus->endTransmission();
return !retval;
}

void MCP23017::writeRegister(MCP23017Register reg, uint8_t portA, uint8_t portB)
bool MCP23017::writeRegister(MCP23017Register reg, uint8_t portA, uint8_t portB)
{
_bus->beginTransmission(_deviceAddr);
_bus->write(static_cast<uint8_t>(reg));
_bus->write(portA);
_bus->write(portB);
_bus->endTransmission();
uint8_t retval = _bus->endTransmission();
return !retval;
}


uint8_t MCP23017::readRegister(MCP23017Register reg)
{
_bus->beginTransmission(_deviceAddr);
_bus->write(static_cast<uint8_t>(reg));
_bus->endTransmission();
_bus->requestFrom(_deviceAddr, (uint8_t)1);
uint8_t retval = _bus->endTransmission();
retval &= _bus->requestFrom(_deviceAddr, (uint8_t)1);
return _bus->read();
}

void MCP23017::readRegister(MCP23017Register reg, uint8_t& portA, uint8_t& portB)
bool MCP23017::readRegister(MCP23017Register reg, uint8_t& portA, uint8_t& portB)
{
_bus->beginTransmission(_deviceAddr);
_bus->write(static_cast<uint8_t>(reg));
_bus->endTransmission();
_bus->requestFrom(_deviceAddr, (uint8_t)2);
uint8_t retval = _bus->endTransmission();
retval &= _bus->requestFrom(_deviceAddr, (uint8_t)2);
portA = _bus->read();
portB = _bus->read();
return !retval;
}

#ifdef _MCP23017_INTERRUPT_SUPPORT_

void MCP23017::interruptMode(MCP23017InterruptMode intMode)
bool MCP23017::interruptMode(MCP23017InterruptMode intMode)
{
uint8_t iocon = readRegister(MCP23017Register::IOCON);
if(intMode == MCP23017InterruptMode::Or) iocon |= static_cast<uint8_t>(MCP23017InterruptMode::Or);
else iocon &= ~(static_cast<uint8_t>(MCP23017InterruptMode::Or));

writeRegister(MCP23017Register::IOCON, iocon);
return writeRegister(MCP23017Register::IOCON, iocon);
}

void MCP23017::interrupt(MCP23017Port port, uint8_t mode)
bool MCP23017::interrupt(MCP23017Port port, uint8_t mode)
{
MCP23017Register defvalreg = MCP23017Register::DEFVAL_A + port;
MCP23017Register intconreg = MCP23017Register::INTCON_A + port;

//enable interrupt for port
writeRegister(MCP23017Register::GPINTEN_A + port, 0xFF);
bool retVal = writeRegister(MCP23017Register::GPINTEN_A + port, 0xFF);
switch(mode)
{
case CHANGE:
//interrupt on change
writeRegister(intconreg, 0);
retVal &= writeRegister(intconreg, 0);
break;
case FALLING:
//interrupt falling : compared against defval, 0xff
writeRegister(intconreg, 0xFF);
writeRegister(defvalreg, 0xFF);
retVal &= writeRegister(intconreg, 0xFF);
retVal &= writeRegister(defvalreg, 0xFF);
break;
case RISING:
//interrupt rising : compared against defval, 0x00
writeRegister(intconreg, 0xFF);
writeRegister(defvalreg, 0x00);
retVal &= writeRegister(intconreg, 0xFF);
retVal &= writeRegister(defvalreg, 0x00);
break;
}
return retVal;
}

void MCP23017::interruptedBy(uint8_t& portA, uint8_t& portB)
bool MCP23017::interruptedBy(uint8_t& portA, uint8_t& portB)
{
readRegister(MCP23017Register::INTF_A, portA, portB);
return readRegister(MCP23017Register::INTF_A, portA, portB);
}

void MCP23017::disableInterrupt(MCP23017Port port)
bool MCP23017::disableInterrupt(MCP23017Port port)
{
writeRegister(MCP23017Register::GPINTEN_A + port, 0x00);
return writeRegister(MCP23017Register::GPINTEN_A + port, 0x00);
}

void MCP23017::clearInterrupts()
bool MCP23017::clearInterrupts()
{
uint8_t a, b;
clearInterrupts(a, b);
return clearInterrupts(a, b);
}

void MCP23017::clearInterrupts(uint8_t& portA, uint8_t& portB)
bool MCP23017::clearInterrupts(uint8_t& portA, uint8_t& portB)
{
readRegister(MCP23017Register::INTCAP_A, portA, portB);
return readRegister(MCP23017Register::INTCAP_A, portA, portB);
}

#endif
34 changes: 17 additions & 17 deletions src/MCP23017.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,20 @@ class MCP23017
/**
* Uses the I2C address set during construction. Implicitly calls init().
*/
void begin();
bool begin();
/**
* Overrides the I2C address set by the constructor. Implicitly calls begin().

*/
void begin(uint8_t address);
bool begin(uint8_t address);
/**
* 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.
*
* See "3.2.1 Byte mode and Sequential mode".
*/
void init();
bool init();
/**
* Controls the pins direction on a whole port at once.
*
Expand All @@ -122,7 +122,7 @@ class MCP23017
*
* See "3.5.1 I/O Direction register".
*/
void portMode(MCP23017Port port, uint8_t directions, uint8_t pullups = 0xFF, uint8_t inverted = 0x00);
bool portMode(MCP23017Port port, uint8_t directions, uint8_t pullups = 0xFF, uint8_t inverted = 0x00);
/**
* Controls a single pin direction.
* Pin 0-7 for port A, 8-15 fo port B.
Expand All @@ -138,7 +138,7 @@ class MCP23017
* This library pinMode function behaves like Arduino's standard pinMode for consistency.
* [ OUTPUT | INPUT | INPUT_PULLUP ]
*/
void pinMode(uint8_t pin, uint8_t mode, bool inverted = false);
bool pinMode(uint8_t pin, uint8_t mode, bool inverted = false);

/**
* Writes a single pin state.
Expand All @@ -149,7 +149,7 @@ class MCP23017
*
* See "3.5.10 Port register".
*/
void digitalWrite(uint8_t pin, uint8_t state);
bool digitalWrite(uint8_t pin, uint8_t state);
/**
* Reads a single pin state.
* Pin 0-7 for port A, 8-15 for port B.
Expand All @@ -169,7 +169,7 @@ class MCP23017
*
* See "3.5.10 Port register".
*/
void writePort(MCP23017Port port, uint8_t value);
bool writePort(MCP23017Port port, uint8_t value);
/**
* Writes pins state to both ports.
*
Expand All @@ -178,7 +178,7 @@ class MCP23017
*
* See "3.5.10 Port register".
*/
void write(uint16_t value);
bool write(uint16_t value);

/**
* Reads pins state for a whole port.
Expand All @@ -202,15 +202,15 @@ class MCP23017
/**
* Writes a single register value.
*/
void writeRegister(MCP23017Register reg, uint8_t value);
bool writeRegister(MCP23017Register reg, uint8_t value);
/**
* Writes values to a register pair.
*
* 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(MCP23017Register reg, uint8_t portA, uint8_t portB);
bool writeRegister(MCP23017Register reg, uint8_t portA, uint8_t portB);
/**
* Reads a single register value.
*/
Expand All @@ -222,7 +222,7 @@ class MCP23017
* 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 readRegister(MCP23017Register reg, uint8_t& portA, uint8_t& portB);
bool readRegister(MCP23017Register reg, uint8_t& portA, uint8_t& portB);

#ifdef _MCP23017_INTERRUPT_SUPPORT_

Expand All @@ -234,28 +234,28 @@ class MCP23017
* Controls the IOCON.MIRROR bit.
* See "3.5.6 Configuration register".
*/
void interruptMode(MCP23017InterruptMode intMode);
bool interruptMode(MCP23017InterruptMode intMode);
/**
* Configures interrupt registers using an Arduino-like API.
* mode can be one of CHANGE, FALLING or RISING.
*/
void interrupt(MCP23017Port port, uint8_t mode);
bool interrupt(MCP23017Port port, uint8_t mode);
/**
* Disable interrupts for the specified port.
*/
void disableInterrupt(MCP23017Port port);
bool disableInterrupt(MCP23017Port port);
/**
* Reads which pin caused the interrupt.
*/
void interruptedBy(uint8_t& portA, uint8_t& portB);
bool interruptedBy(uint8_t& portA, uint8_t& portB);
/**
* Clears interrupts on both ports.
*/
void clearInterrupts();
bool clearInterrupts();
/**
* Clear interrupts on both ports. Returns port values at the time the interrupt occured.
*/
void clearInterrupts(uint8_t& portA, uint8_t& portB);
bool clearInterrupts(uint8_t& portA, uint8_t& portB);

#endif
};