No takers…
OK, I found a solution on my own. I’ll detail it here (such as it is) as it may be useful for those in similar predicament.
I downloaded the MENWIZ from GitHub - brunialti/MENWIZ: ARDUINO LCD menu library: short user code to manage complex menu structures. All libraries used are included. As a test bed, I used the quick_tour.ino from the \examples folder.
Here is what I did:
- redefine the pins for navigation buttons (in range 0 …7)
// DEFINE PORT EXPANDER PINS FOR NAVIGATION BUTTONS
#define UP_BUTTON_PIN 1 // was 9
#define DOWN_BUTTON_PIN 2 // was 10
#define LEFT_BUTTON_PIN 4 // was 7
#define RIGHT_BUTTON_PIN 5 // was 8
#define CONFIRM_BUTTON_PIN 6 // was 12
#define ESCAPE_BUTTON_PIN 7 // was 11
- Create and initialize port expander object (here ‘remIO’) using I2CIO library
// create port expander obj using I2CIO lib
I2CIO remIO;
byte IOaddr = 0x26; // port expander's hardware I2C address
byte portIn = 0; // port expander's inputs
void setup(){
remIO.begin(IOaddr); // initialize remIO port expander at IOaddr
remIO.portMode(INPUT); // set all pins as inputs
- Read the port expander data continuously
void loop(){
portIn = remIO.read(); // scan port expander continuously
- Modify the (MENWIZ class) ‘navButtons’ method by adding the pointer to port expander’s data as argument (here the ‘portIn’ byte)
In quick_tour.ino (original code commented out) :
// tree.navButtons(UP_BUTTON_PIN,DOWN_BUTTON_PIN,LEFT_BUTTON_PIN,RIGHT_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);
tree.navButtons(&portIn,UP_BUTTON_PIN,DOWN_BUTTON_PIN,LEFT_BUTTON_PIN,RIGHT_BUTTON_PIN,ESCAPE_BUTTON_PIN,CONFIRM_BUTTON_PIN);
In MENWIZ.h :
void navButtons(byte*,int,int,int,int,int,int); // was navButtons(int,int,int,int,int,int);
void navButtons(byte*,int,int,int,int); // was navButtons(int,int,int,int);
In MENWIZ.cpp :
void menwiz::navButtons(byte*IO,int btu,int btd,int bte,int btc){
and:
void menwiz::navButtons(byte*IO,int btu,int btd,int btl,int btr,int bte,int btc){
- While you are in MENWIZ.cpp, add (actually copy) pointer to buttons ‘assign’ method calls (calls are from within ‘navButtons’ methods) as well as delete calls to ‘turnOnPullUp’ method (not needed as 8574 has always active built-in pullups) :
/*
if(btu!=0){btx->BTU.assign(btu); btx->BTU.setMode(OneShot); btx->BTU.turnOnPullUp();}
if(btd!=0){btx->BTD.assign(btd); btx->BTD.setMode(OneShot); btx->BTD.turnOnPullUp();}
if(bte!=0){btx->BTE.assign(bte); btx->BTE.setMode(OneShot); btx->BTE.turnOnPullUp();}
if(btc!=0){btx->BTC.assign(btc); btx->BTC.setMode(OneShot); btx->BTC.turnOnPullUp();}
*/
if(btu!=0){btx->BTU.assign(IO, btu); btx->BTU.setMode(OneShot);}
if(btd!=0){btx->BTD.assign(IO, btd); btx->BTD.setMode(OneShot);}
if(bte!=0){btx->BTE.assign(IO, bte); btx->BTE.setMode(OneShot);}
if(btc!=0){btx->BTC.assign(IO, btc); btx->BTC.setMode(OneShot);}
as well as
/*
if(btu!=0){btx->BTU.assign(btu); btx->BTU.setMode(OneShot); btx->BTU.turnOnPullUp();}
if(btd!=0){btx->BTD.assign( btd); btx->BTD.setMode(OneShot); btx->BTD.turnOnPullUp();}
if(btl!=0){btx->BTL.assign( btl); btx->BTL.setMode(OneShot); btx->BTL.turnOnPullUp();}
if(btr!=0){btx->BTR.assign(btr); btx->BTR.setMode(OneShot); btx->BTR.turnOnPullUp();}
if(bte!=0){btx->BTE.assign(bte); btx->BTE.setMode(OneShot); btx->BTE.turnOnPullUp();}
if(btc!=0){btx->BTC.assign(btc); btx->BTC.setMode(OneShot); btx->BTC.turnOnPullUp();}
*/
if(btu!=0){btx->BTU.assign(IO, btu); btx->BTU.setMode(OneShot);}
if(btd!=0){btx->BTD.assign(IO, btd); btx->BTD.setMode(OneShot);}
if(btl!=0){btx->BTL.assign(IO, btl); btx->BTL.setMode(OneShot);}
if(btr!=0){btx->BTR.assign(IO, btr); btx->BTR.setMode(OneShot);}
if(bte!=0){btx->BTE.assign(IO, bte); btx->BTE.setMode(OneShot);}
if(btc!=0){btx->BTC.assign(IO, btc); btx->BTC.setMode(OneShot);}
- Add pointer argument to Button class ‘assign’ method:
In buttons.h :
// void assign(byte pin);
void assign(byte*, byte pin);
as well as declare pointer variable in ‘private’ section:
byte *_io; // add place to hold pointer
and while you are there comment out pull up methods (optional):
// void turnOnPullUp(); - not needed for port expander
// void turnOffPullUp(); - not needed for port expander
In buttons.cpp initialize pointer in constructors:
Button::Button() {
previous = false;
mode = OneShot;
hold_timer = millis();
refresh_timer = millis();
hold_level = 1000; // 1 second
hold_refresh = 100; // 100 ms
pin = 0;
_io = NULL; // pointer to port expander data
}
Button::Button(byte mode_v) {
previous = false;
mode = mode_v;
hold_timer = millis();
refresh_timer = millis();
hold_level = 1000;
hold_refresh = 100;
pin = 0;
_io = NULL; // pointer to port expander data
}
add pointer argument to assign method and comment out ‘pinMode’ (and pull up methods)
void Button::assign(byte*IO, byte pin_v) {
pin = pin_v;
_io = IO; // save pointer to data (read from port expander in the main sketch)
// pinMode(pin, INPUT); this is now handled by 'remIO.portMode(INPUT);' in the main sketch
}
// void Button::turnOnPullUp() { if (pin) digitalWrite(pin, HIGH); }
// void Button::turnOffPullUp() { if (pin) digitalWrite(pin, LOW); }
- and finally, use the buttons attached to port expander pins:
In buttons.cpp
byte Button::check() {
// if (digitalRead(pin)) - replaced by 'if (*_io & (1 << pin))' below
if (*_io & (1 << pin)) {
switch (mode) {
If somebody has a better or cleaner way, please let me know