Skip to content
Merged
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
56 changes: 56 additions & 0 deletions src/system/mcpExpander/mcpExpander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ bool IOExpander::begin(uint8_t _addr)

readMCPRegisters();

// Snapshot the INTF and INTCAP values that we just read into the cache.
// The bulk read in readMCPRegisters() returns registers 0x00..0x15
// sequentially, so INTFA (0x0E) and INTFB (0x0F) are read BEFORE INTCAPA
// (0x10) and INTCAPB (0x11). On the MCP23017, reading INTCAP is what
// clears the INTF latch as a side effect. So the cache positions for
// INTF (14, 15) and INTCAP (16, 17) currently hold the pre-clear values
// captured at the moment of the most recent interrupt — but those cache
// positions can be overwritten by subsequent reads (e.g. getInt() or
// getIntState()). Save the pre-clear values into dedicated members so
// application code can determine which expander pin caused a wake from
// deep sleep after begin() has cleared the live latch.
_interruptFlagsAtBegin = ((uint16_t)_ioExpanderRegs[15] << 8) | _ioExpanderRegs[14];
_interruptCaptureAtBegin = ((uint16_t)_ioExpanderRegs[17] << 8) | _ioExpanderRegs[16];

#ifdef IO_INT_ADDR
if (_addr == IO_INT_ADDR)
{
Expand Down Expand Up @@ -244,6 +258,48 @@ uint16_t IOExpander::getIntState()
return getINTStateInternal();
}

/**
* @brief getInterruptFlagsAtBegin returns the value of the MCP23017's
* INTFA/INTFB latch as it was at the moment begin() was called.
*
* begin()'s bulk register read passes through INTCAP, which
* clears the INTF latch as a side effect. After begin() returns,
* calling getInt() reads the live INTF register, which is now 0
* even if a wake-triggering interrupt was pending. This getter
* returns the value that was captured BEFORE that clear happened
* — useful for determining which pin triggered a wake from deep
* sleep on hardware where the MCP is kept powered during sleep
* (e.g. Inkplate 6 / 10).
*
* @return INTFA in low byte, INTFB in high byte
*/
uint16_t IOExpander::getInterruptFlagsAtBegin()
{
return _interruptFlagsAtBegin;
}

/**
* @brief getInterruptCaptureAtBegin returns the value of the MCP23017's
* INTCAPA/INTCAPB register as it was at the moment begin() was
* called.
*
* Pairing this with getInterruptFlagsAtBegin() lets callers
* distinguish rising vs falling edges on each interrupt-enabled
* pin even after begin() has cleared the latch.
*
* The library's getIntState() also returns INTCAP but does so
* via a fresh I2C read; that fresh value can be overwritten by
* any subsequent interrupt event (e.g. capacitive noise during
* application startup), whereas this snapshot is fixed at
* begin() time.
*
* @return INTCAPA in low byte, INTCAPB in high byte
*/
uint16_t IOExpander::getInterruptCaptureAtBegin()
{
return _interruptCaptureAtBegin;
}

/**
* @brief setPorts sets states on every IO Expander pin at once.
*
Expand Down
8 changes: 8 additions & 0 deletions src/system/mcpExpander/mcpExpander.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,21 @@ class IOExpander
void removeIntPin(uint8_t _pin);
uint16_t getInt();
uint16_t getIntState();
uint16_t getInterruptFlagsAtBegin();
uint16_t getInterruptCaptureAtBegin();
uint16_t getPorts();
void blockPinUsage(uint8_t _pin);
void unblockPinUsage(uint8_t _pin);
uint8_t _ioExpanderRegs[22];

private:
uint16_t _blockedPinsForUser = 0;
// INTF and INTCAP register values captured during begin()'s bulk read,
// BEFORE the same read clears the INTF latch as a side effect of passing
// through INTCAP. Lets callers determine which pin caused a wake from
// deep sleep after begin() has run.
uint16_t _interruptFlagsAtBegin = 0;
uint16_t _interruptCaptureAtBegin = 0;

const uint8_t regAddresses[22] = {
MCP23017_IODIRA, MCP23017_IODIRB, MCP23017_IPOLA, MCP23017_IPOLB, MCP23017_GPINTENA, MCP23017_GPINTENB,
Expand Down
Loading