Merge branch '332-feature-request-add-a-no-programming-option-to-save-ram-on-uno' into devel

This commit is contained in:
Harald Barth 2023-05-09 14:11:18 +02:00
commit ecc366cbd1
11 changed files with 81 additions and 198 deletions

View File

@ -152,7 +152,7 @@ byte DCCACK::getAck() {
return(0); // pending set off but not detected means no ACK.
}
#ifndef DISABLE_PROG
void DCCACK::loop() {
while (ackManagerProg) {
byte opcode=GETFLASH(ackManagerProg);
@ -414,7 +414,7 @@ void DCCACK::callback(int value) {
(ackManagerCallback)( value);
}
}
#endif
void DCCACK::checkAck(byte sentResetsSincePacket) {
if (!ackPending) return;

View File

@ -3,7 +3,7 @@
* © 2021 Neil McKechnie
* © 2021 Mike S
* © 2021 Herb Morton
* © 2020-2022 Harald Barth
* © 2020-2023 Harald Barth
* © 2020-2021 M Steve Todd
* © 2020-2021 Fred Decker
* © 2020-2021 Chris Harlow
@ -54,9 +54,7 @@
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
// To discover new keyword numbers , use the <$ YOURKEYWORD> command
const int16_t HASH_KEYWORD_PROG = -29718;
const int16_t HASH_KEYWORD_MAIN = 11339;
const int16_t HASH_KEYWORD_JOIN = -30750;
const int16_t HASH_KEYWORD_CABS = -11981;
const int16_t HASH_KEYWORD_RAM = 25982;
const int16_t HASH_KEYWORD_CMD = 9962;
@ -64,7 +62,11 @@ const int16_t HASH_KEYWORD_ACK = 3113;
const int16_t HASH_KEYWORD_ON = 2657;
const int16_t HASH_KEYWORD_DCC = 6436;
const int16_t HASH_KEYWORD_SLOW = -17209;
#ifndef DISABLE_PROG
const int16_t HASH_KEYWORD_JOIN = -30750;
const int16_t HASH_KEYWORD_PROG = -29718;
const int16_t HASH_KEYWORD_PROGBOOST = -6353;
#endif
#ifndef DISABLE_EEPROM
const int16_t HASH_KEYWORD_EEPROM = -7168;
#endif
@ -371,6 +373,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return;
break;
#ifndef DISABLE_PROG
case 'w': // WRITE CV on MAIN <w CAB CV VALUE>
DCC::writeCVByteMain(p[0], p[1], p[2]);
return;
@ -378,9 +381,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
case 'b': // WRITE CV BIT ON MAIN <b CAB CV BIT VALUE>
DCC::writeCVBitMain(p[0], p[1], p[2], p[3]);
return;
#endif
case 'M': // WRITE TRANSPARENT DCC PACKET MAIN <M REG X1 ... X9>
#ifndef DISABLE_PROG
case 'P': // WRITE TRANSPARENT DCC PACKET PROG <P REG X1 ... X9>
#endif
// NOTE: this command was parsed in HEX instead of decimal
params--; // drop REG
if (params<1) break;
@ -395,6 +401,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
}
return;
#ifndef DISABLE_PROG
case 'W': // WRITE CV ON PROG <W CV VALUE CALLBACKNUM CALLBACKSUB>
if (!stashCallback(stream, p, ringStream))
break;
@ -452,6 +459,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
return;
}
break;
#endif
case '1': // POWERON <1 [MAIN|PROG|JOIN]>
{
@ -464,17 +472,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
prog=true;
}
if (params==1) {
if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN>
if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
main=true;
}
#ifndef DISABLE_PROG
else if (p[0] == HASH_KEYWORD_JOIN) { // <1 JOIN>
main=true;
prog=true;
join=true;
}
else if (p[0]==HASH_KEYWORD_MAIN) { // <1 MAIN>
main=true;
}
else if (p[0]==HASH_KEYWORD_PROG) { // <1 PROG>
prog=true;
}
#endif
else break; // will reply <X>
}
if (main) TrackManager::setMainPower(POWERMODE::ON);
@ -498,9 +508,11 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
if (p[0]==HASH_KEYWORD_MAIN) { // <0 MAIN>
main=true;
}
#ifndef DISABLE_PROG
else if (p[0]==HASH_KEYWORD_PROG) { // <0 PROG>
prog=true;
}
#endif
else break; // will reply <X>
}
@ -895,6 +907,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
StringFormatter::send(stream, F("Free memory=%d\n"), DCCTimer::getMinimumFreeMemory());
break;
#ifndef DISABLE_PROG
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX|RETRY] Value>
if (params >= 3) {
if (p[1] == HASH_KEYWORD_LIMIT) {
@ -915,6 +928,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
Diag::ACK = onOff;
}
return true;
#endif
case HASH_KEYWORD_CMD: // <D CMD ON/OFF>
Diag::CMD = onOff;
@ -937,11 +951,11 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
Diag::LCN = onOff;
return true;
#endif
#ifndef DISABLE_PROG
case HASH_KEYWORD_PROGBOOST:
TrackManager::progTrackBoosted=true;
return true;
#endif
case HASH_KEYWORD_RESET:
DCCTimer::reset();
break; // and <X> if we didnt restart

View File

@ -705,11 +705,11 @@ void RMFT2::loop2() {
DCC::setThrottle(0,1,true); // pause all locos on the track
pausingTask=this;
break;
case OPCODE_POM:
if (loco) DCC::writeCVByteMain(loco, operand, getOperand(1));
break;
case OPCODE_POWEROFF:
TrackManager::setPower(POWERMODE::OFF);
TrackManager::setJoin(false);
@ -884,23 +884,18 @@ void RMFT2::loop2() {
while(loopTask) loopTask->kill(F("KILLALL"));
return;
#ifndef DISABLE_PROG
case OPCODE_JOIN:
TrackManager::setPower(POWERMODE::ON);
TrackManager::setJoin(true);
CommandDistributor::broadcastPower();
break;
case OPCODE_POWERON:
TrackManager::setMainPower(POWERMODE::ON);
TrackManager::setJoin(false);
CommandDistributor::broadcastPower();
break;
case OPCODE_UNJOIN:
TrackManager::setJoin(false);
CommandDistributor::broadcastPower();
break;
case OPCODE_READ_LOCO1: // READ_LOCO is implemented as 2 separate opcodes
progtrackLocoId=LOCO_ID_WAITING; // Nothing found yet
DCC::getLocoId(readLocoCallback);
@ -921,6 +916,13 @@ void RMFT2::loop2() {
forward=true;
invert=false;
break;
#endif
case OPCODE_POWERON:
TrackManager::setMainPower(POWERMODE::ON);
TrackManager::setJoin(false);
CommandDistributor::broadcastPower();
break;
case OPCODE_START:
{

View File

@ -45,7 +45,10 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_RED,OPCODE_GREEN,OPCODE_AMBER,OPCODE_DRIVE,
OPCODE_SERVO,OPCODE_SIGNAL,OPCODE_TURNOUT,OPCODE_WAITFOR,
OPCODE_PAD,OPCODE_FOLLOW,OPCODE_CALL,OPCODE_RETURN,
OPCODE_JOIN,OPCODE_UNJOIN,OPCODE_READ_LOCO1,OPCODE_READ_LOCO2,OPCODE_POM,
#ifndef DISABLE_PROG
OPCODE_JOIN,OPCODE_UNJOIN,OPCODE_READ_LOCO1,OPCODE_READ_LOCO2,
#endif
OPCODE_POM,
OPCODE_START,OPCODE_SETLOCO,OPCODE_SENDLOCO,OPCODE_FORGET,
OPCODE_PAUSE, OPCODE_RESUME,OPCODE_POWEROFF,OPCODE_POWERON,
OPCODE_ONCLOSE, OPCODE_ONTHROW, OPCODE_SERVOTURNOUT, OPCODE_PINTURNOUT,

View File

@ -101,7 +101,9 @@
#undef PAUSE
#undef PIN_TURNOUT
#undef PRINT
#ifndef DISABLE_PROG
#undef POM
#endif
#undef POWEROFF
#undef POWERON
#undef READ_LOCO
@ -224,7 +226,9 @@
#define PIN_TURNOUT(id,pin,description...)
#define PRINT(msg)
#define PARSE(msg)
#ifndef DISABLE_PROG
#define POM(cv,value)
#endif
#define POWEROFF
#define POWERON
#define READ_LOCO

View File

@ -327,8 +327,10 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = {
#define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id),
#define ONCHANGE(sensor_id) OPCODE_ONCHANGE,V(sensor_id),
#define PAUSE OPCODE_PAUSE,0,0,
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),
#define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin),
#ifndef DISABLE_PROG
#define POM(cv,value) OPCODE_POM,V(cv),OPCODE_PAD,V(value),
#endif
#define POWEROFF OPCODE_POWEROFF,0,0,
#define POWERON OPCODE_POWERON,0,0,
#define PRINT(msg) OPCODE_PRINT,V(__COUNTER__ - StringMacroTracker2),

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-202305072222Z"
#define GITHUB_SHA "devel-202305091210Z"

View File

@ -33,8 +33,9 @@
FOR_EACH_TRACK(t) \
if (trackMode[t]==findmode) \
track[t]->function;
#ifndef DISABLE_PROG
const int16_t HASH_KEYWORD_PROG = -29718;
#endif
const int16_t HASH_KEYWORD_MAIN = 11339;
const int16_t HASH_KEYWORD_OFF = 22479;
const int16_t HASH_KEYWORD_DC = 2183;
@ -116,7 +117,11 @@ void TrackManager::Setup(const FSH * shieldname,
// Default the first 2 tracks (which may be null) and perform HA waveform check.
setTrackMode(0,TRACK_MODE_MAIN);
#ifndef DISABLE_PROG
setTrackMode(1,TRACK_MODE_PROG);
#else
setTrackMode(1,TRACK_MODE_MAIN);
#endif
// TODO Fault pin config for odd motor boards (example pololu)
// MotorDriver::commonFaultPin = ((mainDriver->getFaultPin() == progDriver->getFaultPin())
@ -198,7 +203,11 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
pinMode(p.invpin, OUTPUT); // gpio_reset_pin may reset to input
}
#endif
#ifndef DISABLE_PROG
if (mode==TRACK_MODE_PROG) {
#else
if (false) {
#endif
// only allow 1 track to be prog
FOR_EACH_TRACK(t)
if (trackMode[t]==TRACK_MODE_PROG && t != trackToSet) {
@ -306,8 +315,10 @@ bool TrackManager::parseJ(Print *stream, int16_t params, int16_t p[])
if (params==2 && p[1]==HASH_KEYWORD_MAIN) // <= id MAIN>
return setTrackMode(p[0],TRACK_MODE_MAIN);
#ifndef DISABLE_PROG
if (params==2 && p[1]==HASH_KEYWORD_PROG) // <= id PROG>
return setTrackMode(p[0],TRACK_MODE_PROG);
#endif
if (params==2 && p[1]==HASH_KEYWORD_OFF) // <= id OFF>
return setTrackMode(p[0],TRACK_MODE_OFF);
@ -332,9 +343,11 @@ void TrackManager::streamTrackState(Print* stream, byte t) {
case TRACK_MODE_MAIN:
format=F("<= %c MAIN>\n");
break;
#ifndef DISABLE_PROG
case TRACK_MODE_PROG:
format=F("<= %c PROG>\n");
break;
#endif
case TRACK_MODE_OFF:
format=F("<= %c OFF>\n");
break;
@ -357,8 +370,10 @@ void TrackManager::streamTrackState(Print* stream, byte t) {
byte TrackManager::nextCycleTrack=MAX_TRACKS;
void TrackManager::loop() {
DCCWaveform::loop();
DCCACK::loop();
DCCWaveform::loop();
#ifndef DISABLE_PROG
DCCACK::loop();
#endif
bool dontLimitProg=DCCACK::isActive() || progTrackSyncMain || progTrackBoosted;
nextCycleTrack++;
if (nextCycleTrack>lastTrack) nextCycleTrack=0;

View File

@ -141,7 +141,7 @@ The configuration file for DCC-EX Command Station
//
// If you do not need the EEPROM at all, you can disable all the code that saves
// data in the EEPROM. You might want to do that if you are in a Arduino UNO
// and want to use the EX-RAIL automation. Otherwise you do not have enough RAM
// and want to use the EXRAIL automation. Otherwise you do not have enough RAM
// to do that. Of course, then none of the EEPROM related commands work.
//
// EEPROM does not work on ESP32. So on ESP32, EEPROM will always be disabled,
@ -149,6 +149,17 @@ The configuration file for DCC-EX Command Station
//
// #define DISABLE_EEPROM
/////////////////////////////////////////////////////////////////////////////////////
// DISABLE PROG
//
// If you do not need programming capability, you can disable all programming related
// commands. You might want to do that if you are using an Arduino UNO and still want
// to use EXRAIL automation, as the Uno is lacking in RAM and Flash to run both.
//
// Note this disables all programming functionality, including EXRAIL.
//
// #define DISABLE_PROG
/////////////////////////////////////////////////////////////////////////////////////
// REDEFINE WHERE SHORT/LONG ADDR break is. According to NMRA the last short address
// is 127 and the first long address is 128. There are manufacturers which have

View File

@ -1,169 +0,0 @@
/**********************************************************************
Config.h
COPYRIGHT (c) 2013-2016 Gregg E. Berman
COPYRIGHT (c) 2020 Fred Decker
The configuration file for DCC++ EX Command Station
**********************************************************************/
/////////////////////////////////////////////////////////////////////////////////////
// NOTE: Before connecting these boards and selecting one in this software
// check the quick install guides!!! Some of these boards require a voltage
// generating resitor on the current sense pin of the device. Failure to select
// the correct resistor could damage the sense pin on your Arduino or destroy
// the device.
//
// DEFINE MOTOR_SHIELD_TYPE BELOW ACCORDING TO THE FOLLOWING TABLE:
//
// STANDARD_MOTOR_SHIELD : Arduino Motor shield Rev3 based on the L298 with 18V 2A per channel
// POLOLU_MOTOR_SHIELD : Pololu MC33926 Motor Driver (not recommended for prog track)
// FUNDUMOTO_SHIELD : Fundumoto Shield, no current sensing (not recommended, no short protection)
// FIREBOX_MK1 : The Firebox MK1
// FIREBOX_MK1S : The Firebox MK1S
// |
// +-----------------------v
//
// #define STANDARD_MOTOR_SHIELD F("STANDARD_MOTOR_SHIELD"),
// new MotorDriver(3, 12, UNUSED_PIN, 9, A0, 0.488, 1500, UNUSED_PIN),
// new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 0.488, 1500, UNUSED_PIN)
#define MOTOR_SHIELD_TYPE STANDARD_MOTOR_SHIELD
/////////////////////////////////////////////////////////////////////////////////////
//
// The IP port to talk to a WIFI or Ethernet shield.
//
#define IP_PORT 2560
/////////////////////////////////////////////////////////////////////////////////////
//
// NOTE: Only supported on Arduino Mega
// Set to false if you not even want it on the Arduino Mega
//
//#define ENABLE_WIFI true
/////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE WiFi Parameters (only in effect if WIFI is on)
//
// If DONT_TOUCH_WIFI_CONF is set, all WIFI config will be done with
// the <+> commands and this sketch will not change anything over
// AT commands and the other WIFI_* defines below do not have any effect.
//#define DONT_TOUCH_WIFI_CONF
//
// WIFI_SSID is the network name IF you want to use your existing home network.
// Do NOT change this if you want to use the WiFi in Access Point (AP) mode.
//
// If you do NOT set the WIFI_SSID, the WiFi chip will first try
// to connect to the previously configured network and if that fails
// fall back to Access Point mode. The SSID of the AP will be
// automatically set to DCCEX_*.
//
// Your SSID may not conain ``"'' (double quote, ASCII 0x22).
#define WIFI_SSID "Your network name"
//
// WIFI_PASSWORD is the network password for your home network or if
// you want to change the password from default AP mode password
// to the AP password you want.
// Your password may not conain ``"'' (double quote, ASCII 0x22).
#define WIFI_PASSWORD "deadcafe"
//
// WIFI_HOSTNAME: You probably don't need to change this
#define WIFI_HOSTNAME "dccex"
//
/////////////////////////////////////////////////////////////////////////////////////
//
// Wifi connect timeout in milliseconds. Default is 14000 (14 seconds). You only need
// to set this if you have an extremely slow Wifi router.
//
#define WIFI_CONNECT_TIMEOUT 14000
/////////////////////////////////////////////////////////////////////////////////////
//
// ENABLE_ETHERNET: Set to true if you have an Arduino Ethernet card (wired). This
// is not for Wifi. You will then need the Arduino Ethernet library as well
//
//#define ENABLE_ETHERNET true
/////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE STATIC IP ADDRESS *OR* COMMENT OUT TO USE DHCP
//
//#define IP_ADDRESS { 192, 168, 1, 31 }
/////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE MAC ADDRESS ARRAY FOR ETHERNET COMMUNICATIONS INTERFACE
//
// Uncomment to use with Ethernet Shields
//
// Ethernet Shields do not have have a MAC address in hardware. There may be one on
// a sticker on the Shield that you should use. Otherwise choose one of the ones below
// Be certain that no other device on your network has this same MAC address!
//
// 52:b8:8a:8e:ce:21
// e3:e9:73:e1:db:0d
// 54:2b:13:52:ac:0c
// NOTE: This is not used with ESP8266 WiFi modules.
//#define MAC_ADDRESS { 0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21 } // MAC address of your networking card found on the sticker on your card or take one from above
//
// #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF }
/////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE LCD SCREEN USAGE BY THE BASE STATION
//
// Note: This feature requires an I2C enabled LCD screen using a Hitachi HD44780
// controller and a PCF8574 based I2C 'backpack',
// OR an I2C Oled screen based on SSD1306 (128x64 or 128x32) controller,
// OR an I2C Oled screen based on SH1106 (132x64) controller.
// To enable, uncomment one of the lines below
// define LCD_DRIVER for I2C LCD address 0x3f,16 cols, 2 rows
//#define LCD_DRIVER {SubBus_4,0x27},20,4
//OR define OLED_DRIVER width,height in pixels (address auto detected)
#if defined(ARDUINO_ARCH_STM32)
#define OLED_DRIVER 0x3c, 128, 64
#else
#define OLED_DRIVER {SubBus_0,0x3c}, 128, 32
#endif
#define SCROLLMODE 1
/////////////////////////////////////////////////////////////////////////////////////
// DISABLE EEPROM
//
// If you do not need the EEPROM at all, you can disable all the code that saves
// data in the EEPROM. You might want to do that if you are in a Arduino UNO
// and want to use the EX-RAIL automation. Otherwise you do not have enough RAM
// to do that. Of course, then none of the EEPROM related commands work.
//
#define DISABLE_EEPROM
/////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE TURNOUTS/ACCESSORIES FOLLOW NORM RCN-213
//
// According to norm RCN-213 a DCC packet with a 1 is closed/straight
// and one with a 0 is thrown/diverging. In DCC++ Classic, and in previous
// versions of DCC++EX, a turnout throw command was implemented in the packet as
// '1' and a close command as '0'. The #define below makes the states
// match with the norm. But we don't want to cause havoc on existent layouts,
// so we define this only for new installations. If you don't want this,
// don't add it to your config.h.
//#define DCC_TURNOUTS_RCN_213
// The following #define likewise inverts the behaviour of the <a> command
// for triggering DCC Accessory Decoders, so that <a addr subaddr 0> generates a
// DCC packet with D=1 (close turnout) and <a addr subaddr 1> generates D=0
// (throw turnout).
//#define DCC_ACCESSORY_RCN_213
/////////////////////////////////////////////////////////////////////////////////////

View File

@ -4,7 +4,8 @@
#include "StringFormatter.h"
#define VERSION "4.2.50"
#define VERSION "4.2.51"
// 4.2.51 - Add DISABLE_PROG to disable programming to save RAM/Flash
// 4.2.50 - Fixes: estop all, turnout eeprom, cab ID check
// 4.2.49 - Exrail SPEED take notice of external direction change
// 4.2.48 - BROADCAST/WITHROTTLE Exrail macros