1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-24 21:21:24 +01:00

Merge branch 'devel-stm32EC' of https://github.com/DCC-EX/CommandStation-EX into devel-stm32EC

This commit is contained in:
Ash-4 2024-02-04 23:33:57 -06:00
commit df20e3ad95
8 changed files with 116 additions and 63 deletions

View File

@ -258,4 +258,23 @@ private:
#define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter)
#define SKIPOP progCounter+=3 #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 #endif

View File

@ -59,6 +59,10 @@
// helper macro for turnout description as HIDDEN // helper macro for turnout description as HIDDEN
#define HIDDEN "\x01" #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 // helper macro to strip leading zeros off time inputs
// (10#mins)%100) // (10#mins)%100)
#define STRIP_ZERO(value) 10##value%100 #define STRIP_ZERO(value) 10##value%100

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-stm32EC 202402041220Z" #define GITHUB_SHA "devel-stm32EC 202402041604Z"

View File

@ -54,8 +54,8 @@ static const FSH * guessI2CDeviceType(uint8_t address) {
return F("Time-of-flight sensor"); return F("Time-of-flight sensor");
else if (address >= 0x3c && address <= 0x3d) else if (address >= 0x3c && address <= 0x3d)
return F("OLED Display"); return F("OLED Display");
else if (address >= 0x48 && address <= 0x57) // Henkk: Added SC16IS752 UART detection else if (address >= 0x48 && address <= 0x57) // SC16IS752x UART detection
return F("SC16IS752 UART"); return F("SC16IS75x UART");
else if (address >= 0x48 && address <= 0x4f) else if (address >= 0x48 && address <= 0x4f)
return F("Analogue Inputs or PWM"); return F("Analogue Inputs or PWM");
else if (address >= 0x40 && address <= 0x4f) else if (address >= 0x40 && address <= 0x4f)

View File

@ -23,23 +23,28 @@
* This driver is a modified version of the IO_DFPlayer.h file * 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 * 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 * 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 * 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: * myHall.cpp configuration syntax:
* *
* I2CDFPlayer::create(1st vPin, vPins, I2C address, UART ch, AM); * I2CDFPlayer::create(1st vPin, vPins, I2C address, xtal);
* *
* Parameters: * Parameters:
* 1st vPin : First virtual pin that EX-Rail can control to play a sound, use PLAYSOUND command (alias of ANOUT) * 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) * vPins : Total number of virtual pins allocated (2 vPins are supported, one for each UART)
* I2C Address : I2C address of the serial controller, in 0x format, * 1st vPin for UART 0, 2nd for UART 1
* UART ch : Indicating UART 0 or UART 1, values 0 or 1 * I2C Address : I2C address of the serial controller, in 0x format
* AM : audio mixer, values: 1 or 2 to select an audio amplifier, no effect if AM is not installed * 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 // SC16IS752 defines
I2CAddress _I2CAddress; I2CAddress _I2CAddress;
I2CRB _rb; 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 // 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 WORD_LEN = 0x03; // Value LCR bit 0,1
uint8_t STOP_BIT = 0x00; // Value LCR bit 2 uint8_t STOP_BIT = 0x00; // Value LCR bit 2
@ -96,33 +101,36 @@ private:
bool _stopplayCmd = false; bool _stopplayCmd = false;
bool _resetCmd = false; bool _resetCmd = false;
bool _eqCmd = false; bool _eqCmd = false;
uint8_t _requestedEQValue = NORMAL; uint8_t _requestedEQValue = DF_NORMAL;
uint8_t _currentEQvalue = NORMAL; // start equalizer value uint8_t _currentEQvalue = DF_NORMAL; // start equalizer value
bool _daconCmd = false; bool _daconCmd = false;
uint8_t _audioMixer = 0x01; // Default to output amplifier 1 uint8_t _audioMixer = 0x01; // Default to output amplifier 1
bool _setamCmd = false; // Set the Audio mixer channel 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 _outbuffer [11]; // DFPlayer command is 10 bytes + 1 byte register address & UART channel
uint8_t _inbuffer[10]; // expected DFPlayer return 10 bytes 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;
unsigned long SC16IS752_XTAL_FREQ = 14745600; // Support for higher baud rates, standard for modular EX-IO system 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: public:
// Constructor // 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; _firstVpin = firstVpin;
_nPins = nPins; _nPins = nPins;
_I2CAddress = i2cAddress; _I2CAddress = i2cAddress;
_UART_CH = UART_CH; if (xtal == 0){
_audioMixer = AM; _sc16is752_xtal_freq = SC16IS752_XTAL_FREQ_LOW;
} else { // should be 1
_sc16is752_xtal_freq = SC16IS752_XTAL_FREQ_HIGH;
}
addDevice(this); addDevice(this);
} }
public: public:
static void create(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t UART_CH, uint8_t AM) { static void create(VPIN firstVpin, int nPins, I2CAddress i2cAddress, uint8_t xtal) {
if (checkNoOverlap(firstVpin, nPins, i2cAddress)) new I2CDFPlayer(firstVpin, nPins, i2cAddress, UART_CH, AM); if (checkNoOverlap(firstVpin, nPins, i2cAddress)) new I2CDFPlayer(firstVpin, nPins, i2cAddress, xtal);
} }
void _begin() override { void _begin() override {
// check if SC16IS752 exist first, initialize and then resume DFPlayer init via SC16IS752 // check if SC16IS752 exist first, initialize and then resume DFPlayer init via SC16IS752
@ -426,18 +434,18 @@ public:
//case NONE: //case NONE:
// DFPlayerCmd = cmd; // DFPlayerCmd = cmd;
// break; // break;
case PLAY: case DF_PLAY:
_playCmd = true; _playCmd = true;
_volCmd = true; _volCmd = true;
_requestedSong = value; _requestedSong = value;
_requestedVolumeLevel = volume; _requestedVolumeLevel = volume;
_playing = true; _playing = true;
break; break;
case VOL: case DF_VOL:
_volCmd = true; _volCmd = true;
_requestedVolumeLevel = volume; _requestedVolumeLevel = volume;
break; break;
case FOLDER: case DF_FOLDER:
_folderCmd = true; _folderCmd = true;
if (volume <= 0 || volume > 99){ // Range checking, valid values 1-99, else default to 1 if (volume <= 0 || volume > 99){ // Range checking, valid values 1-99, else default to 1
_requestedFolder = 0x01; // if outside range, default to folder 01 _requestedFolder = 0x01; // if outside range, default to folder 01
@ -445,7 +453,7 @@ public:
_requestedFolder = volume; _requestedFolder = volume;
} }
break; 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) { if (_repeat == false) {
#ifdef DIAG_I2CDFplayer_playing #ifdef DIAG_I2CDFplayer_playing
DIAG(F("I2CDFPlayer: WriteAnalog Repeat: _repeat: 0x0%x, value: %d _repeatCmd: 0x%x"), _repeat, value, _repeatCmd); DIAG(F("I2CDFPlayer: WriteAnalog Repeat: _repeat: 0x0%x, value: %d _repeatCmd: 0x%x"), _repeat, value, _repeatCmd);
@ -456,30 +464,30 @@ public:
_playing = true; _playing = true;
} }
break; break;
case STOPPLAY: case DF_STOPPLAY:
_stopplayCmd = true; _stopplayCmd = true;
break; break;
case EQ: case DF_EQ:
#ifdef DIAG_I2CDFplayer_playing #ifdef DIAG_I2CDFplayer_playing
DIAG(F("I2CDFPlayer: WriteAnalog EQ: cmd: 0x%x, EQ value: 0x%x"), cmd, volume); DIAG(F("I2CDFPlayer: WriteAnalog EQ: cmd: 0x%x, EQ value: 0x%x"), cmd, volume);
#endif #endif
_eqCmd = true; _eqCmd = true;
if (volume <= 0 || volume > 5) { // If out of range, default to NORMAL if (volume <= 0 || volume > 5) { // If out of range, default to NORMAL
_requestedEQValue = NORMAL; _requestedEQValue = DF_NORMAL;
} else { // Valid EQ parameter range } else { // Valid EQ parameter range
_requestedEQValue = volume; _requestedEQValue = volume;
} }
break; break;
case RESET: case DF_RESET:
_resetCmd = true; _resetCmd = true;
break; 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 #ifdef DIAG_I2CDFplayer_playing
DIAG(F("I2CDFPlayer: WrtieAnalog DACON: cmd: 0x%x"), cmd); DIAG(F("I2CDFPlayer: WrtieAnalog DACON: cmd: 0x%x"), cmd);
#endif #endif
_daconCmd = true; _daconCmd = true;
break; 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; _setamCmd = true;
#ifdef DIAG_I2CDFplayer_playing #ifdef DIAG_I2CDFplayer_playing
DIAG(F("I2CDFPlayer: WrtieAnalog SETAM: cmd: 0x%x"), cmd); DIAG(F("I2CDFPlayer: WrtieAnalog SETAM: cmd: 0x%x"), cmd);
@ -604,7 +612,8 @@ private:
#ifdef DIAG_I2CDFplayer #ifdef DIAG_I2CDFplayer
DIAG(F("SC16IS752: Initialize I2C: %s , UART Ch: 0x%x"), _I2CAddress.toString(), _UART_CH); DIAG(F("SC16IS752: Initialize I2C: %s , UART Ch: 0x%x"), _I2CAddress.toString(), _UART_CH);
#endif #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 TEMP_REG_VAL = 0x08; // UART Software reset
UART_WriteRegister(REG_IOCONTROL, TEMP_REG_VAL); UART_WriteRegister(REG_IOCONTROL, TEMP_REG_VAL);
TEMP_REG_VAL = 0x00; // Set pins to GPIO mode TEMP_REG_VAL = 0x00; // Set pins to GPIO mode
@ -770,23 +779,25 @@ enum : uint8_t{
REG_XOFF2 = 0x07, // R/W REG_XOFF2 = 0x07, // R/W
}; };
// DFPlayer commands and values // DFPlayer commands and values
// Declared in this scope
enum : uint8_t{ enum : uint8_t{
PLAY = 0x0F, DF_PLAY = 0x0F,
VOL = 0x06, DF_VOL = 0x06,
FOLDER = 0x2B, // Not a DFPlayer command, used to set folder nr where audio file is DF_FOLDER = 0x2B, // Not a DFPlayer command, used to set folder nr where audio file is
REPEATPLAY = 0x08, DF_REPEATPLAY = 0x08,
STOPPLAY = 0x16, DF_STOPPLAY = 0x16,
EQ = 0x07, // Set equaliser, require parameter NORMAL, POP, ROCK, JAZZ, CLASSIC or BASS DF_EQ = 0x07, // Set equaliser, require parameter NORMAL, POP, ROCK, JAZZ, CLASSIC or BASS
RESET = 0x0C, DF_RESET = 0x0C,
DACON = 0x1A, DF_DACON = 0x1A,
SETAM = 0x2A, // Set audio mixer 1 or 2 for this DFPLayer DF_SETAM = 0x2A, // Set audio mixer 1 or 2 for this DFPLayer
NORMAL = 0x00, // Equalizer parameters DF_NORMAL = 0x00, // Equalizer parameters
POP = 0x01, DF_POP = 0x01,
ROCK = 0x02, DF_ROCK = 0x02,
JAZZ = 0x03, DF_JAZZ = 0x03,
CLASSIC = 0x04, DF_CLASSIC = 0x04,
BASS = 0x05, DF_BASS = 0x05,
}; };
}; };

