mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 12:51:24 +01:00
Merge branch 'devel' of https://github.com/DCC-EX/CommandStation-EX into devel
This commit is contained in:
commit
b5ddade2b3
@ -76,6 +76,12 @@ void setup()
|
|||||||
|
|
||||||
DIAG(F("License GPLv3 fsf.org (c) dcc-ex.com"));
|
DIAG(F("License GPLv3 fsf.org (c) dcc-ex.com"));
|
||||||
|
|
||||||
|
// If user has defined a startup delay, delay here before starting IO
|
||||||
|
#if defined(STARTUP_DELAY)
|
||||||
|
DIAG(F("Delaying startup for %dms"), STARTUP_DELAY);
|
||||||
|
delay(STARTUP_DELAY);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Initialise HAL layer before reading EEprom or setting up MotorDrivers
|
// Initialise HAL layer before reading EEprom or setting up MotorDrivers
|
||||||
IODevice::begin();
|
IODevice::begin();
|
||||||
|
|
||||||
|
50
DCCRMT.cpp
50
DCCRMT.cpp
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* © 2021-2022, Harald Barth.
|
* © 2021-2024, Harald Barth.
|
||||||
*
|
*
|
||||||
* This file is part of DCC-EX
|
* This file is part of DCC-EX
|
||||||
*
|
*
|
||||||
@ -25,6 +25,18 @@
|
|||||||
#include "DCCWaveform.h" // for MAX_PACKET_SIZE
|
#include "DCCWaveform.h" // for MAX_PACKET_SIZE
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
|
||||||
|
// check for right type of ESP32
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#ifndef SOC_RMT_MEM_WORDS_PER_CHANNEL
|
||||||
|
#error This symobol should be defined
|
||||||
|
#endif
|
||||||
|
#if SOC_RMT_MEM_WORDS_PER_CHANNEL < 64
|
||||||
|
#warning This is not an ESP32-WROOM but some other unsupported variant
|
||||||
|
#warning You are outside of the DCC-EX supported hardware
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const byte RMT_CHAN_PER_DCC_CHAN = 2;
|
||||||
|
|
||||||
// Number of bits resulting out of X bytes of DCC payload data
|
// Number of bits resulting out of X bytes of DCC payload data
|
||||||
// Each byte has one bit extra and at the end we have one EOF marker
|
// Each byte has one bit extra and at the end we have one EOF marker
|
||||||
#define DATA_LEN(X) ((X)*9+1)
|
#define DATA_LEN(X) ((X)*9+1)
|
||||||
@ -75,12 +87,30 @@ void IRAM_ATTR interrupt(rmt_channel_t channel, void *t) {
|
|||||||
RMTChannel::RMTChannel(pinpair pins, bool isMain) {
|
RMTChannel::RMTChannel(pinpair pins, bool isMain) {
|
||||||
byte ch;
|
byte ch;
|
||||||
byte plen;
|
byte plen;
|
||||||
|
|
||||||
|
// Below we check if the DCC packet actually fits into the RMT hardware
|
||||||
|
// Currently MAX_PACKET_SIZE = 5 so with checksum there are
|
||||||
|
// MAX_PACKET_SIZE+1 data packets. Each need DATA_LEN (9) bits.
|
||||||
|
// To that we add the preamble length, the fencepost DCC end bit
|
||||||
|
// and the RMT EOF marker.
|
||||||
|
// SOC_RMT_MEM_WORDS_PER_CHANNEL is either 64 (original WROOM) or
|
||||||
|
// 48 (all other ESP32 like the -C3 or -S2
|
||||||
|
// The formula to get the possible MAX_PACKET_SIZE is
|
||||||
|
//
|
||||||
|
// ALLOCATED = RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL
|
||||||
|
// MAX_PACKET_SIZE = floor((ALLOCATED - PREAMBLE_LEN - 2)/9 - 1)
|
||||||
|
//
|
||||||
|
|
||||||
if (isMain) {
|
if (isMain) {
|
||||||
ch = 0;
|
ch = 0;
|
||||||
plen = PREAMBLE_BITS_MAIN;
|
plen = PREAMBLE_BITS_MAIN;
|
||||||
|
static_assert (DATA_LEN(MAX_PACKET_SIZE+1) + PREAMBLE_BITS_MAIN + 2 <= RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL,
|
||||||
|
"Number of DCC packet bits greater than ESP32 RMT memory available");
|
||||||
} else {
|
} else {
|
||||||
ch = 2;
|
ch = RMT_CHAN_PER_DCC_CHAN; // number == offset
|
||||||
plen = PREAMBLE_BITS_PROG;
|
plen = PREAMBLE_BITS_PROG;
|
||||||
|
static_assert (DATA_LEN(MAX_PACKET_SIZE+1) + PREAMBLE_BITS_PROG + 2 <= RMT_CHAN_PER_DCC_CHAN * SOC_RMT_MEM_WORDS_PER_CHANNEL,
|
||||||
|
"Number of DCC packet bits greater than ESP32 RMT memory available");
|
||||||
}
|
}
|
||||||
|
|
||||||
// preamble
|
// preamble
|
||||||
@ -115,7 +145,7 @@ RMTChannel::RMTChannel(pinpair pins, bool isMain) {
|
|||||||
// data: max packet size today is 5 + checksum
|
// data: max packet size today is 5 + checksum
|
||||||
maxDataLen = DATA_LEN(MAX_PACKET_SIZE+1); // plus checksum
|
maxDataLen = DATA_LEN(MAX_PACKET_SIZE+1); // plus checksum
|
||||||
data = (rmt_item32_t*)malloc(maxDataLen*sizeof(rmt_item32_t));
|
data = (rmt_item32_t*)malloc(maxDataLen*sizeof(rmt_item32_t));
|
||||||
|
|
||||||
rmt_config_t config;
|
rmt_config_t config;
|
||||||
// Configure the RMT channel for TX
|
// Configure the RMT channel for TX
|
||||||
bzero(&config, sizeof(rmt_config_t));
|
bzero(&config, sizeof(rmt_config_t));
|
||||||
@ -123,20 +153,10 @@ RMTChannel::RMTChannel(pinpair pins, bool isMain) {
|
|||||||
config.channel = channel = (rmt_channel_t)ch;
|
config.channel = channel = (rmt_channel_t)ch;
|
||||||
config.clk_div = RMT_CLOCK_DIVIDER;
|
config.clk_div = RMT_CLOCK_DIVIDER;
|
||||||
config.gpio_num = (gpio_num_t)pins.pin;
|
config.gpio_num = (gpio_num_t)pins.pin;
|
||||||
config.mem_block_num = 2; // With longest DCC packet 11 inc checksum (future expansion)
|
config.mem_block_num = RMT_CHAN_PER_DCC_CHAN;
|
||||||
// number of bits needed is 22preamble + start +
|
// use config
|
||||||
// 11*9 + extrazero + EOT = 124
|
|
||||||
// 2 mem block of 64 RMT items should be enough
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(rmt_config(&config));
|
ESP_ERROR_CHECK(rmt_config(&config));
|
||||||
addPin(pins.invpin, true);
|
addPin(pins.invpin, true);
|
||||||
/*
|
|
||||||
// test: config another gpio pin
|
|
||||||
gpio_num_t gpioNum = (gpio_num_t)(pin-1);
|
|
||||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpioNum], PIN_FUNC_GPIO);
|
|
||||||
gpio_set_direction(gpioNum, GPIO_MODE_OUTPUT);
|
|
||||||
gpio_matrix_out(gpioNum, RMT_SIG_OUT0_IDX, 0, 0);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// NOTE: ESP_INTR_FLAG_IRAM is *NOT* included in this bitmask
|
// NOTE: ESP_INTR_FLAG_IRAM is *NOT* included in this bitmask
|
||||||
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, ESP_INTR_FLAG_LOWMED|ESP_INTR_FLAG_SHARED));
|
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, ESP_INTR_FLAG_LOWMED|ESP_INTR_FLAG_SHARED));
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* © 2021 M Steve Todd
|
* © 2021 M Steve Todd
|
||||||
* © 2021 Mike S
|
* © 2021 Mike S
|
||||||
* © 2021 Fred Decker
|
* © 2021 Fred Decker
|
||||||
* © 2020-2021 Harald Barth
|
* © 2020-2024 Harald Barth
|
||||||
* © 2020-2021 Chris Harlow
|
* © 2020-2021 Chris Harlow
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@ -33,9 +33,9 @@
|
|||||||
|
|
||||||
|
|
||||||
// Number of preamble bits.
|
// Number of preamble bits.
|
||||||
const int PREAMBLE_BITS_MAIN = 16;
|
const byte PREAMBLE_BITS_MAIN = 16;
|
||||||
const int PREAMBLE_BITS_PROG = 22;
|
const byte PREAMBLE_BITS_PROG = 22;
|
||||||
const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum.
|
const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum.
|
||||||
|
|
||||||
|
|
||||||
// The WAVE_STATE enum is deliberately numbered because a change of order would be catastrophic
|
// The WAVE_STATE enum is deliberately numbered because a change of order would be catastrophic
|
||||||
|
@ -333,13 +333,15 @@ if (compileFeatures & FEATURE_SIGNAL) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
void RMFT2::setTurnoutHiddenState(Turnout * t) {
|
||||||
// turnout descriptions are in low flash F strings
|
// turnout descriptions are in low flash F strings
|
||||||
t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01);
|
const FSH *desc = getTurnoutDescription(t->getId());
|
||||||
|
if (desc) t->setHidden(GETFLASH(desc)==0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef IO_NO_HAL
|
#ifndef IO_NO_HAL
|
||||||
void RMFT2::setTurntableHiddenState(Turntable * tto) {
|
void RMFT2::setTurntableHiddenState(Turntable * tto) {
|
||||||
tto->setHidden(GETFLASH(getTurntableDescription(tto->getId()))==0x01);
|
const FSH *desc = getTurntableDescription(tto->getId());
|
||||||
|
if (desc) tto->setHidden(GETFLASH(desc)==0x01);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ void RMFT2::ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (paramCount==2) { // <JA id>
|
if (paramCount==2) { // <JA id>
|
||||||
uint16_t id=p[1];
|
int16_t id=p[1];
|
||||||
StringFormatter::send(stream,F("<jA %d %c \"%S\">\n"),
|
StringFormatter::send(stream,F("<jA %d %c \"%S\">\n"),
|
||||||
id, getRouteType(id), getRouteDescription(id));
|
id, getRouteType(id), getRouteDescription(id));
|
||||||
|
|
||||||
|
@ -59,15 +59,15 @@ EthernetInterface::EthernetInterface()
|
|||||||
DCCTimer::getSimulatedMacAddress(mac);
|
DCCTimer::getSimulatedMacAddress(mac);
|
||||||
connected=false;
|
connected=false;
|
||||||
|
|
||||||
#ifdef IP_ADDRESS
|
#ifdef IP_ADDRESS
|
||||||
Ethernet.begin(mac, IP_ADDRESS);
|
if (Ethernet.begin(mac, IP_ADDRESS) == 0)
|
||||||
#else
|
#else
|
||||||
if (Ethernet.begin(mac) == 0)
|
if (Ethernet.begin(mac) == 0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
DIAG(F("Ethernet.begin FAILED"));
|
DIAG(F("Ethernet.begin FAILED"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
|
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
|
||||||
DIAG(F("Ethernet shield not found or W5100"));
|
DIAG(F("Ethernet shield not found or W5100"));
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
#define GITHUB_SHA "devel-202401030135Z"
|
#define GITHUB_SHA "devel-202401100719Z"
|
||||||
|
@ -222,6 +222,14 @@ The configuration file for DCC-EX Command Station
|
|||||||
// We do not support to use the same address, for example 100(long) and 100(short)
|
// We do not support to use the same address, for example 100(long) and 100(short)
|
||||||
// at the same time, there must be a border.
|
// at the same time, there must be a border.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Some newer 32bit microcontrollers boot very quickly, so powering on I2C and other
|
||||||
|
// peripheral devices at the same time may result in the CommandStation booting too
|
||||||
|
// quickly to detect them.
|
||||||
|
// To work around this, uncomment the STARTUP_DELAY line below and set a value in
|
||||||
|
// milliseconds that works for your environment, default is 3000 (3 seconds).
|
||||||
|
// #define STARTUP_DELAY 3000
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// DEFINE TURNOUTS/ACCESSORIES FOLLOW NORM RCN-213
|
// DEFINE TURNOUTS/ACCESSORIES FOLLOW NORM RCN-213
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.2.18"
|
#define VERSION "5.2.22"
|
||||||
|
// 5.2.22 - Bugfixes: Empty turnout descriptions ok; negative route numbers valid.
|
||||||
|
// 5.2.21 - Add STARTUP_DELAY config option to delay CS bootup
|
||||||
|
// 5.2.20 - Check return of Ethernet.begin()
|
||||||
|
// 5.2.19 - ESP32: Determine if the RMT hardware can handle DCC
|
||||||
// 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
|
||||||
|
Loading…
Reference in New Issue
Block a user