feat: agregar opciones de sonido y volumen independiente de alarma en la configuracion

This commit is contained in:
Sebastián Nieto 2026-09-09 23:46:43 -03:00
parent 88503b0313
commit 0315854a12
3 changed files with 311 additions and 51 deletions

View file

@ -33,13 +33,14 @@ void clickSound() {
casioBeep(4096, 25); casioBeep(4096, 25);
} }
// Configuration menu list (3 options) // Configuration menu list (4 options)
const String menuList[3] = { const String menuList[4] = {
"Ajuste de Alarmas", // 0 "Activación de Alarmas", // 0
"Volumen de Bip", // 1 "Sonido de Alarma", // 1
"Salir" // 2 "Volumen de Bip", // 2
"Salir" // 3
}; };
const uint8_t maxMenu = 3; const uint8_t maxMenu = 4;
// Menu list for warning setting (4 vehicle gauges) // Menu list for warning setting (4 vehicle gauges)
const String parameterList[4][2] = { const String parameterList[4][2] = {
@ -56,7 +57,7 @@ void warningMenu() {
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00); tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK); tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Ajuste de Alarmas ---]", 159, 0, 4); tft.drawCentreString("[--- Activación de Alarmas ---]", 159, 0, 4);
auto drawAllRows = [&]() { auto drawAllRows = [&]() {
for (uint8_t i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
@ -119,7 +120,167 @@ void warningMenu() {
} }
// ------------------------------------------------------------- // -------------------------------------------------------------
// Sub-screen 1: Volumen de Bip (Ajuste Tactil Directo) // Sub-screen 1: Sonido de Alarma (Tipo de Sonido y Volumen)
// -------------------------------------------------------------
const char* const ALARM_NAME_TABLE[4] = {
"Casio Doble",
"Sincronizado",
"Bitonal Auto",
"Triple Urgente"
};
void playAlarmSample(uint8_t type, uint8_t vol) {
if (vol == 0) return;
uint16_t duty = VOL_DUTY_TABLE[vol > 5 ? 3 : vol];
if (type == 0) { // Casio Doble
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(25);
ledcWrite(buzzerChannel, 0);
delay(35);
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(25);
ledcWrite(buzzerChannel, 0);
} else if (type == 1) { // Sincronizado
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(30);
ledcWrite(buzzerChannel, 0);
delay(100);
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(30);
ledcWrite(buzzerChannel, 0);
} else if (type == 2) { // Bitonal Auto
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(40);
ledcWrite(buzzerChannel, 0);
delay(20);
ledcSetup(buzzerChannel, 3072, 10);
ledcWrite(buzzerChannel, duty);
delay(40);
ledcWrite(buzzerChannel, 0);
} else if (type == 3) { // Triple Urgente
for (uint8_t k = 0; k < 3; k++) {
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
delay(20);
ledcWrite(buzzerChannel, 0);
if (k < 2) delay(25);
}
}
}
void alarmSoundMenu() {
tft.fillScreen(TFT_BLACK);
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Sonido de Alarma ---]", 159, 0, 4);
auto drawAlarmUI = []() {
tft.fillRect(0, 28, 320, 160, TFT_BLACK);
// 4 Pattern Tiles (2x2 grid)
for (uint8_t i = 0; i < 4; i++) {
int16_t x = (i % 2 == 0) ? 10 : 166;
int16_t y = (i < 2) ? 34 : 74;
int16_t w = 144;
int16_t h = 34;
bool isSel = (i == alarmSoundType);
uint16_t bg = isSel ? TFT_BLUE : 0x18E3;
tft.fillRoundRect(x, y, w, h, 5, bg);
if (isSel) {
tft.drawRoundRect(x, y, w, h, 5, TFT_CYAN);
tft.drawRoundRect(x + 1, y + 1, w - 2, h - 2, 4, TFT_WHITE);
}
tft.setTextColor(isSel ? TFT_WHITE : 0xBDD7, bg);
tft.drawCentreString(ALARM_NAME_TABLE[i], x + w / 2, y + 8, 2);
}
// Volume level label
tft.setTextColor(TFT_WHITE, TFT_BLACK);
String lvlStr = "Volumen: Nivel " + String(alarmVolumeLevel) + " de 5 (" + VOL_NAME_TABLE[alarmVolumeLevel] + ")";
tft.drawCentreString(lvlStr.c_str(), 160, 116, 2);
// 6 Direct Touch Tiles (0 to 5) for Alarm Volume
for (uint8_t i = 0; i <= 5; i++) {
int16_t bx = 7 + i * 52;
int16_t by = 136;
int16_t bw = 46;
int16_t bh = 46;
bool isSel = (i == alarmVolumeLevel);
uint16_t bgCol = isSel ? (i == 0 ? 0x8000 : (i >= 4 ? TFT_ORANGE : (i >= 2 ? TFT_GREEN : 0x03E0))) : 0x18E3;
tft.fillRoundRect(bx, by, bw, bh, 5, bgCol);
if (isSel) {
tft.drawRoundRect(bx, by, bw, bh, 5, TFT_WHITE);
tft.drawRoundRect(bx + 1, by + 1, bw - 2, bh - 2, 4, TFT_WHITE);
}
tft.setTextColor(isSel ? TFT_WHITE : 0xAD55, bgCol);
tft.drawCentreString(String(i).c_str(), bx + bw / 2, by + 6, 6);
}
};
drawAlarmUI();
// Bottom action button: [ GUARDAR Y SALIR ]
tft.fillRoundRect(25, 192, 270, 40, 5, 0x02EC); // Rich Ocean Blue
tft.setTextColor(TFT_WHITE);
tft.drawCentreString("GUARDAR Y SALIR", 160, 200, 4);
delay(200);
while (true) {
autoDim();
uint16_t tx = 0, ty = 0;
if (getTouch(&tx, &ty)) {
// 1. Touch on pattern selection (y: 32 to 112)
if (ty >= 32 && ty <= 112) {
int8_t col = (tx < 160) ? 0 : 1;
int8_t row = (ty < 72) ? 0 : 1;
uint8_t selType = row * 2 + col;
if (selType < 4) {
alarmSoundType = selType;
drawAlarmUI();
playAlarmSample(alarmSoundType, alarmVolumeLevel);
}
while (isScreenPressed()) { delay(10); yield(); }
delay(50);
}
// 2. Touch on alarm volume tiles (y: 130 to 186)
else if (ty >= 130 && ty <= 186) {
int8_t touchedLvl = (tx - 7) / 52;
if (touchedLvl >= 0 && touchedLvl <= 5) {
alarmVolumeLevel = touchedLvl;
drawAlarmUI();
playAlarmSample(alarmSoundType, alarmVolumeLevel);
}
while (isScreenPressed()) { delay(10); yield(); }
delay(50);
}
// 3. Bottom button [ GUARDAR Y SALIR ] or top bar
else if ((ty >= 188 && ty <= 238 && tx >= 20 && tx <= 300) || ty < 30) {
casioBeep(4096, 25);
pref.begin("setting", false);
pref.putUChar("alm_vol", alarmVolumeLevel);
pref.putUChar("alm_type", alarmSoundType);
pref.end();
while (isScreenPressed()) { delay(10); yield(); }
break;
}
} else if (digitalRead(SELECTOR_PIN) == LOW) {
delay(200);
break;
}
yield();
}
}
// -------------------------------------------------------------
// Sub-screen 2: Volumen de Bip (Ajuste Tactil Directo)
// ------------------------------------------------------------- // -------------------------------------------------------------
void volumeMenu() { void volumeMenu() {
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
@ -205,7 +366,6 @@ void volumeMenu() {
} }
} }
// -------------------------------------------------------------
// ------------------------------------------------------------- // -------------------------------------------------------------
// Menu Principal // Menu Principal
// ------------------------------------------------------------- // -------------------------------------------------------------
@ -213,17 +373,17 @@ void listMenu(uint8_t choice) {
tft.fillRect(0, 28, 320, 212, TFT_BLACK); tft.fillRect(0, 28, 320, 212, TFT_BLACK);
for (uint8_t i = 0; i < maxMenu; i++) { for (uint8_t i = 0; i < maxMenu; i++) {
int y = 46 + i * 64; int y = 34 + i * 50;
if (choice == i) { if (choice == i) {
tft.fillRoundRect(10, y, 300, 48, 6, TFT_BLUE); tft.fillRoundRect(10, y, 300, 42, 5, TFT_BLUE);
tft.drawRoundRect(10, y, 300, 48, 6, TFT_CYAN); tft.drawRoundRect(10, y, 300, 42, 5, TFT_CYAN);
tft.drawRoundRect(11, y + 1, 298, 46, 5, TFT_CYAN); tft.drawRoundRect(11, y + 1, 298, 40, 4, TFT_CYAN);
tft.setTextColor(TFT_WHITE, TFT_BLUE); tft.setTextColor(TFT_WHITE, TFT_BLUE);
} else { } else {
tft.fillRoundRect(10, y, 300, 48, 6, 0x18E3); // subtle dark card tft.fillRoundRect(10, y, 300, 42, 5, 0x18E3); // subtle dark card
tft.setTextColor(TFT_WHITE, 0x18E3); tft.setTextColor(TFT_WHITE, 0x18E3);
} }
tft.drawString(menuList[i], 25, y + 12, 4); tft.drawString(menuList[i], 22, y + 9, 4);
} }
} }
@ -246,9 +406,10 @@ void configMenu() {
if (getTouch(&tx, &ty)) { if (getTouch(&tx, &ty)) {
int8_t touchedOpt = -1; int8_t touchedOpt = -1;
if (ty >= 36 && ty < 102) touchedOpt = 0; if (ty >= 28 && ty < 80) touchedOpt = 0;
else if (ty >= 102 && ty < 166) touchedOpt = 1; else if (ty >= 80 && ty < 130) touchedOpt = 1;
else if (ty >= 166 && ty <= 235) touchedOpt = 2; else if (ty >= 130 && ty < 180) touchedOpt = 2;
else if (ty >= 180 && ty <= 235) touchedOpt = 3;
if (touchedOpt >= 0) { if (touchedOpt >= 0) {
select = touchedOpt; select = touchedOpt;
@ -285,7 +446,7 @@ void configMenu() {
if (executeSelect >= 0) { if (executeSelect >= 0) {
select = executeSelect; select = executeSelect;
// Option 0: Warning setting (Thresholds & ON/OFF) // Option 0: Activacion de Alarmas (ON/OFF)
if (select == 0) { if (select == 0) {
warningMenu(); warningMenu();
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
@ -294,8 +455,17 @@ void configMenu() {
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4); tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
listMenu(select); listMenu(select);
} }
// Option 1: Volume setting (Buzzer level & live touch) // Option 1: Sonido de Alarma (Tipo de Sonido y Volumen)
else if (select == 1) { else if (select == 1) {
alarmSoundMenu();
tft.fillScreen(TFT_BLACK);
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
tft.setTextColor(TFT_BLACK);
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
listMenu(select);
}
// Option 2: Volumen de Bip (Toques de pantalla)
else if (select == 2) {
volumeMenu(); volumeMenu();
tft.fillScreen(TFT_BLACK); tft.fillScreen(TFT_BLACK);
tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00); tft.fillRectVGradient(0, 0, 320, 26, TFT_ORANGE, 0xfc00);
@ -303,8 +473,8 @@ void configMenu() {
tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4); tft.drawCentreString("[--- Configuration Menu ---]", 159, 0, 4);
listMenu(select); listMenu(select);
} }
// Option 2: Exit // Option 3: Exit
else if (select == 2) { else if (select == 3) {
break; break;
} }

View file

@ -1365,13 +1365,13 @@ void updateMeter(uint8_t pidNo, String response) { // update parameter on screen
} }
/*-------------------------------*/ /*-------------------------------*/
// Non-blocking alarm sound generator: classic Casio double-chirp [bip-bip] every 1 second // Non-blocking alarm sound generator: 4 selectable patterns
uint32_t lastAlarmSoundCycle = 0; uint32_t lastAlarmSoundCycle = 0;
uint8_t alarmSoundStep = 0; uint8_t alarmSoundStep = 0;
uint32_t alarmSoundStepTime = 0; uint32_t alarmSoundStepTime = 0;
void handleAlarmSound(bool anyAlarmActive) { void handleAlarmSound(bool anyAlarmActive, bool flashTick = false) {
if (!anyAlarmActive || buzzerVolumeLevel == 0) { if (!anyAlarmActive || alarmVolumeLevel == 0) {
if (alarmSoundStep != 0) { if (alarmSoundStep != 0) {
ledcWrite(buzzerChannel, 0); ledcWrite(buzzerChannel, 0);
alarmSoundStep = 0; alarmSoundStep = 0;
@ -1380,9 +1380,10 @@ void handleAlarmSound(bool anyAlarmActive) {
} }
uint32_t now = millis(); uint32_t now = millis();
uint16_t duty = VOL_DUTY_TABLE[buzzerVolumeLevel > 5 ? 3 : buzzerVolumeLevel]; uint16_t duty = VOL_DUTY_TABLE[alarmVolumeLevel > 5 ? 3 : alarmVolumeLevel];
// Pattern: [25ms chirp] -> 35ms pause -> [25ms chirp] -> pause until 1000ms if (alarmSoundType == 0) {
// Patrón 0: Casio Doble cada 1000ms
if (alarmSoundStep == 0) { if (alarmSoundStep == 0) {
if (now - lastAlarmSoundCycle >= 1000) { if (now - lastAlarmSoundCycle >= 1000) {
lastAlarmSoundCycle = now; lastAlarmSoundCycle = now;
@ -1391,25 +1392,108 @@ void handleAlarmSound(bool anyAlarmActive) {
ledcSetup(buzzerChannel, 4096, 10); ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty); ledcWrite(buzzerChannel, duty);
} }
} else if (alarmSoundStep == 1) { // 25ms first chirp } else if (alarmSoundStep == 1) { // 25ms chirp
if (now - alarmSoundStepTime >= 25) { if (now - alarmSoundStepTime >= 25) {
ledcWrite(buzzerChannel, 0); ledcWrite(buzzerChannel, 0);
alarmSoundStep = 2; alarmSoundStep = 2;
alarmSoundStepTime = now; alarmSoundStepTime = now;
} }
} else if (alarmSoundStep == 2) { // 35ms gap } else if (alarmSoundStep == 2) { // 35ms pausa
if (now - alarmSoundStepTime >= 35) { if (now - alarmSoundStepTime >= 35) {
ledcSetup(buzzerChannel, 4096, 10); ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty); ledcWrite(buzzerChannel, duty);
alarmSoundStep = 3; alarmSoundStep = 3;
alarmSoundStepTime = now; alarmSoundStepTime = now;
} }
} else if (alarmSoundStep == 3) { // 25ms second chirp } else if (alarmSoundStep == 3) { // 25ms chirp
if (now - alarmSoundStepTime >= 25) { if (now - alarmSoundStepTime >= 25) {
ledcWrite(buzzerChannel, 0); ledcWrite(buzzerChannel, 0);
alarmSoundStep = 0; alarmSoundStep = 0;
} }
} }
} else if (alarmSoundType == 1) {
// Patrón 1: Sincronizado con el parpadeo del vúmetro
if (flashTick && arcFlashVisible) {
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
alarmSoundStep = 1;
alarmSoundStepTime = now;
} else if (alarmSoundStep == 1 && (now - alarmSoundStepTime >= 30)) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 0;
}
} else if (alarmSoundType == 2) {
// Patrón 2: Bitonal Automotriz cada 1000ms (4096 Hz -> 3072 Hz)
if (alarmSoundStep == 0) {
if (now - lastAlarmSoundCycle >= 1000) {
lastAlarmSoundCycle = now;
alarmSoundStep = 1;
alarmSoundStepTime = now;
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
}
} else if (alarmSoundStep == 1) { // 40ms tono alto
if (now - alarmSoundStepTime >= 40) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 2;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 2) { // 20ms silencio
if (now - alarmSoundStepTime >= 20) {
ledcSetup(buzzerChannel, 3072, 10);
ledcWrite(buzzerChannel, duty);
alarmSoundStep = 3;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 3) { // 40ms tono medio
if (now - alarmSoundStepTime >= 40) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 0;
}
}
} else if (alarmSoundType == 3) {
// Patrón 3: Triple Urgente cada 1200ms
if (alarmSoundStep == 0) {
if (now - lastAlarmSoundCycle >= 1200) {
lastAlarmSoundCycle = now;
alarmSoundStep = 1;
alarmSoundStepTime = now;
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
}
} else if (alarmSoundStep == 1) { // 20ms pulso 1
if (now - alarmSoundStepTime >= 20) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 2;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 2) { // 25ms pausa
if (now - alarmSoundStepTime >= 25) {
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
alarmSoundStep = 3;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 3) { // 20ms pulso 2
if (now - alarmSoundStepTime >= 20) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 4;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 4) { // 25ms pausa
if (now - alarmSoundStepTime >= 25) {
ledcSetup(buzzerChannel, 4096, 10);
ledcWrite(buzzerChannel, duty);
alarmSoundStep = 5;
alarmSoundStepTime = now;
}
} else if (alarmSoundStep == 5) { // 20ms pulso 3
if (now - alarmSoundStepTime >= 20) {
ledcWrite(buzzerChannel, 0);
alarmSoundStep = 0;
}
}
}
} }
// Non-blocking handler to blink/flash arcs and numerical values on alarm (when in TFT_RED) // Non-blocking handler to blink/flash arcs and numerical values on alarm (when in TFT_RED)
@ -1595,7 +1679,7 @@ void handleArcAlarmFlash() {
} }
} }
} }
handleAlarmSound(anyInRedAlarm); handleAlarmSound(anyInRedAlarm, toggleTick);
} }
// Target and current brightness variables for smooth fade // Target and current brightness variables for smooth fade

