diff --git a/.gitignore b/.gitignore index 1f24578..c8e40c2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,14 @@ Release/* .vscode/ config.h .vscode/* -mySetup.h +# mySetup.h mySetup.cpp myHal.cpp -myAutomation.h +# myAutomation.h myFilter.cpp -myAutomation.h -myFilter.cpp -myLayout.h +# myAutomation.h +# myLayout.h +my*.h +!my*.example.h .vscode/extensions.json .vscode/extensions.json diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 5342c6d..cbb152e 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -81,6 +81,7 @@ const int16_t HASH_KEYWORD_A='A'; const int16_t HASH_KEYWORD_C='C'; const int16_t HASH_KEYWORD_R='R'; const int16_t HASH_KEYWORD_T='T'; +const int16_t HASH_KEYWORD_X='X'; const int16_t HASH_KEYWORD_LCN = 15137; const int16_t HASH_KEYWORD_HAL = 10853; const int16_t HASH_KEYWORD_SHOW = -21309; @@ -732,15 +733,7 @@ bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[]) switch (params) { case 0: // list turnout definitions - { - bool gotOne = false; - for (Turnout *tt = Turnout::first(); tt != NULL; tt = tt->next()) - { - gotOne = true; - tt->print(stream); - } - return gotOne; // will if none found - } + return Turnout::printAll(stream); // will if none found case 1: // delete turnout if (!Turnout::remove(p[0])) @@ -761,12 +754,19 @@ bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[]) case HASH_KEYWORD_T: state= false; break; - default: - return false; // Invalid parameter + case HASH_KEYWORD_X: + { + Turnout *tt = Turnout::get(p[0]); + if (tt) { + tt->print(stream); + return true; + } + return false; + } + default: // Invalid parameter + return false; } if (!Turnout::setClosed(p[0], state)) return false; - - return true; } diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index a8f8984..3e45ae8 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -120,9 +120,9 @@ void DCCTimer::reset() { } #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) -#define NUM_ADC_INPUTS 7 -#else #define NUM_ADC_INPUTS 15 +#else +#define NUM_ADC_INPUTS 7 #endif uint16_t ADCee::usedpins = 0; int * ADCee::analogvals = NULL; diff --git a/DCCTimerMEGAAVR.cpp b/DCCTimerMEGAAVR.cpp index be9248e..2b2bdab 100644 --- a/DCCTimerMEGAAVR.cpp +++ b/DCCTimerMEGAAVR.cpp @@ -1,4 +1,5 @@ /* + * © 2022 Paul M. Antoine * © 2021 Mike S * © 2021 Harald Barth * © 2021 Fred Decker @@ -124,5 +125,31 @@ void DCCTimer::reset() { while(true){} } +int16_t ADCee::ADCmax() { + return 4095; +} +int ADCee::init(uint8_t pin) { + return analogRead(pin); +} +/* + * Read function ADCee::read(pin) to get value instead of analogRead(pin) + */ +int ADCee::read(uint8_t pin, bool fromISR) { + int current; + if (!fromISR) noInterrupts(); + current = analogRead(pin); + if (!fromISR) interrupts(); + return current; +} +/* + * Scan function that is called from interrupt + */ +void ADCee::scan() { +} + +void ADCee::begin() { + noInterrupts(); + interrupts(); +} #endif diff --git a/DCCTimerTEENSY.cpp b/DCCTimerTEENSY.cpp index a8f97f1..0619e21 100644 --- a/DCCTimerTEENSY.cpp +++ b/DCCTimerTEENSY.cpp @@ -141,4 +141,31 @@ void DCCTimer::reset() { SCB_AIRCR = 0x05FA0004; } +int16_t ADCee::ADCmax() { + return 4095; +} + +int ADCee::init(uint8_t pin) { + return analogRead(pin); +} +/* + * Read function ADCee::read(pin) to get value instead of analogRead(pin) + */ +int ADCee::read(uint8_t pin, bool fromISR) { + int current; + if (!fromISR) noInterrupts(); + current = analogRead(pin); + if (!fromISR) interrupts(); + return current; +} +/* + * Scan function that is called from interrupt + */ +void ADCee::scan() { +} + +void ADCee::begin() { + noInterrupts(); + interrupts(); +} #endif diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index f8c6146..8dd4d31 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -1,6 +1,7 @@ /* + * © 2022 Bruno Sanches * © 2021 Fred Decker - * © 2020-2021 Harald Barth + * © 2020-2022 Harald Barth * © 2020-2021 Chris Harlow * © 2020 Gregor Baues * All rights reserved. @@ -36,8 +37,13 @@ EthernetInterface * EthernetInterface::singleton=NULL; */ void EthernetInterface::setup() { - singleton=new EthernetInterface(); - if (!singleton->connected) singleton=NULL; + if (singleton!=NULL) { + DIAG(F("Prog Error!")); + return; + } + if ((singleton=new EthernetInterface())) + return; + DIAG(F("Ethernet not initialized")); }; @@ -54,45 +60,41 @@ EthernetInterface::EthernetInterface() connected=false; #ifdef IP_ADDRESS - Ethernet.begin(mac, IP_ADDRESS); + if (Ethernet.begin(mac, IP_ADDRESS) == 0) #else if (Ethernet.begin(mac) == 0) + #endif { DIAG(F("Ethernet.begin FAILED")); return; } - #endif - DIAG(F("begin OK.")); - if (Ethernet.hardwareStatus() == EthernetNoHardware) { - DIAG(F("Ethernet shield not found")); - return; + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + DIAG(F("Ethernet shield not found or W5100")); } unsigned long startmilli = millis(); - while ((millis() - startmilli) < 5500) // Loop to give time to check for cable connection - { + while ((millis() - startmilli) < 5500) { // Loop to give time to check for cable connection if (Ethernet.linkStatus() == LinkON) break; DIAG(F("Ethernet waiting for link (1sec) ")); delay(1000); } + // now we either do have link of we have a W5100 + // where we do not know if we have link. That's + // the reason to now run checkLink. + // CheckLinks sets up outboundRing if it does + // not exist yet as well. + checkLink(); +} - if (Ethernet.linkStatus() == LinkOFF) { - DIAG(F("Ethernet cable not connected")); - return; - } - - connected=true; - - IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address - - server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT - server->begin(); - - LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); - LCD(5,F("Port:%d"), IP_PORT); - - outboundRing=new RingStream(OUTBOUND_RING_SIZE); +/** + * @brief Cleanup any resources + * + * @return none + */ +EthernetInterface::~EthernetInterface() { + delete server; + delete outboundRing; } /** @@ -101,33 +103,70 @@ EthernetInterface::EthernetInterface() */ void EthernetInterface::loop() { - if (!singleton) return; + if (!singleton || (!singleton->checkLink())) + return; - switch (Ethernet.maintain()) - { + switch (Ethernet.maintain()) { case 1: //renewed fail DIAG(F("Ethernet Error: renewed fail")); singleton=NULL; return; - case 3: //rebind fail DIAG(F("Ethernet Error: rebind fail")); singleton=NULL; return; - default: //nothing happened break; } - singleton->loop2(); - } - void EthernetInterface::loop2() -{ +/** + * @brief Checks ethernet link cable status and detects when it connects / disconnects + * + * @return true when cable is connected, false otherwise + */ +bool EthernetInterface::checkLink() { + if (Ethernet.linkStatus() != LinkOFF) { // check for not linkOFF instead of linkON as the W5100 does return LinkUnknown + //if we are not connected yet, setup a new server + if(!connected) { + DIAG(F("Ethernet cable connected")); + connected=true; + IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address + server = new EthernetServer(IP_PORT); // Ethernet Server listening on default port IP_PORT + server->begin(); + LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); + LCD(5,F("Port:%d"), IP_PORT); + // only create a outboundRing it none exists, this may happen if the cable + // gets disconnected and connected again + if(!outboundRing) + outboundRing=new RingStream(OUTBOUND_RING_SIZE); + } + return true; + } else { // connected + DIAG(F("Ethernet cable disconnected")); + connected=false; + //clean up any client + for (byte socket = 0; socket < MAX_SOCK_NUM; socket++) { + if(clients[socket].connected()) + clients[socket].stop(); + } + // tear down server + delete server; + server = nullptr; + LCD(4,F("IP: None")); + } + return false; +} + +void EthernetInterface::loop2() { + if (!outboundRing) { // no idea to call loop2() if we can't handle outgoing data in it + if (Diag::ETHERNET) DIAG(F("No outboundRing")); + return; + } // get client from the server EthernetClient client = server->accept(); @@ -182,7 +221,9 @@ void EthernetInterface::loop() // handle at most 1 outbound transmission int socketOut=outboundRing->read(); - if (socketOut>=0) { + if (socketOut >= MAX_SOCK_NUM) { + DIAG(F("Ethernet outboundRing socket=%d error"), socketOut); + } else if (socketOut >= 0) { int count=outboundRing->count(); if (Diag::ETHERNET) DIAG(F("Ethernet reply socket=%d, count=:%d"), socketOut,count); for(;count>0;count--) clients[socketOut].write(outboundRing->read()); diff --git a/EthernetInterface.h b/EthernetInterface.h index e79996d..8078c3f 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -56,15 +56,16 @@ class EthernetInterface { static void loop(); private: - static EthernetInterface * singleton; - bool connected; - EthernetInterface(); - void loop2(); - EthernetServer * server; + static EthernetInterface * singleton; + bool connected; + EthernetInterface(); + ~EthernetInterface(); + void loop2(); + bool checkLink(); + EthernetServer * server = NULL; 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 uint8_t buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv - RingStream * outboundRing; - + RingStream * outboundRing = NULL; }; #endif diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index a025a4e..e870d25 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "PORTX-HAL-cursense2-202210192255Z" +#define GITHUB_SHA "devel-202211071020Z" diff --git a/MotorDrivers.h b/MotorDrivers.h index a7d3bc5..328d5e6 100644 --- a/MotorDrivers.h +++ b/MotorDrivers.h @@ -183,6 +183,6 @@ new MotorDriver( 3, 12, UNUSED_PIN, 9, A0, 2.99, 1500, UNUSED_PIN), \ new MotorDriver(11, 13, UNUSED_PIN, 8, A1, 2.99, 1500, UNUSED_PIN), \ new MotorDriver( 2, 10, UNUSED_PIN, 7, A3, 2.99, 1500, UNUSED_PIN), \ - new MotorDriver(10, 4, UNUSED_PIN, 6, A4, 2.99, 1500, UNUSED_PIN) + new MotorDriver( 5, 4, UNUSED_PIN, 6, A4, 2.99, 1500, UNUSED_PIN) // #endif diff --git a/Turnouts.h b/Turnouts.h index b181709..7c40bde 100644 --- a/Turnouts.h +++ b/Turnouts.h @@ -171,9 +171,14 @@ public: // Save all turnout definitions static void store(); #endif - static void printAll(Print *stream) { + static bool printAll(Print *stream) { + bool gotOne=false; for (Turnout *tt = _firstTurnout; tt != 0; tt = tt->_nextTurnout) - if (!tt->isHidden()) StringFormatter::send(stream, F("\n"),tt->getId(), tt->isThrown()); + if (!tt->isHidden()) { + gotOne=true; + StringFormatter::send(stream, F("\n"),tt->getId(), tt->isThrown()); + } + return gotOne; } diff --git a/version.h b/version.h index 7851c43..43e48e9 100644 --- a/version.h +++ b/version.h @@ -5,6 +5,7 @@ #define VERSION "4.2.4" +// Ethernet start improvement and link detection // 4.2.4 ESP32 experimental BT support // More DC configurations possible and lower frequency // Handle decoders that do not ack at write better