Files
RetroCallBLE/new.cpp
T

163 lines
5.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <Arduino.h>
#include <BleKeyboard.h>
// --- Pin-Definitionen ---
#define PIN_HOOK 18 // GRÜN: HIGH = Hörer abgehoben, LOW = aufgelegt
#define PIN_DIAL 19 // WEISS: HIGH bei Drehung, fallende Flanken = Impulse
// --- Hardware & Timing-Konstanten ---
#define DEBOUNCE_MS 30 // Entprellzeit für Impulse (ms)
#define DIGIT_TIMEOUT_MS 350 // Pause nach Drehung, bis Ziffer erkannt ist (ms)
#define COMPLETE_DIAL_TIMEOUT 2500 // Pause nach letzter Ziffer, bis Rufnummer komplett ist (ms)
// --- BLE Keyboard Instanz ---
BleKeyboard bleKeyboard("FeTAp 791 Telefon", "Deutsche Bundespost", 100);
// --- Interrupt-Variablen (müssen volatile sein!) ---
volatile int pulseCount = 0;
volatile unsigned long lastPulseTime = 0;
volatile bool isDialing = false;
// --- Hauptprogramm-Variablen ---
bool bleConnectedLastState = false;
bool hookLastState = false;
String dialedNumber = "";
unsigned long lastDigitCompletedTime = 0;
bool waitingForCompleteNumber = false;
// -------------------------------------------------------------------
// Interrupt Service Routine (ISR) für die fallende Flanke
// -------------------------------------------------------------------
// 'IRAM_ATTR' sorgt dafür, dass dieser Code im schnellen RAM des ESP32 liegt
void IRAM_ATTR handleDialPulse() {
unsigned long currentMillis = millis();
// Entprellung direkt im Interrupt:
// Nur zählen, wenn der letzte Impuls länger als DEBOUNCE_MS her ist
if ((currentMillis - lastPulseTime) > DEBOUNCE_MS) {
pulseCount++;
isDialing = true;
lastPulseTime = currentMillis;
}
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=========================================");
Serial.println("FeTAp 791 - ESP32 mit Hardware-Interrupt");
Serial.println("=========================================");
pinMode(PIN_HOOK, INPUT_PULLDOWN);
pinMode(PIN_DIAL, INPUT_PULLDOWN);
// --- Hardware-Interrupt konfigurieren ---
// Löst 'handleDialPulse()' EXAKT beim Übergang von HIGH nach LOW aus!
attachInterrupt(digitalPinToInterrupt(PIN_DIAL), handleDialPulse, FALLING);
bleKeyboard.begin();
Serial.println("[BLE] Warte auf Verbindung zum iPhone...");
}
void triggerIphoneShortcut(String number) {
if (!bleKeyboard.isConnected()) {
Serial.println("[BLE] Nicht verbunden – Kurzbefehl kann nicht gesendet werden!");
return;
}
Serial.printf("[Kurzbefehl] Starte Aktion für Rufnummer: %s\n", number.c_str());
// Nummer eintippen und mit 'Enter' bestätigen
bleKeyboard.print(number);
delay(100);
bleKeyboard.write(KEY_RETURN);
}
void processDialedDigit(int pulses) {
char digitChar;
if (pulses == 10) {
digitChar = '0';
} else if (pulses >= 1 && pulses <= 9) {
digitChar = '0' + pulses;
} else {
Serial.printf("[Wahl] Ungültige Impulsanzahl (%d) ignoriert.\n", pulses);
return;
}
dialedNumber += digitChar;
lastDigitCompletedTime = millis();
waitingForCompleteNumber = true;
Serial.printf("[Wahl] Ziffer: %c | Aktuelle Nummer: %s\n", digitChar, dialedNumber.c_str());
}
void loop() {
unsigned long currentMillis = millis();
// 1. Bluetooth-Verbindungsstatus
bool isConnectedNow = bleKeyboard.isConnected();
if (isConnectedNow && !bleConnectedLastState) {
Serial.println("\n[BLE] >>> iPhone erfolgreich VERBUNDEN! <<<");
bleConnectedLastState = true;
} else if (!isConnectedNow && bleConnectedLastState) {
Serial.println("\n[BLE] >>> Verbindung zum iPhone VERLOREN! <<<");
bleConnectedLastState = false;
}
// 2. Gabelumschalter (Hook)
bool currentHookState = digitalRead(PIN_HOOK);
if (currentHookState != hookLastState) {
delay(20); // Entprellen der Gabel
currentHookState = digitalRead(PIN_HOOK);
if (currentHookState != hookLastState) {
hookLastState = currentHookState;
if (currentHookState == HIGH) {
Serial.println("\n[Hörer] ABGEHOBEN");
dialedNumber = "";
waitingForCompleteNumber = false;
// Interrupt aktivieren / Zähler nullen
pulseCount = 0;
isDialing = false;
} else {
Serial.println("\n[Hörer] AUFGELEGT");
dialedNumber = "";
waitingForCompleteNumber = false;
pulseCount = 0;
isDialing = false;
}
}
}
// 3. Auswertung der Ziffern & Rufnummer (nur bei abgehobenem Hörer)
if (hookLastState == HIGH) {
// A) Ist die Ziffern-Drehung beendet? (Timeout seit letztem Interrupt-Impuls)
if (isDialing && (currentMillis - lastPulseTime > DIGIT_TIMEOUT_MS)) {
// Für die sichere Übergabe aus der ISR kurz Interrupts pausieren oder Wert kopieren
noInterrupts();
int currentPulses = pulseCount;
pulseCount = 0;
isDialing = false;
interrupts();
if (currentPulses > 0) {
processDialedDigit(currentPulses);
}
}
// B) Ist die komplette Rufnummer fertig gewählt? (Pause nach letzter Ziffer)
if (waitingForCompleteNumber && (currentMillis - lastDigitCompletedTime > COMPLETE_DIAL_TIMEOUT)) {
waitingForCompleteNumber = false;
Serial.printf("\n[Wahl abgeschlossen] Vollständige Nummer: %s\n", dialedNumber.c_str());
// Kurzbefehl am iPhone ausführen
triggerIphoneShortcut(dialedNumber);
}
}
}