From 8141311e6672c28d82a922e82ac61cd2692053b3 Mon Sep 17 00:00:00 2001 From: Mike S Date: Thu, 25 Mar 2021 13:16:12 -0400 Subject: [PATCH 1/8] Revisions to support Teensy 3.x and Teensy 4.x --- DCC.cpp | 12 ++++---- DCC.h | 16 +++++----- DCCEXParser.cpp | 75 ++++++++++++++++++++++----------------------- DCCEXParser.h | 38 +++++++++++------------ DCCTimer.cpp | 57 ++++++++++++++++++++++++++++++++-- DCCTimer.h | 4 +++ DCCWaveform.cpp | 2 ++ EthernetInterface.h | 8 +++-- MotorDriver.h | 8 +++++ defines.h | 4 +-- 10 files changed, 147 insertions(+), 77 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index 241103b..f8c9c92 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -480,31 +480,31 @@ const ackOp FLASH LONG_LOCO_ID_PROG[] = { FAIL }; -void DCC::writeCVByte(int cv, byte byteValue, ACK_CALLBACK callback) { +void DCC::writeCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback) { ackManagerSetup(cv, byteValue, WRITE_BYTE_PROG, callback); } -void DCC::writeCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) { +void DCC::writeCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) { if (bitNum >= 8) callback(-1); else ackManagerSetup(cv, bitNum, bitValue?WRITE_BIT1_PROG:WRITE_BIT0_PROG, callback); } -void DCC::verifyCVByte(int cv, byte byteValue, ACK_CALLBACK callback) { +void DCC::verifyCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback) { ackManagerSetup(cv, byteValue, VERIFY_BYTE_PROG, callback); } -void DCC::verifyCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) { +void DCC::verifyCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) { if (bitNum >= 8) callback(-1); else ackManagerSetup(cv, bitNum, bitValue?VERIFY_BIT1_PROG:VERIFY_BIT0_PROG, callback); } -void DCC::readCVBit(int cv, byte bitNum, ACK_CALLBACK callback) { +void DCC::readCVBit(int16_t cv, byte bitNum, ACK_CALLBACK callback) { if (bitNum >= 8) callback(-1); else ackManagerSetup(cv, bitNum,READ_BIT_PROG, callback); } -void DCC::readCV(int cv, ACK_CALLBACK callback) { +void DCC::readCV(int16_t cv, ACK_CALLBACK callback) { ackManagerSetup(cv, 0,READ_CV_PROG, callback); } diff --git a/DCC.h b/DCC.h index aa4451f..a224fb9 100644 --- a/DCC.h +++ b/DCC.h @@ -23,7 +23,7 @@ #include "MotorDrivers.h" #include "FSH.h" -typedef void (*ACK_CALLBACK)(int result); +typedef void (*ACK_CALLBACK)(int16_t result); enum ackOp : byte { // Program opcodes for the ack Manager @@ -86,12 +86,12 @@ public: static void setProgTrackBoost(bool on); // when true, special prog track current limit does not apply // ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1 - static void readCV(int cv, ACK_CALLBACK callback); - static void readCVBit(int cv, byte bitNum, ACK_CALLBACK callback); // -1 for error - static void writeCVByte(int cv, byte byteValue, ACK_CALLBACK callback); - static void writeCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback); - static void verifyCVByte(int cv, byte byteValue, ACK_CALLBACK callback); - static void verifyCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback); + static void readCV(int16_t cv, ACK_CALLBACK callback); + static void readCVBit(int16_t cv, byte bitNum, ACK_CALLBACK callback); // -1 for error + static void writeCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback); + static void writeCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback); + static void verifyCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback); + static void verifyCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback); static void getLocoId(ACK_CALLBACK callback); static void setLocoId(int id,ACK_CALLBACK callback); @@ -168,6 +168,8 @@ private: #define ARDUINO_TYPE "MEGA" #elif defined(ARDUINO_ARCH_MEGAAVR) #define ARDUINO_TYPE "MEGAAVR" +#elif defined(TEENSYDUINO) +#define ARDUINO_TYPE "TEENSY" #else #error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560 #endif diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 9b174bc..2b75479 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -34,29 +34,26 @@ // 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 int HASH_KEYWORD_PROG = -29718; -const int HASH_KEYWORD_MAIN = 11339; -const int HASH_KEYWORD_JOIN = -30750; -const int HASH_KEYWORD_CABS = -11981; -const int HASH_KEYWORD_RAM = 25982; -const int HASH_KEYWORD_CMD = 9962; -const int HASH_KEYWORD_WIT = 31594; -const int HASH_KEYWORD_WIFI = -5583; -const int HASH_KEYWORD_ACK = 3113; -const int HASH_KEYWORD_ON = 2657; -const int HASH_KEYWORD_DCC = 6436; -const int HASH_KEYWORD_SLOW = -17209; -const int HASH_KEYWORD_PROGBOOST = -6353; -const int HASH_KEYWORD_EEPROM = -7168; -const int HASH_KEYWORD_LIMIT = 27413; -const int HASH_KEYWORD_ETHERNET = -30767; -const int HASH_KEYWORD_MAX = 16244; -const int HASH_KEYWORD_MIN = 15978; -const int HASH_KEYWORD_LCN = 15137; -const int HASH_KEYWORD_RESET = 26133; +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; +const int16_t HASH_KEYWORD_WIT = 31594; +const int16_t HASH_KEYWORD_WIFI = -5583; +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; +const int16_t HASH_KEYWORD_PROGBOOST = -6353; +const int16_t HASH_KEYWORD_EEPROM = -7168; +const int16_t HASH_KEYWORD_LIMIT = 27413; +const int16_t HASH_KEYWORD_ETHERNET = -30767; +const int16_t HASH_KEYWORD_MAX = 16244; +const int16_t HASH_KEYWORD_MIN = 15978; - -int DCCEXParser::stashP[MAX_COMMAND_PARAMS]; +int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS]; bool DCCEXParser::stashBusy; Print *DCCEXParser::stashStream = NULL; @@ -108,16 +105,16 @@ void DCCEXParser::loop(Stream &stream) Sensor::checkAll(&stream); // Update and print changes } -int DCCEXParser::splitValues(int result[MAX_COMMAND_PARAMS], const byte *cmd) +int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd) { byte state = 1; byte parameterCount = 0; - int runningValue = 0; + int16_t runningValue = 0; const byte *remainingCmd = cmd + 1; // skips the opcode bool signNegative = false; // clear all parameters in case not enough found - for (int i = 0; i < MAX_COMMAND_PARAMS; i++) + for (int16_t i = 0; i < MAX_COMMAND_PARAMS; i++) result[i] = 0; while (parameterCount < MAX_COMMAND_PARAMS) @@ -167,15 +164,15 @@ int DCCEXParser::splitValues(int result[MAX_COMMAND_PARAMS], const byte *cmd) return parameterCount; } -int DCCEXParser::splitHexValues(int result[MAX_COMMAND_PARAMS], const byte *cmd) +int16_t DCCEXParser::splitHexValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd) { byte state = 1; byte parameterCount = 0; - int runningValue = 0; + int16_t runningValue = 0; const byte *remainingCmd = cmd + 1; // skips the opcode // clear all parameters in case not enough found - for (int i = 0; i < MAX_COMMAND_PARAMS; i++) + for (int16_t i = 0; i < MAX_COMMAND_PARAMS; i++) result[i] = 0; while (parameterCount < MAX_COMMAND_PARAMS) @@ -257,7 +254,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) (void)EEPROM; // tell compiler not to warn this is unused if (Diag::CMD) DIAG(F("PARSING:%s"), com); - int p[MAX_COMMAND_PARAMS]; + int16_t p[MAX_COMMAND_PARAMS]; while (com[0] == '<' || com[0] == ' ') com++; // strip off any number of < or spaces byte params = splitValues(p, com); @@ -275,9 +272,9 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) return; // filterCallback asked us to ignore case 't': // THROTTLE { - int cab; - int tspeed; - int direction; + int16_t cab; + int16_t tspeed; + int16_t direction; if (params == 4) { // @@ -561,7 +558,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream) StringFormatter::send(stream, F("")); } -bool DCCEXParser::parseZ(Print *stream, int params, int p[]) +bool DCCEXParser::parseZ(Print *stream, int16_t params, int16_t p[]) { switch (params) @@ -605,7 +602,7 @@ bool DCCEXParser::parseZ(Print *stream, int params, int p[]) } //=================================== -bool DCCEXParser::parsef(Print *stream, int params, int p[]) +bool DCCEXParser::parsef(Print *stream, int16_t params, int16_t p[]) { // JMRI sends this info in DCC message format but it's not exactly // convenient for other processing @@ -637,9 +634,9 @@ bool DCCEXParser::parsef(Print *stream, int params, int p[]) return true; } -void DCCEXParser::funcmap(int cab, byte value, byte fstart, byte fstop) +void DCCEXParser::funcmap(int16_t cab, byte value, byte fstart, byte fstop) { - for (int i = fstart; i <= fstop; i++) + for (int16_t i = fstart; i <= fstop; i++) { DCC::setFn(cab, i, value & 1); value >>= 1; @@ -647,7 +644,7 @@ void DCCEXParser::funcmap(int cab, byte value, byte fstart, byte fstop) } //=================================== -bool DCCEXParser::parseT(Print *stream, int params, int p[]) +bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[]) { switch (params) { @@ -690,7 +687,7 @@ bool DCCEXParser::parseT(Print *stream, int params, int p[]) } } -bool DCCEXParser::parseS(Print *stream, int params, int p[]) +bool DCCEXParser::parseS(Print *stream, int16_t params, int16_t p[]) { switch (params) @@ -722,7 +719,7 @@ bool DCCEXParser::parseS(Print *stream, int params, int p[]) return false; } -bool DCCEXParser::parseD(Print *stream, int params, int p[]) +bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) { if (params == 0) return false; diff --git a/DCCEXParser.h b/DCCEXParser.h index 499218a..6953562 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -22,7 +22,7 @@ #include "FSH.h" #include "RingStream.h" -typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int p[]); +typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int16_t p[]); typedef void (*AT_COMMAND_CALLBACK)(const byte * command); struct DCCEXParser @@ -39,18 +39,18 @@ struct DCCEXParser private: - static const int MAX_BUFFER=50; // longest command sent in + static const int16_t MAX_BUFFER=50; // longest command sent in byte bufferLength=0; bool inCommandPayload=false; byte buffer[MAX_BUFFER+2]; - int splitValues( int result[MAX_COMMAND_PARAMS], const byte * command); - int splitHexValues( int result[MAX_COMMAND_PARAMS], const byte * command); + int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command); + int16_t splitHexValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command); - bool parseT(Print * stream, int params, int p[]); - bool parseZ(Print * stream, int params, int p[]); - bool parseS(Print * stream, int params, int p[]); - bool parsef(Print * stream, int params, int p[]); - bool parseD(Print * stream, int params, int p[]); + bool parseT(Print * stream, int16_t params, int16_t p[]); + bool parseZ(Print * stream, int16_t params, int16_t p[]); + bool parseS(Print * stream, int16_t params, int16_t p[]); + bool parsef(Print * stream, int16_t params, int16_t p[]); + bool parseD(Print * stream, int16_t params, int16_t p[]); static Print * getAsyncReplyStream(); static void commitAsyncReplyStream(); @@ -60,19 +60,19 @@ struct DCCEXParser static Print * stashStream; static RingStream * stashRingStream; - static int stashP[MAX_COMMAND_PARAMS]; - bool stashCallback(Print * stream, int p[MAX_COMMAND_PARAMS], RingStream * ringStream); - static void callback_W(int result); - static void callback_B(int result); - static void callback_R(int result); - static void callback_Rloco(int result); - static void callback_Wloco(int result); - static void callback_Vbit(int result); - static void callback_Vbyte(int result); + static int16_t stashP[MAX_COMMAND_PARAMS]; + bool stashCallback(Print * stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream); + static void callback_W(int16_t result); + static void callback_B(int16_t result); + static void callback_R(int16_t result); + static void callback_Rloco(int16_t result); + static void callback_Wloco(int16_t result); + static void callback_Vbit(int16_t result); + static void callback_Vbyte(int16_t result); static FILTER_CALLBACK filterCallback; static FILTER_CALLBACK filterRMFTCallback; static AT_COMMAND_CALLBACK atCommandCallback; - static void funcmap(int cab, byte value, byte fstart, byte fstop); + static void funcmap(int16_t cab, byte value, byte fstart, byte fstop); }; diff --git a/DCCTimer.cpp b/DCCTimer.cpp index 622b798..eb592c7 100644 --- a/DCCTimer.cpp +++ b/DCCTimer.cpp @@ -81,10 +81,63 @@ INTERRUPT_CALLBACK interruptHandler=0; void DCCTimer::getSimulatedMacAddress(byte mac[6]) { memcpy(mac,(void *) &SIGROW.SERNUM0,6); // serial number - mac[0] &= 0xFE; - mac[0] |= 0x02; } +#elif defined(TEENSYDUINO) + IntervalTimer myDCCTimer; + + void DCCTimer::begin(INTERRUPT_CALLBACK callback) { + interruptHandler=callback; + + myDCCTimer.begin(interruptHandler, DCC_SIGNAL_TIME); + + } + + bool DCCTimer::isPWMPin(byte pin) { + //Teensy: digitalPinHasPWM, todo + return false; // TODO what are the relevant pins? + } + + void DCCTimer::setPWM(byte pin, bool high) { + // TODO what are the relevant pins? + } + + void DCCTimer::getSimulatedMacAddress(byte mac[6]) { +#if defined(__IMXRT1062__) //Teensy 4.0 and Teensy 4.1 + uint32_t m1 = HW_OCOTP_MAC1; + uint32_t m2 = HW_OCOTP_MAC0; + mac[0] = m1 >> 8; + mac[1] = m1 >> 0; + mac[2] = m2 >> 24; + mac[3] = m2 >> 16; + mac[4] = m2 >> 8; + mac[5] = m2 >> 0; +#else + read_mac(mac); +#endif +} + +#if !defined(__IMXRT1062__) +void DCCTimer::read_mac(byte mac[6]) { + read(0xe,mac,0); + read(0xf,mac,3); +} + +// http://forum.pjrc.com/threads/91-teensy-3-MAC-address +void DCCTimer::read(uint8_t word, uint8_t *mac, uint8_t offset) { + FTFL_FCCOB0 = 0x41; // Selects the READONCE command + FTFL_FCCOB1 = word; // read the given word of read once area + + // launch command and wait until complete + FTFL_FSTAT = FTFL_FSTAT_CCIF; + while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)); + + *(mac+offset) = FTFL_FCCOB5; // collect only the top three bytes, + *(mac+offset+1) = FTFL_FCCOB6; // in the right orientation (big endian). + *(mac+offset+2) = FTFL_FCCOB7; // Skip FTFL_FCCOB4 as it's always 0. +} +#endif + #else // Arduino nano, uno, mega etc #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) diff --git a/DCCTimer.h b/DCCTimer.h index dfe9ef2..0c3274c 100644 --- a/DCCTimer.h +++ b/DCCTimer.h @@ -10,6 +10,10 @@ class DCCTimer { static void getSimulatedMacAddress(byte mac[6]); static bool isPWMPin(byte pin); static void setPWM(byte pin, bool high); +#if (defined(TEENSYDUINO) && !defined(__IMXRT1062__)) + static void read_mac(byte mac[6]); + static void read(uint8_t word, uint8_t *mac, uint8_t offset); +#endif private: }; diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 8d695e5..c87f768 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -53,8 +53,10 @@ void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) { } void DCCWaveform::loop(bool ackManagerActive) { + noInterrupts(); mainTrack.checkPowerOverload(false); progTrack.checkPowerOverload(ackManagerActive); + interrupts(); } void DCCWaveform::interruptHandler() { diff --git a/EthernetInterface.h b/EthernetInterface.h index 87bb8b6..df6504d 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -31,8 +31,12 @@ #include "DCCEXParser.h" #include #include -#include -#include "RingStream.h" +#if defined (ARDUINO_TEENSY41) + #include //TEENSY Ethernet Treiber + #include +#else + #include "Ethernet.h" +#endif#include "RingStream.h" /** * @brief Network Configuration diff --git a/MotorDriver.h b/MotorDriver.h index 2af1b58..f659918 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -26,11 +26,19 @@ #define UNUSED_PIN 127 // inside int8_t #endif +#if defined(__IMXRT1062__) +struct FASTPIN { + volatile uint32_t *inout; + uint32_t maskHIGH; + uint32_t maskLOW; +}; +#else struct FASTPIN { volatile uint8_t *inout; uint8_t maskHIGH; uint8_t maskLOW; }; +#endif class MotorDriver { public: diff --git a/defines.h b/defines.h index 5c08f01..c3454c1 100644 --- a/defines.h +++ b/defines.h @@ -23,7 +23,7 @@ // WIFI_ON: All prereqs for running with WIFI are met // Note: WIFI_CHANNEL may not exist in early config.h files so is added here if needed. -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) +#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) || defined(Teensyduino) #define WIFI_ON true #ifndef WIFI_CHANNEL #define WIFI_CHANNEL 1 @@ -32,7 +32,7 @@ #define WIFI_ON false #endif -#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) +#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) || defined(Teensyduino) #define ETHERNET_ON true #else #define ETHERNET_ON false From 8e63c452b26ef928301b4de4d01d2bdab4d8df0c Mon Sep 17 00:00:00 2001 From: Mike S Date: Thu, 25 Mar 2021 14:02:33 -0400 Subject: [PATCH 2/8] Fix a few bugs as a result of latest version --- DCCEXParser.cpp | 18 ++++++++------- freeMemory.cpp | 58 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2b75479..21f273a 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -52,6 +52,8 @@ const int16_t HASH_KEYWORD_LIMIT = 27413; const int16_t HASH_KEYWORD_ETHERNET = -30767; const int16_t HASH_KEYWORD_MAX = 16244; const int16_t HASH_KEYWORD_MIN = 15978; +const int16_t HASH_KEYWORD_LCN = 15137; +const int16_t HASH_KEYWORD_RESET = 26133; int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS]; bool DCCEXParser::stashBusy; @@ -795,7 +797,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) } // CALLBACKS must be static -bool DCCEXParser::stashCallback(Print *stream, int p[MAX_COMMAND_PARAMS], RingStream * ringStream) +bool DCCEXParser::stashCallback(Print *stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream) { if (stashBusy ) return false; @@ -820,43 +822,43 @@ void DCCEXParser::commitAsyncReplyStream() { stashBusy = false; } -void DCCEXParser::callback_W(int result) +void DCCEXParser::callback_W(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), stashP[2], stashP[3], stashP[0], result == 1 ? stashP[1] : -1); commitAsyncReplyStream(); } -void DCCEXParser::callback_B(int result) +void DCCEXParser::callback_B(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), stashP[3], stashP[4], stashP[0], stashP[1], result == 1 ? stashP[2] : -1); commitAsyncReplyStream(); } -void DCCEXParser::callback_Vbit(int result) +void DCCEXParser::callback_Vbit(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), stashP[0], stashP[1], result); commitAsyncReplyStream(); } -void DCCEXParser::callback_Vbyte(int result) +void DCCEXParser::callback_Vbyte(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), stashP[0], result); commitAsyncReplyStream(); } -void DCCEXParser::callback_R(int result) +void DCCEXParser::callback_R(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), stashP[1], stashP[2], stashP[0], result); commitAsyncReplyStream(); } -void DCCEXParser::callback_Rloco(int result) +void DCCEXParser::callback_Rloco(int16_t result) { StringFormatter::send(getAsyncReplyStream(), F(""), result); commitAsyncReplyStream(); } -void DCCEXParser::callback_Wloco(int result) +void DCCEXParser::callback_Wloco(int16_t result) { if (result==1) result=stashP[0]; // pick up original requested id from command StringFormatter::send(getAsyncReplyStream(), F(""), result); diff --git a/freeMemory.cpp b/freeMemory.cpp index f640abe..5514e8d 100644 --- a/freeMemory.cpp +++ b/freeMemory.cpp @@ -34,7 +34,7 @@ extern char *__malloc_heap_start; static volatile int minimum_free_memory = __INT_MAX__; - +#if !defined(__IMXRT1062__) static inline int freeMemory() { char top; #if defined(__arm__) @@ -46,6 +46,54 @@ static inline int freeMemory() { #endif } +// Return low memory value. +int minimumFreeMemory() { + byte sreg_save = SREG; + noInterrupts(); // Disable interrupts + int retval = minimum_free_memory; + SREG = sreg_save; // Restore interrupt state + return retval; +} + +#else +#if defined(ARDUINO_TEENSY40) + static const unsigned DTCM_START = 0x20000000UL; + static const unsigned OCRAM_START = 0x20200000UL; + static const unsigned OCRAM_SIZE = 512; + static const unsigned FLASH_SIZE = 1984; +#elif defined(ARDUINO_TEENSY41) + static const unsigned DTCM_START = 0x20000000UL; + static const unsigned OCRAM_START = 0x20200000UL; + static const unsigned OCRAM_SIZE = 512; + static const unsigned FLASH_SIZE = 7936; +#if TEENSYDUINO>151 + extern "C" uint8_t external_psram_size; +#endif +#endif + +static inline int freeMemory() { + extern unsigned long _ebss; + extern unsigned long _sdata; + extern unsigned long _estack; + const unsigned DTCM_START = 0x20000000UL; + unsigned dtcm = (unsigned)&_estack - DTCM_START; + unsigned stackinuse = (unsigned) &_estack - (unsigned) __builtin_frame_address(0); + unsigned varsinuse = (unsigned)&_ebss - (unsigned)&_sdata; + unsigned freemem = dtcm - (stackinuse + varsinuse); + return freemem; +} + +// Return low memory value. +int minimumFreeMemory() { + //byte sreg_save = SREG; + //noInterrupts(); // Disable interrupts + int retval = minimum_free_memory; + //SREG = sreg_save; // Restore interrupt state + return retval; +} +#endif + + // Update low ram level. Allow for extra bytes to be specified // by estimation or inspection, that may be used by other // called subroutines. Must be called with interrupts disabled. @@ -61,11 +109,3 @@ void updateMinimumFreeMemory(unsigned char extraBytes) { if (spare < minimum_free_memory) minimum_free_memory = spare; } -// Return low memory value. -int minimumFreeMemory() { - byte sreg_save = SREG; - noInterrupts(); // Disable interrupts - int retval = minimum_free_memory; - SREG = sreg_save; // Restore interrupt state - return retval; -} From 54773297bf6698f2718b785266e90d809f2d7cb2 Mon Sep 17 00:00:00 2001 From: Mike S Date: Fri, 26 Mar 2021 07:37:17 -0400 Subject: [PATCH 3/8] Minor changes to Arduino Type List & DCCWaveform --- DCC.h | 12 ++++++++++-- DCCWaveform.cpp | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/DCC.h b/DCC.h index a224fb9..c4a6ae3 100644 --- a/DCC.h +++ b/DCC.h @@ -168,8 +168,16 @@ private: #define ARDUINO_TYPE "MEGA" #elif defined(ARDUINO_ARCH_MEGAAVR) #define ARDUINO_TYPE "MEGAAVR" -#elif defined(TEENSYDUINO) -#define ARDUINO_TYPE "TEENSY" +#elif defined(ARDUINO_TEENSY32) +#define ARDUINO_TYPE "TEENSY32" +#elif defined(ARDUINO_TEENSY35) +#define ARDUINO_TYPE "TEENSY35" +#elif defined(ARDUINO_TEENSY36) +#define ARDUINO_TYPE "TEENSY36" +#elif defined(ARDUINO_TEENSY40) +#define ARDUINO_TYPE "TEENSY40" +#elif defined(ARDUINO_TEENSY41) +#define ARDUINO_TYPE "TEENSY41" #else #error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560 #endif diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index c87f768..125bc93 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -52,12 +52,19 @@ void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) { DCCTimer::begin(DCCWaveform::interruptHandler); } +#if defined(TEENSYDUINO) void DCCWaveform::loop(bool ackManagerActive) { noInterrupts(); mainTrack.checkPowerOverload(false); progTrack.checkPowerOverload(ackManagerActive); interrupts(); } +#else +void DCCWaveform::loop(bool ackManagerActive) { + mainTrack.checkPowerOverload(false); + progTrack.checkPowerOverload(ackManagerActive); +} +#endif void DCCWaveform::interruptHandler() { // call the timer edge sensitive actions for progtrack and maintrack From 136e9934185683f71e9c108b537f6c312344264e Mon Sep 17 00:00:00 2001 From: Mike S Date: Sat, 27 Mar 2021 07:17:47 -0400 Subject: [PATCH 4/8] Changed to Continuous analogReads for Teensy --- DCCWaveform.cpp | 17 +++-------------- DCCWaveform.h | 1 + MotorDriver.cpp | 39 +++++++++++++++++++++++++++++++++++++-- MotorDriver.h | 3 +-- WiThrottle.cpp | 2 +- WiThrottle.h | 2 +- 6 files changed, 44 insertions(+), 20 deletions(-) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 125bc93..68549c9 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -24,12 +24,10 @@ #include "DCCTimer.h" #include "DIAG.h" #include "freeMemory.h" - DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true); DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false); - bool DCCWaveform::progTrackSyncMain=false; bool DCCWaveform::progTrackBoosted=false; int DCCWaveform::progTripValue=0; @@ -52,19 +50,10 @@ void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) { DCCTimer::begin(DCCWaveform::interruptHandler); } -#if defined(TEENSYDUINO) -void DCCWaveform::loop(bool ackManagerActive) { - noInterrupts(); - mainTrack.checkPowerOverload(false); - progTrack.checkPowerOverload(ackManagerActive); - interrupts(); -} -#else void DCCWaveform::loop(bool ackManagerActive) { mainTrack.checkPowerOverload(false); progTrack.checkPowerOverload(ackManagerActive); } -#endif void DCCWaveform::interruptHandler() { // call the timer edge sensitive actions for progtrack and maintrack @@ -138,7 +127,7 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) { break; case POWERMODE::ON: // Check current - lastCurrent=motorDriver->getCurrentRaw(); + lastCurrent=motorDriver->getCurrentRaw(isMainTrack); if (lastCurrent < 0) { // We have a fault pin condition to take care of lastCurrent = -lastCurrent; @@ -286,7 +275,7 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea void DCCWaveform::setAckBaseline() { if (isMainTrack) return; - int baseline=motorDriver->getCurrentRaw(); + int baseline=motorDriver->getCurrentRaw(isMainTrack); ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %dus and %dus"), baseline,motorDriver->raw2mA(baseline), @@ -320,7 +309,7 @@ void DCCWaveform::checkAck() { return; } - int current=motorDriver->getCurrentRaw(); + int current=motorDriver->getCurrentRaw(isMainTrack); if (current > ackMaxCurrent) ackMaxCurrent=current; // An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba) diff --git a/DCCWaveform.h b/DCCWaveform.h index f3f26c7..211281b 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -19,6 +19,7 @@ */ #ifndef DCCWaveform_h #define DCCWaveform_h + #include "MotorDriver.h" // Wait times for power management. Unit: milliseconds diff --git a/MotorDriver.cpp b/MotorDriver.cpp index c50615a..7f44cd2 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -20,6 +20,14 @@ #include "MotorDriver.h" #include "DCCTimer.h" #include "DIAG.h" +#if defined(TEENSYDUINO) +#include +#include +ADC *adc = new ADC(); // adc object +#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) +ADC *adc1 = new ADC(); // adc object +#endif +#endif #define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH #define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW @@ -63,6 +71,20 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 senseOffset=analogRead(currentPin); // value of sensor at zero current } +#if defined(TEENSYDUINO) + if(currentPin != current_pin && currentPin!=UNUSED_PIN){ + adc->adc0->setReference(ADC_REFERENCE::REF_3V3); + adc->adc0->startContinuous(currentPin); + } else if(currentPin!=UNUSED_PIN){ +#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) + adc1->adc0->setReference(ADC_REFERENCE::REF_3V3); + adc1->adc0->startContinuous(currentPin); +#else + adc->adc1->setReference(ADC_REFERENCE::REF_3V3); + adc->adc1->startContinuous(currentPin); +#endif + } +#endif faultPin=fault_pin; if (faultPin != UNUSED_PIN) { getFastPin(F("FAULT"),faultPin, 1 /*input*/, fastFaultPin); @@ -137,10 +159,23 @@ bool MotorDriver::canMeasureCurrent() { * senseOffset handles the case where a shield returns values above or below * a central value depending on direction. */ -int MotorDriver::getCurrentRaw() { +int MotorDriver::getCurrentRaw(bool isMain) { if (currentPin==UNUSED_PIN) return 0; - int current = analogRead(currentPin)-senseOffset; + int current; +#if defined(TEENSYDUINO) + if(isMain) { + current = (uint16_t)adc->adc0->analogReadContinuous(); + } else { + #if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) + current = (uint16_t)adc1->adc0->analogReadContinuous(); + #else + current = (uint16_t)adc->adc1->analogReadContinuous(); + #endif + } +#else + current = analogRead(currentPin)-senseOffset; +#endif if (current<0) current=0-current; if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && isHIGH(fastPowerPin)) diff --git a/MotorDriver.h b/MotorDriver.h index f659918..f7d8580 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -47,7 +47,7 @@ class MotorDriver { virtual void setPower( bool on); virtual void setSignal( bool high); virtual void setBrake( bool on); - virtual int getCurrentRaw(); + virtual int getCurrentRaw(bool isMain); virtual unsigned int raw2mA( int raw); virtual int mA2raw( unsigned int mA); inline int getRawCurrentTripValue() { @@ -60,7 +60,6 @@ class MotorDriver { inline byte getFaultPin() { return faultPin; } - private: void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result); void getFastPin(const FSH* type,int pin, FASTPIN & result) { diff --git a/WiThrottle.cpp b/WiThrottle.cpp index ba9198d..f3664a8 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -388,7 +388,7 @@ WiThrottle * WiThrottle::stashInstance; byte WiThrottle::stashClient; char WiThrottle::stashThrottleChar; -void WiThrottle::getLocoCallback(int locoid) { +void WiThrottle::getLocoCallback(int16_t locoid) { stashStream->mark(stashClient); if (locoid<0) StringFormatter::send(stashStream,F("HMNo loco found on prog track\n")); else { diff --git a/WiThrottle.h b/WiThrottle.h index b065d4f..0f9b573 100644 --- a/WiThrottle.h +++ b/WiThrottle.h @@ -67,7 +67,7 @@ class WiThrottle { static WiThrottle * stashInstance; static byte stashClient; static char stashThrottleChar; - static void getLocoCallback(int locoid); + static void getLocoCallback(int16_t locoid); }; #endif From 8839eb293cbe36aabaa9068312870da888861c74 Mon Sep 17 00:00:00 2001 From: Mike S Date: Mon, 29 Mar 2021 13:00:56 -0400 Subject: [PATCH 5/8] Update for T3.x to use SREG analogReads. Still a bunch of commented out code but its a start. --- MotorDriver.cpp | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 7f44cd2..926e8db 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -20,13 +20,14 @@ #include "MotorDriver.h" #include "DCCTimer.h" #include "DIAG.h" -#if defined(TEENSYDUINO) +//#if defined(TEENSYDUINO) +#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) #include #include ADC *adc = new ADC(); // adc object -#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) -ADC *adc1 = new ADC(); // adc object -#endif +//#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) +//ADC *adc1 = new ADC(); // adc object +//#endif #endif #define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH @@ -71,18 +72,19 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 senseOffset=analogRead(currentPin); // value of sensor at zero current } -#if defined(TEENSYDUINO) +//#if defined(TEENSYDUINO) +#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) if(currentPin != current_pin && currentPin!=UNUSED_PIN){ - adc->adc0->setReference(ADC_REFERENCE::REF_3V3); + //adc->adc0->setReference(ADC_REFERENCE::REF_3V3); adc->adc0->startContinuous(currentPin); } else if(currentPin!=UNUSED_PIN){ -#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) - adc1->adc0->setReference(ADC_REFERENCE::REF_3V3); - adc1->adc0->startContinuous(currentPin); -#else - adc->adc1->setReference(ADC_REFERENCE::REF_3V3); +//#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) +// adc1->adc0->setReference(ADC_REFERENCE::REF_3V3); +// adc1->adc0->startContinuous(currentPin); +//#else + //adc->adc1->setReference(ADC_REFERENCE::REF_3V3); adc->adc1->startContinuous(currentPin); -#endif +//#endif } #endif faultPin=fault_pin; @@ -148,6 +150,8 @@ void MotorDriver::setSignal( bool high) { } } +volatile unsigned int overflow_count=0; + bool MotorDriver::canMeasureCurrent() { return currentPin!=UNUSED_PIN; } @@ -163,16 +167,24 @@ int MotorDriver::getCurrentRaw(bool isMain) { if (currentPin==UNUSED_PIN) return 0; int current; -#if defined(TEENSYDUINO) +//#if defined(TEENSYDUINO) +#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) if(isMain) { current = (uint16_t)adc->adc0->analogReadContinuous(); } else { - #if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) - current = (uint16_t)adc1->adc0->analogReadContinuous(); - #else + //#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) + //current = (uint16_t)adc1->adc0->analogReadContinuous(); + //#else current = (uint16_t)adc->adc1->analogReadContinuous(); - #endif + //#endif } +#elif defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36) + unsigned char sreg_backup; + sreg_backup = SREG; /* save interrupt enable/disable state */ + cli(); + current = analogRead(currentPin)-senseOffset; + overflow_count = 0; + SREG = sreg_backup; /* restore interrupt state */ #else current = analogRead(currentPin)-senseOffset; #endif From f5cdd88854e1c711a5eca26f54e84bee80f7dd39 Mon Sep 17 00:00:00 2001 From: Mike S Date: Mon, 29 Mar 2021 15:06:06 -0400 Subject: [PATCH 6/8] Cleanup of extra commented lines --- MotorDriver.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 926e8db..1819ab7 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -20,14 +20,11 @@ #include "MotorDriver.h" #include "DCCTimer.h" #include "DIAG.h" -//#if defined(TEENSYDUINO) + #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) #include #include ADC *adc = new ADC(); // adc object -//#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) -//ADC *adc1 = new ADC(); // adc object -//#endif #endif #define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH @@ -72,19 +69,13 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 senseOffset=analogRead(currentPin); // value of sensor at zero current } -//#if defined(TEENSYDUINO) #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) if(currentPin != current_pin && currentPin!=UNUSED_PIN){ //adc->adc0->setReference(ADC_REFERENCE::REF_3V3); adc->adc0->startContinuous(currentPin); } else if(currentPin!=UNUSED_PIN){ -//#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) -// adc1->adc0->setReference(ADC_REFERENCE::REF_3V3); -// adc1->adc0->startContinuous(currentPin); -//#else //adc->adc1->setReference(ADC_REFERENCE::REF_3V3); adc->adc1->startContinuous(currentPin); -//#endif } #endif faultPin=fault_pin; @@ -167,16 +158,11 @@ int MotorDriver::getCurrentRaw(bool isMain) { if (currentPin==UNUSED_PIN) return 0; int current; -//#if defined(TEENSYDUINO) #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) if(isMain) { current = (uint16_t)adc->adc0->analogReadContinuous(); } else { - //#if defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY32) - //current = (uint16_t)adc1->adc0->analogReadContinuous(); - //#else current = (uint16_t)adc->adc1->analogReadContinuous(); - //#endif } #elif defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36) unsigned char sreg_backup; From c70ef3ffaad37de0287aa8f06106b60ab27444cb Mon Sep 17 00:00:00 2001 From: Mike S Date: Tue, 30 Mar 2021 16:12:47 -0400 Subject: [PATCH 7/8] Final Fix for T4 interrupts --- DCCWaveform.cpp | 6 +++--- MotorDriver.cpp | 31 +++++++++---------------------- MotorDriver.h | 13 ++++++++++++- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 68549c9..57f20a1 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -127,7 +127,7 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) { break; case POWERMODE::ON: // Check current - lastCurrent=motorDriver->getCurrentRaw(isMainTrack); + lastCurrent=motorDriver->getCurrentRaw(); if (lastCurrent < 0) { // We have a fault pin condition to take care of lastCurrent = -lastCurrent; @@ -275,7 +275,7 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea void DCCWaveform::setAckBaseline() { if (isMainTrack) return; - int baseline=motorDriver->getCurrentRaw(isMainTrack); + int baseline=motorDriver->getCurrentRaw(); ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA); if (Diag::ACK) DIAG(F("ACK baseline=%d/%dmA Threshold=%d/%dmA Duration between %dus and %dus"), baseline,motorDriver->raw2mA(baseline), @@ -309,7 +309,7 @@ void DCCWaveform::checkAck() { return; } - int current=motorDriver->getCurrentRaw(isMainTrack); + int current=motorDriver->getCurrentRaw(); if (current > ackMaxCurrent) ackMaxCurrent=current; // An ACK is a pulse lasting between minAckPulseDuration and maxAckPulseDuration uSecs (refer @haba) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 1819ab7..d3f1f9c 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -21,12 +21,6 @@ #include "DCCTimer.h" #include "DIAG.h" -#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) -#include -#include -ADC *adc = new ADC(); // adc object -#endif - #define setHIGH(fastpin) *fastpin.inout |= fastpin.maskHIGH #define setLOW(fastpin) *fastpin.inout &= fastpin.maskLOW #define isHIGH(fastpin) (*fastpin.inout & fastpin.maskHIGH) @@ -69,15 +63,6 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 senseOffset=analogRead(currentPin); // value of sensor at zero current } -#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) - if(currentPin != current_pin && currentPin!=UNUSED_PIN){ - //adc->adc0->setReference(ADC_REFERENCE::REF_3V3); - adc->adc0->startContinuous(currentPin); - } else if(currentPin!=UNUSED_PIN){ - //adc->adc1->setReference(ADC_REFERENCE::REF_3V3); - adc->adc1->startContinuous(currentPin); - } -#endif faultPin=fault_pin; if (faultPin != UNUSED_PIN) { getFastPin(F("FAULT"),faultPin, 1 /*input*/, fastFaultPin); @@ -154,16 +139,18 @@ bool MotorDriver::canMeasureCurrent() { * senseOffset handles the case where a shield returns values above or below * a central value depending on direction. */ -int MotorDriver::getCurrentRaw(bool isMain) { +int MotorDriver::getCurrentRaw() { if (currentPin==UNUSED_PIN) return 0; - int current; #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) - if(isMain) { - current = (uint16_t)adc->adc0->analogReadContinuous(); - } else { - current = (uint16_t)adc->adc1->analogReadContinuous(); - } + //if(isMain) { + // current = (uint16_t)adc->adc0->analogReadContinuous(); + //} else { + // current = (uint16_t)adc->adc1->analogReadContinuous(); + //} + bool irq = disableInterrupts(); + current = analogRead(currentPin)-senseOffset; + enableInterrupts(irq); #elif defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36) unsigned char sreg_backup; sreg_backup = SREG; /* save interrupt enable/disable state */ diff --git a/MotorDriver.h b/MotorDriver.h index f7d8580..08db049 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -47,7 +47,7 @@ class MotorDriver { virtual void setPower( bool on); virtual void setSignal( bool high); virtual void setBrake( bool on); - virtual int getCurrentRaw(bool isMain); + virtual int getCurrentRaw(); virtual unsigned int raw2mA( int raw); virtual int mA2raw( unsigned int mA); inline int getRawCurrentTripValue() { @@ -73,5 +73,16 @@ class MotorDriver { int senseOffset; unsigned int tripMilliamps; int rawCurrentTripValue; +#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) + static bool disableInterrupts() { + uint32_t primask; + __asm__ volatile("mrs %0, primask\n" : "=r" (primask)::); + __disable_irq(); + return (primask == 0) ? true : false; + } + static void enableInterrupts(bool doit) { + if (doit) __enable_irq(); + } +#endif }; #endif From dd97c4ba492a5167a5d9bd0a3f73846f2333db40 Mon Sep 17 00:00:00 2001 From: Mike S Date: Tue, 30 Mar 2021 18:11:22 -0400 Subject: [PATCH 8/8] Some additional fixes for typos. --- DCCTimer.cpp | 12 +++++++----- EthernetInterface.h | 3 ++- MotorDriver.cpp | 8 ++------ defines.h | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/DCCTimer.cpp b/DCCTimer.cpp index eb592c7..1d3e6ac 100644 --- a/DCCTimer.cpp +++ b/DCCTimer.cpp @@ -81,6 +81,8 @@ INTERRUPT_CALLBACK interruptHandler=0; void DCCTimer::getSimulatedMacAddress(byte mac[6]) { memcpy(mac,(void *) &SIGROW.SERNUM0,6); // serial number + mac[0] &= 0xFE; + mac[0] |= 0x02; } #elif defined(TEENSYDUINO) @@ -115,13 +117,13 @@ INTERRUPT_CALLBACK interruptHandler=0; #else read_mac(mac); #endif -} + } #if !defined(__IMXRT1062__) -void DCCTimer::read_mac(byte mac[6]) { - read(0xe,mac,0); - read(0xf,mac,3); -} + void DCCTimer::read_mac(byte mac[6]) { + read(0xe,mac,0); + read(0xf,mac,3); + } // http://forum.pjrc.com/threads/91-teensy-3-MAC-address void DCCTimer::read(uint8_t word, uint8_t *mac, uint8_t offset) { diff --git a/EthernetInterface.h b/EthernetInterface.h index df6504d..e97ebfc 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -36,7 +36,8 @@ #include #else #include "Ethernet.h" -#endif#include "RingStream.h" +#endif +#include "RingStream.h" /** * @brief Network Configuration diff --git a/MotorDriver.cpp b/MotorDriver.cpp index d3f1f9c..f51ee04 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -126,7 +126,9 @@ void MotorDriver::setSignal( bool high) { } } +#if defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36) volatile unsigned int overflow_count=0; +#endif bool MotorDriver::canMeasureCurrent() { return currentPin!=UNUSED_PIN; @@ -143,11 +145,6 @@ int MotorDriver::getCurrentRaw() { if (currentPin==UNUSED_PIN) return 0; int current; #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) - //if(isMain) { - // current = (uint16_t)adc->adc0->analogReadContinuous(); - //} else { - // current = (uint16_t)adc->adc1->analogReadContinuous(); - //} bool irq = disableInterrupts(); current = analogRead(currentPin)-senseOffset; enableInterrupts(irq); @@ -162,7 +159,6 @@ int MotorDriver::getCurrentRaw() { current = analogRead(currentPin)-senseOffset; #endif if (current<0) current=0-current; - if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && isHIGH(fastPowerPin)) return (current == 0 ? -1 : -current); return current; diff --git a/defines.h b/defines.h index c3454c1..b018c54 100644 --- a/defines.h +++ b/defines.h @@ -23,7 +23,7 @@ // WIFI_ON: All prereqs for running with WIFI are met // Note: WIFI_CHANNEL may not exist in early config.h files so is added here if needed. -#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) || defined(Teensyduino) +#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO) || defined(TEENSYDUINO)) #define WIFI_ON true #ifndef WIFI_CHANNEL #define WIFI_CHANNEL 1 @@ -32,7 +32,7 @@ #define WIFI_ON false #endif -#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) || defined(Teensyduino) +#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO) || defined(TEENSYDUINO)) #define ETHERNET_ON true #else #define ETHERNET_ON false