#include <Keypad.h>
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] =
{
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
uint8_t colPins[COLS] = { 44, 42, 40, 38 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 52, 50, 48, 46 }; // Pins connected to R1, R2, R3, R4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
const byte hookPinA = 23; // your interrupt pin
const byte interruptPin = 22; // your interrupt pin
const byte column4InterruptPin = 2; // Column 4 interrupt pin connected to column4Pin via a wire link. Could add a 1K series resistor to protect against short circuit to ground if it were output low when pin 38 is output high.
const byte column4Pin = 38; // Column 4 pin connected to column4InterruptPin via a wire link.
// States updated by ISR.
volatile byte isr_hookOffState = 0;
volatile byte isr_interruptState = 0;
volatile bool isr_column4Pressed = false;
// Working copies of ISR data.
byte hookOffState = 0;
byte interruptState = 0;
bool column4Pressed = false;
// Use a single byte for the state variable and initialise it to OFF.
enum class State : byte
{
OFF = 0,
IDLE = 1,
LISTEN_KEY = 2,
PLAYER = 3
} state = State::OFF;
void setup()
{
Serial.begin(115200);
pinMode(hookPinA, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); // test interrupt with a regular button
pinMode(column4InterruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(column4InterruptPin), interruptColumn4, FALLING); // Triggered by pulling column 4 low, e.g. digitalWrite(column4Pin, LOW) or within myKeypad.getKey().
}
void loop()
{
const char key = keypad.getKey();
if (key != NO_KEY)
{
Serial.println(key);
}
// Get a fresh copy of the ISR data and reset the interrupt state flag atomically
// by temporarily disabling interrupts.
cli();
hookOffState = isr_hookOffState;
interruptState = isr_interruptState;
column4Pressed = isr_column4Pressed;
isr_interruptState = 0; // Reset to detect next interrupt.
isr_column4Pressed = false; // Reset to detect next interrupt.
sei();
// Non-interrupt alternative method to test whether any button in column 4 is pressed.
/*
pinMode(column4Pin, OUTPUT);
digitalWrite(column4Pin, LOW);
column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
digitalWrite(column4Pin, HIGH);
pinMode(column4Pin, INPUT);
*/
// Debug prints.
//Serial.println(column4Pressed);
if (column4Pressed)
{
Serial.println("Column 4 is pressed.");
}
// Process the working copies of the ISR data.
// You will need to change the state machine logic to process column4Pressed obtained from the ISR or the alternative method.
switch (state)
{
case State::OFF:
break;
case State::IDLE:
break;
case State::LISTEN_KEY:
break;
case State::PLAYER:
break;
}
}
void hookOffToggle()
{
isr_hookOffState = digitalRead(hookPinA);
}
void interruptToggle()
{
isr_interruptState = 1;
}
void interruptColumn4()
{
// Test whether any button in column 4 is pressed.
isr_column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
}