/*
* F-16 ICP — Final Schematic Firmware
* Blue Pill (STM32F103C8T6) | stm32duino core
*
* Inputs:
* - 5x6 button matrix (26 buttons populated, 4 spare slots)
* - 2 rotary encoders (rotation only, no push function)
*
* Matrix 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 + 2 spares)
* Row 2: 4 5 6 RCL SP+ SP- (keypad row 2 + steerpoint)
* Row 3: 7 8 9 0 TGL+ TGL- (keypad row 3 + 3-pos toggle)
* Row 4: DCS_U DCS_D DCS_L DCS_R -- -- (DCS hat + 2 spares)
*
* Pin map:
* Cols (OUTPUT, idle HIGH): PB0, PB1, PB10, PB11, PB8, PB9
* Rows (INPUT_PULLUP): PB12, PB13, PB14, PB15, PB5
* Encoder 1 (CLK, DT): PA0, PA1
* Encoder 2 (CLK, DT): PA2, PA3
*/
// ============ Matrix ============
constexpr uint8_t NUM_ROWS = 5;
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, PB5 };
const char* BTN_LABEL[NUM_ROWS][NUM_COLS] = {
{ "T1", "T2", "T3", "T4", "T5", "T6" },
{ "1", "2", "3", "ENT", "", "" },
{ "4", "5", "6", "RCL", "SP+", "SP-" },
{ "7", "8", "9", "0", "TGL+", "TGL-" },
{ "DCS_U", "DCS_D", "DCS_L", "DCS_R", "", "" }
};
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}};
// ============ Encoders ============
struct Encoder {
uint8_t clkPin;
uint8_t dtPin;
const char* name;
int lastClk;
long count;
};
Encoder enc1 = { PA0, PA1, "ENC1", HIGH, 0 };
Encoder enc2 = { PA2, PA3, "ENC2", HIGH, 0 };
void readEncoder(Encoder& e) {
int clkNow = digitalRead(e.clkPin);
if (clkNow != e.lastClk) {
e.lastClk = clkNow;
if (clkNow == LOW) {
int dtNow = digitalRead(e.dtPin);
if (dtNow == HIGH) {
e.count++;
Serial.print(e.name); Serial.print(F(" CW count=")); Serial.println(e.count);
} else {
e.count--;
Serial.print(e.name); Serial.print(F(" CCW count=")); Serial.println(e.count);
}
}
}
}
// ============ Setup / Loop ============
void setup() {
Serial.begin(115200);
unsigned long t0 = millis();
while (!Serial && (millis() - t0) < 2000) { /* wait for host */ }
Serial.println();
Serial.println(F("=== F-16 ICP firmware ready ==="));
Serial.println(F("Top: q w e r t y"));
Serial.println(F("Keypad: 1-9 0 ENT=n RCL=c"));
Serial.println(F("Side: i k (SP up/dn) | o l (TGL up/dn)"));
Serial.println(F("DCS: arrow keys"));
Serial.println(F("Encs: click KY-040 arrows"));
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);
}
pinMode(enc1.clkPin, INPUT_PULLUP);
pinMode(enc1.dtPin, INPUT_PULLUP);
pinMode(enc2.clkPin, INPUT_PULLUP);
pinMode(enc2.dtPin, INPUT_PULLUP);
}
void scanMatrix() {
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;
if (BTN_LABEL[r][c][0] != '\0') {
Serial.print(BTN_LABEL[r][c]);
Serial.println(pressed ? F(" PRESSED") : F(" released"));
}
}
}
}
digitalWrite(COLS[c], HIGH);
}
}
void loop() {
scanMatrix();
readEncoder(enc1);
readEncoder(enc2);
}