/*
* 4x6 ICP Matrix Scanner - Blue Pill (STM32F103C8T6)
*
* Layout (electrical):
* Col: 0 1 2 3 4 5
* Row 0: T1 T2 T3 T4 T5 T6 <- top strip
* Row 1: 1 2 3 ENT -- -- <- keypad row 1
* Row 2: 4 5 6 RCL -- -- <- keypad row 2
* Row 3: 7 8 9 0 -- -- <- keypad row 3
*
* Pin map:
* Columns (OUTPUT, idle HIGH): PB0, PB1, PB10, PB11, PB8, PB9
* Rows (INPUT_PULLUP): PB12, PB13, PB14, PB15
*
* Free matrix slots (rows 1-3, cols 4-5) reserved for the 4 encoder
* push-buttons we'll add later. Until then those slots are unwired
* and will simply never trigger.
*
* Output: prints "<label> PRESSED" / "<label> released" at 115200 baud.
* Keyboard shortcuts in Wokwi: q-y for top strip, 0-9 for keypad,
* n for ENT, c for RCL.
*/
constexpr uint8_t NUM_ROWS = 4;
constexpr uint8_t NUM_COLS = 6;
const uint8_t COLS[NUM_COLS] = { PB0, PB1, PB10, PB11, PB8, PB9 };
const uint8_t ROWS[NUM_ROWS] = { PB12, PB13, PB14, PB15 };
// Empty string = unwired slot (won't print)
const char* BTN_LABEL[NUM_ROWS][NUM_COLS] = {
{ "T1", "T2", "T3", "T4", "T5", "T6" },
{ "1", "2", "3", "ENT", "", "" },
{ "4", "5", "6", "RCL", "", "" },
{ "7", "8", "9", "0", "", "" }
};
const unsigned long DEBOUNCE_MS = 10;
bool rawReading[NUM_ROWS][NUM_COLS] = {{false}};
bool stableState[NUM_ROWS][NUM_COLS] = {{false}};
unsigned long lastChangeMs[NUM_ROWS][NUM_COLS] = {{0}};
void setup() {
Serial.begin(115200);
unsigned long t0 = millis();
while (!Serial && (millis() - t0) < 2000) { /* wait for host */ }
Serial.println();
Serial.println(F("4x6 ICP matrix scanner ready."));
Serial.println(F("Top strip: q w e r t y"));
Serial.println(F("Keypad: 1-9, 0, n=ENT, c=RCL"));
Serial.println();
for (uint8_t c = 0; c < NUM_COLS; c++) {
pinMode(COLS[c], OUTPUT);
digitalWrite(COLS[c], HIGH);
}
for (uint8_t r = 0; r < NUM_ROWS; r++) {
pinMode(ROWS[r], INPUT_PULLUP);
}
}
void loop() {
for (uint8_t c = 0; c < NUM_COLS; c++) {
digitalWrite(COLS[c], LOW);
delayMicroseconds(5);
for (uint8_t r = 0; r < NUM_ROWS; r++) {
bool pressed = (digitalRead(ROWS[r]) == LOW);
if (pressed != rawReading[r][c]) {
rawReading[r][c] = pressed;
lastChangeMs[r][c] = millis();
}
if ((millis() - lastChangeMs[r][c]) >= DEBOUNCE_MS) {
if (pressed != stableState[r][c]) {
stableState[r][c] = pressed;
// Only print if this slot has a wired button (non-empty label)
if (BTN_LABEL[r][c][0] != '\0') {
Serial.print(BTN_LABEL[r][c]);
Serial.println(pressed ? F(" PRESSED") : F(" released"));
}
}
}
}
digitalWrite(COLS[c], HIGH);
}
}