From 7c857b0feb5178595301040d8b25a1fc808c9a50 Mon Sep 17 00:00:00 2001 From: Luis Teixeira Date: Wed, 4 Dec 2019 22:51:21 +0000 Subject: [PATCH] Added the command SerialConfig with the capability of changing the data bits/parity/stop bits setting in the hardware serial port. --- tasmota/i18n.h | 1 + tasmota/language/en-GB.h | 1 + tasmota/language/pt-PT.h | 1 + tasmota/settings.h | 22 ++++++++++++- tasmota/settings.ino | 35 +++++++++++++++++++-- tasmota/support.ino | 62 ++++++++++++++++++++++++++++++++++--- tasmota/support_command.ino | 50 ++++++++++++++++++++++++------ tasmota/tasmota.ino | 4 ++- 8 files changed, 158 insertions(+), 18 deletions(-) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 5de4b7a1d..65f9887a3 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -284,6 +284,7 @@ #define D_CMND_I2CDRIVER "I2CDriver" #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" +#define D_CMND_SERIALCONFIG "SerialConfig" #define D_CMND_BAUDRATE "Baudrate" #define D_CMND_TEMPLATE "Template" #define D_JSON_NAME "NAME" diff --git a/tasmota/language/en-GB.h b/tasmota/language/en-GB.h index a98087a18..15e880600 100644 --- a/tasmota/language/en-GB.h +++ b/tasmota/language/en-GB.h @@ -190,6 +190,7 @@ #define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled" #define D_SET_BAUDRATE_TO "Set Baudrate to" +#define D_SET_SERIAL_CONFIG_TO "Set serial port mode to" #define D_RECEIVED_TOPIC "Received Topic" #define D_DATA_SIZE "Data Size" #define D_ANALOG_INPUT "Analog" diff --git a/tasmota/language/pt-PT.h b/tasmota/language/pt-PT.h index 46bafdef6..27987acf0 100644 --- a/tasmota/language/pt-PT.h +++ b/tasmota/language/pt-PT.h @@ -190,6 +190,7 @@ #define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" #define D_SET_BAUDRATE_TO "Ajuste da velocidade para" +#define D_SET_SERIAL_CONFIG_TO "Ajuste do modo da porta série" #define D_RECEIVED_TOPIC "Topico Recebido" #define D_DATA_SIZE "Tamanho de Dados" #define D_ANALOG_INPUT "Entrada Analógica" diff --git a/tasmota/settings.h b/tasmota/settings.h index 554711cad..61359226b 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -231,6 +231,26 @@ typedef struct { const uint8_t MAX_TUYA_FUNCTIONS = 16; +/** + * Structure used for holding the hardware serial port settings. + * + * Description of the fields: + * + * baudrate - the baud rate multiplier, which can range from 0 - 15360 (multiply by 300 to obtain the actual baud rate) + * mode - encodes a selection of the main serial port settings. + * + * The mode field can take the following values: + * + * 0 - 7N1 (7 data bits / no parity / 1 stop bit) + * 1 - 7E1 (7 data bits / even parity / 1 stop bit) + * 2 - 8N1 (8 data bits / no parity / 1 stop bit) + * 3 - 8E1 (8 data bits / even parity / 1 stop bit) + */ +typedef struct { + uint16_t baudrate; // the baud rate multiplier, which can range from 0 - 15360 (multiply by 300 to obtain the actual baud rate) + uint8_t mode; // encodes a selection of the main serial port settings: 8E1, 8N1, 7E1 and 7N1 +} SerialCfg; + /* struct SYSCFG { unsigned long cfg_holder; // 000 Pre v6 header @@ -397,7 +417,7 @@ struct SYSCFG { uint8_t web_color[18][3]; // 73E uint16_t display_width; // 774 uint16_t display_height; // 776 - uint16_t baudrate; // 778 + uint16_t serial_config; // 778 - 11 MSB's define the baud rate; 5 LSB's define the serial config (e.g. 8N1). Maps to the SerialCfg struct. uint16_t sbaudrate; // 77A EnergyUsage energy_usage; // 77C // uint32_t drivers[3]; // 794 - 6.5.0.12 replaced by below three entries diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 9ca979b45..3f6621495 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -670,8 +670,13 @@ void SettingsDefaultSet2(void) // for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } // Serial - Settings.baudrate = APP_BAUDRATE / 300; + + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + config.baudrate = APP_BAUDRATE / 300; + Settings.serial_config = SerialCfgToSetting(config); + Settings.sbaudrate = SOFT_BAUDRATE / 300; + //Settings.serial_config = SERIAL_8N1; Settings.serial_delimiter = 0xff; Settings.seriallog_level = SERIAL_LOG_LEVEL; @@ -1059,7 +1064,10 @@ void SettingsDelta(void) } } if (Settings.version < 0x06060009) { - Settings.baudrate = Settings.ex_baudrate * 4; + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + config.baudrate = Settings.ex_baudrate * 4; + Settings.serial_config = SerialCfgToSetting(config); + Settings.sbaudrate = Settings.ex_sbaudrate * 4; } if (Settings.version < 0x0606000A) { @@ -1160,3 +1168,26 @@ void SettingsDelta(void) SettingsSave(1); } } + +/* Performs the bitwise operations needed for translating the serial port settings 16-bit word + to the SerialCfg struct: */ +SerialCfg SettingToSerialCfg(uint16_t setting) +{ + SerialCfg serial_config; + + serial_config.baudrate = (uint16_t) (setting >> 2) & 0x3FFF; + serial_config.mode = (uint8_t) (setting) & 0x3; + + return serial_config; +} + +/* Performs the bitwise operations needed for translating from the SerialCfg struct + to the serial port settings 16-bit word: */ +uint16_t SerialCfgToSetting(SerialCfg serial_config) +{ + uint16_t setting; + + setting = (uint16_t) ((uint16_t) (serial_config.baudrate << 2 & 0xFFFC)) | (serial_config.mode & 0x3); + + return setting; +} diff --git a/tasmota/support.ino b/tasmota/support.ino index 55c01b71d..8f1ba2862 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -738,16 +738,42 @@ int GetStateNumber(char *state_text) return state_number; } -void SetSerialBaudrate(int baudrate) +void SetSerialConfig(uint8_t mode) { - Settings.baudrate = baudrate / 300; + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + config.mode = mode; + Settings.serial_config = SerialCfgToSetting(config); + + SerialConfig hardware_serial_config = ConvertSettingByteToSerialConfig(mode); + + if (seriallog_level) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_SERIAL_CONFIG_TO " %d"), mode); + } + + delay(100); + Serial.flush(); + + Serial.begin(Serial.baudRate(), hardware_serial_config); + delay(10); + Serial.println(); +} + +void SetSerialBaudrate(uint32_t baudrate) +{ + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + config.baudrate = ((baudrate / 300) & 0x3FFF); + Settings.serial_config = SerialCfgToSetting(config); + + SerialConfig hardware_serial_config = ConvertSettingByteToSerialConfig(config.mode); + if (Serial.baudRate() != baudrate) { if (seriallog_level) { AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); } delay(100); Serial.flush(); - Serial.begin(baudrate, serial_config); + + Serial.begin(baudrate, hardware_serial_config); delay(10); Serial.println(); } @@ -759,7 +785,10 @@ void ClaimSerial(void) AddLog_P(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial")); SetSeriallog(LOG_LEVEL_NONE); baudrate = Serial.baudRate(); - Settings.baudrate = baudrate / 300; + + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + config.baudrate = baudrate / 300; + Settings.serial_config = SerialCfgToSetting(config); } void SerialSendRaw(char *codes) @@ -1647,3 +1676,28 @@ void AddLogMissed(char *sensor, uint32_t misses) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SNS: %s missed %d"), sensor, SENSOR_MAX_MISS - misses); } + +SerialConfig ConvertSettingByteToSerialConfig(uint8_t setting_byte) +{ + SerialConfig hardware_serial_config; + + switch(setting_byte) { + case 0: + hardware_serial_config = SERIAL_7N1; + break; + case 1: + hardware_serial_config = SERIAL_7E1; + break; + case 2: + hardware_serial_config = SERIAL_8N1; + break; + case 3: + hardware_serial_config = SERIAL_8E1; + break; + default: + hardware_serial_config = SERIAL_8N1; + break; + } + + return hardware_serial_config; +} \ No newline at end of file diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index fe8640045..f0a5ba87d 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -23,10 +23,10 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" - D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" - D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" - D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" + D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_SERIALCONFIG "|" + D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" + D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" + D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -38,7 +38,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, + &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndSerialConfig, &CmndBaudrate, &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, @@ -1072,14 +1072,44 @@ void CmndSwitchDebounce(void) ResponseCmndNumber(Settings.switch_debounce); } +/** + * Changes the Serial port number of bits, parity and stop bits. + * For the time being this command only has effect on the hardware + * serial port (GPIO1 and GPIO3) + * + * Meaning of the values: + * + * 0 - 7N1 (7 data bits / no parity / 1 stop bit) + * 1 - 7E1 (7 data bits / even parity / 1 stop bit) + * 2 - 8N1 (8 data bits / no parity / 1 stop bit) + * 3 - 8E1 (8 data bits / even parity / 1 stop bit) + * + */ + +void CmndSerialConfig(void) +{ + // a frugal validation to check if the provided serial port mode is valid: + + if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 3) { + uint8_t mode = (uint8_t) (XdrvMailbox.payload & 3); + + SetSerialConfig(mode); + } + + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + + ResponseCmndNumber(config.mode); +} + void CmndBaudrate(void) { - if (XdrvMailbox.payload >= 300) { - XdrvMailbox.payload /= 300; // Make it a valid baudrate - baudrate = (XdrvMailbox.payload & 0xFFFF) * 300; - SetSerialBaudrate(baudrate); + if (XdrvMailbox.payload >= 300) { + SetSerialBaudrate(XdrvMailbox.payload); } - ResponseCmndNumber(Settings.baudrate * 300); + + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + + ResponseCmndNumber(config.baudrate * 300); } void CmndSerialSend(void) diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 64a1125c6..e6511eb04 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -1535,7 +1535,9 @@ void setup(void) XdrvCall(FUNC_SETTINGS_OVERRIDE); } - baudrate = Settings.baudrate * 300; + SerialCfg config = SettingToSerialCfg(Settings.serial_config); + + baudrate = config.baudrate * 300; // mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START]; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER;