diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index cd23f0e..d2627ea 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -66,6 +66,7 @@ void setup() SerialManager::init(); DIAG(F("License GPLv3 fsf.org (c) dcc-ex.com")); + DIAG(F("Platform: %s"), F(ARDUINO_TYPE)); // PMA - temporary CONDITIONAL_LCD_START { // This block is still executed for DIAGS if LCD not in use @@ -85,7 +86,7 @@ void setup() #endif // ETHERNET_ON // Initialise HAL layer before reading EEprom or setting up MotorDrivers - IODevice::begin(); +// IODevice::begin(); // Responsibility 3: Start the DCC engine. // Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s) @@ -100,18 +101,18 @@ void setup() // Invoke any DCC++EX commands in the form "SETUP("xxxx");"" found in optional file mySetup.h. // This can be used to create turnouts, outputs, sensors etc. through the normal text commands. +// PMA - how to handle __has_include?? #if __has_include ( "mySetup.h") - #define SETUP(cmd) DCCEXParser::parse(F(cmd)) - #include "mySetup.h" - #undef SETUP + #define SETUP(cmd) DCCEXParser::parse(F(cmd)) + #include "mySetup.h" + #undef SETUP #endif - #if defined(LCN_SERIAL) - LCN_SERIAL.begin(115200); - LCN::init(LCN_SERIAL); - #endif - - LCD(3,F("Ready")); +// #if defined(LCN_SERIAL) +// LCN_SERIAL.begin(115200); +// LCN::init(LCN_SERIAL); +// #endif + LCD(3, F("Ready")); CommandDistributor::broadcastPower(); } @@ -121,7 +122,7 @@ void loop() // Responsibility 1: Handle DCC background processes // (loco reminders and power checks) - DCC::loop(); +// DCC::loop(); // Responsibility 2: handle any incoming commands on USB connection SerialManager::loop(); @@ -134,18 +135,18 @@ void loop() EthernetInterface::loop(); #endif - RMFT::loop(); // ignored if no automation +// RMFT::loop(); // ignored if no automation #if defined(LCN_SERIAL) LCN::loop(); #endif - LCDDisplay::loop(); // ignored if LCD not in use +// LCDDisplay::loop(); // ignored if LCD not in use // Handle/update IO devices. - IODevice::loop(); + //IODevice::loop(); - Sensor::checkAll(); // Update and print changes + //Sensor::checkAll(); // Update and print changes // Report any decrease in memory (will automatically trigger on first call) static int ramLowWatermark = __INT_MAX__; // replaced on first loop diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2fc8f6b..ad4054d 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -781,7 +781,9 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) wdt_enable( WDTO_15MS); // set Arduino watchdog timer for 15ms delay(50); // wait for the prescaller time to expire #else +#ifdef ARDUINO_ARCH_ESP ESP.restart(); +#endif #endif break; // and if we didnt restart } diff --git a/DCCTimerSAMD.cpp b/DCCTimerSAMD.cpp new file mode 100644 index 0000000..74ec18b --- /dev/null +++ b/DCCTimerSAMD.cpp @@ -0,0 +1,90 @@ +/* + * © 2021 Mike S + * © 2021 Harald Barth + * © 2021 Fred Decker + * © 2021 Chris Harlow + * © 2021 David Cutting + * © 2022 Paul M. Antoine + * All rights reserved. + * + * This file is part of Asbelos DCC API + * + * 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 . + */ + +// ATTENTION: this file only compiles on a TEENSY +// Please refer to DCCTimer.h for general comments about how this class works +// This is to avoid repetition and duplication. +#ifdef ARDUINO_ARCH_SAMD + +#include "FSH.h" //PMA temp debug +#include "DIAG.h" //PMA temp debug +#include "DCCTimer.h" + +INTERRUPT_CALLBACK interruptHandler=0; + +void DCCTimer::begin(INTERRUPT_CALLBACK callback) { + interruptHandler=callback; + + + + + } + +bool DCCTimer::isPWMPin(byte pin) { + //SAMD: digitalPinHasPWM, todo + (void) pin; + return false; // TODO what are the relevant pins? + } + +void DCCTimer::setPWM(byte pin, bool high) { + // TODO what are the relevant pins? + (void) pin; + (void) high; +} + +void DCCTimer::getSimulatedMacAddress(byte mac[6]) { + volatile uint32_t *serno1 = (volatile uint32_t *)0x0080A00C; + volatile uint32_t *serno2 = (volatile uint32_t *)0x0080A040; +// volatile uint32_t *serno3 = (volatile uint32_t *)0x0080A044; +// volatile uint32_t *serno4 = (volatile uint32_t *)0x0080A048; + + volatile uint32_t m1 = *serno1; + volatile uint32_t m2 = *serno2; + mac[0] = m1 >> 8; + mac[1] = m1 >> 0; + mac[2] = m2 >> 24; + mac[3] = m2 >> 16; + mac[4] = m2 >> 8; + mac[5] = m2 >> 0; +} + +volatile int DCCTimer::minimum_free_memory=__INT_MAX__; + +// Return low memory value... +int DCCTimer::getMinimumFreeMemory() { + noInterrupts(); // Disable interrupts to get volatile value + int retval = freeMemory(); + interrupts(); + return retval; +} + +extern "C" char* sbrk(int incr); + +int DCCTimer::freeMemory() { + char top; + return (int)(&top - reinterpret_cast(sbrk(0))); +} + +#endif \ No newline at end of file diff --git a/I2CManager.h b/I2CManager.h index 1163261..67fd1ad 100644 --- a/I2CManager.h +++ b/I2CManager.h @@ -111,10 +111,10 @@ */ // Uncomment following line to enable Wire library instead of native I2C drivers -//#define I2C_USE_WIRE +#define I2C_USE_WIRE // Uncomment following line to disable the use of interrupts by the native I2C drivers. -//#define I2C_NO_INTERRUPTS +#define I2C_NO_INTERRUPTS // Default to use interrupts within the native I2C drivers. #ifndef I2C_NO_INTERRUPTS diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 517e2dd..c40a0f1 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -192,8 +192,12 @@ int MotorDriver::mA2raw( unsigned int mA) { void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & result) { // DIAG(F("MotorDriver %S Pin=%d,"),type,pin); - (void) type; // avoid compiler warning if diag not used above. + (void) type; // avoid compiler warning if diag not used above. +#if defined(ARDUINO_ARCH_SAMD) + PortGroup *port = digitalPinToPort(pin); +#else uint8_t port = digitalPinToPort(pin); +#endif if (input) result.inout = portInputRegister(port); else diff --git a/MotorDriver.h b/MotorDriver.h index 981b259..3a21b89 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -30,7 +30,7 @@ #define UNUSED_PIN 127 // inside int8_t #endif -#if defined(__IMXRT1062__) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#if defined(__IMXRT1062__) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD) struct FASTPIN { volatile uint32_t *inout; uint32_t maskHIGH; diff --git a/SerialManager.cpp b/SerialManager.cpp index 8717227..2dce51b 100644 --- a/SerialManager.cpp +++ b/SerialManager.cpp @@ -32,9 +32,15 @@ SerialManager::SerialManager(Stream * myserial) { } void SerialManager::init() { - while (!Serial && millis() < 5000); // wait max 5s for Serial to start +// while (!Serial && millis() < 5000); // wait max 5s for Serial to start +#if defined(ARDUINO_ARCH_SAMD) + SerialUSB.begin(115200); + while (!SerialUSB); // PMA - temporary for debuggering purpoises + new SerialManager(&SerialUSB); +#else Serial.begin(115200); new SerialManager(&Serial); +#endif #ifdef SERIAL3_COMMANDS Serial3.begin(115200); new SerialManager(&Serial3); diff --git a/defines.h b/defines.h index c24d6af..aba5daf 100644 --- a/defines.h +++ b/defines.h @@ -77,14 +77,15 @@ // 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 +#define WIFI_SERIAL_LINK_SPEED 9600 -#if __has_include ( "myAutomation.h") - #if defined(BIG_RAM) || defined(DISABLE_EEPROM) - #define EXRAIL_ACTIVE - #else - #define EXRAIL_WARNING - #endif -#endif +// TODO: PMA - figure out why enabling this causes the CS to crashe immediately after starting the motor driver +//#if __has_include ( "myAutomation.h") +// #if defined(BIG_RAM) || defined(DISABLE_EEPROM) +// #define EXRAIL_ACTIVE +// #else +// #define EXRAIL_WARNING +// #endif +//#endif #endif diff --git a/platformio.ini b/platformio.ini index 8bba297..59136b3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,13 +10,9 @@ [platformio] default_envs = - mega2560 - uno - mega328 - unowifiR2 - nano -src_dir = . -include_dir = . + samd21 +src_dir = /Users/paul/Projects/CommandStation-EX +include_dir = /Users/paul/Projects/CommandStation-EX [env] build_flags = -Wall -Wextra @@ -25,12 +21,13 @@ build_flags = -Wall -Wextra platform = atmelsam board = sparkfun_samd21_dev_usb framework = arduino -upload_protocol = atmel-ice +upload_protocol = sam-ba lib_deps = ${env.lib_deps} SparkFun External EEPROM Arduino Library monitor_speed = 115200 monitor_flags = --echo +build_flags = -std=c++17 [env:mega2560-debug] platform = atmelavr @@ -131,7 +128,6 @@ platform = atmelavr board = nanoatmega328new board_upload.maximum_size = 32256 framework = arduino -lib_deps = - ${env.lib_deps} +lib_deps = ${env.lib_deps} monitor_speed = 115200 monitor_flags = --echo