Files
Maison/PacoMouseCYD/Platformio/Arduino.old/encoder.ino
2026-02-13 08:49:53 +01:00

239 lines
7.2 KiB
C++

/**
* @file encoder.ino
* @brief Rotary encoder and button handling for PacoMouseCYD throttle.
* @author F. Cañada
* @date 2025-2026
* @copyright https://usuaris.tinet.cat/fmco/
*
* This file contains interrupt service routines and functions for reading and processing
* rotary encoder and button input, including debouncing and value management.
*/
////////////////////////////////////////////////////////////
// API Documentation
////////////////////////////////////////////////////////////
/**
* @brief Interrupt Service Routine for the encoder.
*
* Sets a flag indicating the encoder needs service.
*/
void IRAM_ATTR encoderISR();
/**
* @brief Handles encoder state changes and updates encoder value.
*/
void encoderService();
/**
* @brief Reads the encoder button and updates its state.
*/
void readButtons();
/**
* @brief Processes encoder movement and updates UI or state accordingly.
*/
void controlEncoder();
////////////////////////////////////////////////////////////
// End API Documentation
////////////////////////////////////////////////////////////
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
*/
////////////////////////////////////////////////////////////
// ***** ENCODER *****
////////////////////////////////////////////////////////////
IRAM_ATTR void encoderISR () { // Encoder interrupt
encoderNeedService = true;
}
void encoderService () { // Encoder interrupt service
encoderNeedService = false;
lastTimeEncoder = millis();
outA = digitalRead (ENCODER_A);
outB = digitalRead (ENCODER_B);
if (outA != copyOutA) { // evitamos rebotes
copyOutA = outA;
if (copyOutB == 0x80) {
copyOutB = outB;
}
else {
if ( outB != copyOutB) {
copyOutB = 0x80;
if (outA == outB) // comprueba sentido de giro
encoderValue = (encoderValue < encoderMax) ? ++encoderValue : encoderMax ; // CW, hasta maximo
else
encoderValue = (encoderValue > 0) ? --encoderValue : 0; // CCW, hasta 0
encoderChange = true;
}
}
}
}
void readButtons () {
byte inputButton;
timeButtons = millis(); // lee cada cierto tiempo
inputButton = digitalRead (ENCODER_SW); // comprueba cambio en boton del encoder
if (statusSwitch != inputButton) {
statusSwitch = inputButton;
if (statusSwitch == LOW)
switchOn = true;
}
}
void controlEncoder() { // encoder movement
encoderChange = false;
aliveAndKicking();
DEBUG_MSG("Encoder: %d", encoderValue);
switch (objStack[lastWinStack].objID) {
case WIN_SSID:
scrSSID = encoderValue;
scanWiFiFill();
drawObject(OBJ_TXT, TXT_SSID1);
drawObject(OBJ_TXT, TXT_SSID2);
drawObject(OBJ_TXT, TXT_SSID3);
drawObject(OBJ_TXT, TXT_SSID4);
drawObject(OBJ_TXT, TXT_SSID5);
drawObject(OBJ_TXT, TXT_SSID6);
break;
case WIN_THROTTLE:
case WIN_SPEEDO:
case WIN_STA_PLAY:
updateMySpeed();
break;
case WIN_CHG_FUNC:
fncData[FNC_CHG].idIcon = encoderValue * 2;
drawObject(OBJ_FNC, FNC_CHG);
break;
case WIN_SEL_LOCO:
populateLocoList();
drawObject(OBJ_TXT, TXT_SEL_ADDR1);
drawObject(OBJ_TXT, TXT_SEL_NAME1);
drawObject(OBJ_TXT, TXT_SEL_ADDR2);
drawObject(OBJ_TXT, TXT_SEL_NAME2);
drawObject(OBJ_TXT, TXT_SEL_ADDR3);
drawObject(OBJ_TXT, TXT_SEL_NAME3);
drawObject(OBJ_TXT, TXT_SEL_ADDR4);
drawObject(OBJ_TXT, TXT_SEL_NAME4);
drawObject(OBJ_TXT, TXT_SEL_ADDR5);
drawObject(OBJ_TXT, TXT_SEL_NAME5);
drawObject(OBJ_TXT, TXT_SEL_ADDR6);
drawObject(OBJ_TXT, TXT_SEL_NAME6);
break;
case WIN_STEAM:
showSpeedSteam((encoderValue << 1) + 240);
break;
case WIN_ACC_TYPE:
fncData[FNC_ACC_TYPE].num = accDef[encoderValue].num;
fncData[FNC_ACC_TYPE].idIcon = accDef[encoderValue].icon[0].fncIcon;
fncData[FNC_ACC_TYPE].color = accDef[encoderValue].icon[0].color;
fncData[FNC_ACC_TYPE].colorOn = accDef[encoderValue].icon[0].colorOn;
drawObject(OBJ_FNC, FNC_ACC_TYPE);
break;
}
}
void controlSwitch() { // encoder switch
uint16_t value, value2, txtID;
uint32_t delta, dist;
char msg[NAME_LNG + 1];
switchOn = false;
aliveAndKicking();
DEBUG_MSG("Encoder Switch");
switch (objStack[lastWinStack].objID) {
case WIN_SSID:
snprintf (wifiSetting.ssid, 32, WiFi.SSID(scrSSID).c_str()); //saveSSID(scrSSID);
DEBUG_MSG("New SSID: %s", wifiSetting.ssid);
eepromChanged = true;
closeWindow(WIN_SSID);
openWindow(WIN_WIFI);
break;
case WIN_THROTTLE:
case WIN_STA_PLAY:
if (encoderValue > 0) {
encoderValue = 0;
if (stopMode > 0)
locoData[myLocoData].mySpeed = 1;
else
locoData[myLocoData].mySpeed = 0;
locoOperationSpeed();
}
else {
locoData[myLocoData].myDir ^= 0x80;
changeDirection();
}
updateSpeedDir();
break;
case WIN_CHG_FUNC:
fncData[FNC_F0 + paramChild].idIcon = fncData[FNC_CHG].idIcon;
closeWindow(WIN_CHG_FUNC);
break;
case WIN_SEL_LOCO:
releaseLoco();
txtID = (encoderValue > 5) ? 5 : encoderValue;
if (useID) {
value2 = (encoderValue > 5) ? encoderValue - 5 : 0;
value = sortedLocoStack[value2 + txtID];
}
else {
value = atoi(txtData[TXT_SEL_ADDR1 + txtID].buf);
}
//value = atoi(txtData[TXT_SEL_ADDR1 + txtID].buf);
DEBUG_MSG("Selected Loco %d", value);
closeWindow(WIN_SEL_LOCO);
getNewLoco(value);
break;
case WIN_SPEEDO:
switch (speedoPhase) { //enum speedo {SPD_WAIT, SPD_BEGIN, SPD_COUNT, SPD_ARRIVE, SPD_END};
case SPD_WAIT:
if (getCurrentStep() > 0) {
speedoStartTime = millis();
setSpeedoPhase(SPD_BEGIN);
getLabelTxt(LBL_MEASURE, msg);
snprintf(spdSpeedBuf, NAME_LNG + 1, "%s", msg);
drawObject(OBJ_TXT, TXT_SPEEDO_SPD);
setTimer(TMR_SPEEDO, 5, TMR_ONESHOT);
}
else {
locoData[myLocoData].myDir ^= 0x80;
changeDirection();
updateSpeedDir();
}
break;
case SPD_BEGIN:
case SPD_COUNT:
speedoEndTime = millis();
setSpeedoPhase(SPD_ARRIVE);
setTimer(TMR_SPEEDO, 5, TMR_ONESHOT);
dist = speedoLength * 36 * speedoScale;
delta = (speedoEndTime - speedoStartTime) * 10;
speedoSpeed = dist / delta;
snprintf(spdSpeedBuf, NAME_LNG + 1, "%d km/h", speedoSpeed);
drawObject(OBJ_TXT, TXT_SPEEDO_SPD);
break;
case SPD_ARRIVE:
break;
case SPD_END:
break;
}
break;
case WIN_STEAM:
steamThrottleStop();
currentSteamSpeed = 0;
locoData[myLocoData].mySpeed = 0;
locoOperationSpeed();
break;
case WIN_ACC_TYPE:
accTypeClick();
break;
}
}