Add ESP32-S3 + AG1171S project plan and firmware skeleton
This commit is contained in:
@@ -1,2 +1,21 @@
|
|||||||
# RTC_BL_PHONE
|
# RTC_BL_PHONE
|
||||||
esp32 bluetooth audio to rtc phone
|
|
||||||
|
Projet PlatformIO ESP32 pour recycler un téléphone RTC ancien (combiné, clavier, hook).
|
||||||
|
|
||||||
|
## Démarrage rapide
|
||||||
|
1. Ouvrir le dossier dans PlatformIO.
|
||||||
|
2. Compiler et flasher l'environnement `esp32-s3-devkitc-1` (par défaut).
|
||||||
|
3. Ouvrir le moniteur série à 115200 bauds.
|
||||||
|
4. Utiliser les commandes série (`h`, `r`, `o`, `d`, `c`) pour piloter la machine d'états.
|
||||||
|
|
||||||
|
## Choix de cartes ESP32
|
||||||
|
Voir `docs/solutions_rtc_phone_esp32.md` pour la shortlist des DevKit utilisables (ESP32-DevKitC, ESP32-S3-DevKitC-1, NodeMCU-32S, LOLIN32), les liens de référence web, et les solutions d’interface (direct combiné/clavier, SLIC/FXS, ATA externe), dont une variante AG1171S (Silvertel).
|
||||||
|
|
||||||
|
## Plan projet (chef de projet)
|
||||||
|
Voir `docs/plan_chef_projet_esp32s3_ag1171s.md` pour le planning en phases, les risques, les critères d'acceptation et les livrables de la version ESP32-S3 + AG1171S.
|
||||||
|
|
||||||
|
## Contenu
|
||||||
|
- `platformio.ini`: configuration multi-env (ESP32-S3 par défaut + ESP32 legacy).
|
||||||
|
- `src/main.cpp`: squelette firmware machine d'états pour intégration AG1171S.
|
||||||
|
- `docs/solutions_rtc_phone_esp32.md`: comparaison des architectures et recommandations.
|
||||||
|
- `docs/plan_chef_projet_esp32s3_ag1171s.md`: plan d'exécution projet version V0.1.
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Plan chef de projet — ESP32-S3 + AG1171S (Silvertel)
|
||||||
|
|
||||||
|
## 1) Objectif projet
|
||||||
|
Livrer un prototype fonctionnel "téléphone analogique ancien" piloté par ESP32-S3, avec interface 2 fils privée via AG1171S, sans connexion PSTN publique.
|
||||||
|
|
||||||
|
## 2) Périmètre (version V0.1)
|
||||||
|
- Détection hook (on/off hook).
|
||||||
|
- Commande d'activation ligne (line enable).
|
||||||
|
- Commande de sonnerie (ring command/cadence côté analogique).
|
||||||
|
- Journal série + machine d'états téléphonie basique.
|
||||||
|
- Cible matérielle principale: **ESP32-S3-DevKitC-1**.
|
||||||
|
|
||||||
|
## 3) Planning macro
|
||||||
|
### Phase A — Cadrage & schéma (Semaine 1)
|
||||||
|
- Valider broches AG1171S retenues (hook detect, ring control, line feed control).
|
||||||
|
- Produire schéma de câblage V0.1 (alims, masses, protections, découplage).
|
||||||
|
- Sortie: checklist sécurité + BOM V0.1.
|
||||||
|
|
||||||
|
### Phase B — Firmware fondation (Semaine 2)
|
||||||
|
- Mettre en place environnement PlatformIO `esp32-s3-devkitc-1`.
|
||||||
|
- Implémenter machine d'états: `ON_HOOK`, `OFF_HOOK`, `DIALING`, `IN_CALL`, `RINGING`.
|
||||||
|
- Ajouter commandes série pour tests rapides (`r/o/d/c`).
|
||||||
|
- Sortie: build firmware de base + logs validés.
|
||||||
|
|
||||||
|
### Phase C — Intégration hardware (Semaine 3)
|
||||||
|
- Câblage réel ESP32-S3 ↔ AG1171S.
|
||||||
|
- Test de robustesse hook (anti-rebond + stabilité).
|
||||||
|
- Test commande ring/line sans charge puis avec téléphone analogique.
|
||||||
|
- Sortie: matrice de tests V0.1 avec résultats.
|
||||||
|
|
||||||
|
### Phase D — Validation système (Semaine 4)
|
||||||
|
- Campagne tests end-to-end: raccroché/décroché, sonnerie, transitions d'état.
|
||||||
|
- Vérifier alimentation et thermique.
|
||||||
|
- Corriger pinout/temporisations selon résultats.
|
||||||
|
- Sortie: release candidate V0.1.
|
||||||
|
|
||||||
|
## 4) Risques & mitigation
|
||||||
|
- **Risque analogique (niveaux/impédance):** prévoir test progressif et instrumentation (oscillo, multimètre).
|
||||||
|
- **Risque sécurité téléphonie:** rester hors PSTN publique tant que conformité non traitée.
|
||||||
|
- **Risque planning:** découper firmware et hardware en jalons testables hebdomadaires.
|
||||||
|
|
||||||
|
## 5) Critères d'acceptation V0.1
|
||||||
|
- Boot stable sur ESP32-S3.
|
||||||
|
- Hook detect stable (> 100 transitions sans faux positif en test de banc).
|
||||||
|
- Commande `RINGING` active le signal de commande attendu.
|
||||||
|
- Retour `ON_HOOK` coupe ligne et ring command.
|
||||||
|
|
||||||
|
## 6) Suite (V0.2+)
|
||||||
|
- Ajout décodage numérotation (DTMF/pulse).
|
||||||
|
- Ajout audio (codec I2S) et scénarios d'appel avancés.
|
||||||
|
- Option passerelle SIP locale.
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
# Solutions recommandées: ESP32 + téléphone RTC ancien
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
Créer un projet PlatformIO sur ESP32 pour réutiliser un ancien téléphone analogique RTC (combiné, clavier, crochet) avec une architecture moderne.
|
||||||
|
|
||||||
|
## Contraintes importantes
|
||||||
|
- **Ne jamais connecter directement** l'ESP32 à une ligne téléphonique publique (PSTN) sans isolation/éléments homologués.
|
||||||
|
- Les tensions de sonnerie peuvent être élevées; prévoir isolation galvanique si interface ligne 2 fils.
|
||||||
|
- La qualité audio dépend fortement du front-end analogique (adaptation d'impédance, gain, anti-larsen).
|
||||||
|
|
||||||
|
## Option A — Réutiliser uniquement le combiné + clavier (recommandé MVP)
|
||||||
|
### Principe
|
||||||
|
- Débrancher l'électronique ligne d'origine.
|
||||||
|
- Lire en hard:
|
||||||
|
- hook switch (décroché/raccroché)
|
||||||
|
- clavier (matrice)
|
||||||
|
- Audio:
|
||||||
|
- micro du combiné vers préampli + ADC/codec I2S
|
||||||
|
- écouteur via DAC/codec + ampli
|
||||||
|
|
||||||
|
### Avantages
|
||||||
|
- La plus simple pour un premier prototype.
|
||||||
|
- Sécurité électrique plus facile à maîtriser.
|
||||||
|
- Excellente maîtrise logicielle côté ESP32 (Bluetooth, Wi-Fi, SIP, intercom local).
|
||||||
|
|
||||||
|
### Inconvénients
|
||||||
|
- Nécessite un peu d'analogique audio (préamp, filtre, gain).
|
||||||
|
- Le clavier ancien peut demander reverse engineering.
|
||||||
|
|
||||||
|
## Option B — Interface 2 fils complète type "ligne RTC privée" (SLIC/DAA)
|
||||||
|
### Principe
|
||||||
|
- Conserver le téléphone quasiment tel quel (port RJ11/2 fils).
|
||||||
|
- Générer alimentation de boucle, tonalité, éventuellement sonnerie via circuit spécialisé (SLIC).
|
||||||
|
|
||||||
|
### Avantages
|
||||||
|
- Expérience "téléphone d'origine" la plus fidèle.
|
||||||
|
- Compatible avec plusieurs postes analogiques.
|
||||||
|
|
||||||
|
### Inconvénients
|
||||||
|
- Plus complexe et coûteux.
|
||||||
|
- Design analogique + sécurité plus exigeants.
|
||||||
|
- Debug plus long.
|
||||||
|
|
||||||
|
### Variante concrète: module **Silvertel AG1171S**
|
||||||
|
Si tu veux garder un ancien téléphone tel quel (2 fils TIP/RING) avec une carte ESP32, l'AG1171S est une piste concrète côté **FXS/SLIC**.
|
||||||
|
|
||||||
|
#### Ce que ça apporte
|
||||||
|
- Génération de la boucle analogique pour alimenter un poste RTC ancien.
|
||||||
|
- Interface pensée pour créer une "ligne privée" locale (pas une connexion directe PSTN brute).
|
||||||
|
- Réduction de la complexité analogique par rapport à un design SLIC discret from-scratch.
|
||||||
|
|
||||||
|
#### Comment l'intégrer proprement avec ESP32
|
||||||
|
1. **AG1171S = étage ligne analogique** (alimentation de boucle, interface 2 fils).
|
||||||
|
2. **ESP32 = logique et signalisation** (états off-hook/on-hook, numérotation, scénarios).
|
||||||
|
3. **Chemin audio**:
|
||||||
|
- soit via codec audio externe (I2S) + adaptation vers l'étage ligne,
|
||||||
|
- soit via une architecture où l'audio analogique reste majoritairement côté téléphonie, et l'ESP32 pilote surtout la logique.
|
||||||
|
4. **Détection d'événements**: exposer vers GPIO les états utiles (hook, ring detect selon schéma d'application).
|
||||||
|
|
||||||
|
#### Points d'attention (importants)
|
||||||
|
- Respecter strictement les notes d'application Silvertel (DC feed, protection, découplage, routage).
|
||||||
|
- Ne pas connecter à une ligne publique sans conformité réglementaire et schéma adapté.
|
||||||
|
- Prévoir protections (surintensité/surtension) et isolation selon l'usage final.
|
||||||
|
- Valider impédance et niveau audio pour éviter faible volume, saturation, écho/larsen.
|
||||||
|
|
||||||
|
#### Recommandation projet
|
||||||
|
- **MVP rapide**: continuer Option A (combiné + clavier en hard) pour avancer sur firmware.
|
||||||
|
- **Version "vraie ligne 2 fils"**: passer en Option B avec AG1171S quand la logique applicative est stable.
|
||||||
|
|
||||||
|
|
||||||
|
### Proposition de mapping initial (ESP32-S3-DevKitC-1)
|
||||||
|
- `GPIO4` : Hook sense (entrée, `INPUT_PULLUP`, actif bas selon câblage).
|
||||||
|
- `GPIO5` : Ring command (sortie logique vers étage de commande sonnerie).
|
||||||
|
- `GPIO6` : Line enable (sortie logique vers activation ligne AG1171S).
|
||||||
|
- `GPIO48`: LED debug état firmware.
|
||||||
|
|
||||||
|
> Ce mapping est un **point de départ firmware** et doit être validé/ajusté selon le schéma AG1171S final.
|
||||||
|
|
||||||
|
## Option C — Passerelle hybride (ATA/FXS externe + ESP32 contrôle)
|
||||||
|
### Principe
|
||||||
|
- L'audio et la boucle téléphonique sont gérés par un matériel externe (ATA/box FXS).
|
||||||
|
- ESP32 gère logique applicative (boutons, scénario d'appel, domotique, BLE/Wi-Fi).
|
||||||
|
|
||||||
|
### Avantages
|
||||||
|
- Déploiement rapide avec qualité voix stable.
|
||||||
|
- Risque analogique réduit.
|
||||||
|
|
||||||
|
### Inconvénients
|
||||||
|
- Dépendance à un boîtier externe.
|
||||||
|
- Moins "DIY full stack".
|
||||||
|
|
||||||
|
## Dev kits ESP32 utilisables (vérifiés web)
|
||||||
|
> Recherche croisée faite sur la doc officielle Espressif (`esp-dev-kits`) et la liste des cartes PlatformIO (`espressif32`).
|
||||||
|
|
||||||
|
### Recommandés pour TON projet (RTC + combiné + clavier + audio)
|
||||||
|
1. **ESP32-DevKitC (WROOM-32)**
|
||||||
|
- Très compatible avec exemples existants.
|
||||||
|
- Wi-Fi + Bluetooth Classic/BLE utile si tu vises audio BT/HFP plus tard.
|
||||||
|
- Mapping PlatformIO simple: `board = esp32dev`.
|
||||||
|
|
||||||
|
2. **ESP32-S3-DevKitC-1**
|
||||||
|
- Plus récent, bon support I/O et USB natif.
|
||||||
|
- Très bon choix pour version long terme (UI, USB CDC, plus de marge CPU/RAM selon variantes).
|
||||||
|
- Mapping PlatformIO: `board = esp32-s3-devkitc-1`.
|
||||||
|
|
||||||
|
3. **NodeMCU-32S / LOLIN32**
|
||||||
|
- Faciles à trouver et souvent moins chers.
|
||||||
|
- Bons pour prototypage hook + clavier + logique de numérotation.
|
||||||
|
- Mapping PlatformIO: `board = nodemcu-32s` ou `board = lolin32`.
|
||||||
|
|
||||||
|
### Utilisables mais moins adaptés à ton besoin immédiat
|
||||||
|
- **ESP32-C3-DevKitC-02**
|
||||||
|
- Très bien pour projets IoT BLE/Wi-Fi.
|
||||||
|
- Mais pas de Bluetooth Classic, donc moins idéal si objectif audio BT "téléphone" avancé.
|
||||||
|
|
||||||
|
## Recommandation pratique
|
||||||
|
1. **Phase 1 (MVP): Option A + ESP32-DevKitC**
|
||||||
|
- Hook + clavier + audio local simple.
|
||||||
|
- Validation UX (décroché, composition, feedback audio).
|
||||||
|
2. **Phase 2:** ajout Bluetooth/Wi-Fi (SIP/WebRTC passerelle).
|
||||||
|
3. **Phase 3:** si besoin d'un vrai port 2 fils: migration vers Option B.
|
||||||
|
|
||||||
|
## Matériel conseillé (MVP)
|
||||||
|
- ESP32-WROOM / ESP32-S3.
|
||||||
|
- Codec audio I2S simple (ou carte audio ESP32 dédiée).
|
||||||
|
- Petit ampli casque/écouteur + préampli micro électret/carbone selon combiné.
|
||||||
|
- Optocoupleur ou transistors pour lecture fiable hook/clavier si tensions atypiques.
|
||||||
|
- Alimentation propre 5V + 3.3V, masse analogique soignée.
|
||||||
|
|
||||||
|
## Notes logiciel PlatformIO
|
||||||
|
- Démarrer avec un squelette Arduino + machine d'états:
|
||||||
|
- `IDLE` (raccroché)
|
||||||
|
- `OFF_HOOK`
|
||||||
|
- `DIALING`
|
||||||
|
- `IN_CALL`
|
||||||
|
- Ajouter journal série détaillé dès le début.
|
||||||
|
- Écrire des tests de mapping clavier (table de correspondance).
|
||||||
|
|
||||||
|
|
||||||
|
## Solutions existantes pour interfacer un ancien téléphone à un microcontrôleur
|
||||||
|
|
||||||
|
Oui, il existe plusieurs familles de solutions déjà utilisées en pratique:
|
||||||
|
|
||||||
|
1. **Interface combiné “en direct” (hook + clavier + audio séparé)**
|
||||||
|
- Tu n’utilises pas la ligne RJ11 d’origine: tu récupères seulement le crochet, le clavier, le micro et l’écouteur.
|
||||||
|
- C’est la méthode la plus simple pour ESP32 et la plus sûre pour un prototype.
|
||||||
|
- Très bien pour interphone, SIP local, Bluetooth, domotique vocale.
|
||||||
|
|
||||||
|
2. **Interface FXS/SLIC (émuler une vraie ligne analogique privée)**
|
||||||
|
- Le microcontrôleur pilote un front-end téléphonique spécialisé qui fournit tension de ligne, courant de boucle et sonnerie.
|
||||||
|
- C’est la solution “propre téléphonie” si tu veux brancher un poste analogique sur 2 fils comme à l’époque.
|
||||||
|
- Plus complexe en électronique et en sécurité CEM/isolement.
|
||||||
|
|
||||||
|
3. **Interface FXO/DAA (recevoir ou analyser une ligne analogique existante)**
|
||||||
|
- Utilisée quand on veut interfacer une ligne analogique côté “réseau”.
|
||||||
|
- Demande encore plus de prudence réglementaire/sécurité selon le pays.
|
||||||
|
|
||||||
|
4. **Passerelle ATA externe (FXS déjà intégrée)**
|
||||||
|
- Exemple courant: un ATA SIP/FXS fait tout le travail téléphonique analogique.
|
||||||
|
- L’ESP32 ne gère que la logique (capteurs, scénarios, UI, automation).
|
||||||
|
- Super choix pour aller vite avec une bonne qualité audio.
|
||||||
|
|
||||||
|
5. **Décodage DTMF / cadran impulsionnel dédié**
|
||||||
|
- Si ton téléphone est à cadran ou clavier ancien, tu peux ajouter un étage dédié:
|
||||||
|
- décodage DTMF matériel,
|
||||||
|
- ou capture d’impulsions du cadran via GPIO + anti-rebond/filtrage.
|
||||||
|
- Souvent combiné avec l’Option A.
|
||||||
|
|
||||||
|
### Ce qui marche le mieux pour ton cas
|
||||||
|
- Vu ton besoin ("combiné + clavier en hard"), la meilleure approche reste:
|
||||||
|
- **MVP: interface directe (Option A)**,
|
||||||
|
- puis migration vers **ATA externe** ou **SLIC/FXS** si tu veux une expérience “ligne RTC” complète.
|
||||||
|
|
||||||
|
## Sources web utiles
|
||||||
|
- Espressif DevKitC: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-devkitc/index.html
|
||||||
|
- Espressif S3 DevKitC-1: https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-devkitc-1/index.html
|
||||||
|
- PlatformIO `esp32dev`: https://docs.platformio.org/en/latest/boards/espressif32/esp32dev.html
|
||||||
|
- PlatformIO `esp32-s3-devkitc-1`: https://docs.platformio.org/en/latest/boards/espressif32/esp32-s3-devkitc-1.html
|
||||||
|
- PlatformIO `nodemcu-32s`: https://docs.platformio.org/en/latest/boards/espressif32/nodemcu-32s.html
|
||||||
|
- PlatformIO `lolin32`: https://docs.platformio.org/en/latest/boards/espressif32/lolin32.html
|
||||||
|
- PlatformIO `esp32-c3-devkitc-02`: https://docs.platformio.org/en/latest/boards/espressif32/esp32-c3-devkitc-02.html
|
||||||
|
- Asterisk documentation (PBX/VoIP): https://docs.asterisk.org/
|
||||||
|
- Exemple ATA FXS (Grandstream HT801): https://www.grandstream.com/products/gateways-and-atas/analog-telephone-adaptors/product/ht801
|
||||||
|
- Silvertel (catalogue modules téléphonie): https://www.silvertel.com/
|
||||||
|
|
||||||
|
## Décision proposée
|
||||||
|
Pour ton besoin immédiat (PLIP / combiné + clavier en hard), la **meilleure balance risque/temps** est:
|
||||||
|
- **Option A en premier** avec **ESP32-DevKitC**.
|
||||||
|
- Puis extension progressive vers ESP32-S3 ou interface ligne complète si nécessaire.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[platformio]
|
||||||
|
default_envs = esp32-s3-devkitc-1
|
||||||
|
|
||||||
|
[env]
|
||||||
|
platform = espressif32
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
build_flags =
|
||||||
|
-DCORE_DEBUG_LEVEL=1
|
||||||
|
|
||||||
|
[env:esp32-s3-devkitc-1]
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
|
||||||
|
[env:esp32dev]
|
||||||
|
board = esp32dev
|
||||||
+188
@@ -0,0 +1,188 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
RTC_BL_PHONE - ESP32-S3 + AG1171S control skeleton
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
- Provide a practical firmware base for a private analog line project.
|
||||||
|
- Keep telephony analog front-end on AG1171S side.
|
||||||
|
- Let ESP32 manage call-state logic and debug observability.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Pin mapping must be validated against your AG1171S application schematic.
|
||||||
|
- Never connect to PSTN without compliant isolation/protection design.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum class PhoneState : uint8_t {
|
||||||
|
ON_HOOK,
|
||||||
|
OFF_HOOK,
|
||||||
|
DIALING,
|
||||||
|
IN_CALL,
|
||||||
|
RINGING
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhonePins {
|
||||||
|
uint8_t pinHookSense;
|
||||||
|
uint8_t pinRingCmd;
|
||||||
|
uint8_t pinLineEnable;
|
||||||
|
uint8_t pinLed;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
constexpr PhonePins PINS{
|
||||||
|
.pinHookSense = 4, // AG1171S hook/off-hook indication input to ESP32-S3
|
||||||
|
.pinRingCmd = 5, // ESP32-S3 output: request ring cadence generator/enable
|
||||||
|
.pinLineEnable = 6, // ESP32-S3 output: line feed enable (through safe driver)
|
||||||
|
.pinLed = 48 // ESP32-S3 DevKitC-1 RGB/Status-compatible GPIO
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
constexpr PhonePins PINS{
|
||||||
|
.pinHookSense = 27,
|
||||||
|
.pinRingCmd = 26,
|
||||||
|
.pinLineEnable = 25,
|
||||||
|
.pinLed = 2
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr uint32_t SERIAL_BAUD = 115200;
|
||||||
|
constexpr uint32_t DEBOUNCE_MS = 25;
|
||||||
|
|
||||||
|
PhoneState g_state = PhoneState::ON_HOOK;
|
||||||
|
bool g_hookOffHook = false;
|
||||||
|
uint32_t g_lastHookEdgeMs = 0;
|
||||||
|
|
||||||
|
const char* stateToString(PhoneState state) {
|
||||||
|
switch (state) {
|
||||||
|
case PhoneState::ON_HOOK: return "ON_HOOK";
|
||||||
|
case PhoneState::OFF_HOOK: return "OFF_HOOK";
|
||||||
|
case PhoneState::DIALING: return "DIALING";
|
||||||
|
case PhoneState::IN_CALL: return "IN_CALL";
|
||||||
|
case PhoneState::RINGING: return "RINGING";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(PhoneState newState) {
|
||||||
|
if (newState == g_state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_state = newState;
|
||||||
|
Serial.printf("[RTC_PHONE] state=%s\n", stateToString(g_state));
|
||||||
|
|
||||||
|
switch (g_state) {
|
||||||
|
case PhoneState::ON_HOOK:
|
||||||
|
digitalWrite(PINS.pinLineEnable, LOW);
|
||||||
|
digitalWrite(PINS.pinRingCmd, LOW);
|
||||||
|
digitalWrite(PINS.pinLed, LOW);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhoneState::OFF_HOOK:
|
||||||
|
digitalWrite(PINS.pinLineEnable, HIGH);
|
||||||
|
digitalWrite(PINS.pinRingCmd, LOW);
|
||||||
|
digitalWrite(PINS.pinLed, HIGH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhoneState::DIALING:
|
||||||
|
digitalWrite(PINS.pinLineEnable, HIGH);
|
||||||
|
digitalWrite(PINS.pinRingCmd, LOW);
|
||||||
|
digitalWrite(PINS.pinLed, HIGH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhoneState::IN_CALL:
|
||||||
|
digitalWrite(PINS.pinLineEnable, HIGH);
|
||||||
|
digitalWrite(PINS.pinRingCmd, LOW);
|
||||||
|
digitalWrite(PINS.pinLed, HIGH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PhoneState::RINGING:
|
||||||
|
digitalWrite(PINS.pinLineEnable, HIGH);
|
||||||
|
digitalWrite(PINS.pinRingCmd, HIGH);
|
||||||
|
digitalWrite(PINS.pinLed, HIGH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printHelp() {
|
||||||
|
Serial.println("[RTC_PHONE] Commands:");
|
||||||
|
Serial.println(" h -> help");
|
||||||
|
Serial.println(" r -> enter RINGING");
|
||||||
|
Serial.println(" o -> force ON_HOOK");
|
||||||
|
Serial.println(" d -> force DIALING");
|
||||||
|
Serial.println(" c -> force IN_CALL");
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleSerialCommands() {
|
||||||
|
while (Serial.available() > 0) {
|
||||||
|
const char cmd = static_cast<char>(Serial.read());
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case 'h':
|
||||||
|
printHelp();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
setState(PhoneState::RINGING);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
setState(PhoneState::ON_HOOK);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
setState(PhoneState::DIALING);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
setState(PhoneState::IN_CALL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateHookState() {
|
||||||
|
const bool rawOffHook = (digitalRead(PINS.pinHookSense) == LOW);
|
||||||
|
const uint32_t nowMs = millis();
|
||||||
|
|
||||||
|
if (rawOffHook != g_hookOffHook && (nowMs - g_lastHookEdgeMs) > DEBOUNCE_MS) {
|
||||||
|
g_lastHookEdgeMs = nowMs;
|
||||||
|
g_hookOffHook = rawOffHook;
|
||||||
|
|
||||||
|
Serial.printf("[RTC_PHONE] hook=%s\n", g_hookOffHook ? "OFF_HOOK" : "ON_HOOK");
|
||||||
|
|
||||||
|
if (g_hookOffHook) {
|
||||||
|
setState(PhoneState::OFF_HOOK);
|
||||||
|
} else {
|
||||||
|
setState(PhoneState::ON_HOOK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(SERIAL_BAUD);
|
||||||
|
|
||||||
|
pinMode(PINS.pinHookSense, INPUT_PULLUP);
|
||||||
|
pinMode(PINS.pinRingCmd, OUTPUT);
|
||||||
|
pinMode(PINS.pinLineEnable, OUTPUT);
|
||||||
|
pinMode(PINS.pinLed, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(PINS.pinRingCmd, LOW);
|
||||||
|
digitalWrite(PINS.pinLineEnable, LOW);
|
||||||
|
digitalWrite(PINS.pinLed, LOW);
|
||||||
|
|
||||||
|
Serial.println("\n[RTC_PHONE] Boot OK");
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
Serial.println("[RTC_PHONE] Target: ESP32-S3");
|
||||||
|
#else
|
||||||
|
Serial.println("[RTC_PHONE] Target: ESP32 (legacy mapping)");
|
||||||
|
#endif
|
||||||
|
Serial.println("[RTC_PHONE] Profile: AG1171S control skeleton");
|
||||||
|
printHelp();
|
||||||
|
|
||||||
|
setState(PhoneState::ON_HOOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
updateHookState();
|
||||||
|
handleSerialCommands();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user