diff --git a/EXRAIL2.h b/EXRAIL2.h index 63d20e7..10306a4 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -258,4 +258,23 @@ private: #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 +// IO_I2CDFPlayer commands and values +enum : uint8_t{ + DF_PLAY = 0x0F, + DF_VOL = 0x06, + DF_FOLDER = 0x2B, // Not a DFPlayer command, used to set folder nr where audio file is + DF_REPEATPLAY = 0x08, + DF_STOPPLAY = 0x16, + DF_EQ = 0x07, // Set equaliser, require parameter NORMAL, POP, ROCK, JAZZ, CLASSIC or BASS + DF_RESET = 0x0C, + DF_DACON = 0x1A, + DF_SETAM = 0x2A, // Set audio mixer 1 or 2 for this DFPLayer + DF_NORMAL = 0x00, // Equalizer parameters + DF_POP = 0x01, + DF_ROCK = 0x02, + DF_JAZZ = 0x03, + DF_CLASSIC = 0x04, + DF_BASS = 0x05, + }; + #endif diff --git a/EXRAILMacros.h b/EXRAILMacros.h index ccf04c9..9d9306b 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -59,6 +59,10 @@ // helper macro for turnout description as HIDDEN #define HIDDEN "\x01" +// PLAYSOUND is alias of ANOUT to make the user experience of a Conductor beter for +// playing sounds with IO_I2CDFPlayer +#define PLAYSOUND ANOUT + // helper macro to strip leading zeros off time inputs // (10#mins)%100) #define STRIP_ZERO(value) 10##value%100 diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index d27b1be..db92939 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-stm32EC 202402041220Z" +#define GITHUB_SHA "devel-stm32EC 202402041604Z" diff --git a/I2CManager.cpp b/I2CManager.cpp index 2591e13..5558c57 100644 --- a/I2CManager.cpp +++ b/I2CManager.cpp @@ -54,8 +54,8 @@ static const FSH * guessI2CDeviceType(uint8_t address) { return F("Time-of-flight sensor"); else if (address >= 0x3c && address <= 0x3d) return F("OLED Display"); - else if (address >= 0x48 && address <= 0x57) // Henkk: Added SC16IS752 UART detection - return F("SC16IS752 UART"); + else if (address >= 0x48 && address <= 0x57) // SC16IS752x UART detection + return F("SC16IS75x UART"); else if (address >= 0x48 && address <= 0x4f) return F("Analogue Inputs or PWM"); else if (address >= 0x40 && address <= 0x4f) diff --git a/IO_I2CDFPlayer.h b/IO_I2CDFPlayer.h index 39c0e02..c291b56 100644 --- a/IO_I2CDFPlayer.h +++ b/IO_I2CDFPlayer.h @@ -23,23 +23,28 @@ * This driver is a modified version of the IO_DFPlayer.h file * ********************************************************************************************* * - * 2023, Added NXP SC16IS752 I2C Dual UART to enable the DFPlayer connection over the I2C bus + * Dec 2023, Added NXP SC16IS752 I2C Dual UART to enable the DFPlayer connection over the I2C bus * The SC16IS752 has 64 bytes TX & RX FIFO buffer * First version without interrupts from I2C UART and only RX/TX are used, interrupts may not be * needed as the RX Fifo holds the reply * + * Jan 2024, Issue with using both UARTs simultaniously, the secod uart seems to work but the first transmit + * corrupt data. This need more analysis and experimenatation. + * Will push this driver to the dev branch with the uart fixed to 0 + * Both SC16IS750 (single uart) and SC16IS752 (dual uart, but only uart 0 is enable) + * * myHall.cpp configuration syntax: * - * I2CDFPlayer::create(1st vPin, vPins, I2C address, UART ch, AM); + * I2CDFPlayer::create(1st vPin, vPins, I2C address, xtal); * * Parameters: * 1st vPin : First virtual pin that EX-Rail can control to play a sound, use PLAYSOUND command (alias of ANOUT) - * vPins : Total number of virtual pins allocated (only 1 vPin is supported) - * I2C Address : I2C address of the serial controller, in 0x format, - * UART ch : Indicating UART 0 or UART 1, values 0 or 1 - * AM : audio mixer, values: 1 or 2 to select an audio amplifier, no effect if AM is not installed + * vPins : Total number of virtual pins allocated (2 vPins are supported, one for each UART) + * 1st vPin for UART 0, 2nd for UART 1 + * I2C Address : I2C address of the serial controller, in 0x format + * xtal : 0 for 1,8432Mhz, 1 for 14,7456Mhz * - * The vPin is also an pin that can be read, it indicated if the DFPlayer has finished playing a track + * The vPin is also a pin that can be read, it indicate if the DFPlayer has finished playing a track * */ @@ -75,7 +80,7 @@ private: // SC16IS752 defines I2CAddress _I2CAddress; I2CRB _rb; - uint8_t _UART_CH; + uint8_t _UART_CH=0x00; // Fix uart ch to 0 for now // Communication parameters for the DFPlayer are fixed at 8 bit, No parity, 1 stopbit uint8_t WORD_LEN = 0x03; // Value LCR bit 0,1 uint8_t STOP_BIT = 0x00; // Value LCR bit 2 @@ -96,33 +101,36 @@ private: bool _stopplayCmd = false; bool _resetCmd = false; bool _eqCmd = false; - uint8_t _requestedEQValue = NORMAL; - uint8_t _currentEQvalue = NORMAL; // start equalizer value + uint8_t _requestedEQValue = DF_NORMAL; + uint8_t _currentEQvalue = DF_NORMAL; // start equalizer value bool _daconCmd = false; uint8_t _audioMixer = 0x01; // Default to output amplifier 1 bool _setamCmd = false; // Set the Audio mixer channel uint8_t _outbuffer [11]; // DFPlayer command is 10 bytes + 1 byte register address & UART channel uint8_t _inbuffer[10]; // expected DFPlayer return 10 bytes - - //unsigned long SC16IS752_XTAL_FREQ = 1843200; // To support cheap eBay/AliExpress SC16IS752 boards - unsigned long SC16IS752_XTAL_FREQ = 14745600; // Support for higher baud rates, standard for modular EX-IO system - + + unsigned long _sc16is752_xtal_freq; + unsigned long SC16IS752_XTAL_FREQ_LOW = 1843200; // To support cheap eBay/AliExpress SC16IS752 boards + unsigned long SC16IS752_XTAL_FREQ_HIGH = 14745600; // Support for higher baud rates, standard for modular EX-IO system public: // Constructor - I2CDFPlayer(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t UART_CH, uint8_t AM){ + I2CDFPlayer(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t xtal){ _firstVpin = firstVpin; _nPins = nPins; _I2CAddress = i2cAddress; - _UART_CH = UART_CH; - _audioMixer = AM; + if (xtal == 0){ + _sc16is752_xtal_freq = SC16IS752_XTAL_FREQ_LOW; + } else { // should be 1 + _sc16is752_xtal_freq = SC16IS752_XTAL_FREQ_HIGH; + } addDevice(this); } public: - static void create(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t UART_CH, uint8_t AM) { - if (checkNoOverlap(firstVpin, nPins, i2cAddress)) new I2CDFPlayer(firstVpin, nPins, i2cAddress, UART_CH, AM); - } + static void create(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t xtal) { + if (checkNoOverlap(firstVpin, nPins, i2cAddress)) new I2CDFPlayer(firstVpin, nPins, i2cAddress, xtal); + } void _begin() override { // check if SC16IS752 exist first, initialize and then resume DFPlayer init via SC16IS752 @@ -426,18 +434,18 @@ public: //case NONE: // DFPlayerCmd = cmd; // break; - case PLAY: + case DF_PLAY: _playCmd = true; _volCmd = true; _requestedSong = value; _requestedVolumeLevel = volume; _playing = true; break; - case VOL: + case DF_VOL: _volCmd = true; _requestedVolumeLevel = volume; break; - case FOLDER: + case DF_FOLDER: _folderCmd = true; if (volume <= 0 || volume > 99){ // Range checking, valid values 1-99, else default to 1 _requestedFolder = 0x01; // if outside range, default to folder 01 @@ -445,7 +453,7 @@ public: _requestedFolder = volume; } break; - case REPEATPLAY: // Need to check if _repeat == true, if so do nothing + case DF_REPEATPLAY: // Need to check if _repeat == true, if so do nothing if (_repeat == false) { #ifdef DIAG_I2CDFplayer_playing DIAG(F("I2CDFPlayer: WriteAnalog Repeat: _repeat: 0x0%x, value: %d _repeatCmd: 0x%x"), _repeat, value, _repeatCmd); @@ -456,30 +464,30 @@ public: _playing = true; } break; - case STOPPLAY: + case DF_STOPPLAY: _stopplayCmd = true; break; - case EQ: + case DF_EQ: #ifdef DIAG_I2CDFplayer_playing DIAG(F("I2CDFPlayer: WriteAnalog EQ: cmd: 0x%x, EQ value: 0x%x"), cmd, volume); #endif _eqCmd = true; if (volume <= 0 || volume > 5) { // If out of range, default to NORMAL - _requestedEQValue = NORMAL; + _requestedEQValue = DF_NORMAL; } else { // Valid EQ parameter range _requestedEQValue = volume; } break; - case RESET: + case DF_RESET: _resetCmd = true; break; - case DACON: // Works, but without the DACOFF command limited value, except when not relying on DFPlayer default to turn the DAC on + case DF_DACON: // Works, but without the DACOFF command limited value, except when not relying on DFPlayer default to turn the DAC on #ifdef DIAG_I2CDFplayer_playing DIAG(F("I2CDFPlayer: WrtieAnalog DACON: cmd: 0x%x"), cmd); #endif _daconCmd = true; break; - case SETAM: // Set the audio mixer channel to 1 or 2 + case DF_SETAM: // Set the audio mixer channel to 1 or 2 _setamCmd = true; #ifdef DIAG_I2CDFplayer_playing DIAG(F("I2CDFPlayer: WrtieAnalog SETAM: cmd: 0x%x"), cmd); @@ -604,7 +612,8 @@ private: #ifdef DIAG_I2CDFplayer DIAG(F("SC16IS752: Initialize I2C: %s , UART Ch: 0x%x"), _I2CAddress.toString(), _UART_CH); #endif - uint16_t _divisor = (SC16IS752_XTAL_FREQ / PRESCALER) / (BAUD_RATE * 16); + //uint16_t _divisor = (SC16IS752_XTAL_FREQ / PRESCALER) / (BAUD_RATE * 16); + uint16_t _divisor = (_sc16is752_xtal_freq/PRESCALER)/(BAUD_RATE * 16); // Calculate _divisor for baudrate TEMP_REG_VAL = 0x08; // UART Software reset UART_WriteRegister(REG_IOCONTROL, TEMP_REG_VAL); TEMP_REG_VAL = 0x00; // Set pins to GPIO mode @@ -770,23 +779,25 @@ enum : uint8_t{ REG_XOFF2 = 0x07, // R/W }; + // DFPlayer commands and values +// Declared in this scope enum : uint8_t{ - PLAY = 0x0F, - VOL = 0x06, - FOLDER = 0x2B, // Not a DFPlayer command, used to set folder nr where audio file is - REPEATPLAY = 0x08, - STOPPLAY = 0x16, - EQ = 0x07, // Set equaliser, require parameter NORMAL, POP, ROCK, JAZZ, CLASSIC or BASS - RESET = 0x0C, - DACON = 0x1A, - SETAM = 0x2A, // Set audio mixer 1 or 2 for this DFPLayer - NORMAL = 0x00, // Equalizer parameters - POP = 0x01, - ROCK = 0x02, - JAZZ = 0x03, - CLASSIC = 0x04, - BASS = 0x05, + DF_PLAY = 0x0F, + DF_VOL = 0x06, + DF_FOLDER = 0x2B, // Not a DFPlayer command, used to set folder nr where audio file is + DF_REPEATPLAY = 0x08, + DF_STOPPLAY = 0x16, + DF_EQ = 0x07, // Set equaliser, require parameter NORMAL, POP, ROCK, JAZZ, CLASSIC or BASS + DF_RESET = 0x0C, + DF_DACON = 0x1A, + DF_SETAM = 0x2A, // Set audio mixer 1 or 2 for this DFPLayer + DF_NORMAL = 0x00, // Equalizer parameters + DF_POP = 0x01, + DF_ROCK = 0x02, + DF_JAZZ = 0x03, + DF_CLASSIC = 0x04, + DF_BASS = 0x05, }; }; diff --git a/WifiESP32.cpp b/WifiESP32.cpp index 2aef5d1..e45d0e8 100644 --- a/WifiESP32.cpp +++ b/WifiESP32.cpp @@ -164,6 +164,8 @@ bool WifiESP::setup(const char *SSid, if (haveSSID && havePassword && !forceAP) { WiFi.setHostname(hostname); // Strangely does not work unless we do it HERE! WiFi.mode(WIFI_STA); + WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); // Scan all channels so we find strongest + // (default in Wifi library is first match) #ifdef SERIAL_BT_COMMANDS WiFi.setSleep(true); #else @@ -204,7 +206,7 @@ bool WifiESP::setup(const char *SSid, if (!haveSSID || forceAP) { // prepare all strings String strSSID(forceAP ? SSid : "DCCEX_"); - String strPass(forceAP ? password : "PASS_"); + String strPass( (forceAP && havePassword) ? password : "PASS_"); if (!forceAP) { String strMac = WiFi.macAddress(); strMac.remove(0,9); @@ -228,7 +230,8 @@ bool WifiESP::setup(const char *SSid, // DIAG(F("Wifi AP SSID %s PASS %s"),strSSID.c_str(),havePassword ? password : strPass.c_str()); DIAG(F("Wifi in AP mode")); LCD(5, F("Wifi: %s"), strSSID.c_str()); - LCD(6, F("PASS: %s"),havePassword ? password : strPass.c_str()); + if (!havePassword) + LCD(6, F("PASS: %s"),strPass.c_str()); // DIAG(F("Wifi AP IP %s"),WiFi.softAPIP().toString().c_str()); LCD(7, F("IP: %s"),WiFi.softAPIP().toString().c_str()); wifiUp = true; diff --git a/myHal.cpp_example.txt b/myHal.cpp_example.txt index 288494b..70eb96a 100644 --- a/myHal.cpp_example.txt +++ b/myHal.cpp_example.txt @@ -25,6 +25,7 @@ //#include "IO_EXTurntable.h" // Turntable-EX turntable controller //#include "IO_EXFastClock.h" // FastClock driver //#include "IO_PCA9555.h" // 16-bit I/O expander (NXP & Texas Instruments). +//#include "IO_I2CDFPlayer.h" // DFPlayer over I2C //#include "IO_CMRI.h" // CMRI nodes //========================================================================== @@ -275,19 +276,27 @@ void halSetup() { //======================================================================= - // Play mp3 files from a Micro-SD card, using a DFPlayer MP3 Module on a SC16IS752 I2C Dual UART + // Play mp3 files from a Micro-SD card, using a DFPlayer MP3 Module on a SC16IS750/SC16IS752 I2C UART //======================================================================= - // DFPlayer via NXP SC16IS752 I2C Dual UART. Each device has 2 UARTs on a single I2C address - // Total nr of devices on an I2C bus is 16, with 2 UARTs on each address making a total of 32 UARTs per I2C bus + // DFPlayer via NXP SC16IS752 I2C Dual UART. // I2C address range 0x48 - 0x57 - // I2CDFPlayer::create(1st vPin,vPins, I2C address, UART ch); - - // I2CDFPlayer::create(10000, 10, 0x48, 0); - // I2CDFPlayer::create(10010, 10, 0x48, 1); - - // Multiplexer example - // I2CDFPlayer::create(10020, 10, {I2CMux_0, SubBus_0, 0x50}, 0); - + // + // Generic format: + // I2CDFPlayer::create(1st vPin, vPins, I2C address, xtal); + // Parameters: + // 1st vPin : First virtual pin that EX-Rail can control to play a sound, use PLAYSOUND command (alias of ANOUT) + // vPins : Total number of virtual pins allocated (1 vPin is supported currently) + // 1st vPin for UART 0 + // I2C Address : I2C address of the serial controller, in 0x format + // xtal : 0 for 1.8432Mhz, 1 for 14.7456Mhz + // + // The vPin is also a pin that can be read with the WAITFOR(vPin) command indicating if the DFPlayer has finished playing a track + // + + // I2CDFPlayer::create(10000, 1, 0x48, 1); + // + // Configuration example on a multiplexer + // I2CDFPlayer::create(10000, 1, {I2CMux_0, SubBus_0, 0x48}, 1); diff --git a/version.h b/version.h index eeae782..afe7d9c 100644 --- a/version.h +++ b/version.h @@ -8,6 +8,13 @@ // 5.3.3 - Fix Ethernet cable disconnected message, wait for DHCP // 5.3.2 - MDNS Generic library integration for Ethernet // 5.3.1 - Variable frequency for DC mode +// 5.2.40 - Bugfix: WiThrottle sendIntro after initial N message as well +// 5.2.29 - Added IO_I2CDFPlayer.h to support DFPLayer over I2C connected to NXP SC16IS750/SC16IS752 (currently only single UART for SC16IS752) +// - Added enhanced IO_I2CDFPLayer enum commands to EXRAIL2.h +// - Added PLAYSOUND alias of ANOUT to EXRAILMacros.h +// - Added UART detection to I2CManager.cpp +// 5.2.28 - ESP32: Can all Wifi channels. +// - ESP32: Only write Wifi password to display if it is a well known one // 5.2.27 - Bugfix: IOExpander memory allocation // 5.2.26 - Silently ignore overridden HAL defaults // - include HAL_IGNORE_DEFAULTS macro in EXRAIL @@ -24,7 +31,7 @@ // 5.2.18 - Display network IP fix // 5.2.17 - ESP32 simplify network logic // 5.2.16 - Bugfix to allow for devices using the EX-IOExpander protocol to have no analogue or no digital pins -// df - I2C DFPlayper capability +// df - I2C DFPlayper capability in stm32 branch // 5.2.15 - move call to CommandDistributor::broadcastPower() into the TrackManager::setTrackPower(*) functions // - add repeats to function packets that are not reminded in accordance with accessory packets // 5.2.14eth - Initial ethernet code for STM32F429ZI and F439ZI boards