From 32f1d7d890d44b0d99297de1fdbb589698a15ee9 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 25 Sep 2020 22:14:20 +0200 Subject: [PATCH 01/11] Make all Wifi code disappear if Wifi is not enabled. --- CommandStation-EX.ino | 11 ++++------- DCCEXParser.cpp | 9 ++++++--- WifiInterface.cpp | 7 +++++-- WifiInterface.h | 9 ++++++--- defines.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 defines.h diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index 21487f9..6613d9e 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -12,16 +12,13 @@ // REFER TO SEPARATE EXAMPLE. //////////////////////////////////////////////////////////////////////////////////// -// This defines the speed at which the Arduino will communicate with the ESP8266 module. -// Currently only Arduino Mega and 115200 is supported. -#define WIFI_SERIAL_LINK_SPEED 115200 - #include "config.h" +#include "defines.h" #include "DCC.h" #include "DIAG.h" #include "DCCEXParser.h" #include "version.h" -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#ifdef WIFI_ON #include "WifiInterface.h" #endif #if ENABLE_FREE_MEM_WARNING @@ -169,7 +166,7 @@ void setup() DIAG(F("\n===== DCC::getLocoId has returned, but the callback wont be executed until we are in loop() ======\n")); #endif -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#ifdef WIFI_ON bool wifiUp = false; const __FlashStringHelper *wifiESSID = F(WIFI_SSID); const __FlashStringHelper *wifiPassword = F(WIFI_PASSWORD); @@ -215,7 +212,7 @@ void loop() serialParser.loop(Serial); // Responsibility 3: Optionally handle any incoming WiFi traffic -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#ifdef WIFI_ON WifiInterface::loop(); #endif diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 8b26da7..282237b 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1,7 +1,8 @@ /* * © 2020, Chris Harlow. All rights reserved. + * © 2020, Harald Barth. * - * This file is part of Asbelos DCC API + * This file is part of CommandStation-EX * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,11 +17,13 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ +#include "config.h" +#include "defines.h" #include "StringFormatter.h" #include "DCCEXParser.h" #include "DCC.h" #include "DCCWaveform.h" -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#ifdef WIFI_ON #include "WifiInterface.h" #endif #include "Turnouts.h" @@ -391,7 +394,7 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking) DIAG(F("Setting loco %d F%d %S"), p[0], p[1], p[2] ? F("ON") : F("OFF")); DCC::setFn(p[0], p[1], p[2] == 1); return; -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#ifdef WIFI_ON case '+': // Complex Wifi interface command (not usual parse) WifiInterface::ATCommand(com); return; diff --git a/WifiInterface.cpp b/WifiInterface.cpp index 9ea5738..6dcacae 100644 --- a/WifiInterface.cpp +++ b/WifiInterface.cpp @@ -1,7 +1,8 @@ /* © 2020, Chris Harlow. All rights reserved. + © 2020, Harald Barth. - This file is part of Asbelos DCC API + This file is part of CommandStation-EX This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,8 +18,9 @@ along with CommandStation. If not, see . */ +#include "WifiInterface.h" /* config.h and defines.h included here */ +#ifdef WIFI_ON /* from config.h and defines.h */ #include -#include "WifiInterface.h" #include "DIAG.h" #include "StringFormatter.h" #include "WiThrottle.h" @@ -400,3 +402,4 @@ void WifiInterface::loop() { loopTimeoutStart = millis(); loopstate = 10; // non-blocking loop waits for > before sending } +#endif // WIFI_ON diff --git a/WifiInterface.h b/WifiInterface.h index 003ef2d..fbfde77 100644 --- a/WifiInterface.h +++ b/WifiInterface.h @@ -1,7 +1,8 @@ /* * © 2020, Chris Harlow. All rights reserved. + * © 2020, Harald Barth. * - * This file is part of Asbelos DCC API + * This file is part of CommandStation-EX * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,9 +17,11 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ - #ifndef WifiInterface_h #define WifiInterface_h +#include "config.h" +#include "defines.h" +#ifdef WIFI_ON #include "DCCEXParser.h" #include "MemStream.h" @@ -55,5 +58,5 @@ private: static byte buffer[MAX_WIFI_BUFFER + 1]; static MemStream streamer; }; - +#endif // WIFI_ON #endif diff --git a/defines.h b/defines.h new file mode 100644 index 0000000..8279b8b --- /dev/null +++ b/defines.h @@ -0,0 +1,35 @@ +/* + © 2020, Harald Barth. + + This file is part of CommandStation-EX + + This is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + It is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with CommandStation. If not, see . + +*/ + +//////////////////////////////////////////////////////////////////////////////// +// +// WIFI_ON: All prereqs for running with WIFI are met +// +#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#define WIFI_ON +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// This defines the speed at which the Arduino will communicate with the ESP8266 module. +// Currently only devices which can communicate at 115200 are supported. +// +#define WIFI_SERIAL_LINK_SPEED 115200 + From 6035e4d9ad615bee68c04142acd52551f3e694b6 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 25 Sep 2020 22:27:37 +0200 Subject: [PATCH 02/11] Set preamblebits main to 16 and remove all preamble config from config.h --- DCCWaveform.h | 2 +- config.example.h | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/DCCWaveform.h b/DCCWaveform.h index 96e5887..b1c6f7d 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -30,7 +30,7 @@ const int MIN_ACK_PULSE_DURATION = 2000; const int MAX_ACK_PULSE_DURATION = 8500; -const int PREAMBLE_BITS_MAIN = 20; +const int PREAMBLE_BITS_MAIN = 16; const int PREAMBLE_BITS_PROG = 22; diff --git a/config.example.h b/config.example.h index 33845f4..d8fd4ba 100644 --- a/config.example.h +++ b/config.example.h @@ -110,17 +110,6 @@ The configuration file for DCC++ EX Command Station #define SHOW_CONFIG_DETAIL_PIN A2 -///////////////////////////////////////////////////////////////////////////////////// -// -// PREAMBLE_MAIN: Length of the preamble on the main track. Per standard this should -// be at least 14 bits but if some equipment wants to insert a RailCom -// cutout this should be at least 16 bits. -// PERAMBLE_PROG: Length of the preamble on the programming track. Per standard this -// should be at least 22 bits - -#define PREAMBLE_MAIN 16 // TODO: Finish configurable preamble code -#define PREAMBLE_PROG 22 - ///////////////////////////////////////////////////////////////////////////////////// // // DEFINE LCD SCREEN USAGE BY THE BASE STATION From bff7555102f52ef5debb423c27ce16b0ba0603ce Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Fri, 25 Sep 2020 22:49:53 +0200 Subject: [PATCH 03/11] NUM_SERIAL tells us how many serial lines to check --- CommandStation-EX.ino | 6 +++++- defines.h | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index 6613d9e..e9b33eb 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -175,17 +175,21 @@ void setup() Serial1.begin(WIFI_SERIAL_LINK_SPEED); wifiUp = WifiInterface::setup(Serial1, wifiESSID, wifiPassword, dccex, port); +#if NUM_SERIAL > 1 if (!wifiUp) { Serial2.begin(WIFI_SERIAL_LINK_SPEED); wifiUp = WifiInterface::setup(Serial2, wifiESSID, wifiPassword, dccex, port); } +#if NUM_SERIAL > 2 if (!wifiUp) { Serial3.begin(WIFI_SERIAL_LINK_SPEED); wifiUp = WifiInterface::setup(Serial3, wifiESSID, wifiPassword, dccex, port); } -#endif +#endif // >2 +#endif // >1 +#endif // WIFI_ON // Responsibility 3: Start the DCC engine. // Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s) diff --git a/defines.h b/defines.h index 8279b8b..700687b 100644 --- a/defines.h +++ b/defines.h @@ -33,3 +33,13 @@ // #define WIFI_SERIAL_LINK_SPEED 115200 +//////////////////////////////////////////////////////////////////////////////// +// +// Figure out number of serial ports depending on hardware +// +#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)) +#define NUM_SERIAL 3 +#endif +#ifndef NUM_SERIAL +#define NUM_SERIAL 1 +#endif From 59d77f2362cb60a550618333c769ff8edbebff5c Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 08:42:24 +0100 Subject: [PATCH 04/11] Remove unnecessary #iddefs These are only avoiding files that alrerady self-destruct... so they don't need to be avoided. --- CommandStation-EX.ino | 11 ++--------- DCCEXParser.cpp | 2 -- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index e9b33eb..36b4660 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -18,17 +18,8 @@ #include "DIAG.h" #include "DCCEXParser.h" #include "version.h" -#ifdef WIFI_ON #include "WifiInterface.h" -#endif -#if ENABLE_FREE_MEM_WARNING -#include "freeMemory.h" -int ramLowWatermark = 32767; // This figure gets overwritten dynamically in loop() -#endif - -#if defined(ARDUINO_ARCH_MEGAAVR) #include -#endif @@ -222,6 +213,8 @@ void loop() // Optionally report any decrease in memory (will automatically trigger on first call) #if ENABLE_FREE_MEM_WARNING + static int ramLowWatermark = 32767; // replaced on first loop + int freeNow = freeMemory(); if (freeNow < ramLowWatermark) { diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 282237b..7433576 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -23,9 +23,7 @@ #include "DCCEXParser.h" #include "DCC.h" #include "DCCWaveform.h" -#ifdef WIFI_ON #include "WifiInterface.h" -#endif #include "Turnouts.h" #include "Outputs.h" #include "Sensors.h" From 411a6b1130ba15230401a85388b3a3e93eabeab3 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 08:49:51 +0100 Subject: [PATCH 05/11] Move bulk includes out of .ino I left config.h in the .ino so it shows the user that this will be necessary. --- CommandStation-EX.ino | 10 +--------- DCCEX.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 DCCEX.h diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index 36b4660..cba919c 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -13,15 +13,7 @@ //////////////////////////////////////////////////////////////////////////////////// #include "config.h" -#include "defines.h" -#include "DCC.h" -#include "DIAG.h" -#include "DCCEXParser.h" -#include "version.h" -#include "WifiInterface.h" -#include - - +#include "DCCEX.h" //////////////////////////////////////////////////////////////// diff --git a/DCCEX.h b/DCCEX.h new file mode 100644 index 0000000..fd118ce --- /dev/null +++ b/DCCEX.h @@ -0,0 +1,15 @@ +// This include is intended to visually simplify the .ino for the end users. +// If there were any #ifdefs required they are much better handled in here. + +#ifndef DCCEX_h +#define DCCEX_h + +#include "defines.h" +#include "DCC.h" +#include "DIAG.h" +#include "DCCEXParser.h" +#include "version.h" +#include "WifiInterface.h" +#include + +#endif From 162c7e6e11c1550b12835e709f53ac4a50b0641c Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 09:40:49 +0100 Subject: [PATCH 06/11] UNTESTED Reduce #ifdef hell on wifi This fix to the structure of the Wifi code alows for a better link optimisation and so it is no longer necessary for the wifi code or header to read values from the config.h file. Compilation shows that >11Kb of code is eliminated by the linker if the setup and loop are not called. ~including the interface does not really change anything --- WifiInterface.cpp | 34 ++++++++++++++++------------------ WifiInterface.h | 7 +------ 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/WifiInterface.cpp b/WifiInterface.cpp index 6dcacae..4d9a7e3 100644 --- a/WifiInterface.cpp +++ b/WifiInterface.cpp @@ -19,7 +19,6 @@ */ #include "WifiInterface.h" /* config.h and defines.h included here */ -#ifdef WIFI_ON /* from config.h and defines.h */ #include #include "DIAG.h" #include "StringFormatter.h" @@ -41,7 +40,7 @@ unsigned long WifiInterface::loopTimeoutStart = 0; int WifiInterface::datalength = 0; int WifiInterface::connectionId; byte WifiInterface::buffer[MAX_WIFI_BUFFER+1]; -MemStream WifiInterface::streamer(buffer, MAX_WIFI_BUFFER); +MemStream * WifiInterface::streamer; Stream * WifiInterface::wifiStream = NULL; HTTP_CALLBACK WifiInterface::httpCallback = 0; @@ -60,7 +59,7 @@ bool WifiInterface::setup(Stream & setupStream, const __FlashStringHelper* SSid StringFormatter::send(wifiStream, F("ATE0\r\n")); // turn off the echo checkForOK(200, OK_SEARCH, true); } - + streamer=new MemStream(buffer, MAX_WIFI_BUFFER); DIAG(F("\n++ Wifi Setup %S ++\n"), connected ? F("OK") : F("FAILED")); return connected; } @@ -300,15 +299,15 @@ void WifiInterface::loop() { case 6: // reading for length if (ch == ':') loopstate = (datalength == 0) ? 99 : 7; // 99 is getout without reading next char else datalength = datalength * 10 + (ch - '0'); - streamer.flush(); // basically sets write point at start of buffer + streamer->flush(); // basically sets write point at start of buffer break; case 7: // reading data - streamer.write(ch); // NOTE: The MemStream will throw away bytes that do not fit in the buffer. + streamer->write(ch); // NOTE: The MemStream will throw away bytes that do not fit in the buffer. // This protects against buffer overflows even with things as innocent // as a browser which send massive, irrlevent HTTP headers. datalength--; if (datalength == 0) { - buffer[streamer.available()]='\0'; // mark end of buffer, so it can be used as a string later + buffer[streamer->available()]='\0'; // mark end of buffer, so it can be used as a string later loopstate = 99; } break; @@ -351,8 +350,8 @@ void WifiInterface::loop() { loopstate = 1; } if (ch == 'K') { // assume its in SEND OK - if (Diag::WIFI) DIAG(F("\n\n Wifi BUSY RETRYING.. AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available()); - StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available()); + if (Diag::WIFI) DIAG(F("\n\n Wifi BUSY RETRYING.. AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available()); + StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available()); loopTimeoutStart = millis(); loopstate = 10; // non-blocking loop waits for > before sending break; @@ -365,7 +364,7 @@ void WifiInterface::loop() { // AT this point we have read an incoming message into the buffer if (Diag::WIFI) DIAG(F("\n%l Wifi(%d)<-[%e]\n"), millis(),connectionId, buffer); - streamer.setBufferContentPosition(0, 0); // reset write position to start of buffer + streamer->setBufferContentPosition(0, 0); // reset write position to start of buffer // SIDE EFFECT WARNING::: // We know that parser will read the entire buffer before starting to write to it. // Otherwise we would have to copy the buffer elsewhere and RAM is in short supply. @@ -374,18 +373,18 @@ void WifiInterface::loop() { // Intercept HTTP requests if (isHTTP()) { - if (httpCallback) httpCallback(&streamer, buffer); + if (httpCallback) httpCallback(streamer, buffer); else { StringFormatter::send(streamer, F("HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnnection: close\n\n")); StringFormatter::send(streamer, F("This is not a web server.
")); } closeAfter = true; } - else if (buffer[0] == '<') parser.parse(&streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async + else if (buffer[0] == '<') parser.parse(streamer, buffer, true); // tell JMRI parser that ACKS are blocking because we can't handle the async - else WiThrottle::getThrottle(connectionId)->parse(streamer, buffer); + else WiThrottle::getThrottle(connectionId)->parse(*streamer, buffer); - if (streamer.available() == 0) { + if (streamer->available() == 0) { // No reply if (closeAfter) { if (Diag::WIFI) DIAG(F("AT+CIPCLOSE=%d\r\n"), connectionId); @@ -395,11 +394,10 @@ void WifiInterface::loop() { return; } // prepare to send reply - buffer[streamer.available()]='\0'; // mark end of buffer, so it can be used as a string later - if (Diag::WIFI) DIAG(F("%l WiFi(%d)->[%e] l(%d)\n"), millis(), connectionId, buffer, streamer.available()); - if (Diag::WIFI) DIAG(F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available()); - StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer.available()); + buffer[streamer->available()]='\0'; // mark end of buffer, so it can be used as a string later + if (Diag::WIFI) DIAG(F("%l WiFi(%d)->[%e] l(%d)\n"), millis(), connectionId, buffer, streamer->available()); + if (Diag::WIFI) DIAG(F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available()); + StringFormatter::send(wifiStream, F("AT+CIPSEND=%d,%d\r\n"), connectionId, streamer->available()); loopTimeoutStart = millis(); loopstate = 10; // non-blocking loop waits for > before sending } -#endif // WIFI_ON diff --git a/WifiInterface.h b/WifiInterface.h index fbfde77..ecf9005 100644 --- a/WifiInterface.h +++ b/WifiInterface.h @@ -19,12 +19,8 @@ */ #ifndef WifiInterface_h #define WifiInterface_h -#include "config.h" -#include "defines.h" -#ifdef WIFI_ON #include "DCCEXParser.h" #include "MemStream.h" - #include #include @@ -56,7 +52,6 @@ private: static unsigned long loopTimeoutStart; static const byte MAX_WIFI_BUFFER = 250; static byte buffer[MAX_WIFI_BUFFER + 1]; - static MemStream streamer; + static MemStream * streamer; }; -#endif // WIFI_ON #endif From 36e6c3cd48ad24a46d6bd54976d07d938622797c Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 10:54:11 +0100 Subject: [PATCH 07/11] Decouple WifiInterface from Parser This removes the need for WifiInterfrace <+> command processing to be included in the link. so parser does not need to see the config settings for wifi. If Wifi doesnt set the At command callback, parser will return for a <+> command --- DCCEXParser.cpp | 19 ++++++++++++------- DCCEXParser.h | 3 +++ WifiInterface.cpp | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 7433576..82cd9d9 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -17,13 +17,10 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ -#include "config.h" -#include "defines.h" #include "StringFormatter.h" #include "DCCEXParser.h" #include "DCC.h" #include "DCCWaveform.h" -#include "WifiInterface.h" #include "Turnouts.h" #include "Outputs.h" #include "Sensors.h" @@ -157,10 +154,15 @@ int DCCEXParser::splitValues(int result[MAX_PARAMS], const byte *cmd) } FILTER_CALLBACK DCCEXParser::filterCallback = 0; +AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0; void DCCEXParser::setFilter(FILTER_CALLBACK filter) { filterCallback = filter; } +void DCCEXParser::setAtCommandCallback(AT_COMMAND_CALLBACK callback) +{ + atCommandCallback = callback; +} // See documentation on DCC class for info on this section void DCCEXParser::parse(Print *stream, byte *com, bool blocking) @@ -392,11 +394,14 @@ void DCCEXParser::parse(Print *stream, byte *com, bool blocking) DIAG(F("Setting loco %d F%d %S"), p[0], p[1], p[2] ? F("ON") : F("OFF")); DCC::setFn(p[0], p[1], p[2] == 1); return; -#ifdef WIFI_ON + case '+': // Complex Wifi interface command (not usual parse) - WifiInterface::ATCommand(com); - return; -#endif + if (atCommandCallback) { + atCommandCallback(com); + return; + } + break; + default: //anything else will diagnose and drop out to DIAG(F("\nOpcode=%c params=%d\n"), opcode, params); for (int i = 0; i < params; i++) diff --git a/DCCEXParser.h b/DCCEXParser.h index e154ff9..5721f6c 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -21,6 +21,7 @@ #include typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int p[]); +typedef void (*AT_COMMAND_CALLBACK)(const byte * command); struct DCCEXParser { @@ -29,6 +30,7 @@ struct DCCEXParser void parse(Print * stream, byte * command, bool blocking); void flush(); static void setFilter(FILTER_CALLBACK filter); + static void setAtCommandCallback(AT_COMMAND_CALLBACK filter); static const int MAX_PARAMS=10; // Must not exceed this private: @@ -59,6 +61,7 @@ struct DCCEXParser static void callback_Vbit(int result); static void callback_Vbyte(int result); static FILTER_CALLBACK filterCallback; + static AT_COMMAND_CALLBACK atCommandCallback; static void funcmap(int cab, byte value, byte fstart, byte fstop); }; diff --git a/WifiInterface.cpp b/WifiInterface.cpp index 4d9a7e3..f027ea0 100644 --- a/WifiInterface.cpp +++ b/WifiInterface.cpp @@ -60,6 +60,8 @@ bool WifiInterface::setup(Stream & setupStream, const __FlashStringHelper* SSid checkForOK(200, OK_SEARCH, true); } streamer=new MemStream(buffer, MAX_WIFI_BUFFER); + parser.setAtCommandCallback(ATCommand); + DIAG(F("\n++ Wifi Setup %S ++\n"), connected ? F("OK") : F("FAILED")); return connected; } From c3e17fcf04b993ca26e47e500b8c7ed6a453008f Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 12:01:00 +0100 Subject: [PATCH 08/11] Add EthernetInterface (UNTESTED, UNCALLED) Thanks to Gregor....I have modified his originals to eliminate the static initialisation memory loss. These do not show up in the object code if they are not referenced. --- DCCEX.h | 2 + EthernetInterface.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++ EthernetInterface.h | 107 +++++++++++++++ objdump.bat | 10 +- 4 files changed, 419 insertions(+), 4 deletions(-) create mode 100644 EthernetInterface.cpp create mode 100644 EthernetInterface.h diff --git a/DCCEX.h b/DCCEX.h index fd118ce..091bd47 100644 --- a/DCCEX.h +++ b/DCCEX.h @@ -10,6 +10,8 @@ #include "DCCEXParser.h" #include "version.h" #include "WifiInterface.h" +#include "EthernetInterface.h" + #include #endif diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp new file mode 100644 index 0000000..3498871 --- /dev/null +++ b/EthernetInterface.cpp @@ -0,0 +1,304 @@ +/* + * © 2020,Gregor Baues, Chris Harlow. All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + * + * Ethernet Interface added by Gregor Baues + */ + +#include "EthernetInterface.h" +#include "DIAG.h" +#include "StringFormatter.h" + +//#include +#include +#include + + +// Support Functions +/** + * @brief Aquire IP Address from DHCP; if that fails try a statically configured address + * + * @return true + * @return false + */ +bool EthernetInterface::setupConnection() +{ + + singleton=this; + + DIAG(F("\nInitialize Ethernet with DHCP:")); + server = EthernetServer(LISTEN_PORT); // Ethernet Server listening on default port LISTEN_PORT + ip = IPAddress(IP_ADDRESS); // init with fixed IP address needed to get to the server + connected = false; // Connection status + streamer= new MemStream(buffer, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true); // streamer who writes the results to the buffer + + if (Ethernet.begin(EthernetInterface::mac) == 0) + { + DIAG(F("\nFailed to configure Ethernet using DHCP ... Trying with fixed IP")); + Ethernet.begin(EthernetInterface::mac, EthernetInterface::ip); // default ip address + + if (Ethernet.hardwareStatus() == EthernetNoHardware) + { + DIAG(F("\nEthernet shield was not found. Sorry, can't run without hardware. :(")); + return false; + }; + if (Ethernet.linkStatus() == LinkOFF) + { + DIAG(F("\nEthernet cable is not connected.")); + return false; + } + } + + ip = Ethernet.localIP(); // reassign the obtained ip address + + DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]); + DIAG(F("\nListening on port: [%d]"), port); + dnsip = Ethernet.dnsServerIP(); + DIAG(F("\nDNS server IP address: [%d.%d.%d.%d] "), ip[0], ip[1], ip[2], ip[3]); + return true; +} + +/** + * @brief Handles command requests recieved via UDP. UDP is a connection less, unreliable protocol as it doesn't maintain state but fast. + * + */ + void EthernetInterface::udpHandler() { + singleton->udpHandler2(); + } + void EthernetInterface::udpHandler2() +{ + + int packetSize = Udp.parsePacket(); + if (packetSize) + { + DIAG(F("\nReceived packet of size:[%d]\n"), packetSize); + IPAddress remote = Udp.remoteIP(); + DIAG(F("From: [%d.%d.%d.%d:"), remote[0], remote[1], remote[2], remote[3]); + char portBuffer[6]; + DIAG(F("%s]\n"), utoa(Udp.remotePort(), portBuffer, 10)); // DIAG has issues with unsigend int's so go through utoa + + // read the packet into packetBufffer + Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); + + DIAG(F("Command: [%s]\n"), packetBuffer); + + streamer->flush(); + + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + + ethParser.parse(streamer, (byte *)packetBuffer, true); // set to true so it is sync cf. WifiInterface + + if (streamer->available() == 0) + { + DIAG(F("\nNo response\n")); + } + else + { + // send the reply + DIAG(F("Response: %s\n"), (char *)buffer); + Udp.write((char *)buffer); + Udp.endPacket(); + } + + memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); // reset PacktBuffer + return; + } +} + +/** + * @brief Handles command requests recieved via TCP. Supports up to the max# of simultaneous requests which is 8. The connection gets closed as soon as we finished processing + * + */ + void EthernetInterface::tcpHandler() +{ + singleton->tcpHandler2(); +} + void EthernetInterface::tcpHandler2() +{ + // get client from the server + EthernetClient client = getServer().accept(); + + // check for new client + if (client) + { + for (byte i = 0; i < MAX_SOCK_NUM; i++) + { + if (!clients[i]) + { + // On accept() the EthernetServer doesn't track the client anymore + // so we store it in our client array + clients[i] = client; + break; + } + } + } + + // check for incoming data from all possible clients + for (byte i = 0; i < MAX_SOCK_NUM; i++) + { + if (clients[i] && clients[i].available() > 0) + { + // read bytes from a client + int count = clients[i].read(buffer, MAX_ETH_BUFFER); + buffer[count] = '\0'; // terminate the string properly + DIAG(F("\nReceived packet of size:[%d]\n"), count); + DIAG(F("From Client #: [%d]\n"), i); + DIAG(F("Command: [%s]\n"), buffer); + + // as we use buffer for recv and send we have to reset the write position + streamer->setBufferContentPosition(0, 0); + + ethParser.parse(streamer, buffer, true); // set to true to that the execution in DCC is sync + + if (streamer->available() == 0) + { + DIAG(F("No response\n")); + } + else + { + buffer[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later + DIAG(F("Response: %s\n"), (char *)buffer); + if (clients[i].connected()) + { + clients[i].write(buffer, streamer->available()); + } + } + } + // stop any clients which disconnect + for (byte i = 0; i < MAX_SOCK_NUM; i++) + { + if (clients[i] && !clients[i].connected()) + { + DIAG(F("Disconnect client #%d \n"), i); + clients[i].stop(); + } + } + } +} + +// Class Functions +/** + * @brief Setup Ethernet Connection + * + * @param pt Protocol used + * @param localPort Port number for the connection + */ +void EthernetInterface::setup(protocolType pt, uint16_t localPort) +{ + DIAG(F("\n++++++ Ethernet Setup In Progress ++++++++\n")); + port = localPort; + if (setupConnection()) + { + DIAG(F("\nProtocol: [%s]\n"), pt ? "UDP" : "TCP"); + switch (pt) + { + case UDP: + { + if (Udp.begin(localPort)) + { + connected = true; + protocolHandler = udpHandler; + } + else + { + DIAG(F("\nUDP client failed to start")); + connected = false; + } + break; + }; + case TCP: + { + Ethernet.begin(mac, ip); + EthernetServer server(localPort); + setServer(server); + server.begin(); + connected = true; + protocolHandler = tcpHandler; + break; + }; + default: + { + DIAG(F("Unkown Ethernet protocol; Setup failed")); + connected = false; + return; + } + } + } + else + { + connected = false; + }; + DIAG(F("\n++++++ Ethernet Setup %S ++++++++\n"), connected ? F("OK") : F("FAILED")); +}; + +/** + * @brief Setup Ethernet on default port and user choosen protocol + * + * @param pt Protocol UDP or TCP + */ +void EthernetInterface::setup(protocolType pt) +{ + setup(pt, LISTEN_PORT); +}; + +/** + * @brief Ethernet setup with defaults TCP / Listen Port + * + */ +void EthernetInterface::setup() +{ + setup(TCP, LISTEN_PORT); +} + +/** + * @brief Main loop for the EthernetInterface + * + */ +void EthernetInterface::loop() +{ + switch (Ethernet.maintain()) + { + case 1: + //renewed fail + DIAG(F("\nError: renewed fail")); + break; + + case 2: + //renewed success + DIAG(F("\nRenewed success: ")); + ip = Ethernet.localIP(); // reassign the obtained ip address + DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"),ip[0], ip[1], ip[2], ip[3]); + break; + + case 3: + //rebind fail + DIAG(F("Error: rebind fail")); + break; + + case 4: + //rebind success + DIAG(F("Rebind success")); + ip = Ethernet.localIP(); // reassign the obtained ip address + DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]); + break; + + default: + //nothing happened + break; + } + protocolHandler(); +} diff --git a/EthernetInterface.h b/EthernetInterface.h new file mode 100644 index 0000000..b702f04 --- /dev/null +++ b/EthernetInterface.h @@ -0,0 +1,107 @@ +/* + * © 2020,Gregor Baues, Chris Harlow. All rights reserved. + * + * This file is part of DCC-EX/CommandStation-EX + * + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + * + * Ethernet Interface added by Gregor Baues + */ + +#ifndef EthernetInterface_h +#define EthernetInterface_h + +#include "DCCEXParser.h" +#include "MemStream.h" +#include +#include +#include + +/* some generated mac addresses as EthernetShields don't have one by default in HW. + * Sometimes they come on a sticker on the EthernetShield then use this address otherwise + * just choose one from below or generate one yourself. Only condition is that there is no + * other device on your network with the same Mac address. + * + * 52:b8:8a:8e:ce:21 + * e3:e9:73:e1:db:0d + * 54:2b:13:52:ac:0c + * c2:d8:d4:7d:7c:cb + * 86:cf:fa:9f:07:79 + */ + +/** + * @brief Network Configuration + * + */ +#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 IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one; make sure + // this one is not used elsewhere and corresponds to your network layout +#define LISTEN_PORT 3366 // default listen port for the server +#define MAX_ETH_BUFFER 250 + +typedef void (*HTTP_CALLBACK)(Print * stream, byte * cmd); + +enum protocolType { + TCP, + UDP +}; + +typedef void (*protocolCallback)(); + +class EthernetInterface { + +private: + EthernetServer server; + + public: + DCCEXParser ethParser; + bool connected; + byte mac[6]; + IPAddress ip; + uint16_t port; + IPAddress dnsip; + + void setup(protocolType pt, uint16_t lp); // specific port nummber + void setup(protocolType pt); // uses default port number + void setup(); // all defaults (protocol/port) + + protocolCallback protocolHandler; + + void loop(); + + private: + static EthernetInterface * singleton; + + char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming UDP packet, + uint8_t buffer[MAX_ETH_BUFFER]; // buffer provided to the streamer to be filled with the reply (used by TCP also for the recv) + MemStream * streamer; // streamer who writes the results to the buffer + EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield + + bool setupConnection(); + static void udpHandler(); + static void tcpHandler(); + void udpHandler2(); + void tcpHandler2(); + EthernetUDP Udp; + + EthernetServer getServer() { + return server; + }; + void setServer(EthernetServer s) { + server = s; + }; +}; + +#endif diff --git a/objdump.bat b/objdump.bat index bee2d0f..af30cb5 100644 --- a/objdump.bat +++ b/objdump.bat @@ -1,12 +1,14 @@ ECHO ON FOR /F "delims=" %%i IN ('dir %TMP%\arduino_build_* /b /ad-h /t:c /od') DO SET a=%%i echo Most recent subfolder: %a% >%TMP%\OBJDUMP_%a%.txt -avr-objdump --private=mem-usage %TMP%\%a%\DCCEX.ino.elf >>%TMP%\OBJDUMP_%a%.txt +SET ELF=%TMP%\%a%\CommandStation-EX.ino.elf + +avr-objdump --private=mem-usage %ELF% >>%TMP%\OBJDUMP_%a%.txt ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt -avr-objdump -x -C %TMP%\%a%\DCCEX.ino.elf | find ".text" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt +avr-objdump -x -C %ELF% | find ".text" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt -avr-objdump -x -C %TMP%\%a%\DCCEX.ino.elf | find ".data" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt +avr-objdump -x -C %ELF% | find ".data" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt ECHO ++++++++++++++++++++++++++++++++++ >>%TMP%\OBJDUMP_%a%.txt -avr-objdump -x -C %TMP%\%a%\DCC.ino.elf | find ".bss" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt +avr-objdump -x -C %ELF% | find ".bss" | sort /+25 /R >>%TMP%\OBJDUMP_%a%.txt notepad %TMP%\OBJDUMP_%a%.txt EXIT From 38fe65fcca3057c17e940249fb5405925d34e6d7 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 26 Sep 2020 16:29:11 +0100 Subject: [PATCH 09/11] Drop advanced feature samples from basic ino --- CommandStation-EX.ino | 88 +++---------------------------------------- 1 file changed, 6 insertions(+), 82 deletions(-) diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index cba919c..5f1f87e 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -2,14 +2,11 @@ // © 2020, Chris Harlow. All rights reserved. // // This file is a demonstattion of setting up a DCC-EX -// Command station to support direct connection of WiThrottle devices +// Command station with optional support for direct connection of WiThrottle devices // such as "Engine Driver". If you contriol your layout through JMRI // then DON'T connect throttles to this wifi, connect them to JMRI. // -// This is just 3 statements longer than the basic setup. -// -// THIS SETUP DOES NOT APPLY TO ARDUINO UNO WITH ONLY A SINGLE SERIAL PORT. -// REFER TO SEPARATE EXAMPLE. +// THE WIFI FEATURE IS NOT SUPPORTED ON ARDUINO DEVICES WITH ONLY 2KB RAM. //////////////////////////////////////////////////////////////////////////////////// #include "config.h" @@ -28,74 +25,14 @@ LiquidCrystal_I2C lcdDisplay = LiquidCrystal_I2C(LCD_ADDRESS, LCD_COLUMNS, LCD_L #endif #endif -// this code is here to demonstrate use of the DCC API and other techniques - -// myFilter is an example of an OPTIONAL command filter used to intercept < > commands from -// the usb or wifi streamm. It demonstrates how a command may be intercepted -// or even a new command created without having to break open the API library code. -// The filter is permitted to use or modify the parameter list before passing it on to -// the standard parser. By setting the opcode to 0, the standard parser will -// just ignore the command on the assumption that you have already handled it. -// -// The filter must be enabled by calling the DCC EXParser::setFilter method, see use in setup(). -#if ENABLE_CUSTOM_FILTER -void myComandFilter(Print *stream, byte &opcode, byte ¶mCount, int p[]) -{ - (void)stream; // avoid compiler warning if we don't access this parameter - switch (opcode) - { - case '!': // Create a bespoke new command to clear all loco reminders or specific locos e.g - if (paramCount == 0) - DCC::forgetAllLocos(); - else - for (int i = 0; i < paramCount; i++) - DCC::forgetLoco(p[i]); - opcode = 0; // tell parser to ignore this command as we have done it already - break; - default: // drop through and parser will use the command unaltered. - break; - } -} - -// This is an OPTIONAL example of a HTTP filter... -// If you have configured wifi and an HTTP request is received on the Wifi connection -// it will normally be rejected 404 Not Found. - -// If you wish to handle HTTP requests, you can create a filter and ask the WifiInterface to -// call your code for each detected http request. - -void myHttpFilter(Print *stream, byte *cmd) -{ - (void)cmd; // Avoid compiler warning because this example doesnt use this parameter - - // BEWARE - As soon as you start responding, the cmd buffer is trashed! - // You must get everything you need from it before using StringFormatter::send! - - StringFormatter::send(stream, F("HTTP/1.1 200 OK\nContent-Type: text/html\nConnnection: close\n\n")); - StringFormatter::send(stream, F("This is my HTTP filter responding.
")); -} -#endif - -// Callback functions are necessary if you call any API that must wait for a response from the -// programming track. The API must return immediately otherwise other loop() functions would be blocked. -// Your callback function will be invoked when the data arrives from the prog track. -// See the DCC:getLocoId example in the setup function. -#if ENABLE_CUSTOM_CALLBACK -void myCallback(int result) -{ - DIAG(F("\n getting Loco Id callback result=%d"), result); -} -#endif - -// Create a serial command parser... Enables certain diagnostics and commands -// to be issued from the USB serial console -// This is NOT intended for JMRI.... - +// Create a serial command parser for the USB connection, +// This supports JMRI or manual diagnostics and commands +// to be issued from the USB serial console. DCCEXParser serialParser; void setup() { - + //////////////////////////////////////////// // // More display stuff. Need to put this in a .h file and make @@ -136,19 +73,6 @@ void setup() // NOTE: References to Serial1 are for the serial port used to connect // your wifi chip/shield. -// Optionally tell the command parser to use my example filter. -// This will intercept JMRI commands from both USB and Wifi -#if ENABLE_CUSTOM_FILTER - DCCEXParser::setFilter(myComandFilter); -#endif - -#if ENABLE_CUSTOM_CALLBACK - // This is just for demonstration purposes - DIAG(F("\n===== DCCEX demonstrating DCC::getLocoId() call ==========\n")); - DCC::getLocoId(myCallback); // myCallback will be called with the result - DIAG(F("\n===== DCC::getLocoId has returned, but the callback wont be executed until we are in loop() ======\n")); -#endif - #ifdef WIFI_ON bool wifiUp = false; const __FlashStringHelper *wifiESSID = F(WIFI_SSID); From 79201a911c101b5a69668af82666f7260314a7d0 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 26 Sep 2020 22:28:29 +0200 Subject: [PATCH 10/11] fix objdump.sh --- objdump.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/objdump.sh b/objdump.sh index 2e18af2..6e8e7d3 100755 --- a/objdump.sh +++ b/objdump.sh @@ -4,9 +4,10 @@ ARDUINOBIN=$(ls -l $(type -p arduino)| awk '{print $NF ; exit 0}') PATH=$(dirname "$ARDUINOBIN")/hardware/tools/avr/bin:$PATH -avr-objdump --private=mem-usage /tmp/arduino_build_233823/Blinkhabaplus.ino.elf +LASTBUILD=$(ls -tr /tmp/arduino_build_*/*.ino.elf | tail -1) +avr-objdump --private=mem-usage "$LASTBUILD" for segment in .text .data .bss ; do echo '++++++++++++++++++++++++++++++++++' - avr-objdump -x -C /tmp/arduino_build_233823/Blinkhabaplus.ino.elf | awk '$2 == "'$segment'" && $3 != 0 {print $3,$2} ; $4 == "'$segment'" && $5 != 0 { print $5,$6}' | sort -r + avr-objdump -x -C "$LASTBUILD" | awk '$2 == "'$segment'" && $3 != 0 {print $3,$2} ; $4 == "'$segment'" && $5 != 0 { print $5,$6}' | sort -r done From 00202e7966596db1561d6ddf6f372275dd68b73e Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 26 Sep 2020 22:56:35 +0200 Subject: [PATCH 11/11] remove unused configs --- config.example.h | 66 ++++++++---------------------------------------- 1 file changed, 10 insertions(+), 56 deletions(-) diff --git a/config.example.h b/config.example.h index d8fd4ba..bb3e302 100644 --- a/config.example.h +++ b/config.example.h @@ -15,23 +15,18 @@ The configuration file for DCC++ EX Command Station // the correct resistor could damage the sense pin on your Arduino or destroy // the device. // -// DEFINE MOTOR_SHIELD_TYPE ACCORDING TO THE FOLLOWING TABLE: +// 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 // -// STANDARD_MOTOR_SHIELD = ARDUINO MOTOR SHIELD (MAX 18V/2A PER CHANNEL) Arduino Motor shield Rev3 based on the L298 -// POLOLU_MOTOR_SHIELD = POLOLU MC33926 MOTOR SHIELD (MAX 28V/2.5 PER CHANNEL) Pololu MC33926 Motor Driver (shield or carrier) -// FUNDUMOTO_SHIELD = FunduMoto Motor Shield -// FIREBOX_MK1 = Firebox MK1 -// FIREBOX_MK1S = Firebox MK1S - - #define MOTOR_SHIELD_TYPE STANDARD_MOTOR_SHIELD -///////////////////////////////////////////////////////////////////////////////////// -// -// DEFINE PROGRAM TRACK CURRENT LIMIT IN MILLIAMPS - -#define TRIP_CURRENT_PROG 250 - ///////////////////////////////////////////////////////////////////////////////////// // // The IP port to talk to a WIFI or Ethernet shield. @@ -57,7 +52,6 @@ The configuration file for DCC++ EX Command Station // // DEFINE STATIC IP ADDRESS *OR* COMMENT OUT TO USE DHCP // - //#define IP_ADDRESS { 192, 168, 1, 200 } ///////////////////////////////////////////////////////////////////////////////////// @@ -67,49 +61,9 @@ The configuration file for DCC++ EX Command Station // Uncomment to use with Ethernet Shields // // NOTE: This is not used with ESP8266 WiFi modules. - +// // #define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF } -///////////////////////////////////////////////////////////////////////////////////// -// -// Allows using a pin as a trigger for a scope or analyzer so we can capture only -// the important parts of the data stream -// -// USE_TRIGGERPIN: Enable code that switches the trigger pin on and off at end -// of the preamble. This takes some clock cycles in the -// interrupt routine for the main track. -// USE_TRIGGERPIN_PER_BIT: As above but for every bit. This only makes sense -// if USE_TRIGGERPIN is set. -// -// The value of the TRIGGERPIN is defined in DCCppEX.h because it might -// be board specific -// -//#define USE_TRIGGERPIN -//#define USE_TRIGGERPIN_PER_BIT - -///////////////////////////////////////////////////////////////////////////////////// -// -// Define only of you need the store to EEPROM feature. This takes RAM and -// you may need to use less MAX_MAIN_REGISTERS to compensate (at least on the UNO) - -#define EESTORE - -///////////////////////////////////////////////////////////////////////////////////// -// -// This shows the status and version at startup. This takes RAM. You can comment -// this line if you need to increase MAX_MAIN_REGISTERS(at least on the UNO) - -#define SHOWCONFIG - -///////////////////////////////////////////////////////////////////////////////////// -// -// This is different from the above config display which only shows one line at startup -// This defines a pin that when jumpered to ground before powering up the Arduinio, -// will display more detailed settings for diagnostics. You must remove the jumper and -// restart the Arduino to return to normal operation - -#define SHOW_CONFIG_DETAIL_PIN A2 - ///////////////////////////////////////////////////////////////////////////////////// // // DEFINE LCD SCREEN USAGE BY THE BASE STATION