Skip to content
New issue

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

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

Already on GitHub? # to your account

Addressing the 16 bit registers. #50

Open
RobTillaart opened this issue Nov 19, 2024 · 0 comments
Open

Addressing the 16 bit registers. #50

RobTillaart opened this issue Nov 19, 2024 · 0 comments
Assignees
Labels
question Further information is requested

Comments

@RobTillaart
Copy link
Owner

extracted from - #48

Investigate if it is worth breaking the interface.


So in general I believe the the 16 functions are a bit conceptually out of whack with the single pin versions. However I see that this has to do with what arises naturally out of the MCP23S17's register map rather than any Library issue.

The natural 0..15 (used in single pin functions) is:
GPA0, GPA1 ... GPA7, GPB0, GPB1, ... GPB7

The 0..15 from the datasheet (used in 16 pin functions) is:
GPB0, GPB1 ... GPB7, GPA0, GPA1, ... GPA7

I think the only way to get consistency would be to swap the first and second byte so that you could use reg[3] to access GPA4, matching the "natural" way (for me at least). I don't think using [15..0] would have the desired effect.

However, I'm honestly not sure that's worth doing regardless. The 16 mode as implemented matches the datasheet so I'd say it's best to leave it alone and let people choose to either use the 16 bit "full" interface or the single bit at a time interface. The only reason for my difficulty was because the enableInterrupt function appeared to match the pinMode1 function but didn't.


Alternatively, I had another thought of how to achieve consistency (again I don't know that it's worth upending the library).

This section of code in begin() exists to ensure the sequential mode is active:

//  disable address increment - datasheet P20
//  note that address increment must be enabled for readReg16() and writeReg16() to work.
//    SEQOP: Sequential Operation mode bit
//    1 = Sequential operation disabled, address pointer does not increment.
//    0 = Sequential operation enabled, address pointer increments.
uint8_t reg = readReg(MCP23x17_IOCR);
if (reg & MCP23x17_IOCR_SEQOP)  //  check if already zero
{
  reg &= ~MCP23x17_IOCR_SEQOP;  //  clear SEQOP bit for sequential read/write
  if (! writeReg(MCP23x17_IOCR, reg)) return false;
}

The phrase "note that address increment must be enabled for readReg16() and writeReg16() to work" is actually not quite accurate. On page 13 of the datasheet -

A special mode (Byte mode with IOCON.BANK = 0)
causes the address pointer to toggle between
associated A/B register pairs. For example, if the BANK
bit is cleared and the Address Pointer is initially set to
address 12h (GPIOA) or 13h (GPIOB), the pointer will
toggle between GPIOA and GPIOB. Note that the
Address Pointer can initially point to either address in
the register pair.

Because all read16 and write16 work on A/B pairs (that I've seen at least), even with sequential mode off, they would work and bounce between the registers. So my proposal is: turn off sequential mode (IOCON.SEQOP=1) and target the B port for all read16/write16. That way the upper byte is associated with the B port and the following lower byte is associated with the A port.

Obviously this would be a breaking change and warrants more consideration, but I think it would have the desired outcome.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant