#include <Wire.h>
#include <Adafruit_MCP23X17.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Adafruit_MCP23X17 mcp1;
Adafruit_MCP23X17 mcp2;
#define MASTER_PTT_PIN 17
int selectedChannel = -1;
int activeChannel = -1;
unsigned long lastBlink = 0;
bool blinkState = false;
// MCP1 @ 0x20
const int relayPins1[8] = {0,1,2,3,4,5,6,7}; // GPA0–7 -> Relais 1–8
const int ledPins1[8] = {8,9,10,11,12,13,14,15}; // GPB0–7 -> LEDs 1–8
// MCP2 @ 0x21
const int relayPins2[2] = {0,1}; // GPA0–1 -> Relais 9–10
const int ledPins2[2] = {8,9}; // GPB0–1 -> LEDs 9–10
const int buttonPins[10] = {2,3,4,5,6,7,10,11,12,13}; // Rest -> Buttons
void setup() {
Serial.begin(115200);
Wire.begin();
if (!mcp1.begin_I2C(0x20)) {
Serial.println("Fehler: MCP1 (0x20) nicht gefunden!");
while (1);
}
if (!mcp2.begin_I2C(0x21)) {
Serial.println("Fehler: MCP2 (0x21) nicht gefunden!");
while (1);
}
// MCP1: Relais + LEDs
for (int i=0; i<8; i++) {
mcp1.pinMode(relayPins1[i], OUTPUT);
mcp1.digitalWrite(relayPins1[i], LOW);
mcp1.pinMode(ledPins1[i], OUTPUT);
mcp1.digitalWrite(ledPins1[i], HIGH); // LED aus (aktiv LOW)
}
// MCP2: Relais + LEDs
for (int i=0; i<2; i++) {
mcp2.pinMode(relayPins2[i], OUTPUT);
mcp2.digitalWrite(relayPins2[i], LOW);
mcp2.pinMode(ledPins2[i], OUTPUT);
mcp2.digitalWrite(ledPins2[i], HIGH);
}
// Buttons als Eingang
for (int i=0; i<10; i++) {
mcp2.pinMode(buttonPins[i], INPUT_PULLUP);
}
pinMode(MASTER_PTT_PIN, INPUT_PULLUP);
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 nicht gefunden!"));
for(;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("System bereit");
display.display();
}
void setRelay(int channel, bool state) {
if (channel < 0) return;
if (channel < 8)
mcp1.digitalWrite(relayPins1[channel], state ? HIGH : LOW);
else
mcp2.digitalWrite(relayPins2[channel-8], state ? HIGH : LOW);
}
void setLED(int channel, bool state) {
if (channel < 0) return;
if (channel < 8)
mcp1.digitalWrite(ledPins1[channel], state ? (LOW) : (HIGH)); // aktiv LOW
else
mcp2.digitalWrite(ledPins2[channel-8], state ? (LOW) : (HIGH));
}
bool readButton(int channel) {
if (channel < 0 || channel >= 10) return false;
return (mcp2.digitalRead(buttonPins[channel]) == LOW);
}
void updateDisplay() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// 1. Zeile Status
display.setTextSize(2);
display.setCursor(0,0);
if (activeChannel >= 0) display.print("SENDE");
else if (selectedChannel >= 0) display.print("VORWAHL");
else display.print("BEREIT");
// 2. Zeile Kanalnummer
display.setTextSize(3);
display.setCursor(0,28);
if (activeChannel >= 0)
display.printf("CH %d", activeChannel+1);
else if (selectedChannel >= 0)
display.printf("CH %d", selectedChannel+1);
else
display.print("--");
display.display();
}
void loop() {
// --- Buttons ---
for (int i=0; i<10; i++) {
if (readButton(i)) {
selectedChannel = i;
Serial.printf("Vorwahl: Kanal %d\n", i+1);
updateDisplay();
delay(200);
}
}
// --- Blinken ---
if (millis() - lastBlink > 500) {
blinkState = !blinkState;
lastBlink = millis();
}
// --- LEDs ---
for (int i=0; i<10; i++) setLED(i, false);
if (selectedChannel >= 0 && activeChannel < 0)
setLED(selectedChannel, blinkState);
// --- PTT ---
if (digitalRead(MASTER_PTT_PIN) == LOW) {
if (selectedChannel >= 0) {
if (activeChannel != selectedChannel) {
for (int i=0; i<10; i++) setRelay(i, false);
activeChannel = selectedChannel;
setRelay(activeChannel, true);
Serial.print("Sende Kanal: ");
Serial.println(activeChannel+1);
updateDisplay();
}
setLED(activeChannel, true);
}
} else {
if (activeChannel >= 0) {
setRelay(activeChannel, false);
activeChannel = -1;
updateDisplay();
}
}
}