View file

@ -97,6 +97,8 @@ bool alarmEnabled[4] = { true, true, true, true };
const uint16_t VOL_DUTY_TABLE[6] = { 0, 2, 8, 25, 80, 250 }; const uint16_t VOL_DUTY_TABLE[6] = { 0, 2, 8, 25, 80, 250 };
const char* const VOL_NAME_TABLE[6] = { "SILENCIO", "ULTRA BAJO", "MUY BAJO", "BAJO (CASIO)", "MEDIO", "ALTO" }; const char* const VOL_NAME_TABLE[6] = { "SILENCIO", "ULTRA BAJO", "MUY BAJO", "BAJO (CASIO)", "MEDIO", "ALTO" };
uint8_t buzzerVolumeLevel = 3; // Default 3: Bajo (Casio suave) uint8_t buzzerVolumeLevel = 3; // Default 3: Bajo (Casio suave)
uint8_t alarmVolumeLevel = 3; // Default 3: Bajo/Casio (Volumen independiente de alarma)
uint8_t alarmSoundType = 0; // Default 0: Casio Doble (0: Casio Doble, 1: Sincronizado, 2: Bitonal, 3: Triple Urgente)
/* /*
0 - Refrigerante 0 - Refrigerante
@ -286,8 +288,12 @@ recent_client_addr : {0x00,0x00,0x00,0x00,0x00,0x00} array of bytes[6]
String almKey = "alm_" + String(i); String almKey = "alm_" + String(i);
alarmEnabled[i] = pref.getBool(almKey.c_str(), true); alarmEnabled[i] = pref.getBool(almKey.c_str(), true);
} }
buzzerVolumeLevel = pref.getUChar("b_vol", 2); buzzerVolumeLevel = pref.getUChar("b_vol", 3);
if (buzzerVolumeLevel > 5) buzzerVolumeLevel = 2; if (buzzerVolumeLevel > 5) buzzerVolumeLevel = 3;
alarmVolumeLevel = pref.getUChar("alm_vol", 3);
if (alarmVolumeLevel > 5) alarmVolumeLevel = 3;
alarmSoundType = pref.getUChar("alm_type", 0);
if (alarmSoundType > 3) alarmSoundType = 0;
pref.getBytes("recent_client", recent_client_addr, pref.getBytesLength("recent_client")); //read last bt address pref.getBytes("recent_client", recent_client_addr, pref.getBytesLength("recent_client")); //read last bt address