View File

@ -164,6 +164,8 @@ bool WifiESP::setup(const char *SSid,
if (haveSSID && havePassword && !forceAP) { if (haveSSID && havePassword && !forceAP) {
WiFi.setHostname(hostname); // Strangely does not work unless we do it HERE! WiFi.setHostname(hostname); // Strangely does not work unless we do it HERE!
WiFi.mode(WIFI_STA); 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 #ifdef SERIAL_BT_COMMANDS
WiFi.setSleep(true); WiFi.setSleep(true);
#else #else
@ -204,7 +206,7 @@ bool WifiESP::setup(const char *SSid,
if (!haveSSID || forceAP) { if (!haveSSID || forceAP) {
// prepare all strings // prepare all strings
String strSSID(forceAP ? SSid : "DCCEX_"); String strSSID(forceAP ? SSid : "DCCEX_");
String strPass(forceAP ? password : "PASS_"); String strPass( (forceAP && havePassword) ? password : "PASS_");
if (!forceAP) { if (!forceAP) {
String strMac = WiFi.macAddress(); String strMac = WiFi.macAddress();
strMac.remove(0,9); 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 AP SSID %s PASS %s"),strSSID.c_str(),havePassword ? password : strPass.c_str());
DIAG(F("Wifi in AP mode")); DIAG(F("Wifi in AP mode"));
LCD(5, F("Wifi: %s"), strSSID.c_str()); 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()); // DIAG(F("Wifi AP IP %s"),WiFi.softAPIP().toString().c_str());
LCD(7, F("IP: %s"),WiFi.softAPIP().toString().c_str()); LCD(7, F("IP: %s"),WiFi.softAPIP().toString().c_str());
wifiUp = true; wifiUp = true;

View File

@ -25,6 +25,7 @@
//#include "IO_EXTurntable.h" // Turntable-EX turntable controller //#include "IO_EXTurntable.h" // Turntable-EX turntable controller
//#include "IO_EXFastClock.h" // FastClock driver //#include "IO_EXFastClock.h" // FastClock driver
//#include "IO_PCA9555.h" // 16-bit I/O expander (NXP & Texas Instruments). //#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 //#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 // DFPlayer via NXP SC16IS752 I2C Dual UART.
// 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
// I2C address range 0x48 - 0x57 // I2C address range 0x48 - 0x57
// I2CDFPlayer::create(1st vPin,vPins, I2C address, UART ch); //
// Generic format:
// I2CDFPlayer::create(10000, 10, 0x48, 0); // I2CDFPlayer::create(1st vPin, vPins, I2C address, xtal);
// I2CDFPlayer::create(10010, 10, 0x48, 1); // Parameters:
// 1st vPin : First virtual pin that EX-Rail can control to play a sound, use PLAYSOUND command (alias of ANOUT)
// Multiplexer example // vPins : Total number of virtual pins allocated (1 vPin is supported currently)
// I2CDFPlayer::create(10020, 10, {I2CMux_0, SubBus_0, 0x50}, 0); // 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);

View File

@ -8,6 +8,13 @@
// 5.3.3 - Fix Ethernet cable disconnected message, wait for DHCP // 5.3.3 - Fix Ethernet cable disconnected message, wait for DHCP
// 5.3.2 - MDNS Generic library integration for Ethernet // 5.3.2 - MDNS Generic library integration for Ethernet
// 5.3.1 - Variable frequency for DC mode // 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.27 - Bugfix: IOExpander memory allocation
// 5.2.26 - Silently ignore overridden HAL defaults // 5.2.26 - Silently ignore overridden HAL defaults
// - include HAL_IGNORE_DEFAULTS macro in EXRAIL // - include HAL_IGNORE_DEFAULTS macro in EXRAIL
@ -24,7 +31,7 @@
// 5.2.18 - Display network IP fix // 5.2.18 - Display network IP fix
// 5.2.17 - ESP32 simplify network logic // 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 // 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 // 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 // - 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 // 5.2.14eth - Initial ethernet code for STM32F429ZI and F439ZI boards